Utiliser les notifications Android

Cet atelier de programmation fait partie du cours Développement Android avancé en Kotlin. Vous tirerez pleinement parti de ce cours en suivant les ateliers de programmation dans l'ordre, mais ce n'est pas obligatoire. Tous les ateliers de programmation du cours sont listés sur la page de destination des ateliers de programmation Android avancé en Kotlin.

Introduction

Les notifications sont des messages qui s'affichent en dehors de l'UI de votre application. Les notifications s'affichent en haut de l'écran si l'appareil est déverrouillé ou, selon les paramètres de sécurité, sur l'écran de verrouillage lorsque l'appareil est verrouillé.

Une notification typique se compose d'un titre, d'une description et d'une icône. Une notification peut également comporter des actions cliquables, une réponse rapide, du contenu extensible et des images.

Les notifications peuvent fournir des informations opportunes et comporter des boutons permettant à l'utilisateur d'effectuer des actions rapides, comme envoyer une réponse ou mettre une alarme en veille. Lorsque l'utilisateur clique sur une notification, il est redirigé vers une vue de votre application liée au contenu de la notification.

Les notifications sont un moyen utile de rappeler aux utilisateurs une tâche importante, de les informer d'un événement ou de leur communiquer des informations importantes dont ils ont besoin immédiatement lorsque votre application est en arrière-plan. Utilisez les notifications avec parcimonie. Cela respecte les utilisateurs et augmente les chances que la notification de votre application reçoive l'attention qu'elle mérite.

Dans cet atelier de programmation, vous apprendrez à créer et à utiliser des notifications dans une application Android.

Ce que vous devez déjà savoir

Vous devez maîtriser les éléments suivants :

  • Comment créer des applications Android en Kotlin ? En particulier, travaillez avec le SDK Android.
  • Concevoir des applications à l'aide des composants d'architecture et de la liaison de données.
  • Connaissances de base sur les BroadcastReceivers
  • Connaissances de base d'AlarmManager

Points abordés

  • Découvrez comment créer, styliser et envoyer une notification.
  • Annuler les notifications
  • Découvrez comment créer des canaux de notification.
  • Découvrez comment ajouter des actions rapides aux notifications.
  • Comment afficher les badges de notification sur l'icône de l'application ?

Objectifs de l'atelier

  • Ajoutez une notification à l'application de démarrage.
  • Annulez la notification que vous avez envoyée précédemment.
  • Créez des canaux pour différents types de notifications.
  • Personnalisez les notifications dans l'application de démarrage.
  • Ajoutez des actions rapides pour rendre votre notification interactive.
  • Désactivez les badges de notification.

Cuisiner des œufs est simple, mais peut s'avérer difficile si vous ne respectez pas le temps de cuisson. Dans cet atelier de programmation, vous allez travailler sur une application de minuteur d'œufs et la rendre parfaite, tout comme vos futurs œufs. Vous allez commencer par créer une application de minuteur d'œufs fonctionnelle qui permet à l'utilisateur de définir différents temps de cuisson pour différents types d'œufs. Le minuteur décompte l'intervalle de temps sélectionné et affiche un message toast lorsque les œufs sont prêts.

Cela peut sembler fonctionnel, mais c'est loin d'être parfait et pas vraiment convivial. Pour commencer, le message toast ne s'affiche que brièvement et peut donc facilement passer inaperçu. De plus, si l'application n'est pas au premier plan ou si l'appareil est verrouillé, il n'y a aucun indicateur visuel de l'état du minuteur une fois le message toast disparu.

Idéalement, le minuteur doit utiliser des notifications pour indiquer aux utilisateurs que le temps est écoulé. L'utilisateur doit vraiment savoir que les œufs sont prêts immédiatement, sinon ils seront trop cuits. Les notifications sont visuelles, peuvent inclure des sons et peuvent faire vibrer l'appareil. Autant de moyens d'attirer l'attention de l'utilisateur ! Vous pourrez ainsi obtenir des œufs parfaits et des utilisateurs heureux et bien nourris.

Pour obtenir l'application exemple, vous pouvez :

Clonez le dépôt depuis GitHub et passez à la branche starter.

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


Vous pouvez également télécharger le dépôt sous forme de fichier ZIP, le décompresser et l'ouvrir dans Android Studio.

Télécharger le fichier ZIP

  1. Ouvrez et créez l'application dans Android Studio.

Une image d'œuf et un menu déroulant contenant une liste d'intervalles de temps prédéfinis pour la cuisson d'un œuf s'affichent. Cliquez sur le triangle du menu déroulant Soft Boiled. La première option de la liste est fournie à des fins de test et règle l'alarme sur 10 secondes seulement. À côté de la liste se trouve un bouton qui lance le minuteur. Vous pouvez utiliser ce bouton pour démarrer et arrêter le minuteur à tout moment. Le code de démarrage est entièrement fonctionnel, ce qui signifie que vous pouvez configurer le minuteur et le regarder décompter jusqu'à 0. Une fois le minuteur terminé, un message toast s'affiche, comme indiqué ci-dessous.

  1. Inspectez le code source. L'application de démarrage se compose d'une seule activité nommée MainActivity. Il existe trois sous-packages nommés receiver, ui et util.

  • /receiver : le package receiver contient deux récepteurs de diffusion nommés AlarmReceiver et SnoozeReceiver. AlarmReceiver est déclenché par AlarmManager pour envoyer la notification lorsque le minuteur défini par l'utilisateur est écoulé. SnoozeReceiver gère le clic de l'utilisateur pour mettre en veille la notification.
  • /ui : contient EggTimerFragment, qui fait partie de la section UI de l'application. EggTimerViewModel est responsable du démarrage et de l'annulation du minuteur, ainsi que d'autres tâches liées au cycle de vie de l'application.
  • /util : ce package contient deux fichiers. BindingUtils.kt dispose d'adaptateurs de liaison pour activer la liaison de données entre l'UI de l'application et le ViewModel. NotificationUtils.kt comporte des méthodes d'extension sur NotificationManager.

Les notifications sont un excellent moyen d'attirer l'attention des utilisateurs sur votre application. Que votre application soit en cours d'exécution ou non, une notification affichera une fenêtre pop-up en haut de l'écran et pourra inclure un son ou une vibration. Pour créer une notification, vous devez utiliser un générateur de notifications et fournir un texte de titre, un texte de contenu et une icône. Une fois que le compilateur dispose de tous les champs nécessaires, NotificationManager, qui est un service système, vous aide à afficher ce contenu sous forme de notification. NotificationManager est responsable de l'envoi d'une notification, de la mise à jour de son contenu et de l'annulation de la notification. Dans les étapes suivantes, vous allez ajouter des méthodes d'extension à NotificationManager. De cette façon, chaque fois que vous aurez besoin d'utiliser NotificationManager, vous pourrez utiliser ces fonctions d'extension pour obtenir la fonctionnalité dont vous avez besoin.

Étape 1 : Créez une notification de base

Dans cette tâche, vous allez créer une notification, définir un message pour votre utilisateur et envoyer la notification.

  1. Ouvrez la classe NotificationUtils.kt et recherchez TODO: Step 1.1. Vous trouverez des tâches correspondantes dans cet atelier de programmation et dans le code de l'application.
  2. Examinez la fonction sendNotification() fournie. Vous allez étendre cette fonction d'extension à NotificationManager pour envoyer des notifications.
//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. Obtenez une instance du générateur de notifications, transmettez le contexte de l'application et un ID de canal. L'ID du canal est une valeur de chaîne pour le canal.

Les canaux de notification permettent de regrouper les notifications. En regroupant des types de notifications similaires, les développeurs et les utilisateurs peuvent contrôler toutes les notifications du canal. Une fois un canal créé, il peut être utilisé pour envoyer un nombre illimité de notifications.

//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. Définissez l'icône de notification pour représenter votre application, un titre et le texte du contenu du message que vous souhaitez transmettre à l'utilisateur. Vous verrez d'autres options pour personnaliser davantage votre notification dans l'atelier de programmation, mais il s'agit de la quantité minimale de données que vous devez définir pour envoyer une notification.
//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. Vous devez ensuite appeler notify() avec un ID unique pour votre notification et avec l'objet Notification de votre compilateur.

Cet ID représente l'instance de notification actuelle et est nécessaire pour mettre à jour ou annuler cette notification. Étant donné que votre application ne comporte qu'une seule notification active à un moment donné, vous pouvez utiliser le même ID pour toutes vos notifications. Une constante appelée NOTIFICATION_ID vous est déjà fournie à cet effet dans NotificationUtils.kt. Notez que vous pouvez appeler directement notify(), car vous effectuez l'appel à partir d'une fonction d'extension sur la même classe.

//NotificationUtils.kt
   // TODO: Step 1.4 call notify to send the notification
    // Deliver the notification
    notify(NOTIFICATION_ID, builder.build())
  1. Ouvrez ui/EggTimerViewModel.kt et recherchez la fonction startTimer(). Cette fonction crée une alarme avec l'intervalle de temps sélectionné lorsque l'utilisateur active le minuteur.
  2. Vous déclencherez une notification dans cette fonction lorsque l'utilisateur démarrera le minuteur. Pour appeler la fonction sendNotification() que vous avez implémentée précédemment, vous avez besoin d'une instance de NotificationManager. NotificationManager est un service système qui fournit toutes les fonctions exposées pour l'API Notifications, y compris la fonction d'extension que vous avez ajoutée. Chaque fois que vous souhaitez envoyer, annuler ou modifier une notification, vous devez demander une instance de NotificationManager au système. Appelez la fonction sendNotification()| avec le message de notification et le contexte.
// 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)

Vous y êtes presque. Toutefois, si vous exécutez votre application maintenant et que vous définissez le minuteur, vous ne recevrez pas de notification.

  1. Ouvrez logcat et recherchez "No Channel found". Un message d'erreur indiquant que egg_channel n'existe pas devrait s'afficher. Dans les étapes suivantes, vous en apprendrez plus sur les canaux de notification et vous résoudrez ce problème.

Étape 2 : Canaux de notification

À partir du niveau d'API 26, toutes les notifications doivent être attribuées à un canal. Si vous appuyez de manière prolongée sur l'icône du lanceur d'applications, sélectionnez "Infos sur l'appli", puis "Notifications", vous verrez une liste des canaux de notification associés à l'application. Pour l'instant, la liste est vide, car votre application n'a créé aucun canal.

Les canaux représentent un "type" de notification. Par exemple, votre minuteur peut envoyer une notification lorsque l'œuf est cuit, et utiliser un autre canal pour envoyer des notifications quotidiennes vous rappelant de manger des œufs au petit-déjeuner. Toutes les notifications d'un canal sont regroupées, et les utilisateurs peuvent configurer les paramètres de notification pour un canal entier. Les utilisateurs peuvent ainsi personnaliser leurs paramètres de notification en fonction du type de notification qui les intéresse. Par exemple, vos utilisateurs peuvent désactiver les notifications pour le petit-déjeuner, mais choisir de continuer à voir les notifications du minuteur.

Les développeurs définissent les paramètres initiaux, l'importance et le comportement à appliquer à toutes les notifications d'un canal. Une fois les paramètres initiaux définis, les utilisateurs peuvent les remplacer.

À l'étape 1.1, vous avez utilisé egg_notification_channel_id comme canal de notification. Vous devez maintenant créer et personnaliser les paramètres et le comportement des notifications de ce canal.

  1. Ouvrez EggTimerFragment.kt et recherchez la fonction createChannel().
  2. Transmettez l'ID de canal unique au constructeur de NotificationChannel.
  3. Transmettez le nom du canal de notification, que les utilisateurs verront également sur l'écran Paramètres.
  4. Transmettez le niveau d'importance du canal de notification en tant que dernier paramètre. Les niveaux d'importance seront abordés plus loin dans cet atelier de programmation. Pour l'instant, vous pouvez utiliser NotificationManager.IMPORTANCE_LOW.
  5. Dans l'objet notificationChannel, définissez enableLights sur "true". Ce paramètre permet d'allumer les lumières lorsqu'une notification s'affiche.
  6. Sur l'objet notificationChannel, définissez lightColor sur "red" (rouge) pour afficher un voyant rouge lorsqu'une notification s'affiche.
  7. Dans l'objet notificationChannel, définissez enableVibration sur "true" pour activer les vibrations.
  8. Dans la description du canal de l'ensemble d'objets notificationChannel, définissez la valeur sur ‘Time for breakfast.
  9. Obtenez une instance de NotificationManager en appelant getSystemService().
  10. Appelez createNotificationChannel() sur NotificationManager et transmettez l'objet notificationChannel que vous avez créé à l'étape précédente.
