Udostępnione trwałe powiadomienia

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 we wszystkich usługach, wtedy pojawia się wiele stale, których nie można zamknąć, 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 uruchamiają usługi działające na pierwszym planie niezależnie od aplikacji i mogą mieć 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.


Interfejs NavigationAPI 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 otoczyć je blokiem try-catch, na wypadek gdyby ta ścieżka została wprowadzona ponownie. Aby zapobiec problemom ze zgodnością, pakiet SDK nawigacji zgłasza wyjątek w czasie działania, jeśli wywołujesz którąś z tych metod więcej niż raz, chyba że najpierw usuniesz wszystkie odwołania do funkcji ForegroundServiceManager i przed każdym wywołaniem clearForegroundServiceManager() wywołasz. W tym celu w wersji 2.0 pakietu SDK nawigacji w wersji 2.0 do interfejsu API został dodany zaznaczony wyjątek.

Cztery parametry właściwości initForegroundServiceManagerMessageAndIntent() to application, notificationId, defaultMessage i resumeIntent. Jeśli ostatnie trzy parametry mają wartość null, powiadomienie jest standardowym powiadomieniem SDK nawigacji. Nadal możesz ukryć w aplikacji inne usługi działające na pierwszym planie. Parametr notificationId określa identyfikator powiadomienia, którego należy użyć w związku z powiadomieniem. Jeśli ma wartość null, używana jest dowolna wartość. Możesz skonfigurować tę opcję tak, aby omijał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żyć w związku z powiadomieniem. Jeśli ma wartość null, używana jest dowolna wartość. Możesz skonfigurować tę opcję 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 chcesz mieć pełną kontrolę nad zawartością udostępnianego stałego powiadomienia, nowy interfejs API udostępnia interfejs NotificationContentProvider do definiowania dostawcy powiadomień, który udostępnia jedną metodę otrzymywania powiadomień o bieżącej zawartoś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 łatwe wywoływanie funkcji updateNotification() bez konieczności uzyskiwania dostępu do klasy ForegroundServiceManager. Ta metoda pomocnicza może być przydatna, jeśli do odbierania nowych wiadomości z powiadomieniami używasz instancji dostawcy powiadomień. W takim przypadku możesz bezpośrednio wywołać tę metodę wewnętrzną, 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 używanie trwałego powiadomienia tylko 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 interfejsie initForegroundServiceManagerMessageAndIntent() zamiast domyślnego ciągu tekstowego pakietu SDK nawigacyjnego zawierającego wzmianki o „Mapach Google”. To wywołanie może też służyć do ustawiania intencji wznowienia, która będzie uruchamiana po kliknięciu powiadomienia.
Przejmij pełną kontrolę nad renderowaniem stałego powiadomienia
Ostateczny scenariusz wymaga zdefiniowania i utworzenia dostawcy powiadomień oraz przekazania go do usługi ForegroundServiceManager za pomocą initForegroundServiceManagerProvider(). Ta opcja daje pełną kontrolę nad tym, co jest wyświetlane w powiadomieniu, ale odłącza też od powiadomienia informacje pochodzące z pakietu Navigation SDK, usuwając w ten sposób przydatne szczegółowe wskazówki. Google nie zapewnia jeszcze prostego sposobu pobierania tych informacji i umieszczania 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 "";
   }
 }
}

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 udostępnia jeszcze prostego sposobu pobierania szczegółowych informacji, które dostawca powiadomień może wstawić do powiadomienia.