從 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()
}
Java
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 內容,這個方法會傳回非空值的MediaPlayer.DrmInfo值。
如果 MediaPlayer.DrmInfo 存在:
- 查看可用 UUID 的對應表,然後選擇一個。
- 呼叫
prepareDrm(),準備目前來源的 DRM 設定。- 如果您建立並註冊
OnDrmConfigHelper回呼,系統會在prepareDrm()執行時呼叫該回呼。這樣一來,您就能在開啟 DRM 工作階段前,自訂 DRM 屬性。回呼會在呼叫prepareDrm()的執行緒中同步呼叫。如要存取 DRM 屬性,請呼叫getDrmPropertyString()和setDrmPropertyString()。避免執行耗時的作業。 - 如果裝置尚未佈建,
prepareDrm()也會存取佈建伺服器來佈建裝置。視網路連線而定,這項作業可能需要一段時間才能完成。
- 如果您建立並註冊
- 如要取得不透明金鑰要求位元組陣列,並傳送至授權伺服器,請呼叫
getKeyRequest()。 - 如要將授權伺服器傳回的金鑰回應告知 DRM 引擎,請呼叫
provideKeyResponse()。結果取決於金鑰要求類型:- 如果回應是針對離線金鑰要求,結果會是金鑰集 ID。您可以使用這個金鑰集 ID 和
restoreKeys(),將金鑰還原至新工作階段。 - 如果是串流或發行要求的回應,結果會是空值。
- 如果回應是針對離線金鑰要求,結果會是金鑰集 ID。您可以使用這個金鑰集 ID 和
以非同步方式準備 DRM
根據預設,prepareDrm() 會同步執行,並封鎖直到準備完成為止。不過,在新裝置上首次準備 DRM 時,可能也需要佈建,這項作業由 prepareDrm() 內部處理,且由於涉及網路作業,可能需要一段時間才能完成。如要避免 prepareDrm() 發生封鎖,請定義並設定 MediaPlayer.OnDrmPreparedListener。
設定 OnDrmPreparedListener。prepareDrm() 會在背景執行佈建 (如有需要) 和準備作業。當佈建和準備完成時,系統會呼叫接聽程式。請勿對呼叫順序或執行監聽器的執行緒做出任何假設 (除非您使用處理常式執行緒註冊監聽器)。系統可以在 prepareDrm() 傳回之前或之後呼叫監聽器。
以非同步方式設定 DRM
您可以建立及註冊 MediaPlayer.OnDrmInfoListener,以非同步方式初始化 DRM,準備 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()
}
Java
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=SAMPLE-AES),適用於基本串流類型 H.264 和 AAC。先前支援全區段加密媒體 (METHOD=AES-128)。
瞭解詳情
建議您使用 Jetpack Media3 在應用程式中播放媒體。進一步瞭解。
這些頁面涵蓋音訊和影片的錄製、儲存及播放相關主題: