Aplikację do multimediów można połączyć na 2 sposoby:
MediaControllerMediaBrowser
MediaController
Kontroler multimediów wchodzi w interakcję z sesją multimedialną, aby wysyłać zapytania i sterować odtwarzaniem w aplikacji multimedialnej. W Media3 interfejs API MediaController implementuje interfejs Player. Przykłady aplikacji klienckich, które używają kontrolera multimediów:
- elementy sterujące multimediami w systemie Android,
- aplikacja towarzysząca na Wear OS,
- Android Auto i Automotive OS,
- asystenci głosowi, np. Asystent Google
- aplikacja Media Controller Test.
Opcje sterowania multimediami mogą być też przydatne w aplikacji do multimediów, np. jeśli odtwarzacz i sesja multimedialna znajdują się w Service oddzielnym od Activity lub Fragment z interfejsem.
Tworzenie MediaController
Aby utworzyć MediaController, zacznij od utworzenia SessionToken dla odpowiedniej MediaSession. Dobrym miejscem na to może być metoda onStart() w Activity lub Fragment.
Kotlin
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
Java
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, PlaybackService.class));
Użycie tego SessionToken do utworzenia MediaController łączy kontroler z daną sesją. Odbywa się to asynchronicznie, więc musisz nasłuchiwać wyniku i użyć go, gdy będzie dostępny.
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());
Używanie MediaController
MediaController implementuje interfejs Player, więc możesz używać poleceń zdefiniowanych w tym interfejsie do sterowania odtwarzaniem w połączonej MediaSession.
Oznacza to, że wywołanie play() w MediaController spowoduje wysłanie polecenia do połączonej MediaSession, która następnie przekaże to polecenie do bazowego Player.
Możesz dodać Player.Listener do kontrolera, aby nasłuchiwać zmian stanu
Player. Więcej informacji o używaniu
Player.Listener znajdziesz w przewodniku po zdarzeniach odtwarzacza Player events.
Interfejs MediaController.Listener definiuje dodatkowe wywołania zwrotne dla zdarzeń i poleceń niestandardowych z połączonej MediaSession. Przykłady to
onCustomCommand(), gdy sesja wysyła polecenie niestandardowe,
onAvailableSessionCommandsChanged(), gdy sesja zmienia dostępne
polecenia sesji, lub onDisconnected(), gdy kontroler zostanie odłączony
od sesji.
Element MediaController.Listener można ustawić podczas tworzenia kontrolera za pomocą 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();
Podobnie jak w przypadku innych komponentów, pamiętaj, aby zwolnić MediaController, gdy nie jest już potrzebny, np. w metodzie onStop() w Activity lub Fragment.
Kotlin
MediaController.releaseFuture(controllerFuture)
Java
MediaController.releaseFuture(controllerFuture);
Zwolnienie kontrolera spowoduje dostarczenie wszystkich oczekujących poleceń wysłanych do sesji i odłączenie od usługi sesji dopiero po obsłużeniu tych poleceń lub po upływie limitu czasu (w zależności od tego, co nastąpi wcześniej).
MediaBrowser
MediaBrowser wykorzystuje możliwości oferowane przez MediaController, aby umożliwić przeglądanie biblioteki multimediów oferowanej przez MediaLibraryService aplikacji multimedialnej.
Tworzenie 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());
Używanie MediaBrowser
Aby rozpocząć przeglądanie biblioteki treści aplikacji multimedialnej, najpierw pobierz węzeł główny za pomocą 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());
Następnie możesz poruszać się po bibliotece multimediów, pobierając elementy podrzędne MediaItem w bibliotece za pomocą getChildren(). Aby na przykład pobrać elementy podrzędne węzła głównego 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());
Wyświetlanie elementów sterujących odtwarzaniem innej aplikacji do multimediów
Podczas wyświetlania elementów sterujących interfejsu z przyciskami dla innej aplikacji do multimediów ważne jest, aby przestrzegać zadeklarowanych preferencji dotyczących przycisków multimediów w tej aplikacji.
Aby rozwiązać preferencje aplikacji z ograniczeniami i wymaganiami interfejsu, użyj CommandButton.DisplayConstraints. Możesz zdefiniować limity i
ograniczenia interfejsu, a metoda resolve()udostępni konkretną listę przycisków do wyświetlenia wraz z ich ikoną, pozycją i
zamierzonym działaniem. Jeśli użytkownik kliknie jeden z tych przycisków, możesz użyć CommandButton.executeAction, aby wywołać powiązane działanie w aplikacji multimedialnej.
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)); }