غالبًا ما تحتوي تطبيقات الوسائط على مجموعات من عناصر الوسائط منظَّمة في تسلسل هرمي. على سبيل المثال، الأغاني في ألبوم أو حلقات تلفزيونية في قائمة تشغيل يُعرف هذا التسلسل الهرمي لعناصر الوسائط باسم مكتبة الوسائط.
توفّر MediaLibraryService
واجهة برمجة تطبيقات موحّدة لعرض مكتبة الوسائط والوصول إليها. يمكن أن يكون ذلك مفيدًا، على سبيل المثال، عند إضافة إمكانية استخدام Android Auto إلى تطبيق الوسائط، ما يوفّر واجهة مستخدم آمنة للسائق خاصة بمكتبة الوسائط.
إنشاء MediaLibraryService
إنّ تنفيذ MediaLibraryService
يشبه تنفيذ MediaSessionService
،
باستثناء أنّه في طريقة onGetSession()
، عليك عرض MediaLibrarySession
بدلاً من MediaSession
.
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(); } }
تذكَّر أيضًا أنّه عليك الإفصاح عن Service
والأذونات المطلوبة في ملف البيان:
<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
تتوقّع واجهة برمجة التطبيقات MediaLibraryService
أن تكون مكتبة الوسائط منظَّمة بتنسيق شجري، مع عقدة جذرية واحدة وعُقد فرعية قد تكون قابلة للتشغيل أو قابلة للتصفّح.
توسّع MediaLibrarySession
واجهة برمجة التطبيقات MediaSession
لإضافة واجهات برمجة تطبيقات لتصفّح المحتوى. مقارنةً بمعالجة البيانات MediaSession
،
تضيف معالجة البيانات MediaLibrarySession
طُرقًا مثل:
onGetLibraryRoot()
عندما يطلب العميلMediaItem
الجذر لشجرة محتوىonGetChildren()
عندما يطلب عميل عناصر فرعية منMediaItem
في شجرة المحتوىonGetSearchResult()
عندما يطلب عميل نتائج بحث من شجرة المحتوى لاستعلام معيّن
ستتضمّن طرق معاودة الاتصال ذات الصلة عنصر LibraryParams
يحتوي على إشارات إضافية حول نوع شجرة المحتوى التي يهتم بها تطبيق العميل.
أزرار الأوامر لعناصر الوسائط
يمكن لتطبيق الجلسة تحديد أزرار الأوامر المتوافقة مع MediaItem
في MediaMetadata
. يتيح ذلك تعيين إدخال واحد أو أكثر من 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(), // 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();
عند إنشاء عنصر وسائط، يمكن لتطبيق جلسة إضافة مجموعة من أرقام تعريف الأوامر المتوافقة التي تشير إلى أوامر الجلسة الخاصة بأزرار الأوامر التي تم إعدادها عند إنشاء الجلسة:
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 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; }
عند التعامل مع إجراء مخصّص تم إرساله لعنصر وسائط، يمكن لتطبيق الجلسة الحصول على معرّف عنصر الوسائط من الوسيطات Bundle
التي تم تمريرها إلى 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); }
استخدام أزرار الأوامر كمتصفّح أو وحدة تحكّم
على الجانب 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: List<CommandButton> = controller.getCommandButtonsForMediaItem(mediaItem)
Java
ImmutableList<CommandButton> commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem);
لتسهيل الأمر، يمكن أن يرسل MediaController
أوامر مخصّصة خاصة بعناصر الوسائط
باستخدام MediaController.sendCustomCommand(SessionCommand, MediaItem, Bundle)
:
Kotlin
controller.sendCustomCommand(addToPlaylistButton.sessionCommand!!, mediaItem, Bundle.EMPTY)
Java
controller.sendCustomCommand( checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);