Skonsoliduj powiadomienia na urządzeniach mobilnych

Od poziomu 26 interfejsu Android API w przypadku usług działających na pierwszym planie wymagane są trwałe powiadomienia. To wymaganie ma zapobiec ukryciu usług, które mogłyby spowodować nadmierne obciążenie zasobów systemowych, w tym baterii. To wymaganie tworzy potencjalny problem: jeśli aplikacja z wieloma usługami na pierwszym planie nie zarządza odpowiednio powiadomieniem w taki sposób, aby było udostępniane wszystkim usługom, wtedy może pojawić się wiele trwałych powiadomień, których nie można odrzucić, co prowadzi do powstawania niepotrzebnych powiadomień na aktywnej liście powiadomień.

Ten problem staje się trudniejszy, gdy używasz pakietów SDK takich jak pakiet SDK nawigacji, które działają na pierwszym planie niezależnie od aplikacji mających własne, niezależne powiadomienia trwałe, co utrudnia ich konsolidację. Aby rozwiązać te problemy, w pakiecie SDK nawigacji w wersji 1.11 wprowadziliśmy prosty interfejs API, który ułatwia zarządzanie stałymi powiadomieniami w aplikacji, w tym w pakiecie SDK.

Skonsoliduj trwałe powiadomienia

Komponenty

Menedżer usługi na pierwszym planie zapewnia otokę wokół klasy usługi działającej na pierwszym planie w Androidzie i klasy trwałego powiadomienia. Główna funkcja tego kodu polega na wymuszaniu ponownego użycia identyfikatora powiadomienia, aby powiadomienie było udostępniane wszystkim usługom na pierwszym planie za pomocą menedżera.


Pakiet SDK nawigacji zawiera metody statyczne do inicjowania i pobierania singletonu ForegroundServiceManager. Ten singleton można zainicjować tylko raz w cyklu życia pakietu Navigation SDK. Jeśli używasz jednego z wywołań inicjujących (initForegroundServiceManagerMessageAndIntent() lub initForegroundServiceManagerProvider()), musisz je otaczać blokiem typu try-catch na wypadek ponownego wpisania ścieżki. Pakiet SDK nawigacji zgłosi wyjątek środowiska wykonawczego, jeśli wywołasz którąś z tych metod więcej niż raz, chyba że najpierw usuniesz wszystkie odwołania do funkcji ForegroundServiceManager i wywołasz metodę clearForegroundServiceManager() przed każdym kolejnym wywołaniem.

Cztery parametry właściwości initForegroundServiceManagerMessageAndIntent() to application, notificationId, defaultMessage i resumeIntent. Jeśli ostatnie 3 parametry mają wartość null, powiadomienie jest standardowym powiadomieniem z pakietu nawigacyjnego SDK. Za tym powiadomieniem nadal możesz ukryć inne usługi działające na pierwszym planie w aplikacji. Parametr notificationId określa identyfikator powiadomienia, którego należy używać w przypadku danego powiadomienia. Jeśli ma wartość null, używana jest dowolna wartość. Możesz skonfigurować ją tak, aby pomijała konflikty z innymi powiadomieniami, np. z innego pakietu SDK. defaultMessage to ciąg znaków wyświetlany, gdy system nie korzysta z nawigacji. Intencja resumeIntent jest uruchamiana po kliknięciu powiadomienia. Jeśli resumeIntent ma wartość null, kliknięcia powiadomienia są ignorowane.

Trzy parametry właściwości initForegroundServiceManagerProvider() to application, notificationId i notificationProvider. Jeśli dwa ostatnie parametry mają wartość null, powiadomienie jest standardowym powiadomieniem SDK nawigacji. Parametr notificationId określa identyfikator powiadomienia, którego należy używać w przypadku danego powiadomienia. Jeśli ma wartość null, używana jest dowolna wartość. Możesz wyraźnie ustawić ją tak, aby omijała konflikty z innymi powiadomieniami, np. z innego pakietu SDK. Jeśli ustawiono notificationProvider, dostawca zawsze odpowiada za wygenerowanie powiadomienia, które ma zostać wyrenderowane.

Metoda getForegroundServiceManager() pakietu Navigation SDK zwraca singleton menedżera usługi na pierwszym planie. Jeśli nie został jeszcze wygenerowany, jest to odpowiednik wywołania initForegroundServiceManagerMessageAndIntent() z parametrami null dla notificationId, defaultMessage i resumeIntent.

ForegroundServiceManager ma 3 proste metody. Pierwsze dwa służą do przenoszenia usługi na pierwszy plan i z niej. Zwykle są wywoływane z poziomu utworzonej usługi. Użycie tych metod daje pewność, że usługi są powiązane z udostępnionym trwałym powiadomieniem. Ostatnia metoda (updateNotification()) informuje menedżera, że powiadomienie się zmieniło, i należy je ponownie wyrenderować.

Jeśli potrzebujesz pełnej kontroli nad współdzielonym trwałym powiadomieniem, interfejs API udostępnia interfejs NotificationContentProvider do definiowania dostawcy powiadomień, który udostępnia jedną metodę otrzymywania powiadomień o bieżącej treści. Zapewnia też klasę bazową, której możesz opcjonalnie użyć do zdefiniowania dostawcy. Jednym z głównych celów klasy podstawowej jest to, że umożliwia ona wywoływanie funkcji updateNotification() bez konieczności uzyskiwania dostępu do klasy ForegroundServiceManager. Jeśli do odbierania nowych powiadomień używasz instancji dostawcy powiadomień, możesz wywołać tę metodę wewnętrzną bezpośrednio, aby wyrenderować wiadomość w powiadomieniu.

Scenariusze użycia

W tej sekcji szczegółowo opisujemy scenariusze użycia dotyczące używania udostępnionych stałych powiadomień.

Ukryj stałe powiadomienia o innych usługach działających na pierwszym planie aplikacji
Najprostszym sposobem jest zachowanie aktualnego działania i wykorzystanie tylko trwałego powiadomienia do renderowania informacji z pakietu Navigation SDK. Inne usługi mogą ukrywać się za tym powiadomieniem, używając metod startForeground() i stopForeground() menedżera usługi na pierwszym planie.
Ukryj stałe powiadomienia o innych usługach działających na pierwszym planie, ale ustaw domyślny tekst wyświetlany, gdy nie korzystasz z nawigacji
Drugi najprostszy scenariusz to zachowanie aktualnego działania i korzystanie tylko z trwałego powiadomienia do renderowania informacji z pakietu Navigation SDK, z wyjątkiem sytuacji, gdy system nie korzysta z nawigacji. Gdy system nie korzysta z nawigacji, wyświetlany jest ciąg znaków podany w elemencie initForegroundServiceManagerMessageAndIntent() zamiast domyślnego ciągu tekstowego pakietu Navigation SDK zawierającego wzmianki o „Mapach Google”. Możesz też użyć tego wywołania, aby ustawić intencję wznawiania, która uruchamia się po kliknięciu powiadomienia.
Przejmij pełną kontrolę nad renderowaniem stałego powiadomienia
Ostatni scenariusz wymaga zdefiniowania i utworzenia dostawcy powiadomień oraz przekazania go do ForegroundServiceManager za pomocą initForegroundServiceManagerProvider(). Ta opcja daje Ci pełną kontrolę nad tym, co jest wyświetlane w powiadomieniu, ale odłącza od powiadomienia informacje pochodzące z pakietu Navigation SDK, usuwając w ten sposób przydatne szczegółowe wskazówki. Google nie zapewnia prostego sposobu na pobranie tych informacji i umieszczenie ich w powiadomieniu.

Przykładowy dostawca powiadomień

Poniższy przykładowy kod pokazuje, jak tworzyć i zwracać powiadomienia przy użyciu prostego dostawcy treści powiadomień.

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

Po utworzeniu pliku NotificationContentProviderImpl połącz z nim pakiet SDK nawigacji za pomocą tego kodu:

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

Zastrzeżenia i przyszłe plany

  • Pamiętaj o wywołaniu funkcji initForegroundServiceManagerMessageAndIntent() lub initForegroundServiceManagerProvider() wcześniej, aby poprawnie określić oczekiwany scenariusz użycia. Musisz wywołać tę metodę przed utworzeniem nowego nawigatora.
  • Zwróć uwagę na wyjątki od wywołań funkcji initForegroundServiceManagerMessageAndIntent() lub initForegroundServiceManagerProvider() na wypadek, gdyby ścieżka kodu została wpisana więcej niż raz. W pakiecie Navigation SDK w wersji 2.0 wielokrotne wywołanie tej metody powoduje zgłoszenie zaznaczonego wyjątku, a nie wyjątku środowiska wykonawczego.
  • Być może Google musi jeszcze coś zrobić, aby uzyskać spójny styl przez cały okres istnienia powiadomienia, który pasuje do stylu nagłówka.
  • Po zdefiniowaniu dostawcy powiadomień możesz za pomocą priorytetu kontrolować działanie powiadomień z wyprzedzeniem.
  • Google nie zapewnia prostego sposobu pobierania szczegółowych informacji, które dostawca powiadomień może wstawić do powiadomienia.