38

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

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...");   
} 

ответ

51

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

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

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

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

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

Избавьтесь от FLAG_ACTIVITY_NEW_TASK. Add notifyIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - см. this sample project.

Context context = getApplicationContext(); 

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

+0

Thaks много для того, чтобы взглянуть на это! когда вы получите шанс, не могли бы вы взглянуть на верхнюю часть редактирования? – brybam

+0

Это сработало для меня, спасибо :) – stealthcopter

+0

Посмотрите пример проекта @commonsware, подскажите, это помогло мне очень хорошо понять, как это должно быть сделано. –

19

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

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()); 
} 
+1

Это рабочее решение – nsgulliver

+3

Этот вариант создает новый экземпляр при нажатии на уведомление. Хотя автор спросил о возобновлении деятельности, а не о создании новой. Странно, что этот ответ собрал столько очков. –

13

Только в случае, если кто-то имеет те же трудности у меня было ....

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

android:launchMode="singleInstance"

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

+0

Это сработало для меня. Если вы создадите, например, активность GPS, это будет правильным способом. –

+0

Это сработало для меня и является самым простым решением и самым прямым. Спасибо, что поделился. – Mijo

1

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

Шаг 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); 
1

Я обнаружил, что ни один из ответов не работал для приложения с несколькими задачами. Похоже, что 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<ActivityManager.AppTask> 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... 
    } 
} 

<uses-permission android:name="android.permission.REORDER_TASKS"/> 

...

<receiver android:name=".TaskReturn"/> 

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

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

Смежные вопросы