기기 기반으로 추상화되어 간단한 아키텍처로 강력한 맞춤설정, 안정성, 최적화를 제공하는 라이브러리.
Player: 재생, 일시중지, 탐색 등의 고급 기능을 정의하는 인터페이스.ExoPlayer: Player 인터페이스의 구현체MediaSession: 오디오/비디오 플레이어와 상호작용할 수 있도록 하는 컨테이너 역할. 생성 시 Player를 주입받음.MediaSessionService: 백그라운드 재생을 지원하며, MediaSession과 Player를 갖고 백그라운드에서 Activity에 독립적으로 실행될 수 있게 함. MediaController: 앱 외부에서 제어할 때 사용. Player 구현체이지만, MediaSession의 Player에 명령을 전달하는 역할만 수행함. 즉, TV(Player) - 셋탑박스(MediaSession) - 리모컨(MediaController)의 관계.MediaLibraryService: MediaSessionService와 같지만, 라이브러리 형태로 컨텐츠를 제공할 수 있게 돕는다.MediaBrowser: Player와 MediaController를 모두 구현하여, 라이브러리에서 재생할 컨텐츠를 고르는 등의 액션을 제공한다.PlayerView: 비디오나 Playback 컨트롤러를 제공하는 기본적인 viewPlayerSurface: 비디오를 보여주기 위한 Compose view. 단, playback 컨트롤러에는 연결할 수 없다.| class | 설명 | 노트 |
|---|---|---|
Transformer | 미디어 변환을 시작하거나 확인할 수 있음 | |
Effects | MediaItem에 적용될 액션들 | ExoPlayer를 사용하여 적용된 Effect를 export하기 전에 볼 수 있다. |
EditMediaItem | 편집될 MediaItem들의 컬렉션 |

핵심 컴포넌트인 ExoPlayer, MediaController가 Player의 구현체로, Media3의 재생 아키텍처에서 핵심적인 인터페이스로 작동한다.
getPlaybackState()로 가져오며, 상태 값은 STATE_IDLE, STATE_BUFFERING, STATE_READY, and STATE_ENDED이다.getCurrentTimeline()으로 가져오며, MediaItem(재생목록)에 대해 추가, 삭제 같은 작업을 할 수 있다.isPlaying, playWhenReady 등isPlayingAd, 현재 재생 위치 등play(), pause(), prepare(), stop()addMediaItem(), removeMediaItem()생성 시 Player 구현체와 Context를 파라미터로 받습니다.
val player = ExoPlayer.Builder(context).build()
val mediaSession = MediaSession.Builder(context, player).build()
MediaSession에 있는 재생 상태를 업데이트합니다.Builder에 setId를 추가하여 여러 세션을 만들고 관리할 수 있습니다.다음 경우들에 쉽게 대응할 수 있다.
이를 위해선 해당 클라이언트에 제어 권한을 부여해야 한다.

외부 클라이언트(MediaController)가 보낸 명령은 MediaSession이 수신하여, 명령어를 수행한다.
onConnect(): 외부 MediaController가 연결을 시도할 경우 호출된다. ContollerInfo를 보고 수락, 거부를 결정하면 된다.
MediaItem
System Media Controls :
Media Notification : 상태바를 내렸을 때 보이는 재생기Lockscreen Media Controls : 폰을 켜자마자 비밀번호를 치기 전에 크게 보이는 재생기
class PlaybackService : MediaSessionService() {
private var mediaSession: MediaSession? = null
override fun onCreate() {
super.onCreate()
// 초기화
val player = ExoPlayer.Builder(this).build()
mediaSession = MediaSession.Builder(this, player).build()
}
override fun onDestroy() {
// 리소스 해제
mediaSession?.run {
player.release()
release()
mediaSession = null
}
super.onDestroy()
}
// MediaSession 할당
override fun onGetSession(controllerInfo: MediaSession.ControllerInfo): MediaSession? =
mediaSession
// 앱 종료 시 필요한 적업 수행
override fun onTaskRemoved(rootIntent: Intent?) {
pauseAllPlayersAndStopSelf()
}
onCreate(): MediaController가 연결을 시도하는 시점. Player와 MediaSession을 빌드하기에 최적onDestroy(): 리소스 해제 필요onTaskRemoved(Intent): 앱이 종료될 시 호출되는 함수로, 필요 시 재정의권한
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
서비스 선언
<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>
생성
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
val controllerFuture = MediaController.Builder(context, sessionToken).buildAsync()
controllerFuture.addListener(
{
// MediaController is available here with controllerFuture.get()
mediaController = controllFuture.get()
},
MoreExecutors.directExecutor(),
)
또는 CoroutineScope에서
val sessionToken = SessionToken(context, ComponentName(context, PlaybackService::class.java))
val mediaController = MediaController
.Builder(context, sessionToken)
.buildAsync()
.await() // Future에서 객체가 할당되기를 기다리는 코루틴 확장 함수
onStart()에서 sessionToken 만들기MediaController를 빌더 함수로 비동기 생성. 사용
play(), pause(), release() 등Player에 상태 변경 리스너 등록MediaSession.Callback 등록onCustomCommand()onDisconnected()MediaController.releaseFuture(controllerFuture) : 리소스 해제자동으로 MediaNotification을 만듦. 세션을 인식하여 동일한 세션에 연결된 다른 앱의 재생을 제어 할 수도 있음.
val mediaItem =
MediaItem.Builder()
.setMediaId("media-1")
.setUri(mediaUri)
.setMediaMetadata(
MediaMetadata.Builder()
.setArtist("David Bowie")
.setTitle("Heroes")
.setArtworkUri(artworkUri)
.build()
)
.build()
mediaController.setMediaItem(mediaItem)
mediaController.prepare()
mediaController.play()
생명주기
Player 재생 목록에 MediaItem 인스턴스에 따라 자동 생성 및 자동 업데이트Player.release()나 Player.clearMediaItems()를 호출해야함.기본적으로
MediaSessionService와 같음.
onGetSession() 메서드에서 MediaSession 대신 MediaLibrarySession를 반환MediaItem을 트리 형식으로 제공해야 함.onGetLibraryRoot(): 컨텐츠 트리의 루트 MediaItem를 요청하는 경우onGetChildren(): 컨텐츠 트리의 루트 MediaItem의 하위 요소를 요청하는 경우onGetSearchResult(): 특정 쿼리의 콘센츠 트리에서 결과를 요청하는 경우