Począwszy od poziomu API 26 Androida, usługi działające na pierwszym planie wymagają trwałych powiadomień. Ten wymóg ma zapobiegać ukrywaniu usług, które mogą nadmiernie obciążać zasoby systemowe, w tym zwłaszcza baterię. Ten wymóg stwarza potencjalny problem: jeśli aplikacja z wieloma usługami działającymi na pierwszym planie nie będzie starannie zarządzać powiadomieniem, tak aby było ono udostępniane we wszystkich usługach, może pojawić się wiele trwałych powiadomień, których nie można odrzucić, co spowoduje niepożądany bałagan na aktywnej liście powiadomień.
Problem staje się bardziej złożony, gdy używasz pakietów SDK, takich jak Navigation SDK, które uruchamiają usługi działające na pierwszym planie niezależnie od aplikacji i mają własne, niezależne, trwałe powiadomienia, co utrudnia ich konsolidację.
Aby rozwiązać te problemy, w pakiecie Navigation SDK w wersji 1.11 wprowadziliśmy prosty interfejs API, który pomaga zarządzać trwałymi powiadomieniami w aplikacji, w tym w pakiecie SDK.
Komponenty
Menedżer usług na pierwszym planie zapewnia otoczkę wokół klasy usługi na pierwszym planie Androida i klasy trwałego powiadomienia. Głównym zadaniem tego opakowania jest wymuszanie ponownego użycia identyfikatora powiadomienia, aby powiadomienie było udostępniane we wszystkich usługach działających na pierwszym planie, które korzystają z menedżera.
Pakiet SDK Navigation zawiera statyczne metody inicjowania i pobierania ForegroundServiceManager
singletonu. Ten singleton można zainicjować tylko raz w okresie istnienia pakietu Navigation SDK. Dlatego jeśli używasz jednego z wywołań inicjujących (initForegroundServiceManagerMessageAndIntent()
lub initForegroundServiceManagerProvider()
), umieść go w bloku try-catch na wypadek ponownego wejścia na tę ścieżkę. Pakiet Navigation SDK zgłasza wyjątek czasu działania, jeśli wywołasz którąkolwiek z tych metod więcej niż raz, chyba że najpierw usuniesz wszystkie odwołania do ForegroundServiceManager
i wywołasz clearForegroundServiceManager()
przed każdym kolejnym wywołaniem.
4 parametry funkcji initForegroundServiceManagerMessageAndIntent()
to application
, notificationId
, defaultMessage
i resumeIntent
. Jeśli 3 ostatnie parametry mają wartość null, powiadomienie jest standardowym powiadomieniem pakietu Navigation SDK. Nadal można ukryć inne usługi działające na pierwszym planie w aplikacji za tym powiadomieniem. Parametr notificationId
określa identyfikator powiadomienia, który ma być używany w przypadku powiadomienia. Jeśli jest to wartość null, używana jest dowolna wartość. Możesz ustawić go w sposób jawny, aby uniknąć konfliktów z innymi powiadomieniami, np. z innego pakietu SDK. SymboldefaultMessage
to ciąg znaków wyświetlany, gdy system nie prowadzi do celu. resumeIntent
to intencja, która jest uruchamiana po kliknięciu powiadomienia. Jeśli wartość resumeIntent
to null, kliknięcia powiadomienia są ignorowane.
Trzy parametry funkcji initForegroundServiceManagerProvider()
to application
, notificationId
i notificationProvider
. Jeśli 2 ostatnie parametry mają wartość null, powiadomienie jest standardowym powiadomieniem pakietu Navigation SDK. Parametr notificationId
określa identyfikator powiadomienia, który powinien być używany w przypadku powiadomienia. Jeśli jest to wartość null, używana jest dowolna wartość. Możesz ustawić go w sposób jawny, aby uniknąć konfliktów z innymi powiadomieniami, np. z innego pakietu SDK. Jeśli parametr notificationProvider
jest ustawiony, dostawca zawsze odpowiada za wygenerowanie powiadomienia do wyświetlenia.
Metoda getForegroundServiceManager()
pakietu Navigation SDK zwraca pojedynczy obiekt menedżera usługi działającej na pierwszym planie. Jeśli nie masz jeszcze wygenerowanego identyfikatora, wywołanie initForegroundServiceManagerMessageAndIntent()
jest równoznaczne z wywołaniem z parametrami null dla notificationId
, defaultMessage
i resumeIntent
.
ForegroundServiceManager
ma 3 proste metody. Pierwsze 2 służą do przenoszenia usługi na pierwszy plan i z niego, a zwykle są wywoływane z poziomu utworzonej usługi. Dzięki tym metodom usługi są powiązane z udostępnionym trwałym powiadomieniem. Ostatnia metoda, updateNotification()
, informuje menedżera, że powiadomienie zostało zmienione i należy je ponownie wyrenderować.
Jeśli potrzebujesz pełnej kontroli nad udostępnionym trwałym powiadomieniem, interfejs API udostępnia interfejs NotificationContentProvider
do definiowania dostawcy powiadomień, który zawiera jedną metodę pobierania powiadomienia z bieżącą treścią. Zawiera też klasę bazową, której możesz opcjonalnie użyć do zdefiniowania dostawcy. Jednym z głównych celów klasy bazowej jest umożliwienie wywoływania funkcji updateNotification()
bez konieczności uzyskiwania dostępu do funkcji ForegroundServiceManager
. Jeśli używasz instancji dostawcy powiadomień do otrzymywania nowych wiadomości z powiadomieniami, możesz bezpośrednio wywołać tę wewnętrzną metodę, aby wyrenderować wiadomość w powiadomieniu.
Scenariusze użycia
W tej sekcji znajdziesz szczegółowe informacje o scenariuszach użycia wspólnych trwałych powiadomień.
- Ukrywanie trwałych powiadomień o usługach na pierwszym planie innych aplikacji
- Najprostszy scenariusz to zachowanie obecnego działania i używanie trwałego powiadomienia tylko do renderowania informacji z pakietu Navigation SDK. Inne usługi mogą ukrywać się za tym powiadomieniem, korzystając z metod menedżera usług na pierwszym planie
startForeground()
istopForeground()
. - Ukrywanie trwałych powiadomień o usługach działających na pierwszym planie innych aplikacji, ale ustawianie domyślnego tekstu wyświetlanego, gdy nie korzystasz z nawigacji
- Drugi najprostszy scenariusz to zachowanie obecnego działania i używanie powiadomienia trwałego tylko do renderowania informacji z pakietu SDK nawigacji, z wyjątkiem sytuacji, gdy system nie prowadzi nawigacji. Gdy system nie prowadzi nawigacji, wyświetla się ciąg znaków podany w
initForegroundServiceManagerMessageAndIntent()
, a nie domyślny ciąg znaków pakietu Navigation SDK, który zawiera wzmiankę o „Mapach Google”. Możesz też użyć tego wywołania, aby ustawić intencję wznowienia, która zostanie wywołana po kliknięciu powiadomienia. - Pełna kontrola renderowania trwał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 renderowane w powiadomieniu, ale odłącza też informacje o powiadomieniu z pakietu Navigation SDK od powiadomienia, co powoduje usunięcie przydatnych wskazówek dotyczących kolejnych kroków wyświetlanych w powiadomieniu. Google nie udostępnia prostego sposobu pobierania tych informacji i wstawiania ich do powiadomienia.
Przykładowy dostawca powiadomień
Poniższy przykład kodu pokazuje, jak tworzyć i zwracać powiadomienia za pomocą 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 NotificationContentProviderImpl
połącz z nim pakiet SDK do nawigacji za pomocą tego kodu:
ForegroundServiceManager f = NavigationApi.getForegroundServiceManager(getApplication());
mNotification = new NotificationContentProviderImpl(getApplication());
NavigationApi.clearForegroundServiceManager();
NavigationApi.initForegroundServiceManagerProvider(getApplication(), null, mNotification);
Zastrzeżenia i plany na przyszłość
- Pamiętaj, aby wywołać funkcję
initForegroundServiceManagerMessageAndIntent()
lubinitForegroundServiceManagerProvider()
na wczesnym etapie, aby oczekiwany scenariusz użycia był dobrze zdefiniowany. Musisz wywołać tę metodę, zanim utworzysz nowy obiekt Navigator. - Pamiętaj, aby wyłapywać wyjątki z wywołań funkcji
initForegroundServiceManagerMessageAndIntent()
lubinitForegroundServiceManagerProvider()
, jeśli ścieżka kodu zostanie wpisana więcej niż raz. W pakiecie Navigation SDK w wersji 2.0 wywołanie tej metody wielokrotnie powoduje zgłoszenie wyjątku sprawdzanego, a nie wyjątku środowiska wykonawczego. - Google może nadal pracować nad zapewnieniem spójnego stylu przez cały okres wyświetlania powiadomienia, który będzie pasować do stylu nagłówka.
- Gdy zdefiniujesz dostawcę powiadomień, możesz kontrolować zachowanie powiadomień wyskakujących za pomocą priorytetu.
- Google nie udostępnia prostego sposobu pobierania szczegółowych informacji o kolejnych krokach, które dostawca powiadomień mógłby wstawić do powiadomienia.