Cuando inicias una actividad desde una notificación, debes preservar la experiencia de navegación del usuario. Cuando el usuario presiona Atrás, debería retroceder a la pantalla principal mediante el flujo de trabajo normal de tu app. Asimismo, al abrir la pantalla Recientes, se debería mostrar la actividad como una tarea separada. Para preservar esta experiencia de navegación, deberías iniciar la actividad en una tarea nueva.
Si bien el enfoque básico de configuración del comportamiento cuando se presiona tu notificación se describe en Cómo crear una notificación, en esta página se explica cómo configurar un PendingIntent
para la acción de tu notificación de manera que se cree una nueva tarea y una pila de actividades.
Sin embargo, la manera de hacerlo dependerá de qué tipo de actividad quieres iniciar:
- Actividad normal
- Corresponde a una actividad que forma parte del flujo normal de la experiencia del usuario de tu app. Por lo tanto, cuando el usuario llegue a la actividad desde la notificación, la próxima tarea debería incluir una pila de actividades completa, que le permita presionar Atrás y navegar hacia arriba en la jerarquía de la app.
- Actividad especial
- El usuario solamente ve esta actividad si se inicia desde una notificación. En cierto modo, esta actividad extiende la IU de la notificación al proporcionar información que sería difícil de mostrar en la notificación. Por lo tanto, esta actividad no necesita una pila de actividades.
Cómo configurar un PendingIntent de actividad normal
Para iniciar una "actividad normal" desde tu notificación, configura el PendingIntent
con TaskStackBuilder
de modo que se cree una nueva pila de actividades de la siguiente manera.
Cómo definir la jerarquía de actividades de tu app
Para definir la jerarquía natural de tus actividades, agrega el atributo android:parentActivityName
en cada elemento <activity>
del archivo de manifiesto de tu app. Por ejemplo:
<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>
Cómo compilar un PendingIntent con una pila de actividades
Si quieres iniciar una actividad que incluya una pila de actividades, necesitas crear una instancia de TaskStackBuilder
, llamar a addNextIntentWithParentStack()
y pasar el Intent
de la actividad que quieres iniciar.
Siempre y cuando hayas definido la actividad principal para cada actividad como se describe más arriba, puedes llamar a getPendingIntent()
a fin de recibir un PendingIntent
que incluya toda la pila de actividades.
Kotlin
// 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) }
Java
// 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);
Si es necesario, puedes agregar argumentos a los objetos Intent
de la pila mediante una llamada a TaskStackBuilder.editIntentAt()
. A veces debes realizar esta acción para asegurarte de que una actividad de la pila de actividades muestre datos útiles cuando el usuario navega por ella.
Luego, puedes pasar el PendingIntent
a la notificación como lo haces normalmente:
Kotlin
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply { setContentIntent(resultPendingIntent) ... } with(NotificationManagerCompat.from(this)) { notify(NOTIFICATION_ID, builder.build()) }
Java
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID); builder.setContentIntent(resultPendingIntent); ... NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(NOTIFICATION_ID, builder.build());
Cómo configurar un PendingIntent de actividad especial
Como una "actividad especial" que se inició desde una notificación no necesita una pila de actividades, puedes llamar a getActivity()
para crear el PendingIntent
, aunque también deberías asegurarte de definir las opciones de la tarea apropiadas en el manifiesto.
-
En tu manifiesto, agrega los siguientes atributos al elemento
<activity>
.-
android:taskAffinity=""
-
Junto con la marca
FLAG_ACTIVITY_NEW_TASK
que usarás en el código, dejar este atributo en blanco garantiza que esta actividad no se incluya en la tarea predeterminada de tu app. Las tareas existentes que tengan la afinidad predeterminada de la app no se verán afectadas. -
android:excludeFromRecents="true"
- Excluye la nueva tarea de Recientes a fin de que el usuario no pueda retroceder accidentalmente a ella.
Por ejemplo:
<activity android:name=".ResultActivity" android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true"> </activity>
-
-
Crea y emite la notificación:
-
Crea un
Intent
que inicie laActivity
. -
Establece la
Activity
para iniciar una tarea nueva vacía llamando asetFlags()
con las marcasFLAG_ACTIVITY_NEW_TASK
yFLAG_ACTIVITY_CLEAR_TASK
. -
Llama a
getActivity()
para crear unPendingIntent
.
Por ejemplo:
Kotlin
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 )
Java
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 );
-
Crea un
- Luego, puedes pasar el
PendingIntent
a la notificación como lo haces normalmente:Kotlin
val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply { setContentIntent(notifyPendingIntent) ... } with(NotificationManagerCompat.from(this)) { notify(NOTIFICATION_ID, builder.build()) }
Java
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID); builder.setContentIntent(notifyPendingIntent); ... NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); notificationManager.notify(NOTIFICATION_ID, builder.build());
Para obtener más información sobre las diferentes opciones de tareas y cómo funciona la pila de actividades, lee Tareas y pila de actividades. Para ver un código de ejemplo que usa notificaciones, consulta Ejemplo de notificaciones de Android.