אפליקציות מדיה מכילות לרוב אוספים של פריטי מדיה, שמאורגנים בהיררכיה. לדוגמה, שירים באלבום או פרקים בתוכנית טלוויזיה בפלייליסט. ההיררכיה הזו של פריטי המדיה נקראת 'ספריית מדיה'.
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"/>
</intent-filter>
</service>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<!-- For targetSdk 34+ -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
שימוש ב-MediaLibrarySession
ממשק ה-API של MediaLibraryService
מצפה שספריית המדיה תהיה מובנית בפורמט עץ, עם צומת root יחיד וצמתים צאצאים שאפשר להפעיל או לעיין בהם.
MediaLibrarySession
הוא תוסף ל-MediaSession
API שמאפשר להוסיף ממשקי API לגלישה בתוכן. בהשוואה ל-callback של MediaSession
, ל-callback של 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)) .setDisplayName("Add to playlist") .setIconResId(R.drawable.playlist_add) .setSessionCommand(SessionCommand(COMMAND_PLAYLIST_ADD, Bundle.EMPTY)) .setExtras(playlistAddExtras) .build(), CommandButton.Builder(CommandButton.ICON_RADIO) .setDisplayName(context.getString(R.string.radio_station)) .setIconResId(R.drawable.radio) .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("Add to playlist") .setIconUri(Uri.parse("http://www.example.com/icon/playlist_add")) .setSessionCommand(new SessionCommand(COMMAND_PLAYLIST_ADD, Bundle.EMPTY)) .setExtras(playlistAddExtras) .build(), new CommandButton.Builder(CommandButton.ICON_RADIO) .setDisplayName("Radio station") .setIconUri(Uri.parse("http://www.example.com/icon/radio")) .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
שמוענק ל-callback כדי לקבל את המספר המקסימלי של לחצני הפקודה שאפשר להציג בבקר או בדפדפן. הערך 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);