Возобновить приложение и стек из уведомления


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

то есть: я хочу, чтобы стек был в том же состоянии, что и до того, как пользователь покинул его.

проблема при установке ожидающего намерения в уведомлении заключается в том, что оно всегда нацелено на определенную деятельность. Я не хочу этого. Мне нужно возобновить приложение так же, как это делает пусковая установка.

Итак, если пользователь находится в действии A, I хотите возобновить действие A. Если он запустил действие B Из действия A, то я хочу, чтобы B отображался, когда пользователь нажимает уведомление, и стек должен быть восстановлен, чтобы a возобновлялся, когда пользователь нажимает кнопку "Назад" в B.

есть несколько других вопросов вопросов с похожими названиями, но ни один не решает мою проблему.

7 53

7 ответов:

просто используйте те же фильтры намерений, что и Android, когда он запускает приложение:

final Intent notificationIntent = new Intent(context, YourActivity.class);
notificationIntent.setAction(Intent.ACTION_MAIN);
notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

как Intent вы создали, чтобы открыть ваш Activity из панели уведомлений так же, как Android используется для запуска вашего приложения, ранее открытый Activity будет показано вместо создания нового.

для ситуаций, когда вы не хотите / не можете жестко закодировать активность запуска это решение работает

Intent i = getPackageManager()
    .getLaunchIntentForPackage(getPackageName())
    .setPackage(null)
    .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, i, 0);

return new NotificationCompat.Builder(context)
        ...
        .setContentIntent(pendingIntent)
        .build();

на setPackage (null) часть была ключевой в моем случае, так как без него приложение не возвращаюсь к предыдущей задаче. Я сравнил свое намерение с намерением из Android launcher и заметил, что pkg не был установлен там, поэтому я придумал удаление имени пакета из намерения.

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

создание действия, а затем установить категории и соответствующие флаги... Это было так, как это работало для меня, я должен был сделать это таким образом, потому что я сделал это, чтобы поддержать Api lvl 8

intent.addCategory(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClass(this, YourActivity.class);

intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT|
                Intent.FLAG_ACTIVITY_SINGLE_TOP);

PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 
                   PendingIntent.FLAG_UPDATE_CURRENT);

и в AndroidManifest

android:launchMode="singleTask"

Так что же сделал трюк был Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT наряду с указанными в манифесте.

надеюсь, что это помогает другим людям.

У меня также была та же проблема и попытаться решить эту проблему, как @Grand's ответ:

final Intent notificationIntent = new Intent(context,YourActivity.class);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);

это работает, нет сомнений в этом, но проблема заключается в том, когда вы устанавливаете свое намерение как ACTION_MAIN. Тогда вы не сможете установить какой-либо пакет для намерения. Я имею в виду, что ваши примитивные данные не будут получены из целевой активности, потому что ACTION_MAIN не может содержать никаких дополнительных данных.

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

но помнить, если вы позвоните, супер.onNewIntent (intent); затем будет создан второй экземпляр действия.

Это очень просто откройте файл манифеста и установите режим запуска атрибута singleTop в вашем атрибуте активности

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

private void bringApplicationToForeground(){
    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

      List<ActivityManager.AppTask> tasksList = am.getAppTasks();
      for (ActivityManager.AppTask task : tasksList){
        task.moveToFront();
      }
    }else{

      List<ActivityManager.RunningTaskInfo> tasksList = am.getRunningTasks(Integer.MAX_VALUE);
      if(!tasksList.isEmpty()){
        int nSize = tasksList.size();
        for(int i = 0; i < nSize;  i++){
          if(tasksList.get(i).topActivity.getPackageName().equals(getPackageName())){
            am.moveTaskToFront(tasksList.get(i).id, 0);
          }
        }
      }
    }
}

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