A partir de Android 8.0 (nivel de API 26), MediaPlayer
incluye APIs que son compatibles con la reproducción de material protegido por DRM. Las APIs de DRM de MediaPlayer son similares a las APIs de bajo nivel que proporciona MediaDrm
, pero funcionan a un nivel más alto y no exponen a los objetos de extractor, DRM y criptografía subyacentes.
Si bien la API de DRM de MediaPlayer no proporciona la funcionalidad completa de MediaDrm
, admite los casos de uso más comunes. La implementación actual puede controlar los siguientes tipos de contenido:
- Archivos de medios locales protegidos por Widevine
- Archivos multimedia de transmisión o control remoto protegidos por Widevine
En el siguiente fragmento de código, se demuestra cómo usar los nuevos métodos MediaPlayer
de DRM en una implementación síncrona.
Para administrar medios controlados por DRM, debes incluir los nuevos métodos junto con el flujo habitual de llamadas de MediaPlayer, como se muestra en este ejemplo:
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();
Para comenzar, inicializa el objeto MediaPlayer
y establece su fuente con setDataSource()
, como de costumbre. Luego, para usar DRM, sigue estos pasos:
- Si quieres que tu app realice una configuración personalizada, define una interfaz
OnDrmConfigHelper
y adjúntala al reproductor mediantesetOnDrmConfigHelper()
. - Llama a
prepare()
. - Llama a
getDrmInfo()
. Si la fuente tiene contenido DRM, el método muestra un valor no nulo deMediaPlayer.DrmInfo
.
Si MediaPlayer.DrmInfo
existe:
- Examina el mapa de UUID disponibles y elige uno.
- Llama a
prepareDrm()
para preparar la configuración de DRM para la fuente actual.- Si creaste y registraste una devolución de llamada de
OnDrmConfigHelper
, se la llama mientras se está ejecutandoprepareDrm()
. Esto te permite realizar una configuración personalizada de las propiedades de DRM antes de abrir la sesión de DRM. Se realiza la devolución de llamada de manera síncrona en el subproceso que llamó aprepareDrm()
. Para acceder a las propiedades de DRM, llama agetDrmPropertyString()
ysetDrmPropertyString()
. Evita realizar operaciones prolongadas. - Si aún no se aprovisionó el dispositivo,
prepareDrm()
también accede al servidor de aprovisionamiento para hacerlo. La duración de esta operación puede variar según la conectividad de la red.
- Si creaste y registraste una devolución de llamada de
- Para obtener un arreglo de bytes de solicitud de clave opaca para enviar a un servidor de licencias, llama a
getKeyRequest()
. - Para informar al motor de DRM sobre la respuesta clave que recibió el servidor de licencias, llama a
provideKeyResponse()
. El resultado depende del tipo de solicitud de clave:- Si la respuesta es para una solicitud de clave sin conexión, el resultado es un identificador de conjunto de claves. Puedes usar este identificador de conjunto de claves con
restoreKeys()
para restaurar las claves en una nueva sesión. - Si la respuesta es para una solicitud de transmisión o lanzamiento, el resultado es nulo.
- Si la respuesta es para una solicitud de clave sin conexión, el resultado es un identificador de conjunto de claves. Puedes usar este identificador de conjunto de claves con
Prepara la DRM de forma asíncrona
De forma predeterminada, prepareDrm()
se ejecuta de forma síncrona y se bloquea hasta que finaliza la preparación. Sin embargo, la primera preparación de DRM en un dispositivo nuevo también puede requerir aprovisionamiento, que prepareDrm()
administra de forma interna y puede tardar un poco en completarse debido a la operación de red involucrada. Puedes evitar el bloqueo en prepareDrm()
definiendo y configurando un MediaPlayer.OnDrmPreparedListener
.
Establece un OnDrmPreparedListener
. prepareDrm()
realiza el aprovisionamiento (si es necesario) y la preparación en segundo plano. Cuando finalizan el aprovisionamiento y la preparación, el sistema llama al objeto de escucha. No hagas ninguna suposición sobre la secuencia de llamada o el subproceso en el que se ejecuta el objeto de escucha (a menos que lo registres con un subproceso de controlador). El sistema puede llamar al objeto de escucha antes o después de que se muestre prepareDrm()
.
Cómo configurar la DRM de forma asíncrona
Puedes inicializar la DRM de forma asíncrona creando y registrando el MediaPlayer.OnDrmInfoListener
para la preparación de DRM y el MediaPlayer.OnDrmPreparedListener
para iniciar el reproductor. Funcionan junto con prepareAsync()
, como se muestra en este ejemplo:
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();
}
Cómo controlar el contenido multimedia encriptado
A partir de Android 8.0 (nivel de API 26), MediaPlayer
también puede desencriptar el esquema de encriptación común (CENC) y los medios encriptados de nivel de muestra HLS (MÉTODO=MUESTRA-AES) para los tipos de transmisión elemental H.264 y AAC. Antes, los medios encriptados de segmento completo (MÉTODO=AES-128) eran compatibles.
Más información
Jetpack Media3 es la solución recomendada para la reproducción de contenido multimedia en tu app. Obtén más información al respecto.
En estas páginas, se analizan temas relacionados con la grabación, el almacenamiento y la reproducción de audio y video: