Począwszy od interfejsu API na poziomie 26 Androida, w przypadku usług na pierwszym planie wymagane są powiadomienia trwałe. Ten wymóg ma na celu zapobieganie ukrywaniu usług, które mogą nadmiernie obciążać zasoby systemowe, w tym zwłaszcza baterię. To wymaganie powoduje potencjalny problem: jeśli aplikacja z wieloma usługami na pierwszym planie nie zarządza powiadomieniami w sposób, który umożliwia ich udostępnianie wszystkim usługom, może się zdarzyć, że będzie wyświetlać wiele nieusuwanych powiadomień, co spowoduje niechciany bałagan na liście aktywnych powiadomień.
Ten problem staje się bardziej złożony, gdy używasz pakietów SDK, takich jak pakiet SDK nawigacji, które uruchamiają usługi na pierwszym planie niezależnie od aplikacji i mają własne powiadomienia trwałe, co utrudnia ich konsolidację.
Aby rozwiązać te problemy, w wersji 1.11 pakietu SDK nawigacji wprowadzono prosty interfejs API, który ułatwia zarządzanie trwałymi powiadomieniami w aplikacji, w tym w pakiecie SDK.
Komponenty
Menedżer usługi na pierwszym planie udostępnia element opakowujący dla klasy usługi na pierwszym planie Androida i klasy powiadomienia trwałego. Główną funkcją tego opakowania jest wymuszanie 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 służące do inicjowania i uzyskiwania obiektu ForegroundServiceManager
singleton. Ten obiekt singleton może zostać zainicjowany tylko raz w cyklu życia pakietu SDK nawigacji. Dlatego jeśli używasz jednego z wywołań inicjalizujących (initForegroundServiceManagerMessageAndIntent()
lub initForegroundServiceManagerProvider()
), musisz je otoczyć blokiem try-catch na wypadek, gdyby ta ścieżka została ponownie wprowadzona. Jeśli wywołasz którąś z tych metod więcej niż raz, Navigation SDK zgłasza wyjątek czasu wykonywania, chyba że najpierw usuniesz wszystkie odwołania do ForegroundServiceManager
i przed każdym kolejnym wywołaniem wywołasz metodę clearForegroundServiceManager()
.
4 parametry initForegroundServiceManagerMessageAndIntent()
to: application
, notificationId
, defaultMessage
i resumeIntent
. Jeśli 3 ostatnie parametry są puste, powiadomienie jest standardowym powiadomieniem pakietu SDK nawigacji. Nadal możesz ukrywać inne usługi na pierwszym planie w aplikacji za pomocą tego powiadomienia. Parametr notificationId
określa identyfikator powiadomienia, którego należy użyć w powiadomieniu. Jeśli jest null, używana jest dowolna wartość. Możesz go ustawić wyraźnie, aby uniknąć konfliktów z innymi powiadomieniami, np. z innego pakietu SDK. defaultMessage
to ciąg znaków wyświetlany, gdy system nie jest nawigowany. resumeIntent
to intencja, która jest wywoływana po kliknięciu powiadomienia. Jeśli wartość resumeIntent
jest pusta, kliknięcia powiadomienia są ignorowane.
Trzy parametry initForegroundServiceManagerProvider()
to: application
, notificationId
i notificationProvider
. Jeśli 2 ostatnie parametry są puste, powiadomienie jest standardowym powiadomieniem pakietu SDK nawigacji. Parametr notificationId
określa identyfikator powiadomienia, którego należy użyć do powiadomienia. Jeśli ma wartość null, używana jest dowolna wartość. Możesz go ustawić wyraźnie, aby uniknąć konfliktów z innymi powiadomieniami, np. z innego pakietu SDK. Jeśli parametr notificationProvider
jest ustawiony, to dostawca jest zawsze odpowiedzialny za wygenerowanie powiadomienia do wyświetlenia.
Metoda getForegroundServiceManager()
pakietu SDK Nawigacji zwraca pojedynczy obiekt menedżera usług na pierwszym planie. Jeśli nie został jeszcze wygenerowany, jest to równoznaczne z wywołaniem funkcji initForegroundServiceManagerMessageAndIntent()
z parametrami null dla parametrów notificationId
, defaultMessage
i resumeIntent
.
ForegroundServiceManager
ma 3 proste metody. Pierwsze 2 są przeznaczone do przenoszenia usługi na pierwszy lub z pierwszego planu i są one zwykle wywoływane z ram utworzonej usługi. Dzięki tym metodom usługi są powiązane z udostępnionym trwałym powiadomieniem. Ostatnia metoda, updateNotification()
, sygnalizuje menedżerowi, że powiadomienie zostało zmienione i należy je ponownie wyrenderować.
Jeśli chcesz mieć pełną kontrolę 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ą zawartością. Zawiera też klasę podstawową, której możesz opcjonalnie użyć do zdefiniowania dostawcy. Jednym z głównych celów klasy bazowej jest to, że umożliwia ona wywołanie funkcji updateNotification()
bez konieczności uzyskiwania dostępu do funkcji ForegroundServiceManager
. Jeśli używasz wystąpienia dostawcy powiadomień, aby otrzymywać nowe wiadomości powiadomień, możesz wywołać tę wewnętrzną metodę bezpośrednio, aby wyrenderować wiadomość w powiadomieniu.
Scenariusze użycia
W tej sekcji opisujemy scenariusze użycia udostępnionych powiadomień trwałych.
- Ukrywanie trwałych powiadomień z innych usług na pierwszym planie
- Najprostszym rozwiązaniem jest zachowanie obecnego zachowania i używanie powiadomienia trwałego tylko do renderowania informacji z Navigation SDK. Inne usługi mogą się ukrywać za tym powiadomieniem, korzystając z metody
startForeground()
lubstopForeground()
menedżera usług na pierwszym planie. - Ukrywanie trwałych powiadomień z innych usług na pierwszym planie aplikacji, ale ustawianie domyślnego tekstu wyświetlanego, gdy nie ma nawigacji
- Drugim najprostszym scenariuszem jest zachowanie obecnego zachowania 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 parametrze
initForegroundServiceManagerMessageAndIntent()
, a nie domyślny ciąg znaków w Navigation SDK, który zawiera „Mapy Google”. Za pomocą tego wywołania możesz też ustawić intencję wznowienia, która zostanie uruchomiona po kliknięciu powiadomienia. - mieć pełną kontrolę nad renderowaniem trwałego powiadomienia;
- Ostatni scenariusz wymaga zdefiniowania i utworzenia dostawcy powiadomień oraz przekazania go do
ForegroundServiceManager
za pomocą funkcjiinitForegroundServiceManagerProvider()
. Ta opcja daje pełną kontrolę nad tym, co jest renderowane w powiadomieniu, ale powoduje też odłączenie informacji z powiadomienia pakietu SDK nawigacji od powiadomienia, co powoduje usunięcie przydatnych promptów wyświetlanych w powiadomieniu. Google nie udostępnia prostego sposobu pobierania tych informacji i wstawiania ich do powiadomienia.
Przykładowy dostawca powiadomień
Ten przykładowy kod 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
możesz połączyć 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 plany na przyszłość
- Pamiętaj, aby wcześniej wywołać funkcję
initForegroundServiceManagerMessageAndIntent()
lubinitForegroundServiceManagerProvider()
, aby dobrze zdefiniować oczekiwany scenariusz użycia. Tę metodę musisz wywołać przed utworzeniem nowego obiektu Navigator. - Pamiętaj, aby przechwytywać wyjątki z wywołań do funkcji
initForegroundServiceManagerMessageAndIntent()
lubinitForegroundServiceManagerProvider()
, jeśli ścieżka kodu została wpisana więcej niż raz. W pakiecie Navigation SDK w wersji 2.0 wywołanie tej metody więcej niż raz powoduje wyjątek sprawdzony, a nie wyjątek czasu wykonywania. - Google może jeszcze potrzebować czasu, aby zapewnić spójny styl powiadomienia przez cały okres jego ważności, który pasuje do stylu nagłówka.
- Gdy zdefiniujesz dostawcę powiadomień, możesz sterować działaniem powiadomień z poprzednim wyświetleniem, korzystając z priorytetu.
- Google nie udostępnia prostego sposobu na pobranie informacji o kierunkach, które dostawca powiadomień może wstawić do powiadomienia.