メディアアプリに接続する

メディア コントローラはメディア セッションとやり取りして、メディアアプリの再生をクエリして制御します。Media3 では、MediaController API が Player インターフェースを実装します。メディア コントローラを使用するクライアント アプリの例を次に示します。

メディア コントローラは、メディア アプリ内でも役立ちます。たとえば、プレーヤーとメディア セッションが UI の Activity または Fragment とは別の Service にある場合などです。

MediaController を作成

MediaController を作成するには、まず対応する MediaSessionSessionToken を作成します。Activity または FragmentonStart() メソッドが適しています。

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 を使用

MediaControllerPlayer インターフェースを実装しているため、インターフェースで定義されたコマンドを使用して、接続された MediaSession の再生を制御できます。つまり、MediaControllerplay() を呼び出すと、接続された 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 または FragmentonStop() メソッドなど、不要になったら 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 メソッドは、アイコン、位置、目的のアクションとともに表示するボタンの明確なリストを提供します。