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 nivel bajo proporcionadas por 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 prácticos más comunes. La implementación actual puede controlar los siguientes tipos de contenidos:
- 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 de DRM de MediaPlayer 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 MediaPlayer objeto y establece la 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
OnDrmConfigHelperinterfaz y adjúntala al reproductor mediantesetOnDrmConfigHelper(). - Llama a
prepare(). - Llama a
getDrmInfo(). Si la fuente tiene contenido DRM, el método muestra un valorMediaPlayer.DrmInfono nulo.
Si MediaPlayer.DrmInfo existe:
- Examina el mapa de UUID disponibles y elige uno.
- Prepara la configuración de DRM para la fuente actual llamando a
prepareDrm().- 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óprepareDrm(). 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 retiro, 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 internamente 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 finaliza 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 prepareDrm() muestre resultados.
Configura 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();
}
Administra medios encriptados
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: