Применение стилей контента

После использования просматриваемых или воспроизводимых элементов для построения иерархии контента примените стили контента, чтобы определить, как эти элементы будут отображаться в автомобиле. Используйте следующие стили контента:

Список элементов

Рисунок 1. Элементы списка отдают приоритет заголовкам и метаданным над изображениями.

Элементы сетки

Рисунок 2. Элементы сетки отдают приоритет изображениям по сравнению с заголовками и метаданными.

Установить стили содержимого по умолчанию

Вы можете задать глобальные значения по умолчанию для отображения медиа-элементов. Для этого включите определённые константы в пакет дополнительных функций BrowserRoot , возвращаемый реализацией onGetRoot вашего сервиса, и найдите эти константы, чтобы определить подходящий стиль.

Эти дополнения можно использовать в качестве ключей в комплекте:

Эти ключи могут соответствовать следующим целочисленным константным значениям, чтобы влиять на представление этих элементов:

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM : Соответствующие элементы, представленные как элементы списка.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM : Соответствующие элементы, представленные в виде элементов сетки.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM : Соответствующие элементы представлены как элементы списка «категории», аналогичные обычным элементам списка, но вокруг значков элементов применяются поля. Это улучшает внешний вид маленьких значков. Значки должны быть векторными, с возможностью тонирования. Ожидается, что эта подсказка будет предоставлена только для элементов, доступных для просмотра.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM : Соответствующие элементы представлены как элементы сетки «категории» и похожи на обычные элементы сетки, но вокруг значков элементов применяются поля. Это улучшает внешний вид мелких значков. Значки должны быть векторными, с возможностью тонирования. Ожидается, что эта подсказка будет предоставлена только для элементов, доступных для просмотра.

В этом фрагменте кода показано, как задать стиль содержимого по умолчанию для просматриваемых элементов в виде сеток, а для воспроизводимых элементов — в виде списков:

Котлин

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

Ява

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

Установить стили содержимого для каждого элемента

Вы можете переопределить стиль содержимого по умолчанию для всех дочерних элементов просматриваемого медиа-элемента, а также для любого медиа-элемента. Чтобы переопределить стиль содержимого по умолчанию для дочерних элементов просматриваемого медиа-элемента, создайте пакет дополнительных материалов в MediaDescription медиа-элемента и добавьте те же упомянутые ранее подсказки:

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE применяется к воспроизводимым потомкам этого элемента.

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE применяется к просматриваемым потомкам этого элемента.

Чтобы переопределить значение по умолчанию для конкретного медиа-элемента (но не для его потомков), создайте пакет дополнительных материалов в MediaDescription медиа-элемента. Затем добавьте подсказку с ключом DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM . Используйте те же значения, что и ранее, для указания представления этого элемента.

Этот фрагмент кода показывает, как создать просматриваемый MediaItem , который переопределяет стиль содержимого по умолчанию для себя и своих потомков. Он оформляет себя как элемент списка категорий, своих просматриваемых потомков — как элементы списка, а своих воспроизводимых потомков — как элементы сетки.

Котлин

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

Ява

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

Группируйте элементы, используя подсказки по заголовкам

Чтобы сгруппировать связанные медиа-элементы, используйте подсказку для каждого элемента. Каждый медиа-элемент в группе должен декларировать пакет дополнительных материалов в своём MediaDescription . Этот пакет должен включать сопоставление с ключом DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE и идентичным строковым значением. Локализуйте эту строку, так как она используется в заголовке группы.

В этом фрагменте кода показано, как создать MediaItem с заголовком подгруппы Songs :

Котлин

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

Ява

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

Ваше приложение должно передавать все медиа-элементы, которые вы хотите сгруппировать в виде непрерывного блока. Например, рассмотрите возможность отображения двух групп медиа-элементов: «Песни» и «Альбомы» — в указанном порядке. Если ваше приложение передает пять медиа-элементов в таком порядке, Android Auto и AAOS интерпретируют их как четыре отдельные группы:

  • Медиа-элемент A с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент B с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
  • Медиа-элемент C с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент D с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент E с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")

