Подключитесь к мультимедийному приложению

Существует два способа подключения к медиаприложению:

  1. MediaController
  2. MediaBrowser

MediaController

Контроллер мультимедиа взаимодействует с медиасессией для запроса и управления воспроизведением медиаприложения. В Media3 API MediaController реализует интерфейс Player . Примеры клиентских приложений, использующих контроллер мультимедиа, включают:

Контроллер мультимедиа также может быть полезен в рамках медиаприложения, например, если плеер и медиасессия находятся в отдельном Service , отличном от Activity или Fragment с пользовательским интерфейсом.

Создайте MediaController

Для создания MediaController начните с создания SessionToken для соответствующей MediaSession . Для этого хорошо подойдет метод onStart() вашей Activity или Fragment .

Котлин

val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))

Java

SessionToken sessionToken =
    new SessionToken(context, new ComponentName(context, PlaybackService.class));

Использование этого SessionToken для создания MediaController подключает контроллер к заданной сессии. Это происходит асинхронно, поэтому вам следует отслеживать результат и использовать его, когда он станет доступен.

Котлин

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 . Это означает, что вызов play() на MediaController отправит команду подключенной MediaSession , которая впоследствии передаст команду своему базовому объекту Player .

Вы можете добавить Player.Listener в контроллер, чтобы отслеживать изменения состояния Player . Более подробную информацию об использовании Player.Listener см. в руководстве по событиям игрока .

Интерфейс MediaController.Listener определяет дополнительные функции обратного вызова для событий и пользовательских команд от подключенной сессии MediaSession . Примерами являются onCustomCommand() , когда сессия отправляет пользовательскую команду, onAvailableSessionCommandsChanged() , когда сессия изменяет доступные команды сессии, или onDisconnected() когда контроллер отключается от сессии.

Объект MediaController.Listener можно установить при создании контроллера с помощью Builder :

Котлин

val controllerFuture =
  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

ListenableFuture<MediaController> controllerFuture =
    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 , когда он больше не нужен, например, в методе onStop() Activity или Fragment .

Котлин

MediaController.releaseFuture(controllerFuture)

Java

MediaController.releaseFuture(controllerFuture);

При освобождении контроллера все ожидающие команды, отправленные в сессию, будут доставлены, и он отсоединится от службы сессии только после обработки этих команд или по истечении периода ожидания, в зависимости от того, что произойдет раньше.

MediaBrowser

Компонент MediaBrowser расширяет возможности MediaController и позволяет также просматривать медиатеку, предоставляемую MediaLibraryService медиаприложения.

Создать MediaBrowser

Котлин

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

Используйте MediaBrowser

Чтобы начать просмотр библиотеки контента медиаприложения, сначала получите корневой узел с помощью getLibraryRoot() :

Котлин

// 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 :

Котлин

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

Отображение элементов управления воспроизведением для другого медиаприложения

При отображении элементов управления пользовательского интерфейса в виде кнопок для другого медиаприложения важно соблюдать заданные в этом приложении параметры кнопок мультимедиа .

Чтобы согласовать настройки приложения с ограничениями и требованиями вашего пользовательского интерфейса, используйте CommandButton.DisplayConstraints . Вы можете определить ограничения и возможности вашего пользовательского интерфейса, а метод resolve предоставляет определенный список кнопок для отображения с их значком, положением и предполагаемым действием. Если пользователь нажимает одну из этих кнопок, вы можете использовать CommandButton.executeAction для запуска соответствующего действия в медиаприложении.

Котлин

// Get media button preferences from media app
val mediaButtonPreferences = controller.getMediaButtonPreferences()
// Declare constraints of UI (example: limit overflow button to one)
val displayConstraints =
  DisplayConstraints.Builder().setMaxButtonsForSlot(CommandButton.SLOT_OVERFLOW, 1).build()
// Resolve media app preferences with constraints
val resolvedButtons = displayConstraints.resolve(mediaButtonPreferences, controller)
// Display buttons in UI
for (button in resolvedButtons) {
  generateUiButton(
    uiPosition = button.slots[0],
    icon = getIconRes(button.icon),
    onClick = { button.executeAction(controller) },
  )
}

Java

// Get media button preferences from media app
List<CommandButton> mediaButtonPreferences = controller.getMediaButtonPreferences();
// Declare constraints of UI (example: limit overflow button to one)
DisplayConstraints displayConstraints =
    new DisplayConstraints.Builder()
        .setMaxButtonsForSlot(CommandButton.SLOT_OVERFLOW, 1)
        .build();
// Resolve media app preferences with constraints
List<CommandButton> resolvedButtons =
    displayConstraints.resolve(mediaButtonPreferences, controller);
// Display buttons in UI
for (CommandButton button : resolvedButtons) {
  generateUiButton(
      /* uiPosition= */ button.slots.get(0),
      /* icon= */ getIconRes(button.icon),
      /* onClick= */ () -> button.executeAction(controller));
}