從 Android API 級別 26 開始,應用程式必須使用持續通知 前景服務這項規定旨在避免您隱藏可能對系統資源 (特別是電池) 造成過度需求的服務。這項規定會造成潛在問題:如果應用程式有多個前景服務,但未仔細管理通知,以便在所有服務間共用,則可能會有多個無法關閉的持續性通知,導致通知的有效清單中出現不必要的雜亂。
使用 Navigation 等 SDK 時,這個問題會更加棘手
SDK,這類 SDK 是用於執行前景服務,不受
因此會造成獨立永久通知,導致系統難以整合。
為解決這些問題,Navigation SDK 1.11 版推出了簡單的 API,可協助管理應用程式 (包括 SDK 內) 中的持續性通知。
元件
前景服務管理員會在 Android 前景服務類別和持續通知類別周圍提供包裝函式。這個包裝函式的主功能是強制重複使用 Notification ID,以便透過管理員在所有前景服務中共用通知。
Navigation SDK 包含用於初始化及取得
ForegroundServiceManager
單例模式。這個單例在 Navigation SDK 的生命週期中只能初始化一次。因此,如果您使用其中一個初始化呼叫 (initForegroundServiceManagerMessageAndIntent()
或 initForegroundServiceManagerProvider()
),則應在該呼叫前後加上 try-catch 區塊,以防該路徑重新輸入。如果您呼叫任一方法超過一次,Navigation SDK 就會擲回執行階段例外狀況,除非您先清除所有對 ForegroundServiceManager
的參照,並在每次後續呼叫之前呼叫 clearForegroundServiceManager()
。
initForegroundServiceManagerMessageAndIntent()
的四個參數是
application
、notificationId
、defaultMessage
和resumeIntent
。如果最後三個參數為空值,則通知為標準 Navigation SDK 通知。您仍可在通知後方隱藏應用程式中的其他前景服務。notificationId
參數會指定應用於通知的通知 ID。如果為空值,則會使用任意值。您可以明確設定這項功能
與其他通知發生衝突,比如其他 SDK 的通知。
defaultMessage
是系統未
導航。resumeIntent
是通知時觸發的意圖
即可。如果 resumeIntent
為空值,請按一下通知
系統會忽略此值。
initForegroundServiceManagerProvider()
的三個參數分別是 application
、notificationId
和 notificationProvider
。如果最終結果為
兩個參數為空值,則通知是標準 Navigation SDK
通知。notificationId
參數會指定通知 ID
通知。如果值為空值,任意值會是
您可以明確調整設定,以解決與其他
像是來自其他 SDK 的通知如果已設定 notificationProvider
,則供應器一律負責產生要轉譯的通知。
Navigation SDK getForegroundServiceManager()
方法會傳回
前景服務管理工具單例模式如果您尚未產生一個,那麼這就等同於使用 notificationId
、defaultMessage
和 resumeIntent
的空參數呼叫 initForegroundServiceManagerMessageAndIntent()
。
ForegroundServiceManager
有三種簡單方法。前兩個用於將服務移入及移出前景,通常會在已建立的服務中呼叫。使用這些方法可確保
都會與共用永久通知建立關聯最後一個
方法 updateNotification()
,會標記通知含有通知的管理員
並應重新轉譯。
如果您需要完全控管共用永久通知:
API 提供的 NotificationContentProvider
介面可用來定義
通知提供者,內含接收通知的一種方法
與目前內容互動此 API 也提供基礎類別,您可以
視需要用來定義供應器基礎類別的主要用途之一,是提供一種方法,讓您不必存取 ForegroundServiceManager
即可呼叫 updateNotification()
。如果使用
通知供應商以便接收新的通知訊息,您可以呼叫
內部方法來在通知中顯示訊息。
使用情境
本節將詳細說明使用共用持續性通知的使用情境。
- 隱藏其他應用程式前景服務的持續通知
- 最簡單的情況是保留目前的行為,並只使用持久通知來轉譯 Navigation SDK 資訊。其他服務可以使用前景服務管理器
startForeground()
和stopForeground()
方法,隱藏在該通知後方。 - 隱藏其他應用程式前景服務的常駐通知,但設定在未導覽時顯示的預設文字
- 第二個最簡單的情況是保留目前行為,並只在系統未導覽時使用持續性通知來轉譯 Navigation SDK 資訊。系統沒有進行導覽時
提供給
initForegroundServiceManagerMessageAndIntent()
的字串 ,而不是先前提到的 「Google 地圖」。您也可以使用此呼叫設定重新啟用意圖 使用者點擊通知時觸發。 - 完全掌控持續性通知的顯示方式
- 最後一個情境需要定義並建立通知供應器
並使用以下指令將其傳遞至
ForegroundServiceManager
initForegroundServiceManagerProvider()
。這個選項可讓您完全控制通知中顯示的內容,但也會將 Navigation SDK 通知資訊與通知分開,進而移除通知中顯示的實用逐轉指示提示。Google 並不提供簡單的方式讓您擷取此資訊 資訊,並將資訊插入通知中。
通知提供者範例
以下程式碼範例說明如何使用簡單的通知內容提供者建立及傳回通知。
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 "";
}
}
}
建立 NotificationContentProviderImpl
後,您可以使用以下程式碼將 Navigation SDK 連結至 NotificationContentProviderImpl
:
ForegroundServiceManager f = NavigationApi.getForegroundServiceManager(getApplication());
mNotification = new NotificationContentProviderImpl(getApplication());
NavigationApi.clearForegroundServiceManager();
NavigationApi.initForegroundServiceManagerProvider(getApplication(), null, mNotification);
注意事項和未來計畫
- 請務必盡早呼叫
initForegroundServiceManagerMessageAndIntent()
或initForegroundServiceManagerProvider()
,以便 定義了預期用途您必須呼叫此方法 再建立新的導覽器 - 請務必找出與
initForegroundServiceManagerMessageAndIntent()
或initForegroundServiceManagerProvider()
(如果程式碼路徑為 重複輸入。在 Navigation SDK 2.0 版中,呼叫此方法 多次擲回已檢查的例外狀況,而非執行階段例外狀況。 - Google 可能還要做一些努力,才能使樣式更加一致 符合標頭樣式的通知的生命週期。
- 定義通知供應器時,您可以使用優先順序控制抬頭通知行為。
- Google 無法提供簡便的即時路線擷取方法 通知供應程式可能插入通知中的資訊。