В результате получаются следующие четыре группы:

  • Группа 1, называемая «Песни», содержащая медиафайл A
  • Группа 2, называемая «Альбомы», содержащая медиафайл B
  • Группа 3, называемая «Песни», содержит медиафайлы C и D.
  • Группа 4, называемая «Альбомы», содержащая медиафайл E

Чтобы отобразить эти элементы в двух группах, ваше приложение должно передавать элементы мультимедиа в следующем порядке:

  • Медиа-элемент A с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент C с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент D с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент B с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
  • Медиа-элемент E с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")

Отображать дополнительные индикаторы метаданных

Вы можете включить дополнительные индикаторы метаданных, чтобы предоставить наглядную информацию о контенте в дереве медиабраузера и во время воспроизведения.

В дереве обзора Android Auto и AAOS считывают дополнительные данные, связанные с элементом, и отображают индикаторы. Во время воспроизведения медиафайлов Android Auto и AAOS считывают метаданные медиасеанса и ищут определённые константы, чтобы определить, какие индикаторы отображать.

Просмотр воспроизведения с метаданными

Рисунок 3. Вид воспроизведения с метаданными.

Просмотреть невоспроизведенный контент.

Рисунок 4. Просмотр невоспроизведенного контента.

Эти константы можно использовать как в дополнительных описаниях MediaItem , так и в дополнительных материалах MediaMetadata :

  • EXTRA_DOWNLOAD_STATUS : Показывает статус загрузки элемента. Используйте эту константу в качестве ключа. Возможны следующие длинные константы:

  • METADATA_KEY_IS_EXPLICIT : Указывает, что элемент содержит явное содержимое. Чтобы указать, что элемент является явным, используйте эту константу в качестве ключа и длинное значение METADATA_VALUE_ATTRIBUTE_PRESENT в качестве значения.

Эти константы можно использовать только в дополнительных описаниях MediaItem :

Чтобы отображать индикаторы, появляющиеся при просмотре пользователем дерева медиаконтента, создайте пакет дополнительных данных, включающий одну или несколько из этих констант. Затем передайте этот пакет методу MediaDescription.Builder.setExtras .

В этом фрагменте показано, как отображать индикаторы для откровенного медиа-элемента, который завершен на 70%:

Котлин

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

Ява

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

Чтобы отобразить индикаторы для воспроизводимого в данный момент медиа-элемента, объявите значения для METADATA_KEY_IS_EXPLICIT или EXTRA_DOWNLOAD_STATUS в MediaMetadataCompat вашего mediaSession .

В этом фрагменте кода показано, как указать, что песня в представлении воспроизведения является ненормативной лексикой и загружена:

Котлин

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

Ява

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

Обновлять индикатор выполнения в режиме просмотра во время воспроизведения контента

Как упоминалось ранее, можно использовать дополнительный параметр DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE для отображения индикатора прогресса для частично воспроизведенного контента в режиме просмотра. Однако, если пользователь продолжает воспроизведение частично воспроизведенного контента, этот индикатор со временем становится неточным.

Чтобы Android Auto и AAOS поддерживали полосу прогресса в актуальном состоянии, предоставьте дополнительную информацию в MediaMetadataCompat и PlaybackStateCompat для привязки текущего содержимого к элементам мультимедиа в представлении обзора.

Чтобы медиа-элемент имел автоматически обновляемую полосу прогресса, должны быть соблюдены следующие требования:

В этом фрагменте кода показано, как указать, что воспроизводимый элемент связан с элементом в представлении обзора:

Котлин

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

Ява

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

Даже для невоспроизведённого или полностью воспроизведённого контента может отображаться автоматически обновляющийся индикатор прогресса. Это происходит, если соответствующие медиафайлы содержат дополнительный параметр DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE со значением 0.0 (для невоспроизведённого) или 1.0 (для полностью воспроизведённого). После выбора пользователем этих медиафайлов Android Auto и AAOS отображают индикатор прогресса поверх других индикаторов прогресса.

,

