Cómo usar las notificaciones de Android

Este codelab es parte del curso Aspectos avanzados de Android en Kotlin. Aprovecharás al máximo este curso si trabajas con los codelabs en secuencia, pero no es obligatorio. Todos los codelabs del curso se detallan en la página de destino de Codelabs avanzados de Android en Kotlin.

Introducción

Las notificaciones son mensajes que se muestran al usuario fuera de la IU de la app. Las notificaciones se muestran en la parte superior de la pantalla si el dispositivo está desbloqueado o, según la configuración de seguridad, en la pantalla de bloqueo cuando el dispositivo está bloqueado.

Una notificación típica consiste en un título, una descripción y un ícono. Una notificación también puede tener acciones en las que se puede hacer clic, una respuesta rápida, contenido extensible y también imágenes.

Las notificaciones pueden entregar material oportuno y pueden tener botones para permitir que el usuario realice acciones rápidas, como enviar una respuesta o posponer una alarma. Al hacer clic en una notificación, el usuario accede a una vista de tu app relacionada con el contenido de la notificación.

Las notificaciones son una manera útil de recordarles a los usuarios una tarea importante, informarles que ocurrió algo o comunicar la información importante que necesitan de inmediato mientras la app se ejecuta en segundo plano. Usa las notificaciones con moderación. Esto no solo respeta a los usuarios, sino que también hace que sea más probable que la notificación de tu app reciba la atención que merece.

En este codelab, aprenderás a crear y usar notificaciones en una app para Android.

Conocimientos que ya deberías tener

Debes estar familiarizado con lo siguiente:

  • Cómo crear apps para Android en Kotlin En particular, trabaja con el SDK de Android.
  • Cómo diseñar apps con los componentes de la arquitectura y la vinculación de datos
  • Conocimientos básicos de BroadcastReceivers
  • Conocimientos básicos sobre AlarmManager

Qué aprenderás

  • Cómo crear, diseñar y enviar una notificación
  • Cómo cancelar notificaciones
  • Cómo crear canales de notificaciones
  • Cómo agregar acciones rápidas a las notificaciones
  • Cómo mostrar insignias de notificación en el ícono de la app

Actividades

  • Agrega una notificación a la app de inicio.
  • Cancela la notificación que enviaste anteriormente.
  • Crear canales para distintos tipos de notificaciones
  • Personaliza las notificaciones en la app de inicio.
  • Agrega Acciones rápidas para que tus notificaciones sean interactivas.
  • Desactiva las insignias de notificaciones.

Cocinar huevos es simple, pero puede ser una tarea desafiante si no puedes registrar el tiempo. En este codelab, trabajarás en una app de temporizador de huevos y la pondrás al día, como tus huevos futuros. Comenzarás con una app de temporizador de huevos que funciona. Esta le permite al usuario establecer diferentes configuraciones de tiempo de cocción para diferentes estilos de huevos. El temporizador cuenta regresiva desde el intervalo de tiempo seleccionado y muestra un mensaje de aviso cuando los huevos están listos.

Puede parecer funcional, pero no es la opción perfecta ni fácil de usar. Para empezar, el mensaje de aviso se muestra solo durante un breve período y, por lo tanto, es fácil de perder. Además, si la aplicación no está en primer plano o el dispositivo está bloqueado, no hay un indicador visual del estado del temporizador una vez que el mensaje de aviso desaparece.

Idealmente, el temporizador debe usar notificaciones para informar a los usuarios cuando se acabe el tiempo. De verdad, el usuario necesita saber que los huevos están listos de inmediato; de lo contrario, se prepararán. Las notificaciones son visuales, pueden incluir sonidos y hacer que el dispositivo vibre. ¡Todas las maneras de captar la atención del usuario! De esta forma, puede consumir huevos perfectos y usuarios felices alimentados.

Para obtener la app de muestra, puedes hacer lo siguiente:

Clona el repositorio desde GitHub y cambia a la rama starter.

$  git clone https://github.com/googlecodelabs/android-kotlin-notifications


También puedes descargar el repositorio como un archivo ZIP, descomprimirlo y abrirlo en Android Studio.

Download Zip

  1. Abre y ejecuta la app en Android Studio.

Verás una imagen de un huevo y un menú desplegable con una lista de intervalos de tiempo predefinidos para cocinar un huevo. Haga clic en el triángulo del menú desplegable Soft Heril. La primera opción de la lista se ofrece con fines de prueba y establece la alarma en solo 10 segundos. Junto a la lista hay un interruptor que inicia el temporizador de huevo. Usa este interruptor para iniciar y detener el temporizador de huevos cuando quieras. El código de inicio es completamente funcional, lo que significa que puedes configurar el temporizador de huevo y ver cómo realiza la cuenta regresiva hasta 0 días. Una vez que finalice el temporizador, aparecerá un mensaje de aviso, como se muestra a continuación.

  1. Inspecciona el código fuente. La app de inicio consta de una sola actividad llamada MainActivity. Existen tres subpaquetes llamados receiver, ui y util.

  • /receiver: El paquete receiver contiene dos receptores de emisión llamados AlarmReceiver y SnoozeReceiver. AlarmManager activa AlarmReceiver para enviar la notificación cuando el temporizador definido por el usuario está activo. SnoozeReceiver controla el clic del usuario para posponer la notificación.
  • /ui: Contiene el EggTimerFragment, que forma parte de la IU de la app. EggTimerViewModel es responsable de iniciar y cancelar el temporizador y de otras tareas relacionadas con el ciclo de vida de la app.
  • /util: En este paquete hay dos archivos. BindingUtils.kt tiene adaptadores de vinculación para habilitar la vinculación de datos entre la IU de la app y la ViewModel. NotificationUtils.kt tiene métodos de extensión en NotificationManager.

Las notificaciones son una excelente manera de llamar la atención de los usuarios a tu app. Ya sea que la app no se esté ejecutando o no se esté ejecutando en primer plano, una notificación mostrará una ventana emergente en la parte superior de la pantalla y podría incluir sonido o vibración. Para crear una notificación, debes usar un compilador de notificaciones y proporcionar un texto del título, un texto del contenido y un ícono. Una vez que el compilador tenga todos los campos necesarios, NotificationManager, que es un servicio del sistema, te ayudará a mostrar este contenido como una notificación. NotificationManager es responsable de enviar una notificación, actualizar su contenido y cancelarla. En los siguientes pasos, agregarás métodos de extensión a NotificationManager. De esta manera, cada vez que necesites usar NotificationManager, podrás usar estas funciones de extensión para lograr la funcionalidad que necesites.

Paso 1: Crea una notificación básica

En esta tarea, creará una notificación nueva, establecerá un mensaje para su usuario y enviará la notificación.

  1. Abre la clase NotificationUtils.kt y busca TODO: Step 1.1. En este codelab y en el código de la app encontrarás todos los elementos que coinciden.
  2. Examina la función sendNotification() especificada. Extenderás esta función de extensión a NotificationManager para enviar notificaciones.
//NotificationUtils.kt
// TODO: Step 1.1 extension function to send messages (GIVEN)
/**
 * Builds and delivers a notification.
 *
 * @param messageBody, notification text.
 * @param context, activity context.
 */
fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
  1. Obtén una instancia del compilador de notificaciones, pasa el contexto de la app y un ID de canal. El ID del canal es un valor de string para el canal.

Los canales de notificaciones son una forma de agrupar notificaciones. Si agrupas tipos de notificaciones similares, los desarrolladores y usuarios pueden controlar todas las notificaciones del canal. Una vez que creas un canal, puedes usarlo para entregar cualquier cantidad de notificaciones.

//NotificationUtils.kt
// TODO: Step 1.2 get an instance of NotificationCompat.Builder
val builder = NotificationCompat.Builder(
        applicationContext,
        applicationContext.getString(R.string.egg_notification_channel_id)
)
  1. Establece el ícono de notificación para representar tu app, un título y el texto del contenido del mensaje que deseas enviar al usuario. Verás más opciones para personalizar la notificación en el codelab, pero esta es la cantidad mínima de datos que debes configurar para enviar una notificación.
//NotificationUtils.kt
   // TODO: Step 1.3 set title, text and icon to builder
   .setSmallIcon(R.drawable.cooked_egg)
   .setContentTitle(applicationContext.getString(R.string.notification_title))
   .setContentText(messageBody)
  1. A continuación, debes llamar a notify() con un ID único para tu notificación y con el objeto Notification de tu compilador.

Este ID representa la instancia de notificación actual y es necesario para actualizar o cancelar la notificación. Como tu app solo tendrá una notificación activa a la vez, puedes usar el mismo ID en todas ellas. Ya tienes una constante para este propósito, llamada NOTIFICATION_ID, en NotificationUtils.kt. Ten en cuenta que puedes llamar directamente a notify(), ya que realizarás la llamada desde una función de extensión en la misma clase.

//NotificationUtils.kt
   // TODO: Step 1.4 call notify to send the notification
    // Deliver the notification
    notify(NOTIFICATION_ID, builder.build())
  1. Abre ui/EggTimerViewModel.kt y busca la función startTimer(). Esta función crea una alarma con el intervalo de tiempo seleccionado cuando el usuario habilita el temporizador de huevos.
  2. Activará una notificación en esta función cuando el usuario inicie el temporizador. Para llamar a la función sendNotification() que implementaste antes, necesitas una instancia de NotificationManager. NotificationManager es un servicio del sistema que proporciona todas las funciones expuestas de la API de notificaciones, incluida la función de extensión que agregaste. Cada vez que desees enviar, cancelar o actualizar una notificación, deberás solicitar una instancia de NotificationManager al sistema. Llama a la función sendNotification()| con el mensaje de notificación y el contexto.
// EggTimerViewModel.kt
// TODO: Step 1.5 get an instance of NotificationManager 
// and call sendNotification

val notificationManager = ContextCompat.getSystemService(
    app, 
    NotificationManager::class.java
) as NotificationManager
                notificationManager.sendNotification(app.getString(R.string.timer_running), app)

Ya casi terminas. Sin embargo, si ejecutas la app ahora y estableces el temporizador, no recibirás una notificación.

  1. Abre logcat y busca "No Channel found". Deberías ver un mensaje de error que indica que egg_channel no existe. En los siguientes pasos, obtendrás más información sobre los canales de notificaciones y cómo corregir este problema.

Paso 2: Canales de notificaciones

A partir del nivel de API 26, todas las notificaciones deben asignarse a un canal. Si mantienes presionado el ícono de selector de apps, seleccionas la información de la app y presionas las notificaciones, verás una lista de canales de notificaciones asociados con la app. En este momento, la lista está vacía porque la app no creó ningún canal.

Los canales representan una notificación; por ejemplo, el temporizador de huevo puede enviar una notificación cuando se cocina el huevo y también puede usar otro canal para enviar notificaciones diarias para recordarte que debes tomar huevos con tu desayuno. Todas las notificaciones de un canal se agrupan, y los usuarios pueden configurar las notificaciones de un canal completo. Esto les permite a los usuarios personalizar su configuración de notificaciones en función del tipo de notificación que les interese. Por ejemplo, los usuarios pueden inhabilitar las notificaciones de desayuno, pero, de todos modos, eligen ver las notificaciones del temporizador.

Los desarrolladores establecen la configuración inicial, la importancia y el comportamiento que se aplicarán a todas las notificaciones de un canal. Una vez que establezcas la configuración inicial, los usuarios podrán anularla.

En el paso 1.1, usaste egg_notification_channel_id como tu canal de notificaciones, por lo que ahora debes crear y personalizar la configuración de notificaciones y el comportamiento de este canal.

  1. Abre EggTimerFragment.kt y busca la función createChannel().
  2. Pasa el ID de canal único al constructor de NotificationChannel.
  3. Pasa el nombre del canal de notificaciones, que también verán los usuarios en la pantalla Configuración.
  4. Como último parámetro, pasa el nivel de importancia del canal de notificaciones. Más adelante en este codelab, se abordarán los niveles de importancia. Por el momento, puedes usar NotificationManager.IMPORTANCE_LOW.
  5. En el objeto notificationChannel, establece enableLights en verdadero. Este parámetro de configuración habilitará las luces cuando se muestre una notificación.
  6. En el objeto notificationChannel, establece lightColor en rojo para mostrar una luz roja cuando se muestre una notificación.
  7. En el objeto notificationChannel, configura enableVibration como verdadero para habilitar la vibración.
  8. En el objeto notificationChannel, establece la descripción del canal en ‘Time for breakfast'
  9. Para obtener una instancia de NotificationManager, llama a getSystemService().
  10. Llama a createNotificationChannel() en NotificationManager y pasa el objeto notificationChannel que creaste en el paso anterior.
