Połącz z aplikacją do multimediów

Z aplikacją do multimediów możesz się połączyć na 2 sposoby:

  1. MediaController
  2. MediaBrowser

MediaController

Kontroler multimediów wchodzi w interakcję z sesją multimedialną, aby wysyłać zapytania i sterować odtwarzaniem w aplikacji do multimediów. W Media3 interfejs API MediaController implementuje interfejs Player. Przykłady aplikacji klienckich, które używają kontrolera multimediów:

Kontroler multimediów może być też przydatny w aplikacji do multimediów, np. jeśli odtwarzacz i sesja multimedialna znajdują się w Service oddzielnym od Activity lub Fragment z interfejsem.

Utwórz MediaController

Aby utworzyć MediaController, zacznij od utworzenia SessionToken dla odpowiedniego MediaSession. Dobrym miejscem na to może być metoda onStart() obiektu Activity lub Fragment.

Kotlin

val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))

Java

SessionToken sessionToken =
    new SessionToken(context, new ComponentName(context, PlaybackService.class));

Użycie tego SessionToken do utworzenia MediaController łączy kontroler z daną sesją. Odbywa się to asynchronicznie, więc musisz poczekać na wynik i użyć go, gdy będzie dostępny.

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());

Użyj MediaController

MediaController implementuje interfejs Player, dzięki czemu możesz używać poleceń zdefiniowanych w interfejsie do sterowania odtwarzaniem na połączonym urządzeniu MediaSession. Oznacza to, że wywołanie play() na MediaController spowoduje wysłanie polecenia do połączonego MediaSession, który następnie przekaże polecenie do powiązanego Player.

Możesz dodać Player.Listener do kontrolera, aby monitorować zmiany stanu Player. Więcej informacji o korzystaniu z Player.Listener znajdziesz w przewodniku po zdarzeniach odtwarzacza.

Interfejs MediaController.Listener definiuje dodatkowe wywołania zwrotne dla zdarzeń i poleceń niestandardowych z połączonego MediaSession. Przykłady: onCustomCommand(), gdy sesja wysyła polecenie niestandardowe, onAvailableSessionCommandsChanged(), gdy sesja zmienia dostępne polecenia sesji, lub onDisconnected(), gdy kontroler jest odłączony od sesji.

MediaController.Listener można ustawić podczas tworzenia kontrolera za pomocą 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();

Podobnie jak w przypadku innych komponentów pamiętaj, aby zwolnić obiekt MediaController, gdy nie jest już potrzebny, np. w metodzie onStop() obiektu Activity lub Fragment.

Kotlin

MediaController.releaseFuture(controllerFuture)

Java

MediaController.releaseFuture(controllerFuture);

Zwolnienie kontrolera spowoduje dostarczenie wszystkich oczekujących poleceń wysłanych do sesji i odłączenie od usługi sesji dopiero po obsłużeniu tych poleceń lub po upływie limitu czasu (w zależności od tego, co nastąpi wcześniej).

MediaBrowser

MediaBrowser rozszerza możliwości oferowane przez MediaController, umożliwiając też przeglądanie biblioteki multimediów oferowanej przez MediaLibraryService aplikacji do multimediów.

Utwórz 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());

Użyj MediaBrowser

Aby rozpocząć przeglądanie biblioteki treści aplikacji do multimediów, najpierw pobierz węzeł główny za pomocą 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());

Następnie możesz poruszać się po bibliotece multimediów, pobierając elementy podrzędne MediaItem w bibliotece za pomocą getChildren(). Aby na przykład pobrać elementy podrzędne węzła głównego 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());

Wyświetlanie elementów sterujących odtwarzaniem w przypadku innej aplikacji do multimediów

Podczas wyświetlania elementów sterujących interfejsu z przyciskami innej aplikacji do multimediów ważne jest, aby przestrzegać zadeklarowanych ustawień przycisków multimediów tej aplikacji.

Aby dostosować preferencje aplikacji do ograniczeń i wymagań interfejsu, użyj CommandButton.DisplayConstraints. Możesz określić limity i ograniczenia interfejsu, a metoda resolve() udostępnia listę przycisków do wyświetlenia wraz z ich ikoną, pozycją i zamierzonym działaniem. Jeśli użytkownik kliknie jeden z tych przycisków, możesz użyć CommandButton.executeAction, aby wywołać powiązane działanie w aplikacji do multimediów.

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));
}