Aplica los estilos de contenido

Después de usar elementos explorables o reproducibles para crear la jerarquía de contenido, aplica estilos de contenido para determinar cómo se muestran esos elementos en el automóvil. Usa estos estilos de contenido:

Elementos de listas

Figura 1: Los elementos de lista priorizan los títulos y los metadatos por sobre las imágenes.

Elementos de cuadrícula

Figura 2: Los elementos de cuadrícula priorizan las imágenes por sobre los títulos y los metadatos.

Establece estilos de contenido predeterminados

Puedes establecer valores globales predeterminados para la manera en la que se muestran los elementos multimedia. Para ello, incluye constantes específicas en el paquete de extras BrowserRoot que muestra la implementación onGetRoot de tu servicio y busca estas constantes para determinar el estilo adecuado.

Estos extras pueden usarse como claves en el paquete:

Estas claves se pueden mapear a los siguientes valores constantes de números enteros para influir en la presentación de esos elementos:

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM: Los elementos correspondientes se presentan como elementos de lista.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM: Los elementos correspondientes se presentan como elementos de cuadrícula.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM: Los elementos correspondientes se presentan como elementos de una lista de categorías, similares a los elementos de lista comunes, pero se aplican márgenes alrededor de los íconos de los elementos. Esto mejora la apariencia de los íconos pequeños. Los íconos deben ser elementos de diseño vectoriales de tono. Proporciona esta sugerencia solo para elementos explorables.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM: Los elementos correspondientes se presentan como elementos de una cuadrícula de categorías y son similares a los elementos de cuadrícula comunes, pero se aplican márgenes alrededor de los íconos de los elementos. Esto mejora la apariencia de los íconos pequeños. Los íconos deben ser elementos de diseño vectoriales de tono. Proporciona esta sugerencia solo para elementos explorables.

En el siguiente fragmento de código, se muestra cómo establecer el estilo de contenido predeterminado de los elementos explorables en cuadrículas y el correspondiente a los elementos reproducibles en listas:

Kotlin

import androidx.media.utils.MediaConstants

@Nullable
override fun onGetRoot(
    @NonNull clientPackageName: String,
    clientUid: Int,
    @Nullable rootHints: Bundle
): BrowserRoot {
    val extras = Bundle()
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM)
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM)
    return BrowserRoot(ROOT_ID, extras)
}

Java

import androidx.media.utils.MediaConstants;

@Nullable
@Override
public BrowserRoot onGetRoot(
    @NonNull String clientPackageName,
    int clientUid,
    @Nullable Bundle rootHints) {
    Bundle extras = new Bundle();
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM);
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM);
    return new BrowserRoot(ROOT_ID, extras);
}

Define estilos de contenido por elemento

Puedes anular el estilo de contenido predeterminado de cualquier descendiente de un elemento multimedia explorable, así como de cualquier elemento multimedia. Para anular el valor predeterminado de los descendientes de un elemento multimedia explorable, crea un paquete de extras en el MediaDescription del elemento multimedia y agrega las mismas sugerencias de antes:

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE se aplica a los descendientes reproducibles de ese elemento.

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE se aplica a los descendientes explorables de ese elemento.

Para anular el valor predeterminado de un elemento multimedia específico (no sus descendientes), crea un paquete de extras en el MediaDescription del elemento multimedia. Luego, agrega una sugerencia con la clave DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM. Usa los mismos valores descritos anteriormente para especificar la presentación de ese elemento.

En el siguiente fragmento de código, se muestra cómo crear un MediaItem explorable que anule el estilo de contenido predeterminado para él y sus descendientes. Se diseña como un elemento de lista de categoría, sus descendientes explorables como elementos de lista y sus descendientes reproducibles como elementos de cuadrícula.

Kotlin

import androidx.media.utils.MediaConstants

private fun createBrowsableMediaItem(
    mediaId: String,
    folderName: String,
    iconUri: Uri
): MediaBrowser.MediaItem {
    val mediaDescriptionBuilder = MediaDescription.Builder()
    mediaDescriptionBuilder.setMediaId(mediaId)
    mediaDescriptionBuilder.setTitle(folderName)
    mediaDescriptionBuilder.setIconUri(iconUri)
    val extras = Bundle()
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM)
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM)
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM)
    mediaDescriptionBuilder.setExtras(extras)
    return MediaBrowser.MediaItem(
        mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE)
}

Java

import androidx.media.utils.MediaConstants;

private MediaBrowser.MediaItem createBrowsableMediaItem(
    String mediaId,
    String folderName,
    Uri iconUri) {
    MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder();
    mediaDescriptionBuilder.setMediaId(mediaId);
    mediaDescriptionBuilder.setTitle(folderName);
    mediaDescriptionBuilder.setIconUri(iconUri);
    Bundle extras = new Bundle();
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM);
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM);
    extras.putInt(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE,
        MediaConstants.DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM);
    mediaDescriptionBuilder.setExtras(extras);
    return new MediaBrowser.MediaItem(
        mediaDescriptionBuilder.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE);
}

Agrupa elementos con sugerencias de títulos

Para agrupar elementos multimedia relacionados, usa una sugerencia que se relacione con ese elemento. Cada elemento multimedia de un grupo debe declarar un paquete de extras en su MediaDescription. Este paquete debe incluir una asignación con la clave DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE y un valor de cadena idéntico. Localiza esta cadena, ya que se usa para el título del grupo.

En el siguiente fragmento de código, se muestra cómo crear un MediaItem con un encabezado de subgrupo de Songs:

Kotlin

import androidx.media.utils.MediaConstants

private fun createMediaItem(
    mediaId: String,
    folderName: String,
    iconUri: Uri
): MediaBrowser.MediaItem {
    val mediaDescriptionBuilder = MediaDescription.Builder()
    mediaDescriptionBuilder.setMediaId(mediaId)
    mediaDescriptionBuilder.setTitle(folderName)
    mediaDescriptionBuilder.setIconUri(iconUri)
    val extras = Bundle()
    extras.putString(
        MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE,
        "Songs")
    mediaDescriptionBuilder.setExtras(extras)
    return MediaBrowser.MediaItem(
        mediaDescriptionBuilder.build(), /* playable or browsable flag*/)
}

Java

import androidx.media.utils.MediaConstants;

private MediaBrowser.MediaItem createMediaItem(String mediaId, String folderName, Uri iconUri) {
   MediaDescription.Builder mediaDescriptionBuilder = new MediaDescription.Builder();
   mediaDescriptionBuilder.setMediaId(mediaId);
   mediaDescriptionBuilder.setTitle(folderName);
   mediaDescriptionBuilder.setIconUri(iconUri);
   Bundle extras = new Bundle();
   extras.putString(
       MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE,
       "Songs");
   mediaDescriptionBuilder.setExtras(extras);
   return new MediaBrowser.MediaItem(
       mediaDescriptionBuilder.build(), /* playable or browsable flag*/);
}

La app debe pasar todos los elementos multimedia que deseas agrupar como un bloque contiguo. Por ejemplo, considera mostrar dos grupos de elementos multimedia, "Canciones" y "Álbumes", en ese orden. Si tu app pasa cinco elementos multimedia en este orden, Android Auto y AAOS los interpretan como cuatro grupos separados:

  • Elemento multimedia A con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Elemento multimedia B con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
  • Elemento multimedia C con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Elemento multimedia D con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Elemento multimedia E con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")

Esto da como resultado estos cuatro grupos:

  • Grupo 1 llamado "Canciones" que contiene el elemento multimedia A
  • Grupo 2 llamado "Álbumes" que contiene el elemento multimedia B
  • Grupo 3 llamado "Canciones" que contiene elementos multimedia C y D
  • Grupo 4 llamado "Álbumes" que contiene el elemento multimedia E

Para mostrar estos elementos en dos grupos, la app debe pasar los elementos multimedia en el siguiente orden:

  • Elemento multimedia A con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Elemento multimedia C con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Elemento multimedia D con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Elemento multimedia B con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
  • Elemento multimedia E con extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")

Muestra indicadores de metadatos adicionales

Puedes incluir indicadores de metadatos adicionales para proporcionar información de un vistazo sobre el contenido en el árbol del navegador multimedia y durante la reproducción.

En el árbol de exploración, Android Auto y AAOS leen los extras asociados con un elemento y muestran los indicadores. Durante la reproducción de contenido multimedia, Android Auto y AAOS leen los metadatos de la sesión multimedia y buscan constantes específicas para determinar qué indicadores mostrar.

Vista de reproducción con metadatos

Figura 3: Vista de reproducción con metadatos

Vista de exploración para contenido no reproducido.

Figura 4: Vista de exploración para contenido no reproducido

Estas constantes se pueden usar en los extras de descripción MediaItem y en los extras MediaMetadata:

Las siguientes constantes solo se pueden usar en los extras de descripción MediaItem:

Para mostrar los indicadores que aparecen mientras el usuario explora el árbol del navegador multimedia, crea un paquete de extras que incluya una o más de estas constantes. Luego, pasa ese paquete al método MediaDescription.Builder.setExtras.

En el siguiente fragmento de código, se indica cómo mostrar los indicadores para un elemento multimedia explícito que está completo en un 70%:

Kotlin

import androidx.media.utils.MediaConstants

val extras = Bundle()
extras.putLong(
    MediaConstants.METADATA_KEY_IS_EXPLICIT,
    MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT)
extras.putInt(
    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS,
    MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED)
extras.putDouble(
    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7)
val description =
    MediaDescriptionCompat.Builder()
        .setMediaId(/*...*/)
        .setTitle(resources.getString(/*...*/))
        .setExtras(extras)
        .build()
return MediaBrowserCompat.MediaItem(description, /* flags */)

Java

import androidx.media.utils.MediaConstants;

Bundle extras = new Bundle();
extras.putLong(
    MediaConstants.METADATA_KEY_IS_EXPLICIT,
    MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT);
extras.putInt(
    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS,
    MediaConstants.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED);
extras.putDouble(
    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.7);
MediaDescriptionCompat description =
    new MediaDescriptionCompat.Builder()
        .setMediaId(/*...*/)
        .setTitle(resources.getString(/*...*/))
        .setExtras(extras)
        .build();
return new MediaBrowserCompat.MediaItem(description, /* flags */);

Si quieres mostrar los indicadores de un elemento multimedia que se está reproduciendo, declara los valores de METADATA_KEY_IS_EXPLICIT o EXTRA_DOWNLOAD_STATUS en MediaMetadataCompat de tu mediaSession.

En el siguiente fragmento de código, se muestra cómo indicar que la canción de la vista de reproducción es explícita y que se descargó:

Kotlin

import androidx.media.utils.MediaConstants

