미디어 컨트롤러는 미디어 세션과 상호작용하여 미디어 앱의 재생을 쿼리하고 제어합니다. Media3에서 MediaController
API는 Player
인터페이스를 구현합니다. 미디어 컨트롤러를 사용하는 클라이언트 앱의 예는 다음과 같습니다.
- Android 시스템 미디어 컨트롤
- Android Wear OS 호환 앱
- Android Auto 및 Automotive OS
- Google 어시스턴트와 같은 음성 어시스턴트
- 미디어 컨트롤러 테스트 앱
미디어 컨트롤러는 미디어 앱 내에서도 유용할 수 있습니다. 예를 들어 플레이어와 미디어 세션이 UI가 있는 Activity
또는 Fragment
와 별도의 Service
에 있는 경우입니다.
MediaController
를 만드는 방법
MediaController
을 만들려면 먼저 상응하는 MediaSession
의 SessionToken
를 만듭니다. Activity
또는 Fragment
의 onStart()
메서드가 적합합니다.
Kotlin
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
자바
SessionToken sessionToken = new SessionToken(context, new ComponentName(context, PlaybackService.class));
이 SessionToken
를 사용하여 MediaController
를 빌드하면 컨트롤러가 지정된 세션에 연결됩니다. 이는 비동기식으로 실행되므로 결과를 리슨하고 사용 가능한 경우 사용해야 합니다.
Kotlin
val controllerFuture = MediaController.Builder(context, sessionToken).buildAsync() controllerFuture.addListener({ // MediaController is available here with controllerFuture.get() }, MoreExecutors.directExecutor())
자바
ListenableFuture<MediaController> controllerFuture = new MediaController.Builder(context, sessionToken).buildAsync(); controllerFuture.addListener(() -> { // MediaController is available here with controllerFuture.get() }, MoreExecutors.directExecutor());
MediaController
사용
MediaController
는 Player
인터페이스를 구현하므로 인터페이스에 정의된 명령어를 사용하여 연결된 MediaSession
의 재생을 제어할 수 있습니다.
즉, MediaController
에서 play()
를 호출하면 연결된 MediaSession
에 명령어가 전송되고 MediaSession
는 이후에 명령어를 기본 Player
에 위임합니다.
마찬가지로 컨트롤러에 Player.Listener
를 추가하여 Player
상태의 변경사항을 수신 대기할 수도 있습니다. Player.Listener
사용에 관한 자세한 내용은 플레이어 이벤트 가이드를 참고하세요. MediaController.Listener
인터페이스는 연결된 MediaSession
의 이벤트 및 수신 명령어에 관한 추가 콜백을 정의합니다. 예를 들어 미디어 세션에서 사용 가능한 세션 명령어를 변경할 때의 onAvailableSessionCommandsChanged()
, 컨트롤러가 세션에서 연결 해제될 때의 onDisconnected()
등이 있습니다.
다른 구성요소와 마찬가지로 MediaController
가 더 이상 필요하지 않으면 해제해야 합니다(예: Activity
또는 Fragment
의 onStop()
메서드).
Kotlin
MediaController.releaseFuture(controllerFuture)
자바
MediaController.releaseFuture(controllerFuture);
컨트롤러를 해제해도 세션에 전송된 대기 중인 모든 명령이 계속 전송되며, 이러한 명령이 처리된 후에 세션 서비스에서만 바인딩이 해제됩니다(둘 중 먼저 발생하는 경우).
MediaBrowser
만들기 및 사용
MediaBrowser
는 MediaController
에서 제공하는 기능을 기반으로 하여 미디어 앱의 MediaLibraryService
에서 제공하는 미디어 라이브러리 탐색도 지원합니다.
Kotlin
val browserFuture = MediaBrowser.Builder(context, sessionToken).buildAsync() browserFuture.addListener({ // MediaBrowser is available here with browserFuture.get() }, MoreExecutors.directExecutor())
자바
ListenableFuture<MediaBrowser> browserFuture = new MediaBrowser.Builder(context, sessionToken).buildAsync(); browserFuture.addListener(() -> { // MediaBrowser is available here with browserFuture.get() }, MoreExecutors.directExecutor());
미디어 앱의 콘텐츠 라이브러리 탐색을 시작하려면 먼저 getLibraryRoot()
를 사용하여 루트 노드를 가져옵니다.
Kotlin
// Get the library root to start browsing the library tree. val rootFuture = mediaBrowser.getLibraryRoot(/* params= */ null) rootFuture.addListener({ // Root node MediaItem is available here with rootFuture.get().value }, MoreExecutors.directExecutor())
자바
// Get the library root to start browsing the library tree. ListenableFuture<LibraryResult<MediaItem>> rootFuture = mediaBrowser.getLibraryRoot(/* params= */ null); rootFuture.addListener(() -> { // Root node MediaItem is available here with rootFuture.get().value }, MoreExecutors.directExecutor());
그런 다음 getChildren()
를 사용하여 라이브러리의 MediaItem
하위 요소를 검색하여 미디어 라이브러리를 탐색할 수 있습니다. 예를 들어 루트 노드 MediaItem
의 하위 요소를 검색하려면 다음을 실행합니다.
Kotlin
// Get the library root to start browsing the library tree. val childrenFuture = mediaBrowser.getChildren(rootMediaItem.mediaId, 0, Int.MAX_VALUE, null) childrenFuture.addListener({ // List of children MediaItem nodes is available here with // childrenFuture.get().value }, MoreExecutors.directExecutor())
Java
ListenableFuture<LibraryResult<ImmutableList<MediaItem>>> childrenFuture = mediaBrowser.getChildren(rootMediaItem.mediaId, 0, Integer.MAX_VALUE, null); childrenFuture.addListener(() -> { // List of children MediaItem nodes is available here with // childrenFuture.get().value }, MoreExecutors.directExecutor());