MediaLibraryService ile içerik sunma

Medya uygulamaları genellikle hiyerarşik olarak düzenlenmiş medya öğeleri koleksiyonları içerir. Örneğin, bir albümdeki şarkılar veya bir oynatma listesindeki TV bölümleri. Bu medya öğeleri hiyerarşisine medya kitaplığı adı verilir.

Hiyerarşik olarak düzenlenmiş medya içeriği örnekleri
Şekil 1: Medya kitaplığı oluşturan medya öğesi hiyerarşilerine ilişkin örnekler.

MediaLibraryService, medya kitaplığınıza hizmet vermek ve erişmek için standartlaştırılmış bir API sağlar. Örneğin, medya kitaplığınız için sürücü güvenli kullanıcı arayüzü sağlayan medya uygulamanıza Android Auto desteği eklerken bu özellikten yararlanabilirsiniz.

MediaLibraryService oluşturma

MediaLibraryService uygulamak, MediaSessionService uygulamaya benzer. Tek fark, onGetSession() yönteminde MediaSession yerine MediaLibrarySession döndürmeniz gerektiğidir.

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

Manifest dosyasında Service ve gerekli izinlerinizi de belirtmeyi unutmayın:

<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 kullanın

MediaLibraryService API, medya kitaplığınızın tek bir kök düğüm ve oynatılabilir ya da daha fazla göz atılabilir alt düğümlerle birlikte ağaç biçiminde yapılandırılmasını bekler.

MediaLibrarySession, içeriklere göz atma API'leri eklemek için MediaSession API'sini genişletir. MediaSession geri çağırma ile karşılaştırıldığında, MediaLibrarySession geri çağırma aşağıdaki gibi yöntemler ekler:

  • onGetLibraryRoot() Bir istemci, içerik ağacının MediaItem kökünü istediğinde
  • onGetChildren() Bir istemci, içerik ağacında MediaItem öğesinin alt öğelerini istediğinde
  • onGetSearchResult() Bir istemci, belirli bir sorgu için içerik ağacından arama sonuçları istediğinde

İlgili geri çağırma yöntemleri, bir istemci uygulamasının ilgilendiği içerik ağacı türüyle ilgili ek sinyaller içeren bir LibraryParams nesnesi içerir.

Medya öğeleri için komut düğmeleri

Bir oturum uygulaması, MediaItem içinde MediaMetadata tarafından desteklenen komut düğmelerini bildirebilir. Bu, bir denetleyicinin görüntüleyebileceği ve öğe için özel komutu oturuma göndermek üzere kullanabileceği bir medya öğesine bir veya daha fazla CommandButton girişi atamanıza olanak tanır.

Oturum tarafında kurulum komutu düğmeleri

Oturum oluşturulurken oturum uygulaması, oturumun özel komut olarak işleyebileceği komut düğmeleri grubunu bildirir:

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

Bir medya öğesi oluştururken oturum uygulaması, oturum oluşturulurken ayarlanan komut düğmelerinin oturum komutlarına referans veren bir dizi desteklenen komut kimliği ekleyebilir:

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

Bir kontrol cihazı veya tarayıcı bağlandığında ya da oturumun başka bir yöntemini çağırdığında Callback, oturum uygulaması, bir kontrol cihazının veya tarayıcının görüntüleyebileceği maksimum komut düğmesi sayısını almak için geri çağırmaya iletilen ControllerInfo değerini inceleyebilir. Bir geri çağırma yöntemine iletilen ControllerInfo, bu değere kolayca erişmek için bir alıcı sağlar. Varsayılan olarak değer 0'a ayarlanır. Bu değer, tarayıcının veya denetleyicinin bu özelliği desteklemediğini gösterir:

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

Bir medya öğesi için gönderilen özel bir işlem işlenirken oturum uygulaması, Bundle içine iletilen bağımsız değişkenlerden medya öğesi kimliğini alabilir: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);
}

Komut düğmelerini tarayıcı veya kumanda olarak kullanma

MediaController tarafında, bir uygulama MediaController veya MediaBrowser oluştururken bir medya öğesi için desteklediği maksimum komut düğmesi sayısını bildirebilir:

Kotlin

val browserFuture =
  MediaBrowser.Builder(context, sessionToken)
    .setMaxCommandsForMediaItems(3)
    .buildAsync()

Java

ListenableFuture<MediaBrowser> browserFuture =
    new MediaBrowser.Builder(context, sessionToken)
        .setMaxCommandsForMediaItems(3)
        .buildAsync();

Oturuma bağlandığında kontrol uygulaması, medya öğesi tarafından desteklenen ve kontrol cihazının oturum uygulaması tarafından verilen kullanılabilir komut iznine sahip olduğu komut düğmelerini alabilir:

Kotlin

val commandButtonsForMediaItem: List<CommandButton> =
  controller.getCommandButtonsForMediaItem(mediaItem)

Java

ImmutableList<CommandButton> commandButtonsForMediaItem =
    controller.getCommandButtonsForMediaItem(mediaItem);

Kolaylık sağlamak için MediaController, MediaController.sendCustomCommand(SessionCommand, MediaItem, Bundle) ile medya öğesine özel özel komutlar gönderebilir:

Kotlin

controller.sendCustomCommand(addToPlaylistButton.sessionCommand!!, mediaItem, Bundle.EMPTY)

Java

controller.sendCustomCommand(
    checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);