//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. Ensuite, pour créer un canal, vous devez appeler la fonction createChannel() que vous venez d'écrire (étape 1.7). Cette fonction utilise deux paramètres : l'ID et le nom du canal. Vous devez rechercher l'ID et le nom de votre chaîne à partir des ressources de chaîne déjà fournies dans votre projet.
// EggTimerFragment.kt
    // TODO: Step 1.7 call createChannel
    createChannel(
          getString(R.string.egg_notification_channel_id),
          getString(R.string.egg_notification_channel_name)
    )
  1. Vous devez transmettre l'ID du canal au générateur de notifications. Vous l'avez déjà fait à l'étape 1.2. Si vous définissez une valeur incorrecte comme ID de canal, la notification échouera. Ouvrez NotificationUtils.kt pour vérifier que l'ID de chaîne que vous avez défini précédemment est correct.
// 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. Exécutez l'application. Vous verrez qu'elle envoie une notification chaque fois que vous démarrez le minuteur.
  2. Déroulez la barre d'état et vérifiez que le titre, le contenu et l'icône de la notification sont tels que vous les avez définis lors des étapes précédentes.
  3. Pour vérifier la chaîne nouvellement créée, fermez l'application et recherchez son icône. Appuyez de manière prolongée sur l'icône de l'application, puis sélectionnez Infos sur l'appli.

  1. Sélectionnez Notifications dans la liste des paramètres. Un nouveau canal nommé Egg devrait s'afficher juste en dessous du paramètre Afficher les notifications.

Lorsque vous exécutez l'application, la notification s'affiche désormais. En tant que développeur d'applications, vous pouvez personnaliser les paramètres et le comportement de toutes les notifications envoyées sur ce canal, tout comme vos utilisateurs. Félicitations, vous avez créé une notification !

Étape 3 : Ajoutez des notifications à votre application

Jusqu'à présent, nous avons vu l'utilisation de base de l'API Notifications, mais l'envoi d'une notification juste après le démarrage du minuteur n'a pas beaucoup de sens. Les utilisateurs préfèrent probablement être avertis lorsque l'œuf est prêt. Dans la partie suivante de l'atelier de programmation, vous allez corriger ce problème et remplacer le message toast par une notification.

Vous avez déjà envoyé la notification et observé comment elle s'affiche pour les utilisateurs, mais ce n'était que la première étape pour créer des notifications efficaces. Au cours de cette étape, vous allez modifier l'heure d'envoi de votre notification pour qu'elle soit plus appropriée.

Votre application utilise AlarmManager pour configurer une alarme. Le code associé à AlarmManager est déjà fourni dans le code de démarrage et utilisé pour afficher le message toast. AlarmManager suit la sélection de l'heure souhaitée et déclenche la fonction onReceive() de AlarmReceiver.kt lorsque le temps est écoulé. Si vous ouvrez AlarmReceiver.kt et accédez à onReceive(), vous devriez voir le message toast qui s'affiche chaque fois que vous configurez un minuteur.

  1. Ouvrez AlarmReceiver.kt, une instance de NotificationManager, et appelez la fonction sendNotification() avec le texte du message et les paramètres de contexte.
// 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. Vous pouvez également supprimer le toast, car votre application enverra une notification à la fin du minuteur.
// AlarmReceiver.kt
     // TODO: Step 1.10 [Optional] remove toast
//   Toast.makeText(
//       context, 
//       context.getText(R.string.eggs_ready),
//       Toast.LENGTH_SHORT
//   ).show()
  1. Exécutez votre application . Vous devriez recevoir une notification chaque fois que vous démarrez le minuteur et chaque fois qu'il se termine.

Ce n'est pas idéal. Vous ne souhaitez pas envoyer trop de notifications à vos utilisateurs. Vous pouvez supprimer la première notification envoyée lorsque l'utilisateur démarre le minuteur.

  1. Ouvrez EggTimerFragment.kt et supprimez le code de notification de l'étape 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. Exécutez à nouveau votre application.
  2. Réglez un minuteur, mettez-le en arrière-plan et attendez qu'il se termine. Une notification s'affiche. Cette notification est beaucoup plus utile.

Étape 4 : Ajoutez une intention de contenu

  1. Exécutez à nouveau l'application, si elle n'est pas déjà en cours d'exécution.
  2. Cliquez sur la notification. Rien ne se passe !

Afficher la notification et informer l'utilisateur est une bonne chose, mais lorsqu'un utilisateur clique sur une notification, il s'attend à revenir à l'application correspondante. Dans cette partie de l'atelier de programmation, vous allez ajouter un intent à votre notification pour ramener l'utilisateur à l'écran du minuteur.

Un Intent est un objet de messagerie que vous pouvez utiliser pour demander une action à un autre composant d'application. Les intents peuvent être utilisés pour démarrer une activité ou un service, ou pour diffuser un broadcast. Dans ce cas, vous utilisez cet intent pour indiquer au système d'ouvrir MainActivity lorsque l'utilisateur appuie sur la notification. Étant donné que votre application ne comporte qu'une seule vue, vous n'avez pas beaucoup d'options ici. Toutefois, dans une application plus grande, la notification doit créer une expérience fluide en redirigeant l'utilisateur vers un écran pertinent lorsqu'il interagit avec la notification.

  1. Ouvrez NotificationUtils.kt et recherchez la fonction d'extension sendNotification().
  2. Créez un Intent avec votre applicationContext et l'activité à lancer, 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)

Vous avez créé l'intent, mais la notification s'affiche en dehors de votre application. Pour qu'un intent fonctionne en dehors de votre application, vous devez créer un PendingIntent.

PendingIntent accorde des droits à une autre application ou au système pour effectuer une opération au nom de votre application. Un PendingIntent est simplement une référence à un jeton géré par le système qui décrit les données d'origine utilisées pour le récupérer. Cela signifie que même si le processus de l'application propriétaire est arrêté, le PendingIntent lui-même restera utilisable à partir des autres processus auxquels il a été attribué. Dans ce cas, le système utilisera l'intent en attente pour ouvrir l'application en votre nom, que l'application de minuteur soit en cours d'exécution ou non.

  1. Créez un PendingIntent avec applicationContext, NOTIFICATION_ID, le contentIntent que vous avez créé à l'étape précédente et l'indicateur PendingIntent. L'indicateur PendingIntent spécifie l'option permettant de créer un PendingIntent ou d'en utiliser un existant. Vous devez définir PendingIntent.FLAG_UPDATE_CURRENT comme indicateur, car vous ne souhaitez pas créer de notification si une notification existe déjà. Vous modifierez ainsi le PendingIntent actuel associé à l'intention que vous fournissez.
// NotificationUtils.kt
   // TODO: Step 1.12 create PendingIntent
    val contentPendingIntent = PendingIntent.getActivity(
        applicationContext, 
        NOTIFICATION_ID,
        contentIntent,
        PendingIntent.FLAG_UPDATE_CURRENT
    )
  1. Transmettez le PendingIntent à votre notification. Pour ce faire, appelez setContentIntent() sur NotificationBuilder. Désormais, lorsque vous cliquerez sur la notification, le PendingIntent sera déclenché et votre MainActivity s'ouvrira.
  2. Définissez également setAutoCancel() sur true afin que, lorsque l'utilisateur appuie sur la notification, celle-ci se ferme automatiquement lorsqu'il est redirigé vers l'application.
// NotificationUtils.kt
    // TODO: Step 1.13 set content intent
    .setContentIntent(contentPendingIntent)
    .setAutoCancel(true)
  1. Exécutez à nouveau l'application.
  2. Définissez un minuteur, mettez l'application en arrière-plan et attendez que la notification s'affiche.
  3. Une fois la notification affichée, cliquez dessus en tirant la barre d'état vers le bas et observez comment l'application est mise au premier plan.

Étape 5 : Annulez la notification

Vous disposez d'un minuteur fonctionnel avec des notifications, mais il y a un petit problème. Si vous définissez un minuteur, recevez une notification, puis définissez à nouveau le minuteur, la notification précédente reste dans la barre d'état pendant que le nouveau minuteur est en cours d'exécution. Cela peut dérouter l'utilisateur si l'application est en arrière-plan et peut entraîner des œufs pas assez cuits.

Pour résoudre ce problème, vous devez effacer la notification précédente lorsque vous démarrez un nouveau minuteur. Commencez par créer une autre fonction d'extension dans votre NotificationUtils.kt. NotificationManager dispose d'une API permettant d'annuler toutes les notifications actives, appelée cancelAll().

  1. Ouvrez NotificationsUtil.kt.
  2. Ajoutez une fonction d'extension sur NotificationManager qui appelle cancelAll().
// NotificationUtils.kt

// TODO: Step 1.14 Cancel all notifications
/**
 * Cancels all notifications.
 *
 */
fun NotificationManager.cancelNotifications() {
    cancelAll()
}
  1. Ouvrez EggTimerViewModel.kt et accédez à la fonction startTimer().
  2. Dans startTimer(), obtenez une instance de NotificationManager à partir du système et appelez cancelNotifications().
//  EggTimerViewModel.kt
   //TODO Step 1.15 call cancel notification
    val notificationManager =
       ContextCompat.getSystemService(
            app,
            NotificationManager::class.java
        ) as NotificationManager
    notificationManager.cancelNotifications()       
  1. Exécutez l'application et démarrez le minuteur.
  2. Une fois la notification affichée, redémarrez le minuteur et observez comment notre application supprime automatiquement la notification précédente de la barre d'état.

Le framework de notification offre aux développeurs diverses options de personnalisation pour définir des actions personnalisées et styliser leurs notifications selon leurs besoins. Dans cette tâche, vous allez apprendre à personnaliser les notifications de votre minuteur.

Étape 1 : Mettez en forme votre notification

En personnalisant le style de vos notifications en fonction de vos besoins et de leur contenu, vous les rendrez plus visibles et plus semblables à une extension de votre application. Le framework de notification est fourni avec plusieurs styles intégrés pour vous aider, et vous pouvez toujours créer les vôtres.

NotificationCompat propose des styles intégrés pour :

  • BigTextStyle, qui peut afficher un grand bloc de texte, comme le contenu d'un e-mail lorsqu'il est développé.
  • BigPictureStyle, qui affiche des notifications grand format incluant une pièce jointe d'image de grande taille.
  • InboxStyle, qui affiche un contenu textuel de style conversationnel.
  • MediaStyle, qui affiche les commandes de lecture multimédia.
  • MessagingStyle, qui affiche des notifications grand format incluant plusieurs messages entre un nombre quelconque de personnes.

Pour en savoir plus sur les autres styles, consultez la documentation Créer une notification extensible. Dans cette étape, vous allez utiliser NotificationCompat.BigPictureStyle pour créer une notification extensible qui affiche une grande image d'œuf lorsqu'elle est développée.

  1. Ouvrez NotificationUtils.kt et recherchez la fonction sendNotification().
  2. Commencez par charger une image à partir de resources à l'aide de BitmapFactory.
// NotificationUtils.kt

// TODO: Step 2.0 add style
val eggImage = BitmapFactory.decodeResource(
     applicationContext.resources, 
     R.drawable.cooked_egg
)
  1. Créez un fichier BigPictureStyle et définissez votre image.
  2. Définissez bigLargeIcon() sur null pour que la grande icône disparaisse lorsque la notification est développée.
// 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. Définissez le style avec setStyle() sur bigPicStyle.
  2. Définissez la grande icône avec setLargeIcon() sur eggImage afin que l'image s'affiche sous forme d'icône plus petite lorsque la notification est réduite.
// NotificationUtils.kt
// TODO: Step 2.1 add style to builder
.setStyle(bigPicStyle)
.setLargeIcon(eggImage)
  1. Exécutez l'application et définissez un minuteur. Lorsqu'une notification s'affiche pour la première fois, elle est réduite dans le panneau des notifications. Si vous développez la notification, une grande image s'affiche dans la zone de notification étendue.

Étape 2 : Actions de notification

Les actions de notification sont une autre personnalisation que vous pouvez ajouter à vos notifications. Vos notifications redirigent actuellement les utilisateurs vers votre application lorsqu'ils cliquent dessus. En plus de cette action par défaut, vous pouvez ajouter des boutons d'action permettant d'effectuer une tâche liée à l'application depuis la notification.

Une notification peut proposer jusqu'à trois boutons d'action permettant à l'utilisateur de répondre rapidement, par exemple en mettant en veille un rappel ou en répondant à un message. Ces boutons d'action ne doivent pas dupliquer l'action effectuée lorsque l'utilisateur appuie sur la notification.

Pour ajouter un bouton d'action, transmettez un PendingIntent à la fonction addAction() sur le compilateur. Cela revient à configurer l'action par défaut de la notification en appelant setContentIntent(), sauf qu'au lieu de lancer une activité, vous pouvez effectuer diverses autres actions, par exemple démarrer un BroadcastReceiver qui effectue un travail en arrière-plan afin que l'action n'interrompe pas l'application déjà ouverte.

