Android Auto と Android Automotive OS(AAOS)は、アプリのメディア ブラウザ サービスを呼び出して、利用可能なコンテンツを検出します。これをサポートするには、メディア ブラウザ サービスに次の 2 つのメソッドを実装します。
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, null)
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 の Universal
Android Music Player サンプルアプリの onGetRoot をご覧ください。
パッケージの検証を追加する
サービスの onGetRoot メソッドが呼び出されると、呼び出し元の
パッケージが識別情報をサービスに渡します。サービスはこの情報を使用して、そのパッケージがコンテンツにアクセスできるかどうかを判断できます。
たとえば、アプリのコンテンツへのアクセスを承認済みパッケージのリストに制限できます。
clientPackageNameを許可リストと比較します。- パッケージの APK の署名に使用された証明書を確認します。
パッケージを検証できない場合は、null を返してコンテンツへのアクセスを拒否します。
Android Auto や AAOS などのシステムアプリにコンテンツへのアクセス権を付与するには、これらのシステムアプリが onGetRoot
メソッドを呼び出したときに、サービスが null 以外の 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 の
Universal Android Music Player サンプルアプリの PackageValidator クラスからの抜粋です。サービスの onGetRoot
メソッドのパッケージ検証を実装する方法の詳細な例については、そのクラスをご覧ください。
システムアプリを許可するだけでなく、Google アシスタントが MediaBrowserService
に接続できるようにする必要があります。Google アシスタントは、モバイルアプリと AAOS アプリで
異なるパッケージ名を使用します。
onLoadChildren を実装する
Android Auto と AAOS
は、ルートノードのオブジェクトを受け取った後、そのオブジェクトで onLoadChildren を呼び出してその子孫を取得することにより、最上位メニューを構築します。クライアント
アプリは、子孫ノードのオブジェクトを使用してこの同じメソッドを呼び出すことにより、サブメニューを構築します。
onGetChildrenコンテンツ階層の各ノードは、
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 の
Universal Android Music Player サンプルアプリの 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 統合によって異なる場合に、これらのヒントの値に基づいてコンテンツ階層の構造のロジックを分岐することもできます。
たとえば、ルートの再生可能なアイテムを通常どおり表示する場合、サポートされるフラグヒントの値に従って、ルートのブラウズ可能なアイテムの下にネストできます。
タブを最適に表示するには、ルートヒントとは別に次のガイドラインにも従う必要があります。
各タブアイテムのモノクロ(できれば白)のアイコン
各タブアイテムの短く意味のあるラベル(ラベルが短ければ、ラベルが切り捨てられる可能性が低くなります)