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. Im Vergleich zum MediaSession
-Callback werden dem MediaLibrarySession
-Callback Methoden wie die folgenden hinzugefügt:
onGetLibraryRoot()
wenn ein Client den StammMediaItem
eines Inhaltsbaums anfordertonGetChildren()
wenn ein Client die untergeordneten Elemente vonMediaItem
im 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);