החלת סגנונות תוכן

אחרי שמשתמשים בפריטים שאפשר לעיין בהם או להפעיל אותם כדי ליצור היררכיית תוכן, אפשר להחיל סגנונות תוכן כדי לקבוע איך הפריטים האלה יוצגו ברכב. אפשר להשתמש בסגנונות התוכן האלה:

פריטים ברשימה

איור 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: פריטים תואמים שמוצגים כפריטים ברשת של 'קטגוריה' ודומים לפריטים רגילים ברשת, אבל השוליים מוחלים סביב הסמלים של הפריטים. כך משפרים את המראה של סמלים קטנים. הסמלים צריכים להיות וקטורים שאפשר לצבוע אותם. ההצעה הזו אמורה להופיע רק לפריטים שאפשר לעיין בהם.

בקטע הקוד הבא מוצג איך להגדיר את סגנון התוכן שמוגדר כברירת מחדל לפריטים שאפשר לעיין בהם כרשתות ולפריטים שאפשר להפעיל כרשימות:

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 וערך מחרוזת זהה. צריך לבצע לוקליזציה של המחרוזת הזו, כי היא משמשת לכותרת של הקבוצה.

בקטע הקוד הבא אפשר לראות איך יוצרים MediaItem עם כותרת של קבוצת משנה 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*/);
}

האפליקציה צריכה להעביר את כל פריטי המדיה שרוצים לקבץ יחד כבלוק רציף. לדוגמה, נניח שרוצים להציג שתי קבוצות של פריטי מדיה, 'שירים' ו'אלבומים', בסדר הזה. אם האפליקציה מעבירה חמישה פריטי מדיה בסדר הזה, מערכות Android Auto ו-AAOS מפרשות אותם כארבע קבוצות נפרדות:

  • פריט מדיה א' עם extras.putString(MediaConstants.DESCRIPTION_EXTRAS_KEY_CONTENT_STYLE_GROUP_TITLE, "Songs")
  • קובץ מדיה ב' עם 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, שנקראת 'אלבומים', שמכילה את פריט המדיה ב'
  • קבוצה 3, שנקראת 'שירים', שמכילה את פריטי המדיה C ו-D
  • קבוצה 4, שנקראת 'אלבומים', שמכילה את פריט המדיה E

כדי להציג את הפריטים האלה בשתי קבוצות, האפליקציה צריכה להעביר את פריטי המדיה בסדר הזה:

  • פריט מדיה א' עם 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")
  • קובץ מדיה ב' עם 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 נכסי מידע נוסף:

אפשר להשתמש בקבועים האלה רק בתוספי תיאור של 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 */);

כדי להציג אינדיקטורים לפריט מדיה שמופעל כרגע, צריך להצהיר על ערכים של METADATA_KEY_IS_EXPLICIT או EXTRA_DOWNLOAD_STATUS ב-MediaMetadataCompat של mediaSession.

בקטע הקוד הבא מוצג איך לציין שהשיר בתצוגת ההפעלה הוא בתוכן בוטה והורד:

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 יתעדכן, צריך לספק מידע נוסף ב-MediaMetadataCompat וב-PlaybackStateCompat כדי לקשר תוכן שמתנגן לפריטי מדיה בתצוגת העיון.

כדי שסרגל ההתקדמות של פריט מדיה יתעדכן באופן אוטומטי, צריך לעמוד בדרישות הבאות:

בקטע הקוד הבא מוצג איך מציינים שהפריט שמופעל מקושר לפריט בתצוגת העיון:

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 גם תוכן שלא הופעל או שהופעל במלואו יכול להציג סרגל התקדמות שמתעדכן אוטומטית. הבעיה הזו מתרחשת אם פריטי המדיה התואמים כוללים את DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGEהתוספת עם הערך 0.0 (לתוכן שלא הופעל) או 1.0 (לתוכן שהופעל במלואו). אחרי שהמשתמש בוחר את פריטי המדיה האלה, מערכות Android Auto ו-AAOS מציגות את סרגל ההתקדמות מעל אינדיקטורים אחרים של התקדמות.