Benachrichtigungen auf Mobilgeräten zusammenfassen

Ab Android API-Ebene 26 sind persistente Benachrichtigungen für Dienste im Vordergrund erforderlich. Mit dieser Anforderung soll verhindert werden, dass Sie Dienste ausblenden, die die Systemressourcen übermäßig beanspruchen, insbesondere den Akku. Diese Anforderung birgt ein potenzielles Problem: Wenn eine App mit mehreren Diensten im Vordergrund die Benachrichtigung nicht sorgfältig so verwaltet, dass sie für alle Dienste freigegeben wird, kann es zu mehreren dauerhaften, nicht wegzuwischenden Benachrichtigungen kommen, was zu unerwünschtem Durcheinander in der aktiven Liste der Benachrichtigungen führt.

Dieses Problem wird noch schwieriger, wenn Sie SDKs wie das Navigations-SDK verwenden, mit dem Dienste im Vordergrund unabhängig von der App ausgeführt werden, die eigene unabhängige persistente Benachrichtigungen haben, was eine Zusammenführung erschwert. Um diese Probleme zu beheben, wurde im Navigation SDK v1.11 eine einfache API eingeführt, mit der sich persistente Benachrichtigungen in der App, einschließlich des SDK, verwalten lassen.

Dauerhafte Benachrichtigungen zusammenführen

Komponenten

Der Dienstmanager im Vordergrund stellt einen Wrapper für die Android-Klasse für Dienste im Vordergrund und die Klasse für persistente Benachrichtigungen bereit. Die Hauptfunktion dieses Wrappers besteht darin, die Wiederverwendung der Benachrichtigungs-ID zu erzwingen, damit die Benachrichtigung für alle Dienste im Vordergrund freigegeben wird, die den Manager verwenden.


Das Navigation SDK enthält statische Methoden zum Initialisieren und Abrufen des ForegroundServiceManager-Singletons. Dieses Singleton kann nur einmal während der Lebensdauer des Navigation SDK initialisiert werden. Wenn Sie also einen der Initialisierungsaufrufe (initForegroundServiceManagerMessageAndIntent() oder initForegroundServiceManagerProvider()) verwenden, sollten Sie ihn in einen Try-Catch-Block einschließen, für den Fall, dass dieser Pfad noch einmal eingegeben wird. Das Navigations-SDK wirft eine Laufzeitausnahme, wenn Sie eine der beiden Methoden mehrmals aufrufen, es sei denn, Sie löschen zuerst alle Verweise auf die ForegroundServiceManager und rufen vor jedem nachfolgenden Aufruf clearForegroundServiceManager() auf.

Die vier Parameter von initForegroundServiceManagerMessageAndIntent() sind application, notificationId, defaultMessage und resumeIntent. Wenn die letzten drei Parameter null sind, handelt es sich bei der Benachrichtigung um die Standardbenachrichtigung des Navigation SDK. Es ist weiterhin möglich, andere Dienste im Vordergrund der App hinter dieser Benachrichtigung auszublenden. Mit dem Parameter notificationId wird die Benachrichtigungs-ID angegeben, die für die Benachrichtigung verwendet werden soll. Ist der Wert „null“, wird ein beliebiger Wert verwendet. Sie können sie explizit festlegen, um Konflikte mit anderen Benachrichtigungen zu vermeiden, z. B. solche von einem anderen SDK. defaultMessage ist ein String, der angezeigt wird, wenn das System nicht navigiert. resumeIntent ist ein Intent, der ausgelöst wird, wenn auf die Benachrichtigung geklickt wird. Wenn resumeIntent null ist, werden Klicks auf die Benachrichtigung ignoriert.

Die drei Parameter von initForegroundServiceManagerProvider() sind application, notificationId und notificationProvider. Wenn die letzten beiden Parameter null sind, handelt es sich bei der Benachrichtigung um die Standardbenachrichtigung des Navigation SDK. Mit dem Parameter notificationId wird die Benachrichtigungs-ID angegeben, die für die Benachrichtigung verwendet werden soll. Wenn er null ist, wird ein beliebiger Wert verwendet. Sie können sie explizit festlegen, um Konflikte mit anderen Benachrichtigungen zu vermeiden, z. B. mit denen eines anderen SDKs. Wenn die notificationProvider festgelegt ist, ist der Anbieter immer für die Generierung der zu rendernden Benachrichtigung verantwortlich.

Die getForegroundServiceManager()-Methode des Navigation SDK gibt das Singleton des Dienstmanagers im Vordergrund zurück. Wenn Sie noch keinen generiert haben, entspricht das dem Aufruf von initForegroundServiceManagerMessageAndIntent() mit Nullparametern für notificationId, defaultMessage und resumeIntent.

Die ForegroundServiceManager hat drei einfache Methoden. Die ersten beiden dienen dazu, einen Dienst in den Vordergrund und wieder heraus zu verschieben. Sie werden in der Regel innerhalb des erstellten Dienstes aufgerufen. So wird sichergestellt, dass die Dienste mit der freigegebenen dauerhaften Benachrichtigung verknüpft sind. Die letzte Methode, updateNotification(), weist den Manager darauf hin, dass sich die Benachrichtigung geändert hat und neu gerendert werden muss.

Wenn Sie die freigegebene persistente Benachrichtigung vollständig steuern möchten, bietet die API eine NotificationContentProvider-Schnittstelle zum Definieren eines Benachrichtigungsanbieters, die eine einzelne Methode zum Abrufen einer Benachrichtigung mit dem aktuellen Inhalt enthält. Außerdem wird eine Basisklasse bereitgestellt, die Sie optional zum Definieren des Anbieters verwenden können. Einer der Hauptzwecke der Basisklasse besteht darin, dass sie eine Möglichkeit bietet, updateNotification() aufzurufen, ohne auf ForegroundServiceManager zugreifen zu müssen. Wenn Sie eine Instanz des Benachrichtigungsanbieters verwenden, um neue Benachrichtigungsnachrichten zu erhalten, können Sie diese interne Methode direkt aufrufen, um die Nachricht in der Benachrichtigung zu rendern.

Nutzungsszenarien

In diesem Abschnitt werden die Anwendungsfälle für freigegebene persistente Benachrichtigungen beschrieben.

Dauerhafte Benachrichtigungen anderer App-Dienste im Vordergrund ausblenden
Das einfachste Szenario ist es, das aktuelle Verhalten beizubehalten und die dauerhafte Benachrichtigung nur zum Rendern von Navigation SDK-Informationen zu verwenden. Andere Dienste können sich hinter dieser Benachrichtigung verstecken, indem sie die Methoden startForeground() und stopForeground() des Dienstmanagers für Dienste im Vordergrund verwenden.
Dauerhafte Benachrichtigungen anderer App-Dienste im Vordergrund ausblenden, aber Standardtext festlegen, der angezeigt wird, wenn nicht navigiert wird
Das zweitleichteste Szenario besteht darin, das aktuelle Verhalten beizubehalten und die dauerhafte Benachrichtigung nur zum Rendern von Navigation SDK-Informationen zu verwenden, es sei denn, das System führt keine Navigation durch. Wenn das System nicht navigiert, wird der für initForegroundServiceManagerMessageAndIntent() angegebene String angezeigt, nicht der Standardstring des Navigation SDK, der „Google Maps“ enthält. Mit diesem Aufruf können Sie auch die Wiedergabeabsicht festlegen, die ausgelöst wird, wenn auf die Benachrichtigung geklickt wird.
Vollständige Kontrolle über das Rendern der dauerhaften Benachrichtigung
Im letzten Szenario müssen Sie einen Benachrichtigungsanbieter definieren und erstellen und ihn mit initForegroundServiceManagerProvider() an die ForegroundServiceManager übergeben. Mit dieser Option haben Sie die volle Kontrolle darüber, was in der Benachrichtigung gerendert wird. Die Benachrichtigungsinformationen des Navigation SDK werden jedoch von der Benachrichtigung getrennt, wodurch die hilfreichen Schritt-für-Schritt-Hinweise entfernt werden. Google bietet keine einfache Möglichkeit, diese Informationen abzurufen und in die Benachrichtigung einzufügen.

Beispiel für einen Benachrichtigungsanbieter

Das folgende Codebeispiel zeigt, wie Benachrichtigungen mit einem einfachen Benachrichtigungsinhaltsanbieter erstellt und zurückgegeben werden.

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

Nachdem Sie NotificationContentProviderImpl erstellt haben, stellen Sie mit dem folgenden Code eine Verbindung zum Navigation SDK her:

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

Einschränkungen und zukünftige Pläne

  • Rufe initForegroundServiceManagerMessageAndIntent() oder initForegroundServiceManagerProvider() frühzeitig auf, damit das erwartete Nutzungsszenario klar definiert ist. Sie müssen diese Methode aufrufen, bevor Sie einen neuen Navigator erstellen.
  • Achten Sie darauf, Ausnahmen von Aufrufen von initForegroundServiceManagerMessageAndIntent() oder initForegroundServiceManagerProvider() zu erfassen, falls der Codepfad mehrmals eingegeben wird. Im Navigation SDK v2.0 wird beim mehrmaligen Aufrufen dieser Methode eine geprüfte Ausnahme statt einer Laufzeitausnahme ausgelöst.
  • Google muss möglicherweise noch daran arbeiten, ein einheitliches Design für die gesamte Dauer der Benachrichtigung zu erreichen, das dem Header-Design entspricht.
  • Wenn Sie einen Benachrichtigungsanbieter definieren, können Sie das Verhalten von Push-Benachrichtigungen mit der Priorität steuern.
  • Google bietet keine einfache Möglichkeit zum Abrufen von detaillierten Wegbeschreibungen, die ein Benachrichtigungsanbieter in die Benachrichtigung einfügen könnte.