Le app multimediali spesso contengono raccolte di elementi multimediali, organizzati in una gerarchia. Ad esempio, i brani di un album o le puntate di un programma TV in una playlist. Questa gerarchia di elementi multimediali è nota come raccolta multimediale.
Un MediaLibraryService
fornisce un'API standardizzata per pubblicare e accedere alla tua biblioteca multimediale. Ciò può essere utile, ad esempio, quando aggiungi il supporto di Android Auto alla tua app multimediale, che fornisce la propria UI sicura per il conducente per la tua raccolta multimediale.
Creare un MediaLibraryService
L'implementazione di un MediaLibraryService
è simile all'implementazione di un MediaSessionService
,
ma nel metodo onGetSession()
devi
restituire un MediaLibrarySession
anziché un MediaSession
.
Kotlin
class PlaybackService : MediaLibraryService() { var mediaLibrarySession: MediaLibrarySession? = null var callback: MediaLibrarySession.Callback = object : MediaLibrarySession.Callback {...} // If desired, validate the controller before returning the media library session override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaLibrarySession? = mediaLibrarySession // Create your player and media library session in the onCreate lifecycle event override fun onCreate() { super.onCreate() val player = ExoPlayer.Builder(this).build() mediaLibrarySession = MediaLibrarySession.Builder(this, player, callback).build() } // Remember to release the player and media library session in onDestroy override fun onDestroy() { mediaLibrarySession?.run { player.release() release() mediaLibrarySession = null } super.onDestroy() } }
Java
class PlaybackService extends MediaLibraryService { MediaLibrarySession mediaLibrarySession = null; MediaLibrarySession.Callback callback = new MediaLibrarySession.Callback() {...}; @Override public MediaLibrarySession onGetSession(MediaSession.ControllerInfo controllerInfo) { // If desired, validate the controller before returning the media library session return mediaLibrarySession; } // Create your player and media library session in the onCreate lifecycle event @Override public void onCreate() { super.onCreate(); ExoPlayer player = new ExoPlayer.Builder(this).build(); mediaLibrarySession = new MediaLibrarySession.Builder(this, player, callback).build(); } // Remember to release the player and media library session in onDestroy @Override public void onDestroy() { if (mediaLibrarySession != null) { mediaLibrarySession.getPlayer().release(); mediaLibrarySession.release(); mediaLibrarySession = null; } super.onDestroy(); } }
Ricordati di dichiarare anche Service
e le autorizzazioni richieste nel file manifest:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- For targetSdk 34+ -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
Utilizza un MediaLibrarySession
L'API MediaLibraryService
prevede che la raccolta multimediale sia strutturata in un formato ad albero, con un singolo nodo principale e nodi secondari che possono essere riprodotti o esplorati ulteriormente.
Un MediaLibrarySession
espande l'API MediaSession
per aggiungere API di navigazione dei contenuti. Rispetto al
callback MediaSession
,
il
callback MediaLibrarySession
aggiunge metodi come:
onGetLibraryRoot()
per quando un cliente richiede la radiceMediaItem
di un albero dei contenutionGetChildren()
per quando un client richiede i figli di unMediaItem
nella struttura ad albero dei contenutionGetSearchResult()
per quando un client richiede risultati di ricerca dall'albero dei contenuti per una determinata query
I metodi di callback pertinenti includeranno un oggetto LibraryParams
con indicatori aggiuntivi sul tipo di albero dei contenuti a cui è interessata un'app client.
Pulsanti di comando per gli elementi multimediali
Un'app di sessione può dichiarare pulsanti di comando supportati da un MediaItem
nel MediaMetadata
. In questo modo è possibile assegnare una o più voci CommandButton
a un elemento multimediale che un controller può visualizzare e utilizzare per inviare il comando personalizzato per l'elemento alla sessione in modo pratico.
Pulsanti di comando di configurazione lato sessione
Quando viene creata, un'app di sessione dichiara l'insieme di pulsanti di comando che una sessione può gestire come comandi personalizzati:
Kotlin
val allCommandButtons = listOf( CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD) .setDisplayName(context.getString(R.string.add_to_playlist)) .setDisplayName("Add to playlist") .setIconResId(R.drawable.playlist_add) .setSessionCommand(SessionCommand(COMMAND_PLAYLIST_ADD, Bundle.EMPTY)) .setExtras(playlistAddExtras) .build(), CommandButton.Builder(CommandButton.ICON_RADIO) .setDisplayName(context.getString(R.string.radio_station)) .setIconResId(R.drawable.radio) .setSessionCommand(SessionCommand(COMMAND_RADIO, Bundle.EMPTY)) .setExtras(radioExtras) .build(), // possibly more here ) // Add all command buttons for media items supported by the session. val session = MediaSession.Builder(context, player) .setCommandButtonsForMediaItems(allCommandButtons) .build()
Java
ImmutableList<CommandButton> allCommandButtons = ImmutableList.of( new CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD) .setDisplayName("Add to playlist") .setIconUri(Uri.parse("http://www.example.com/icon/playlist_add")) .setSessionCommand(new SessionCommand(COMMAND_PLAYLIST_ADD, Bundle.EMPTY)) .setExtras(playlistAddExtras) .build(), new CommandButton.Builder(CommandButton.ICON_RADIO) .setDisplayName("Radio station") .setIconUri(Uri.parse("http://www.example.com/icon/radio")) .setSessionCommand(new SessionCommand(COMMAND_RADIO, Bundle.EMPTY)) .setExtras(radioExtras) .build()); // Add all command buttons for media items supported by the session. MediaSession session = new MediaSession.Builder(context, player) .setCommandButtonsForMediaItems(allCommandButtons) .build();
Quando crea un elemento multimediale, un'app di sessione può aggiungere un insieme di ID comando supportati che fanno riferimento ai comandi di sessione dei pulsanti di comando configurati durante la creazione della sessione:
Kotlin
val mediaItem = MediaItem.Builder() .setMediaMetadata( MediaMetadata.Builder() .setSupportedCommands(listOf(COMMAND_PLAYLIST_ADD, COMMAND_RADIO)) .build()) .build()
Java
MediaItem mediaItem = new MediaItem.Builder() .setMediaMetadata( new MediaMetadata.Builder() .setSupportedCommands(ImmutableList.of(COMMAND_PLAYLIST_ADD, COMMAND_RADIO)) .build()) .build();
Quando un controller o un browser si connette o chiama un altro metodo della sessioneCallback
, l'app della sessione può ispezionare il ControllerInfo
passato al callback per ottenere il numero massimo di pulsanti di comando che un controller o un browser può visualizzare. Il parametro ControllerInfo
passato a un metodo di callback fornisce un metodo getter per accedere comodamente a questo valore. Per impostazione predefinita, il valore è impostato su 0, il che indica che il browser o il controller non supporta questa funzionalità:
Kotlin
override fun onGetItem( session: MediaLibrarySession, browser: MediaSession.ControllerInfo, mediaId: String, ): ListenableFuture<LibraryResult<MediaItem>> { val settableFuture = SettableFuture.create<LibraryResult<MediaItem>>() val maxCommandsForMediaItems = browser.maxCommandsForMediaItems scope.launch { loadMediaItem(settableFuture, mediaId, maxCommandsForMediaItems) } return settableFuture }
Java
@Override public ListenableFuture<LibraryResult<MediaItem>> onGetItem( MediaLibraryService.MediaLibrarySession session, ControllerInfo browser, String mediaId) { SettableFuture<LibraryResult<MediaItem>> settableFuture = SettableFuture.create(); int maxCommandsForMediaItems = browser.getMaxCommandsForMediaItems(); loadMediaItemAsync(settableFuture, mediaId, maxCommandsForMediaItems); return settableFuture; }
Quando gestisce un'azione personalizzata inviata per un elemento multimediale, l'app della sessione può recuperare l'ID elemento multimediale dagli argomenti Bundle
passati a
onCustomCommand
:
Kotlin
override fun onCustomCommand( session: MediaSession, controller: MediaSession.ControllerInfo, customCommand: SessionCommand, args: Bundle, ): ListenableFuture<SessionResult> { val mediaItemId = args.getString(MediaConstants.EXTRA_KEY_MEDIA_ID) return if (mediaItemId != null) handleCustomCommandForMediaItem(controller, customCommand, mediaItemId, args) else handleCustomCommand(controller, customCommand, args) }
Java
@Override public ListenableFuture<SessionResult> onCustomCommand( MediaSession session, ControllerInfo controller, SessionCommand customCommand, Bundle args) { String mediaItemId = args.getString(MediaConstants.EXTRA_KEY_MEDIA_ID); return mediaItemId != null ? handleCustomCommandForMediaItem(controller, customCommand, mediaItemId, args) : handleCustomCommand(controller, customCommand, args); }
Usare i pulsanti di comando come browser o controller
Sul lato MediaController
, un'app può dichiarare il numero massimo di pulsanti di comando supportati per un elemento multimediale durante la creazione del MediaController
o del MediaBrowser
:
Kotlin
val browserFuture = MediaBrowser.Builder(context, sessionToken) .setMaxCommandsForMediaItems(3) .buildAsync()
Java
ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken) .setMaxCommandsForMediaItems(3) .buildAsync();
Quando è connessa alla sessione, l'app del controller può ricevere i pulsanti di comando supportati dall'elemento multimediale e per i quali il controller dispone del comando disponibile concesso dall'app della sessione:
Kotlin
val commandButtonsForMediaItem: List<CommandButton> = controller.getCommandButtonsForMediaItem(mediaItem)
Java
ImmutableList<CommandButton> commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem);
Per comodità, un MediaController
può inviare comandi personalizzati specifici per gli elementi multimediali con MediaController.sendCustomCommand(SessionCommand, MediaItem, Bundle)
:
Kotlin
controller.sendCustomCommand(addToPlaylistButton.sessionCommand!!, mediaItem, Bundle.EMPTY)
Java
controller.sendCustomCommand( checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);