メディア コントローラはメディア セッションとやり取りして、メディアアプリの再生をクエリして制御します。Media3 では、MediaController
API が Player
インターフェースを実装します。メディア コントローラを使用するクライアント アプリの例は次のとおりです。
- Android システムのメディア コントロール
- Android Wear OS コンパニオン アプリ
- Android Auto と Automotive OS
- Google アシスタントなどの音声アシスタント
- メディア コントローラ テストアプリ
メディア コントローラは、メディアアプリ内でも役立ちます。たとえば、プレーヤーとメディア セッションが UI を含む Activity
または Fragment
とは別の Service
に存在する場合などです。
MediaController
を作成
MediaController
を作成するには、まず対応する MediaSession
の SessionToken
を作成します。Activity
または Fragment
の onStart()
メソッドが適しています。
Kotlin
val sessionToken =
SessionToken(context, ComponentName(context, PlaybackService::class.java))
Java
SessionToken sessionToken =
new SessionToken(context, new ComponentName(context, PlaybackService.class));
この SessionToken
を使用して MediaController
をビルドすると、コントローラが指定されたセッションに接続されます。これは非同期で行われるため、結果をリッスンし、利用可能になったら使用する必要があります。
Kotlin
val controllerFuture =
MediaController.Builder(context, sessionToken).buildAsync()
controllerFuture.addListener({
// MediaController is available here with controllerFuture.get()
}, MoreExecutors.directExecutor())
Java
ListenableFuture<MediaController> controllerFuture =
new MediaController.Builder(context, sessionToken).buildAsync();
controllerFuture.addListener(() -> {
// MediaController is available here with controllerFuture.get()
}, MoreExecutors.directExecutor());
MediaController
を使用する
MediaController
は Player
インターフェースを実装しているため、インターフェースで定義されたコマンドを使用して、接続された MediaSession
の再生を制御できます。つまり、MediaController
で play()
を呼び出すと、接続された MediaSession
にコマンドが送信され、その後、コマンドが基盤となる Player
に委任されます。
コントローラに Player.Listener
を追加して、Player
状態の変化をリッスンできます。Player.Listener
の使用について詳しくは、プレーヤー イベントのガイドをご覧ください。
MediaController.Listener
インターフェースは、接続された MediaSession
からのイベントとカスタム コマンドの追加のコールバックを定義します。たとえば、セッションがカスタム コマンドを送信した場合は onCustomCommand()
、セッションが使用可能なセッション コマンドを変更した場合は onAvailableSessionCommandsChanged()
、コントローラがセッションから切断された場合は onDisconnected()
です。
Builder
を使用してコントローラをビルドするときに、MediaController.Listener
を設定できます。
Kotlin
MediaController.Builder(context, sessionToken)
.setListener(
object : MediaController.Listener {
override fun onCustomCommand(
controller: MediaController,
command: SessionCommand,
args: Bundle,
): ListenableFuture<SessionResult> {
// Handle custom command.
return Futures.immediateFuture(SessionResult(SessionResult.RESULT_SUCCESS))
}
override fun onDisconnected(controller: MediaController) {
// Handle disconnection.
}
}
)
.buildAsync()
Java
new MediaController.Builder(context, sessionToken)
.setListener(
new MediaController.Listener() {
@Override
public ListenableFuture<SessionResult> onCustomCommand(
MediaController controller, SessionCommand command, Bundle args) {
// Handle custom command.
return Futures.immediateFuture(new SessionResult(SessionResult.RESULT_SUCCESS));
}
@Override
public void onDisconnected(MediaController controller) {
// Handle disconnection.
}
})
.buildAsync();
他のコンポーネントと同様に、Activity
や Fragment
の onStop()
メソッドなど、MediaController
が不要になったらリリースするようにしてください。
Kotlin
MediaController.releaseFuture(controllerFuture)
Java
MediaController.releaseFuture(controllerFuture);
コントローラをリリースしても、セッションに送信された保留中のコマンドはすべて配信されます。これらのコマンドが処理されるか、タイムアウト期間が経過するかのいずれか早い方のタイミングで、セッション サービスからバインドが解除されます。
MediaBrowser
を作成して使用する
MediaBrowser
は MediaController
が提供する機能の上に構築され、メディアアプリの MediaLibraryService
が提供するメディア ライブラリのブラウジングも可能にします。
Kotlin
val browserFuture = MediaBrowser.Builder(context, sessionToken).buildAsync()
browserFuture.addListener({
// MediaBrowser is available here with browserFuture.get()
}, MoreExecutors.directExecutor())
Java
ListenableFuture<MediaBrowser> browserFuture =
new MediaBrowser.Builder(context, sessionToken).buildAsync();
browserFuture.addListener(() -> {
// MediaBrowser is available here with browserFuture.get()
}, MoreExecutors.directExecutor());
メディアアプリのコンテンツ ライブラリの閲覧を開始するには、まず getLibraryRoot()
でルートノードを取得します。
Kotlin
// Get the library root to start browsing the library tree.
val rootFuture = mediaBrowser.getLibraryRoot(/* params= */ null)
rootFuture.addListener({
// Root node MediaItem is available here with rootFuture.get().value
}, MoreExecutors.directExecutor())
Java
// Get the library root to start browsing the library tree.
ListenableFuture<LibraryResult<MediaItem>> rootFuture =
mediaBrowser.getLibraryRoot(/* params= */ null);
rootFuture.addListener(() -> {
// Root node MediaItem is available here with rootFuture.get().value
}, MoreExecutors.directExecutor());
ライブラリ内の MediaItem
の子を getChildren()
で取得することで、メディア ライブラリ内を移動できます。たとえば、ルートノード MediaItem
の子を取得するには、次のようにします。
Kotlin
// Get the library root to start browsing the library tree.
val childrenFuture =
mediaBrowser.getChildren(rootMediaItem.mediaId, 0, Int.MAX_VALUE, null)
childrenFuture.addListener({
// List of children MediaItem nodes is available here with
// childrenFuture.get().value
}, MoreExecutors.directExecutor())
Java
ListenableFuture<LibraryResult<ImmutableList<MediaItem>>> childrenFuture =
mediaBrowser.getChildren(rootMediaItem.mediaId, 0, Integer.MAX_VALUE, null);
childrenFuture.addListener(() -> {
// List of children MediaItem nodes is available here with
// childrenFuture.get().value
}, MoreExecutors.directExecutor());
別のメディアアプリの再生コントロールを表示する
別のメディアアプリのボタンを含む UI コントロールを表示する場合は、そのアプリの宣言されたメディアボタンの優先設定に従うことが重要です。
アプリの優先設定と UI の制約や要件を解決するには、CommandButton.DisplayConstraints
を使用することをおすすめします。UI で実行できる操作の制限を定義できます。また、resolve
メソッドは、アイコン、位置、意図したアクションとともに表示するボタンの明確なリストを提供します。