使用可浏览项或可播放项构建内容层次结构后,应用内容样式来确定这些项目在汽车中的显示方式。使用以下内容样式:

图 1. 列表项优先显示标题和元数据,其次是图片。

图 2. 网格项优先显示图片,其次是标题和元数据。
设置默认内容样式
您可以设置媒体项的全局默认显示方式。为此,请在服务 onGetRoot
实现返回的 BrowserRoot
extra 包中包含特定常量,并查找这些常量以确定合适的样式。
以下 extra 可用作软件包中的键:
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
:相应项以“类别”网格项的形式呈现,与普通网格项类似,但会在这些项的图标周围应用边距。这可改善小图标的外观。这些图标必须是可着色的矢量可绘制对象。此提示应仅针对可浏览项提供。
此代码段展示了如何将可浏览项的默认内容样式设置为网格,并将可播放项的默认内容样式设置为列表:
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);
}
按项设置内容样式
您可以替换任何可浏览媒体项的后代以及任何媒体项本身的默认内容样式。如需为可浏览媒体项的后代替换默认项,请在媒体项的 MediaDescription
中创建 extra 包,并添加上述相同的提示:
DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE
适用于该项的可播放后代。DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE
适用于该项的可浏览后代。
如需替换特定媒体项(而非其后代)的默认值,请在媒体项的 MediaDescription
中创建 extra 包。然后,添加一个键为 DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_SINGLE_ITEM
的提示。请使用上述相同值指定相应项的呈现方式。
此代码段展示了如何创建可浏览的 MediaItem
,用于替换其自身和后代的默认内容样式。它将自身设为类别列表项,将可浏览的后代项设置为列表项,将可播放的后代项设置为网格项。
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);
}
使用标题提示对项进行分组
如需将相关媒体项归入一组,请使用按项提示。组中的每个媒体项都必须在其 MediaDescription
中声明一个 extras 包。此软件包必须包含一个键为 DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE
的映射和一个相同的字符串值。本地化此字符串,因为它将用作群组的标题。
以下代码段展示了如何创建子组标题为 Songs
的 MediaItem
:
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*/);
}
您的应用必须将您想要归入一组的所有媒体项传递为一个连续的块。例如,假设您希望按“歌曲”和“专辑”的顺序显示两组媒体项。如果您的应用按此顺序传递五个媒体项,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 组名为“Songs”,包含媒体项 A
- 第 2 组名为“Albums”,包含媒体项 B
- 第 3 组名为“Songs”,包含媒体项 C 和 D
- 第 4 组名为“Albums”,包含媒体项 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 会读取与项关联的 extra 并显示指示符。在媒体播放期间,Android Auto 和 AAOS 会读取媒体会话的元数据,并查找特定常量来确定要显示的指示符。

图 3. 包含元数据的播放视图。

图 4. 未播放内容的浏览视图。
以下常量可同时用于 MediaItem
说明 extra 和 MediaMetadata
extra:
EXTRA_DOWNLOAD_STATUS
:表示项的下载状态。 将此常量用作键。以下长常量为可能的值:STATUS_DOWNLOADED
:项已下载完毕。STATUS_DOWNLOADING
:正在下载相应项。STATUS_NOT_DOWNLOADED
:未下载项。
METADATA_KEY_IS_EXPLICIT
:表示相应媒体项包含露骨内容。如需表明某个项为露骨内容,请使用此常量作为键,并使用长常量METADATA_VALUE_ATTRIBUTE_PRESENT
作为值。
以下常量只能在 MediaItem
说明 extra 中使用:
DESCRIPTION_EXTRAS_KEY_COMPLETION_STATUS
:表示较长内容(例如播客分集和有声读物)是否播放完毕。将此常量用作键。这些整数常量是可能的值:DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
:用 0.0 到 1.0(含)之间的双精度数值表示长片内容的播放进度。此 extra 会提供有关PARTIALLY_PLAYING
状态的更多信息,因此 Android Auto 或 AAOS 会显示更有意义的进度指示器,例如进度条。如果您使用此 extra,请参阅在内容播放时更新浏览视图中的进度条,了解如何使此指示符在初始播放后保持最新状态。
为了显示在用户浏览媒体浏览树时出现的指示器,可创建一个 extra 包,在其中加入一个或多个常量。然后,将该软件包传递给 MediaDescription.Builder.setExtras
方法。
以下代码段展示了如何为 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 */);
如需为当前播放的媒体项显示指示符,请在 mediaSession
的 MediaMetadataCompat
中声明 METADATA_KEY_IS_EXPLICIT
或 EXTRA_DOWNLOAD_STATUS
的值。
以下代码段展示了如何表明播放视图中的歌曲为露骨内容并已下载:
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());
在内容播放时更新浏览视图中的进度条
如上文所述,您可以使用 DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
extra 在浏览视图中显示部分播放内容的进度条。但是,如果用户继续播放已部分播放的内容,该指示器就会随着时间的推移而变得不准确。
为了使 Android Auto 和 AAOS 及时更新进度条,请在 MediaMetadataCompat
和 PlaybackStateCompat
中提供更多信息,以将正在播放的内容与浏览视图中的媒体项目相关联。
媒体项必须满足以下要求才能自动更新进度条:
创建后,
MediaItem
必须在其 extra 中发送DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
,其值介于0.0
和1.0
(含)之间。MediaMetadataCompat
必须发送METADATA_KEY_MEDIA_ID
,且字符串值等于传递到MediaItem
的媒体 ID。PlaybackStateCompat
必须包含一个键为PLAYBACK_STATE_EXTRAS_KEY_MEDIA_ID
的 extra,其映射到与传递到MediaItem
的媒体 ID 相同的字符串值。
此代码段展示了如何指示播放的项已关联到浏览视图中的项:
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
即使是未播放或播放完毕的内容,也可以显示自动更新的进度条。如果对应的媒体项包含值为 0.0
(未播放)或 1.0
(播放完毕)的 DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE
extra,就会发生这种情况。用户选择这些媒体项后,Android Auto 和 AAOS 会优先显示进度条,而非其他进度指示器。