Подключиться к мультимедийному приложению можно двумя способами:
MediaControllerMediaBrowser
MediaController
Контроллер мультимедиа взаимодействует с сеансом мультимедиа, чтобы запрашивать и контролировать воспроизведение мультимедийного приложения. В Media3 API MediaController реализует интерфейс Player. Примеры клиентских приложений, использующих контроллер мультимедиа:
- Системные элементы управления мультимедиа в Android
- Сопутствующее приложение для Android Wear OS
- Android Auto и Android Automotive OS
- Голосовые помощники, например Google Ассистент.
- Приложение Media Controller Test
Контроллер также может быть полезен в мультимедийном приложении, например если проигрыватель и сеанс мультимедиа находятся в Service отдельно от Activity или Fragment с пользовательским интерфейсом.
Создать MediaController
Чтобы создать MediaController, сначала создайте SessionToken для соответствующего MediaSession. Для этого можно использовать метод onStart() в Activity или Fragment.
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.
Это означает, что вызов play() для MediaController отправит команду подключенному MediaSession, который затем делегирует команду своему базовому Player.
Вы можете добавить в контроллер Player.Listener, чтобы отслеживать изменения состояния Player. Подробную информацию об использовании Player.Listener можно найти в руководстве События игрока.
Интерфейс MediaController.Listener определяет дополнительные обратные вызовы для событий и специальных команд из подключенного MediaSession. Например, onCustomCommand(), когда сеанс отправляет специальную команду, onAvailableSessionCommandsChanged(), когда сеанс меняет доступные команды, или onDisconnected(), когда контроллер отключается от сеанса.
Объект MediaController.Listener можно задать при создании контроллера с помощью Builder:
Kotlin
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.
Kotlin
MediaController.releaseFuture(controllerFuture)
Java
MediaController.releaseFuture(controllerFuture);
При освобождении контроллера все ожидающие команды будут отправлены в сеанс, а отмена привязки к сервису сеанса произойдет только после обработки этих команд или по истечении времени ожидания (в зависимости от того, что произойдет раньше).
MediaBrowser
MediaBrowser расширяет возможности MediaController, позволяя просматривать медиатеку, которую предоставляет MediaLibraryService мультимедийного приложения.
Создать MediaBrowser
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());
Используйте MediaBrowser
Чтобы начать просмотр библиотеки контента мультимедийного приложения, сначала получите корневой узел с помощью 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());
Как показать элементы управления воспроизведением для другого мультимедийного приложения
При показе элементов управления пользовательского интерфейса с кнопками для другого мультимедийного приложения важно следовать объявленным настройкам кнопок мультимедиа этого приложения.
Чтобы согласовать настройки приложения с ограничениями и требованиями пользовательского интерфейса, используйте CommandButton.DisplayConstraints. Вы можете определить ограничения для своего интерфейса, а метод resolve() предоставляет определенный список кнопок для отображения с их значком, положением и предполагаемым действием. Если пользователь нажимает одну из этих кнопок, вы можете использовать CommandButton.executeAction, чтобы запустить связанное действие в мультимедийном приложении.
Kotlin
// 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)); }