플레이어 인터페이스

플레이어는 미디어 항목의 재생을 용이하게 하는 앱의 구성요소입니다. Media3 Player 인터페이스는 일반적으로 플레이어에서 처리하는 기능의 개요를 설정합니다. 여기에는 다음이 포함됩니다.

  • 재생, 일시중지, 탐색과 같은 재생 컨트롤에 영향을 미칩니다.
  • 현재 재생 중인 미디어의 속성(예: 재생 위치) 쿼리
  • 미디어 항목의 재생목록/대기열 관리
  • 재생 속성(예: 셔플, 반복, 속도, 볼륨) 구성
  • 화면에 동영상 렌더링

Media3는 Player 인터페이스의 구현인 ExoPlayer도 제공합니다.

구성요소 간의 공통 인터페이스

Media3의 여러 구성요소는 플레이어 인터페이스를 구현합니다. 예를 들면 다음과 같습니다.

구성요소 설명 및 동작 참고사항
ExoPlayer 미디어 플레이어 API 및 Player 인터페이스의 기본 구현입니다.
MediaController MediaSession와 상호작용하여 재생 명령을 전송합니다. PlayerMediaSession가 플레이어의 UI가 있는 Activity 또는 Fragment와는 다른 Service에 있다면 MediaControllerPlayerView UI의 플레이어로 할당할 수 있습니다. 재생 및 재생목록 메서드 호출은 MediaSession를 통해 Player로 전송됩니다.
MediaBrowser MediaController에서 제공하는 기능 외에도 MediaLibrarySession와 상호작용하여 사용 가능한 미디어 콘텐츠를 탐색합니다.
ForwardingPlayer 메서드 호출을 다른 Player로 전달하는 Player 구현입니다. 이 클래스를 사용하여 각 메서드를 재정의하여 특정 작업을 억제하거나 수정합니다.
SimpleBasePlayer 구현할 메서드 수를 최소로 줄이는 Player 구현입니다. MediaSession에 연결하려는 맞춤 플레이어를 사용할 때 유용합니다.
CastPlayer Cast 수신기 앱과 통신하는 Player 구현입니다. 동작은 기본 Cast 세션에 따라 다릅니다.

MediaSessionPlayer 인터페이스를 구현하지 않지만 인터페이스를 만들 때 Player가 필요합니다. 이 목적은 다른 프로세스 또는 스레드에서 Player에 대한 액세스를 제공하는 것입니다.

Media3 재생 아키텍처

Player에 액세스할 수 있는 경우 재생 명령어를 실행하려면 메서드를 직접 호출해야 합니다. MediaSession를 구현하여 재생을 광고하고 외부 소스에 재생 제어 권한을 부여할 수 있습니다. 이러한 외부 소스는 미디어 세션에 연결하고 재생 명령 요청을 실행하는 데 도움이 되는 MediaController를 구현합니다.

백그라운드에서 미디어를 재생할 때는 포그라운드 서비스로 실행되는 MediaSessionService 또는 MediaLibraryService 내에 미디어 세션과 플레이어를 배치해야 합니다. 이렇게 하면 재생 제어용 UI가 포함된 앱의 Activity에서 플레이어를 분리할 수 있습니다. 이 경우 미디어 컨트롤러를 사용해야 할 수도 있습니다.

Media3 재생 구성요소가 미디어 앱 아키텍처에 어떻게 적용되는지 보여주는 다이어그램
그림 1: Player 인터페이스는 Media3의 아키텍처에서 중요한 역할을 합니다.

플레이어 상태

Player 인터페이스를 구현하는 미디어 플레이어의 상태는 주로 다음 네 가지 카테고리의 정보로 구성됩니다.

  1. 재생 상태
  2. 미디어 항목의 재생목록
    • 재생할 MediaItem 인스턴스 시퀀스입니다.
    • getCurrentTimeline()를 사용하여 검색
    • Player 인스턴스는 MediaItem추가하거나 삭제하는 것과 같은 재생목록 작업 메서드와 getCurrentMediaItem()와 같은 편의 메서드를 제공할 수 있습니다.
  3. 재생/일시중지 속성(예: 다음)
    • playWhenReady: 사용자가 가능한 경우 미디어를 재생할지 아니면 일시중지된 상태로 둘지 나타내는 표시입니다.
    • 재생 억제 이유: 재생이 억제되는 이유를 나타냅니다(해당하는 경우, playWhenReadytrue인 경우에도 적용됨).
    • isPlaying: 플레이어가 현재 재생 중인지 여부를 나타냅니다. 재생 상태가 STATE_READY이고, playWhenReadytrue이며, 재생이 억제되지 않은 경우에만 true입니다.
  4. 재생 위치(다음 포함)

또한 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 인터페이스는 상태를 조작하고 재생을 제어하는 다양한 방법을 제공합니다.

맞춤 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();
  }
}

SimpleBasePlayerState가 유효한 상태 값 조합으로 생성되도록 합니다. 또한 리스너를 처리하고 리스너에게 상태 변경을 알립니다. 상태 업데이트를 수동으로 트리거해야 하는 경우 invalidateState()를 호출합니다.

getState() 메서드 외에도 플레이어가 사용 가능하도록 선언한 명령어에 사용되는 메서드만 구현하면 됩니다. 구현하려는 기능에 해당하는 재정의 가능한 핸들러 메서드를 찾습니다. 예를 들어 handleSeek() 메서드를 재정의하여 COMMAND_SEEK_IN_CURRENT_MEDIA_ITEMCOMMAND_SEEK_TO_NEXT_MEDIA_ITEM와 같은 작업을 지원합니다.