Nuevos controles de contenido multimedia

En Android 11, se actualiza la forma en que se muestran los controles de contenido multimedia y se usan las API MediaSession y MediaRouter2 para procesar los controles y la información de salida de audio.

Los controles de contenido multimedia de Android 11 se encuentran cerca de la Configuración rápida. Se organizan en un carrusel deslizable las sesiones de varias apps. En el carrusel, se enumeran las sesiones en este orden:

  • Transmisiones locales en el teléfono
  • Transmisiones remotas, como las detectadas en dispositivos externos o sesiones de transmisión
  • Sesiones reanudables anteriores, en el orden en que se reprodujeron por última vez

Los usuarios pueden reiniciar las sesiones anteriores desde el carrusel sin tener que iniciar la app. Cuando comienza la reproducción, el usuario interactúa con los controles de contenido multimedia de la manera habitual.

Cómo brindar compatibilidad con la reanudación de la reproducción

Para usar esta función, debes habilitar la Reanudación de contenido multimedia en la configuración de Opciones para desarrolladores.

Si deseas que la aplicación de reproducción aparezca en el área de configuración rápida, debes crear una notificación MediaStyle con un token MediaSession válido.

Para mostrar el ícono de marca del reproductor de contenido multimedia, usa NotificationBuilder.setSmallIcon().

Para admitir la reanudación de la reproducción, las apps deben implementar un MediaBrowserService y una MediaSession.

Implementación de MediaBrowserService

Después de que se inicia el dispositivo, el sistema busca las últimas cinco apps de contenido multimedia y proporciona controles que se pueden usar para reiniciar la reproducción desde cada app.

El sistema intenta comunicarse con tu MediaBrowserService mediante una conexión desde SystemUI. Tu app debe permitir estas conexiones; de lo contrario, no podrá reanudar la reproducción.

Se pueden identificar y verificar las conexiones de SystemUI usando el nombre de paquete com.android.systemui y la firma. La interfaz de sistema lleva la firma de la plataforma. Puedes encontrar un ejemplo de cómo verificar la firma de la plataforma en la app de UAMP.

Para admitir la reanudación de la reproducción, tu MediaBrowserService debe implementar estos comportamientos:

  • onGetRoot() debe mostrar rápidamente una raíz no nula. Se debería manejar otra lógica compleja en onLoadChildren().

  • Cuando se llama a onLoadChildren() en el ID de contenido multimedia raíz, el resultado debe contener un elemento FLAG_PLAYABLE secundario.

  • MediaBrowserService debería mostrar el elemento multimedia reproducido más recientemente cuando reciba una consulta EXTRA_RECENT. El valor que se muestre debería ser un elemento multimedia real en lugar de una función genérica.

  • MediaBrowserService debe proporcionar una MediaDescription adecuada, con un título y un subtítulo que no estén vacíos. También debería establecer un URI de ícono o un mapa de bits de ícono.

En los siguientes ejemplos de código, se muestra cómo implementar onGetRoot().

Kotlin

override fun onGetRoot(
    clientPackageName: String,
    clientUid: Int,
    rootHints: Bundle?
): BrowserRoot? {
    ...
    // Verify that the specified package is SystemUI. You'll need to write your
    // own logic to do this.
    if (isSystem(clientPackageName, clientUid)) {
        rootHints?.let {
            if (it.getBoolean(BrowserRoot.EXTRA_RECENT)) {
                // Return a tree with a single playable media item for resumption.
                return BrowserRoot(MY_RECENTS_ROOT_ID, null)
            }
        }
        // You can return your normal tree if the EXTRA_RECENT flag is not present.
        return BrowserRoot(MY_MEDIA_ROOT_ID, null)
    }
    // Return an empty tree to disallow browsing.
    return BrowserRoot(MY_EMPTY_ROOT_ID, null)

Java

@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
    Bundle rootHints) {
    ...
    // Verify that the specified package is SystemUI. You'll need to write your
    // own logic to do this.
    if (isSystem(clientPackageName, clientUid)) {
        if (rootHints != null) {
            if (rootHints.getBoolean(BrowserRoot.EXTRA_RECENT)) {
                // Return a tree with a single playable media item for resumption.
                return new BrowserRoot(MY_RECENTS_ROOT_ID, null);
            }
        }
        // You can return your normal tree if the EXTRA_RECENT flag is not present.
        return new BrowserRoot(MY_MEDIA_ROOT_ID, null);
    }
    // Return an empty tree to disallow browsing.
    return new BrowserRoot(MY_EMPTY_ROOT_ID, null);
}

Implementación de MediaSession

El sistema recupera la siguiente información de MediaMetadata de la MediaSession y la muestra cuando está disponible:

  • METADATA_KEY_ALBUM_ART_URI
  • METADATA_KEY_TITLE
  • METADATA_KEY_ARTIST
  • METADATA_KEY_DURATION (si la duración no está configurada, la barra de búsqueda no mostrará el progreso)

Para admitir la reanudación de la reproducción, tu MediaSession debe implementar una devolución de llamada a MediaSession para onPlay().

El reproductor de contenido multimedia muestra el tiempo transcurrido del contenido multimedia que se está reproduciendo, junto con una barra de búsqueda que se asigna a la PlaybackState de la MediaSession.

Para que la barra de búsqueda funcione correctamente, debes implementar PlaybackState.Builder#setActions e incluir ACTION_SEEK_TO. De lo contrario, el reproductor solo mostrará el tiempo y la duración transcurridos.

Si deseas configurar los controles del reproductor, usa Notification.Builder#setCustomActions. Solo se mostrarán las acciones indicadas con Notification.MediaStyle#setShowsActionsInCompactView en el reproductor de contenido multimedia que aparece en la configuración rápida contraída.