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 ausblenden, die möglicherweise übermäßige Anforderungen an Systemressourcen stellen, insbesondere an den Akku. Diese Anforderung birgt ein potenzielles Problem: Wenn eine App mit mehreren Vordergrunddiensten die Benachrichtigung nicht sorgfältig verwaltet, sodass sie für alle Dienste freigegeben ist, kann es zu mehreren persistenten, nicht schließbaren Benachrichtigungen kommen, was zu unerwünschten Unordnung in der aktiven Liste der Benachrichtigungen führt.

Dieses Problem wird noch schwieriger, wenn Sie SDKs wie das Navigation SDK verwenden, die Dienste im Vordergrund unabhängig von der App ausführen und eigene unabhängige dauerhafte Benachrichtigungen haben, die sich nur schwer konsolidieren lassen. Um diese Probleme zu beheben, wurde im Navigation SDK v1.11 eine einfache API eingeführt, mit der sich dauerhafte Benachrichtigungen in der gesamten App, einschließlich des SDK, verwalten lassen.

Dauerhafte Benachrichtigungen zusammenfassen

Komponenten

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


Das Navigation SDK enthält statische Methoden zum Initialisieren und Abrufen des ForegroundServiceManager-Singleton. Dieses Singleton kann nur einmal während der Lebensdauer des Navigation SDK initialisiert werden. Wenn Sie einen der Initialisierungsaufrufe (initForegroundServiceManagerMessageAndIntent() oder initForegroundServiceManagerProvider()) verwenden, sollten Sie ihn daher mit einem try-catch-Block umgeben, falls dieser Pfad noch einmal aufgerufen wird. Das Navigation SDK löst eine Laufzeit-Ausnahme aus, wenn Sie eine der beiden Methoden mehr als einmal aufrufen, es sei denn, Sie löschen zuerst alle Verweise auf ForegroundServiceManager und rufen clearForegroundServiceManager() vor jedem nachfolgenden Aufruf 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 Vordergrunddienste in der App hinter dieser Benachrichtigung zu verbergen. 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 es explizit festlegen, um Konflikte mit anderen Benachrichtigungen, z. B. von einem anderen SDK, zu vermeiden. defaultMessage ist ein String, der angezeigt wird, wenn das System nicht navigiert. 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, 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 Benachrichtigungen aus einem anderen SDK. Wenn notificationProvider festgelegt ist, ist der Anbieter immer für die Generierung der Benachrichtigung verantwortlich, die gerendert werden soll.

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

Die ForegroundServiceManager bietet drei einfache Methoden. Die ersten beiden dienen dazu, einen Dienst in den Vordergrund und aus dem Vordergrund zu verschieben. Sie werden in der Regel vom Dienst aufgerufen, der erstellt wurde. Durch die Verwendung dieser Methoden wird sichergestellt, dass die Dienste mit der gemeinsamen persistenten Benachrichtigung verknüpft sind. Die letzte Methode, updateNotification(), weist den Manager darauf hin, dass sich die Benachrichtigung geändert hat und neu gerendert werden sollte.

Wenn Sie die vollständige Kontrolle über die gemeinsame dauerhafte Benachrichtigung benötigen, bietet die API eine NotificationContentProvider-Schnittstelle zum Definieren eines Benachrichtigungsanbieters, der eine einzelne Methode zum Abrufen einer Benachrichtigung mit dem aktuellen Inhalt enthält. Außerdem wird eine Basisklasse bereitgestellt, die Sie optional verwenden können, um den Anbieter zu definieren. Einer der Hauptzwecke der Basisklasse besteht darin, dass sie eine Möglichkeit bietet, updateNotification() aufzurufen, ohne auf die ForegroundServiceManager zugreifen zu müssen. Wenn Sie eine Instanz des Benachrichtigungsanbieters verwenden, um neue Benachrichtigungen zu empfangen, können Sie diese interne Methode direkt aufrufen, um die Nachricht in der Benachrichtigung zu rendern.

Anwendungsszenarien

In diesem Abschnitt werden die Anwendungsfälle für die Verwendung von freigegebenen persistenten Benachrichtigungen beschrieben.

Permanente Benachrichtigungen von anderen App-Vordergrunddiensten ausblenden
Am einfachsten ist es, das aktuelle Verhalten beizubehalten und die dauerhafte Benachrichtigung nur zum Rendern von Informationen aus dem Navigation SDK zu verwenden. Andere Dienste können sich hinter dieser Benachrichtigung verbergen, indem sie die Methoden startForeground() und stopForeground() des Dienstmanagers für Dienste im Vordergrund verwenden.
Dauerhafte Benachrichtigungen anderer Vordergrunddienste ausblenden, aber Standardtext festlegen, der angezeigt wird, wenn nicht navigiert wird
Im zweitbesten Fall wird das aktuelle Verhalten beibehalten und die dauerhafte Benachrichtigung nur zum Rendern von Navigation SDK-Informationen verwendet, es sei denn, das System navigiert nicht. Wenn das System nicht navigiert, wird der für initForegroundServiceManagerMessageAndIntent() bereitgestellte String anstelle des Standard-Navigation SDK-Strings angezeigt, in dem „Google Maps“ erwähnt wird. Mit diesem Aufruf können Sie auch die Resume-Absicht festlegen, die ausgelöst wird, wenn auf die Benachrichtigung geklickt wird.
Volle Kontrolle über das Rendern der dauerhaften Benachrichtigung
Im letzten Szenario muss ein Benachrichtigungsanbieter definiert und erstellt und mit initForegroundServiceManagerProvider() an ForegroundServiceManager übergeben werden. Mit dieser Option haben Sie die volle Kontrolle darüber, was in der Benachrichtigung gerendert wird. Allerdings werden dadurch auch die Benachrichtigungsinformationen des Navigation SDK von der Benachrichtigung getrennt, sodass die hilfreichen Hinweise zur detaillierten Routenführung in der Benachrichtigung nicht mehr angezeigt 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, verbinden Sie das Navigation SDK mit dem folgenden Code damit:

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

Einschränkungen und zukünftige Pläne

  • Rufen Sie initForegroundServiceManagerMessageAndIntent() oder initForegroundServiceManagerProvider() frühzeitig auf, damit das erwartete Nutzungsszenario gut definiert ist. Sie müssen diese Methode aufrufen, bevor Sie einen neuen Navigator erstellen.
  • Fangen Sie Ausnahmen von Aufrufen von initForegroundServiceManagerMessageAndIntent() oder initForegroundServiceManagerProvider() ab, falls der Codepfad mehr als einmal aufgerufen wird. Im Navigation SDK v2.0 wird beim mehrmaligen Aufrufen dieser Methode eine geprüfte Ausnahme anstelle einer Laufzeit-Ausnahme ausgelöst.
  • Google muss möglicherweise noch Anpassungen vornehmen, um das Styling der Benachrichtigung über ihren gesamten Lebenszyklus hinweg an das Styling des Headers anzugleichen.
  • Wenn Sie einen Benachrichtigungsanbieter definieren, können Sie das Verhalten von Kurzinfos mit der Priorität steuern.
  • Google bietet keine einfache Möglichkeit, detaillierte Informationen zur Routenführung abzurufen, die ein Benachrichtigungsanbieter in die Benachrichtigung einfügen könnte.