從 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()
會在內部處理此作業,且由於涉及網路作業,因此可能需要一些時間才能完成。您可以定義並設定 MediaPlayer.OnDrmPreparedListener
,避免在 prepareDrm()
上發生封鎖。
設定 OnDrmPreparedListener
。prepareDrm()
會在背景執行佈建作業 (如有需要) 和準備作業。佈建和準備程序完成後,系統會呼叫監聽器。請勿對呼叫序列或事件監聽器執行的執行緒做出任何假設 (除非您使用處理常式執行緒註冊事件監聽器)。系統可以在 prepareDrm()
回傳之前或之後呼叫監聽器。
非同步設定 DRM
您可以建立並註冊 MediaPlayer.OnDrmInfoListener
來準備 DRM,並註冊 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()
}
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
也能為基本串流類型 H.264 和 AAC 解密通用加密方案 (CENC) 和 HLS 樣本層級加密媒體 (METHOD=SAMPLE-AES)。我們先前支援全片段加密媒體 (METHOD=AES-128)。
瞭解詳情
如要在應用程式中播放媒體,建議您採用 Jetpack Media3 解決方案。請參閱更多資訊。
以下頁面將說明錄製、儲存及播放音訊和影片的相關主題: