MediaPlayer 개요

Android 멀티미디어 프레임워크는 다양한 일반 미디어 유형의 재생에 대한 지원을 포함하므로 오디오, 동영상, 이미지를 애플리케이션에 쉽게 통합할 수 있습니다. 오디오를 재생하거나 독립형 파일에서 애플리케이션의 리소스 (원시 리소스)에 저장된 미디어 파일의 동영상 파일 시스템에서 또는 네트워크 연결을 통해 도착하는 데이터 스트림에서 수집하며 이 모든 작업은 MediaPlayer API를 사용합니다.

이 문서에서는 MediaPlayer: 미디어 재생 작성 사용자 및 시스템과 상호 작용하는 애플리케이션은 즐거운 사용자 경험을 제공합니다. 또는 다음과 같이 한다면 맞춤설정 가능한 오픈소스인 ExoPlayer를 사용해 MediaPlayer에서는 제공되지 않는 고성능 기능을 지원하는 라이브러리입니다.

참고: 오디오 데이터는 표준 출력으로만 재생할 수 있습니다. 있습니다. 현재 표준 출력 기기에는 휴대기기 스피커 또는 블루투스 헤드셋이 있습니다. 소리를 재생할 수 없음 파일을 공유할 수 있습니다.

기본 사항

다음 클래스는 Android 프레임워크에서 사운드 및 동영상을 재생하는 데 사용됩니다.

MediaPlayer
이 클래스는 사운드 및 동영상을 재생하는 기본 API입니다.
AudioManager
이 클래스는 기기의 오디오 소스 및 오디오 출력을 관리합니다.

매니페스트 선언

MediaPlayer를 사용하여 애플리케이션 개발을 시작하기 전에 매니페스트가 다음과 같아야 합니다. 적절한 선언이 있어야 관련 기능을 사용할 수 있습니다.

  • 인터넷 권한 - MediaPlayer를 사용하여 네트워크 기반 스트리밍을 사용하는 경우 애플리케이션에서 네트워크 액세스를 요청해야 합니다.
    <uses-permission android:name="android.permission.INTERNET" />
    
  • Wake Lock 권한 - 플레이어 애플리케이션에서 화면을 유지해야 하는 경우 프로세서의 절전 모드를 해제하거나 MediaPlayer.setScreenOnWhilePlaying() 또는 MediaPlayer.setWakeMode() 메서드에서 이 권한을 요청해야 합니다.
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    

MediaPlayer 사용

미디어 프레임워크의 가장 중요한 구성 요소 중 하나는 MediaPlayer 클래스에 대해 자세히 알아보세요. 이 클래스의 객체는 오디오와 동영상을 모두 가져오고 디코딩하고 재생할 수 있습니다. 자동화합니다 다음과 같은 여러 미디어 소스를 지원합니다.

  • 로컬 리소스
  • 콘텐츠 리졸버에서 가져올 수 있는 것과 같은 내부 URI
  • 외부 URL(스트리밍)

Android에서 지원하는 미디어 형식 목록은 자세한 내용은 지원되는 미디어 형식 페이지를 참조하세요.

예를 들면 다음과 같습니다. (애플리케이션의 res/raw/ 디렉터리):

Kotlin

var mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1)
mediaPlayer.start() // no need to call prepare(); create() does that for you

자바

MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1);
mediaPlayer.start(); // no need to call prepare(); create() does that for you

이 경우 'raw'가 리소스라고 하는 파일은 시스템에서 특정 방식으로 파싱하려고 시도합니다. 하지만 이 리소스의 콘텐츠가 원시 오디오일 수 있습니다. 하나의 파일에 올바르게 인코딩되고 형식이 지정된 미디어 파일이어야 하며 모두 합쳐야 합니다.

다음은 시스템에서 로컬로 사용할 수 있는 URI에서 재생하는 방법입니다. (예: 콘텐츠 리졸버를 통해 얻은 코드)

Kotlin

val myUri: Uri = .... // initialize Uri here
val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(applicationContext, myUri)
    prepare()
    start()
}

자바

Uri myUri = ....; // initialize Uri here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(getApplicationContext(), myUri);
mediaPlayer.prepare();
mediaPlayer.start();

HTTP 스트리밍을 통해 원격 URL에서 재생하는 방법은 다음과 같습니다.

Kotlin

val url = "http://........" // your URL here
val mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(url)
    prepare() // might take long! (for buffering, etc)
    start()
}

자바

String url = "http://........"; // your URL here
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(url);
mediaPlayer.prepare(); // might take long! (for buffering, etc)
mediaPlayer.start();

참고: 온라인 미디어 파일을 스트리밍하기 위해 URL을 전달하는 경우 파일은 다운로드되어야 합니다.

주의: catch 또는 전달 중 하나를 사용해야 합니다. IllegalArgumentExceptionIOException 사용 시 setDataSource(), 이유 참조하려는 파일이 존재하지 않을 수 있습니다.

비동기 준비

MediaPlayer 사용은 다음에서 간단할 수 있습니다. 제공합니다 하지만 기억해야 할 몇 가지 사항이 더 있습니다. 일반적인 Android 애플리케이션과 올바르게 통합하는 데 필요합니다. 대상 예를 들어 prepare() 호출은 실행하는 데 시간이 오래 걸립니다. 미디어 데이터를 가져오고 디코딩해야 할 수도 있습니다. 따라서 여느 경우와 마찬가지로 시간이 오래 걸릴 수 있는 메서드를 호출하지 마세요. 애플리케이션의 UI 스레드를 반환합니다. 이렇게 하면 메서드가 반환될 때까지 UI가 멈추고 이 경우 매우 부정적인 사용자 환경이 되어 ANR (애플리케이션 응답 없음) 오류가 발생할 수 있습니다. 심지어 리소스가 빠르게 로드될 것으로 예상되는 경우 로드 시간이 10분의 1 이상 눈에 띄는 일시중지가 발생하고 사용자에게 애플리케이션이 느리다는 인상을 줍니다.

UI 스레드가 중단되지 않도록 다른 스레드를 생성하여 MediaPlayer를 준비하고 완료되면 기본 스레드에 알립니다. 그러나 스레딩 로직을 작성하여 이 패턴은 MediaPlayer를 사용할 때 너무 일반적이기 때문에 프레임워크가 는 prepareAsync() 메서드를 사용하여 지도 가장자리에 패딩을 추가할 수 있습니다. 이 방법 백그라운드에서 미디어 준비를 시작하고 즉시 돌아옵니다. 미디어가 준비가 완료되면 onPrepared() 다음을 통해 구성된 MediaPlayer.OnPreparedListener의 메서드 setOnPreparedListener()가 호출됩니다.

상태 관리

MediaPlayer의 또 다른 측면은 다음과 같습니다. 사용할 수 있습니다 즉, MediaPlayer에 내부 상태가 있습니다. 특정 작업은 코드 작성 시 항상 주의해야 하므로 플레이어가 특정 상태에 있는 경우에만 유효합니다. Compute Engine에서 작업을 수행하면 시스템이 예외를 발생시키거나 기타 바람직하지 않은 동작을 유발할 수 있습니다.

자세한 내용은 MediaPlayer 클래스는 전체 상태 다이어그램을 보여줍니다. 는 어떤 메서드가 MediaPlayer 한 상태에서 다른 상태로 이동하는지 명확히 보여줍니다. 예를 들어 새 MediaPlayer를 만들면 유휴 상태가 됩니다. 있습니다. 이 시점에서 다음을 호출하여 초기화해야 합니다. setDataSource()님, 이제 문제가 해결됩니다 초기화 상태로 전환됩니다. 그런 다음 prepare() 또는 prepareAsync() 메서드를 사용하여 지도 가장자리에 패딩을 추가할 수 있습니다. 날짜 MediaPlayer 준비가 완료되면 Prepared 즉, start()를 호출할 수 있습니다. 그것이 미디어를 재생하도록 합니다. 이 시점에서 다이어그램에서 볼 수 있듯이 Started, Pause, PlaybackCompleted 상태 사이를 이동하려면 다음과 같은 메서드를 호출할 수 있습니다. start(), pause()seekTo(), 있습니다. stop()를 호출하면 start()을(를) 다시 호출할 수 없습니다. MediaPlayer를 다시 준비합니다.

항상 상태 다이어그램 유지 코드 작성 시 유념해야 하는 MediaPlayer 객체의 경우 잘못된 상태에서 메서드를 호출하는 것은 버그의 흔한 원인을 보여줍니다.

MediaPlayer 해제

MediaPlayer는 가치 있는 시스템 리소스에 액세스할 수 있습니다 그러므로 항상 각별히 주의하시기 바랍니다. MediaPlayer 인스턴스에 필요한 시간보다 오래 대기하는 경우 끝났으므로 항상 release()하여 제대로 해제되도록 할 수 있습니다. 예를 들어, MediaPlayer를 사용하고 활동이 onStop() 호출을 수신하는 경우 MediaPlayer를 해제해야 합니다. 왜냐하면 활동이 상호 작용하지 않는 동안 그 상태를 유지하는 것은 말이 되지 않습니다. (다음 섹션에서 설명하는 백그라운드에서 미디어를 재생하지 않는 경우) 물론 활동이 재개되거나 다시 시작되면 재생을 재개하기 전에 새 MediaPlayer를 만들고 다시 준비합니다.

다음은 MediaPlayer를 해제한 다음 무효화하는 방법입니다.

Kotlin

mediaPlayer?.release()
mediaPlayer = null

자바

mediaPlayer.release();
mediaPlayer = null;

예를 들어, 데이터 포인트가 너무 많아서 활동이 중지되면 MediaPlayer를 해제하는 것을 잊어버렸지만 새 객체를 생성합니다. 아시다시피 사용자가 화면 방향 (또는 다른 방식으로 기기 구성 변경) 시스템은 기본적으로 활동을 다시 시작하여 이를 처리하므로 (기본값) 시스템 리소스를 모두 사용함에 있어 가로 또는 세로로 기기를 왔다 갔다 해야 합니다 새 MediaPlayer를 만들 때 있습니다. 런타임 다시 시작에 관한 자세한 내용은 런타임 변경 처리를 참조하세요.

게임을 계속 플레이하면 어떻게 될지 궁금할 수 있습니다 "백그라운드 미디어" 사용자가 액티비티를 떠날 때도 마찬가지로 음악 애플리케이션이 작동하는 방식으로 작동합니다. 이 경우 필요한 것은 서비스로 제어되는 MediaPlayer 자세한 내용은 다음 섹션에서

서비스에서 MediaPlayer 사용

애플리케이션이 즉, 사용자가 동영상 광고를 보는 동안에도 계속 재생되도록 상호 작용하는 경우 해당 애플리케이션을 서비스를 제어하고 MediaPlayer 인스턴스를 제거합니다. 이 MediaBrowserServiceCompat 서비스의 MediaPlayer에 할당되었으며 Kubernetes와 다른 활동에서 MediaBrowserCompat입니다.

이 클라이언트/서버 설정에 주의해야 합니다. 예상되는 상황 백그라운드 서비스에서 실행 중인 플레이어가 나머지 애플리케이션과 상호작용하는 방식과 있습니다. 애플리케이션이 이러한 기대를 충족하지 못하는 경우 사용자는 부정적인 경험을 할 수 있습니다. 읽기 오디오 앱 빌드 를 참조하세요.

이 섹션에서는 서비스 내부에서 구현될 때 MediaPlayer를 관리하는 특수 안내를 설명합니다.

비동기 실행

먼저 Activity와 같이 모두 Service는 단일 스레드에서 다음을 통해 실행됩니다. 기본적으로, 사실 동일한 애플리케이션에서 액티비티와 서비스를 실행하면 기본적으로 동일한 스레드('기본 스레드')를 사용합니다. 따라서 서비스는 수신되는 인텐트를 빠르게 처리 응답할 때 긴 계산을 수행하지 않습니다. 무거운 호출 차단이 예상되는 경우 이러한 작업은 비동기식으로 수행해야 합니다. 직접 구현하는 다른 스레드를 사용하거나 프레임워크의 많은 기능을 사용하여 사용할 수 있습니다

예를 들어 기본 스레드에서 MediaPlayer를 사용하는 경우 다음과 같이 prepareAsync()를 호출해야 합니다. prepare(), 구현 MediaPlayer.OnPreparedListener 알림이 전송되고 플레이를 시작할 수 있습니다. 예를 들면 다음과 같습니다.

Kotlin

private const val ACTION_PLAY: String = "com.example.action.PLAY"

class MyService: Service(), MediaPlayer.OnPreparedListener {

    private var mMediaPlayer: MediaPlayer? = null

    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
        ...
        val action: String = intent.action
        when(action) {
            ACTION_PLAY -> {
                mMediaPlayer = ... // initialize it here
                mMediaPlayer?.apply {
                    setOnPreparedListener(this@MyService)
                    prepareAsync() // prepare async to not block main thread
                }

            }
        }
        ...
    }

    /** Called when MediaPlayer is ready */
    override fun onPrepared(mediaPlayer: MediaPlayer) {
        mediaPlayer.start()
    }
}

자바

public class MyService extends Service implements MediaPlayer.OnPreparedListener {
    private static final String ACTION_PLAY = "com.example.action.PLAY";
    MediaPlayer mediaPlayer = null;

    public int onStartCommand(Intent intent, int flags, int startId) {
        ...
        if (intent.getAction().equals(ACTION_PLAY)) {
            mediaPlayer = ... // initialize it here
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.prepareAsync(); // prepare async to not block main thread
        }
    }

    /** Called when MediaPlayer is ready */
    public void onPrepared(MediaPlayer player) {
        player.start();
    }
}

비동기 오류 처리

동기 작업에서 오류는 일반적으로 예외 또는 오류 코드와 함께 신호를 받을 수 있지만 비동기식으로 애플리케이션에 대한 알림을 받도록 적절한 조치를 취할 수 있습니다 MediaPlayer의 경우 이렇게 하려면 MediaPlayer.OnErrorListenerMediaPlayer 인스턴스에서 설정합니다.

Kotlin

class MyService : Service(), MediaPlayer.OnErrorListener {

    private var mediaPlayer: MediaPlayer? = null

    fun initMediaPlayer() {
        // ...initialize the MediaPlayer here...
        mediaPlayer?.setOnErrorListener(this)
    }

    override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean {
        // ... react appropriately ...
        // The MediaPlayer has moved to the Error state, must be reset!
    }
}

자바

public class MyService extends Service implements MediaPlayer.OnErrorListener {
    MediaPlayer mediaPlayer;

    public void initMediaPlayer() {
        // ...initialize the MediaPlayer here...
        mediaPlayer.setOnErrorListener(this);
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        // ... react appropriately ...
        // The MediaPlayer has moved to the Error state, must be reset!
    }
}

오류가 발생하면 MediaPlayerError 상태가 됩니다 (자세한 내용은 전체 상태 다이어그램의 MediaPlayer 클래스) 재설정해야 다시 사용할 수 있습니다.

wake lock 사용

미디어를 재생하는 애플리케이션을 설계할 때 백그라운드에서 기기가 절전 모드로 전환될 수 있음 서비스 실행 중에만 다를 수 있습니다 Android 시스템은 배터리가 방전되면 시스템은 시스템을 휴대전화의 기능을 CPU 및 WiFi 하드웨어를 포함하여 필요하지 않습니다. 하지만 서비스에서 음악을 재생하거나 스트리밍하는 경우에는 방해하지 않도록 하기 위한 것입니다.

서비스가 중단 없이 계속 실행되도록 하기 위해 'wake lock'을 사용해야 합니다 wake lock은 애플리케이션이 사용 중인 시스템에서 휴대전화가 유휴 상태일 때도 사용 가능한 상태를 유지할 수 있습니다

참고: wake lock은 항상 가끔씩만 사용하고 유지해야 합니다. 이러한 방식으로 작동하면 기기의 배터리 수명이 크게 줄어들기 때문에 실제로 필요한 만큼만 있습니다.

MediaPlayer이(가) 실행되는 동안 CPU가 계속 실행되도록 하기 위해 재생 중인 경우 MediaPlayer를 초기화할 때 setWakeMode() 메서드를 호출합니다. 일단 선택하면 MediaPlayer가 재생하는 동안 지정된 잠금을 유지하고 잠금을 해제합니다. :

