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