メディアアプリには、階層構造で整理されたメディア アイテムのコレクションが含まれていることがよくあります。 たとえば、アルバム内の曲やプレイリスト内のテレビ番組などです。このメディア アイテムの階層は、メディア ライブラリと呼ばれます。
MediaLibraryService は、メディア ライブラリの提供とアクセスを行うための標準化された API を提供します。これは、たとえば、メディアアプリに
Android Auto のサポートを追加する場合に役立ちます。Android Auto は、
メディア ライブラリ用の独自の安全運転 UI を提供します。
MediaLibraryService をビルドする
MediaLibraryService の実装は MediaSessionService の実装と似ていますが、onGetSession() メソッドでは MediaSession ではなく MediaLibrarySession を返す必要があります。
Kotlin
class PlaybackService : MediaLibraryService() { private var mediaLibrarySession: MediaLibrarySession? = null private val callback: MediaLibrarySession.Callback = object : MediaLibrarySession.Callback { /* ... */ } override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaLibrarySession? { // 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 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 は、メディア ライブラリが
ツリー形式で構造化されていることを想定しています。つまり、1 つのルートノードと、
再生可能またはさらにブラウジング可能な子ノードで構成されていることを想定しています。
MediaLibrarySession は MediaSession API を拡張して、コンテンツ
ブラウジング API を追加します。MediaSession コールバックと比較して、
MediaLibrarySession コールバックには次のようなメソッドが追加されています。
onGetLibraryRoot()クライアントが コンテンツ ツリーのルートMediaItemをリクエストした場合onGetChildren()クライアントがコンテンツ ツリー内のMediaItemの子をリクエストした場合onGetSearchResult()クライアントが特定のクエリの コンテンツ ツリーから検索結果をリクエストした場合
関連するコールバック メソッドには、LibraryParams オブジェクトと
、クライアント アプリが
関心を持っているコンテンツ ツリーのタイプに関する追加のシグナルが含まれます。
メディア アイテムのコマンドボタン
セッション アプリは、MediaMetadata の MediaItem でサポートされているコマンドボタンを宣言できます。これにより、コントローラがメディア アイテムに 1 つ以上の 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(), ) // 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();
メディア アイテムをビルドするときに、セッション アプリは、セッションのビルド時に設定されたコマンドボタンのセッション コマンドを参照する、サポートされているコマンド ID のセットを追加できます。
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 には、この値に簡単にアクセスできるゲッターが用意されています。デフォルトでは、値は 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 loadMediaItemAsync(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; }
メディア アイテムに送信されたカスタム アクションを処理するときに、セッション アプリは onCustomCommand に渡された引数 Bundle からメディア アイテム ID を取得できます。
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 = controller.getCommandButtonsForMediaItem(mediaItem)
Java
ImmutableList<CommandButton> commandButtonsForMediaItem = controller.getCommandButtonsForMediaItem(mediaItem);
Kotlin
val future = controller.sendCustomCommand( requireNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY, )
Java
ListenableFuture<SessionResult> future = controller.sendCustomCommand( checkNotNull(addToPlaylistButton.sessionCommand), mediaItem, Bundle.EMPTY);