Kotlin

mediaPlayer = MediaPlayer().apply {
    // ... other initialization here ...
    setWakeMode(applicationContext, PowerManager.PARTIAL_WAKE_LOCK)
}

자바

mediaPlayer = new MediaPlayer();
// ... other initialization here ...
mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);

그러나 이 예에서 습득한 wake lock은 CPU의 절전모드가 해제된 상태만을 보장합니다. 만약 미디어를 스트리밍하거나 Wi-Fi를 사용 중인 경우에는 WifiLock 유형: 수동으로 가져와 해제해야 합니다. 데이터 레이크를 MediaPlayer를 원격 URL로 대체하려면 Wi-Fi 잠금을 만들고 획득해야 합니다. 예를 들면 다음과 같습니다.

Kotlin

val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager
val wifiLock: WifiManager.WifiLock =
    wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock")

wifiLock.acquire()

자바

WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE))
    .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock");

wifiLock.acquire();

미디어를 일시중지 또는 중지하거나 더 이상 잠금을 해제해야 합니다.

Kotlin

wifiLock.release()

자바

wifiLock.release();

정리 실행

앞서 언급했듯이 MediaPlayer 객체는 상당한 양의 많은 시스템 리소스가 있으므로 필요한 만큼만 유지하고 완료되면 release()입니다. 중요한 것은 시스템 가비지 컬렉션에 의존하지 않고 명시적으로 이 정리 메서드를 호출할 수 있습니다. 가비지 컬렉터가 MediaPlayer를 회수하는 데 시간이 걸릴 수 있습니다. 이는 메모리 요구 사항에만 민감하고 다른 미디어 관련 리소스의 부족에는 영향을 주지 않기 때문입니다. 따라서 서비스를 사용하는 경우 항상 onDestroy() 메서드를 사용하여 MediaPlayer:

Kotlin

class MyService : Service() {

    private var mediaPlayer: MediaPlayer? = null
    // ...

    override fun onDestroy() {
        super.onDestroy()
        mediaPlayer?.release()
    }
}

자바

public class MyService extends Service {
   MediaPlayer mediaPlayer;
   // ...

   @Override
   public void onDestroy() {
       super.onDestroy();
       if (mediaPlayer != null) mediaPlayer.release();
   }
}

MediaPlayer이(가) 해제될 수 있는 다른 기회를 항상 확인해야 합니다. 종료할 때 해제하는 것 외에는 할 수 없습니다. 예를 들어 장시간 미디어 재생 (예: 오디오 포커스를 잃은 후) 기존 MediaPlayer을(를) 해제하고 다시 만들어야 합니다. 확인할 수 있습니다 일 반면에 아주 짧은 시간 동안만 재생을 중지할 것으로 예상되는 경우라면 만들고 준비하는 오버헤드가 없도록 MediaPlayer를 유지하세요. 다시 시도합니다.

디지털 권한 관리(DRM)

Android 8.0 (API 수준 26)부터 MediaPlayer에는 DRM으로 보호된 자료의 재생을 지원합니다. API가 제공하는 하위 수준 API와 유사합니다. MediaDrm이지만 더 높은 수준에서 작동하고 기본 추출기, DRM 및 암호화 객체를 노출합니다.

MediaPlayer DRM API는 MediaDrm는 가장 일반적인 사용 사례를 지원합니다. 이 현재 구현은 다음 콘텐츠 유형을 처리할 수 있습니다.

  • Widevine으로 보호되는 로컬 미디어 파일
  • Widevine으로 보호되는 원격/스트리밍 미디어 파일

다음 코드 스니펫은 새 DRM MediaPlayer 사용 방법을 보여줍니다. 메서드를 호출할 수 있습니다.

DRM 제어 미디어를 관리하려면 새로운 메서드를 MediaPlayer 호출의 일반적인 흐름을 보여줍니다.

Kotlin