mediaSession.setMetadata(
    MediaMetadataCompat.Builder()
        .putString(
            MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name")
        .putString(
            MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name")
        .putString(
            MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI,
            albumArtUri.toString())
        .putLong(
            MediaConstants.METADATA_KEY_IS_EXPLICIT,
            MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT)
        .putLong(
            MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS,
            MediaDescriptionCompat.STATUS_DOWNLOADED)
        .build())

Java

import androidx.media.utils.MediaConstants;

mediaSession.setMetadata(
    new MediaMetadataCompat.Builder()
        .putString(
            MediaMetadataCompat.METADATA_KEY_DISPLAY_TITLE, "Song Name")
        .putString(
            MediaMetadataCompat.METADATA_KEY_DISPLAY_SUBTITLE, "Artist name")
        .putString(
            MediaMetadataCompat.METADATA_KEY_ALBUM_ART_URI,
            albumArtUri.toString())
        .putLong(
            MediaConstants.METADATA_KEY_IS_EXPLICIT,
            MediaConstants.METADATA_VALUE_ATTRIBUTE_PRESENT)
        .putLong(
            MediaDescriptionCompat.EXTRA_DOWNLOAD_STATUS,
            MediaDescriptionCompat.STATUS_DOWNLOADED)
        .build());

Actualiza la barra de progreso en la vista de exploración mientras se reproduce el contenido

Puedes usar el DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE extra para mostrar una barra de progreso del contenido que se reprodujo parcialmente en la vista de navegación. Sin embargo, si un usuario continúa reproduciendo el contenido que no se terminó de reproducir, el indicador en cuestión se volverá inexacto a medida que pase el tiempo.

Para que Android Auto y AAOS mantengan la barra de progreso actualizada, proporciona información adicional en MediaMetadataCompat y PlaybackStateCompat para vincular contenido continuo a elementos multimedia en la vista de exploración.

Debes cumplir los siguientes requisitos para que el elemento multimedia tenga una barra de progreso de actualización automática:

En el siguiente fragmento de código, se muestra cómo indicar que el elemento que se está reproduciendo está vinculado a un elemento en la vista de exploración:

Kotlin

import androidx.media.utils.MediaConstants

// When the MediaItem is constructed to show in the browse view.
// Suppose the item was 25% complete when the user launched the browse view.
val mediaItemExtras = Bundle()
mediaItemExtras.putDouble(
    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25)
val description =
    MediaDescriptionCompat.Builder()
        .setMediaId("my-media-id")
        .setExtras(mediaItemExtras)
        // ...and any other setters.
        .build()
return MediaBrowserCompat.MediaItem(description, /* flags */)

// Elsewhere, when the user has selected MediaItem for playback.
mediaSession.setMetadata(
    MediaMetadataCompat.Builder()
        .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id")
        // ...and any other setters.
        .build())

val playbackStateExtras = Bundle()
playbackStateExtras.putString(
    MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id")
mediaSession.setPlaybackState(
    PlaybackStateCompat.Builder()
        .setExtras(playbackStateExtras)
        // ...and any other setters.
        .build())

Java

import androidx.media.utils.MediaConstants;

// When the MediaItem is constructed to show in the browse view.
// Suppose the item was 25% complete when the user launched the browse view.
Bundle mediaItemExtras = new Bundle();
mediaItemExtras.putDouble(
    MediaConstants.DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE, 0.25);
MediaDescriptionCompat description =
    new MediaDescriptionCompat.Builder()
        .setMediaId("my-media-id")
        .setExtras(mediaItemExtras)
        // ...and any other setters.
        .build();
return new MediaBrowserCompat.MediaItem(description, /* flags */);

// Elsewhere, when the user has selected MediaItem for playback.
mediaSession.setMetadata(
    new MediaMetadataCompat.Builder()
        .putString(MediaMetadata.METADATA_KEY_MEDIA_ID, "my-media-id")
        // ...and any other setters.
        .build());

Bundle playbackStateExtras = new Bundle();
playbackStateExtras.putString(
    MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, "my-media-id");
mediaSession.setPlaybackState(
    new PlaybackStateCompat.Builder()
        .setExtras(playbackStateExtras)
        // ...and any other setters.
        .build());

Incluso el contenido que no se reproduce o que se reproduce por completo puede mostrar una barra de progreso de actualización automática. Esto ocurre si los elementos multimedia correspondientes incluyen el extra DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE con un valor de 0.0 (cuando no hubo reproducción) o 1.0 (para reproducción completa). Después de que el usuario seleccione estos elementos multimedia, Android Auto y AAOS mostrarán la barra de progreso por sobre otros indicadores de progreso.