Activité en cours

Dans Wear OS, l'association d'une activité en cours à une notification d'activité en cours ajoute cette notification à d'autres surfaces de l'interface utilisateur de Wear OS. Cette approche permet aux utilisateurs de rester plus impliqués dans les activités de longue durée.

Les notifications en cours sont généralement utilisées pour indiquer qu'une notification comporte une tâche d'arrière-plan dans laquelle l'utilisateur est activement impliqué ou est en attente d'une manière ou d'une autre et qui occupe donc l'appareil.

Par exemple, un utilisateur de Wear OS peut utiliser une application d'entraînement physique pour enregistrer une course à partir d'une activité, puis quitter cette application pour lancer une autre tâche. Lorsque l'utilisateur quitte l'application d'entraînement, celle-ci passe à une notification d'activité en cours liée à des tâches en arrière-plan pour le tenir informé de sa course. La notification fournit aux utilisateurs des informations et est un moyen simple de revenir sur l'application en un geste.

Toutefois, pour afficher la notification, l'utilisateur doit balayer l'écran jusqu'à la barre de notification sous le cadran et trouver la notification appropriée. L'action n'est donc pas aussi pratique que sur les autres surfaces.

Avec l'API "Activité en cours", la notification d'activité en cours d'une application peut afficher les informations sur plusieurs nouvelles surfaces pratiques sur Wear OS afin de maintenir les utilisateurs impliqués.

Par exemple, dans cette application d'entraînement physique, les informations peuvent s'afficher sur le cadran de l'utilisateur sous la forme d'une icône tactile de course :

icône-de-course

Figure 1 : Indicateur d'activité

La section Recents (Éléménts récents) du lanceur d'applications global indique également les activités en cours :

lanceur d'applications

Figure 2 : Lanceur global

Quelques exemples de situations dans lesquelles il est conseillé d'utiliser une notification d'activité en cours liée à une activité en cours :

minuteur

Figure 3 : Minuteur : compte à rebours actif qui se termine lorsque le minuteur est mis en pause ou arrêté

carte

Figure 4 : Navigation détaillée : annonce les instructions de navigation vers une destination. Se termine lorsque l'utilisateur atteint la destination ou arrête la navigation

musique

Figure 5 : Multimédia : lit de la musique pendant une session et se termine immédiatement lorsque l'utilisateur met la session en pause

Wear OS crée automatiquement des activités en cours pour les applications multimédias.

Consultez l'atelier de programmation "Activité en cours" pour obtenir un exemple détaillé de création d'activités en cours pour d'autres types d'applications.

Configuration

Pour commencer à utiliser l'API "Activité en cours" dans votre application, ajoutez les dépendances suivantes au fichier build.gradle de votre application :

dependencies {
  implementation "androidx.wear:wear-ongoing:1.0.0"
  // Includes LocusIdCompat and new Notification categories for Ongoing Activity.
  implementation "androidx.core:core:1.6.0"
}

Démarrer une activité en cours

Pour commencer, créez une notification d'activité en cours, puis une activité.

Créer une notification d'activité en cours

Une activité en cours est étroitement liée à une notification d'activité en cours. Elles fonctionnent ensemble pour informer les utilisateurs d'une tâche dans laquelle ils sont activement impliqués ou d'une tâche en attente d'une manière ou d'une autre, et qui occupe donc l'appareil.

Vous devez associer une activité en cours à une notification d'activité en cours. Associer votre activité en cours à une notification présente de nombreux avantages, parmi lesquels :

  • Les notifications sont des solutions de secours sur des appareils non compatibles avec les activités en cours. La notification est la seule surface affichée par votre application lorsqu'elle s'exécute en arrière-plan.
  • Sur Android 11 ou version ultérieure, Wear OS masque la notification dans la barre de notification lorsque l'application est visible en tant qu'activité en cours sur d'autres surfaces.
  • La procédure actuelle d'intégration utilise Notification comme mécanisme de communication.

Créez une notification d'activité en cours à l'aide de Notification.Builder.setOngoing.

Démarrer une activité en cours

Une fois que vous avez défini une notification d'activité en cours, créez une activité en cours, comme illustré dans l'exemple suivant. Consultez les commentaires inclus pour comprendre le comportement de chaque propriété.

Kotlin

var notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
      
      .setSmallIcon(..)
      .setOngoing(true)

val ongoingActivityStatus = Status.Builder()
    // Sets the text used across various surfaces.
    .addTemplate(mainText)
    .build()

val ongoingActivity =
    OngoingActivity.Builder(
        applicationContext, NOTIFICATION_ID, notificationBuilder
    )
        // Sets the animated icon that will appear on the watch face in
        // active mode.
        // If it isn't set, the watch face will use the static icon in
        // active mode.
        .setAnimatedIcon(R.drawable.ic_walk)
        // Sets the icon that will appear on the watch face in ambient mode.
        // Falls back to Notification's smallIcon if not set.
        // If neither is set, an Exception is thrown.
        .setStaticIcon(R.drawable.ic_walk)
        // Sets the tap/touch event so users can re-enter your app from the
        // other surfaces.
        // Falls back to Notification's contentIntent if not set.
        // If neither is set, an Exception is thrown.
        .setTouchIntent(activityPendingIntent)
        // Here, sets the text used for the Ongoing Activity (more
        // options are available for timers and stopwatches).
        .setStatus(ongoingActivityStatus)
        .build()

ongoingActivity.apply(applicationContext)

notificationManager.notify(NOTIFICATION_ID, builder.build())

Java

NotificationCompat.Builder notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
      
      .setSmallIcon(..)
      .setOngoing(true);

OngoingActivityStatus ongoingActivityStatus = OngoingActivityStatus.Builder()
    // Sets the text used across various surfaces.
    .addTemplate(mainText)
    .build();

OngoingActivity ongoingActivity =
    OngoingActivity.Builder(
        applicationContext, NOTIFICATION_ID, notificationBuilder
    )
        // Sets the animated icon that will appear on the watch face in
        // active mode.
        // If it isn't set, the watch face will use the static icon in
        // active mode.
        .setAnimatedIcon(R.drawable.ic_walk)
        // Sets the icon that will appear on the watch face in ambient mode.
        // Falls back to Notification's smallIcon if not set.
        // If neither is set, an Exception is thrown.
        .setStaticIcon(R.drawable.ic_walk)
        // Sets the tap/touch event so users can re-enter your app from the
        // other surfaces.
        // Falls back to Notification's contentIntent if not set.
        // If neither is set, an Exception is thrown.
        .setTouchIntent(activityPendingIntent)
        // Here, sets the text used for the Ongoing Activity (more
        // options are available for timers and stopwatches).
        .setStatus(ongoingActivityStatus)
        .build();

ongoingActivity.apply(applicationContext);

notificationManager.notify(NOTIFICATION_ID, builder.build());

Les étapes suivantes décrivent la partie la plus importante de l'exemple précédent :

  1. Appelez .setOngoing(true) sur NotificationCompat.Builder et déterminez les champs facultatifs.

  2. Créez un élément OngoingActivityStatus (ou une autre option d'état, comme décrit dans la section suivante) pour représenter le texte.

  3. Créez un élément OngoingActivity et définissez un identifiant de notification.

  4. Appelez apply() sur OngoingActivity avec le contexte.

  5. Appelez notificationManager.notify() et entrez le même identifiant de notification que l'activité en cours pour les lier.

État

Utilisez Status pour présenter l'état actuel en direct de l'élément OngoingActivity à l'utilisateur sur les nouvelles surfaces, telles que la section Recents (Éléments récents) du lanceur d'applications. Pour utiliser cette fonctionnalité, utilisez la sous-classe Status.Builder.

Dans la plupart des cas, il vous suffit d'ajouter un modèle qui représente le texte que vous souhaitez afficher dans la section Recents (Éléments récents) du lanceur d'applications.

Vous pouvez personnaliser la manière dont le texte s'affiche avec des segments à l'aide de la méthode addTemplate() et en spécifiant n'importe quelle partie dynamique du texte sous forme de Status.Part.

L'exemple suivant montre comment afficher le mot "time" (heure) en rouge. Cet exemple utilise un élément Status.StopwatchPart pour représenter un chronomètre dans la section Recents (Éléments récents) du lanceur d'applications.

Kotlin

val htmlStatus =
        "<p>The <font color=\"red\">time</font> on your current #type# is #time#.</p>"

val statusTemplate =
        Html.fromHtml(
                htmlStatus,
                Html.FROM_HTML_MODE_COMPACT
        )

// Creates a 5 minute timer.
// Note the use of SystemClock.elapsedRealtime(), not System.currentTimeMillis().
val runStartTime = SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(5)

val status = new Status.Builder()
   .addTemplate(statusTemplate)
   .addPart("type", Status.TextPart("run"))
   .addPart("time", Status.StopwatchPart(runStartTime)
   .build()

Java

String htmlStatus =
        "<p>The <font color=\"red\">time</font> on your current #type# is #time#.</p>";

Spanned statusTemplate =
        Html.fromHtml(
                htmlStatus,
                Html.FROM_HTML_MODE_COMPACT
        );

// Creates a 5 minute timer.
// Note the use of SystemClock.elapsedRealtime(), not System.currentTimeMillis().
Long runStartTime = SystemClock.elapsedRealtime() + TimeUnit.MINUTES.toMillis(5);

Status status = new Status.Builder()
   .addTemplate(statusTemplate)
   .addPart("type", new Status.TextPart("run"))
   .addPart("time", new Status.StopwatchPart(runStartTime)
   .build();

Pour faire référence à une partie du modèle, utilisez le nom encadré par #. Pour obtenir # en sortie, utilisez ## dans le modèle.

L'exemple précédent utilise HTMLCompat pour générer un élément CharSequence à soumettre au modèle, ce qui est plus facile que de définir manuellement un objet Spannable.

Autres personnalisations

Au-delà de Status, vous pouvez personnaliser votre activité ou vos notifications en cours de différentes manières : Toutefois, l'utilisation de ces personnalisations dépend de l'intégration de l'OEM.

Notification d'activité en cours

  • Les options de catégories déterminent la priorité de l'activité en cours.
    • CATEGORY_CALL : appel vocal ou vidéo entrant, ou requête de communication synchrone similaire.
    • CATEGORY_NAVIGATION : carte ou navigation détaillée.
    • CATEGORY_TRANSPORT : commande de transport multimédia pour la lecture.
    • CATEGORY_ALARM : alarme ou minuteur.
    • CATEGORY_WORKOUT : entraînement (nouvelle catégorie)
    • CATEGORY_LOCATION_SHARING : partage temporaire de la position (nouvelle catégorie)
    • CATEGORY_STOPWATCH : chronomètre (nouvelle catégorie)

Activité en cours

  • Icône animée : vecteur noir et blanc, de préférence avec un arrière-plan transparent. S'affiche sur le cadran en mode actif. Si l'icône animée n'est pas fournie, l'icône de notification par défaut est utilisée. Notez que l'icône de notification par défaut est différente pour chaque application.

  • Icône statique : icône vectorielle sur fond transparent. S'affiche sur le cadran en mode ambiant. Si l'icône animée n'est pas définie, l'icône statique est utilisée sur le cadran en mode actif. Si cette icône n'est pas fournie, l'icône de notification est utilisée. Si aucune de ces icônes n'est définie, une exception est générée. Notez que le lanceur d'applications utilise toujours l'icône de l'application.

  • OncontinueActivityStatus : texte brut ou Chronometer. S'affiche dans la section Recents (Éléments récents) du lanceur d'applications. Si cette valeur n'est pas définie, la notification Context text (Texte contextuel) est utilisée.

  • Intent tactile : PendingIntent qui permet de revenir à l'application si l'utilisateur appuie sur l'icône d'activité en cours. S'affiche sur le cadran ou sur l'élément du lanceur d'applications. Il peut être différent de l'intent d'origine utilisé pour lancer l'application. S'il n'est pas fourni, l'intent de contenu de la notification est utilisé. Si aucun de ces éléments n'est défini, une exception est générée.

  • LocusId : identifiant qui attribue le raccourci du lanceur d'applications auquel l'activité en cours correspond. S'affiche dans le lanceur d'applications dans la section Recents (Éléments récents) lorsque l'activité est en cours. Si ce n'est pas le cas, le lanceur d'applications masquera tous les éléments de l'application présents dans la section Recents (Éléments récents) dans le même package et n'affichera que l'activité en cours.

  • Identifiant d'activité en cours : identifiant qui permet de faire la distinction entre les appels à fromExistingOngoingActivity() lorsque plusieurs activités sont en cours sur une application.

Mettre à jour une activité en cours

Dans la plupart des cas, les développeurs créent une nouvelle notification d'activité en cours et une nouvelle activité en cours lorsqu'ils doivent mettre à jour les données à l'écran. Cependant, l'API "Activité en cours" propose aussi des méthodes pour mettre à jour un élément OngoingActivity si vous souhaitez conserver une instance plutôt que de la recréer.

Si l'application s'exécute en arrière-plan, elle peut envoyer des mises à jour à l'API "Activité en cours". Toutefois, n'abusez pas de cette méthode, car elle ignore les appels trop proches les uns des autres. Quelques mises à jour par minute suffisent.

Pour mettre à jour l'activité en cours et la notification publiée, utilisez l'objet que vous avez créé précédemment et appelez update(), comme l'illustre l'exemple suivant :

Kotlin

ongoingActivity.update(context, newStatus)

Java

ongoingActivity.update(context, newStatus);

Pour plus de confort, il existe une méthode statique permettant de créer une activité en cours.

Kotlin

OngoingActivity.recoverOngoingActivity(context)
               .update(context, newStatus)

Java

OngoingActivity.recoverOngoingActivity(context)
               .update(context, newStatus);

Arrêter une activité en cours

Lorsque l'exécution de l'application est terminée en tant qu'activité en cours, il suffit d'annuler la notification en cours.

Vous pouvez également choisir d'annuler la notification ou l'activité en cours qui s'exécute au premier plan, puis de la recréer lorsqu'elle repasse en arrière-plan, mais cela n'est pas obligatoire.

Suspendre une activité en cours

Si votre application dispose d'une action d'arrêt explicite, poursuivez l'activité en cours après sa réactivation. Pour une application sans action d'arrêt explicite, mettez fin à l'activité lorsqu'elle est mise en pause.

Bonnes pratiques

Gardez les points suivants en tête lorsque vous utilisez l'API "Activité en cours" :

  • Appelez ongoingActivity.apply(context) avant notificationManager.notify(...).
  • Définissez une icône statique pour votre activité en cours soit de manière explicite, soit comme solution de secours via la notification. Sinon, vous serez confronté à une IllegalArgumentException.

  • Utilisez des icônes vectorielles noires et blanches avec des arrière-plans transparents.

  • Définissez un intent tactile pour votre activité en cours soit de manière explicite, soit comme solution de secours via la notification. Sinon, vous serez confronté à une IllegalArgumentException.

  • Pour NotificationCompat, utilisez la bibliothèque principale AndroidX core:1.5.0-alpha05+, qui inclut LocusIdCompat et les nouvelles catégories pour l'entraînement, le chronomètre et le partage de position.

  • Si votre application comporte plusieurs activités MAIN LAUNCHER déclarées dans le fichier manifeste, publiez un raccourci dynamique et associez-le à votre activité en cours à l'aide de LocusId.

Publier des notifications multimédias lors de la lecture de contenus multimédias sur des appareils Wear OS

Si le contenu multimédia est en cours de lecture sur un appareil Wear OS, publiez une notification multimédia. Cela permet au système de créer l'activité en cours correspondante.

.

Si vous utilisez Media3, la notification est publiée automatiquement. Si vous créez votre notification manuellement, elle doit utiliser le MediaStyleNotificationHelper.MediaStyle, et la MediaSession correspondante doit avoir son activité de session renseignée.