Aplicar estilos de conteúdo

Depois de usar itens navegáveis ou reproduzíveis para criar sua hierarquia de conteúdo, aplique estilos de conteúdo para determinar como esses itens serão exibidos no carro. Use estes estilos de conteúdo:

Itens em lista

Figura 1. Os itens da lista priorizam títulos e metadados em vez de imagens.

Itens em grade

Figura 2. Os itens de grade priorizam imagens em vez de títulos e metadados.

Definir estilos de conteúdo padrão

Você pode definir padrões globais para a forma como seus itens de mídia são exibidos. Para fazer isso, inclua constantes específicas no pacote de extras BrowserRoot retornado pela implementação onGetRoot do seu serviço e procure essas constantes para determinar o estilo adequado.

Estes extras podem ser usados como chaves no pacote:

Essas chaves podem ser mapeadas para os seguintes valores constantes inteiros para influenciar a apresentação desses itens:

Este snippet de código mostra como definir o estilo de conteúdo padrão para itens navegáveis como grades e para itens reproduzíveis como 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);
}

Definir estilos de conteúdo por item

É possível substituir o estilo de conteúdo padrão para os descendentes de qualquer item de mídia navegável e para qualquer item de mídia. Para substituir o padrão dos descendentes de um item de mídia navegável, crie um pacote de extras na MediaDescription do item de mídia e adicione as mesmas dicas mencionadas anteriormente:

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE se aplica aos descendentes reproduzíveis desse item.

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE se aplica aos descendentes navegáveis desse item.

Para substituir o padrão de um item de mídia específico (e não dos descendentes), crie um pacote de extras na MediaDescription do item de mídia. Em seguida, adicione uma dica com a chave DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM. Use os mesmos valores descritos anteriormente para especificar a apresentação desse item.

Este snippet de código mostra como criar um MediaItem navegável que substitui o estilo de conteúdo padrão para ele e seus descendentes. Ele é definido como um item de lista de categorias, os descendentes navegáveis como itens de lista e os descendentes reproduzíveis como itens de grade.

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);
}

Agrupar itens usando dicas de título

Para agrupar itens de mídia relacionados, use uma dica por item. Cada item de mídia em um grupo precisa declarar um pacote de extras no MediaDescription. Esse pacote precisa incluir um mapeamento com a chave DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE e um valor de string idêntico. Localize essa string, já que ela é usada como título do grupo.

Este snippet de código mostra como criar um MediaItem com um título 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*/);
}

É necessário que o app transmita todos os itens de mídia que você quer agrupar como um bloco contíguo. Por exemplo, considere exibir dois grupos de itens de mídia, "Músicas" e "Álbuns", nessa ordem. Se o app transmitir cinco itens de mídia nessa ordem, o Android Auto e o AAOS vão interpretá-los como quatro grupos separados:

  • Item de mídia A com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Item de mídia B com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
  • Item de mídia C com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Item de mídia D com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Item de mídia E com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")

Isso resulta nestes quatro grupos:

  • Grupo 1 chamado "Songs" e contendo o item de mídia A
  • Grupo 2 chamado "Albums" e contendo o item de mídia B
  • Grupo 3 chamado "Songs" e contendo itens de mídia C e D
  • Grupo 4 chamado "Albums" e contendo o item de mídia E

Para exibir esses itens em dois grupos, o app precisa transmitir os itens de mídia nesta ordem:

  • Item de mídia A com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Item de mídia C com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Item de mídia D com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Item de mídia B com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
  • Item de mídia E com extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")

Exibir mais indicadores de metadados

Você pode incluir mais indicadores de metadados para fornecer informações resumidas sobre o conteúdo da árvore de navegação de mídia e durante a reprodução.

Na árvore de navegação, o Android Auto e o AAOS leem os extras associados a um item e mostram os indicadores. Durante a reprodução de mídia, o Android Auto e o AAOS leem os metadados da sessão de mídia e procuram constantes específicas para determinar quais indicadores exibir.

Visualização de reprodução com metadados

Figura 3. Visualização de reprodução com metadados.

Visualização de navegação para conteúdo não reproduzido.

Figura 4. Visualização de navegação para conteúdo não reproduzido.

Essas constantes podem ser usadas nos extras de descrição MediaItem e nos extras de MediaMetadata:

Essas constantes podem ser usadas apenas nos extras de descrição MediaItem:

Para mostrar indicadores que aparecem enquanto o usuário estiver percorrendo a árvore de navegação, crie um pacote de extras que inclua uma ou mais dessas constantes. Em seguida, transmita esse pacote para o método MediaDescription.Builder.setExtras.

Este snippet mostra como exibir indicadores para um item de mídia explícito com 70% de conteúdo reproduzido:

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 */);

Para mostrar indicadores de um item de mídia que está sendo reproduzido, declare valores para METADATA_KEY_IS_EXPLICIT ou EXTRA_DOWNLOAD_STATUS no MediaMetadataCompat da sua mediaSession.

Este snippet de código mostra como indicar que a música na visualização de reprodução é explícita e foi salva:

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());

Atualizar a barra de progresso na visualização de navegação enquanto o conteúdo é reproduzido

Conforme mencionado anteriormente, você pode usar o extra DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE para mostrar uma barra de progresso para conteúdo parcialmente reproduzido na visualização de navegação. No entanto, se o usuário continuar reproduzindo o conteúdo parcialmente reproduzido, esse indicador vai ficar impreciso com o tempo.

Para que o Android Auto e o AAOS mantenham a barra de progresso atualizada, forneça mais informações em MediaMetadataCompat e PlaybackStateCompat para vincular o conteúdo em andamento a itens de mídia na visualização de navegação.

Para que um item de mídia tenha uma barra de progresso com atualização automática, estes requisitos precisam ser atendidos:

Este snippet de código mostra como indicar que o item em reprodução está vinculado a um item na visualização de navegação:

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());

P Mesmo conteúdos não reproduzidos ou totalmente reproduzidos podem mostrar uma barra de progresso de atualização automática. Isso acontece se os itens de mídia correspondentes incluem o extra DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE com um valor de 0.0 (para não reproduzido) ou 1.0 (para totalmente reproduzido). Depois que o usuário seleciona esses itens de mídia, o Android Auto e o AAOS mostram a barra de progresso em vez de outros indicadores de progresso.