El framework multimedia de Android admite la reproducción de diversos tipos de medios comunes.
que te permite integrar fácilmente audio, video e imágenes en tus aplicaciones. Puedes reproducir audio o
video de archivos multimedia almacenados en los recursos de tu aplicación (recursos sin procesar), de archivos independientes
en el sistema de archivos o desde un flujo de datos que llega a través de una conexión de red, todo con APIs de MediaPlayer
.
En este documento, se muestra cómo usar
MediaPlayer
para escribir una reproducción de contenido multimedia
que interactúa con el usuario y el sistema para obtener un buen rendimiento y una
una experiencia del usuario agradable. Como alternativa, es posible que quieras
usar ExoPlayer, que es un software de código abierto
biblioteca compatible con funciones de alto rendimiento que no están disponibles en MediaPlayer
Nota: Solo puedes reproducir los datos de audio en la salida estándar. dispositivo. Por el momento, este es la bocina del dispositivo móvil o los auriculares Bluetooth. No puedes reproducir sonido en el audio de la conversación durante una llamada.
Conceptos básicos
Las siguientes clases se usan para reproducir sonido y video en el marco de trabajo de Android:
MediaPlayer
- Esta clase es la API principal para reproducir sonido y video.
AudioManager
- Esta clase administra fuentes y salidas de audio en un dispositivo.
Declaraciones del manifiesto
Antes de comenzar a desarrollar tu aplicación con MediaPlayer, comprueba que tu manifiesto cuente con las declaraciones adecuadas para permitir el uso de funciones relacionadas.
- Permiso de Internet: si estás usando MediaPlayer para transmitir con
tu aplicación debe solicitar acceso a la red.
<uses-permission android:name="android.permission.INTERNET" />
- Permiso de bloqueo de activación: Indica si la aplicación del reproductor debe conservar la pantalla.
de atenuación o que el procesador entre en estado de suspensión, o utiliza los parámetros
MediaPlayer.setScreenOnWhilePlaying()
oMediaPlayer.setWakeMode()
, debes solicitar este permiso.<uses-permission android:name="android.permission.WAKE_LOCK" />
Cómo usar MediaPlayer
Uno de los componentes más importantes
del framework de medios es el
MediaPlayer
. Un objeto de esta clase puede recuperar, decodificar y reproducir audio y video
con una configuración mínima. Es compatible con varias fuentes de medios diferentes, entra las que se incluyen las siguientes:
- Recursos locales
- URI internos, como uno que se pueda obtener de un agente de resolución de contenido
- URL externas (transmisión)
Para obtener una lista de los formatos multimedia compatibles con Android, consulta la página Contenido multimedia compatible Formatos de la página.
Aquí hay un ejemplo
sobre cómo reproducir audio disponible como recurso local sin procesar (guardado en el archivo
res/raw/
):
var mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1) mediaPlayer.start() // no need to call prepare(); create() does that for you
MediaPlayer mediaPlayer = MediaPlayer.create(context, R.raw.sound_file_1); mediaPlayer.start(); // no need to call prepare(); create() does that for you
En este caso, un producto "sin procesar" recurso es un archivo que el sistema no analizar de alguna manera en particular. Sin embargo, el contenido de este recurso no debe audio sin procesar. Debe ser un archivo multimedia con el formato y la codificación adecuados de los formatos admitidos.
Así es como puedes reproducir desde un URI disponible localmente en el sistema (la cual obtuviste mediante un agente de resolución de contenido, por ejemplo):
val myUri: Uri = .... // initialize Uri here val mediaPlayer = MediaPlayer().apply { setAudioAttributes( AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ) setDataSource(applicationContext, myUri) prepare() start() }
Uri myUri = ....; // initialize Uri here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioAttributes( new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ); mediaPlayer.setDataSource(getApplicationContext(), myUri); mediaPlayer.prepare(); mediaPlayer.start();
La reproducción desde una URL remota a través de la transmisión HTTP tiene el siguiente aspecto:
val url = "http://........" // your URL here val mediaPlayer = MediaPlayer().apply { setAudioAttributes( AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ) setDataSource(url) prepare() // might take long! (for buffering, etc) start() }
String url = "http://........"; // your URL here MediaPlayer mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioAttributes( new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ); mediaPlayer.setDataSource(url); mediaPlayer.prepare(); // might take long! (for buffering, etc) mediaPlayer.start();
Nota: Si envías una URL para transmitir un archivo multimedia en línea, el archivo debe tener descarga progresiva.
Precaución: Debes atrapar o pasar
IllegalArgumentException
y IOException
cuando se usan
setDataSource()
, porque
es posible que no exista el archivo al que te refieres.
Preparación asíncrona
Usar MediaPlayer
puede ser sencillo en
. Sin embargo, es importante tener en cuenta
que algunas cosas más
necesario para integrarla correctamente
a una aplicación Android típica. Para
Por ejemplo, la llamada a prepare()
puede
tardar mucho tiempo en ejecutarse, porque
puede implicar recuperar y decodificar datos de medios. Al igual que con cualquier otra
que pueda tardar mucho en ejecutarse, nunca debes llamarlo desde tu
subproceso de IU de la app. Eso hace que la IU se bloquee hasta que el método muestre resultados.
lo que supone una muy mala experiencia del usuario y puede
causar un error ANR ("Aplicación no responde"). Incluso si
Si esperas que tu recurso se cargue rápido, recuerda que todo lo que tarda más de una
de segundo para responder en la IU causa una pausa notable y da
al usuario la impresión de que tu aplicación es lenta.
Para evitar colgar tu subproceso de IU, genera otro subproceso en
preparar el MediaPlayer
y notificar al subproceso principal cuando esté listo. Sin embargo, aunque
puedes escribir la lógica de subprocesos
este patrón es tan común cuando usas MediaPlayer
que el framework
proporciona una forma conveniente de realizar esta tarea mediante el
prepareAsync()
. Este método
comienza a preparar los medios en segundo plano y regresa de inmediato. Cuando los medios
terminó de preparar, el onPrepared()
de MediaPlayer.OnPreparedListener
, que se configura mediante
Se llama a setOnPreparedListener()
.
Cómo administrar estados
Otro aspecto de un MediaPlayer
que debes tener en cuenta es
que está basada en el estado. Es decir, MediaPlayer
tiene un estado interno
que siempre debes tener en cuenta cuando escribes el código, ya que ciertas operaciones
solo son válidas cuando el reproductor
está en estados específicos. Si realizas una operación mientras
estado incorrecto, el sistema podría generar una excepción o provocar otros comportamientos no deseados.
La documentación en la
La clase MediaPlayer
muestra un diagrama completo de estado.
que aclara qué métodos mueven el MediaPlayer
de un estado a otro.
Por ejemplo, cuando creas un MediaPlayer
nuevo, estará en Idle.
para cada estado. En ese momento, debes inicializarlo llamando
setDataSource()
, lo que aporta
al estado Inicializada. Después, debes prepararlo con el
prepare()
o
prepareAsync()
. Cuándo
MediaPlayer
termina de prepararse, entra en Prepared.
estado, lo que significa que puedes llamar a start()
para que reproduzca el contenido multimedia. En ese punto, como se ilustra en el diagrama,
Puedes cambiar entre los estados Started, Pause y PlaybackCompleted,
llamando a métodos como
start()
,
pause()
y
seekTo()
,
entre otros. Cuando
llama a stop()
; sin embargo, ten en cuenta que
no puedes volver a llamar a start()
hasta que
preparar el MediaPlayer
de nuevo.
Mantén siempre el diagrama de estado
cuando escribas código que interactúe con un
MediaPlayer
, porque llamar a sus métodos desde el estado incorrecto es un
causa común de errores.
Cómo retirar MediaPlayer
Un MediaPlayer
puede consumir recursos
los recursos del sistema.
Por lo tanto, toma siempre precauciones adicionales para asegurarte de no estar
permanecen en una instancia MediaPlayer
más tiempo del necesario. Cuando
no terminaste, siempre debes llamar
release()
para asegurarte de que
los recursos del sistema asignados
se liberan correctamente. Por ejemplo, si estás
con un MediaPlayer
y tu actividad recibe una llamada a onStop()
, debes liberar el MediaPlayer
.
porque
no tiene mucho sentido aferrarse a ella mientras la actividad no está interactuando con
al usuario (a menos que estés reproduciendo contenido multimedia en segundo plano, como se explica en la siguiente sección).
Por supuesto, cuando se reanude o reinicie tu actividad,
Crea un MediaPlayer
nuevo y vuelve a prepararlo antes de reanudar la reproducción.
A continuación, se muestra cómo debes retirar y, luego, anular tu MediaPlayer
:
Como ejemplo, considera los problemas que podrían ocurrir
te olvidaste de liberar el MediaPlayer
cuando se detuvo tu actividad, pero crea un
uno nuevo cuando la actividad comience de nuevo. Como sabrás, cuando el usuario cambia
orientación de la pantalla (o cambia la configuración del dispositivo de otra manera)
El sistema se encarga de eso reiniciando la actividad (de forma predeterminada), de modo que puedas
consumen todos los recursos del sistema
el dispositivo rota entre el modo vertical y el horizontal, ya que en cada
cambio de orientación, creas un nuevo elemento MediaPlayer
que nunca
lanzamiento. (Para obtener más información sobre los reinicios durante el tiempo de ejecución, consulta Cómo controlar los cambios en el tiempo de ejecución).
Es posible que te preguntes qué sucede si quieres seguir jugando
“contenido multimedia en segundo plano” incluso cuando el usuario abandona tu actividad, casi en el mismo
la forma en que se comporta la aplicación integrada de música. En este caso, lo que necesitas es
un MediaPlayer
controlado por un Servicio, como
que analizamos en la próxima sección
Cómo usar MediaPlayer en un servicio
Si quieres que tu contenido multimedia se reproduzca en segundo plano incluso cuando tu app
no está en la pantalla, es decir, quieres que siga reproduciéndose mientras el usuario
interactuando con otras aplicaciones, debes comenzar un
Sitúa y controla el
MediaPlayer
a partir de allí.
Debes incorporar
MediaPlayer en un servicio de MediaBrowserServiceCompat
y tienen
interactúan con una
MediaBrowserCompat
en otra actividad.
Debes tener cuidado con esta configuración de cliente/servidor. Hay expectativas sobre cómo un reproductor que se ejecuta en un servicio en segundo plano interactúa con el resto del en un sistema de archivos. Si tu aplicación no cumple con esas expectativas, el usuario puede tengan una mala experiencia. Leído Cómo compilar una app de audio para conocer todos los detalles.
En esta sección, se incluyen instrucciones especiales para administrar un MediaPlayer cuando se implementa dentro de un servicio.
Ejecución asíncrona
En primer lugar, al igual que un Activity
, todos funcionan en una
Service
se realiza en un solo subproceso
predeterminada; de hecho, si ejecutas una actividad y un servicio desde la misma aplicación, estos
usar el mismo subproceso (el "subproceso principal") de forma predeterminada. Por lo tanto, los servicios deben
procesar intents entrantes con rapidez
y nunca realicen cálculos largos
cuando respondan a ellos. Si hay mucho
trabajo o de bloqueo, debes realizar esas tareas de forma asíncrona: ya sea desde
otro subproceso que implementes por tu cuenta o con las diversas instalaciones
para el procesamiento asíncrono.
Por ejemplo, cuando usas un MediaPlayer
de tu subproceso principal,
deberías llamar a prepareAsync()
en lugar de
prepare()
y, luego, implementa
un MediaPlayer.OnPreparedListener
para recibir una notificación cuando se complete la preparación y puedas comenzar a jugar.
Por ejemplo:
private const val ACTION_PLAY: String = "com.example.action.PLAY" class MyService: Service(), MediaPlayer.OnPreparedListener { private var mMediaPlayer: MediaPlayer? = null override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { ... val action: String = intent.action when(action) { ACTION_PLAY -> { mMediaPlayer = ... // initialize it here mMediaPlayer?.apply { setOnPreparedListener(this@MyService) prepareAsync() // prepare async to not block main thread } } } ... } /** Called when MediaPlayer is ready */ override fun onPrepared(mediaPlayer: MediaPlayer) { mediaPlayer.start() } }
public class MyService extends Service implements MediaPlayer.OnPreparedListener { private static final String ACTION_PLAY = "com.example.action.PLAY"; MediaPlayer mediaPlayer = null; public int onStartCommand(Intent intent, int flags, int startId) { ... if (intent.getAction().equals(ACTION_PLAY)) { mediaPlayer = ... // initialize it here mediaPlayer.setOnPreparedListener(this); mediaPlayer.prepareAsync(); // prepare async to not block main thread } } /** Called when MediaPlayer is ready */ public void onPrepared(MediaPlayer player) { player.start(); } }
Cómo manejar errores asíncronos
En operaciones síncronas, los errores normalmente
se señalizar con una excepción o un código de error, pero siempre que uses
debes asegurarte de que tu aplicación reciba notificaciones
los errores de forma adecuada. En el caso de un MediaPlayer
,
puedes lograrlo implementando una
MediaPlayer.OnErrorListener
y
configúralo en tu instancia MediaPlayer
:
class MyService : Service(), MediaPlayer.OnErrorListener { private var mediaPlayer: MediaPlayer? = null fun initMediaPlayer() { // ...initialize the MediaPlayer here... mediaPlayer?.setOnErrorListener(this) } override fun onError(mp: MediaPlayer, what: Int, extra: Int): Boolean { // ... react appropriately ... // The MediaPlayer has moved to the Error state, must be reset! } }
public class MyService extends Service implements MediaPlayer.OnErrorListener { MediaPlayer mediaPlayer; public void initMediaPlayer() { // ...initialize the MediaPlayer here... mediaPlayer.setOnErrorListener(this); } @Override public boolean onError(MediaPlayer mp, int what, int extra) { // ... react appropriately ... // The MediaPlayer has moved to the Error state, must be reset! } }
Es importante recordar que, cuando se produce un error, el MediaPlayer
pasa al estado Error (consulta la documentación del
clase MediaPlayer
para el diagrama de estado completo)
por lo que debes restablecerla antes de volver a usarla.
Cómo usar bloqueos de activación
Cuando se diseñan aplicaciones que reproducen contenido multimedia en segundo plano, es posible que el dispositivo entre en modo de suspensión. mientras se ejecuta el servicio. Como el sistema Android intenta conservar mientras el dispositivo está suspendido, el sistema intenta apagar de las funciones del teléfono que son incluso la CPU y el hardware de Wi-Fi. Sin embargo, si tu servicio reproduce o transmite música, debes evitar que el sistema interfiera en la reproducción.
Para garantizar que tu servicio siga funcionando estas condiciones, debes usar "bloqueos de activación". Un bloqueo de activación es una señal de al sistema de que tu aplicación está usando alguna función que debería seguirán disponibles aunque el teléfono esté inactivo.
Aviso: Siempre debes usar los bloqueos de activación con moderación y retenerlos. solo durante el tiempo que sea realmente necesario, porque reducen significativamente la duración de la batería del dispositivo.
Para asegurarte de que la CPU continúe ejecutándose mientras tu MediaPlayer
esté
en reproducción, llama al método setWakeMode()
cuando inicialices tu MediaPlayer
. Una vez que lo hagas,
MediaPlayer
mantiene el bloqueo especificado durante la reproducción y libera el bloqueo.
cuando se ponen en pausa o se detienen:
mediaPlayer = MediaPlayer().apply { // ... other initialization here ... setWakeMode(applicationContext, PowerManager.PARTIAL_WAKE_LOCK) }
mediaPlayer = new MediaPlayer(); // ... other initialization here ... mediaPlayer.setWakeMode(getApplicationContext(), PowerManager.PARTIAL_WAKE_LOCK);
Sin embargo, el bloqueo de activación de este ejemplo solo garantiza que la CPU permanezca activa. Si
estás transmitiendo contenido multimedia a través de la
y estás usando Wi-Fi, quizás quieras mantener una
WifiLock
como
que debes adquirir y lanzar manualmente. Entonces, cuando empieces a preparar
MediaPlayer
por la URL remota, debes crear y adquirir el bloqueo de Wi-Fi.
Por ejemplo:
val wifiManager = getSystemService(Context.WIFI_SERVICE) as WifiManager val wifiLock: WifiManager.WifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock") wifiLock.acquire()
WifiLock wifiLock = ((WifiManager) getSystemService(Context.WIFI_SERVICE)) .createWifiLock(WifiManager.WIFI_MODE_FULL, "mylock"); wifiLock.acquire();
Cuando pausas o detienes tu contenido multimedia, o cuando ya no necesitas debes liberar el bloqueo:
Cómo realizar la limpieza
Como se mencionó antes, un objeto MediaPlayer
puede consumir una cantidad significativa
cantidad de recursos del sistema, por lo que debes conservarla solo durante el tiempo que necesites y llamar
release()
cuando termines. Es importante
llamar a este método de limpieza de manera explícita en lugar de depender de la recolección de elementos no utilizados del sistema, ya que
puede llevar un tiempo hasta que el recolector de elementos no utilizados reclama el MediaPlayer
,
ya que solo es sensible a las necesidades de memoria y no a la escasez de otros recursos relacionados con los medios.
Así que, cuando uses un servicio, siempre debes anular el
Método onDestroy()
para asegurarte de que realizarás el lanzamiento
MediaPlayer
:
class MyService : Service() { private var mediaPlayer: MediaPlayer? = null // ... override fun onDestroy() { super.onDestroy() mediaPlayer?.release() } }
public class MyService extends Service { MediaPlayer mediaPlayer; // ... @Override public void onDestroy() { super.onDestroy(); if (mediaPlayer != null) mediaPlayer.release(); } }
Siempre debes buscar otras oportunidades para lanzar tu MediaPlayer
además de liberarlo cuando se cierra. Por ejemplo, si esperas que no
poder reproducir contenido multimedia durante un período prolongado (después de perder el foco de audio, por ejemplo)
definitivamente debes liberar tu MediaPlayer
existente y crearlo de nuevo
más adelante. En la
Por otro lado, si esperas detener la reproducción por muy poco tiempo, probablemente deberías
Conserva tu MediaPlayer
para evitar la sobrecarga de crearlo y prepararlo.
de nuevo.
Administración de derechos digitales (DRM)
A partir de Android 8.0 (nivel de API 26), MediaPlayer
incluye APIs que
admitir la reproducción de material protegido por DRM. Son similares a la API de bajo nivel proporcionada por
MediaDrm
, pero operan a un nivel superior y no
exponen los objetos extractor, drm y criptográficos subyacentes.
Si bien la API de DRM de MediaPlayer no proporciona la funcionalidad completa de
MediaDrm
, es compatible con los casos de uso más comunes. El
La implementación actual puede admitir los siguientes tipos de contenido:
- Archivos de medios locales protegidos por Widevine
- Archivos multimedia de transmisión/control remoto protegidos por Widevine
El siguiente fragmento de código demuestra cómo usar el nuevo MediaPlayer de DRM en una implementación síncrona simple.
Para administrar medios controlados por DRM, debes incluir los nuevos métodos junto con el flujo habitual de llamadas de MediaPlayer, como se muestra a continuación:
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() }
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 configura
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 un
OnDrmConfigHelper
y conéctala a la jugador usandosetOnDrmConfigHelper()
- Llamar a
prepare()
- Llamar a
getDrmInfo()
Si la fuente tiene DRM content, el método devuelve un valor ValorMediaPlayer.DrmInfo
.
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 un
OnDrmConfigHelper
, se llama mientras queprepareDrm()
se está ejecutando. Esto te permite realizar una configuración personalizada de la DRM las propiedades antes de abrir la sesión de DRM. Se llama a la devolución de llamada de forma síncrona en el subproceso que llamóprepareDrm()
Para acceder a las propiedades de DRM, llamargetDrmPropertyString()
ysetDrmPropertyString()
Evita realizar operaciones prolongadas. - Si el dispositivo aún no se aprovisionó,
prepareDrm()
también accede al servidor de aprovisionamiento para aprovisionar el dispositivo. Esto puede tardar de tiempo variable, según la conectividad de red. - Para obtener un array de bytes de solicitud de clave opaca para enviar a un servidor de licencias, llama
getKeyRequest()
- Para informar al motor de DRM de la respuesta clave recibida del servidor de licencias, llama
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 restablecer las claves a un nuevo 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
Cómo ejecutar prepareDrm()
de manera 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 la DRM en un nuevo dispositivo también puede requerir aprovisionamiento, lo cual
manejadas internamente por
prepareDrm()
y
puede tardar un poco en completarse debido a la operación de red involucrada. Puedes
evitar bloqueos en
prepareDrm()
el
definir y configurar una MediaPlayer.OnDrmPreparedListener
Cuando estableces un OnDrmPreparedListener
,
prepareDrm()
realiza el aprovisionamiento (si es necesario) y la preparación en segundo plano. Cuándo
el aprovisionamiento y la preparación, se llama al objeto de escucha. Deberías
no hagas suposiciones sobre la secuencia de llamada o el subproceso en el que
se ejecuta el objeto de escucha (a menos que esté registrado con un subproceso de controlador).
Se puede llamar al objeto de escucha antes o después
prepareDrm()
de retorno.
Cómo configurar la DRM de forma asíncrona
Puedes inicializar la DRM de forma asíncrona creando y registrando la
MediaPlayer.OnDrmInfoListener
para la preparación de DRM y la
MediaPlayer.OnDrmPreparedListener
para iniciar el reproductor.
Funcionan en conjunto con
prepareAsync()
, como se muestra a continuación:
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() }
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 administrar medios encriptados
A partir de Android 8.0 (nivel de API 26), MediaPlayer
también puede desencriptar
el esquema de cifrado común (CENC)
Medios encriptados a nivel de muestra de HLS (METHOD=SAMPLE-AES) para los tipos de transmisión elementales
H.264 y AAC. Antes, los medios encriptados de segmento completo (MÉTODO=AES-128) eran compatibles.
Cómo recuperar contenido multimedia de un ContentResolver
Otra función que puede ser útil en una aplicación de reproductor multimedia es la capacidad de
recuperar la música que el usuario tiene en el dispositivo. Puedes hacerlo consultando los medios externos en el ContentResolver
:
val resolver: ContentResolver = contentResolver val uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI val cursor: Cursor? = resolver.query(uri, null, null, null, null) when { cursor == null -> { // query failed, handle error. } !cursor.moveToFirst() -> { // no media on the device } else -> { val titleColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE) val idColumn: Int = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID) do { val thisId = cursor.getLong(idColumn) val thisTitle = cursor.getString(titleColumn) // ...process entry... } while (cursor.moveToNext()) } } cursor?.close()
ContentResolver contentResolver = getContentResolver(); Uri uri = android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; Cursor cursor = contentResolver.query(uri, null, null, null, null); if (cursor == null) { // query failed, handle error. } else if (!cursor.moveToFirst()) { // no media on the device } else { int titleColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media.TITLE); int idColumn = cursor.getColumnIndex(android.provider.MediaStore.Audio.Media._ID); do { long thisId = cursor.getLong(idColumn); String thisTitle = cursor.getString(titleColumn); // ...process entry... } while (cursor.moveToNext()); }
Para usar esta función con el MediaPlayer
, puedes hacer lo siguiente:
val id: Long = /* retrieve it from somewhere */ val contentUri: Uri = ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id ) mediaPlayer = MediaPlayer().apply { setAudioAttributes( AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ) setDataSource(applicationContext, contentUri) } // ...prepare and start...
long id = /* retrieve it from somewhere */; Uri contentUri = ContentUris.withAppendedId( android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id); mediaPlayer = new MediaPlayer(); mediaPlayer.setAudioAttributes( new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC) .setUsage(AudioAttributes.USAGE_MEDIA) .build() ); mediaPlayer.setDataSource(getApplicationContext(), contentUri); // ...prepare and start...
Más información
En estas páginas, se analizan temas relacionados con la grabación, el almacenamiento y la reproducción de audio y video.