Es gibt zwei Möglichkeiten, eine Verbindung zu einer Medien-App herzustellen:
MediaControllerMediaBrowser
MediaController
Ein Media Controller interagiert mit einer Media Session, um die Wiedergabe einer Medien-App abzufragen und zu steuern. In Media3 implementiert die MediaController API die Player-Schnittstelle. Beispiele für Client-Apps, die einen MediaController verwenden:
- Mediensteuerung des Android-Systems
- Android Wear OS-Companion-App
- Android Auto und Automotive OS
- Sprachassistenten wie Google Assistant
- Test-App für die Mediensteuerung
Ein Media Controller kann auch in einer Medien-App nützlich sein, z. B. wenn sich der Player und die Mediensitzung in einem Service befinden, der sich von der Activity oder dem Fragment mit der Benutzeroberfläche unterscheidet.
MediaController erstellen
Wenn Sie einen MediaController erstellen möchten, müssen Sie zuerst einen SessionToken für den entsprechenden MediaSession erstellen. Die Methode onStart() von Activity oder Fragment kann dafür ein guter Ort sein.
Kotlin
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
Java
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, PlaybackService.class));
Wenn Sie mit diesem SessionToken dann einen MediaController erstellen, wird der Controller mit der angegebenen Sitzung verbunden. Dies geschieht asynchron. Sie sollten also auf das Ergebnis warten und es verwenden, sobald es verfügbar ist.
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());
MediaController verwenden
MediaController implementiert die Player-Schnittstelle, sodass du die in der Schnittstelle definierten Befehle verwenden kannst, um die Wiedergabe des verbundenen MediaSession zu steuern.
Das bedeutet, dass beim Aufrufen von play() für ein MediaController der Befehl an das verbundene MediaSession gesendet wird, das den Befehl dann an das zugrunde liegende Player delegiert.
Sie können dem Controller einen Player.Listener hinzufügen, um auf Änderungen des Player-Status zu reagieren. Weitere Informationen zur Verwendung eines Player.Listener findest du im Leitfaden zu Player-Ereignissen.
Die MediaController.Listener-Schnittstelle definiert zusätzliche Callbacks für Ereignisse und benutzerdefinierte Befehle vom verbundenen MediaSession. Beispiele sind onCustomCommand(), wenn die Sitzung einen benutzerdefinierten Befehl sendet, onAvailableSessionCommandsChanged(), wenn die Sitzung die verfügbaren Sitzungsbefehle ändert, oder onDisconnected(), wenn der Controller von der Sitzung getrennt wird.
Ein MediaController.Listener kann beim Erstellen des Controllers mit einem Builder festgelegt werden:
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();
Wie bei anderen Komponenten auch, müssen Sie den MediaController freigeben, wenn er nicht mehr benötigt wird, z. B. in der Methode onStop() einer Activity oder eines Fragment.
Kotlin
MediaController.releaseFuture(controllerFuture)
Java
MediaController.releaseFuture(controllerFuture);
Wenn der Controller freigegeben wird, werden alle ausstehenden Befehle, die an die Sitzung gesendet wurden, weiterhin zugestellt. Die Bindung an den Sitzungsdienst wird erst aufgehoben, wenn diese Befehle verarbeitet wurden oder ein Zeitlimit abgelaufen ist, je nachdem, was zuerst eintritt.
MediaBrowser
Ein MediaBrowser baut auf den Funktionen eines MediaController auf und ermöglicht auch das Durchsuchen der Mediathek, die von der MediaLibraryService einer Medien-App angeboten wird.
MediaBrowser erstellen
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());
MediaBrowser verwenden
Wenn du die Inhaltsbibliothek der Medien-App durchsuchen möchtest, rufe zuerst den Stammknoten mit getLibraryRoot() ab:
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());
Anschließend kannst du durch die Mediathek navigieren, indem du die untergeordneten Elemente eines MediaItem in der Mediathek mit getChildren() abrufst. So rufen Sie beispielsweise die untergeordneten Elemente des Stammknotens MediaItem ab:
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());
Wiedergabesteuerung für eine andere Medien-App anzeigen
Wenn du UI-Steuerelemente mit Schaltflächen für eine andere Medien-App anzeigst, ist es wichtig, die deklarierten Einstellungen für Medienschaltflächen dieser App zu beachten.
Verwenden Sie CommandButton.DisplayConstraints, um die Einstellungen der App mit den Einschränkungen und Anforderungen Ihrer Benutzeroberfläche abzugleichen. Sie können die Limits und Einschränkungen Ihrer UI definieren. Die Methode resolve() bietet eine Liste von Schaltflächen, die mit ihrem Symbol, ihrer Position und ihrer beabsichtigten Aktion angezeigt werden sollen. Wenn ein Nutzer auf eine dieser Schaltflächen klickt, kannst du mit CommandButton.executeAction die zugehörige Aktion in der Medien-App auslösen.
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)); }