Cómo crear una notificación

Las notificaciones proporcionan información breve y oportuna sobre eventos de tu app cuando no está en uso. En este documento, se muestra cómo crear una notificación con varias funciones. Para obtener una introducción sobre cómo aparecen las notificaciones en Android, consulta la Descripción general de notificaciones. Para ver un código de muestra que usa notificaciones, consulta Muestra de personas en GitHub.

El código de esta página usa las APIs de NotificationCompat de la biblioteca de AndroidX. Estas APIs te permiten agregar funciones disponibles solo en las versiones más recientes de Android y, al mismo tiempo, proporcionar compatibilidad con Android 9 (nivel de API 28). Sin embargo, algunas funciones, como la acción de respuesta en línea, generan una no-op en versiones anteriores.

Agrega la biblioteca principal de AndroidX

Aunque la mayoría de los proyectos creados con Android Studio incluyen las dependencias necesarias para usar NotificationCompat, verifica que tu archivo build.gradle a nivel de módulo incluya la siguiente dependencia:

Groovy

dependencies {
    implementation "androidx.core:core:2.2.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-ktx:2.2.0")
}

Cómo crear una notificación básica

Una notificación, en su forma más básica y compacta, también conocida como forma contraída, muestra un ícono, un título y una pequeña cantidad de contenido de texto. En esta sección, se muestra cómo crear una notificación que el usuario pueda presionar para iniciar una actividad en tu app.

Figura 1: Una notificación con un ícono, un título y algo de texto.

Para obtener más detalles sobre cada parte de una notificación, lee sobre la anatomía de las notificaciones.

Declara el permiso de tiempo de ejecución

Android 13 (nivel de API 33) y las versiones posteriores admiten un permiso de tiempo de ejecución para publicar notificaciones no exentas (incluidos los servicios en primer plano (FGS)) de una app.

El permiso que debes declarar en el archivo de manifiesto de tu app aparece en el siguiente fragmento de código:

<manifest ...>
    <uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
    <application ...>
        ...
    </application>
</manifest>

Para obtener más detalles sobre los permisos de tiempo de ejecución, consulta Permiso de tiempo de ejecución de notificaciones.

Cómo definir el contenido de la notificación

Para comenzar, configura el contenido y el canal de la notificación con un objeto NotificationCompat.Builder. En el siguiente ejemplo, se muestra cómo crear una notificación con lo siguiente:

  • Un ícono pequeño, establecido por setSmallIcon(). que es el único contenido necesario visible para el usuario

  • Un título, establecido por setContentTitle().

  • El texto del cuerpo, establecido por setContentText().

  • La prioridad de notificación, establecida por setPriority(). La prioridad determina cuán intrusiva es la notificación en Android 7.1 y versiones anteriores. Para Android 8.0 y versiones posteriores, establece la importancia del canal como se muestra en la siguiente sección.

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle(textTitle)
        .setContentText(textContent)
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

El constructor NotificationCompat.Builder requiere que proporciones un ID de canal. Esto es necesario para la compatibilidad con Android 8.0 (nivel de API 26) y versiones posteriores, pero se ignora en versiones anteriores.

De forma predeterminada, el contenido de texto de la notificación se trunca para que quepa en una línea. Para mostrar información adicional, crea una notificación expandible.

Figura 2: Una notificación expandible en sus formularios contraídos y expandidos

Si deseas que la notificación sea más larga, puedes habilitar una notificación expandible agregando una plantilla de estilo con setStyle(). Por ejemplo, el siguiente código crea un área de texto más grande:

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Much longer text that cannot fit one line...")
        .setStyle(new NotificationCompat.BigTextStyle()
                .bigText("Much longer text that cannot fit one line..."))
        .setPriority(NotificationCompat.PRIORITY_DEFAULT);

Para obtener más información sobre otros estilos de notificaciones grandes, incluso cómo agregar una imagen y controles de reproducción multimedia, consulta Cómo crear una notificación expandible.

Cómo crear un canal y definir la importancia

Antes de poder entregar la notificación en Android 8.0 y versiones posteriores, registra el canal de notificaciones de la app en el sistema pasando una instancia de NotificationChannel a createNotificationChannel(). Una condición de la versión SDK_INT bloquea el siguiente código:

Kotlin

private fun createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val name = getString(R.string.channel_name)
        val descriptionText = getString(R.string.channel_description)
        val importance = NotificationManager.IMPORTANCE_DEFAULT
        val channel = NotificationChannel(CHANNEL_ID, name, importance).apply {
            description = descriptionText
        }
        // Register the channel with the system.
        val notificationManager: NotificationManager =
            getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
    }
}

Java

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is not in the Support Library.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = getString(R.string.channel_name);
        String description = getString(R.string.channel_description);
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this.
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

Dado que debes crear el canal de notificaciones antes de publicar notificaciones en Android 8.0 y versiones posteriores, ejecuta este código apenas se inicie la app. Es seguro realizar llamadas repetidas porque no se realiza ninguna operación cuando se crea un canal de notificaciones.

El constructor NotificationChannel requiere un importance, con una de las constantes de la clase NotificationManager. Este parámetro determina cómo interrumpir al usuario con cualquier notificación que pertenezca a este canal. Establece la prioridad con setPriority() para admitir Android 7.1 y versiones anteriores, como se muestra en el ejemplo anterior.

Aunque debes establecer la importancia o prioridad de la notificación como se muestra en el siguiente ejemplo, el sistema no garantiza el comportamiento de alerta que obtienes. En algunos casos, el sistema puede cambiar el nivel de importancia en función de otros factores, y el usuario siempre puede redefinir el nivel de importancia para un canal determinado.

Para obtener más información sobre el significado de los diferentes niveles, lee información sobre los niveles de importancia de las notificaciones.

Cómo establecer la acción de toque de la notificación

Cada notificación debe responder a un toque, generalmente para abrir una actividad en tu app que se corresponda con la notificación. Para hacerlo, especifica un intent de contenido definido con un objeto PendingIntent y pásalo a setContentIntent().

En el siguiente fragmento, se muestra cómo crear un intent básico para abrir una actividad cuando el usuario presiona la notificación:

Kotlin

// Create an explicit intent for an Activity in your app.
val intent = Intent(this, AlertDetails::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
val pendingIntent: PendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE)

val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)

Java

// Create an explicit intent for an Activity in your app.
Intent intent = new Intent(this, AlertDetails.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_IMMUTABLE);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        // Set the intent that fires when the user taps the notification.
        .setContentIntent(pendingIntent)
        .setAutoCancel(true);

Este código llama a setAutoCancel(), que quita automáticamente la notificación cuando el usuario la presiona.

El método setFlags() que se muestra en el ejemplo anterior conserva la experiencia de navegación esperada del usuario después de que este abre la app con la notificación. Es posible que quieras usarla según el tipo de actividad que quieras iniciar, que puede ser una de las siguientes:

  • Una actividad que existe exclusivamente para respuestas a la notificación. No hay motivo para que el usuario navegue a esta actividad durante el uso normal de la app, por lo que la actividad inicia una tarea nueva en lugar de agregarse a la pila de actividades y tareas existente de la app. Este es el tipo de intent creado en el ejemplo anterior.

  • Una actividad que existe en el flujo regular de la app. En este caso, cuando se inicia la actividad, se crea una pila de actividades, de modo que se conserven las expectativas del usuario relacionadas con los botones Atrás y Arriba.

Para obtener más información sobre las diferentes maneras de configurar el intent de tu notificación, consulta Cómo iniciar una actividad desde una notificación.

Cómo mostrar la notificación

Para que aparezca la notificación, llama a NotificationManagerCompat.notify() y pásale un ID único para la notificación y el resultado de NotificationCompat.Builder.build(). Esto se muestra en el siguiente ejemplo:

Kotlin

with(NotificationManagerCompat.from(this)) {
    if (ActivityCompat.checkSelfPermission(
            this@MainActivity,
            Manifest.permission.POST_NOTIFICATIONS
        ) != PackageManager.PERMISSION_GRANTED
    ) {
        // TODO: Consider calling
        // ActivityCompat#requestPermissions
        // here to request the missing permissions, and then overriding
        // public fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
        //                                        grantResults: IntArray)
        // to handle the case where the user grants the permission. See the documentation
        // for ActivityCompat#requestPermissions for more details.

        return@with
    }
    // notificationId is a unique int for each notification that you must define.
    notify(NOTIFICATION_ID, builder.build())
}

Java

with(NotificationManagerCompat.from(this)) {
   if (ActivityCompat.checkSelfPermission(
           this@MainActivity,
           Manifest.permission.POST_NOTIFICATIONS
       ) != PackageManager.PERMISSION_GRANTED
   ) {
       // TODO: Consider calling
       // ActivityCompat#requestPermissions
       // here to request the missing permissions, and then overriding
       // public void onRequestPermissionsResult(int requestCode, String[] permissions,
       //                                        int[] grantResults)
       // to handle the case where the user grants the permission. See the documentation
       // for ActivityCompat#requestPermissions for more details.

       return
   }
   // notificationId is a unique int for each notification that you must define.
   notify(NOTIFICATION_ID, builder.build())
}

Guarda el ID de notificación que pasas a NotificationManagerCompat.notify(), ya que lo necesitarás cuando quieras actualizar o quitar la notificación.

Además, si quieres probar las notificaciones básicas en dispositivos que ejecutan Android 13 y versiones posteriores, debes activar las notificaciones de forma manual o crear un diálogo para solicitarlas.

Cómo agregar botones de acción

Una notificación puede ofrecer hasta tres botones de acción que le permitan al usuario responder con rapidez, como posponer un recordatorio o responder un mensaje de texto. Sin embargo, estos botones de acción no deben duplicar la acción realizada cuando el usuario presiona la notificación.

Figura 3: Una notificación con un botón de acción.

Para agregar un botón de acción, pasa un PendingIntent al método addAction(). Es similar a configurar la acción de toque predeterminada de la notificación, excepto que, en lugar de iniciar una actividad, puedes realizar otras acciones, como iniciar una BroadcastReceiver que realiza un trabajo en segundo plano, de modo que la acción no interrumpa a la app que ya está abierta.

Por ejemplo, en el siguiente código, se muestra cómo enviar una transmisión a un receptor específico:

Kotlin


val ACTION_SNOOZE = "snooze"

val snoozeIntent = Intent(this, MyBroadcastReceiver::class.java).apply {
    action = ACTION_SNOOZE
    putExtra(EXTRA_NOTIFICATION_ID, 0)
}
val snoozePendingIntent: PendingIntent =
    PendingIntent.getBroadcast(this, 0, snoozeIntent, 0)
val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent)

Java


String ACTION_SNOOZE = "snooze"

Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(ACTION_SNOOZE);
snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
PendingIntent snoozePendingIntent =
        PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent);

Si quieres obtener más información para compilar un BroadcastReceiver para ejecutar trabajos en segundo plano, consulta la Descripción general de las transmisiones.

En cambio, si estás intentando compilar una notificación con botones de reproducción multimedia, como pausar y omitir pistas, consulta cómo crear una notificación con controles multimedia.

Cómo agregar una acción de respuesta directa

La acción de respuesta directa, que se introdujo en Android 7.0 (nivel de API 24), permite a los usuarios ingresar texto directamente en la notificación. Luego, el texto se envía a tu app sin abrir una actividad. Por ejemplo, puedes usar una acción de respuesta directa para permitir que los usuarios respondan mensajes de texto o actualicen listas de tareas desde la notificación.

Figura 4: Al presionar el botón "Responder", se abre la entrada de texto.

La acción de respuesta directa aparece como un botón adicional en la notificación que abre una entrada de texto. Cuando el usuario termina de escribir, el sistema adjunta la respuesta de texto al intent que especificaste para la acción de notificación y lo envía a tu app.

Cómo agregar el botón de respuesta

Para crear una acción de notificación que admita la respuesta directa, sigue estos pasos:

  1. Crea una instancia de RemoteInput.Builder que puedas agregar a tu acción de notificación. El constructor de esta clase acepta una cadena que el sistema usa como clave para la entrada de texto. Luego, tu app usará esa clave para recuperar el texto de la entrada.

    Kotlin

      // Key for the string that's delivered in the action's intent.
      private val KEY_TEXT_REPLY = "key_text_reply"
      var replyLabel: String = resources.getString(R.string.reply_label)
      var remoteInput: RemoteInput = RemoteInput.Builder(KEY_TEXT_REPLY).run {
          setLabel(replyLabel)
          build()
      }
      

    Java

      // Key for the string that's delivered in the action's intent.
      private static final String KEY_TEXT_REPLY = "key_text_reply";
    
      String replyLabel = getResources().getString(R.string.reply_label);
      RemoteInput remoteInput = new RemoteInput.Builder(KEY_TEXT_REPLY)
              .setLabel(replyLabel)
              .build();
      
  2. Crea un PendingIntent para la acción de respuesta.

    Kotlin

      // Build a PendingIntent for the reply action to trigger.
      var replyPendingIntent: PendingIntent =
          PendingIntent.getBroadcast(applicationContext,
              conversation.getConversationId(),
              getMessageReplyIntent(conversation.getConversationId()),
              PendingIntent.FLAG_UPDATE_CURRENT)
      

    Java

      // Build a PendingIntent for the reply action to trigger.
      PendingIntent replyPendingIntent =
              PendingIntent.getBroadcast(getApplicationContext(),
                      conversation.getConversationId(),
                      getMessageReplyIntent(conversation.getConversationId()),
                      PendingIntent.FLAG_UPDATE_CURRENT);
      
  3. Adjunta el objeto RemoteInput a una acción mediante addRemoteInput().

    Kotlin

      // Create the reply action and add the remote input.
      var action: NotificationCompat.Action =
          NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
              getString(R.string.label), replyPendingIntent)
              .addRemoteInput(remoteInput)
              .build()
      

    Java

      // Create the reply action and add the remote input.
      NotificationCompat.Action action =
              new NotificationCompat.Action.Builder(R.drawable.ic_reply_icon,
                      getString(R.string.label), replyPendingIntent)
                      .addRemoteInput(remoteInput)
                      .build();
      
  4. Aplica la acción a una notificación y emite la notificación.

    Kotlin

      // Build the notification and add the action.
      val newMessageNotification = Notification.Builder(context, CHANNEL_ID)
              .setSmallIcon(R.drawable.ic_message)
              .setContentTitle(getString(R.string.title))
              .setContentText(getString(R.string.content))
              .addAction(action)
              .build()
    
      // Issue the notification.
      with(NotificationManagerCompat.from(this)) {
          notificationManager.notify(notificationId, newMessageNotification)
      }
      

    Java

      // Build the notification and add the action.
      Notification newMessageNotification = new Notification.Builder(context, CHANNEL_ID)
              .setSmallIcon(R.drawable.ic_message)
              .setContentTitle(getString(R.string.title))
              .setContentText(getString(R.string.content))
              .addAction(action)
              .build();
    
      // Issue the notification.
      NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
      notificationManager.notify(notificationId, newMessageNotification);
      

Cuando se active la acción de notificación, el sistema le solicitará al usuario que ingrese una respuesta, como se muestra en la Figura 4.

Cómo recuperar entradas del usuario a partir de la respuesta

Para recibir entradas del usuario de la IU de respuesta de la notificación, llama a RemoteInput.getResultsFromIntent() y pásale la Intent que recibió tu BroadcastReceiver:

Kotlin

private fun getMessageText(intent: Intent): CharSequence? {
    return RemoteInput.getResultsFromIntent(intent)?.getCharSequence(KEY_TEXT_REPLY)
}

Java

private CharSequence getMessageText(Intent intent) {
    Bundle remoteInput = RemoteInput.getResultsFromIntent(intent);
    if (remoteInput != null) {
        return remoteInput.getCharSequence(KEY_TEXT_REPLY);
    }
    return null;
 }

Después de procesar el texto, actualiza la notificación llamando a NotificationManagerCompat.notify() con el mismo ID y la misma etiqueta, si se usan. Esto es necesario para ocultar la IU de respuesta directa y confirmar al usuario que su respuesta se recibe y procesa correctamente.

Kotlin

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
val repliedNotification = Notification.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_message)
        .setContentText(getString(R.string.replied))
        .build()

// Issue the new notification.
NotificationManagerCompat.from(this).apply {
    notificationManager.notify(notificationId, repliedNotification)
}

Java

// Build a new notification, which informs the user that the system
// handled their interaction with the previous notification.
Notification repliedNotification = new Notification.Builder(context, CHANNEL_ID)
        .setSmallIcon(R.drawable.ic_message)
        .setContentText(getString(R.string.replied))
        .build();

// Issue the new notification.
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify(notificationId, repliedNotification);

Cuando trabajes con esta nueva notificación, usa el contexto que se pasa al método onReceive() del receptor.

Agrega la respuesta a la parte inferior de la notificación con una llamada a setRemoteInputHistory(). Sin embargo, si estás compilando una app de mensajería, crea una notificación de estilo de mensajería y agrega el mensaje nuevo a la conversación.

Si quieres obtener más consejos sobre las notificaciones de apps de mensajería, consulta la sección sobre prácticas recomendadas para apps de mensajería.

Cómo agregar una barra de progreso

Las notificaciones pueden incluir un indicador de progreso animado que muestre a los usuarios el estado de una operación en curso.

Figura 5: La barra de progreso durante una operación

Si puedes estimar qué parte de la operación estará completa en cualquier momento, llama a setProgress(max, progress, false) con el formulario "definido" del indicador, como se muestra en la Figura 5. El primer parámetro es el valor "completo", como 100. El segundo es cuánto está completo. El último indica que esta es una barra de progreso determinado.

A medida que la operación avance, llama de forma continua a setProgress(max, progress, false) con un valor actualizado de progress y vuelve a emitir la notificación, como se muestra en el siguiente ejemplo.

Kotlin

val builder = NotificationCompat.Builder(this, CHANNEL_ID).apply {
    setContentTitle("Picture Download")
    setContentText("Download in progress")
    setSmallIcon(R.drawable.ic_notification)
    setPriority(NotificationCompat.PRIORITY_LOW)
}
val PROGRESS_MAX = 100
val PROGRESS_CURRENT = 0
NotificationManagerCompat.from(this).apply {
    // Issue the initial notification with zero progress.
    builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false)
    notify(notificationId, builder.build())

    // Do the job that tracks the progress here.
    // Usually, this is in a worker thread.
    // To show progress, update PROGRESS_CURRENT and update the notification with:
    // builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
    // notificationManager.notify(notificationId, builder.build());

    // When done, update the notification once more to remove the progress bar.
    builder.setContentText("Download complete")
            .setProgress(0, 0, false)
    notify(notificationId, builder.build())
}

Java

...
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID);
builder.setContentTitle("Picture Download")
        .setContentText("Download in progress")
        .setSmallIcon(R.drawable.ic_notification)
        .setPriority(NotificationCompat.PRIORITY_LOW);

// Issue the initial notification with zero progress.
int PROGRESS_MAX = 100;
int PROGRESS_CURRENT = 0;
builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
notificationManager.notify(notificationId, builder.build());

// Do the job that tracks the progress here.
// Usually, this is in a worker thread.
// To show progress, update PROGRESS_CURRENT and update the notification with:
// builder.setProgress(PROGRESS_MAX, PROGRESS_CURRENT, false);
// notificationManager.notify(notificationId, builder.build());

// When done, update the notification once more to remove the progress bar.
builder.setContentText("Download complete")
        .setProgress(0,0,false);
notificationManager.notify(notificationId, builder.build());

Al final de la operación, progress debe ser igual a max. Puedes salir de la barra de progreso para mostrar que la operación finalizó o quitarla. En cualquier caso, actualiza el texto de la notificación para mostrar que la operación se completó. Para quitar la barra de progreso, llama a setProgress(0, 0, false).

Para mostrar una barra de progreso indeterminado (una barra que no indica el porcentaje de finalización), llama a setProgress(0, 0, true). El resultado es un indicador que tiene el mismo estilo que la barra de progreso anterior, con la excepción de que se trata de una animación continua que no indica la finalización. La animación de progreso se ejecuta hasta que llamas a setProgress(0, 0, false) y, luego, actualizas la notificación para quitar el indicador de actividad.

Recuerda cambiar el texto de la notificación para indicar que la operación se completó.

Cómo establecer una categoría para todo el sistema

Android usa categorías predefinidas para todo el sistema a fin de determinar si es necesario molestar al usuario con una notificación determinada cuando este habilita el modo No interrumpir.

Si tu notificación pertenece a una de las categorías de notificación definidas en NotificationCompat, como CATEGORY_ALARM, CATEGORY_REMINDER, CATEGORY_EVENT o CATEGORY_CALL, declárala como tal pasando la categoría adecuada a setCategory():

Kotlin

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE)

Java

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setCategory(NotificationCompat.CATEGORY_MESSAGE);

El sistema usa esta información sobre la categoría de tu notificación para tomar decisiones acerca de cómo mostrarla cuando el dispositivo está en modo No interrumpir. Sin embargo, no es necesario que establezcas una categoría para todo el sistema. Solo debes hacerlo si tus notificaciones coinciden con una de las categorías definidas en NotificationCompat.

Cómo mostrar un mensaje urgente

Es posible que tu app necesite mostrar un mensaje urgente y urgente, como una llamada entrante o una alarma que está sonando. En esas situaciones, puedes asociar un intent de pantalla completa con tu notificación.

Cuando se invoca la notificación, los usuarios ven una de las siguientes opciones, según el estado de bloqueo del dispositivo:

  • Si el dispositivo del usuario está bloqueado, aparece una actividad en pantalla completa que cubre la pantalla de bloqueo.
  • Si el dispositivo del usuario está desbloqueado, la notificación aparece en un formato expandido que incluye opciones para controlar o descartar la notificación.

En el siguiente fragmento de código, se muestra cómo asociar la notificación con un intent de pantalla completa:

Kotlin

val fullScreenIntent = Intent(this, ImportantActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
    fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)

var builder = NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true)

Java

Intent fullScreenIntent = new Intent(this, ImportantActivity.class);
PendingIntent fullScreenPendingIntent = PendingIntent.getActivity(this, 0,
        fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT);

NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setFullScreenIntent(fullScreenPendingIntent, true);

Cómo establecer la visibilidad de la pantalla de bloqueo

Para controlar el nivel de detalle visible en la notificación desde la pantalla de bloqueo, llama a setVisibility() y especifica uno de los siguientes valores:

  • VISIBILITY_PUBLIC: Todo el contenido de la notificación se muestra en la pantalla de bloqueo.

  • VISIBILITY_SECRET: No se muestra ninguna parte de la notificación en la pantalla de bloqueo.

  • VISIBILITY_PRIVATE: En la pantalla de bloqueo, solo se muestra información básica, como el ícono de la notificación y el título del contenido. No se muestra todo el contenido de la notificación.

Cuando configuras VISIBILITY_PRIVATE, también puedes proporcionar una versión alternativa del contenido de la notificación que oculta ciertos detalles. Por ejemplo, una app de SMS podría mostrar una notificación con el mensaje "Tienes 3 mensajes de texto nuevos", pero ocultar el contenido del mensaje y los remitentes. Para proporcionar esta notificación alternativa, primero crea la notificación alternativa con NotificationCompat.Builder como de costumbre. Luego, adjunta la notificación alternativa a la normal con setPublicVersion().

Ten en cuenta que el usuario siempre tiene el control total sobre si sus notificaciones son visibles en la pantalla de bloqueo y puede controlarlas según los canales de notificaciones de tu app.

Cómo actualizar una notificación

Para actualizar una notificación después de emitirla, vuelve a llamar a NotificationManagerCompat.notify() y pásale el mismo ID que usaste antes. Si se descarta la notificación anterior, se creará una nueva.

De manera opcional, puedes llamar a setOnlyAlertOnce() para que tu notificación interrumpa al usuario (con sonido, vibración o pistas visuales) solo la primera vez que aparezca la notificación, y no en las actualizaciones posteriores.

Cómo quitar una notificación

Las notificaciones permanecen visibles hasta que alguna de estas acciones tiene lugar:

  • El usuario descarta la notificación.
  • El usuario presiona la notificación si llamas a setAutoCancel() cuando creas la notificación.
  • Llama a cancel() para un ID de notificación específico. Este método también borra las notificaciones continuas.
  • Llama a cancelAll(), que quita todas las notificaciones que emitiste previamente.
  • La duración especificada transcurre si configuras un tiempo de espera cuando creas la notificación con setTimeoutAfter(). Si es necesario, puedes cancelar una notificación antes de que transcurra el tiempo de espera especificado.

Prácticas recomendadas para apps de mensajería

Ten en cuenta las prácticas recomendadas que se enumeran aquí cuando crees notificaciones para tus apps de mensajería y chat.

Usa MessagingStyle

A partir de Android 7.0 (nivel de API 24), Android proporciona una plantilla de estilo de notificación específica para contenido de mensajería. Con la clase NotificationCompat.MessagingStyle, puedes cambiar varias de las etiquetas que se muestran en la notificación, incluidos el título de la conversación, mensajes adicionales y la vista de contenido de la notificación.

En el siguiente fragmento de código, se muestra cómo personalizar el estilo de una notificación con la clase MessagingStyle.

Kotlin

val user = Person.Builder()
    .setIcon(userIcon)
    .setName(userName)
    .build()

val notification = NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("2 new messages with $sender")
    .setContentText(subject)
    .setSmallIcon(R.drawable.new_message)
    .setStyle(NotificationCompat.MessagingStyle(user)
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
        .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
    )
    .build()

Java

Person user = new Person.Builder()
    .setIcon(userIcon)
    .setName(userName)
    .build();

Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("2 new messages with " + sender)
    .setContentText(subject)
    .setSmallIcon(R.drawable.new_message)
    .setStyle(new NotificationCompat.MessagingStyle(user)
        .addMessage(messages[1].getText(), messages[1].getTime(), messages[1].getPerson())
        .addMessage(messages[2].getText(), messages[2].getTime(), messages[2].getPerson())
    )
    .build();

A partir de Android 9.0 (nivel de API 28), también es necesario usar la clase Person para obtener una renderización óptima de la notificación y sus avatares.

Cuando uses NotificationCompat.MessagingStyle, haz lo siguiente:

  • Llama a MessagingStyle.setConversationTitle() si quieres definir un título para los chats en grupo con más de dos personas. Un buen título de conversación podría ser el nombre del chat en grupo o, si no tiene nombre, una lista de los participantes de la conversación. Sin esto, se podría confundir que el mensaje pertenece a una conversación individual con el remitente del mensaje más reciente de la conversación.
  • Usa el método MessagingStyle.setData() para incluir mensajes multimedia, como imágenes. Se admiten tipos de MIME de patrón image/*.

Cómo usar la respuesta directa

Respuesta directa permite al usuario responder en línea a un mensaje.

  • Después de que un usuario responda con la acción de respuesta en línea, usa MessagingStyle.addMessage() para actualizar la notificación MessagingStyle y no retractes ni canceles la notificación. Si no cancelas la notificación, el usuario podrá enviar varias respuestas desde la notificación.
  • Para que la acción de respuesta en línea sea compatible con Wear OS, llama a Action.WearableExtender.setHintDisplayInlineAction(true).
  • Usa el método addHistoricMessage() para proporcionar contexto a una conversación de respuesta directa. Para ello, agrega mensajes históricos a la notificación.

Habilitar Respuesta inteligente

  • Para habilitar la Respuesta inteligente, llama a setAllowGeneratedResponses(true) en la acción de respuesta. Esto hace que las respuestas de Respuesta inteligente estén disponibles para los usuarios cuando la notificación se conecta con un dispositivo Wear OS. Las respuestas de Respuesta inteligente son generadas por un modelo de aprendizaje automático completamente en el reloj a partir del contexto que brinda la notificación NotificationCompat.MessagingStyle, y no se suben datos a Internet para generar las respuestas.

Agrega metadatos de notificación