Afficher les activités en cours

Les appareils Wear OS sont souvent utilisés pour des expériences de longue durée, comme le suivi d'une séance d'entraînement. Cela pose un problème d'expérience utilisateur : si un utilisateur commence une tâche, puis quitte le cadran, comment peut-il revenir en arrière ? Revenir à l'application à l'aide du lanceur peut être difficile, en particulier en déplacement, ce qui crée des frictions inutiles.

La solution consiste à associer une notification d'activité en cours à un OngoingActivity. Cela permet à l'appareil d'afficher des informations sur l'activité de longue durée dans l'interface utilisateur, ce qui permet d'activer des fonctionnalités telles que l'icône tactile en bas du cadran. Les utilisateurs sont ainsi informés de la tâche en arrière-plan et peuvent revenir à l'application en un seul geste.

Une activité en cours permet également de conserver la visibilité de votre application plus longtemps, empêchant le système de revenir au cadran après une période d'inactivité. Pour en savoir plus, consultez la section Conserver la visibilité de votre application sur Wear.

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é

Une notification d'activité en cours affiche également des informations dans la section Recents (Éléments récents) du lanceur d'applications global. Les utilisateurs peuvent ainsi consulter l'état de leur tâche et interagir à nouveau avec l'application :

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.1.0"
  implementation "androidx.core:core:1.18.0"
}

Créer une activité en cours

Le processus comporte trois étapes :

  1. Créez un standard NotificationCompat.Builder et configurez-le comme étant en cours.
  2. Créez et configurez un objet OngoingActivity, en lui transmettant l'outil de création des notifications.
  3. Appliquez l'activité en cours à l'outil de création des notifications et publiez la notification résultante.

Créer et configurer la notification

Commencez par créer un NotificationCompat.Builder. L'étape clé consiste à appeler setOngoing(true) pour la marquer comme notification en cours. Vous pouvez également définir d'autres propriétés de notification à ce stade, comme la petite icône et la catégorie.

// Create a PendingIntent to pass to the notification builder
val pendingIntent =
    PendingIntent.getActivity(
        this,
        0,
        Intent(this, AlwaysOnActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
        },
        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
    )

val notificationBuilder = NotificationCompat.Builder(this, CHANNEL_ID)
    .setContentTitle("Always On Service")
    .setContentText("Service is running in background")
    .setSmallIcon(R.drawable.animated_walk)
    // Category helps the system prioritize the ongoing activity
    .setCategory(NotificationCompat.CATEGORY_WORKOUT)
    .setContentIntent(pendingIntent)
    .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
    .setOngoing(true) // Important!

Créer l'activité en cours

Créez ensuite une instance de OngoingActivity à l'aide de son compilateur. Le OngoingActivity.Builder nécessite un Context, un ID de notification et le NotificationCompat.Builder que vous avez créé à l'étape précédente.

Configurez les propriétés clés qui s'afficheront sur les nouvelles surfaces de l'UI :

  • Icônes animées et statiques : fournissez des icônes qui s'affichent sur le cadran en mode actif et ambiant.
  • Intent tactile : PendingIntent qui ramène l'utilisateur à votre application lorsqu'il appuie sur l'icône d'activité en cours. Vous pouvez réutiliser le pendingIndent créé à l'étape précédente.

val ongoingActivity =
    OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder)
        // Sets the icon that appears on the watch face in active mode.
        .setAnimatedIcon(R.drawable.animated_walk)
        // Sets the icon that appears on the watch face in ambient mode.
        .setStaticIcon(R.drawable.ic_walk)
        // Sets the tap target to bring the user back to the app.
        .setTouchIntent(pendingIntent)
        .build()

Appliquer à la notification et publier

La dernière étape consiste à lier l'OngoingActivity à la notification, puis à la publier. La méthode ongoingActivity.apply() modifie l'outil de création des notifications d'origine, en ajoutant les données nécessaires pour que le système puisse l'afficher sur les surfaces supplémentaires. Une fois l'application appliquée, vous pouvez créer et publier la notification comme d'habitude.

// This call modifies notificationBuilder to include the ongoing activity data.
ongoingActivity.apply(applicationContext)

// Post the notification.
startForeground(NOTIFICATION_ID, notificationBuilder.build())

Ajouter du texte d'état dynamique au lanceur

Le code précédent ajoute l'icône tactile au cadran. Pour fournir des mises à jour en temps réel encore plus riches dans la section Recents (Éléments récents) du lanceur, créez un objet Status et associez-le à votre OngoingActivity. Si vous ne fournissez pas de Status personnalisé, le système utilise par défaut le texte de contenu de la notification (défini à l'aide de setContentText()). Pour afficher du texte dynamique, utilisez un Status.Builder. Vous pouvez définir une chaîne de modèle avec des espaces réservés et fournir des objets Status.Part pour remplir ces espaces réservés. Le Status.Part peut être dynamique, comme un chronomètre ou un minuteur.

L'exemple suivant montre comment créer un état qui affiche "Run for [a stopwatch timer]" (Courir pendant [un chronomètre]) :

// Define a template with placeholders for the activity type and the timer.
val statusTemplate = "#type# for #time#"

// Set the start time for a stopwatch.
// Use SystemClock.elapsedRealtime() for time-based parts.
val runStartTime = SystemClock.elapsedRealtime()

val ongoingActivityStatus = Status.Builder()
    // Sets the template string.
    .addTemplate(statusTemplate)
    // Fills the #type# placeholder with a static text part.
    .addPart("type", Status.TextPart("Run"))
    // Fills the #time# placeholder with a stopwatch part.
    .addPart("time", Status.StopwatchPart(runStartTime))
    .build()

Enfin, liez ce Status à votre OngoingActivity en appelant setStatus() sur le OngoingActivity.Builder.

val ongoingActivity =
    OngoingActivity.Builder(applicationContext, NOTIFICATION_ID, notificationBuilder)
        // ...
        // Add the status to the OngoingActivity.
        .setStatus(ongoingActivityStatus)
        .build()

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.
    • CATEGORY_LOCATION_SHARING: catégorie de partage temporaire de la position.
    • CATEGORY_STOPWATCH : chronomètre.

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 valeur n'est pas définie, 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" 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 aucune de ces icônes n'est définie, 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

Vous devez mettre à jour l'activité en cours pour la notification existante lorsque vous devez modifier l'état, au lieu de créer une notification et une activité en cours. 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 :

ongoingActivity.update(context, newStatus)

Dans les cas où il n'est pas possible de stocker une référence à l'activité en cours, il existe une méthode statique pour la récupérer. Toutefois, cette méthode est moins recommandée :

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 d'activité 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.

Remarques importantes

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

  • Définissez une icône statique pour votre activité en cours soit de manière explicite, soit comme solution de secours via la notification. Si vous ne le faites pas, vous recevrez 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. Si vous ne le faites pas, vous recevrez une IllegalArgumentException.

  • 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.