メディア コントローラはメディア セッションとやり取りして、メディアアプリの再生をクエリして制御します。Media3 では、MediaController
API が Player
インターフェースを実装します。メディア コントローラを使用するクライアント アプリの例を次に示します。
- Android システムのメディア コントロール
- Android Wear OS コンパニオン アプリ
- Android Auto と Automotive OS
- Google アシスタントなどの音声アシスタント
- Media Controller テストアプリ
メディア コントローラは、メディア アプリ内でも役立ちます。たとえば、プレーヤーとメディア セッションが 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
にコマンドが送信され、MediaSession
は基盤となる Player
にコマンドを委任します。
コントローラに Player.Listener
を追加して、Player
状態の変更をリッスンできます。Player.Listener
の使用方法について詳しくは、プレーヤー イベント ガイドをご覧ください。
MediaController.Listener
インターフェースは、接続された MediaSession
からのイベントとカスタム コマンドに追加のコールバックを定義します。たとえば、セッションがカスタム コマンドを送信する場合は onCustomCommand()
、セッションが使用可能なセッション コマンドを変更する場合は onAvailableSessionCommandsChanged()
、コントローラがセッションから切断された場合は onDisconnected()
です。
MediaController.Listener
は、Builder
を使用してコントローラをビルドするときに設定できます。
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());
次に、getChildren()
を使用してライブラリ内の MediaItem
の子孫を取得することで、メディア ライブラリを移動できます。たとえば、ルートノード 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
メソッドは、アイコン、位置、目的のアクションとともに表示するボタンの明確なリストを提供します。