Dans cet atelier de programmation, un BoadcastReceiver nommé SnoozeReceiver vous est déjà fourni. Vous utiliserez SnoozeReceiver pour recevoir le clic de l'utilisateur sur l'action de notification. Dans les étapes suivantes, vous ajouterez du code pour mettre en veille la notification du minuteur pendant 60 secondes lorsque l'utilisateur cliquera sur le bouton d'action "Mettre en veille". Lorsque l'action de report est sélectionnée, le SnoozeReceiver reçoit une intention et crée une alarme pour envoyer une nouvelle notification au bout de 60 secondes.

  1. Ouvrez SnoozeReceiver.kt. Cette classe est semblable à AlarmReceiver que vous avez utilisée précédemment. Dans les étapes suivantes, vous ajouterez du code qui déclenchera la fonction onReceive() de SnoozeReceiver. En bref, le code dans SnoozeReceiver créera une alarme pour envoyer une nouvelle notification une minute plus tard. Faites défiler l'écran jusqu'en bas de la fonction onReceive, obtenez une instance de notificationManager à partir du système et appelez cancelAll.
// SnoozeReceiver.kt
        val notificationManager = ContextCompat.getSystemService(
            context,
            NotificationManager::class.java
        ) as NotificationManager
        notificationManager.cancelAll()
  1. Pour utiliser SnoozeReceiver, ouvrez NotificationUtils.kt.
  2. Créez un snoozeIntent pour SnoozeReceiver juste après le style dans la fonction sendNotification().Intent
  3. Créez une intention en attente en appelant la méthode getBroadcast() sur PendingIntent, qui attend les paramètres des étapes suivantes. Ce PendingIntent sera utilisé par le système pour configurer une nouvelle alarme afin de publier une nouvelle notification après 60 secondes lorsque l'utilisateur appuie sur le bouton de répétition.
  4. Le premier paramètre est le contexte d'application dans lequel cet PendingIntent doit démarrer l'activité.
  5. Le deuxième paramètre est le code de requête, qui correspond au code de requête de cette intention en attente. Si vous devez mettre à jour ou annuler cette intention en attente, vous devez utiliser ce code pour y accéder.
  6. Ensuite, ajoutez l'objet snoozeIntent, qui correspond à l'intent de l'activité à lancer.
  7. Enfin, ajoutez la valeur #FLAG_ONE_SHOT à l'option, car l'intention ne sera utilisée qu'une seule fois. L'action rapide et la notification disparaissent après le premier appui. C'est pourquoi l'intent ne peut être utilisé qu'une seule fois.
// 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. Ensuite, appelez la fonction addAction() sur notificationBuilder. Cette fonction attend une icône et un texte pour décrire votre action à l'utilisateur. Vous devez également ajouter snoozeIntent. Cet intent sera utilisé pour déclencher le bon boadcastReceiver lorsque l'utilisateur cliquera sur votre action.
// NotificationUtils.kt
// TODO: Step 2.3 add snooze action
.addAction(
    R.drawable.egg_icon, 
    applicationContext.getString(R.string.snooze),
    snoozePendingIntent
)
  1. Exécutez l'application de minuterie pour tester l'action de report.
  2. Démarrez le minuteur et mettez l'application en arrière-plan. Une fois le minuteur terminé, développez la notification. Vous verrez qu'elle comporte désormais un bouton d'action "Répéter" qui permet de répéter le minuteur pendant une minute.

Étape 3 : Importance des notifications

L'importance détermine le degré d'interruption (visuelle et sonore) d'une notification. Les notifications à priorité élevée sont plus interruptives pour les utilisateurs.

Vous devez spécifier le niveau d'importance dans le constructeur NotificationChannel. Vous avez initialement défini une importance faible pour l'application de minuteur. Vous pouvez utiliser l'un des cinq niveaux d'importance, allant de IMPORTANCE_NONE(0) à IMPORTANCE_HIGH(4). Le niveau d'importance que vous attribuez à un canal s'applique à tous les messages de notification que vous y publiez.

Niveaux d'importance des canaux

Niveau d'importance visible par l'utilisateur

Importance (Android 8.0 et versions ultérieures)

Priorité (Android 7.1 et versions antérieures)

