Các ứng dụng đa phương tiện thường chứa các bộ sưu tập mục nội dung nghe nhìn, được sắp xếp theo một hệ phân cấp. Ví dụ: các bài hát trong một đĩa nhạc hoặc các tập của chương trình truyền hình trong một danh sách phát. Hệ phân cấp các mục nội dung nghe nhìn này được gọi là thư viện nội dung nghe nhìn.
MediaLibraryService
cung cấp một API tiêu chuẩn để phân phát và truy cập vào thư viện nội dung đa phương tiện của bạn. Ví dụ: điều này có thể hữu ích khi bạn thêm tính năng hỗ trợ Android Auto vào ứng dụng đa phương tiện của mình. Android Auto cung cấp giao diện người dùng riêng, an toàn cho người lái xe cho thư viện nội dung nghe nhìn của bạn.
Tạo một MediaLibraryService
Việc triển khai MediaLibraryService
tương tự như triển khai MediaSessionService
, ngoại trừ việc trong phương thức onGetSession()
, bạn nên trả về MediaLibrarySession
thay vì 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(); } }
Đừng quên khai báo Service
và các quyền bắt buộc trong tệp kê khai:
<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" />
Dùng MediaLibrarySession
API MediaLibraryService
yêu cầu thư viện nội dung nghe nhìn của bạn phải có cấu trúc ở định dạng cây, với một nút gốc duy nhất và các nút con có thể phát hoặc duyệt thêm.
MediaLibrarySession
mở rộng API MediaSession
để thêm các API duyệt xem nội dung. So với lệnh gọi lại MediaSession
, lệnh gọi lại MediaLibrarySession
sẽ thêm các phương thức như:
onGetLibraryRoot()
khi ứng dụng yêu cầuMediaItem
gốc của một cây nội dungonGetChildren()
khi một ứng dụng yêu cầu các phần tử con củaMediaItem
trong cây nội dungonGetSearchResult()
khi ứng dụng yêu cầu kết quả tìm kiếm từ cây nội dung cho một truy vấn nhất định
Các phương thức gọi lại có liên quan sẽ bao gồm một đối tượng LibraryParams
với các tín hiệu bổ sung về loại cây nội dung mà một ứng dụng khách quan tâm.
Các nút lệnh cho mục nội dung nghe nhìn
Ứng dụng phiên có thể khai báo các nút lệnh được MediaItem
hỗ trợ trong MediaMetadata
. Điều này cho phép bạn chỉ định một hoặc nhiều mục CommandButton
cho một mục nội dung nghe nhìn mà bộ điều khiển có thể hiển thị và sử dụng để gửi lệnh tuỳ chỉnh cho mục đó đến phiên một cách thuận tiện.
Thiết lập các nút lệnh ở phía phiên
Khi tạo phiên, ứng dụng phiên sẽ khai báo tập hợp các nút lệnh mà phiên có thể xử lý dưới dạng các lệnh tuỳ chỉnh:
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();
Khi tạo một mục nội dung nghe nhìn, ứng dụng phiên có thể thêm một tập hợp các mã lệnh được hỗ trợ tham chiếu đến các lệnh phiên của nút lệnh đã được thiết lập khi tạo phiên:
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();
Khi một bộ điều khiển hoặc trình duyệt kết nối hoặc gọi một phương thức khác của phiên Callback
, ứng dụng phiên có thể kiểm tra ControllerInfo
được truyền đến lệnh gọi lại để lấy số lượng nút lệnh tối đa mà bộ điều khiển hoặc trình duyệt có thể hiển thị. ControllerInfo
được truyền vào một phương thức gọi lại sẽ cung cấp một phương thức getter để truy cập thuận tiện vào giá trị này. Theo mặc định, giá trị được đặt thành 0, cho biết trình duyệt hoặc bộ điều khiển không hỗ trợ tính năng này:
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; }
Khi xử lý một thao tác tuỳ chỉnh đã được gửi cho một mục nội dung nghe nhìn, ứng dụng phiên có thể lấy mã nhận dạng mục nội dung nghe nhìn từ các đối số Bundle
được truyền vào 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); }
Sử dụng nút lệnh làm trình duyệt hoặc bộ điều khiển
Về phía MediaController
, ứng dụng có thể khai báo số lượng nút lệnh tối đa mà ứng dụng hỗ trợ cho một mục nội dung nghe nhìn khi tạo MediaController
hoặc MediaBrowser
:
Kotlin
val browserFuture = MediaBrowser.Builder(context, sessionToken) .setMaxCommandsForMediaItems(3) .buildAsync()
Java
ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken) .setMaxCommandsForMediaItems(3) .buildAsync();
Khi được kết nối với phiên, ứng dụng bộ điều khiển có thể nhận các nút lệnh mà mục nội dung nghe nhìn hỗ trợ và bộ điều khiển có lệnh có sẵn do ứng dụng phiên cấp:
Kotlin
val commandButtonsForMediaItem: List<CommandButton> = controller.getCommandButtonsForMediaItem(mediaItem)
Java
ImmutableList<CommandButton> commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem);
Để thuận tiện, MediaController
có thể gửi các lệnh tuỳ chỉnh dành riêng cho mục nội dung nghe nhìn bằng MediaController.sendCustomCommand(SessionCommand, MediaItem, Bundle)
:
Kotlin
controller.sendCustomCommand(addToPlaylistButton.sessionCommand!!, mediaItem, Bundle.EMPTY)
Java
controller.sendCustomCommand( checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);