Cuando inicias una actividad desde una notificación, debes conservar la experiencia de navegación esperada del usuario. Cuando el usuario presiona el botón Atrás, debe regresar a la pantalla principal mediante el flujo de trabajo normal de la app, y, al abrir la pantalla Recientes, se debe mostrar la actividad como una tarea separada. Para preservar esta experiencia de navegación, inicia la actividad en una tarea nueva.
El enfoque básico para configurar el comportamiento de presión de tu notificación se describe en Cómo crear una notificación básica.
En esta página, se describe cómo configurar un PendingIntent
para la acción de tu notificación, de modo que se cree una tarea y una pila de actividades nueva. La forma de hacerlo depende del tipo de actividad que inicias:
- Actividad normal
- Corresponde a una actividad que forma parte del flujo normal de la experiencia del usuario de tu app. Cuando el usuario llega a la actividad desde la notificación, la tarea nueva debe incluir una pila de actividades completa, lo que le permite al usuario presionar el botón Atrás para 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 sentido, esta actividad extiende la IU de la notificación, ya que proporciona información que es difícil de mostrar en la notificación en sí. 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 PendingIntent
con TaskStackBuilder
para que 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
a cada elemento <activity>
del archivo de manifiesto de tu app. Observa el siguiente 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
Para iniciar una actividad que incluya una pila de actividades, crea una instancia de TaskStackBuilder
, llama a addNextIntentWithParentStack()
y pásale el objeto Intent
de la actividad que desees iniciar.
Siempre que definas la actividad superior para cada actividad como se describió anteriormente, puedes llamar a getPendingIntent()
para 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 or PendingIntent.FLAG_IMMUTABLE) }
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 | PendingIntent.FLAG_IMMUTABLE);
Si es necesario, puedes agregar argumentos a los objetos Intent
de la pila llamando a TaskStackBuilder.editIntentAt()
.
A veces, esto es necesario para garantizar que una actividad de la pila de actividades muestre datos significativos cuando el usuario navegue hacia 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 comienza desde una notificación no necesita una pila de actividades, puedes llamar a getActivity()
para crear el PendingIntent
.
Sin embargo, debes definir las opciones de tareas 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 usas en el código, establece este atributo en blanco para garantizar que esta actividad no se incluya en la tarea predeterminada de la app. Las tareas existentes que tengan la afinidad predeterminada de la app no se verán afectadas. -
android:excludeFromRecents="true"
- Excluye la tarea nueva de la pantalla Recientes para que el usuario no pueda regresar a ella por accidente.
Esto se muestra en el siguiente ejemplo:
<activity android:name=".ResultActivity" android:launchMode="singleTask" android:taskAffinity="" android:excludeFromRecents="true"> </activity>
-
-
Compila y emite la notificación:
-
Crea un
Intent
que inicie elActivity
. -
Configura 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
.
Esto se muestra en el siguiente 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 or PendingIntent.FLAG_IMMUTABLE )
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 | PendingIntent.FLAG_IMMUTABLE );
-
Crea un
- Pasa 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 distintas opciones de tareas y cómo funciona la pila de actividades, consulta Tareas y la pila de actividades.