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

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

Рисунок 2. В элементах сетки приоритет отдается изображениям, а не заголовкам и метаданным.
Установить стили контента по умолчанию
Вы можете установить глобальные параметры по умолчанию для отображения ваших медиафайлов. Для этого включите определенные константы в пакет дополнительных параметров BrowserRoot , возвращаемый реализацией onGetRoot вашего сервиса, и найдите эти константы, чтобы определить соответствующий стиль.
Эти дополнительные элементы можно использовать в качестве ключей в комплекте:
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE: Подсказка для отображения всех элементов, доступных для просмотра в дереве просмотра.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE: Подсказка для отображения всех воспроизводимых элементов в дереве просмотра.
Эти клавиши могут сопоставляться с этими целочисленными константными значениями, влияя на отображение этих элементов:
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)
}
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);
}
Задайте стили содержимого для каждого элемента.
Вы можете переопределить стиль содержимого по умолчанию для потомков любого просматриваемого медиафайла, а также для любого другого медиафайла. Чтобы переопределить стиль по умолчанию для потомков просматриваемого медиафайла, создайте пакет дополнительных элементов в MediaDescription медиафайла и добавьте те же подсказки, что и ранее:
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLEприменяется к играбельным потомкам этого предмета.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLEприменяется к просматриваемым потомкам этого элемента.
Чтобы переопределить значение по умолчанию для конкретного медиафайла (но не для его потомков), создайте пакет дополнительных материалов в MediaDescription медиафайла (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)
}
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);
}
Группируйте элементы, используя подсказки в заголовках.
Для группировки связанных медиафайлов используйте подсказку для каждого элемента. Каждый медиафайл в группе должен объявить пакет дополнительных материалов (extras bundle) в своем 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*/)
}
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*/);
}
Ваше приложение должно передавать все медиафайлы, которые вы хотите сгруппировать вместе, как единый блок. Например, рассмотрите возможность отображения двух групп медиафайлов: «Песни» и «Альбомы», именно в таком порядке. Если ваше приложение передаст пять медиафайлов в таком порядке, 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, называемая «Песни», содержит медиа-материал А.
- Группа 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: Указывает статус загрузки элемента. Используйте эту константу в качестве ключа. Возможные значения для следующих констант типа long:-
STATUS_DOWNLOADED: Файл полностью загружен. -
STATUS_DOWNLOADING: Файл находится в процессе загрузки. -
STATUS_NOT_DOWNLOADED: Элемент не загружен.
-
METADATA_KEY_IS_EXPLICIT: Указывает, что элемент содержит контент откровенного характера. Чтобы указать, что элемент содержит контент откровенного характера, используйте эту константу в качестве ключа, а длинное значениеMETADATA_VALUE_ATTRIBUTE_PRESENTв качестве значения.
Эти константы можно использовать только в дополнительных параметрах описания MediaItem :
DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS: Указывает состояние завершения воспроизведения длинноформатного контента, такого как эпизоды подкастов и аудиокниги. Используйте эту константу в качестве ключа. Возможные значения:DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_NOT_PLAYED: Предмет не был использован.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_PARTIALLY_PLAYED: Предмет частично воспроизведен, текущая позиция находится где-то посередине.DESCRIPTION_EXTRAS_VALUE_COMPLETION_STATUS_FULLY_PLAYED: Задание выполнено.
DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE: Отображает прогресс завершения воспроизведения длинного контента в виде числа от 0,0 до 1,0 включительно. Это предоставляет больше информации о состоянииPARTIALLY_PLAYING, позволяя Android Auto или AAOS отображать более информативный индикатор прогресса, например, полосу прогресса. Если вы используете этот параметр, см. раздел «Обновление полосы прогресса в режиме просмотра во время воспроизведения контента», чтобы узнать, как поддерживать этот индикатор в актуальном состоянии после первого показа.
Чтобы отображать индикаторы, которые появляются во время просмотра пользователем дерева медиафайлов, создайте пакет дополнительных материалов, включающий одну или несколько из этих констант. Затем передайте этот пакет методу 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 */)
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 */);
Чтобы отобразить индикаторы для воспроизводимого в данный момент медиафайла, объявите значения для 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())
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());
В режиме просмотра контента индикатор выполнения обновляется во время воспроизведения.
Как уже упоминалось ранее, вы можете использовать дополнительный параметр DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE для отображения индикатора выполнения частично воспроизведенного контента в режиме просмотра. Однако, если пользователь продолжает воспроизведение частично воспроизведенного контента, этот индикатор со временем становится неточным.
Чтобы Android Auto и AAOS поддерживали актуальность индикатора выполнения, необходимо предоставлять дополнительную информацию в полях MediaMetadataCompat и PlaybackStateCompat для связи текущего контента с медиафайлами в режиме просмотра.
Для того чтобы медиафайл имел автоматически обновляемую полосу прогресса, необходимо соблюдение следующих требований:
При создании объекта
MediaItemнеобходимо передатьDESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGEв разделе extras со значением от0.0до1.0включительно.Объект
MediaMetadataCompatдолжен отправлятьMETADATA_KEY_MEDIA_IDсо строковым значением, равным идентификатору медиафайла, переданномуMediaItem.Параметр
PlaybackStateCompatдолжен содержать дополнительный параметр с ключомPLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID, который сопоставляется со строковым значением, равным идентификатору медиафайла, переданному вMediaItem.
Этот фрагмент кода показывает, как указать, что воспроизводимый элемент связан с элементом в режиме просмотра:
Котлин
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());
Даже для невоспроизведенного или полностью воспроизведенного контента может отображаться автоматически обновляющаяся полоса прогресса. Это происходит, если соответствующие медиафайлы содержат дополнительный параметр DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE со значением 0.0 (для невоспроизведенного контента) или 1.0 (для полностью воспроизведенного контента). После выбора пользователем этих медиафайлов Android Auto и AAOS отображают полосу прогресса поверх других индикаторов выполнения.