После использования просматриваемых или воспроизводимых элементов для построения иерархии контента примените стили контента, чтобы определить, как эти элементы будут отображаться в автомобиле. Используйте следующие стили контента:

Список элементов

Рисунок 1. Элементы списка отдают приоритет заголовкам и метаданным над изображениями.

Элементы сетки

Рисунок 2. Элементы сетки отдают приоритет изображениям по сравнению с заголовками и метаданными.

Установить стили содержимого по умолчанию

Вы можете задать глобальные значения по умолчанию для отображения медиа-элементов. Для этого включите определённые константы в пакет дополнительных функций BrowserRoot , возвращаемый реализацией onGetRoot вашего сервиса, и найдите эти константы, чтобы определить подходящий стиль.

Эти дополнения можно использовать в качестве ключей в комплекте:

Эти ключи могут соответствовать следующим целочисленным константным значениям, чтобы влиять на представление этих элементов:

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_LIST_ITEM : Соответствующие элементы, представленные как элементы списка.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_GRID_ITEM : Соответствующие элементы, представленные в виде элементов сетки.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_LIST_ITEM : Соответствующие элементы представлены как элементы списка «категории», аналогичные обычным элементам списка, но вокруг значков элементов применяются поля. Это улучшает внешний вид маленьких значков. Значки должны быть векторными, с возможностью тонирования. Ожидается, что эта подсказка будет предоставлена только для элементов, доступных для просмотра.

  • DESCRIPTION_EXTRAS_VALUE_CONTENT_STYLE_CATEGORY_GRID_ITEM : Соответствующие элементы представлены как элементы сетки «категории» и похожи на обычные элементы сетки, но вокруг значков элементов применяются поля. Это улучшает внешний вид мелких значков. Значки должны быть векторными, с возможностью тонирования. Ожидается, что эта подсказка будет предоставлена только для элементов, доступных для просмотра.

В этом фрагменте кода показано, как задать стиль содержимого по умолчанию для просматриваемых элементов в виде сеток, а для воспроизводимых элементов — в виде списков:

Котлин

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

Ява

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

Установить стили содержимого для каждого элемента

Вы можете переопределить стиль содержимого по умолчанию для всех дочерних элементов просматриваемого медиа-элемента, а также для любого медиа-элемента. Чтобы переопределить стиль содержимого по умолчанию для дочерних элементов просматриваемого медиа-элемента, создайте пакет дополнительных материалов в MediaDescription медиа-элемента и добавьте те же упомянутые ранее подсказки:

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE применяется к воспроизводимым потомкам этого элемента.

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE применяется к просматриваемым потомкам этого элемента.

Чтобы переопределить значение по умолчанию для конкретного медиа-элемента (но не для его потомков), создайте пакет дополнительных материалов в MediaDescription медиа-элемента. Затем добавьте подсказку с ключом DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM . Используйте те же значения, что и ранее, для указания представления этого элемента.

Этот фрагмент кода показывает, как создать просматриваемый MediaItem , который переопределяет стиль содержимого по умолчанию для себя и своих потомков. Он оформляет себя как элемент списка категорий, своих просматриваемых потомков — как элементы списка, а своих воспроизводимых потомков — как элементы сетки.

Котлин

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

Ява

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

Группируйте элементы, используя подсказки по заголовкам

Чтобы сгруппировать связанные медиа-элементы, используйте подсказку для каждого элемента. Каждый медиа-элемент в группе должен декларировать пакет дополнительных материалов в своём MediaDescription . Этот пакет должен включать сопоставление с ключом DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE и идентичным строковым значением. Локализуйте эту строку, так как она используется в заголовке группы.

В этом фрагменте кода показано, как создать MediaItem с заголовком подгруппы Songs :

Котлин

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

Ява

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

Ваше приложение должно передавать все медиа-элементы, которые вы хотите сгруппировать в виде непрерывного блока. Например, рассмотрите возможность отображения двух групп медиа-элементов: «Песни» и «Альбомы» — в указанном порядке. Если ваше приложение передает пять медиа-элементов в таком порядке, Android Auto и AAOS интерпретируют их как четыре отдельные группы:

  • Медиа-элемент A с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент B с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
  • Медиа-элемент C с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент D с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент E с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")

В результате получаются следующие четыре группы:

  • Группа 1, называемая «Песни», содержащая медиафайл A
  • Группа 2, называемая «Альбомы», содержащая медиафайл B
  • Группа 3, называемая «Песни», содержит медиафайлы C и D.
  • Группа 4, называемая «Альбомы», содержащая медиафайл E

Чтобы отобразить эти элементы в двух группах, ваше приложение должно передавать элементы мультимедиа в следующем порядке:

  • Медиа-элемент A с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент C с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент D с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • Медиа-элемент B с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")
  • Медиа-элемент E с extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums")

Отображать дополнительные индикаторы метаданных

Вы можете включить дополнительные индикаторы метаданных, чтобы предоставить наглядную информацию о контенте в дереве медиабраузера и во время воспроизведения.

В дереве обзора Android Auto и AAOS считывают дополнительные данные, связанные с элементом, и отображают индикаторы. Во время воспроизведения медиафайлов Android Auto и AAOS считывают метаданные медиасеанса и ищут определённые константы, чтобы определить, какие индикаторы отображать.

Просмотр воспроизведения с метаданными

Рисунок 3. Вид воспроизведения с метаданными.

Просмотреть невоспроизведенный контент.

Рисунок 4. Просмотр невоспроизведенного контента.

Эти константы можно использовать как в дополнительных описаниях MediaItem , так и в дополнительных материалах MediaMetadata :

  • EXTRA_DOWNLOAD_STATUS : Показывает статус загрузки элемента. Используйте эту константу в качестве ключа. Возможны следующие длинные константы:

  • METADATA_KEY_IS_EXPLICIT : Указывает, что элемент содержит явное содержимое. Чтобы указать, что элемент является явным, используйте эту константу в качестве ключа и длинное значение METADATA_VALUE_ATTRIBUTE_PRESENT в качестве значения.

Эти константы можно использовать только в дополнительных описаниях MediaItem :

Чтобы отображать индикаторы, появляющиеся при просмотре пользователем дерева медиаконтента, создайте пакет дополнительных данных, включающий одну или несколько из этих констант. Затем передайте этот пакет методу MediaDescription.Builder.setExtras .

В этом фрагменте показано, как отображать индикаторы для откровенного медиа-элемента, который завершен на 70%:

Котлин

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

Ява

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

Чтобы отобразить индикаторы для воспроизводимого в данный момент медиа-элемента, объявите значения для METADATA_KEY_IS_EXPLICIT или EXTRA_DOWNLOAD_STATUS в MediaMetadataCompat вашего mediaSession .

В этом фрагменте кода показано, как указать, что песня в представлении воспроизведения является ненормативной лексикой и загружена:

Котлин

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

Ява

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

Обновлять индикатор выполнения в режиме просмотра во время воспроизведения контента

Как упоминалось ранее, можно использовать дополнительный параметр DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE для отображения индикатора прогресса для частично воспроизведенного контента в режиме просмотра. Однако, если пользователь продолжает воспроизведение частично воспроизведенного контента, этот индикатор со временем становится неточным.

Чтобы Android Auto и AAOS поддерживали полосу прогресса в актуальном состоянии, предоставьте дополнительную информацию в MediaMetadataCompat и PlaybackStateCompat для привязки текущего содержимого к элементам мультимедиа в представлении обзора.

Чтобы медиа-элемент имел автоматически обновляемую полосу прогресса, должны быть соблюдены следующие требования:

В этом фрагменте кода показано, как указать, что воспроизводимый элемент связан с элементом в представлении обзора:

Котлин

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

Ява

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

Даже для невоспроизведённого или полностью воспроизведённого контента может отображаться автоматически обновляющийся индикатор прогресса. Это происходит, если соответствующие медиафайлы содержат дополнительный параметр DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE со значением 0.0 (для невоспроизведённого) или 1.0 (для полностью воспроизведённого). После выбора пользователем этих медиафайлов Android Auto и AAOS отображают индикатор прогресса поверх других индикаторов прогресса.