แอปสื่อมักมีคอลเล็กชันรายการสื่อที่จัดระเบียบตามลําดับชั้น เช่น เพลงในอัลบั้มหรือตอนของรายการทีวีในเพลย์ลิสต์ ลําดับชั้นของรายการสื่อนี้เรียกว่าคลังสื่อ
MediaLibraryService
มี API มาตรฐานเพื่อแสดงและเข้าถึงคลังสื่อ การดำเนินการนี้มีประโยชน์ เช่น เมื่อเพิ่มการรองรับ Android Auto ลงในแอปสื่อ ซึ่งจะมี UI ของตนเองที่ปลอดภัยต่อผู้ขับขี่สำหรับคลังสื่อ
สร้าง 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
และสิทธิ์ที่จําเป็นในไฟล์ Manifest ด้วย
<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" />
เพื่อใช้งานร่วมกับไคลเอ็นต์ที่ใช้ Media API แบบเดิมได้
ใช้ MediaLibrarySession
MediaLibraryService
API คาดหวังว่าคลังสื่อของคุณจะมีโครงสร้างในรูปแบบต้นไม้ โดยมีโหนดรูทโหนดเดียวและโหนดย่อยที่เล่นได้หรือเรียกดูเพิ่มเติมได้
MediaLibrarySession
ขยาย MediaSession
API เพื่อเพิ่ม API การเรียกดูเนื้อหา เมื่อเทียบกับ MediaSession
callback แล้ว MediaLibrarySession
callback จะมีวิธีการเพิ่มเติม เช่น
onGetLibraryRoot()
สำหรับกรณีที่ลูกค้าขอรูทMediaItem
ของต้นไม้เนื้อหาonGetChildren()
สำหรับกรณีที่ไคลเอ็นต์ขอรายการย่อยของMediaItem
ในโครงสร้างเนื้อหาonGetSearchResult()
สำหรับเมื่อไคลเอ็นต์ขอผลการค้นหาจากต้นไม้เนื้อหาสำหรับข้อความค้นหาหนึ่งๆ
เมธอดการเรียกกลับที่เกี่ยวข้องจะมีออบเจ็กต์ LibraryParams
ที่มีสัญญาณเพิ่มเติมเกี่ยวกับประเภทของต้นไม้เนื้อหาที่แอปไคลเอ็นต์สนใจ
ปุ่มคำสั่งสำหรับรายการสื่อ
แอปเซสชันสามารถประกาศปุ่มคำสั่งที่ MediaItem
รองรับใน MediaMetadata
ซึ่งช่วยให้คุณกําหนดรายการ CommandButton
อย่างน้อย 1 รายการให้กับรายการสื่อที่ตัวควบคุมสามารถแสดงและใช้เพื่อส่งคําสั่งที่กําหนดเองสําหรับรายการไปยังเซสชันได้อย่างสะดวก
ตั้งค่าปุ่มคำสั่งฝั่งเซสชัน
เมื่อสร้างเซสชัน แอปเซสชันจะประกาศชุดปุ่มคำสั่งที่เซสชันสามารถจัดการเป็นคำสั่งที่กำหนดเอง ดังนี้
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
ที่ส่งไปยังการเรียกกลับเพื่อรับจำนวนสูงสุดของปุ่มคำสั่งที่ตัวควบคุมหรือเบราว์เซอร์แสดงได้ 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; }
เมื่อจัดการการดำเนินการที่กําหนดเองซึ่งส่งสําหรับรายการสื่อ เซสชัน App สามารถรับรหัสรายการสื่อจากอาร์กิวเมนต์ 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);