Подключиться к мультимедийному приложению можно двумя способами:
MediaControllerMediaBrowser
MediaController
Медиаконтроллер взаимодействует с медиасеансом, чтобы запрашивать информацию о воспроизведении в медиаприложении и управлять им. В Media3 API MediaController реализует интерфейс Player. Примеры клиентских приложений, использующих контроллер мультимедиа:
- Системные элементы управления мультимедиа Android
- Сопутствующее приложение для Android Wear OS
- Android Auto и Automotive OS
- Голосовые помощники, например Google Ассистент.
- Тестовое приложение Media Controller
Контроллер мультимедиа также может быть полезен в мультимедийном приложении, например если
проигрыватель и сеанс мультимедиа находятся в 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)); }