Начать действие из уведомления

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

Основной подход к настройке поведения касания для вашего уведомления описан в разделе «Создание базового уведомления» . На этой странице описано, как настроить PendingIntent для действия вашего уведомления, чтобы оно создавало новую задачу и обратный стек . Как вы это сделаете, зависит от того, какой вид деятельности вы начинаете:

Регулярная деятельность
Это действие, которое существует как часть обычного процесса UX вашего приложения. Когда пользователь переходит к действию из уведомления, новая задача должна включать полный задний стек, позволяя пользователю нажать кнопку «Назад» для перемещения вверх по иерархии приложения.
Специальная деятельность
Пользователь видит это действие, только если оно запущено из уведомления. В некотором смысле это действие расширяет пользовательский интерфейс уведомлений, предоставляя информацию, которую сложно отобразить в самом уведомлении. Для этого действия не требуется задний стек.

Настройте регулярное действие PendingIntent

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

Определите иерархию действий вашего приложения.

Определите естественную иерархию своих действий, добавив атрибут android:parentActivityName к каждому элементу <activity> в файле манифеста вашего приложения. См. следующий пример:

<activity
    android:name=".MainActivity"
    android:label="@string/app_name" >
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>
<!-- MainActivity is the parent for ResultActivity. -->
<activity
    android:name=".ResultActivity"
    android:parentActivityName=".MainActivity" />
    ...
</activity>

Создайте PendingIntent с обратным стеком

Чтобы запустить действие, которое включает в себя задний стек действий, создайте экземпляр TaskStackBuilder и вызовите addNextIntentWithParentStack() , передав ему Intent для действия, которое вы хотите запустить.

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

Котлин

// Create an Intent for the activity you want to start.
val resultIntent = Intent(this, ResultActivity::class.java)
// Create the TaskStackBuilder.
val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(this).run {
    // Add the intent, which inflates the back stack.
    addNextIntentWithParentStack(resultIntent)
    // Get the PendingIntent containing the entire back stack.
    getPendingIntent(0,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}

Ява

// Create an Intent for the activity you want to start.
Intent resultIntent = new Intent(this, ResultActivity.class);
// Create the TaskStackBuilder and add the intent, which inflates the back
// stack.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
stackBuilder.addNextIntentWithParentStack(resultIntent);
// Get the PendingIntent containing the entire back stack.
PendingIntent resultPendingIntent =
        stackBuilder.getPendingIntent(0,
            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

При необходимости вы можете добавить аргументы к объектам Intent в стеке, вызвав TaskStackBuilder.editIntentAt() . Иногда это необходимо, чтобы гарантировать, что действие в заднем стеке отображает значимые данные, когда пользователь переходит к нему.

Затем вы можете передать PendingIntent в уведомление как обычно:

Котлин

val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
    setContentIntent(resultPendingIntent)
    ...
}
with(NotificationManagerCompat.from(this)) {
    notify(NOTIFICATION_ID, builder.build())
}

Ява

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setContentIntent(resultPendingIntent);
...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(NOTIFICATION_ID, builder.build());

Настройте специальную активность PendingIntent.

Поскольку специальное действие, которое начинается с уведомления, не требует обратного стека, вы можете создать PendingIntent , вызвав getActivity() . Однако определите соответствующие параметры задачи в манифесте.

  1. В своем манифесте добавьте следующие атрибуты к элементу <activity> .
    android:taskAffinity =""
    В сочетании с флагом FLAG_ACTIVITY_NEW_TASK , который вы используете в коде, установите этот атрибут пустым, чтобы гарантировать, что это действие не входит в задачу приложения по умолчанию. Любые существующие задачи, имеющие сходство приложения по умолчанию, не будут затронуты.
    android:excludeFromRecents ="true"
    Исключает новую задачу с экрана «Последние», чтобы пользователь не мог случайно вернуться к ней.

    Это показано в следующем примере:

    <activity
        android:name=".ResultActivity"
        android:launchMode="singleTask"
        android:taskAffinity=""
        android:excludeFromRecents="true">
    </activity>
    
  2. Создайте и выпустите уведомление:
    1. Создайте Intent , который запускает Activity .
    2. Настройте запуск Activity в новой пустой задаче, вызвав setFlags() с флагами FLAG_ACTIVITY_NEW_TASK и FLAG_ACTIVITY_CLEAR_TASK .
    3. Создайте PendingIntent , вызвав getActivity() .

    Это показано в следующем примере:

    Котлин

    val notifyIntent = Intent(this, ResultActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
    }
    val notifyPendingIntent = PendingIntent.getActivity(
            this, 0, notifyIntent,
            PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
    )
    

    Ява

    Intent notifyIntent = new Intent(this, ResultActivity.class);
    // Set the Activity to start in a new, empty task.
    notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);
    // Create the PendingIntent.
    PendingIntent notifyPendingIntent = PendingIntent.getActivity(
            this, 0, notifyIntent,
            PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
    );
    
  3. Передайте PendingIntent в уведомление как обычно:

    Котлин

    val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
        setContentIntent(notifyPendingIntent)
        ...
    }
    with(NotificationManagerCompat.from(this)) {
        notify(NOTIFICATION_ID, builder.build())
    }
    

    Ява

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
    builder.setContentIntent(notifyPendingIntent);
    ...
    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
    notificationManager.notify(NOTIFICATION_ID, builder.build());
    

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