MediaPlayer 및 디지털 권한 관리 (DRM) 사용
컬렉션을 사용해 정리하기
내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
Android 8.0 (API 수준 26)부터 MediaPlayer
에는 DRM으로 보호되는 자료의 재생을 지원하는 API가 포함됩니다. MediaPlayer DRM API는 MediaDrm
에서 제공하는 낮은 수준의 API와 유사하지만 더 높은 수준에서 작동하고 기본 추출기, 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을 사용하려면 다음 단계를 따르세요.
- 앱에서 맞춤 구성을 실행하려면
OnDrmConfigHelper
인터페이스를 정의하고 setOnDrmConfigHelper()
를 사용하여 플레이어에 연결합니다.
prepare()
을 호출합니다.
getDrmInfo()
을 호출합니다. 소스에 DRM 콘텐츠가 있으면 메서드는 null이 아닌 MediaPlayer.DrmInfo
값을 반환합니다.
MediaPlayer.DrmInfo
가 있는 경우:
- 사용 가능한 UUID의 지도를 검사하고 하나를 선택합니다.
prepareDrm()
를 호출하여 현재 소스의 DRM 구성을 준비합니다.
- 불투명한 키 요청 바이트 배열을 가져와 라이선스 서버로 전송하려면
getKeyRequest()
를 호출합니다.
- 라이선스 서버에서 수신한 키 응답을 DRM 엔진에 알리려면
provideKeyResponse()
를 호출합니다. 결과는 키 요청 유형에 따라 달라집니다.
- 응답이 오프라인 키 요청에 관한 것이면 결과는 키 세트 식별자입니다. 이 키 세트 식별자를
restoreKeys()
와 함께 사용하여 키를 새 세션으로 복원할 수 있습니다.
- 응답이 스트리밍 또는 해제 요청에 관한 것이면 결과는 null입니다.
비동기식으로 DRM 준비
기본적으로 prepareDrm()
은 동기식으로 실행되어 준비가 완료될 때까지 차단됩니다. 그러나 새 기기에서 맨 첫 번째 DRM 준비에는 prepareDrm()
에서 내부적으로 처리하는 프로비저닝이 필요할 수도 있으며 관련된 네트워크 작업으로 인해 완료되는 데 시간이 좀 걸릴 수 있습니다. MediaPlayer.OnDrmPreparedListener
를 정의하고 설정하여 prepareDrm()
에서 차단을 방지할 수 있습니다.
OnDrmPreparedListener
를 설정합니다. prepareDrm()
은 백그라운드에서 프로비저닝 (필요한 경우)과 준비를 실행합니다. 프로비저닝과 준비가 완료되면 시스템은 리스너를 호출합니다. 호출 시퀀스나 리스너가 실행되는 스레드에 관해 어떤 가정도 해서는 안 됩니다. 리스너를 핸들러 스레드에 등록하는 경우는 예외입니다. 시스템은 prepareDrm()
가 반환되기 전이나 후에 리스너를 호출할 수 있습니다.
비동기식으로 DRM 설정
DRM 준비를 위한 MediaPlayer.OnDrmInfoListener
와 플레이어를 시작하기 위한 MediaPlayer.OnDrmPreparedListener
를 만들고 등록하여 DRM을 비동기적으로 초기화할 수 있습니다. 다음 예와 같이 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
는 기본 스트림 유형 H.264 및 AAC에 관해 Common Encryption Scheme (CENC) 및 HLS 샘플 레벨 암호화된 미디어(METHOD=SAMPLE-AES)를 복호화할 수도 있습니다. 전체 세그먼트 암호화된 미디어 (METHOD=AES-128)는 이전에 지원되었습니다.
자세히 알아보기
Jetpack Media3는 앱에서 미디어를 재생하는 데 권장되는 솔루션입니다. 자세한 내용은 자세히 알아보세요.
이 페이지에서는 오디오와 동영상 녹음/녹화, 저장 및 재생과 관련된 주제를 다룹니다.
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-07-27(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-07-27(UTC)"],[],[],null,["# Work with MediaPlayer and Digital Rights Management (DRM)\n\nStarting with Android 8.0 (API level 26), [`MediaPlayer`](/reference/android/media/MediaPlayer) includes APIs that\nsupport the playback of DRM-protected material. The MediaPlayer DRM APIs are\nsimilar to the low-level API provided by [`MediaDrm`](/reference/android/media/MediaDrm), but they operate at a\nhigher level and don't expose the underlying extractor, DRM, and crypto objects.\n\nAlthough the MediaPlayer DRM API does not provide the full functionality of\n[`MediaDrm`](/reference/android/media/MediaDrm), it supports the most common use cases. The current\nimplementation can handle the following content types:\n\n- Widevine-protected local media files\n- Widevine-protected remote or streaming media files\n\nThe following code snippet demonstrates how to use the new DRM `MediaPlayer`\nmethods in a synchronous implementation.\n\nTo manage DRM-controlled media, you need to include the new methods alongside\nthe usual flow of MediaPlayer calls, as shown in this example: \n\n### Kotlin\n\n mediaPlayer?.apply {\n setDataSource()\n setOnDrmConfigHelper() // optional, for custom configuration\n prepare()\n drmInfo?.also {\n prepareDrm()\n getKeyRequest()\n provideKeyResponse()\n }\n\n // MediaPlayer is now ready to use\n start()\n // ...play/pause/resume...\n stop()\n releaseDrm()\n }\n\n### Java\n\n setDataSource();\n setOnDrmConfigHelper(); // optional, for custom configuration\n prepare();\n if (getDrmInfo() != null) {\n prepareDrm();\n getKeyRequest();\n provideKeyResponse();\n }\n\n // MediaPlayer is now ready to use\n start();\n // ...play/pause/resume...\n stop();\n releaseDrm();\n\nStart by initializing the [`MediaPlayer`](/reference/android/media/MediaPlayer) object and setting its source using\n[`setDataSource()`](/reference/android/media/MediaPlayer#setDataSource(android.content.Context,%20android.net.Uri)), as usual. Then, to use DRM, perform these steps:\n\n1. If you want your app to perform custom configuration, define an [`OnDrmConfigHelper`](/reference/android/media/MediaPlayer.OnDrmConfigHelper) interface, and attach it to the player using [`setOnDrmConfigHelper()`](/reference/android/media/MediaPlayer#setOnDrmConfigHelper(android.media.MediaPlayer.OnDrmConfigHelper)).\n2. Call [`prepare()`](/reference/android/media/MediaPlayer#prepare()).\n3. Call [`getDrmInfo()`](/reference/android/media/MediaPlayer#getDrmInfo()). If the source has DRM content, the method returns a non-null [`MediaPlayer.DrmInfo`](/reference/android/media/MediaPlayer.DrmInfo) value.\n\nIf [`MediaPlayer.DrmInfo`](/reference/android/media/MediaPlayer.DrmInfo) exists:\n\n1. Examine the map of available UUIDs and choose one.\n2. Prepare the DRM configuration for the current source by calling [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)).\n - If you created and registered an [`OnDrmConfigHelper`](/reference/android/media/MediaPlayer.OnDrmConfigHelper) callback, it is called while [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)) is executing. This lets you perform custom configuration of the DRM properties before opening the DRM session. The callback is called synchronously in the thread that called [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)). To access the DRM properties, call [`getDrmPropertyString()`](/reference/android/media/MediaPlayer#getDrmPropertyString(java.lang.String)) and [`setDrmPropertyString()`](/reference/android/media/MediaPlayer#setDrmPropertyString(java.lang.String,%20java.lang.String)). Avoid performing lengthy operations.\n - If the device has not yet been provisioned, [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)) also accesses the provisioning server to provision the device. This can take a variable amount of time, depending on the network connectivity.\n3. To get an opaque key request byte array to send to a license server, call [`getKeyRequest()`](/reference/android/media/MediaPlayer#getKeyRequest(byte%5B%5D,%20byte%5B%5D,%20java.lang.String,%20int,%20java.util.Map%3Cjava.lang.String,%20java.lang.String%3E)).\n4. To inform the DRM engine about the key response received from the license server, call [`provideKeyResponse()`](/reference/android/media/MediaPlayer#provideKeyResponse(byte%5B%5D,%20byte%5B%5D)). The result depends on the type of key request:\n - If the response is for an offline key request, the result is a key-set identifier. You can use this key-set identifier with [`restoreKeys()`](/reference/android/media/MediaPlayer#restoreKeys(byte%5B%5D)) to restore the keys to a new session.\n - If the response is for a streaming or release request, the result is null.\n\nPrepare DRM asynchronously\n--------------------------\n\nBy default, [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)) runs synchronously, blocking until preparation\nfinishes. However, the very first DRM preparation on a new device may also\nrequire provisioning, which [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)) handles internally, and may take\nsome time to finish due to the network operation involved. You can avoid\nblocking on [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)) by defining and setting a\n[`MediaPlayer.OnDrmPreparedListener`](/reference/android/media/MediaPlayer.OnDrmPreparedListener).\n\nSet an [`OnDrmPreparedListener`](/reference/android/media/MediaPlayer.OnDrmPreparedListener). [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)) performs the\nprovisioning (if needed) and preparation in the background. When provisioning\nand preparation finish, the system calls the listener. Don't make any\nassumptions about the calling sequence or the thread in which the listener runs\n(unless you register the listener with a handler thread). The system can call\nthe listener before or after [`prepareDrm()`](/reference/android/media/MediaPlayer#prepareDrm(java.util.UUID)) returns.\n\nSet up DRM asynchronously\n-------------------------\n\nYou can initialize the DRM asynchronously by creating and registering the\n[`MediaPlayer.OnDrmInfoListener`](/reference/android/media/MediaPlayer.OnDrmInfoListener) for DRM preparation and the\n[`MediaPlayer.OnDrmPreparedListener`](/reference/android/media/MediaPlayer.OnDrmPreparedListener) to start the player. They work in\nconjunction with [`prepareAsync()`](/reference/android/media/MediaPlayer#prepareAsync()), as shown in this example: \n\n### Kotlin\n\n setOnPreparedListener()\n setOnDrmInfoListener()\n setDataSource()\n prepareAsync()\n // ...\n\n // If the data source content is protected you receive a call to the onDrmInfo() callback.\n override fun onDrmInfo(mediaPlayer: MediaPlayer, drmInfo: MediaPlayer.DrmInfo) {\n mediaPlayer.apply {\n prepareDrm()\n getKeyRequest()\n provideKeyResponse()\n }\n }\n\n // When prepareAsync() finishes, you receive a call to the onPrepared() callback.\n // If there is a DRM, onDrmInfo() sets it up before executing this callback,\n // so you can start the player.\n override fun onPrepared(mediaPlayer: MediaPlayer) {\n mediaPlayer.start()\n }\n\n### Java\n\n setOnPreparedListener();\n setOnDrmInfoListener();\n setDataSource();\n prepareAsync();\n // ...\n\n // If the data source content is protected you receive a call to the onDrmInfo() callback.\n onDrmInfo() {\n prepareDrm();\n getKeyRequest();\n provideKeyResponse();\n }\n\n // When prepareAsync() finishes, you receive a call to the onPrepared() callback.\n // If there is a DRM, onDrmInfo() sets it up before executing this callback,\n // so you can start the player.\n onPrepared() {\n\n start();\n }\n\nHandle encrypted media\n----------------------\n\nStarting with Android 8.0 (API level 26) `MediaPlayer` can also decrypt Common\nEncryption Scheme (CENC) and HLS sample-level encrypted media\n(METHOD=SAMPLE-AES) for the elementary stream types H.264, and AAC. Full-segment\nencrypted media (METHOD=AES-128) was previously supported.\n\nLearn more\n----------\n\nJetpack Media3 is the recommended solution for media playback in your app. [Read\nmore](/media/media3) about it.\n\nThese pages cover topics relating to recording, storing, and playing back audio\nand video:\n\n- [Supported Media Formats](/guide/topics/media/media-formats)\n- [MediaRecorder](/guide/topics/media/mediarecorder)\n- [Data Storage](/guide/topics/data/data-storage)"]]