אפליקציות מדיה מכילות לרוב אוספים של פריטי מדיה, שמסודרים בהיררכיה. לדוגמה, שירים באלבום או פרקים של תוכנית טלוויזיה בפלייליסט. ההיררכיה הזו של פריטי מדיה נקראת ספריית מדיה.
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
שמועבר לשיטת callback מספק 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);