連線至媒體應用程式

媒體控制器會與媒體工作階段互動,查詢及控制媒體應用程式的播放作業。在 Media3 中,MediaController API 會實作 Player 介面。使用媒體控制器的用戶端應用程式範例包括:

媒體控制器在媒體應用程式中也很有用,舉例來說,如果播放器和媒體工作階段位於 Service 與 UI 或 Fragment 不同的位置,媒體控制器就派得上用場。Activity

建立 MediaController

如要建立 MediaController,請先為對應的 MediaSession 建立 SessionTokenActivityFragmentonStart() 方法是個不錯的選擇。

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();

與其他元件一樣,請記得在不再需要 MediaController 時釋放該物件,例如在 ActivityFragmentonStop() 方法中。

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 方法會提供明確的按鈕清單,顯示按鈕的圖示、位置和預期動作。