//EggTimerFragment.kt
private fun createChannel(channelId: String, channelName: String) {
    // TODO: Step 1.6 START create a channel
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val notificationChannel = NotificationChannel(
            channelId,
            channelName,
            // TODO: Step 2.4 change importance
            NotificationManager.IMPORTANCE_LOW
        )
        // TODO: Step 2.6 disable badges for this channel

        notificationChannel.enableLights(true)
        notificationChannel.lightColor = Color.RED
        notificationChannel.enableVibration(true)
        notificationChannel.description = "Time for breakfast"

        val notificationManager = requireActivity().getSystemService(
            NotificationManager::class.java
        )
        notificationManager.createNotificationChannel(notificationChannel)
    }
    // TODO: Step 1.6 END create channel
}
  1. Luego, para crear un canal, debes llamar a la función createChannel() que acabas de escribir (paso 1.7). Esta función toma dos parámetros: el ID del canal y el nombre del canal. Debes buscar el ID y el nombre del canal desde los recursos de strings que ya se incluyen en el proyecto.
// EggTimerFragment.kt
    // TODO: Step 1.7 call createChannel
    createChannel(
          getString(R.string.egg_notification_channel_id),
          getString(R.string.egg_notification_channel_name)
    )
  1. Debes pasar el ID del canal al compilador de notificaciones. Ya lo hiciste en el Paso 1.2. Si estableces un valor incorrecto como ID de canal, la notificación fallará. Abre NotificationUtils.kt para verificar que el ID del canal que configuraste antes sea correcto.
// NotificationUtils.kt
val builder = NotificationCompat.Builder(
        applicationContext,
       // TODO: Step 1.8 verify the notification channel name
        applicationContext.getString(R.string.egg_notification_channel_id)
)
  1. Ejecuta la app, y verás que la app envía una notificación cada vez que inicias el temporizador.
  2. Desliza la barra de estado y observa que el título de la notificación, el contenido y el ícono son los mismos que estableciste en los pasos anteriores.
  3. Para verificar el canal que acabas de crear, cierra la app y busca el ícono de la app. Mantén presionado el ícono de la app y selecciona Información de apps.

  1. Selecciona Notificaciones en la lista de configuración. Deberías ver un canal nuevo llamado Egg, justo debajo de la configuración de Mostrar notificaciones.

Cuando ejecutes la app, se mostrará la notificación. Como desarrollador de la app y como usuario, puedes personalizar la configuración y el comportamiento de todas las notificaciones que se envían a través de este canal. ¡Felicitaciones! Creaste una notificación.

Paso 3: Agrega notificaciones a tu app

Hasta ahora, esto muestra el uso básico de la API de notificaciones, pero enviar una notificación inmediatamente después de iniciar el temporizador no tiene mucho sentido. Es probable que los usuarios prefieran recibir notificaciones cuando el huevo esté listo. En la siguiente parte del codelab, corregirás esto y cambiarás el mensaje de aviso a una notificación.

Ya enviaste la notificación y observaste cómo se muestra a los usuarios, pero este fue solo el primer paso para crear notificaciones excelentes. En este paso, cambiarás la notificación para que se envíe en el momento más apropiado.

La app usa AlarmManager para establecer una alarma. El código relacionado con AlarmManager ya aparece en el código de inicio y se usa para mostrar la notificación. AlarmManager realiza un seguimiento de la selección de tiempo deseada y activará la función onReceive() de AlarmReceiver.kt cuando se acabe el tiempo. Si abres AlarmReceiver.kt y navegas a onReceive(), deberías ver el mensaje de aviso que se muestra cada vez que configuras un temporizador de huevos.

  1. Abre AlarmReceiver.kt, una instancia de NotificationManager, y llama a la función sendNotification() con el texto del mensaje y los parámetros de contexto.
// AlarmReceiver.kt
   // TODO: Step 1.9 add call to sendNotification
   val notificationManager = ContextCompat.getSystemService(
       context, 
       NotificationManager::class.java
   ) as NotificationManager
             
   notificationManager.sendNotification(
       context.getText(R.string.eggs_ready).toString(), 
       context
   )
  1. También puedes quitar el aviso, ya que tu app enviará una notificación cuando se acabe el tiempo.
// AlarmReceiver.kt
     // TODO: Step 1.10 [Optional] remove toast
//   Toast.makeText(
//       context, 
//       context.getText(R.string.eggs_ready),
//       Toast.LENGTH_SHORT
//   ).show()
  1. Ejecuta tu app . Deberías ver una notificación cada vez que inicies el temporizador y cada vez que se acabe el tiempo.

Esto no es ideal. No es recomendable que les envíes demasiadas notificaciones a los usuarios. Puedes quitar la primera notificación que se envía cuando el usuario inicia el temporizador.

  1. Abre EggTimerFragment.kt y quita el código de notificación para el paso 1.5.
// EggTimeViewModel.kt

