MediaLibraryService के साथ कॉन्टेंट दिखाएं

मीडिया ऐप्लिकेशन में अक्सर मीडिया आइटम के कलेक्शन होते हैं, जिन्हें हैरारकी के हिसाब से व्यवस्थित किया जाता है. उदाहरण के लिए, किसी एल्बम में मौजूद गाने या प्लेलिस्ट में मौजूद टीवी शो के एपिसोड. मीडिया आइटम के इस क्रम को मीडिया लाइब्रेरी कहा जाता है.

हैरारकी में व्यवस्थित किए गए मीडिया कॉन्टेंट के उदाहरण
पहली इमेज: मीडिया लाइब्रेरी बनाने वाले मीडिया आइटम की हैरारकी के उदाहरण.

MediaLibraryService, आपकी मीडिया लाइब्रेरी को दिखाने और ऐक्सेस करने के लिए, स्टैंडर्ड एपीआई उपलब्ध कराता है. उदाहरण के लिए, अपने मीडिया ऐप्लिकेशन में Android Auto के साथ काम करने की सुविधा जोड़ते समय, यह जानकारी मददगार हो सकती है. यह सुविधा, आपकी मीडिया लाइब्रेरी के लिए ड्राइवर के हिसाब से यूज़र इंटरफ़ेस (यूआई) उपलब्ध कराती है.

MediaLibraryService बनाना

MediaLibraryService को लागू करना, MediaSessionService को लागू करने जैसा ही है. हालांकि, onGetSession() तरीके में आपको MediaSession के बजाय MediaLibrarySession दिखाना चाहिए.

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

मेनिफ़ेस्ट फ़ाइल में, अपने Service और ज़रूरी अनुमतियों के बारे में भी बताना न भूलें:

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaSessionService"/>
    </intent-filter>
</service>

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- For targetSdk 34+ -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />

MediaLibrarySession का इस्तेमाल करना

MediaLibraryService एपीआई को उम्मीद है कि आपकी मीडिया लाइब्रेरी, ट्री फ़ॉर्मैट में होगी. इसमें एक रूट नोड और चाइल्ड नोड होंगे, जिन्हें चलाया या ब्राउज़ किया जा सकता है.

कॉन्टेंट ब्राउज़ करने वाले एपीआई जोड़ने के लिए, MediaLibrarySession MediaSession एपीआई को बढ़ाता है. MediaSession कॉलबैक की तुलना में, MediaLibrarySession कॉलबैक में ये तरीके जोड़े गए हैं:

  • onGetLibraryRoot() जब कोई क्लाइंट, कॉन्टेंट ट्री के रूट MediaItem का अनुरोध करता है, तब
  • onGetChildren() जब कोई क्लाइंट, कॉन्टेंट ट्री में MediaItem के बच्चों का अनुरोध करता है, तब
  • onGetSearchResult() जब कोई क्लाइंट किसी क्वेरी के लिए कॉन्टेंट ट्री से खोज के नतीजों का अनुरोध करता है

काम के कॉलबैक तरीकों में, LibraryParams ऑब्जेक्ट शामिल होगा. इसमें, उस कॉन्टेंट ट्री के बारे में अतिरिक्त सिग्नल होंगे जिसमें क्लाइंट ऐप्लिकेशन की दिलचस्पी है.

मीडिया आइटम के लिए कमांड बटन

कोई सेशन ऐप्लिकेशन, MediaMetadata में MediaItem के साथ काम करने वाले कमांड बटन का एलान कर सकता है. इससे किसी मीडिया आइटम को एक या उससे ज़्यादा CommandButton एंट्री असाइन की जा सकती हैं. कंट्रोलर, इन एंट्री को आसानी से दिखा सकता है और इनका इस्तेमाल करके, सेशन में आइटम के लिए कस्टम कमांड भेज सकता है.

सेशन साइड पर कमांड बटन सेट अप करना

सेशन बनाते समय, सेशन ऐप्लिकेशन उन कमांड बटन के सेट का एलान करता है जिन्हें सेशन, कस्टम कमांड के तौर पर मैनेज कर सकता है:

KotlinJava
val allCommandButtons =
  listOf(
    CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD)
      .setDisplayName(context.getString(R.string.add_to_playlist))
      .setDisplayName("Add to playlist")
      .setIconResId(R.drawable.playlist_add)
      .setSessionCommand(SessionCommand(COMMAND_PLAYLIST_ADD, Bundle.EMPTY))
      .setExtras(playlistAddExtras)
      .build(),
    CommandButton.Builder(CommandButton.ICON_RADIO)
      .setDisplayName(context.getString(R.string.radio_station))
      .setIconResId(R.drawable.radio)
      .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()
ImmutableList<CommandButton> allCommandButtons =
    ImmutableList.of(
        new CommandButton.Builder(CommandButton.ICON_PLAYLIST_ADD)
            .setDisplayName("Add to playlist")
            .setIconUri(Uri.parse("http://www.example.com/icon/playlist_add"))
            .setSessionCommand(new SessionCommand(COMMAND_PLAYLIST_ADD, Bundle.EMPTY))
            .setExtras(playlistAddExtras)
            .build(),
        new CommandButton.Builder(CommandButton.ICON_RADIO)
            .setDisplayName("Radio station")
            .setIconUri(Uri.parse("http://www.example.com/icon/radio"))
            .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();

मीडिया आइटम बनाते समय, सेशन ऐप्लिकेशन उन कमांड आईडी का एक सेट जोड़ सकता है जो काम करते हैं. ये कमांड आईडी, सेशन बनाते समय सेट अप किए गए कमांड बटन के सेशन कमांड का रेफ़रंस देते हैं:

KotlinJava
val mediaItem =
  MediaItem.Builder()
    .setMediaMetadata(
      MediaMetadata.Builder()
        .setSupportedCommands(listOf(COMMAND_PLAYLIST_ADD, COMMAND_RADIO))
        .build())
    .build()
MediaItem mediaItem =
    new MediaItem.Builder()
        .setMediaMetadata(
            new MediaMetadata.Builder()
                .setSupportedCommands(ImmutableList.of(COMMAND_PLAYLIST_ADD, COMMAND_RADIO))
                .build())
        .build();

जब कोई कंट्रोलर या ब्राउज़र, सेशन Callback के किसी दूसरे तरीके से कनेक्ट होता है या उसे कॉल करता है, तो सेशन ऐप्लिकेशन, कॉलबैक में पास किए गए ControllerInfo की जांच कर सकता है. इससे, कंट्रोलर या ब्राउज़र के ज़रिए दिखाए जा सकने वाले कमांड बटन की ज़्यादा से ज़्यादा संख्या का पता चलता है. कॉलबैक तरीके में पास की गई ControllerInfo, इस वैल्यू को आसानी से ऐक्सेस करने के लिए एक 'गेटर' उपलब्ध कराती है. डिफ़ॉल्ट रूप से, वैल्यू 0 पर सेट होती है. इससे पता चलता है कि ब्राउज़र या कंट्रोलर में यह सुविधा काम नहीं करती:

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

किसी मीडिया आइटम के लिए भेजी गई कस्टम कार्रवाई को मैनेज करते समय, सेशन ऐप्लिकेशन, Bundle में पास किए गए आर्ग्युमेंट onCustomCommand से मीडिया आइटम आईडी पा सकता है:

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

कमांड बटन को ब्राउज़र या कंट्रोलर के तौर पर इस्तेमाल करना

MediaController साइड पर, कोई ऐप्लिकेशन MediaController या MediaBrowser बनाते समय, किसी मीडिया आइटम के लिए कमांड बटन की ज़्यादा से ज़्यादा संख्या का एलान कर सकता है:

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

सेशन से कनेक्ट होने पर, कंट्रोलर ऐप्लिकेशन को ऐसे कंट्रोल बटन मिल सकते हैं जो मीडिया आइटम के साथ काम करते हैं और जिनके लिए कंट्रोलर के पास सेशन ऐप्लिकेशन से मिले उपलब्ध निर्देश हैं:

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

MediaController, MediaController.sendCustomCommand(SessionCommand, MediaItem, Bundle) की मदद से मीडिया आइटम के लिए कस्टम निर्देश भेज सकता है, ताकि आपको आसानी हो:

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