Как уведомить о намерениях уведомления, а не делать новые намерения?

То, что у меня есть, – это простое действие веб-просмотра, которое при загрузке автоматически отображает текущее уведомление. Идея состоит в том, что люди могут перейти от этой деятельности и быстро получить к ней доступ с любого экрана, который они хотят, потянув вниз выпадающее меню и выбрав его. Затем, когда они хотят, они могут просто закрыть уведомление, нажав кнопку меню и нажав кнопку «Выход», а затем уведомление очистится. Все это прекрасно работает. Однако при нажатии уведомления начинается новый экземпляр действия. Что мне нужно изменить, чтобы убедиться, что эта активность еще не была уничтожена, и я могу просто вызвать этот экземпляр обратно (возобновить его) и, следовательно, не нужно загружать его снова и не нужно будет добавлять другую активность в мой стек , Есть идеи? Любая помощь будет принята с благодарностью.

package com.my.app; import com.flurry.android.FlurryAgent; import android.app.Activity; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.webkit.CookieSyncManager; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.Toast; public class Chat extends Activity { private ProgressDialog progressBar; public WebView webview; private static final String TAG = "Main"; private NotificationManager mNotificationManager; private int SIMPLE_NOTFICATION_ID; @Override public void onStart() { super.onStart(); CookieSyncManager.getInstance().sync(); FlurryAgent.onStartSession(this, "H9QGMRC46IPXB43GYWU1"); } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.chat); mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); final Notification notifyDetails = new Notification(R.drawable.chat_notification,"Chat Started",System.currentTimeMillis()); notifyDetails.flags |= Notification.FLAG_ONGOING_EVENT; Context context = getApplicationContext(); CharSequence contentTitle = "Chat"; CharSequence contentText = "Press to return to chat"; Intent notifyIntent = new Intent(context, Chat.class); PendingIntent intent = PendingIntent.getActivity(Chat.this, 0, notifyIntent, android.content.Intent.FLAG_ACTIVITY_NEW_TASK); notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intent); mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails); CookieSyncManager.createInstance(this); CookieSyncManager.getInstance().startSync(); webview = (WebView) findViewById(R.id.webviewchat); webview.setWebViewClient(new chatClient()); webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setPluginsEnabled(true); webview.loadUrl("http://google.com"); progressBar = ProgressDialog.show(Chat.this, "", "Loading Chat..."); } private class chatClient extends WebViewClient { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { Log.i(TAG, "Processing webview url click..."); view.loadUrl(url); return true; } public void onPageFinished(WebView view, String url) { Log.i(TAG, "Finished loading URL: " +url); if (progressBar.isShowing()) { progressBar.dismiss(); } } } public boolean onKeyDown(int keyCode, KeyEvent event) { if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) { webview.goBack(); return true; } return super.onKeyDown(keyCode, event); } @Override public boolean onCreateOptionsMenu (Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.chatmenu, menu); return true; } @Override public boolean onOptionsItemSelected (MenuItem item) { switch (item.getItemId()) { case R.id.home: Intent a = new Intent(this, Home.class); startActivity(a); return true; case R.id.closechat: mNotificationManager.cancel(SIMPLE_NOTFICATION_ID); Intent v = new Intent(this, Home.class); startActivity(v); return true; } return false; } public void onStop() { super.onStop(); CookieSyncManager.getInstance().sync(); FlurryAgent.onEndSession(this); } } 

@Commonsware

Просто чтобы быть уверенным, что у меня это правильно, это то, что вы предлагали?

Я немного беспокоился об этой линии,

 PendingIntent.getActivity(Chat.this, 0, notifyIntent, SIMPLE_NOTFICATION_ID); public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.chat); mNotificationManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE); final Notification notifyDetails = new Notification(R.drawable.chat_notification,"Chat Started",System.currentTimeMillis()); notifyDetails.flags |= Notification.FLAG_ONGOING_EVENT; Context context = getApplicationContext(); CharSequence contentTitle = "Chat"; CharSequence contentText = "Press to return to chat"; Intent notifyIntent = new Intent(context, Chat.class); PendingIntent intent = PendingIntent.getActivity(Chat.this, 0, notifyIntent, SIMPLE_NOTFICATION_ID); notifyDetails.setLatestEventInfo(context, contentTitle, contentText, intent); notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); mNotificationManager.notify(SIMPLE_NOTFICATION_ID, notifyDetails); CookieSyncManager.createInstance(this); CookieSyncManager.getInstance().startSync(); webview = (WebView) findViewById(R.id.webviewchat); webview.setWebViewClient(new chatClient()); webview.getSettings().setJavaScriptEnabled(true); webview.getSettings().setPluginsEnabled(true); webview.loadUrl("http://google.com"); progressBar = ProgressDialog.show(Chat.this, "", "Loading Chat..."); } 

Идея состоит в том, что люди могут перейти от этой деятельности и быстро получить к ней доступ с любого экрана, который они хотят, потянув вниз выпадающее меню и выбрав его.

Пожалуйста, сделайте это необязательным.

Однако при нажатии уведомления начинается новый экземпляр действия.

Это произойдет по умолчанию.

Что мне нужно изменить, чтобы убедиться, что эта активность еще не была уничтожена, и я могу просто вызвать этот экземпляр обратно (возобновить его) и, следовательно, не нужно загружать его снова и не нужно будет добавлять другую активность в мой стек ,

Избавьтесь от FLAG_ACTIVITY_NEW_TASK . Добавить notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); – см. этот образец проекта .

 Context context = getApplicationContext(); 

