Począwszy od interfejsu API na poziomie 26 Androida, w przypadku usług na pierwszym planie wymagane są powiadomienia trwałe. To wymaganie ma na celu uniemożliwienie ukrywania usług, które mogą nadmiernie obciążać zasoby systemowe, w tym zwłaszcza baterię. To wymaganie może powodować 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ę okazać, że na liście aktywnych powiadomień jest ich wiele i nie można ich zamknąć, co powoduje niechciany bałagan.
Ten problem staje się jeszcze 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, 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łównym zadaniem tego opakowania jest wymuszanie ponownego użycia identyfikatora powiadomienia, aby powiadomienie było udostępniane wszystkim usługom na pierwszym planie korzystającym z menedżera.
Pakiet SDK nawigacji zawiera metody statyczne służące do inicjowania i uzyskiwania obiektu singletona ForegroundServiceManager
. Ten obiekt singleton może zostać zainicjowany tylko raz w cyklu życia Navigation SDK. 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 wywołasz clearForegroundServiceManager()
przed każdym kolejnym wywołaniem.
Cztery parametry initForegroundServiceManagerMessageAndIntent()
to: application
, notificationId
, defaultMessage
i resumeIntent
. Jeśli 3 ostatnie parametry są puste, powiadomienie jest standardowym powiadomieniem z 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 powiadomieniami 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 z pakietu SDK nawigacji. Parametr notificationId
określa identyfikator powiadomienia, którego należy użyć. 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 opcja notificationProvider
jest ustawiona, dostawca jest zawsze odpowiedzialny za wygenerowanie powiadomienia do wyświetlenia.
Metoda getForegroundServiceManager()
pakietu SDK nawigacji zwraca pojedynczy obiekt menedżera usługi 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 drugi plan i zwykle są wywoływane z usługi, która została utworzona. Dzięki tym metodom usługi są powiązane z udostępnionym powiadomieniem trwałym. Ostatnia metoda, updateNotification()
, sygnalizuje menedżerowi, że powiadomienie uległo zmianie 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ę umożliwiającą wyświetlanie powiadomienia z aktualną zawartością. Udostępnia ona też klasę podstawową, której możesz użyć opcjonalnie, aby zdefiniować dostawcę. 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 powiadomienia, możesz wywołać tę wewnętrzną metodę bezpośrednio, aby wyświetlić wiadomość w powiadomieniu.
Scenariusze użycia
W tej sekcji znajdziesz szczegółowe informacje o scenariuszach użycia współdzielonych powiadomień trwałych.
- ukrywanie stałych powiadomień z innych aplikacji działających 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()
istopForeground()
menedżera usług na pierwszym planie. - Ukrywanie trwałych powiadomień z innych usług na pierwszym planie, ale ustawianie domyślnego tekstu wyświetlanego, gdy nie odbywa się nawigacja
- Drugim najprostszym scenariuszem jest zachowanie obecnego zachowania i używanie powiadomienia trwałego tylko do renderowania informacji z Navigation SDK, z wyjątkiem sytuacji, gdy system nie prowadzi nawigacji. Gdy system nie prowadzi nawigacji, wyświetla się ciąg znaków podany do parametru
initForegroundServiceManagerMessageAndIntent()
, a nie domyślny ciąg znaków w Navigation SDK, który wspomina o „Mapach Google”. Za pomocą tego wywołania możesz też ustawić intencję wznowienia, która zostanie uruchomiona po kliknięciu powiadomienia. - pełną kontrolę nad renderowaniem powiadomienia trwałego;
- 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 o powiadomieniu z pakietu SDK nawigacji od powiadomienia, co powoduje usunięcie przydatnych promptów wyświetlanych w powiadomieniu. Google nie udostępnia prostego sposobu na pobranie tych informacji i wstawienie ich w powiadomieniu.
Przykładowy dostawca powiadomień
Ten 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
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);
Ograniczenia i przyszłe plany
- Zadzwoń do
initForegroundServiceManagerMessageAndIntent()
lubinitForegroundServiceManagerProvider()
odpowiednio wcześniej, aby dokładnie określić oczekiwany scenariusz użycia. Przed utworzeniem nowego Navigatora musisz wywołać tę metodę. - Pamiętaj, aby przechwytywać wyjątki z wywołań do funkcji
initForegroundServiceManagerMessageAndIntent()
lubinitForegroundServiceManagerProvider()
na wypadek, gdyby ścieżka kodu została wpisana więcej niż raz. W SDK nawigacji 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, określając ich priorytet.
- Google nie udostępnia prostego sposobu na pobranie informacji o nawigacji, które dostawca powiadomień może wstawić do powiadomienia.