Émet un signal sonore et s'affiche sous la forme d'une notification prioritaire (en haut de l'écran)

IMPORTANCE_HIGH

PRIORITY_HIGH / PRIORITY_MAX

Émet un son

IMPORTANCE_DEFAULT

PRIORITY_DEFAULT

Pas de son

IMPORTANCE_LOW

PRIORITY_LOW

Pas de signal sonore et ne s'affiche pas dans la barre d'état

IMPORTANCE_MIN

PRIORITY_MIN

Pour savoir comment choisir un niveau de priorité approprié, consultez "Niveaux de priorité" dans le Guide de conception des notifications. Vous devez faire attention lorsque vous sélectionnez un niveau d'importance pour les notifications de votre application. L'importance des chaînes doit être choisie en tenant compte du temps et de l'attention des utilisateurs. Lorsqu'une notification sans importance est présentée comme urgente, elle peut provoquer une alarme inutile et distraire l'utilisateur. Les utilisateurs ont le contrôle total sur le niveau d'importance de leurs notifications. Par conséquent, si vous créez une notification ennuyeuse, ils peuvent désactiver complètement votre canal de notification.

Lorsque vous avez créé la notification à l'étape 1.6, le minuteur était défini pour envoyer des notifications à faible priorité, car il était conçu pour ne pas déranger l'utilisateur avec des notifications. Toutefois, il peut être judicieux d'attirer l'attention de l'utilisateur avant que l'œuf ne soit trop cuit. Pour modifier le niveau d'importance de la notification, commencez par les paramètres du canal. L'importance du canal affecte le niveau d'interruption de toutes les notifications publiées dans le canal. Elle doit être spécifiée dans le constructeur NotificationChannel.

  1. Pour modifier le niveau d'importance du canal de notification de votre application, ouvrez EggTimerFragment.kt et accédez à createChannel(). Remplacez le niveau d'importance IMPORTANCE_LOW par IMPORTANCE_HIGH.
// EggTimerFragment.kt
    val notificationChannel = NotificationChannel(
        channelId,
        channelName,
        // TODO: Step 2.4 change importance
        NotificationManager.IMPORTANCE_HIGH
    )

Pour prendre en charge les appareils exécutant Android 7.1 (niveau d'API 25) ou version antérieure, vous devez également appeler setPriority() pour chaque notification, en utilisant une constante de priorité de la classe NotificationCompat.

  1. Ouvrez NotificationUtils.kt et ajoutez les éléments suivants à l'objet du générateur de notifications.
// 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. Avant d'exécuter l'application, appuyez de manière prolongée sur son icône sur votre appareil ou émulateur, puis sélectionnez "Désinstaller" pour effacer les paramètres de canal précédents. Si vous ne désinstallez pas l'application, les paramètres de priorité des chaînes ne changeront pas, et le comportement ne changera pas lorsque la notification sera publiée.
  2. Exécutez à nouveau l'application et démarrez le minuteur. Cette fois, lorsque la notification est envoyée, une fenêtre pop-up devrait s'afficher en haut de l'écran, que votre application s'exécute au premier plan ou en arrière-plan.

Étape 4 : Badges de notification

Les badges de notification sont de petits points qui s'affichent sur l'icône de l'application associée dans le Lanceur d'applications lorsqu'une notification est active. Les utilisateurs peuvent appuyer de manière prolongée sur l'icône de l'application pour afficher les notifications.

Ces points, appelés badges, s'affichent par défaut. Votre application n'a rien à faire. Toutefois, il peut arriver que les badges n'aient pas de sens pour vos notifications. Vous pouvez donc les désactiver pour chaque canal en appelant setShowBadge(false) sur votre objet NotificationChannel. Étant donné que le minuteur ne comporte qu'une seule notification active à la fois, le badge sur l'icône de votre application n'est pas très utile pour vos utilisateurs. Dans les étapes suivantes, vous allez désactiver le badge et n'afficher qu'une notification pour le minuteur.

  1. Ajoutez setShowBadge(false) au code de création du canal pour que le minuteur désactive les badges.
// EggTimerFragment.kt

    ).apply {
        // TODO: Step 2.6 disable badges for this channel
        setShowBadge(false)
    }
  1. Exécutez à nouveau l'application, démarrez le minuteur et regardez l'icône de l'application. Aucun badge ne devrait s'afficher sur l'icône de l'application.

Le code de solution se trouve dans la branche principale du code que vous avez téléchargé.

Cours Udacity :

Documentation pour les développeurs Android :

Pour accéder aux autres ateliers de programmation de ce cours, consultez la page de destination des ateliers de programmation "Développement Android avancé en Kotlin".