플레이어는 미디어 항목의 재생을 용이하게 하는 앱의 구성요소입니다.
Media3 Player
인터페이스는 일반적으로 플레이어에서 처리하는 기능의 개요를 설정합니다. 여기에는 다음이 포함됩니다.
- 재생, 일시중지, 탐색과 같은 재생 컨트롤에 영향을 미칩니다.
- 현재 재생 중인 미디어의 속성(예: 재생 위치) 쿼리
- 미디어 항목의 재생목록/현재 재생목록 관리
- 재생 속성(예: 셔플, 반복, 속도, 볼륨) 구성
- 화면에 동영상 렌더링
Media3는 Player
인터페이스의 구현인 ExoPlayer
도 제공합니다.
구성요소 간의 공통 인터페이스
Media3의 여러 구성요소가 Player 인터페이스를 구현합니다. 예를 들면 다음과 같습니다.
구성요소 | 설명 및 동작 메모 |
---|---|
ExoPlayer |
미디어 플레이어 API 및 Player 인터페이스의 기본 구현입니다. |
MediaController |
MediaSession 와 상호작용하여 재생 명령어를 전송합니다. Player 및 MediaSession 가 플레이어의 UI가 있는 Activity 또는 Fragment 와 별도의 Service 에 있는 경우 MediaController 를 PlayerView UI의 플레이어로 할당할 수 있습니다. 재생 및 재생목록 메서드 호출은 MediaSession 를 통해 Player 로 전송됩니다.
|
MediaBrowser |
MediaController 에서 제공하는 기능 외에도 MediaLibrarySession 와 상호작용하여 사용 가능한 미디어 콘텐츠를 탐색합니다.
|
SimpleBasePlayer |
구현할 메서드 수를 최소로 줄이는 Player 구현입니다. MediaSession 에 연결하려는 맞춤 플레이어를 사용할 때 유용합니다.
|
ForwardingSimpleBasePlayer |
SimpleBasePlayer 와 동일한 일관된 동작 맞춤설정을 허용하면서 재생 작업을 다른 Player 로 전달하도록 설계된 SimpleBasePlayer 서브클래스입니다. 이 클래스를 사용하여 특정 재생 작업을 억제하거나 수정합니다.
|
CastPlayer |
Cast 수신기 앱과 통신하는 Player 구현입니다. 동작은 기본 Cast 세션에 따라 다릅니다.
|
MediaSession
는 Player
인터페이스를 구현하지 않지만 Player
를 만들 때는 Player
가 필요합니다. 이 클래스의 목적은 다른 프로세스 또는 스레드에서 Player
에 대한 액세스를 제공하는 것입니다.
Media3 재생 아키텍처
Player
에 액세스할 수 있는 경우 재생 명령어를 실행하려면 메서드를 직접 호출해야 합니다. MediaSession
를 구현하여 재생을 광고하고 외부 소스에 재생 제어 권한을 부여할 수 있습니다. 이러한 외부 소스는 미디어 세션에 연결하고 재생 명령 요청을 실행하는 데 도움이 되는 MediaController
를 구현합니다.
백그라운드에서 미디어를 재생할 때는 포그라운드 서비스로 실행되는 MediaSessionService
또는 MediaLibraryService
내에 미디어 세션과 플레이어를 배치해야 합니다. 이렇게 하면 재생 제어 UI가 포함된 앱의 Activity에서 플레이어를 분리할 수 있습니다. 이 경우 미디어 컨트롤러를 사용해야 할 수 있습니다.
플레이어 상태
Player
인터페이스를 구현하는 미디어 플레이어의 상태는 기본적으로 다음 4가지 카테고리의 정보로 구성됩니다.
- 재생 상태
getPlaybackState()
를 사용하여 가져옵니다.- 인터페이스에 의해 정의된 상태 값은
STATE_IDLE
,STATE_BUFFERING
,STATE_READY
,STATE_ENDED
입니다.
- 미디어 항목의 재생목록
- 재생할
MediaItem
인스턴스의 시퀀스입니다. getCurrentTimeline()
를 사용하여 검색Player
인스턴스는MediaItem
를 추가하거나 삭제하는 것과 같은 재생목록 작업 메서드와getCurrentMediaItem()
와 같은 편의 메서드를 제공할 수 있습니다.
- 재생할
- 재생/일시중지 속성(예: 다음)
playWhenReady
: 사용자가 가능한 경우 미디어를 재생할지 아니면 일시중지된 상태로 둘지 나타내는 표시입니다.- 재생 억제 이유: 재생이 억제되는 이유를 나타냅니다(해당하는 경우,
playWhenReady
이true
인 경우에도 적용됨). isPlaying
: 플레이어가 현재 재생 중인지 여부를 나타냅니다. 재생 상태가STATE_READY
이고,playWhenReady
가true
이며, 재생이 억제되지 않은 경우에만true
입니다.
- 재생 위치(다음 포함)
- 현재 미디어 항목 색인: 재생목록의 현재
MediaItem
색인입니다. isPlayingAd
: 삽입된 광고가 재생 중인지 나타냅니다.- 현재 재생 위치: 현재
MediaItem
또는 삽입된 광고 내의 현재 재생 위치입니다.
- 현재 미디어 항목 색인: 재생목록의 현재
또한 Player
인터페이스를 통해 사용 가능한 트랙, 미디어 메타데이터, 재생 속도, 볼륨 및 재생의 기타 보조 속성에 액세스할 수 있습니다.
변경사항 수신 대기
Player.Listener
를 사용하여 Player
의 변경사항을 수신 대기합니다. 리스너를 만들고 사용하는 방법에 관한 자세한 내용은 플레이어 이벤트에 관한 ExoPlayer 문서를 참고하세요.
리스너 인터페이스에는 일반 재생 진행 상황을 추적하는 콜백이 포함되어 있지 않습니다. 진행률 표시줄 UI를 설정하는 등 재생 진행률을 지속적으로 모니터링하려면 적절한 간격으로 현재 위치를 쿼리해야 합니다.
Kotlin
val handler = Handler(Looper.getMainLooper()) fun checkPlaybackPosition(delayMs: Long): Boolean = handler.postDelayed( { val currentPosition = player.currentPosition // Update UI based on currentPosition checkPlaybackPosition(delayMs) }, delayMs)
자바
Handler handler = new Handler(Looper.getMainLooper()); boolean checkPlaybackPosition(long delayMs) { return handler.postDelayed(() -> { long currentPosition = player.getCurrentPosition(); // Update UI based on currentPosition checkPlaybackPosition(delayMs); }, delayMs); }
재생 제어
Player
인터페이스는 상태를 조작하고 재생을 제어하는 여러 가지 방법을 제공합니다.
play()
,pause()
,prepare()
,stop()
와 같은 기본 재생 컨트롤addMediaItem()
또는removeMediaItem()
와 같은 재생목록 작업- 시킹: 현재 항목 또는 위치를 변경합니다.
- 반복 모드 및 셔플 모드를 설정합니다.
- 트랙 선택 환경설정을 업데이트합니다.
- 재생 속도를 설정합니다.
맞춤 Player
구현
맞춤 플레이어를 만들려면 Media3에 포함된 SimpleBasePlayer
를 확장하면 됩니다. 이 클래스는 구현해야 하는 메서드 수를 최소로 줄이기 위해 Player
인터페이스의 기본 구현을 제공합니다.
먼저 getState()
메서드를 재정의합니다. 이 메서드는 호출될 때 다음을 포함하여 현재 플레이어 상태를 채워야 합니다.
- 사용 가능한 명령어 집합
- 재생 속성이
STATE_READY
일 때 플레이어가 재생을 시작해야 하는지 여부, 현재 재생 중인 미디어 항목의 색인, 현재 항목 내 재생 위치와 같은 재생 속성
Kotlin
class CustomPlayer : SimpleBasePlayer(looper) { override fun getState(): State { return State.Builder() .setAvailableCommands(...) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build() } }
자바
public class CustomPlayer extends SimpleBasePlayer { public CustomPlayer(Looper looper) { super(looper); } @Override protected State getState() { return new State.Builder() .setAvailableCommands(...) // Set which playback commands the player can handle // Configure additional playback properties .setPlayWhenReady(true, PLAY_WHEN_READY_CHANGE_REASON_USER_REQUEST) .setCurrentMediaItemIndex(0) .setContentPositionMs(0) .build(); } }
SimpleBasePlayer
는 State
가 유효한 상태 값 조합으로 만들어지도록 적용합니다. 또한 리스너를 처리하고 리스너에게 상태 변경을 알립니다. 상태 업데이트를 수동으로 트리거해야 하는 경우 invalidateState()
를 호출합니다.
getState()
메서드 외에도 플레이어가 사용 가능하도록 선언한 명령어에 사용되는 메서드만 구현하면 됩니다. 구현하려는 기능에 해당하는 재정의 가능한 핸들러 메서드를 찾습니다. 예를 들어 handleSeek()
메서드를 재정의하여 COMMAND_SEEK_IN_CURRENT_MEDIA_ITEM
및 COMMAND_SEEK_TO_NEXT_MEDIA_ITEM
와 같은 작업을 지원합니다.