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 esa página, aprenderás a crear una notificación con varias funciones para Android 4.0 (API nivel 14) y versiones posteriores. Para ver una introducción sobre cómo aparecen las notificaciones en Android, consulta la Descripción general de notificaciones. Para obtener un ejemplo de código en el que se usan notificaciones, consulta el Ejemplo de notificaciones de Android.

Ten en cuenta que en el código que aparece en esta página se utilizan API de NotificationCompat de la biblioteca de compatibilidad de Android. Estas API te permiten agregar funciones disponibles solo en versiones más recientes de Android, al tiempo que proporcionan compatibilidad con Android 4.0 (API nivel 14). Sin embargo, algunas funciones nuevas, como la acción de respuesta en línea, generan una no-op en versiones anteriores.

Cómo agregar la biblioteca de compatibilidad

Si bien la mayoría de los proyectos creados con Android Studio incluye las dependencias necesarias para usar NotificationCompat, deberías verificar que tu archivo build.gradle de nivel de módulo incluya la siguiente dependencia:

dependencies {
        implementation "com.android.support:support-compat:28.0.0"
    }
    

Cómo crear una notificación básica

En su forma más básica y compacta (también conocida como forma contraída), una notificación muestra un ícono, un título y una pequeña cantidad de texto contextual. En esta sección, aprenderás a crear una notificación en la que el usuario pueda hacer clic para iniciar una actividad en tu app.

Figura 1: Una notificación con título y texto

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

Cómo definir el contenido de la notificación

Para comenzar, debes definir el contenido y el canal de la notificación usando un objeto NotificationCompat.Builder. En el ejemplo de abajo, se muestra cómo crear una notificación con los siguientes elementos:

  • Un pequeño ícono, 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 la notificación, establecida por setPriority(). La prioridad determina cuán intrusiva debería ser la notificación en Android 7.1 y versiones anteriores. (Para Android 8.0 y posteriores, debes establecer la importancia del canal, lo que se muestra en esta 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);
    

Ten en cuenta que, para el constructor de NotificationCompat.Builder, debes proporcionar un ID del canal, que se requiere por motivos de compatibilidad con Android 8.0 (API nivel 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. 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 más grandes, incluso sobre cómo agregar una imagen y controles de reproducción multimedia, consulta Crea una notificación con detalles expandibles.

Cómo crear un canal y definir la importancia

Antes de poder publicar la notificación en Android 8.0 y versiones posteriores, debes registrar el canal de notificación de la app en el sistema transfiriendo una instancia de NotificationChannel a createNotificationChannel(). De este modo, 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 new and 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 new and 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);
        }
    }
    

Debido a que debes crear el canal de notificación antes de publicar notificaciones en Android 8.0 y versiones posteriores, deberías ejecutar este código tan pronto como se inicie la app. Se considera que realizar llamadas repetidas es seguro porque cuando se crea un canal de notificación no se lleva a cabo ninguna operación.

Ten en cuenta que el constructor NotificationChannel requiere una importance y usa 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, aunque también debes definir la prioridad con setPriority() para admitir Android 7.1 y versiones anteriores (como se muestra arriba).

Si bien debes definir la importancia/prioridad de la notificación como se muestra aquí, el sistema no garantiza el comportamiento de alerta que obtendrás. 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 debería responder a un toque, en general para abrir una actividad en la app que se corresponda con la notificación. Para hacerlo, debes especificar un intent de contenido definido con un objeto PendingIntent y transfiérelo 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, 0)

    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 will fire 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, 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)
            // Set the intent that will fire when the user taps the notification
            .setContentIntent(pendingIntent)
            .setAutoCancel(true);
    

Ten en cuenta que 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 arriba ayuda a conservar la experiencia de navegación prevista del usuario después de que este abre la app desde la notificación. Pero el uso de esta función depende del tipo de actividad que inicias, que puede ser una de las siguientes:

  • Una actividad que existe exclusivamente para respuestas a la notificación. No hay motivo por que el usuario navegaría a esta actividad durante el uso normal de la app, de modo que la actividad inicia una nueva tarea, en lugar de agregarse a la pila de actividades existente de la app. Este es el tipo de intent que se creó en el ejemplo de arriba.
  • Una actividad que existe en el flujo regular de la app. En este caso, cuando se inicia la actividad, se debería crear una pila de actividades, de modo que se conserven las expectativas del usuario relacionadas con los botones Back y Up.

Para obtener más información sobre las diferentes maneras de configurar el intent de tu notificación, lee Inicia una actividad desde una notificación.

Cómo mostrar la notificación

Para hacer aparecer la notificación, llama NotificationManagerCompat.notify(), transfiérela a un ID único para la notificación y el resultado de NotificationCompat.Builder.build(). Por ejemplo:

Kotlin

    with(NotificationManagerCompat.from(this)) {
        // notificationId is a unique int for each notification that you must define
        notify(notificationId, builder.build())
    }
    