mediaPlayer?.apply {
    setDataSource()
    setOnDrmConfigHelper() // optional, for custom configuration
    prepare()
    drmInfo?.also {
        prepareDrm()
        getKeyRequest()
        provideKeyResponse()
    }

    // MediaPlayer is now ready to use
    start()
    // ...play/pause/resume...
    stop()
    releaseDrm()
}

자바

setDataSource();
setOnDrmConfigHelper(); // optional, for custom configuration
prepare();
if (getDrmInfo() != null) {
  prepareDrm();
  getKeyRequest();
  provideKeyResponse();
}

// MediaPlayer is now ready to use
start();
// ...play/pause/resume...
stop();
releaseDrm();

MediaPlayer 객체를 초기화하고 설정하여 시작합니다. setDataSource()를 사용하여 평소처럼 말이죠 그리고 나서 DRM을 사용하려면 다음 단계를 따르세요.

  1. 앱에서 맞춤 구성을 수행하도록 하려면 OnDrmConfigHelper 인터페이스를 열고 이를 플레이어 setOnDrmConfigHelper()입니다.
  2. prepare()를 호출합니다.
  3. getDrmInfo()를 호출합니다. 소스에 DRM이 있는 경우 메서드는 null이 아닌 값을 반환합니다. MediaPlayer.DrmInfo 값입니다.

MediaPlayer.DrmInfo가 있으면 다음 단계를 따르세요.

  1. 사용 가능한 UUID의 지도를 검사하고 하나를 선택합니다.
  2. prepareDrm()을 호출하여 현재 소스의 DRM 구성을 준비합니다.
    • Google 애널리틱스 계정을 만들고 OnDrmConfigHelper 콜백에서는 prepareDrm() 동안 확인할 수 있습니다 이렇게 하면 DRM의 맞춤 구성을 수행할 수 있습니다. 속성을 변경해야 합니다. 콜백은 호출한 스레드에서 동기식으로 prepareDrm() 받는사람 DRM 속성에 액세스하려면 getDrmPropertyString()setDrmPropertyString()입니다. 너무 긴 작업은 실행하지 마세요.
    • 기기가 아직 프로비저닝되지 않은 경우 추가로 prepareDrm() 프로비저닝 서버에 액세스하여 기기를 프로비저닝합니다. 이 작업은 가변적인 시간을 소비할 수 있습니다.
  3. 불투명한 키 요청 바이트 배열을 가져와서 라이선스 서버로 전송하려면 다음을 호출합니다. getKeyRequest()
  4. 라이선스 서버에서 수신한 키 응답을 DRM 엔진에 알리려면 provideKeyResponse() 결과는 키 요청 유형에 따라 다릅니다. <ph type="x-smartling-placeholder">
      </ph>
    • 응답이 오프라인 키 요청에 관한 것이면 결과는 키 세트 식별자입니다. 이때 이 키 세트 식별자를 restoreKeys()로 설정하여 키를 새로운 세션입니다.
    • 응답이 스트리밍 또는 해제 요청에 관한 것이면 결과는 null입니다.

비동기적으로 prepareDrm() 실행

기본적으로 prepareDrm() 동기식으로 실행되어 준비가 완료될 때까지 차단됩니다. 그러나 새 기기에서 처음으로 DRM을 준비하려면 프로비저닝이 필요할 수 있습니다. 내부에서 처리 prepareDrm() 및 관련 네트워크 작업으로 인해 완료하는 데 다소 시간이 걸릴 수 있습니다. 다음과 같은 작업을 할 수 있습니다. 차단 피하기 prepareDrm() 기준 MediaPlayer.OnDrmPreparedListener 정의 및 설정

OnDrmPreparedListener를 설정하면 prepareDrm() 백그라운드에서 프로비저닝 (필요한 경우) 및 준비를 수행합니다. 날짜 프로비저닝과 준비가 완료되면 리스너가 호출됩니다. 해야 할 일 호출 시퀀스나 코드가 호출되는 스레드에 대해 리스너가 실행됩니다 (리스너가 핸들러 스레드에 등록되지 않은 경우). 리스너는 호출 이전이나 이후에 호출할 수 있습니다. prepareDrm() 반환합니다.

비동기적으로 DRM 설정