// TODO: Step 1.5 get an instance of NotificationManager 
// and call sendNotification
// val notificationManager = ContextCompat.getSystemService(
//      app,
//      NotificationManager::class.java
// ) as NotificationManager
// notificationManager.sendNotification(app.getString(R.string.eggs_ready), app)
  1. Vuelve a ejecutar tu app.
  2. Establece un temporizador, colócalo en segundo plano y espera a que termine el tiempo. Verás una notificación. Esta notificación es mucho más útil.

Paso 4: Agrega un intent de contenido

  1. Vuelve a ejecutar la app si aún no se está ejecutando.
  2. Haz clic en la notificación. No pasa nada.

Mostrar la notificación e informar al usuario es genial, pero cuando este hace clic en una notificación, espera volver a la app correspondiente. En esta parte del codelab, agregarás un intent a tu notificación para que el usuario vuelva a la pantalla del temporizador.

Una Intent es un objeto de mensajería que puedes usar para solicitar una acción desde otro componente de la app. Los intents se pueden usar para iniciar una actividad, un servicio o entregar una transmisión. En este caso, usas este intent para indicar al sistema que abra MainActivity cuando el usuario presione la notificación. Como tu app consta de una sola vista, no tienes muchas opciones aquí. Sin embargo, en una app más grande, la notificación debería crear una experiencia fluida, llevando al usuario a una pantalla que tenga sentido cuando interactúa con la notificación.

  1. Abre NotificationUtils.kt y busca la función de extensión sendNotification().
  2. Crea un Intent con tu applicationContext y la actividad que se iniciará, MainActivity::class.java.
// NotificationUtils.kt

