Las sesiones multimedia proporcionan una forma universal de interactuar con un reproductor de audio o video. Si se informa a Android que se está reproduciendo contenido multimedia en una app, se pueden delegar los controles de reproducción a la app. La integración con la sesión multimedia permite que una app anuncie la reproducción de contenido multimedia de forma externa y reciba comandos de reproducción de fuentes externas. Estas fuentes pueden ser botones físicos (como el botón de reproducción de un auricular o un control remoto de TV) o comandos indirectos (como indicarle "pausar" a Asistente de Google). Luego, la sesión multimedia delega estos comandos a la app que los aplica al reproductor multimedia, para el que es transparente el origen de los comandos.
Una sesión multimedia existe junto al reproductor que administra. Debes crear
e inicializar una sesión multimedia en el método onCreate() de la actividad o
el servicio que posee la sesión multimedia y su reproductor asociado.
Cómo inicializar la sesión multimedia
Una sesión multimedia recién creada no tiene capacidades. Debes inicializar la sesión siguiendo estos pasos:
- Establece marcas para que la sesión multimedia pueda recibir devoluciones de llamada de los controladores y botones multimedia.
- Crea e inicializa una instancia de
PlaybackStateCompaty asígnala a la sesión. El estado de reproducción cambia durante la sesión, por lo que recomendamos almacenar en caché elPlaybackStateCompat.Builderpara reutilizarlo. - Crea una instancia de
MediaSessionCompat.Callbacky asígnala a la sesión (más información sobre las devoluciones de llamada a continuación).
Debes crear e inicializar una sesión multimedia en el método onCreate() de la actividad o el servicio que posee la sesión.
Para que los botones de contenido multimedia funcionen cuando tu app se inicializa (o se detiene) recientemente, su PlaybackState debe contener una acción de reproducción que coincida con el intent que envía el botón de contenido multimedia. Por este motivo, se asigna ACTION_PLAY al
estado de la sesión durante la inicialización. Para obtener más información, consulta Cómo responder a los botones de contenido multimedia.
Cómo mantener el estado y los metadatos de la reproducción
Existen dos clases que representan el estado de una sesión multimedia.
La clase PlaybackStateCompat describe el estado operativo actual del reproductor. Esto incluye lo siguiente:
- El estado de transporte (si el reproductor está reproduciendo, en pausa, almacenando en búfer, etc.; consulta
getState()) - Un código de error y un mensaje de error opcional cuando corresponda (Consulta
getErrorCode()y lee Estados y errores, a continuación). - La posición del reproductor
- Las acciones válidas del controlador que se pueden manejar en el estado actual
La clase MediaMetadataCompat describe el material que se está reproduciendo:
- El nombre del artista, el álbum y la pista
- La duración de la pista
- La portada del álbum para mostrar en la pantalla de bloqueo La imagen es un mapa de bits con un tamaño máximo de 320 × 320 dp (si es más grande, se reduce).
- Una instancia de
ContentUrisque apunta a una versión más grande de la imagen
El estado y los metadatos del reproductor pueden cambiar durante el ciclo de vida de una sesión multimedia. Cada vez que cambien el estado o los metadatos, debes usar el compilador correspondiente para cada clase, PlaybackStateCompat.Builder() o MediaMetadataCompat.Builder(), y, luego, pasar la instancia nueva a la sesión multimedia llamando a setPlaybackState() o setMetaData(). Para reducir el consumo general de memoria de estas operaciones frecuentes, se recomienda crear los compiladores una vez y reutilizarlos durante toda la sesión.
Estados y errores
Ten en cuenta que PlaybackState es un objeto que contiene valores independientes para el estado de reproducción de la sesión (getState()) y, cuando es necesario, un código de error asociado (getErrorCode()). Los errores pueden ser graves o no graves:
Cada vez que se interrumpa la reproducción, deberás generar un error recuperable: establece el estado de transporte en STATE_ERROR y especifica un error asociado con setErrorMessage(int, CharSequence). Mientras el error bloquee la reproducción, el PlaybackState debe seguir informando el STATE_ERROR y el error.
Se produce un error no recuperable cuando tu app no puede controlar una solicitud, pero puede seguir reproduciendo contenido: el transporte permanece en un estado "normal" (como STATE_PLAYING), pero el PlaybackState contiene un código de error. Por ejemplo, si se está reproduciendo la última canción y el usuario solicita omitirla para pasar a la siguiente, la reproducción puede continuar, pero debes crear un nuevo PlaybackState con el código de error ERROR_CODE_END_OF_QUEUE y, luego, llamar a setPlaybackState(). Los controladores de contenido multimedia conectados a la sesión recibirán la devolución de llamada onPlaybackStateChanged() y le explicarán al usuario lo que sucedió. Un error no fatal solo se debe informar una vez, en el momento en que ocurre. La próxima vez que la sesión actualice el PlaybackState, no vuelvas a establecer el mismo error recuperable (a menos que el error se haya producido en respuesta a una solicitud nueva).
Pantallas de bloqueo de la sesión multimedia
A partir de Android 4.0 (nivel de API 14), el sistema puede acceder al estado de reproducción y a los metadatos de una sesión multimedia. Así es como la pantalla de bloqueo puede mostrar los controles multimedia y la carátula. El comportamiento varía según la versión de Android.
Portada del álbum
En Android 4.0 (nivel de API 14) hasta Android 10 (nivel de API 29), el fondo de la pantalla de bloqueo muestra la imagen del álbum, pero solo si los metadatos de la sesión multimedia incluyen un mapa de bits de fondo.
Controles de transporte
En Android 4.0 (nivel de API 14) hasta Android 4.4 (nivel de API 19), cuando una sesión multimedia está activa y los metadatos de la sesión multimedia incluyen un mapa de bits de fondo, la pantalla de bloqueo muestra automáticamente los controles de transporte.
En Android 5.0 (nivel de API 21) o versiones posteriores, el sistema no proporciona controles de transporte en la pantalla de bloqueo. En su lugar, debes usar una notificación de MediaStyle para mostrar los controles de transporte.
Agrega acciones personalizadas
Las aplicaciones de música pueden definir acciones personalizadas, como Me gusta, No me gusta o Retroceder 30 segundos. Una acción personalizada debería implementar un comportamiento completamente nuevo. No uses una acción personalizada para reemplazar una de las acciones de control de transporte estándar definidas en PlaybackStateCompat.
Agrega acciones personalizadas con addCustomAction(). En el siguiente ejemplo, se muestra cómo agregar un control para una acción de Me gusta:
Kotlin
stateBuilder.addCustomAction(
PlaybackStateCompat.CustomAction.Builder(
CUSTOM_ACTION_THUMBS_UP,
resources.getString(R.string.thumbs_up),
thumbsUpIcon
).run {
setExtras(customActionExtras)
build()
}
)
Java
stateBuilder.addCustomAction(new PlaybackStateCompat.CustomAction.Builder(
CUSTOM_ACTION_THUMBS_UP, resources.getString(R.string.thumbs_up), thumbsUpIcon)
.setExtras(customActionExtras)
.build());
Consulta el Universal Music Player para ver un ejemplo completo.
Respondes a la acción con onCustomAction().
Kotlin
override fun onCustomAction(action: String, extras: Bundle?) {
when(action) {
CUSTOM_ACTION_THUMBS_UP -> {
...
}
}
}
Java
@Override
public void onCustomAction(@NonNull String action, Bundle extras) {
if (CUSTOM_ACTION_THUMBS_UP.equals(action)) {
...
}
}
Consulta también el Universal Music Player.
Devoluciones de llamadas de sesiones multimedia
Los métodos de devolución de llamada principales de la sesión multimedia son onPlay(), onPause() y onStop(). Aquí es donde agregas el código que controla tu reproductor.
Como creas una instancia y configuras la devolución de llamada de la sesión en el entorno de ejecución (en onCreate()), tu app puede definir devoluciones de llamada alternativas que usen diferentes reproductores y elegir la combinación adecuada de devolución de llamada y reproductor según el dispositivo y el nivel del sistema. Puedes cambiar el reproductor sin modificar el resto de la app. Por ejemplo, puedes usar ExoPlayer cuando se ejecute en Android 4.1 (nivel de API 16) o versiones posteriores, y usar MediaPlayer en sistemas anteriores.
Además de controlar el reproductor y administrar las transiciones de estado de la sesión multimedia, las devoluciones de llamada también habilitan e inhabilitan funciones de tu app y controlan la forma en que interactúa con otras apps y el hardware del dispositivo. (consulta Cómo controlar la salida de audio).
La implementación de los métodos de devolución de llamada de la sesión multimedia depende de la estructura de tu app. Consulta las páginas independientes que describen cómo usar las devoluciones de llamada en apps de audio y apps de video, y cómo se deben implementar las devoluciones de llamada para cada tipo de app.