Esistono due modi per connettersi a un'app multimediale:
MediaControllerMediaBrowser
MediaController
Un controller multimediale interagisce con una sessione multimediale per eseguire query e controllare la riproduzione di un'app multimediale. In Media3, l'API MediaController implementa l'interfaccia Player. Ecco alcuni esempi di app client che utilizzano un controller multimediale:
- Controlli multimediali del sistema Android
- App complementare Android Wear OS
- Android Auto e Android Automotive OS
- Assistenti vocali, come l'Assistente Google
- L'app Media Controller Test
Un controller multimediale può essere utile anche all'interno di un'app multimediale, ad esempio se il player e la sessione multimediale si trovano in un Service separato da Activity o Fragment con l'UI.
Crea un MediaController
Per creare un MediaController, inizia creando un SessionToken per il MediaSession corrispondente. Il metodo onStart() di Activity o Fragment può essere un buon punto di partenza.
Kotlin
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
Java
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, PlaybackService.class));
Utilizzando questo SessionToken per creare un MediaController, il controller viene connesso alla sessione specificata. Questa operazione viene eseguita in modo asincrono, quindi devi ascoltare il risultato e utilizzarlo quando è disponibile.
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());
Utilizza un MediaController
MediaController implementa l'interfaccia Player, quindi puoi utilizzare i comandi definiti nell'interfaccia per controllare la riproduzione del MediaSession connesso.
Ciò significa che la chiamata di play() su un MediaController invierà il comando al MediaSession connesso, che successivamente delegherà il comando al Player sottostante.
Puoi aggiungere un Player.Listener al controller per rilevare le modifiche allo stato di Player. Per maggiori dettagli sull'utilizzo di un Player.Listener, consulta la guida Eventi di Player.
L'interfaccia MediaController.Listener definisce callback aggiuntivi per gli eventi
e i comandi personalizzati della MediaSession connessa. Ad esempio,
onCustomCommand() quando la sessione invia un comando personalizzato,
onAvailableSessionCommandsChanged() quando la sessione modifica i comandi di sessione
disponibili o onDisconnected() quando il controller viene disconnesso
dalla sessione.
Puoi impostare MediaController.Listener durante la creazione del controller con
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();
Come per gli altri componenti, ricordati di rilasciare MediaController quando non è più necessario, ad esempio nel metodo onStop() di un Activity o Fragment.
Kotlin
MediaController.releaseFuture(controllerFuture)
Java
MediaController.releaseFuture(controllerFuture);
Il rilascio del controller continuerà a inviare tutti i comandi in attesa inviati alla sessione e si scollegherà dal servizio di sessione solo dopo che questi comandi saranno stati gestiti o dopo un periodo di timeout, a seconda di quale condizione si verifica per prima.
MediaBrowser
Un MediaBrowser si basa sulle funzionalità offerte da un
MediaController per consentire anche la navigazione nella raccolta multimediale offerta dal MediaLibraryService di un'app
multimediale.
Crea un 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());
Utilizza un MediaBrowser
Per iniziare a sfogliare la raccolta di contenuti dell'app multimediale, recupera prima il nodo principale con 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());
Puoi quindi navigare nella raccolta multimediale recuperando gli elementi secondari di un
MediaItem nella raccolta con getChildren(). Ad esempio, per recuperare i nodi secondari del nodo principale 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());
Visualizza i controlli di riproduzione per un'altra app multimediale
Quando mostri i controlli UI con i pulsanti per un'altra app multimediale, è importante seguire le preferenze dei pulsanti multimediali dichiarate di quell'app.
Per risolvere le preferenze dell'app con i vincoli e i requisiti della tua UI, utilizza CommandButton.DisplayConstraints. Puoi definire i limiti e le restrizioni della tua UI e il metodo resolve() fornisce un elenco preciso di pulsanti da visualizzare con la relativa icona, posizione e azione prevista. Se un utente fa clic su uno di questi pulsanti, puoi utilizzare CommandButton.executeAction per attivare l'azione associata nell'app multimediale.
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)); }