Raggruppa notifiche mobile

A partire dal livello API Android 26, sono necessarie notifiche permanenti per i servizi in primo piano. Questo requisito ha lo scopo di evitare di nascondere i servizi che potrebbero richiedere troppe risorse di sistema, in particolare la batteria. Questo requisito crea un potenziale problema: se un'app con più servizi in primo piano non gestisce attentamente la notifica in modo che sia condivisa tra tutti i servizi, potrebbero esserci più notifiche persistenti non ignorabili, che causano disordine non gradito nell'elenco attivo delle notifiche.

Questo problema diventa più difficile quando utilizzi SDK come l'SDK di navigazione, che eseguono servizi in primo piano indipendenti dall'app con notifiche permanenti indipendenti, rendendole difficile il consolidamento. Per risolvere questi problemi, l'SDK Navigation v1.11 ha introdotto una semplice API per gestire le notifiche persistenti in tutta l'app, anche all'interno dell'SDK.

Consolidare le notifiche persistenti

Componenti

Il gestore del servizio in primo piano fornisce un wrapper intorno alla classe del servizio in primo piano Android e alla classe di notifica permanente. La funzione principale di questo wrapper è l'applicazione forzata del riutilizzo dell'ID notifica in modo che la notifica venga condivisa tra tutti i servizi in primo piano che utilizzano il gestore.


L'SDK di navigazione contiene metodi statici per l'inizializzazione e il recupero del singleton ForegroundServiceManager. Questo singleton può essere inizializzato solo una volta durante il ciclo di vita dell'SDK di navigazione. Di conseguenza, se usi una delle chiamate di inizializzazione (initForegroundServiceManagerMessageAndIntent() o initForegroundServiceManagerProvider()), dovresti racchiuderla in un blocco proof-catch nel caso in cui il percorso venga reinserito. L'SDK di navigazione genera un'eccezione di runtime se chiami uno dei due metodi più di una volta, a meno che tu non cancelli tutti i riferimenti a ForegroundServiceManager e chiami clearForegroundServiceManager() prima di ogni chiamata successiva.

I quattro parametri di initForegroundServiceManagerMessageAndIntent() sono application, notificationId, defaultMessage e resumeIntent. Se gli ultimi tre parametri sono nulli, la notifica è la notifica standard dell'SDK di navigazione. È comunque possibile nascondere altri servizi in primo piano nell'app dietro questa notifica. Il parametro notificationId specifica l'ID notifica da utilizzare per la notifica. Se è nullo, viene utilizzato un valore arbitrario. Puoi configurarla in modo esplicito per risolvere i conflitti con altre notifiche, ad esempio quelle di un altro SDK. defaultMessage è una stringa che viene visualizzata quando il sistema non sta navigando. resumeIntent è un intent che viene attivato quando si fa clic sulla notifica. Se resumeIntent è nullo, i clic sulla notifica vengono ignorati.

I tre parametri di initForegroundServiceManagerProvider() sono application, notificationId e notificationProvider. Se gli ultimi due parametri sono nulli, la notifica è la notifica standard dell'SDK di navigazione. Il parametro notificationId specifica l'ID notifica da utilizzare per la notifica. Se è null, viene utilizzato un valore arbitrario. Puoi impostarlo in modo esplicito in modo da aggirare i conflitti con altre notifiche, come quelle di un altro SDK. Se il criterio notificationProvider è impostato, il provider è sempre responsabile di generare la notifica da visualizzare.

Il metodo getForegroundServiceManager() dell'SDK Navigazione restituisce il singleton del gestore del servizio in primo piano. Se non ne hai ancora generato uno, equivale a chiamare initForegroundServiceManagerMessageAndIntent() con parametri nulli per notificationId, defaultMessage e resumeIntent.

ForegroundServiceManager ha tre semplici metodi. I primi due consentono di spostare un servizio da e verso il primo piano e vengono generalmente chiamati dall'interno del servizio creato. L'uso di questi metodi garantisce che i servizi siano associati alla notifica permanente condivisa. Il metodo finale, updateNotification(), segnala al gestore che la notifica è cambiata e deve essere sottoposta di nuovo al rendering.

Se hai bisogno del controllo completo della notifica persistente condivisa, l'API fornisce un'interfaccia NotificationContentProvider per definire un provider di notifiche, che contiene un unico metodo per ricevere una notifica con i contenuti correnti. Fornisce inoltre una classe base, che puoi usare facoltativamente per definire il provider. Uno degli scopi principali della classe base è che fornisce un modo per chiamare updateNotification() senza la necessità di accedere a ForegroundServiceManager. Se utilizzi un'istanza del provider delle notifiche per ricevere i nuovi messaggi di notifica, puoi chiamare questo metodo interno direttamente per eseguire il rendering del messaggio nella notifica.

Scenari di utilizzo

Questa sezione descrive in dettaglio gli scenari di utilizzo per l'utilizzo delle notifiche permanenti condivise.

Nascondi notifiche permanenti di altri servizi in primo piano delle app
Lo scenario più semplice è preservare il comportamento attuale e utilizzare solo la notifica persistente per visualizzare le informazioni dell'SDK di navigazione. Altri servizi possono nascondersi dietro questa notifica utilizzando i metodi di gestore del servizio in primo piano startForeground() e stopForeground().
Nascondi notifiche permanenti di altri servizi delle app in primo piano, ma imposta il testo predefinito mostrato quando non navighi
Il secondo scenario più semplice consiste nel preservare il comportamento attuale e utilizzare la notifica persistente solo per visualizzare le informazioni dell'SDK di navigazione, tranne quando il sistema non è in modalità di navigazione. Quando il sistema non naviga, viene visualizzata la stringa fornita a initForegroundServiceManagerMessageAndIntent() anziché la stringa predefinita dell'SDK di navigazione che indica "Google Maps". Puoi anche utilizzare questa chiamata per impostare l'intent che si attiva quando si fa clic sulla notifica.
Assumi il pieno controllo del rendering della notifica persistente
Lo scenario finale richiede la definizione e la creazione di un provider di notifiche e il suo trasferimento a ForegroundServiceManager utilizzando initForegroundServiceManagerProvider(). Questa opzione ti offre il pieno controllo di ciò che viene visualizzato nella notifica, ma disconnette anche le informazioni di notifica dell'SDK di navigazione dalla notifica, rimuovendo così gli utili prompt passo passo mostrati nella notifica. Google non fornisce un metodo semplice per recuperare queste informazioni e inserirle nella notifica.

Esempio di fornitore di notifiche

L'esempio di codice seguente mostra come creare e restituire notifiche utilizzando un semplice fornitore di contenuti delle notifiche.

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 "";
   }
 }
}

Dopo aver creato NotificationContentProviderImpl, gli colleghi l'SDK di navigazione utilizzando il seguente codice:

ForegroundServiceManager f = NavigationApi.getForegroundServiceManager(getApplication());
mNotification = new NotificationContentProviderImpl(getApplication());
NavigationApi.clearForegroundServiceManager();
NavigationApi.initForegroundServiceManagerProvider(getApplication(), null, mNotification);

Precisazioni e piani futuri

  • Assicurati di chiamare initForegroundServiceManagerMessageAndIntent() o initForegroundServiceManagerProvider() in anticipo, in modo da definire bene lo scenario di utilizzo previsto. Devi chiamare questo metodo prima di creare un nuovo navigatore.
  • Assicurati di rilevare le eccezioni dalle chiamate a initForegroundServiceManagerMessageAndIntent() o initForegroundServiceManagerProvider() nel caso in cui il percorso di codice venga inserito più di una volta. In Navigation SDK v2.0, se chiami questo metodo più volte, viene generata un'eccezione selezionata anziché un'eccezione di runtime.
  • Google potrebbe avere ancora del lavoro da fare per ottenere uno stile coerente per tutta la durata della notifica in base allo stile dell'intestazione.
  • Quando definisci un fornitore di notifiche, puoi controllare il comportamento delle notifiche in base alla priorità.
  • Google non fornisce un mezzo semplice per recuperare informazioni passo passo che un fornitore di notifiche potrebbe inserire nella notifica.