برنامههای رسانهای اغلب شامل مجموعههایی از عناصر رسانهای هستند که بهصورت سلسلهمراتبی سازماندهی شدهاند. برای مثال، آهنگهای یک آلبوم یا قسمتهای تلویزیونی در یک فهرست پخش. این سلسله مراتب فایلهای رسانهای بهعنوان کتابخانه رسانه شناخته میشود.
MediaLibraryService میانای برنامهسازی کاربردی استانداردشدهای برای ارائه و دسترسی به کتابخانه رسانهای شما فراهم میکند. این کار میتواند مفید باشد، برای مثال، هنگام افزودن پشتیبانی از
Android Auto به برنامه رسانهایتان، که رابط کاربری ایمن برای راننده برای
کتابخانه رسانهایتان ارائه میدهد.
ساختن MediaLibraryService
پیادهسازی MediaLibraryService شبیه به پیادهسازی
MediaSessionService است، با این تفاوت که در روش onGetSession()، شما
باید بهجای MediaSession، یک MediaLibrarySession برگردانید.
کاتلین
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() } }
جاوا
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 انتظار دارد کتابخانه رسانهتان در قالب درختی، با یک گره ریشه و گرههای فرزند که ممکن است قابلپخش یا قابلمرور باشند، ساختاربندی شود.
MediaLibrarySession میانای برنامهسازی کاربردی MediaSession را گسترش میدهد تا میاناهای برنامهسازی کاربردی
مرور محتوا را اضافه کند. در مقایسه با MediaSession فراخوانی،
MediaLibrarySession فراخوانی روشهایی مثل اینها را اضافه میکند:
onGetLibraryRoot()برای زمانی که مشتریMediaItemریشه درخت محتوا را درخواست میکندonGetChildren()برای زمانی که مشتری فرزندانMediaItemرا در درخت محتوا درخواست میکندonGetSearchResult()برای زمانی که مشتری نتایج جستجو را از درخت محتوا برای پُرسمان معینی درخواست میکند
روشهای برگشتی مربوطه شامل شیء LibraryParams با
نشانهای اضافی درباره نوع درخت محتوایی که برنامه مشتری به آن
علاقهمند است خواهد بود.
دکمههای فرمان برای فایلهای رسانهای
برنامه جلسه میتواند دکمههای فرمان پشتیبانیشده توسط MediaItem را در MediaMetadata اعلام کند. این کار امکان میدهد یک یا چند ورودی CommandButton
به عنصر رسانهای اختصاص داده شود تا کنترلکننده بتواند آن را نمایش دهد و از آن برای ارسال فرمان سفارشی
برای عنصر به جلسه به روشی راحت استفاده کند.
دکمههای فرمان را در سمت جلسه تنظیم کنید
هنگام ساختن جلسه، برنامه جلسه مجموعه دکمههای فرمان را که جلسه میتواند بهعنوان فرمانهای سفارشی مدیریت کند اعلام میکند:
کاتلین
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()
جاوا
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();
وقتی عنصر رسانهای میسازید، برنامه جلسه میتواند مجموعهای از شناسههای فرمان پشتیبانیشده را اضافه کند که به فرمانهای جلسه دکمههای فرمان که هنگام ساختن جلسه راهاندازی شدهاند ارجاع میدهد:
کاتلین
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 منتقلشده به روش برگشتی یک
دریافتکننده برای دسترسی راحت به این مقدار ارائه میدهد. بهطور پیشفرض، مقدار روی ۰ تنظیم شده است که نشان میدهد مرورگر یا کنترلکننده از این ویژگی پشتیبانی نمیکند:
کاتلین
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 }
جاوا
@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 دریافت کند:
کاتلین
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، حداکثر تعداد دکمههای فرمان را که برای یک عنصر رسانهای پشتیبانی میکند اعلام کند:
کاتلین
val browserFuture = MediaBrowser.Builder(context, sessionToken).setMaxCommandsForMediaItems(3).buildAsync()
جاوا
ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken).setMaxCommandsForMediaItems(3).buildAsync();
وقتی به جلسه متصل میشود، برنامه کنترلکننده میتواند دکمههای فرمان پشتیبانیشده توسط عنصر رسانهای و دکمههایی را که کنترلکننده فرمان دردسترس اعطاشده توسط برنامه جلسه را برای آنها دارد دریافت کند:
کاتلین
val commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem)
جاوا
ImmutableList<CommandButton> commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem);
کاتلین
val future = controller.sendCustomCommand( requireNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY, )
جاوا
ListenableFuture<SessionResult> future = controller.sendCustomCommand( checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);