À partir du niveau d'API Android 26, les notifications persistantes sont obligatoires pour les services de premier plan. Cette exigence vise à vous empêcher de masquer des services qui pourraient solliciter excessivement les ressources système, en particulier la batterie. Cette exigence crée un problème potentiel : si une application comportant plusieurs services de premier plan ne gère pas soigneusement la notification afin qu'elle soit partagée entre tous les services, plusieurs notifications persistantes et non ignorables peuvent s'afficher, ce qui entraîne un encombrement indésirable dans la liste active des notifications.
Ce problème devient plus complexe lorsque vous utilisez des SDK tels que le SDK Navigation, qui exécutent des services de premier plan indépendants de l'application et qui ont leurs propres notifications persistantes indépendantes, ce qui les rend difficiles à consolider.
Pour résoudre ces problèmes, le SDK Navigation v1.11 a introduit une API simple permettant de gérer les notifications persistantes dans l'application, y compris dans le SDK.

Composants
Le gestionnaire de services de premier plan fournit un wrapper autour de la classe de service de premier plan Android et de la classe de notification persistante. La fonction principale de ce wrapper consiste à appliquer la réutilisation de l'ID de notification afin que la notification soit partagée entre tous les services de premier plan à l'aide du gestionnaire.

Le SDK Navigation contient des méthodes statiques pour initialiser et obtenir le singleton ForegroundServiceManager. Ce singleton ne peut être initialisé qu'une seule fois pendant la durée de vie du SDK Navigation. Par conséquent, si vous utilisez l'un des appels d'initialisation (initForegroundServiceManagerMessageAndIntent() ou initForegroundServiceManagerProvider()), vous devez l'entourer d'un bloc try-catch au cas où ce chemin serait réintroduit. Le SDK Navigation
génère une exception d'exécution si vous appelez l'une ou l'autre méthode plus d'une fois, sauf si vous
effacez d'abord toutes les références à ForegroundServiceManager et appelez
clearForegroundServiceManager() avant chaque appel suivant.
Les quatre paramètres de initForegroundServiceManagerMessageAndIntent() sont application, notificationId, defaultMessage et resumeIntent. Si les trois derniers paramètres sont nuls, la notification est la notification standard du SDK Navigation. Il est toujours possible de masquer d'autres services de premier plan dans l'application derrière cette notification. Le paramètre notificationId spécifie l'ID de notification à utiliser pour la notification. S'il est nul, une valeur arbitraire est utilisée. Vous pouvez le définir explicitement pour éviter les conflits avec d'autres notifications, comme celles d'un autre SDK. defaultMessage est une chaîne qui s'affiche lorsque le système ne navigue pas. resumeIntent est un intent qui se déclenche lorsque vous cliquez sur la notification. Si resumeIntent est nul, les clics sur la notification sont ignorés.
Les trois paramètres de initForegroundServiceManagerProvider() sont application, notificationId et notificationProvider. Si les deux derniers paramètres sont nuls, la notification est la notification standard du SDK Navigation. Le paramètre notificationId spécifie l'ID de notification à utiliser pour la notification. S'il est nul, une valeur arbitraire est utilisée. Vous pouvez le définir explicitement pour éviter les conflits avec d'autres notifications, comme celles d'un autre SDK. Si notificationProvider est défini, le fournisseur est toujours responsable de la génération de la notification à afficher.
La méthode getForegroundServiceManager() du SDK Navigation renvoie le singleton du gestionnaire de services de premier plan. Si vous n'en avez pas encore généré, cela équivaut à appeler initForegroundServiceManagerMessageAndIntent() avec des paramètres nuls pour notificationId, defaultMessage et resumeIntent.
ForegroundServiceManager comporte trois méthodes simples. Les deux premières permettent de déplacer un service au premier plan et en arrière-plan, et sont généralement appelées à partir du service créé. L'utilisation de ces méthodes garantit que les services sont associés à la notification persistante partagée. La dernière méthode, updateNotification(), indique au gestionnaire que la notification a changé et qu'elle doit être affichée à nouveau.
Si vous avez besoin d'un contrôle total sur la notification persistante partagée, l'API fournit une interface NotificationContentProvider pour définir un fournisseur de notifications, qui contient une seule méthode permettant d'obtenir une notification avec le contenu actuel. Elle fournit également une classe de base, que vous pouvez éventuellement utiliser pour définir le fournisseur. L'un des principaux objectifs de la classe de base est de fournir un moyen d'appeler updateNotification() sans avoir à accéder à ForegroundServiceManager. Si vous utilisez une instance du fournisseur de notifications pour recevoir de nouveaux messages de notification, vous pouvez appeler directement cette méthode interne pour afficher le message dans la notification.
Scénarios d'utilisation
Cette section décrit les scénarios d'utilisation des notifications persistantes partagées.
- Masquer les notifications persistantes d'autres services de premier plan de l'application
- Le scénario le plus simple consiste à conserver le comportement actuel et à n'utiliser la notification persistante que pour afficher les informations du SDK Navigation. D'autres services peuvent se cacher derrière cette notification à l'aide des méthodes
startForeground()etstopForeground()du gestionnaire de services de premier plan. - Masquer les notifications persistantes d'autres services de premier plan de l'application, mais définir le texte par défaut affiché lorsque vous ne naviguez pas
- Le deuxième scénario le plus simple consiste à conserver le comportement actuel et à n'utiliser
la notification persistante que pour afficher les informations du SDK Navigation, sauf
lorsque le système ne navigue pas. Lorsque le système ne navigue pas, la
chaîne fournie à
initForegroundServiceManagerMessageAndIntent()s'affiche au lieu de la chaîne par défaut du SDK Navigation qui mentionne "Google Maps". Vous pouvez également utiliser cet appel pour définir l'intent de reprise qui se déclenche lorsque vous cliquez sur la notification. - Contrôler entièrement l'affichage de la notification persistante
- Le dernier scénario nécessite de définir et de créer un fournisseur de notifications
et de le transmettre à
ForegroundServiceManagerà l'aide deinitForegroundServiceManagerProvider(). Cette option vous permet de contrôler entièrement ce qui est affiché dans la notification, mais elle déconnecte également les informations de notification du SDK Navigation de la notification, ce qui supprime les invites utiles affichées dans la notification. Google ne fournit pas de moyen simple de récupérer ces informations et de les insérer dans la notification.
Exemple de fournisseur de notifications
L'exemple de code suivant montre comment créer et renvoyer des notifications à l'aide d'un simple fournisseur de contenu de notification.
public class NotificationContentProviderImpl
extends NotificationContentProviderBase
implements NotificationContentProvider {
private String channelId;
private Context context;
private String message;
/** Constructor */
public NotificationContentProviderImpl(Application application) {
super(application);
message = "-- uninitialized --";
channelId = null;
this.context = application;
}
/**
* Sets message to display in the notification. Calls updateNotification
* to display the message immediately.
*
* @param msg The message to display in the notification.
*/
public void setMessage(String msg) {
message = msg;
updateNotification();
}
/**
* Returns the notification as it should be rendered.
*/
@Override
public Notification getNotification() {
Notification notification;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
Spanned styledText = Html.fromHtml(message, FROM_HTML_MODE_LEGACY);
String channelId = getChannelId(context);
notification =
new Notification.Builder(context, channelId)
.setContentTitle("Notifications Demo")
.setStyle(new Notification.BigTextStyle()
.bigText(styledText))
.setSmallIcon(R.drawable.ic_navigation_white_24dp)
.setTicker("ticker text")
.build();
} else {
notification = new Notification.Builder(context)
.setContentTitle("Notification Demo")
.setContentText("testing non-O text")
.build();
}
return notification;
}
// Helper to set up a channel ID.
private String getChannelId(Context context) {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
if (channelId == null) {
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(
"default", "navigation", NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription("For navigation persistent notification.");
notificationManager.createNotificationChannel(channel);
channelId = channel.getId();
}
return channelId;
} else {
return "";
}
}
}
Une fois que vous avez créé NotificationContentProviderImpl, connectez-y le SDK Navigation à l'aide du code suivant :
ForegroundServiceManager f = NavigationApi.getForegroundServiceManager(getApplication());
mNotification = new NotificationContentProviderImpl(getApplication());
NavigationApi.clearForegroundServiceManager();
NavigationApi.initForegroundServiceManagerProvider(getApplication(), null, mNotification);
Avertissements et projets
- Veillez à appeler
initForegroundServiceManagerMessageAndIntent()ouinitForegroundServiceManagerProvider()tôt afin que le scénario d'utilisation attendu soit bien défini. Vous devez appeler cette méthode avant de créer un navigateur. - Veillez à intercepter les exceptions des appels à
initForegroundServiceManagerMessageAndIntent()ouinitForegroundServiceManagerProvider()au cas où le chemin de code serait saisi plus d'une fois. Dans le SDK Navigation v2.0, l'appel de cette méthode plusieurs fois génère une exception vérifiée plutôt qu'une exception d'exécution. - Google devra peut-être encore travailler pour obtenir un style cohérent tout au long de la durée de vie de la notification qui correspond au style de l'en-tête.
- Lorsque vous définissez un fournisseur de notifications, vous pouvez contrôler le comportement de l'affichage en tête avec la priorité.
- Google ne fournit pas de moyen simple de récupérer les informations détaillées qu'un fournisseur de notifications peut insérer dans la notification.