DRM을 비동기식으로 초기화할 수 있습니다. MediaPlayer.OnDrmInfoListener는 DRM 준비 및 MediaPlayer.OnDrmPreparedListener: 플레이어를 시작합니다. 또한 인코더와 디코더는 prepareAsync()를 사용해야 합니다.

Kotlin

setOnPreparedListener()
setOnDrmInfoListener()
setDataSource()
prepareAsync()
// ...

// If the data source content is protected you receive a call to the onDrmInfo() callback.
override fun onDrmInfo(mediaPlayer: MediaPlayer, drmInfo: MediaPlayer.DrmInfo) {
    mediaPlayer.apply {
        prepareDrm()
        getKeyRequest()
        provideKeyResponse()
    }
}

// When prepareAsync() finishes, you receive a call to the onPrepared() callback.
// If there is a DRM, onDrmInfo() sets it up before executing this callback,
// so you can start the player.
override fun onPrepared(mediaPlayer: MediaPlayer) {
    mediaPlayer.start()
}

자바

setOnPreparedListener();
setOnDrmInfoListener();
setDataSource();
prepareAsync();
// ...

// If the data source content is protected you receive a call to the onDrmInfo() callback.
onDrmInfo() {
  prepareDrm();
  getKeyRequest();
  provideKeyResponse();
}

// When prepareAsync() finishes, you receive a call to the onPrepared() callback.
// If there is a DRM, onDrmInfo() sets it up before executing this callback,
// so you can start the player.
onPrepared() {

start();
}

암호화된 미디어 처리

Android 8.0 (API 수준 26)부터 MediaPlayer는 복호화할 수도 있습니다. 공통 암호화 체계 (CENC) 및 기본 스트림 유형에 대한 HLS 샘플 수준 암호화된 미디어 (METHOD=샘플-AES) H.264 및 AAC입니다. 전체 세그먼트 암호화된 미디어(METHOD=AES-128)는 이전에 지원되었습니다.

ContentResolver에서 미디어 검색

미디어 플레이어 애플리케이션에서 유용할 수 있는 또 다른 기능은 사용자가 기기에 있는 음악을 검색할 수 있습니다. 외부 미디어의 ContentResolver를 쿼리하여 검색할 수 있습니다.

Kotlin

val resolver: ContentResolver = contentResolver
val uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val cursor: Cursor? = resolver.query(uri, null, null, null, null)
when {
    cursor == null -> {
        // query failed, handle error.
    }
    !cursor.moveToFirst() -> {
        // no media on the device
    }
    else -> {
        val titleColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE)
        val idColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID)
        do {
            val thisId = cursor.getLong(idColumn)
            val thisTitle = cursor.getString(titleColumn)
            // ...process entry...
        } while (cursor.moveToNext())
    }
}
cursor?.close()

자바

ContentResolver contentResolver = getContentResolver();
Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
Cursor cursor = contentResolver.query(uri, null, null, null, null);
if (cursor == null) {
    // query failed, handle error.
} else if (!cursor.moveToFirst()) {
    // no media on the device
} else {
    int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE);
    int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID);
    do {
       long thisId = cursor.getLong(idColumn);
       String thisTitle = cursor.getString(titleColumn);
       // ...process entry...
    } while (cursor.moveToNext());
}

MediaPlayer로 이 기능을 사용하려면 다음을 실행하면 됩니다.

Kotlin

val id: Long = /* retrieve it from somewhere */
val contentUri: Uri =
    ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id )

mediaPlayer = MediaPlayer().apply {
    setAudioAttributes(
        AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .build()
    )
    setDataSource(applicationContext, contentUri)
}

// ...prepare and start...

자바

long id = /* retrieve it from somewhere */;
Uri contentUri = ContentUris.withAppendedId(
        android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id);

mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioAttributes(
    new AudioAttributes.Builder()
        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
        .setUsage(AudioAttributes.USAGE_MEDIA)
        .build()
);
mediaPlayer.setDataSource(getApplicationContext(), contentUri);

// ...prepare and start...

자세히 알아보기

이 페이지에서는 오디오와 동영상 녹음/녹화, 저장 및 재생과 관련된 주제를 다룹니다.