تطبيق أنماط المحتوى

بعد استخدام العناصر القابلة للتصفّح أو التشغيل لـ إنشاء التدرّج الهرمي للمحتوى، يمكنك تطبيق أنماط المحتوى لتحديد كيفية عرض هذه العناصر في السيارة. استخدِم أنماط المحتوى التالية:

عناصر القائمة

الشكل 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 على أنّها أربع مجموعات منفصلة:

  • عنصر الوسائط 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:

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

يمكن أن يعرض المحتوى الذي لم يتم تشغيله أو الذي تم تشغيله بالكامل شريط تقدّم يتم تعديله تلقائيًا. يحدث ذلك إذا كانت عناصر الوسائط المقابلة تتضمّن الإضافة DESCRIPTION_EXTRAS_KEY_COMPLETION_PERCENTAGE بقيمة 0.0 (للمحتوى الذي لم يتم تشغيله) أو 1.0 (للمحتوى الذي تم تشغيله بالكامل). بعد أن يختار المستخدم عناصر الوسائط هذه، يعرض Android Auto وAAOS شريط التقدّم فوق مؤشرات التقدّم الأخرى.