fun NotificationManager.sendNotification(messageBody: String, applicationContext: Context) {
    // Create the content intent for the notification, which launches
    // this activity
   // TODO: Step 1.11 create intent
    val contentIntent = Intent(applicationContext, MainActivity::class.java)

Creaste el intent, pero la notificación se muestra fuera de la app. Para que un intent funcione fuera de la app, debes crear un PendingIntent nuevo.

PendingIntent otorga derechos a otra aplicación o al sistema para que operen en nombre de tu aplicación. Un elemento PendingIntent en sí es una referencia a un token mantenido por el sistema, que describe los datos originales que se usan para recuperarlo. Esto significa que, aunque se cierre el proceso de su propia aplicación, el PendingIntent seguirá siendo utilizable de otros procesos a los que se haya proporcionado. En este caso, el sistema usará el intent pendiente para abrir la app en tu nombre, sin importar si la app de temporizador se está ejecutando o no.

  1. Crea un PendingIntent con applicationContext, NOTIFICATION_ID, la contentIntent que creaste en el paso anterior y la marca PendingIntent. La marca PendingIntent especifica la opción para crear un PendingIntent nuevo o usar uno existente. Debes configurar PendingIntent.FLAG_UPDATE_CURRENT como la marca, ya que no quieres crear una notificación nueva si existe. De esta manera, modificarás el PendingIntent actual que está asociado al intent que proporcionas.
// NotificationUtils.kt
   // TODO: Step 1.12 create PendingIntent
    val contentPendingIntent = PendingIntent.getActivity(
        applicationContext, 
        NOTIFICATION_ID,
        contentIntent,
        PendingIntent.FLAG_UPDATE_CURRENT
    )
  1. Pasa el PendingIntent a tu notificación. Para ello, llama a setContentIntent() en NotificationBuilder. Ahora, cuando haga clic en la notificación, se activará PendingIntent y se abrirá su MainActivity.
  2. Además, configura el objeto setAutoCancel() como true para que, cuando el usuario presione la notificación, esta se descarte a medida que se dirige a la app.
// NotificationUtils.kt
    // TODO: Step 1.13 set content intent
    .setContentIntent(contentPendingIntent)
    .setAutoCancel(true)
  1. Vuelve a ejecutar la app.
  2. Establece un temporizador, coloca la app en segundo plano y espera a que aparezca la notificación.
  3. Cuando veas la notificación, haz clic en ella deslizando la barra de estado hacia abajo para observar cómo la app pasa al primer plano.

Paso 5: Cancela la notificación

Tienes un temporizador de huevo funcional con notificaciones, pero hay un pequeño problema. Si estableces el temporizador, recibes una notificación y vuelves a establecer el temporizador, la notificación anterior permanecerá en la barra de estado mientras se ejecuta el nuevo temporizador. Esto puede confundir a tu usuario si la app está en segundo plano y puede generar huevos cocidos.

Para solucionar este problema, debes borrar la notificación anterior cuando inicies un temporizador nuevo. Para comenzar, crea otra función de extensión en tu NotificationUtils.kt. NotificationManager tiene una API para cancelar todas las notificaciones activas que se llaman cancelAll().

  1. Abre NotificationsUtil.kt.
  2. Agrega una función de extensión en NotificationManager que llame a cancelAll().
// NotificationUtils.kt

// TODO: Step 1.14 Cancel all notifications
/**
 * Cancels all notifications.
 *
 */
fun NotificationManager.cancelNotifications() {
    cancelAll()
}
  1. Abre EggTimerViewModel.kt y navega a la función startTimer().
  2. Dentro de startTimer(), obtén una instancia del NotificationManager del sistema y llama a cancelNotifications().
//  EggTimerViewModel.kt
   //TODO Step 1.15 call cancel notification
    val notificationManager =
       ContextCompat.getSystemService(
            app,
            NotificationManager::class.java
        ) as NotificationManager
    notificationManager.cancelNotifications()       
  1. Ejecuta la app y, luego, inicia el temporizador.
  2. Una vez que veas la notificación, vuelve a iniciar el temporizador y observa cómo nuestra app borra automáticamente la notificación anterior de la barra de estado.

El framework de notificaciones ofrece una variedad de opciones de personalización para que los desarrolladores establezcan acciones personalizadas y diseñen sus notificaciones según sea necesario. Durante esta tarea, aprenderás a personalizar las notificaciones del temporizador de huevo.

Paso 1: Diseña tu notificación

Si adaptas tus notificaciones de acuerdo con tus necesidades, el contenido de estas se destacará y parecerá más una extensión de tu aplicación. El framework de notificaciones viene con varios estilos integrados para ayudar, y usted siempre puede crear uno propio.

NotificationCompat ofrece estilos integrados para:

  • BigTextStyle, que puede mostrar un bloque de texto grande, como el contenido de un correo electrónico cuando se expande.
  • BigPictureStyle, que muestra notificaciones de formato grande que incluyen un archivo adjunto de imagen grande.
  • InboxStyle, que muestra un contenido de texto con estilo de conversación.
  • MediaStyle, que muestra los controles de reproducción multimedia
  • MessagingStyle, que muestra notificaciones de gran formato que incluyen varios mensajes entre cualquier cantidad de personas.

Puede encontrar más información sobre otros estilos en la documentación sobre Cómo crear una notificación expandible. En este paso, usarás NotificationCompat.BigPictureStyle para crear una notificación expandible que muestre una imagen grande de un huevo cuando se expanda.

  1. Abre NotificationUtils.kt y busca la función sendNotification().
  2. Comienza por cargar una imagen de resources con BitmapFactory.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
  1. Crea un BigPictureStyle nuevo y configura tu imagen.
  2. Establece bigLargeIcon() en null para que el ícono grande desaparezca cuando se expanda la notificación.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
val bigPicStyle = NotificationCompat.BigPictureStyle()
        .bigPicture(eggImage)
        .bigLargeIcon(null)
  1. Establece el estilo de setStyle() en bigPicStyle.
  2. Establece el ícono grande con setLargeIcon() en eggImage, para que la imagen se muestre como un ícono más pequeño cuando se contraiga la notificación.
// NotificationUtils.kt
// TODO: Step 2.1 add style to builder
.setStyle(bigPicStyle)
.setLargeIcon(eggImage)
  1. Ejecuta la app y configura un temporizador. Cuando se muestra la notificación por primera vez, se encuentra en un estado contraído en el panel lateral de notificaciones. Si expandes la notificación, se mostrará una imagen grande en el área de notificaciones extendida.

Paso 2: Acciones de la notificación

Las acciones de notificaciones son otra personalización que puedes agregar a tus notificaciones. Actualmente, las notificaciones redireccionan a su aplicación cuando los usuarios hacen clic en ellas. Además de esta acción de notificación predeterminada, puedes agregar botones de acción que completen una tarea relacionada con la app desde la notificación.

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

Para agregar un botón de acción, pasa un PendingIntent a la función addAction() del compilador. Esto es similar a configurar la acción de toque predeterminada de la notificación llamando a setContentIntent(), excepto que, en lugar de iniciar una actividad, puedes realizar una variedad de otras acciones, por ejemplo, iniciar un BroadcastReceiver que realice un trabajo en segundo plano para que la acción no interrumpa a la app que ya está abierta.

En este codelab, ya tienes una BoadcastReceiver llamada SnoozeReceiver. Utilizarás SnoozeReceiver para recibir un clic del usuario en la acción de notificación. En los siguientes pasos, agregarás código para posponer la notificación del temporizador de huevo durante 60 segundos cuando el usuario haga clic en el botón de acción para posponer. Cuando se haga clic en la acción para posponer, SnoozeReceiver recibirá un intent y creará una alarma nueva para enviar una nueva notificación después de 60 segundos.

  1. Abre SnoozeReceiver.kt. Esta clase es similar a AlarmReceiver que usaste antes. En los siguientes pasos, agregarás código que activará la función onReceive() de SnoozeReceiver. En pocas palabras, el código de SnoozeReceiver creará una nueva alarma para enviar una nueva notificación un minuto después. Desplázate hacia abajo hasta la parte inferior de la función onReceive, obtén una instancia de notificationManager del sistema y llama a cancelAll.
// SnoozeReceiver.kt
        val notificationManager = ContextCompat.getSystemService(
            context,
            NotificationManager::class.java
        ) as NotificationManager
        notificationManager.cancelAll()
  1. Para usar SnoozeReceiver, abre NotificationUtils.kt.
  2. Crea un nuevo snoozeIntent de Intent para el SnoozeReceiver justo después del estilo en la función sendNotification().
  3. Para crear un intent pendiente, llama al método getBroadcast() en PendingIntent, que espera los parámetros de los siguientes pasos. El sistema usará el dispositivo PendingIntent para configurar una alarma nueva a fin de publicar una notificación nueva después de 60 segundos cuando el usuario presione el botón para posponer.
  4. El primer parámetro es el contexto de la aplicación en el que PendingIntent debe iniciar la actividad.
  5. El segundo parámetro es el código de la solicitud, que es el código de la solicitud para este intent pendiente. Si necesitas actualizar o cancelar este intent pendiente, debes usar este código para acceder al intent pendiente.
  6. A continuación, agrega el objeto snoozeIntent, que es el intent de la actividad que se iniciará.
  7. Por último, agrega el valor de marca de #FLAG_ONE_SHOT, ya que el intent se usará solo una vez. La acción rápida y la notificación desaparecerán después del primer toque, por lo que el intent solo se puede usar una vez.
// NotificationUtils.kt

// TODO: Step 2.2 add snooze action
val snoozeIntent = Intent(applicationContext, SnoozeReceiver::class.java)
val snoozePendingIntent: PendingIntent = PendingIntent.getBroadcast(
    applicationContext, 
    REQUEST_CODE, 
    snoozeIntent, 
    FLAGS
)
  1. A continuación, llama a la función addAction() en el notificationBuilder. Esta función espera un ícono y un texto para describir tu acción al usuario. También debes agregar snoozeIntent. Este intent se usará para activar el boadcastReceiver correcto cuando se haga clic en tu acción.
// NotificationUtils.kt
// TODO: Step 2.3 add snooze action
.addAction(
    R.drawable.egg_icon, 
    applicationContext.getString(R.string.snooze),
    snoozePendingIntent
)
  1. Ejecuta la app de temporizador para probar la acción de posponer.
  2. Ejecuta el temporizador y coloca la app en segundo plano. Una vez que finalice el temporizador, expanda la notificación y verá que la notificación ahora tiene un botón de acción para posponer que pospone el temporizador de huevo por otro minuto.

Paso 3: Importancia de las notificaciones

La importancia determina en qué medida la notificación debe interrumpir al usuario de manera visual y auditiva. Las notificaciones de mayor importancia serán más disruptivas para los usuarios.

Debes especificar el nivel de importancia en el constructor NotificationChannel. Originalmente, configuraste la importancia baja para la app de temporizador de huevos. Puedes usar uno de cinco niveles de importancia, que van desde IMPORTANCE_NONE(0) hasta IMPORTANCE_HIGH(4). El nivel de importancia que asignas a un canal se aplica a todos los mensajes de notificación que publicas en él.

Niveles de importancia del canal

Nivel de importancia visible para el usuario

Importancia (Android 8.0 y versiones posteriores)

Prioridad (Android 7.1 y versiones anteriores)

Emite un sonido y aparece como una notificación emergente (aparece en la parte superior de la pantalla)

IMPORTANCE_HIGH

PRIORITY_HIGH/PRIORITY_MAX

Emite un sonido

IMPORTANCE_PREDETERMINADO

PRIORITY_DEFAULT

Sin sonido

IMPORTANCE_LOW

PRIORITY_LOW

No emite sonido ni aparece en la barra de estado

IMPORTANCE_MIN

PRIORITY_MIN

Para obtener información sobre cómo elegir un nivel de prioridad adecuado, consulta los niveles de prioridad en la guía de diseño de notificaciones. Debes tener cuidado cuando selecciones un nivel de importancia para las notificaciones de tu app. Debes elegir la importancia del canal teniendo en cuenta el tiempo y la atención del usuario. Cuando una notificación no importante se oculta como urgente, puede generar una alarma innecesaria que genere distracción. Los usuarios tienen control total sobre el nivel de importancia de sus notificaciones, por lo que, si creas una notificación molesta, pueden desactivar tu canal de notificaciones por completo.

Cuando creaste la notificación en el paso 1.6, el temporizador de huevo se configuró para enviar notificaciones con una prioridad baja, ya que se diseñó para no molestar al usuario con las notificaciones. Sin embargo, podría ser una buena idea llamar la atención del usuario antes de que se cocine el huevo. Para cambiar el nivel de importancia de la notificación, comienza por la configuración del canal. La importancia del canal afecta el nivel de interrupción de todas las notificaciones que se publican y debe especificarse en el constructor NotificationChannel.

  1. Para cambiar el nivel de importancia del canal de notificaciones de tu app, abre EggTimerFragment.kt y navega a createChannel(). Cambia el nivel de importancia de IMPORTANCE_LOW a IMPORTANCE_HIGH.
// EggTimerFragment.kt
    val notificationChannel = NotificationChannel(
        channelId,
        channelName,
        // TODO: Step 2.4 change importance
        NotificationManager.IMPORTANCE_HIGH
    )

Para admitir dispositivos con Android 7.1 (nivel de API 25) o versiones anteriores, también debes llamar a setPriority() para cada notificación, usando una constante de prioridad de la clase NotificationCompat.

  1. Abre NotificationUtils.kt y agrega lo siguiente al objeto compilador de notificaciones:
// NotificationUtils.kt
   .addAction(
       R.drawable.common_google_signin_btn_icon_dark,
       applicationContext.getString(R.string.snooze),
       snoozePendingIntent
    )
   // TODO: Step 2.5 set priority
    .setPriority(NotificationCompat.PRIORITY_HIGH)
  1. Antes de ejecutar la app, haz clic en el ícono de la app del dispositivo o emulador y selecciona Desinstalar para borrar la configuración del canal anterior. Si no desinstala la app, no se modificará la configuración de prioridad del canal, y no se modificará el comportamiento cuando se publique la notificación.
  2. Ahora, vuelve a ejecutar la app e inicia el temporizador. Esta vez, cuando se entregue la notificación, deberías ver una ventana emergente en la parte superior de la pantalla, independientemente de si la app se está ejecutando en primer o segundo plano.

Paso 4: Insignias de notificaciones

Las insignias de notificaciones son puntos pequeños que aparecen en el ícono de selector de la app asociada cuando esta tiene una notificación activa. Los usuarios pueden mantener presionado el ícono de la app para ver las notificaciones.

Estos puntos, llamados insignias, aparecen de forma predeterminada, y tu app no tiene que realizar ninguna acción. Sin embargo, es posible que las insignias no tengan sentido para tus notificaciones, por lo que puedes inhabilitarlas en cada canal llamando a setShowBadge(false) en tu objeto NotificationChannel. Dado que el temporizador de huevos solo tiene una notificación activa a la vez, la insignia del ícono de la app no ofrece mucho beneficio para los usuarios. En los siguientes pasos, inhabilitarás la insignia y solo se mostrará una notificación para el temporizador de huevos.

  1. Agrega setShowBadge(false) al código de creación del canal del temporizador de huevos para inhabilitar las insignias.
// EggTimerFragment.kt

    ).apply {
        // TODO: Step 2.6 disable badges for this channel
        setShowBadge(false)
    }
  1. Vuelve a ejecutar la app, inicia el temporizador y observa el ícono de la app. No deberías ver insignias en el ícono de la app.

El código de la solución se encuentra en la rama principal del código descargado.

Curso de Udacity:

Documentación para desarrolladores de Android:

Para obtener vínculos a otros codelabs de este curso, consulta la página de destino de Codelabs avanzados de Android en Kotlin.