Java

    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

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

Recuerda guardar el ID de la notificación que transfieres a NotificationManagerCompat.notify() porque lo necesitarás más adelante si deseas actualizar o quitar la notificación.

Cómo agregar botones de acción

Una notificación puede ofrecer hasta tres botones de acción que le permitan al usuario responder de manera rápida, como posponer un recordatorio o incluso responder un mensaje de texto. Pero estos botones de acción no deben duplicar la acción realizada cuando el usuario presiona la notificación.

Figura 2: Una notificación con un botón de acción

Para agregar un botón de acción, transfiere un PendingIntent al método addAction(). Esto es similar a configurar la acción de toque predeterminada de la notificación, excepto que en lugar de iniciar una actividad, puedes llevar a cabo una variedad de otras funciones, como iniciar un BroadcastReceiver que realice 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 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

    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);
    

Para obtener más información sobre cómo compilar un BroadcastReceiver para ejecutar trabajos en segundo plano, consulta la Guía de 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 de contenido multimedia.

Cómo agregar una acción de respuesta directa

La acción de respuesta directa, introducida en Android 7.0 (API nivel 24), permite a los usuarios ingresar texto directamente en la notificación, que 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 dentro de la notificación.

Figura 3: Cuando se presiona el botón "Reply", se abre la entrada de texto

La acción de respuesta directa aparece como un botón adicional en la notificación, que permite abrir una entrada de texto. Cuando el usuario termina de escribir, el sistema adjunta la respuesta de texto en el intent que especificaste para la acción de la 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 respuesta directa:

  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 inserción de texto. Luego, tu aplicación para dispositivos portátiles 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);
        

    Precaución: Si reutilizas un PendingIntent, el usuario puede responder a una conversación diferente a la que intenta responder. Debes proporcionar un código de solicitud diferente para cada conversación o un intent que no muestre true cuando llames a equals() en el intent de respuesta de cualquier otra conversación. Con frecuencia, el ID de la conversación se transfiere como parte del paquete de servicios adicionales del intent, pero se ignora cuando llamas a equals().

  3. Adjunta el objeto RemoteInput a una acción con 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 3.

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

Para recibir entradas del usuario desde la IU de respuesta de la notificación, llama a RemoteInput.getResultsFromIntent() y pásala al Intent que recibe 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, debes actualizar la notificación llamando a NotificationManagerCompat.notify() con el mismo ID y la misma etiqueta (si corresponde). Esto es necesario para ocultar la IU de respuesta directa y confirmar al usuario que se recibió y procesó correctamente su respuesta.

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);
    

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

Además, deberías llamar a setRemoteInputHistory() para adjuntar la respuesta en la parte inferior de la notificación. Sin embargo, si vas a compilar una app de mensajería, deberías crear una notificación de estilo de mensajería y adjuntar el nuevo mensaje a la conversación.

Para obtener más consejos sobre las notificaciones de apps de mensajería, consulta las 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 constante.

Figura 4: La barra de progreso durante y después de la operación

Si puedes estimar qué parte de la operación estará completa en cualquier momento, usa el formulario "definido" del indicador (como se muestra en la figura 4) llamando a setProgress(max, progress, false). El primer parámetro es el valor "completo" (como 100); el segundo es qué parte está completa; y el último indica que se trata de una barra de progreso definido.

A medida que progresa la operación, llama continuamente a setProgress(max, progress, false) con un valor de progress actualizado y vuelve a emitir la notificación.

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 here that tracks the progress.
        // Usually, this should be 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 one more time 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 here that tracks the progress.
    // Usually, this should be 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 one more time 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 debería ser igual a max. Puedes dejar que la barra de progreso se siga viendo cuando la operación finalizó o puedes quitarla. En cualquier caso, recuerda actualizar 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 indefinido (una barra que no indica el porcentaje completado de la operación), llama a setProgress(0, 0, true). El resultado es un indicador que tiene el mismo estilo que la barra de progreso que se muestra arriba, excepto que esta barra es una animación constante que no indica qué porcentaje de la operación se completó. Cuando finalice la, llama setProgress(0, 0, false) y, luego, actualiza la notificación para quitar el indicador de actividad.

Además, recuerda cambiar el texto de la notificación para mostrar que la operación se completó.

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

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

Si tu notificación está dentro de una de las categorías de notificación predefinidas en NotificationCompat(por ejemplo, CATEGORY_ALARM, CATEGORY_REMINDER, CATEGORY_EVENT o CATEGORY_CALL), debes declararla como tal pasando la categoría apropiada 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 utiliza esta información sobre la categoría de tu notificación para tomar decisiones acerca de mostrar la notificación cuando el dispositivo está en modo No interrumpir.

Sin embargo, no es necesario que establezcas una categoría para todo el sistema y 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 e importante, como una llamada telefónica entrante o una alarma. En estas situaciones, puedes asociar un intent de pantalla completa a 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 forma expandida e incluye opciones para controlar o descartar la notificación.

En el siguiente fragmento de código, se demuestra 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 los detalles visibles en la notificación desde la pantalla de bloqueo, llama a setVisibility() y especifica uno de los siguientes valores:

  • VISIBILITY_PUBLIC muestra el contenido completo de la notificación.
  • VISIBILITY_SECRET no muestra ninguna parte de la notificación en la pantalla de bloqueo.
  • VISIBILITY_PRIVATE muestra información básica, como el ícono de la notificación y el título del contenido, pero oculta todo el contenido de la notificación.

Cuando se establece VISIBILITY_PRIVATE, también puedes proporcionar una versión alternativa del contenido de la notificación que oculta algunos detalles. Por ejemplo, una aplicación de SMS podría mostrar una notificación con el texto Tienes 3 mensajes de texto nuevos, pero oculta el contenido del mensaje y los remitentes. Para proporcionar esta notificación alternativa, primero créala con NotificationCompat.Builder, como siempre. Luego, adjunta la notificación alternativa a la normal con setPublicVersion().

Sin embargo, el usuario siempre tiene el control final, decide si quiere que las notificaciones se vean en la pantalla de bloqueo e, incluso, puede controlarlo en función de los canales de notificación de tu app.

Cómo actualizar una notificación

Para actualizar esta notificación después de emitirla, vuelve a llamar a NotificationManagerCompat.notify() y pásale una notificación con el mismo ID que usaste antes. Si se la descartó, se crea una notificación 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 aparece, 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 hace clic en la notificación y tú llamaste a setAutoCancel() cuando creaste la notificación.
  • Tú llamas a cancel() para un ID de notificación específico. Este método también borrar las notificaciones constantes.
  • Llamas a cancelAll() que quita todas las notificaciones que emitiste previamente.
  • Si estableciste un tiempo de espera cuando creaste una notificación con setTimeoutAfter(), el sistema la cancela después de que transcurra la duración especificada. 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

Usa las prácticas recomendadas que se enumeran aquí como una referencia rápida sobre lo que debes tener en cuenta cuando creas notificaciones para tus apps de mensajería y chat.

Usa MessagingStyle

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

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

Kotlin

    var notification = NotificationCompat.Builder(this, CHANNEL_ID)
            .setStyle(NotificationCompat.MessagingStyle("Me")
                    .setConversationTitle("Team lunch")
                    .addMessage("Hi", timestamp1, null) // Pass in null for user.
                    .addMessage("What's up?", timestamp2, "Coworker")
                    .addMessage("Not much", timestamp3, null)
                    .addMessage("How about lunch?", timestamp4, "Coworker"))
            .build()
    

Java

    Notification notification = new Notification.Builder(this, CHANNEL_ID)
            .setStyle(new NotificationCompat.MessagingStyle("Me")
                    .setConversationTitle("Team lunch")
                    .addMessage("Hi", timestamp1, null) // Pass in null for user.
                    .addMessage("What's up?", timestamp2, "Coworker")
                    .addMessage("Not much", timestamp3, null)
                    .addMessage("How about lunch?", timestamp4, "Coworker"))
            .build();
    

A partir de Android 8.0 (API nivel 26), las notificaciones que usan la clase NotificationCompat.MessagingStyle muestran más contenido en su forma contraída. También puedes usar el método addHistoricMessage() para proporcionar contexto a una conversación agregando mensajes históricos a las notificaciones relacionadas con la mensajería.

Cuando uses NotificationCompat.MessagingStyle:

  • Llama a MessagingStyle.setConversationTitle() a fin de definir un título para los chats en grupos de más de dos personas. El nombre del chat en grupo puede ser un buen título para la conversación. Si no tiene un nombre específico, puedes usar una lista de los participantes de la conversación. Sin esto, es posible que se considere erróneamente que el mensaje pertenece a una conversación entre dos personas con el remitente a del mensaje más reciente.
  • Usa el método MessagingStyle.setData() para incluir mensajes multimedia, como imágenes. Actualmente, se admiten tipos MIME, del patrón image/*.

Usa Respuesta directa

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

  • Después de que un usuario responde 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, puedes enviar respuestas múltiples desde la notificación.
  • Para hacer que la acción de respuesta en línea sea compatible con Wear OS, llama a Action.WearableExtender.setHintDisplayInlineAction(true).
  • Usar el método addHistoricMessage() a fin de proporcionar contexto para una conversación de respuesta directa agregando mensajes históricos a las notificaciones relacionadas con la mensajería.

Habilita Respuesta inteligente

  • Para habilitar 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 se conecta la notificación con un dispositivo Wear OS. Los mensajes que sugiere Respuesta inteligente son generados por un modelo de aprendizaje automático totalmente incorporado en el reloj a partir del contexto que brinda la notificación de NotificationCompat..MessagingStyle, y no se suben datos a Internet para generar las respuestas.

Agrega metadatos de notificación