Пожалуйста, не делайте этого. Просто используйте свою Activity как Context .

Это мой метод для показа уведомлений. Надеюсь, это поможет вам.

 private static void generateNotification(Context context, String message){ Intent notificationIntent = new Intent(context, YOUR_ACTIVITY.class); notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_launcher) .setContentTitle(context.getString(R.string.app_name)) .setContentIntent(intent) .setPriority(PRIORITY_HIGH) //private static final PRIORITY_HIGH = 5; .setContentText(message) .setAutoCancel(true) .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE | Notification.DEFAULT_LIGHTS); NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); mNotificationManager.notify(0, mBuilder.build()); } 

На всякий случай, у кого-то есть такая же трудность, что и у меня ….

Я пробовал весь код без успеха – элемент уведомления продолжал запускать совершенно новый экземпляр моего приложения, хотя он уже был запущен. (Я хочу, чтобы один экземпляр был доступен в любой момент времени.) Наконец заметил этот другой stream ( https://stackoverflow.com/a/20724199/4307281 ), в котором была одна простая дополнительная запись, необходимая в манифесте:

android:launchMode="singleInstance"

Я поместил это в манифест в раздел основного действия моего приложения, а затем элемент уведомления повторно использовал уже выполненный экземпляр.

Не решение для меня работало, поэтому я нашел свой собственный путь. Все мои действия расширены из BaseActivity . Я выполнил простую последовательность шагов, чтобы сделать мое push-уведомление нажатием кнопки возобновить приложение:

Шаг 1: Постоянная запись текущей активности:

 public static Context currentContext; 

Шаг 2: в onCreate() или onResume() действий, расширенных BaseActivity

 currentContext = this; 

Шаг 3: Intent при создании уведомления:

 Class activity = BaseActivity.commonContext.getClass(); Intent intent = new Intent(this, activity); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); //FLAG_UPDATE_CURRENT is important PendingIntent pendingIntent = PendingIntent.getActivity(this, (int)System.currentTimeMillis(), intent, PendingIntent.FLAG_UPDATE_CURRENT); 

Я обнаружил, что ни один из ответов не работал для приложения с несколькими задачами. Похоже, что Intent.FLAG_ACTIVITY_CLEAR_TOP и Intent.FLAG_ACTIVITY_SINGLE_TOP не ведут себя точно так же в случае нескольких задач. В моем приложении есть несколько действий, связанных с задачами. В какой-то момент пользователю будет показано уведомление о том, что в одной из этих задач должна быть выполнена работа. В отличие от OP, мне нужно только вернуться к вершине одной из этих задач, а не к определенной деятельности, которая может быть похоронена в одной из этих задач. Я думаю, что это достаточно похоже на заданный вопрос, что он может быть полезен кому-то другому.

Мое решение состоит из статического идентификатора задачи для отслеживания текущей задачи, широковещательного приемника для обработки ожидающих намерений, нового тега использования-разрешения и некоторого простого использования ActivityManager.

 private static int taskID; public static void setResumeTask(int tID) { Log.e("TaskReturn", "Setting Task ID: " + tID); taskID = tID; } public static PendingIntent getResumeTask(Context appContext) { return PendingIntent.getBroadcast(appContext, 0, new Intent(appContext, TaskReturn.class).putExtra(TaskReturn.EXTRA_TASK_ID, taskID), PendingIntent.FLAG_UPDATE_CURRENT); } 

 public void onReceive(Context context, Intent intent) { Log.e("TaskReturn", "Task Return!"); if (intent.hasExtra(EXTRA_TASK_ID)) { int taskToStart = intent.getIntExtra(EXTRA_TASK_ID, -1); Log.e("TaskReturn", "Returning To Task: " + taskToStart); ActivityManager activityManager = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE); List allAppTasks = activityManager.getAppTasks(); for (ActivityManager.AppTask task : allAppTasks) { Log.e("TaskReturn", "AllTasks: " + task.getTaskInfo().id + " " + task.getTaskInfo().affiliatedTaskId + " " + task.getTaskInfo().persistentId); } activityManager.moveTaskToFront(taskToStart, ActivityManager.MOVE_TASK_WITH_HOME); } else { Log.e("TaskReturn", "WHERE IS MY EXTRA!?!?!"); //Boo... } } 

  

  

По сути, идея заключается в том, что вы отмечаете результат вызова Activity.getTaskId () в состояние. Позже, создавая уведомление для возобновления работы этой задачи, возьмите идентификатор задачи и добавьте его в дополнительную. Затем установите ожидающее намерение указать на широковещательный приемник, который вытаскивает идентификатор задачи и запускает эту задачу.

Похоже, для этого требуется API 21 с вызовами, которые я использовал, и я подозреваю, что может потребоваться некоторые дополнительные проверки ошибок, если задача уже завершена, но она служит моим целям.

  • Использование активности камеры в Android
  • Intent - если активность запущена, переведите ее вперед, иначе запустите новую (из уведомления)
  • Как возобновить Android-активность программно из фона
  • Начать работу в Android
  • Завершить работу по истечении периода времени
  • Заставка экрана при загрузке URL-адреса в веб-виде в приложении для Android
  • Как передать переменную от Activity to Fragment и передать ее обратно?
  • Android: действие будет уничтожено после вызова камеры Intent
  • Лучшая практика передачи контекста в classы без активности?
  • Программно обновлять виджет из активности / службы / получателя
  • В чем разница между Activity и Context?
  • Давайте будем гением компьютера.