Raggruppa notifiche mobile

A partire dal livello API 26 di Android, sono necessarie notifiche persistenti per i servizi in primo piano. Questo requisito ha lo scopo di impedire di nascondere servizi che potrebbero richiedere un uso eccessivo delle risorse di sistema, in particolare della 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, possono esserci più notifiche persistenti che non possono essere chiuse, il che porta a un disordine indesiderato nell'elenco attivo di notifiche.

Questo problema diventa più difficile quando utilizzi SDK come l'SDK Navigation, che esegue servizi in primo piano indipendenti dall'app che hanno notifiche persistenti indipendenti, rendendoli difficili da consolidare. Per risolvere questi problemi, la versione 1.11 dell'SDK Navigation ha introdotto una semplice API per gestire le notifiche persistenti nell'app, anche all'interno dell'SDK.

Consolidare le notifiche persistenti

Componenti

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


L'SDK Navigation contiene metodi statici per inizializzare e ottenere il singleton ForegroundServiceManager. Questo singleton può essere inizializzato una sola volta durante il ciclo di vita dell'SDK Navigation. Di conseguenza, se utilizzi una delle chiamate di inizializzazione (initForegroundServiceManagerMessageAndIntent() o initForegroundServiceManagerProvider()), devi racchiuderla in un blocco try-catch nel caso in cui il percorso venga reinserito. L'SDK Navigation genera un'eccezione di runtime se chiami uno dei due metodi più di una volta, a meno che non cancelli prima 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 Navigation. È 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 è null, viene utilizzato un valore arbitrario. Puoi impostarlo in modo esplicito per evitare conflitti con altre notifiche, ad esempio quelle di un altro SDK. defaultMessage è una stringa visualizzata quando il sistema non è in navigazione. resumeIntent è un intent che viene attivato quando viene fatto clic sulla notifica. Se resumeIntent è null, 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 è quella standard dell'SDK Navigation. Il parametro notificationId specifica l'ID notifica da utilizzare per la notifica. Se è null, viene utilizzato un valore arbitrario. Puoi impostarlo in modo esplicito per risolvere i conflitti con altre notifiche, ad esempio quelle di un altro SDK. Se notificationProvider è impostato, il fornitore è sempre responsabile della generazione della notifica da visualizzare.

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

Il ForegroundServiceManager ha tre metodi semplici. I primi due servono per spostare un servizio in primo piano e fuori dal primo piano e vengono in genere chiamati all'interno del servizio creato. L'utilizzo di questi metodi garantisce che i servizi siano associati alla notifica persistente condivisa. Il metodo finale, updateNotification(), segnala all'amministratore che la notifica è cambiata e deve essere eseguita di nuovo.

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 singolo metodo per ottenere una notifica con i contenuti attuali. Fornisce anche una classe base, che puoi utilizzare facoltativamente per definire il provider. Uno degli scopi principali della classe base è fornire un modo per chiamare updateNotification() senza la necessità di accedere a ForegroundServiceManager. Se utilizzi un'istanza del provider di notifiche per ricevere 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 delle notifiche persistenti condivise.

Nascondere le notifiche persistenti di altri servizi in primo piano dell'app
Lo scenario più semplice è preservare il comportamento attuale e utilizzare la notifica persistente solo per il rendering delle informazioni dell'SDK Navigation. Altri servizi possono nascondersi dietro questa notifica utilizzando i metodi del gestore dei servizi in primo piano startForeground() e stopForeground().
Nascondi le notifiche persistenti di altri servizi in primo piano dell'app, ma imposta il testo predefinito mostrato quando non si naviga
Il secondo scenario più semplice è conservare il comportamento attuale e utilizzare la notifica persistente solo per il rendering delle informazioni dell'SDK Navigation, tranne quando il sistema non è in navigazione. Quando il sistema non è in navigazione, viene visualizzata la stringa fornita a initForegroundServiceManagerMessageAndIntent() anziché la stringa predefinita dell'SDK Navigation che menziona "Google Maps". Puoi anche utilizzare questa chiamata per impostare l'intent di ripresa che viene attivato quando viene fatto clic sulla notifica.
Controllare completamente il rendering della notifica persistente
Lo scenario finale richiede la definizione e la creazione di un fornitore di notifiche e il suo passaggio a ForegroundServiceManager utilizzando initForegroundServiceManagerProvider(). Questa opzione ti offre il pieno controllo di ciò che viene visualizzato nella notifica, ma scollega anche le informazioni di notifica dell'SDK Navigation dalla notifica, rimuovendo così le utili indicazioni passo passo mostrate nella notifica. Google non fornisce un modo semplice per recuperare queste informazioni e inserirle nella notifica.

Fornitore di notifiche di esempio

Il seguente esempio di codice mostra come creare e restituire notifiche utilizzando un semplice content provider di 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, connetti l'SDK Navigation utilizzando il seguente codice:

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

Avvertenze e piani futuri

  • Assicurati di chiamare initForegroundServiceManagerMessageAndIntent() o initForegroundServiceManagerProvider() in anticipo in modo che lo scenario di utilizzo previsto sia ben definito. Devi chiamare questo metodo prima di creare un nuovo Navigator.
  • Assicurati di rilevare le eccezioni dalle chiamate a initForegroundServiceManagerMessageAndIntent() o initForegroundServiceManagerProvider() nel caso in cui il percorso del codice venga inserito più di una volta. Nell'SDK Navigation v2.0, la chiamata a questo metodo più volte genera un'eccezione controllata anziché un'eccezione di runtime.
  • Google potrebbe dover ancora lavorare per ottenere uno stile coerente per l'intera durata della notifica che corrisponda allo stile dell'intestazione.
  • Quando definisci un fornitore di notifiche, puoi controllare il comportamento di avviso con la priorità.
  • Google non fornisce un mezzo semplice per recuperare le informazioni strada per strada che un fornitore di notifiche potrebbe inserire nella notifica.