Benachrichtigungen auf Mobilgeräten zusammenfassen

Ab Android API-Level 26 sind dauerhafte Benachrichtigungen für Dienste im Vordergrund erforderlich. Diese Anforderung soll verhindern, dass Sie Dienste verstecken, die Systemressourcen, insbesondere den Akku, übermäßig beanspruchen könnten. Diese Anforderung führt zu einem potenziellen Problem: Wenn eine App mit mehreren Diensten im Vordergrund die Benachrichtigung nicht sorgfältig verwaltet, sodass sie für alle Dienste freigegeben wird, kann es mehrere dauerhafte, nicht schließbare Benachrichtigungen geben, was zu unerwünschten Überladen in der aktiven Liste der Benachrichtigungen führt.

Dieses Problem wird noch schwieriger, wenn Sie SDKs wie das Navigation SDK verwenden, bei denen Dienste im Vordergrund unabhängig von der App ausgeführt werden und die eigene, unabhängige persistente Benachrichtigungen haben, was deren Konsolidierung erschwert. Mit Version 1.11 des Navigation SDK wurde eine einfache API eingeführt, mit der sich persistente Benachrichtigungen in der gesamten App – auch im SDK – verwalten lassen.

Dauerhafte Benachrichtigungen konsolidieren

Komponenten

Der Manager für Dienste im Vordergrund bietet einen Wrapper um die Android-Dienstklasse im Vordergrund und die persistente Benachrichtigungsklasse. Die Hauptfunktion dieses Wrappers besteht darin, die Wiederverwendung der Benachrichtigungs-ID zu erzwingen, damit die Benachrichtigung über den Manager für alle Dienste im Vordergrund freigegeben wird.


Das Navigation SDK enthält statische Methoden zum Initialisieren und Abrufen des Singleton-ForegroundServiceManager. Dieser Singleton kann während der Lebensdauer des Navigation SDK nur einmal initialisiert werden. Wenn Sie einen der Initialisierungsaufrufe (initForegroundServiceManagerMessageAndIntent() oder initForegroundServiceManagerProvider()) verwenden, sollten Sie ihn in einen Versuchsblock einfügen, falls der Pfad noch einmal eingegeben wird. Das Navigation SDK löst eine Laufzeitausnahme aus, wenn Sie eine der beiden Methoden mehr als einmal aufrufen, es sei denn, Sie löschen zuerst alle Verweise auf 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, ist die Benachrichtigung die standardmäßige Navigation SDK-Benachrichtigung. Es ist weiterhin möglich, andere Dienste im Vordergrund in der App hinter dieser Benachrichtigung auszublenden. Der Parameter notificationId gibt die Benachrichtigungs-ID an, die für die Benachrichtigung verwendet werden soll. Wenn er null ist, wird ein beliebiger Wert verwendet. Sie können sie explizit so konfigurieren, dass Konflikte mit anderen Benachrichtigungen umgangen werden, z. B. Benachrichtigungen von einem anderen SDK. defaultMessage ist ein String, der angezeigt wird, wenn das System keine Navigation ausführt. Der 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, ist die Benachrichtigung die standardmäßige Navigation SDK-Benachrichtigung. Der Parameter notificationId gibt die Benachrichtigungs-ID an, die für die Benachrichtigung verwendet werden soll. Wenn dieser Wert null ist, wird ein beliebiger Wert verwendet. Sie können sie explizit festlegen, um Konflikte mit anderen Benachrichtigungen zu umgehen, z. B. mit denen von einem anderen SDK. Wenn notificationProvider festgelegt ist, ist der Anbieter immer dafür verantwortlich, die zu rendernde Benachrichtigung zu generieren.

Die getForegroundServiceManager()-Methode des Navigation SDK gibt den Dienstmanager im Vordergrund des Dienstes als Singleton zurück. Wenn Sie noch keine erstellt haben, entspricht dies dem Aufruf von initForegroundServiceManagerMessageAndIntent() mit Nullparametern für notificationId, defaultMessage und resumeIntent.

Für ForegroundServiceManager gibt es drei einfache Methoden. Die ersten beiden dienen zum Verschieben eines Dienstes in den Vordergrund und aus dem Vordergrund und werden normalerweise innerhalb des erstellten Dienstes aufgerufen. Mit diesen Methoden stellen Sie sicher, dass die Dienste der gemeinsamen persistenten Benachrichtigung zugeordnet sind. Bei der letzten Methode updateNotification() wird dem Manager gemeldet, dass sich die Benachrichtigung geändert hat, und er muss noch einmal gerendert werden.

Wenn Sie die vollständige Kontrolle über die gemeinsam genutzte persistente Benachrichtigung benötigen, 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 bietet sie eine Basisklasse, mit der Sie optional den Anbieter definieren 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 Nutzungsszenarien für die Verwendung gemeinsamer persistenter Benachrichtigungen beschrieben.

Dauerhafte Benachrichtigungen anderer App-Dienste im Vordergrund ausblenden
Das einfachste Szenario ist, das aktuelle Verhalten beizubehalten und nur die dauerhafte Benachrichtigung zum Rendern von Navigation SDK-Informationen zu verwenden. Mithilfe der Methoden startForeground() und stopForeground() des Dienstmanagers im Vordergrund können andere Dienste hinter dieser Benachrichtigung verborgen werden.
Dauerhafte Benachrichtigungen anderer Dienste im Vordergrund ausblenden, aber Standardtext festlegen, der angezeigt wird, wenn Sie nicht navigieren
Das zweiteinfachste Szenario ist, das aktuelle Verhalten beizubehalten und die dauerhafte Benachrichtigung nur zum Rendern von Navigation SDK-Informationen zu verwenden, es sei denn, das System ist gerade nicht aktiv. Wenn das System keine Navigation ausführt, wird der für initForegroundServiceManagerMessageAndIntent() bereitgestellte String anstelle des Standard-Navigation SDK-Strings angezeigt, in dem „Google Maps“ erwähnt wird. Sie können mit diesem Aufruf auch den Fortsetzungs-Intent festlegen, der ausgelöst wird, wenn auf die Benachrichtigung geklickt wird.
Vollständige Kontrolle über das Rendern dauerhafter Benachrichtigungen
Im letzten Szenario muss ein Benachrichtigungsanbieter definiert und erstellt und mithilfe von initForegroundServiceManagerProvider() an die ForegroundServiceManager übergeben werden. Bei dieser Option haben Sie die volle Kontrolle darüber, was in der Benachrichtigung gerendert wird. Es werden aber auch die Benachrichtigungsinformationen des Navigation SDK von der Benachrichtigung getrennt. Dadurch werden die nützlichen detaillierten Aufforderungen in der Benachrichtigung entfernt. 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 Anbieter von Benachrichtigungsinhalten 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, verbinden Sie das Navigation SDK mithilfe des folgenden Codes damit:

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

Vorbehalte und Zukunftspläne

  • Rufen Sie 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 bei Aufrufen von initForegroundServiceManagerMessageAndIntent() oder initForegroundServiceManagerProvider() zu erfassen, falls der Codepfad mehrmals eingegeben wird. Wenn im Navigation SDK v2.0 diese Methode mehrmals aufgerufen wird, wird eher eine geprüfte Ausnahme als eine Laufzeitausnahme ausgelöst.
  • Möglicherweise muss Google noch an einem einheitlichen Stil für die gesamte Lebensdauer der Benachrichtigung arbeiten, die dem Stil der Kopfzeile entspricht.
  • Wenn Sie einen Benachrichtigungsanbieter definieren, können Sie das Vorabverhalten mit der Priorität steuern.
  • Google bietet keine einfache Möglichkeit zum Abrufen von detaillierten Informationen, die ein Benachrichtigungsanbieter in die Benachrichtigung einfügen könnte.