Media-Apps enthalten häufig Sammlungen von Media-Elementen, die in einer Hierarchie organisiert sind. Das können beispielsweise Titel in einem Album oder Folgen einer Serie in einer Playlist sein. Diese Hierarchie von Medienelementen wird als Mediathek bezeichnet.
MediaLibraryService bietet eine standardisierte API für die Bereitstellung und den Zugriff auf Ihre Mediathek. Das kann beispielsweise hilfreich sein, wenn Sie Ihrer Medien-App Unterstützung für Android Auto hinzufügen, das eine eigene fahrersichere Benutzeroberfläche für Ihre Mediathek bietet.
MediaLibraryService erstellen
Die Implementierung von MediaLibraryService ähnelt der Implementierung von MediaSessionService. In der Methode onGetSession() sollten Sie jedoch MediaLibrarySession anstelle von MediaSession zurückgeben.
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(); } }
Denken Sie daran, dass Sie auch Ihre Service und die erforderlichen Berechtigungen in der Manifestdatei deklarieren müssen:
<service
android:name=".PlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="true">
<intent-filter>
<action android:name="androidx.media3.session.MediaSessionService"/>
<action android:name="android.media.browse.MediaBrowserService"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
MediaLibrarySession verwenden
Die MediaLibraryService API erwartet, dass Ihre Mediathek in einem Baumformat strukturiert ist, mit einem einzelnen Stammknoten und untergeordneten Knoten, die wiedergegeben oder weiter durchsucht werden können.
Eine MediaLibrarySession erweitert die MediaSession API, um APIs zum Durchsuchen von Inhalten hinzuzufügen. Im Vergleich zum MediaSession-Callback werden im MediaLibrarySession-Callback Methoden wie die folgenden hinzugefügt:
onGetLibraryRoot()wenn ein Client den StammMediaItemeines Inhaltsbaums anfordertonGetChildren()wenn ein Client die untergeordneten Elemente vonMediaItemim Inhaltsbaum anfordertonGetSearchResult()wenn ein Kunde Suchergebnisse aus dem Inhaltsbaum für eine bestimmte Anfrage anfordert
Relevante Callback-Methoden enthalten ein LibraryParams-Objekt mit zusätzlichen Signalen zum Typ des Inhaltsbaums, für den sich eine Client-App interessiert.
Befehlsschaltflächen für Medienelemente
Eine Sitzungs-App kann Befehlsschaltflächen deklarieren, die von einem MediaItem im MediaMetadata unterstützt werden. So können einem Media-Element ein oder mehrere CommandButton-Einträge zugewiesen werden, die ein Controller anzeigen und verwenden kann, um den benutzerdefinierten Befehl für das Element auf bequeme Weise an die Sitzung zu senden.
Befehlsschaltflächen auf der Sitzungsseite einrichten
Beim Erstellen der Sitzung deklariert eine Sitzungs-App die Gruppe von Befehlsschaltflächen, die eine Sitzung als benutzerdefinierte Befehle verarbeiten kann:
Kotlin
val allCommandButtons = listOf( CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD) .setDisplayName(context.getString(R.string.add_to_playlist)) .setSessionCommand(SessionCommand(COMMAND_PLAYLIST_ADD, Bundle.EMPTY)) .setExtras(playlistAddExtras) .build(), CommandButton.Builder(CommandButton.ICON_RADIO) .setDisplayName(context.getString(R.string.radio_station)) .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(context.getString(R.string.add_to_playlist)) .setSessionCommand(new SessionCommand(COMMAND_PLAYLIST_ADD, Bundle.EMPTY)) .setExtras(playlistAddExtras) .build(), new CommandButton.Builder(CommandButton.ICON_RADIO) .setDisplayName(context.getString(R.string.radio_station)) .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();
Beim Erstellen eines Media-Elements kann eine Sitzungs-App eine Reihe unterstützter Befehls-IDs hinzufügen, die auf Sitzungsbefehle von Befehlsschaltflächen verweisen, die beim Erstellen der Sitzung eingerichtet wurden:
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();
Wenn ein Controller oder Browser eine Verbindung herstellt oder eine andere Methode der Sitzung Callback aufruft, kann die Sitzungs-App das an den Callback übergebene ControllerInfo prüfen, um die maximale Anzahl von Schaltflächen zu ermitteln, die ein Controller oder Browser anzeigen kann. Die ControllerInfo, die an eine Callback-Methode übergeben wird, bietet einen Getter für den einfachen Zugriff auf diesen Wert. Standardmäßig ist der Wert auf 0 festgelegt. Das bedeutet, dass der Browser oder Controller diese Funktion nicht unterstützt:
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; }
Wenn eine benutzerdefinierte Aktion für ein Media-Element verarbeitet wird, kann die Sitzungs-App die Media-Element-ID aus den Argumenten Bundle abrufen, die an onCustomCommand übergeben werden:
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); }
Befehlsschaltflächen als Browser oder Controller verwenden
Auf der MediaController-Seite kann eine App die maximale Anzahl von Befehlsschaltflächen deklarieren, die sie für ein Media-Element unterstützt, wenn sie die MediaController oder MediaBrowser erstellt:
Kotlin
val browserFuture = MediaBrowser.Builder(context, sessionToken) .setMaxCommandsForMediaItems(3) .buildAsync()
Java
ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken) .setMaxCommandsForMediaItems(3) .buildAsync();
Wenn die Controller-App mit der Sitzung verbunden ist, kann sie die Befehlsschaltflächen empfangen, die vom Media-Element unterstützt werden und für die der Controller die von der Sitzungs-App gewährte verfügbare Berechtigung hat:
Kotlin
val commandButtonsForMediaItem: List<CommandButton> = controller.getCommandButtonsForMediaItem(mediaItem)
Java
ImmutableList<CommandButton> commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem);
Mit MediaController können Sie ganz einfach medienelementspezifische benutzerdefinierte Befehle mit MediaController.sendCustomCommand(SessionCommand, MediaItem, Bundle) senden:
Kotlin
controller.sendCustomCommand(addToPlaylistButton.sessionCommand!!, mediaItem, Bundle.EMPTY)
Java
controller.sendCustomCommand( checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);