Cette page présente les différentes fonctionnalités de la bibliothèque d'applications pour voitures que vous pouvez utiliser pour implémenter la fonctionnalité de navigation détaillée de votre application.
Déclarer une prise en charge de la navigation dans votre fichier manifeste
Votre application de navigation doit déclarer la catégorie d'application automobile androidx.car.app.category.NAVIGATION
dans le filtre d'intent de son CarAppService
:
<application>
...
<service
...
android:name=".MyNavigationCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.NAVIGATION"/>
</intent-filter>
</service>
...
</application>
Prendre en charge les intents de navigation
Afin de pouvoir prendre en charge les intents de navigation dans votre application, y compris ceux provenant de l'Assistant Google par requête vocale, votre application doit gérer l'intent CarContext.ACTION_NAVIGATE
dans ses Session.onCreateScreen
et Session.onNewIntent
.
Consultez la documentation de CarContext.startCarApp
pour en savoir plus sur le format de l'intent.
Accéder aux modèles de navigation
Les applications de navigation peuvent accéder aux modèles suivants, qui affichent une surface dans en arrière-plan avec la carte et, pendant la navigation, la navigation détaillée les instructions de navigation.
NavigationTemplate
: affiche également un message d'information et des estimations de trajets facultatifs pendant la navigation active.MapWithContentTemplate
: Un modèle qui permet à une application d'afficher des tuiles de carte avec un certain type de contenu (par par exemple, une liste). Le contenu est généralement affiché en superposition sur la des tuiles de carte, la carte étant visible et les zones stables s'ajustant au contenu.
Pour en savoir plus sur la conception de l'interface utilisateur de votre application de navigation à l'aide de ces modèles, consultez l'article Applications de navigation.
Pour accéder aux modèles de navigation, votre application doit déclarer l'autorisation androidx.car.app.NAVIGATION_TEMPLATES
dans son fichier AndroidManifest.xml
:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES"/>
...
</manifest>
Une autorisation supplémentaire est requise pour dessiner des cartes.
Migrer vers MapWithContentTemplate
À partir du niveau d'API 7 de Car App,
MapTemplate
,
PlaceListNavigationTemplate
,
et RoutePreviewNavigationTemplate
sont obsolètes. Les modèles obsolètes continueront d'être acceptés, mais
Nous vous recommandons vivement de migrer vers MapWithContentTemplate
.
Les fonctionnalités fournies par ces modèles peuvent être implémentées
à l'aide de MapWithContentTemplate
. Consultez les extraits de code suivants pour obtenir des exemples:
Modèle de carte
Kotlin
// MapTemplate (deprecated) val template = MapTemplate.Builder() .setPane(paneBuilder.build()) .setActionStrip(actionStrip) .setHeader(header) .setMapController(mapController) .build() // MapWithContentTemplate val template = MapWithContentTemplate.Builder() .setContentTemplate( PaneTemplate.Builder(paneBuilder.build()) .setHeader(header) .build()) .setActionStrip(actionStrip) .setMapController(mapController) .build()
Java
// MapTemplate (deprecated) MapTemplate template = new MapTemplate.Builder() .setPane(paneBuilder.build()) .setActionStrip(actionStrip) .setHeader(header) .setMapController(mapController) .build(); // MapWithContentTemplate MapWithContentTemplate template = new MapWithContentTemplate.Builder() .setContentTemplate(new PaneTemplate.Builder(paneBuilder.build()) .setHeader(header) build()) .setActionStrip(actionStrip) .setMapController(mapController) .build();
Modèle PlaceListNavigationTemplate
Kotlin
// PlaceListNavigationTemplate (deprecated) val template = PlaceListNavigationTemplate.Builder() .setItemList(itemListBuilder.build()) .setHeader(header) .setActionStrip(actionStrip) .setMapActionStrip(mapActionStrip) .build() // MapWithContentTemplate val template = MapWithContentTemplate.Builder() .setContentTemplate( ListTemplate.Builder() .setSingleList(itemListBuilder.build()) .setHeader(header) .build()) .setActionStrip(actionStrip) .setMapController( MapController.Builder() .setMapActionStrip(mapActionStrip) .build()) .build()
Java
// PlaceListNavigationTemplate (deprecated) PlaceListNavigationTemplate template = new PlaceListNavigationTemplate.Builder() .setItemList(itemListBuilder.build()) .setHeader(header) .setActionStrip(actionStrip) .setMapActionStrip(mapActionStrip) .build(); // MapWithContentTemplate MapWithContentTemplate template = new MapWithContentTemplate.Builder() .setContentTemplate(new ListTemplate.Builder() .setSingleList(itemListBuilder.build()) .setHeader(header) .build()) .setActionStrip(actionStrip) .setMapController(new MapController.Builder() .setMapActionStrip(mapActionStrip) .build()) .build();
RoutePreviewNavigationTemplate (Modèle de navigation preview)
Kotlin
// RoutePreviewNavigationTemplate (deprecated) val template = RoutePreviewNavigationTemplate.Builder() .setItemList( ItemList.Builder() .addItem( Row.Builder() .setTitle(title) .build()) .build()) .setHeader(header) .setNavigateAction( Action.Builder() .setTitle(actionTitle) .setOnClickListener { ... } .build()) .setActionStrip(actionStrip) .setMapActionStrip(mapActionStrip) .build() // MapWithContentTemplate val template = MapWithContentTemplate.Builder() .setContentTemplate( ListTemplate.Builder() .setSingleList( ItemList.Builder() .addItem( Row.Builder() .setTitle(title) .addAction( Action.Builder() .setTitle(actionTitle) .setOnClickListener { ... } .build()) .build()) .build()) .setHeader(header) .build()) .setActionStrip(actionStrip) .setMapController( MapController.Builder() .setMapActionStrip(mapActionStrip) .build()) .build()
Java
// RoutePreviewNavigationTemplate (deprecated) RoutePreviewNavigationTemplate template = new RoutePreviewNavigationTemplate.Builder() .setItemList(new ItemList.Builder() .addItem(new Row.Builder() .setTitle(title)) .build()) .build()) .setHeader(header) .setNavigateAction(new Action.Builder() .setTitle(actionTitle) .setOnClickListener(() -> { ... }) .build()) .setActionStrip(actionStrip) .setMapActionStrip(mapActionStrip) .build(); // MapWithContentTemplate MapWithContentTemplate template = new MapWithContentTemplate.Builder() .setContentTemplate(new ListTemplate.Builder() .setSingleList(new ItemList.Builder() .addItem(new Row.Builder() .setTitle(title)) .addAction(new Action.Builder() .setTitle(actionTitle) .setOnClickListener(() -> { ... }) .build()) .build()) .build())) .setHeader(header) .build()) .setActionStrip(actionStrip) .setMapController(new MapController.Builder() .setMapActionStrip(mapActionStrip) .build()) .build();
Communiquer les métadonnées de navigation
Les applications de navigation doivent transmettre des métadonnées de navigation supplémentaires à l'hôte. L'hôte utilise ces informations pour fournir des informations à l'unité principale du véhicule et pour éviter les conflits de ressources partagées entre les applications de navigation.
Les métadonnées de navigation sont fournies via le service de voiture NavigationManager
accessible à partir du CarContext
:
Kotlin
val navigationManager = carContext.getCarService(NavigationManager::class.java)
Java
NavigationManager navigationManager = carContext.getCarService(NavigationManager.class);
Démarrer et arrêter la navigation
Pour que l'hôte puisse gérer plusieurs applications de navigation, notifications d'itinéraire et données de clusters de véhicules, il doit connaître l'état actuel de la navigation. Lorsqu'un utilisateur démarre la navigation, appelez NavigationManager.navigationStarted
.
De même, lorsque la navigation se termine (par exemple, lorsque l'utilisateur arrive à destination ou annule la navigation), appelez NavigationManager.navigationEnded
.
N'appelez NavigationManager.navigationEnded
que lorsque la navigation de l'utilisateur est terminée. Par exemple, si vous devez recalculer l'itinéraire au milieu d'un trajet, utilisez plutôt Trip.Builder.setLoading(true)
.
Parfois, l'hôte a besoin d'une application pour arrêter la navigation et appelle onStopNavigation
dans un objet NavigationManagerCallback
fourni par votre application via NavigationManager.setNavigationManagerCallback
.
L'application doit ensuite cesser de fournir des informations sur le prochain virage dans l'écran du cluster, les notifications de navigation et le guidage vocal.
Mettre à jour les informations sur le trajet
Pendant la navigation active, appelez NavigationManager.updateTrip
.
Les informations fournies dans cet appel pourront être utilisées dans le cluster et les affichages tête haute du véhicule. Selon le véhicule conduit, toutes les informations ne sont pas visibles par l'utilisateur.
Par exemple, l'unité principale pour ordinateur (DHU) affiche la Step
ajoutée au Trip
, mais pas les informations de Destination
.
Intégrer à l'écran du cluster
Pour offrir l'expérience utilisateur la plus immersive possible, vous pouvez aller au-delà de l'affichage des métadonnées de base sur l'écran du cluster du véhicule. À partir du niveau d'API 6 de Car App, les applications de navigation ont la possibilité d'afficher leur propre contenu directement sur l'écran du cluster (dans les véhicules compatibles), avec les limites suivantes :
- L'API de l'écran du cluster n'est pas compatible avec les commandes d'entrée
- L'écran du cluster ne doit afficher que des tuiles de carte. Vous pouvez également afficher une navigation active sur ces tuiles.
- L'API de l'écran du cluster est uniquement compatible avec l'utilisation de
NavigationTemplate
- Contrairement aux écrans principaux, l'écran du cluster peut ne pas afficher de façon cohérente tous les éléments d'interface utilisateur
NavigationTemplate
, tels que les instructions de navigation détaillée, les cartes ETA et les actions. Les tuiles de carte sont le seul élément d'interface utilisateur qui s'affiche de façon cohérente.
- Contrairement aux écrans principaux, l'écran du cluster peut ne pas afficher de façon cohérente tous les éléments d'interface utilisateur
Déclarer la compatibilité des clusters
Pour indiquer à l'application hôte que votre application est compatible avec l'affichage sur l'écran du cluster, vous devez ajouter un élément androidx.car.app.category.FEATURE_CLUSTER
<category>
au <intent-filter>
de votre CarAppService
, comme indiqué dans l'extrait suivant :
<application> ... <service ... android:name=".MyNavigationCarAppService" android:exported="true"> <intent-filter> <action android:name="androidx.car.app.CarAppService" /> <category android:name="androidx.car.app.category.NAVIGATION"/> <category android:name="androidx.car.app.category.FEATURE_CLUSTER"/> </intent-filter> </service> ... </application>
Gérer le cycle de vie et l'état
À partir du niveau d'API 6 de Car App, le flux de cycle de vie est identique, sauf que CarAppService::onCreateSession
prend désormais un paramètre de type SessionInfo
qui fournit des informations supplémentaires sur la Session
en cours de création (le type d'écran et l'ensemble des modèles compatibles).
Les applications peuvent utiliser la même classe Session
pour gérer l'écran du cluster et l'écran principal, ou créer des Sessions
spécifiques à l'écran pour personnaliser le comportement sur chaque écran (comme indiqué dans l'extrait suivant).
Kotlin
override fun onCreateSession(sessionInfo: SessionInfo): Session { return if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER) { ClusterSession() } else { MainDisplaySession() } }
Java
@Override @NonNull public Session onCreateSession(@NonNull SessionInfo sessionInfo) { if (sessionInfo.getDisplayType() == SessionInfo.DISPLAY_TYPE_CLUSTER) { return new ClusterSession(); } else { return new MainDisplaySession(); } }
Nous ne pouvons pas garantir si l'écran du cluster va s'afficher, ni à quel moment. De plus, il est possible que le cluster Session
soit la seule Session
(par exemple, l'utilisateur a remplacé l'écran principal par une autre application lorsque la navigation est active). L'accord standard est le suivant : l'application ne peut contrôler l'écran du cluster qu'après l'appel NavigationManager::navigationStarted
. Toutefois, l'application peut afficher l'écran du cluster en l'absence de navigation active ou ne jamais l'afficher. Il appartient à l'application de gérer ces scénarios en rendant compte de l'état d'inactivité de ses tuiles de carte.
L'hôte crée un binder séparé des instances CarContext
distinctes par Session
. Autrement dit, lorsque vous utilisez des méthodes telles que ScreenManager::push
ou Screen::invalidate
, seule la Session
à partir de laquelle elles sont appelées est concernée. Les applications doivent créer leurs propres canaux de communication entre ces instances si une communication interSession
est nécessaire (par exemple, en utilisant des diffusions, un singleton partagé ou autre chose).
Tester la compatibilité des clusters
Vous pouvez tester votre implémentation sur Android Auto et sur Android Automotive OS Pour Android Auto, vous devez configurer l'unité principale de l'ordinateur de bureau pour émuler l'écran d'un cluster secondaire. Pour Android Automotive OS, les images système génériques de niveau d'API 30 ou supérieur émulent l'écran du cluster.
Personnaliser TravelEstimate avec du texte ou une icône
Pour personnaliser l'estimation du temps de trajet avec du texte et/ou une icône, utilisez la setTripIcon
du TravelEstimate.Builder
ou les méthodes setTripText
. Le NavigationTemplate
utilise TravelEstimate
pour éventuellement définir le texte et les icônes à côté ou à la place de l'heure d'arrivée prévue, du temps restant et de la distance restante.
L'extrait suivant utilise setTripIcon
et setTripText
pour personnaliser l'estimation du temps de trajet :
Kotlin
TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...)) ... .setTripIcon(CarIcon.Builder(...).build()) .setTripText(CarText.create(...)) .build()
Java
new TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...)) ... .setTripIcon(CarIcon.Builder(...).build()) .setTripText(CarText.create(...)) .build();
Envoyer des notifications de navigation détaillée
Fournissez des instructions de navigation détaillée à l'aide d'une notification de navigation fréquemment mise à jour. Pour être traité comme une notification de navigation sur l'écran de la voiture, le compilateur de notifications doit effectuer les opérations suivantes :
- Marquer la notification comme étant en cours avec la méthode
NotificationCompat.Builder.setOngoing
- Définir la catégorie de la notification sur
Notification.CATEGORY_NAVIGATION
. - Étendre la notification avec un
CarAppExtender
Une notification de navigation s'affiche dans le widget de rail au bas de l'écran de la voiture. Si le niveau d'importance de la notification est défini sur IMPORTANCE_HIGH
, elle s'affiche également sous la forme d'une notification prioritaire.
Si l'importance n'est pas définie avec la méthode CarAppExtender.Builder.setImportance
, l'importance du canal de notification est utilisée.
L'application peut définir un PendingIntent
dans le CarAppExtender
qui est envoyé à l'application lorsque l'utilisateur appuie sur la notification prioritaire ou le widget de rail.
Si NotificationCompat.Builder.setOnlyAlertOnce
est appelé avec la valeur true
, une notification d'importance élevée émet une alerte qu'une fois sous forme de notification prioritaire.
L'extrait de code suivant indique comment créer une notification de navigation :
Kotlin
NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) ... .setOnlyAlertOnce(true) .setOngoing(true) .setCategory(NotificationCompat.CATEGORY_NAVIGATION) .extend( CarAppExtender.Builder() .setContentTitle(carScreenTitle) ... .setContentIntent( PendingIntent.getBroadcast( context, ACTION_OPEN_APP.hashCode(), Intent(ACTION_OPEN_APP).setComponent( ComponentName(context, MyNotificationReceiver::class.java)), 0)) .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH) .build()) .build()
Java
new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) ... .setOnlyAlertOnce(true) .setOngoing(true) .setCategory(NotificationCompat.CATEGORY_NAVIGATION) .extend( new CarAppExtender.Builder() .setContentTitle(carScreenTitle) ... .setContentIntent( PendingIntent.getBroadcast( context, ACTION_OPEN_APP.hashCode(), new Intent(ACTION_OPEN_APP).setComponent( new ComponentName(context, MyNotificationReceiver.class)), 0)) .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH) .build()) .build();
Mettez régulièrement à jour la notification de navigation détaillée pour les changements de distance, ce qui actualise le widget de rail, et affichez-la uniquement sous la forme de notification prioritaire.
Vous pouvez contrôler le comportement de la notification prioritaire en définissant l'importance de la notification avec CarAppExtender.Builder.setImportance
. Si l'importance est définie sur IMPORTANCE_HIGH
, une notification prioritaire s'affiche. Si elle est définie sur une autre valeur, seul le widget de rail est actualisé.
Actualiser le contenu de "PlaceListNavigationTemplate"
Vous pouvez autoriser les conducteurs à actualiser le contenu d'un simple geste, tout en parcourant des listes de lieux créées avec PlaceListNavigationTemplate
.
Pour activer l'actualisation des listes, implémentez la méthode onContentRefreshRequested
de l'interface OnContentRefreshListener
et utilisez PlaceListNavigationTemplate.Builder.setOnContentRefreshListener
afin de définir l'écouteur au niveau du modèle.
L'extrait de code suivant montre comment définir l'écouteur au niveau du modèle :
Kotlin
PlaceListNavigationTemplate.Builder() ... .setOnContentRefreshListener { // Execute any desired logic ... // Then call invalidate() so onGetTemplate() is called again invalidate() } .build()
Java
new PlaceListNavigationTemplate.Builder() ... .setOnContentRefreshListener(() -> { // Execute any desired logic ... // Then call invalidate() so onGetTemplate() is called again invalidate(); }) .build();
Le bouton d'actualisation ne s'affiche dans l'en-tête du PlaceListNavigationTemplate
que si l'écouteur a une valeur.
Lorsque le conducteur clique sur le bouton d'actualisation, la méthode onContentRefreshRequested
de votre implémentation de OnContentRefreshListener
est appelée. Dans onContentRefreshRequested
Screen.invalidate
, appelez la méthode.
L'hôte rappelle ensuite la méthode Screen.onGetTemplate
de votre application pour récupérer le modèle avec le contenu actualisé. Pour plus d'informations, consultez la section Actualiser le contenu d'un modèle. Tant que le modèle suivant renvoyé par onGetTemplate
est du même type, il est considéré comme une actualisation et n'est pas comptabilisé dans le quota de modèles.
Fournir des instructions audio
Pour lire les instructions de navigation sur les haut-parleurs de la voiture, votre application doit demander la priorité audio. Dans le cadre de votre AudioFocusRequest
, définissez l'utilisation comme AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
. Définissez également l'obtention de la priorité comme AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
.
Simuler la navigation
Pour valider la fonctionnalité de navigation de votre application lorsque vous l'envoyez au Google Play Store, celle-ci doit implémenter le rappel NavigationManagerCallback.onAutoDriveEnabled
. Lorsque ce rappel est appelé, votre application doit simuler la navigation vers la destination choisie lorsque l'utilisateur démarre la navigation. Votre application peut quitter ce mode chaque fois que le cycle de vie de la Session
actuelle atteint l'état Lifecycle.Event.ON_DESTROY
.
Vous pouvez vérifier que votre implémentation de onAutoDriveEnabled
est appelée en exécutant la commande suivante depuis une ligne de commande :
adb shell dumpsys activity service CAR_APP_SERVICE_NAME AUTO_DRIVE
Ce processus est illustré dans l'exemple suivant :
adb shell dumpsys activity service androidx.car.app.samples.navigation.car.NavigationCarAppService AUTO_DRIVE
Application de navigation par défaut pour voiture
Dans Android Auto, l'application de navigation par défaut pour voiture correspond à la dernière application de navigation lancée par l'utilisateur. Il s'agit de l'application qui reçoit des intents de navigation lorsque l'utilisateur appelle des commandes de navigation via l'Assistant ou lorsqu'une autre application envoie un intent pour démarrer la navigation.
Afficher des alertes de navigation contextuelles
Alert
affiche des informations importantes au conducteur avec des actions facultatives, sans quitter le contexte de l'écran de navigation. Pour fournir une expérience optimale au conducteur, Alert
fonctionne dans le NavigationTemplate
afin d'éviter de bloquer l'itinéraire de navigation et de minimiser les distractions du conducteur.
Alert
n'est disponible que dans le NavigationTemplate
.
Pour avertir un utilisateur hors du NavigationTemplate
, envisagez d'utiliser une notification prioritaire, comme expliqué dans la section Afficher les notifications.
Par exemple, utilisez Alert
pour :
- informer le conducteur d'une information pertinente pour la navigation actuelle, comme une modification des conditions de circulation ;
- demander au conducteur une information concernant la navigation actuelle, telle que la présence d'un radar mobile ;
- proposer une tâche à venir et demander au conducteur s'il l'accepte ou non, par exemple s'il est disposé à prendre quelqu'un à bord sur son chemin.
Dans sa forme de base, une Alert
est composée d'un titre et de la durée de l'Alert
. La durée est représentée par une barre de progression. Vous pouvez éventuellement ajouter un sous-titre, une icône et jusqu'à deux objets Action
.
Une fois qu'une Alert
est affichée, elle n'est pas reportée sur un autre modèle si une interaction du conducteur lui fait quitter le NavigationTemplate
.
Elle reste dans le NavigationTemplate
d'origine jusqu'à ce que l'Alert
expire, que l'utilisateur effectue une action ou que l'application ignore l'Alert
.
Créer une alerte
Utilisez Alert.Builder
pour créer une instance Alert
:
Kotlin
Alert.Builder( /*alertId*/ 1, /*title*/ CarText.create("Hello"), /*durationMillis*/ 5000 ) // The fields below are optional .addAction(firstAction) .addAction(secondAction) .setSubtitle(CarText.create(...)) .setIcon(CarIcon.APP_ICON) .setCallback(...) .build()
Java
new Alert.Builder( /*alertId*/ 1, /*title*/ CarText.create("Hello"), /*durationMillis*/ 5000 ) // The fields below are optional .addAction(firstAction) .addAction(secondAction) .setSubtitle(CarText.create(...)) .setIcon(CarIcon.APP_ICON) .setCallback(...) .build();
Si vous souhaitez écouter l'annulation ou la fermeture de l'Alert
, créez une implémentation de l'interface AlertCallback
.
Les chemins d'appel AlertCallback
sont les suivants :
Si l'
Alert
expire, l'hôte appelle la méthodeAlertCallback.onCancel
avec la valeurAlertCallback.REASON_TIMEOUT
. Il appelle ensuite la méthodeAlertCallback.onDismiss
.Si le pilote clique sur l'un des boutons d'action, l'hôte appelle
Action.OnClickListener
, puisAlertCallback.onDismiss
.Si l'
Alert
n'est pas prise en charge, l'hôte appelleAlertCallback.onCancel
avec la valeurAlertCallback.REASON_NOT_SUPPORTED
. L'hôte n'appelle pasAlertCallback.onDismiss
, carAlert
n'a pas été affichée.
Configurer la durée de l'alerte
Choisissez une durée d'Alert
correspondant aux besoins de votre application. La durée recommandée pour une Alert
de navigation est de 10 secondes. Consultez Alertes de navigation.
pour en savoir plus.
Afficher une alerte
Pour afficher une Alert
, appelez la méthode AppManager.showAlert
disponible via le CarContext
de votre application.
// Show an alert
carContext.getCarService(AppManager.class).showAlert(alert)
- L'appel de
showAlert
avec uneAlert
dont l'alertId
est identique à celui de l'Alert
actuellement affichée n'a aucun effet. L'Alert
n'est pas mise à jour. Pour mettre à jour uneAlert
, vous devez la recréer avec un nouvelalertId
. - Si vous appelez
showAlert
avec uneAlert
dont l'alertId
est différent de celui de l'Alert
actuellement affichée, l'Alert
affichée est ignorée.
Ignorer une alerte
Bien qu'une Alert
soit automatiquement ignorée en raison d'un délai d'inactivité ou d'une interaction du conducteur, vous pouvez également ignorer une Alert
, par exemple si ses informations deviennent obsolètes. Pour ignorer une Alert
, appelez la méthode dismissAlert
avec l'alertId
de l'Alert
.
// Dismiss the same alert
carContext.getCarService(AppManager.class).dismissAlert(alert.getId())
L'appel de dismissAlert
avec un alertId
qui ne correspond pas à celui de l'Alert
actuellement affichée n'a aucun effet. Cela ne génère pas d'exception.