Android Auto 和 Android Automotive OS (AAOS) 會呼叫應用程式的媒體瀏覽器服務,查看有哪些內容可用。如要支援這項功能,請在媒體瀏覽器服務中實作這兩種方法。
實作 onGetRoot
服務的 onGetRoot
方法會傳回內容階層根節點的相關資訊。Android Auto 和 AAOS 會使用這個根節點,透過 onLoadChildren
方法要求其他內容。以下程式碼片段顯示 onGetRoot
方法的實作方式:
Kotlin
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): BrowserRoot? =
// Verify that the specified package is allowed to access your
// content. You'll need to write your own logic to do this.
if (!isValid(clientPackageName, clientUid)) {
// If the request comes from an untrusted package, return null.
// No further calls will be made to other media browsing methods.
null
} else MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, nu
ll)
Java
@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
Bundle rootHints) {
// Verify that the specified package is allowed to access your
// content. You'll need to write your own logic to do this.
if (!isValid(clientPackageName, clientUid)) {
// If the request comes from an untrusted package, return null.
// No further calls will be made to other media browsing methods.
return null;
}
return new MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null)
;
}
如需此方法的詳細範例,請參閱 GitHub 上通用 Android 音樂播放器範例應用程式中的 onGetRoot
。
新增套件驗證
呼叫服務的 onGetRoot
方法時,呼叫套件會將身分識別資訊傳遞至您的服務。您的服務可利用此資訊判斷該套件是否能存取您的內容。
舉例來說,您可以只讓列在核准清單中的套件存取應用程式內容:
- 將
clientPackageName
與許可清單進行比較。 - 驗證用於簽署套件 APK 的憑證。
如果套件沒有通過驗證,則傳回 null
,拒絕該套件存取您的內容。
為了讓系統應用程式 (例如 Android Auto 和 AAOS) 存取您的內容,當這些系統應用程式呼叫 onGetRoot
方法時,您的服務必須傳回非空值的 BrowserRoot
。
AAOS 系統應用程式的簽章會因車輛廠牌和車型而異。請務必允許所有系統應用程式建立連線,以支援 AAOS。
下列程式碼片段說明服務如何驗證呼叫套件是系統應用程式:
fun isKnownCaller(
callingPackage: String,
callingUid: Int
): Boolean {
...
val isCallerKnown = when {
// If the system is making the call, allow it.
callingUid == Process.SYSTEM_UID -> true
// If the app was signed by the same certificate as the platform
// itself, also allow it.
callerSignature == platformSignature -> true
// ... more cases
}
return isCallerKnown
}
以上程式碼片段摘錄自 GitHub 上 Android 通用音樂播放器範例應用程式中的 PackageValidator
類別。請參閱該類別的詳細資料範例,瞭解如何針對服務的 onGetRoot
方法實作套件驗證。
除了允許系統應用程式之外,您也必須允許 Google 助理連結至您的 MediaBrowserService
。Google 助理為手機 (包括 Android Auto 和 Android Automotive OS) 分別提供不同的套件名稱。
實作 onLoadChildren
收到根節點物件之後,Android Auto 和 AAOS 會透過呼叫根節點物件的 onLoadChildren
,建立頂層選單,取得其後代。用戶端應用程式會使用後代節點物件呼叫相同的方法,來建構子選單。
內容階層中的每個節點都以 MediaBrowserCompat.MediaItem
物件表示。每個媒體項目都是透過一組專屬 ID 字串識別。用戶端應用程式會將這些 ID 字串視為不透明權杖。
當用戶端應用程式想要瀏覽子選單或播放媒體項目時,系統會傳遞該權杖。您的應用程式負責將權杖與適當的媒體項目建立關聯。
這個程式碼片段顯示 onLoadChildren
的實作方式
Kotlin
override fun onLoadChildren(
parentMediaId: String,
result: Result<List<MediaBrowserCompat.MediaItem>>
) {
// Assume for example that the music catalog is already loaded/cached.
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
// Check if this is the root menu:
if (MY_MEDIA_ROOT_ID == parentMediaId) {
// Build the MediaItem objects for the top level
// and put them in the mediaItems list.
} else {
// Examine the passed parentMediaId to see which submenu we're at
// and put the descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems
)
}
Java
@Override
public void onLoadChildren(final String parentMediaId,
final Result<List<MediaBrowserCompat.MediaItem>> result) {
// Assume for example that the music catalog is already loaded/cached.
List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();
// Check if this is the root menu:
if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) {
// Build the MediaItem objects for the top level
// and put them in the mediaItems list.
} else {
// Examine the passed parentMediaId to see which submenu we're at
// and put the descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems)
;
}
如要查看這個方法的範例,請參閱 GitHub 上通用 Android 音樂播放器範例應用程式中的 onLoadChildren
。
建構根選單
Android Auto 和 Android Automotive OS 對根選單結構設有特定限制。這些限制會透過根提示傳遞至 MediaBrowserService
,而您可以透過傳入 onGetRoot()
的 Bundle 引數讀取這些提示。按照這些提示操作,系統便能將根層級內容顯示為導覽分頁。如未按照這些提示操作,系統可能會捨棄某些根層級內容或使其不易偵測。
圖 1. 以導覽分頁的形式呈現根內容。
套用這些提示後,系統會將根層級內容顯示為導覽分頁。如未套用這些提示,系統可能會捨棄某些根層級內容或降低其可偵測性。系統會傳送以下提示:
根子項數量的限制:在大多數情況下,此數量上限為 4,也就是說,系統最多只會顯示 4 個分頁。
支援的根子項標記:這個值應為
MediaItem#FLAG_BROWSABLE
,也就是說,只有可瀏覽項目 (而非可播放項目) 可以顯示為分頁。自訂瀏覽動作數量限制:查看支援的自訂瀏覽動作數量。
Kotlin
import androidx.media.utils.MediaConstants
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle
): BrowserRoot {
val maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
/* defaultValue= */ 4)
val supportedRootChildFlags = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ MediaItem.FLAG_BROWSABLE)
// Rest of method...
}
Java
import androidx.media.utils.MediaConstants;
// Later, in your MediaBrowserServiceCompat.
@Override
public BrowserRoot onGetRoot(
String clientPackageName, int clientUid, Bundle rootHints) {
int maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
/* defaultValue= */ 4);
int supportedRootChildFlags = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ MediaItem.FLAG_BROWSABLE);
// Rest of method...
}
您可以根據這些提示的值,選擇建立內容階層結構的邏輯分支,尤其是階層結構在 Android Auto 和 AAOS 以外的 MediaBrowser
整合作業中有所不同的情況。
舉例來說,假如您通常會顯示某個根層級的可播放項目,則可能會根據支援的標記提示值,將它嵌入某個根層級可瀏覽項目底下的巢狀結構。
除了根提示外,請按照下列指引以最佳方式呈現分頁:
每個分頁項目的單色 (建議白色) 圖示
為每個分頁項目提供簡短但有意義的標籤 (簡短的標籤可降低標籤遭截斷的機率)