برنامههای رسانهای اغلب شامل مجموعهای از آیتمهای رسانهای هستند که به صورت سلسله مراتبی سازماندهی شدهاند. به عنوان مثال، آهنگهای یک آلبوم یا قسمتهای تلویزیونی در یک لیست پخش. این سلسله مراتب از آیتمهای رسانهای به عنوان کتابخانه رسانه شناخته میشود.
یک MediaLibraryService یک API استاندارد برای سرویسدهی و دسترسی به کتابخانه رسانه شما ارائه میدهد. این میتواند مفید باشد، برای مثال، هنگام افزودن پشتیبانی از Android Auto به برنامه رسانهای شما، که رابط کاربری امن راننده خود را برای کتابخانه رسانه شما فراهم میکند.
MediaLibraryService پیادهسازی MediaLibraryService مشابه پیادهسازی MediaSessionService است، با این تفاوت که در متد onGetSession() ، باید به جای MediaSession یک MediaLibrarySession برگردانید.
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"/>
<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 API MediaSession را برای افزودن APIهای مرور محتوا، توسعه میدهد. در مقایسه با فراخوانی MediaSession ، فراخوانی MediaLibrarySession متدهایی مانند موارد زیر را اضافه میکند:
-
onGetLibraryRoot()برای زمانی است که یک کلاینتMediaItemاصلی یک درخت محتوا را درخواست میکند. -
onGetChildren() برای زمانی که یک کلاینت، فرزندان یکMediaItemرا در درخت محتوا درخواست میکند. -
onGetSearchResult()برای زمانی که یک کلاینت نتایج جستجو را از درخت محتوا برای یک پرسوجوی مشخص درخواست میکند.
متدهای فراخوانی مرتبط شامل یک شیء LibraryParams با سیگنالهای اضافی در مورد نوع درخت محتوایی که برنامه کلاینت به آن علاقهمند است، خواهند بود.
یک برنامهی session میتواند دکمههای فرمانی را که توسط یک MediaItem در MediaMetadata پشتیبانی میشوند، تعریف کند. این امر امکان اختصاص یک یا چند ورودی CommandButton را به یک آیتم رسانهای فراهم میکند که یک کنترلر میتواند آن را نمایش داده و برای ارسال دستور سفارشی برای آیتم به session به روشی مناسب استفاده کند.
هنگام ساخت جلسه، یک برنامه جلسه، مجموعهای از دکمههای فرمان را که یک جلسه میتواند به عنوان دستورات سفارشی مدیریت کند، اعلام میکند:
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()
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();
وقتی یک کنترلر یا مرورگر به متد دیگری از session Callback متصل میشود یا آن را فراخوانی میکند، برنامه session میتواند ControllerInfo ارسال شده به callback را بررسی کند تا حداکثر تعداد دکمههای فرمانی را که یک کنترلر یا مرورگر میتواند نمایش دهد، بدست آورد. ControllerInfo ارسال شده به یک متد callback، یک getter برای دسترسی راحت به این مقدار فراهم میکند. به طور پیشفرض، مقدار روی 0 تنظیم شده است که نشان میدهد مرورگر یا کنترلر از این ویژگی پشتیبانی نمیکند:
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 دریافت کند:
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: List<CommandButton> = controller.getCommandButtonsForMediaItem(mediaItem)
ImmutableList<CommandButton> commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem);
برای راحتی، یک MediaController میتواند دستورات سفارشی مخصوص آیتم رسانه را با MediaController.sendCustomCommand(SessionCommand, MediaItem, Bundle) ارسال کند:
controller.sendCustomCommand(addToPlaylistButton.sessionCommand!!, mediaItem, Bundle.EMPTY)
controller.sendCustomCommand( checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);