Lavorare con MediaPlayer e DRM (Digital Rights Management)

A partire da Android 8.0 (livello API 26), MediaPlayer include API che supportano la riproduzione di materiale protetto da DRM. Le API MediaPlayer DRM sono simili all'API di basso livello fornita da MediaDrm, ma operano a un livello superiore e non espongono gli oggetti di estrazione, DRM e crittografia sottostanti.

Sebbene l'API MediaPlayer DRM non fornisca la funzionalità completa di MediaDrm, supporta i casi d'uso più comuni. L'attuale implementazione può gestire i seguenti tipi di contenuti:

  • File multimediali locali protetti da Widevine
  • File multimediali in streaming o remoti protetti da Widevine

Il seguente snippet di codice mostra come utilizzare i nuovi metodi DRM MediaPlayer in un'implementazione sincrona.

Per gestire i contenuti multimediali con DRM, devi includere i nuovi metodi insieme al normale flusso di chiamate MediaPlayer, come mostrato in questo esempio:

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();

Inizia inizializzando l'oggetto MediaPlayer e impostandone l'origine utilizzando setDataSource(), come di consueto. Per utilizzare il DRM, segui questi passaggi:

  1. Se vuoi che la tua app esegua una configurazione personalizzata, definisci un'interfaccia OnDrmConfigHelper e associala al player utilizzando setOnDrmConfigHelper().
  2. Chiama il numero prepare().
  3. Chiama il numero getDrmInfo(). Se l'origine contiene contenuti DRM, il metodo restituisce un valore MediaPlayer.DrmInfo non nullo.

Se MediaPlayer.DrmInfo esiste:

  1. Esamina la mappa degli UUID disponibili e scegline uno.
  2. Prepara la configurazione DRM per l'origine corrente chiamando prepareDrm().
    • Se hai creato e registrato un callback OnDrmConfigHelper, viene chiamato durante l'esecuzione di prepareDrm(). In questo modo puoi eseguire la configurazione personalizzata delle proprietà DRM prima di aprire la sessione DRM. Il callback viene chiamato in modo sincrono nel thread che ha chiamato prepareDrm(). Per accedere alle proprietà DRM, chiama getDrmPropertyString() e setDrmPropertyString(). Evita di eseguire operazioni lunghe.
    • Se il provisioning del dispositivo non è ancora stato eseguito, prepareDrm() accede anche al server di provisioning per eseguire il provisioning del dispositivo. Questa operazione può richiedere un tempo variabile, a seconda della connettività di rete.
  3. Per ottenere un array di byte di richiesta di chiave opaca da inviare a un server delle licenze, chiama getKeyRequest().
  4. Per informare il motore DRM della risposta della chiave ricevuta dal server delle licenze, chiama provideKeyResponse(). Il risultato dipende dal tipo di richiesta di chiave:
    • Se la risposta riguarda una richiesta di chiave offline, il risultato è un identificatore di set di chiavi. Puoi utilizzare questo identificatore dell'insieme di chiavi con restoreKeys() per ripristinare le chiavi in una nuova sessione.
    • Se la risposta riguarda una richiesta di streaming o di uscita, il risultato è nullo.

Preparare il DRM in modo asincrono

Per impostazione predefinita, prepareDrm() viene eseguito in modo sincrono e si blocca fino al completamento della preparazione. Tuttavia, la prima preparazione DRM su un nuovo dispositivo potrebbe anche richiedere il provisioning, gestito internamente da prepareDrm(), e potrebbe richiedere un po' di tempo per essere completata a causa delle operazioni di rete coinvolte. Puoi evitare il blocco su prepareDrm() definendo e impostando un MediaPlayer.OnDrmPreparedListener.

Imposta un OnDrmPreparedListener. prepareDrm() esegue il provisioning (se necessario) e la preparazione in background. Al termine del provisioning e della preparazione, il sistema chiama l'ascoltatore. Non fare supposizioni sulla sequenza di chiamate o sul thread in cui viene eseguito l'ascoltatore (a meno che non registri l'ascoltatore con un thread di gestore). Il sistema può chiamare il listener prima o dopo il ritorno di prepareDrm().

Configurare il DRM in modo asincrono

Puoi inizializzare il DRM in modo asincrono creando e registrando il messaggio MediaPlayer.OnDrmInfoListener per la preparazione del DRM e il messaggio MediaPlayer.OnDrmPreparedListener per avviare il player. Funzionano in combinazione con prepareAsync(), come mostrato in questo esempio:

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

Gestire i contenuti multimediali criptati

A partire da Android 8.0 (livello API 26), MediaPlayer può anche decriptare i contenuti multimediali criptati a livello di Sample con Common Encryption Scheme (CENC) e HLS (METHOD=SAMPLE-AES) per i tipi di stream elementari H.264 e AAC. In precedenza, i contenuti multimediali con crittografia del segmento completo (METHOD=AES-128) erano supportati.

Scopri di più

Jetpack Media3 è la soluzione consigliata per la riproduzione di contenuti multimediali nella tua app. Scopri di più.

Queste pagine trattano argomenti relativi alla registrazione, allo stoccaggio e alla riproduzione di audio e video: