套用內容樣式

使用可瀏覽或可播放的項目建構內容階層後,即可套用內容樣式來決定這些項目在車輛中的顯示方式。請使用下列內容樣式:

清單項目

圖 1. 清單項目會優先顯示名稱和中繼資料,而非圖片。

格線項目

圖 2. 格狀項目會優先顯示圖片,而非名稱和中繼資料。

設定預設內容樣式

您可以設定媒體項目顯示方式的通用預設值。如要這麼做,請在服務 onGetRoot 實作項目傳回的 BrowserRoot 額外套件中加入特定常數,並尋找這些常數來判斷適當的樣式。

在套裝組合中可以使用下列額外項目作為索引鍵:

這些鍵可對應至下列整數常數值,以影響這些項目的簡報:

下列程式碼片段說明如何將可瀏覽項目的預設內容樣式設為格線,並將可播放項目的預設內容樣式設定為清單:

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 中建立額外項目套裝組合,並新增之前提及的提示:

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_PLAYABLE 適用於該項目的可播放後代。

  • DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_BROWSABLE 適用於該項目的可瀏覽後代。

如要覆寫特定媒體項目 (非其後代) 的預設值,請在該媒體項目的 MediaDescription 中建立額外套件。然後使用 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 中宣告額外套件。這個套件必須包含具有索引鍵 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 會將這些項目解讀為四個不同的群組:

  • 包含 extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs") 的媒體項目 A
  • 包含 extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums") 的媒體項目 B
  • 包含 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, "Albums") 的媒體項目 E

這樣會產生下列四個群組:

  • 群組 1 稱為「歌曲」,內含媒體項目 A
  • 群組 2 稱為「專輯」,內含媒體項目 B
  • 群組 3 稱為「歌曲」,內含媒體項目 C 和 D
  • 群組 4 稱為「專輯」,內含媒體項目 E

如要讓這兩個群組顯示這些項目,應用程式必須按照下列順序傳遞媒體項目:

  • 包含 extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs") 的媒體項目 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, "Albums") 的媒體項目 B
  • 包含 extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Albums") 的媒體項目 E

顯示其他中繼資料指標

您可以加入其他中繼資料指標,藉此在媒體瀏覽器樹狀結構和播放期間提供一目瞭然的內容資訊。

在瀏覽樹狀結構中,Android Auto 和 AAOS 會讀取與某個項目相關的額外項目,並顯示指標。在媒體播放期間,Android Auto 和 AAOS 會讀取媒體工作階段的中繼資料,並尋找特定常數來決定要顯示哪些指標。

播放檢視畫面內含中繼資料

圖 3. 播放檢視畫面內含中繼資料。

瀏覽檢視畫面,顯示尚未播放的內容。

圖 4. 瀏覽檢視畫面,顯示尚未播放的內容。

這些常數可用於 MediaItem 說明額外項目和 MediaMetadata 額外項目:

這些常數可用於 MediaItem 說明額外項目:

如要顯示使用者正在瀏覽媒體樹狀結構時出現的指標,請建立含有一或多個常數的其他套裝組合。然後將該套件傳遞至 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 */);

如要顯示目前正在播放的媒體項目指標,請在 mediaSessionMediaMetadataCompat 中為 METADATA_KEY_IS_EXPLICITEXTRA_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 額外項目,在瀏覽檢視畫面中顯示已播放部分內容的進度列。不過,如果使用者持續播放已播放部分的內容,該項指標就會隨著時間流逝而變得不準確。

為了讓 Android Auto 和 AAOS 持續更新進度列,請在 MediaMetadataCompatPlaybackStateCompat 中提供其他資訊,將目前播放中的內容連結至瀏覽檢視畫面中的媒體項目。

媒體項目必須符合下列條件,才能自動更新進度列:

下列程式碼片段說明如何表示播放的項目已連結至瀏覽檢視畫面中的特定項目:

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 額外項目,就會發生這種情況。使用者選取這些媒體項目後,Android Auto 和 AAOS 會優先顯示進度列,而非其他進度指標。