אפליקציות מדיה מכילות לרוב אוספים של פריטי מדיה, שמסודרים בהיררכיה. לדוגמה, שירים באלבום או פרקים של תוכנית טלוויזיה בפלייליסט. ההיררכיה הזו של פריטי מדיה נקראת ספריית מדיה.
MediaLibraryService מספק API סטנדרטי להצגת ספריית המדיה ולגישה אליה. לדוגמה, זה יכול להיות שימושי כשמוסיפים תמיכה ב-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 API מצפה שספריית המדיה תהיה מובנית בפורמט של עץ, עם צומת בסיס יחיד וצמתים צאצאים שיכולים להיות ניתנים להפעלה או ניתנים לעיון נוסף.
MediaLibrarySession
מרחיב את MediaSession API כדי להוסיף ממשקי API לעיון בתוכן. בהשוואה לMediaSession callback, ב-MediaLibrarySession callback יש שיטות נוספות כמו:
-
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 שמועבר לשיטת התקשרות חזרה מספק שיטת getter לגישה נוחה לערך הזה. ערך ברירת המחדל הוא 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);