Возобновить приложение и стек из уведомления - PullRequest
57 голосов
/ 31 марта 2011

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

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

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

Поэтому, если пользователь находится в действии A, я хочу возобновить действие A. Если он запустил действие B из действия A, то я хочу, чтобы B отображалось, когда пользователь нажимает на уведомление, и стек восстанавливается, так что что A возобновляется, когда пользователь нажимает кнопку «Назад» в B.

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

Ответы [ 7 ]

145 голосов
/ 31 марта 2011

Просто используйте те же фильтры намерений, которые использует 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.

26 голосов
/ 02 февраля 2017

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

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 и заметил, что pkg там не установлен, поэтому я решил удалить имя пакета из намерения.

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

4 голосов
/ 28 июля 2014

Создание деятельности, а затем установить категории и соответствующие флаги ... Это было то, как это работало для меня, я должен был сделать это так, потому что я сделал это для поддержки 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 вместе с линией, установленной в манифесте.

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

3 голосов
/ 24 апреля 2015

У меня тоже была такая же проблема, и я пытался решить ее, как ответ @ GrAnd:

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 () своей целевой деятельности.

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

0 голосов
/ 12 октября 2015
<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);
          }
        }
      }
    }
}
0 голосов
/ 11 ноября 2012

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

0 голосов
/ 31 марта 2011

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

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