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

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

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

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

MediaLibraryService बनाना

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

Kotlin

class PlaybackService : MediaLibraryService() {
  private var mediaLibrarySession: MediaLibrarySession? = null
  private val callback: MediaLibrarySession.Callback =
    object : MediaLibrarySession.Callback {
      /* ... */
    }

  override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaLibrarySession? {
    // 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 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();
  }
}
मेनिफ़ेस्ट फ़ाइल में, Service और ज़रूरी अनुमतियों का एलान करना न भूलें:

<service
    android:name=".PlaybackService"
    android:foregroundServiceType="mediaPlayback"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaLibraryService"/>
        <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" />

हमारी सलाह है कि अपनी सेवा को प्लैटफ़ॉर्म और Media3 सेवा इंटरफ़ेस, दोनों के तौर पर रजिस्टर करें:

  • प्लैटफ़ॉर्म मीडिया सेशन एपीआई का इस्तेमाल करने वाले क्लाइंट के साथ काम करने के लिए, यह सुझाव दिया जाता है कि <action android:name="android.media.browse.MediaBrowserService"/> को intent-filter एलिमेंट में शामिल करें. Media3, इस सेवा इंटरफ़ेस के साथ अपने-आप बैकवर्ड कंपैटिबिलिटी उपलब्ध कराता है.

  • भविष्य के लिए तैयार सेटअप के तौर पर और यह पक्का करने के लिए कि Media3 का इस्तेमाल करने वाले ऐप्लिकेशन, Media3 API का इस्तेमाल करके आपकी सेवा से कनेक्ट हो सकें, <action android:name="androidx.media3.session.MediaLibraryService"/> प्लैटफ़ॉर्म के विकल्प के साथ-साथ उपलब्ध कराया जाना चाहिए.

इससे ऐप्लिकेशन, PackageManager के ज़रिए आपकी सेवा ढूंढ सकते हैं. साथ ही, इनमें से किसी भी इंटरफ़ेस के ज़रिए, MediaBrowser से कनेक्ट हो सकते हैं.

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

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

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

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

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

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

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

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

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

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

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

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

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

Kotlin

override fun onGetItem(
  session: MediaLibrarySession,
  browser: MediaSession.ControllerInfo,
  mediaId: String,
): ListenableFuture<LibraryResult<MediaItem>> {
  val settableFuture = SettableFuture.create<LibraryResult<MediaItem>>()

  val maxCommandsForMediaItems = browser.maxCommandsForMediaItems
  loadMediaItemAsync(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;
}

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

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

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

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

Kotlin

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

Java

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

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

Kotlin

val commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem)

Java

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

Kotlin

val future =
  controller.sendCustomCommand(
    requireNotNull(addToPlaylistButton.sessionCommand),
    mediaItem,
    Bundle.EMPTY,
  )

Java

ListenableFuture<SessionResult> future =
    controller.sendCustomCommand(
        checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);