تستدعي كلّ من Android Auto ونظام التشغيل Android Automotive (AAOS) خدمة متصفّح الوسائط في تطبيقك لمعرفة المحتوى المتاح. لإتاحة ذلك، عليك تنفيذ هاتين الطريقتين في خدمة متصفّح الوسائط.
تنفيذ onGetRoot
تعرض طريقة onGetRoot في خدمتك معلومات حول العقدة الجذرية
للتسلسل الهرمي للمحتوى. يستخدم Android Auto وAAOS عقدة الجذر هذه لطلب بقية المحتوى باستخدام طريقة onLoadChildren. يعرض مقتطف الرمز البرمجي التالي عملية تنفيذ الطريقة onGetRoot:
Kotlin
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle?
): BrowserRoot? =
// Verify that the specified package is allowed to access your
// content. You'll need to write your own logic to do this.
if (!isValid(clientPackageName, clientUid)) {
// If the request comes from an untrusted package, return null.
// No further calls will be made to other media browsing methods.
null
} else MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null)
Java
@Override
public BrowserRoot onGetRoot(String clientPackageName, int clientUid,
Bundle rootHints) {
// Verify that the specified package is allowed to access your
// content. You'll need to write your own logic to do this.
if (!isValid(clientPackageName, clientUid)) {
// If the request comes from an untrusted package, return null.
// No further calls will be made to other media browsing methods.
return null;
}
return new MediaBrowserServiceCompat.BrowserRoot(MY_MEDIA_ROOT_ID, null);
}
للاطّلاع على مثال مفصّل لهذه الطريقة، يُرجى الرجوع إلى onGetRoot في نموذج تطبيق Universal
Android Music Player على GitHub.
إضافة التحقّق من صحة الحزمة
عند إجراء مكالمة إلى طريقة onGetRoot في خدمتك، ترسل حزمة الاتصال معلومات تكشف الهوية إلى خدمتك. يمكن أن تستخدم خدمتك هذه المعلومات لتحديد ما إذا كان بإمكان هذه الحزمة الوصول إلى المحتوى الخاص بك.
على سبيل المثال، يمكنك حصر إمكانية الوصول إلى محتوى تطبيقك على قائمة بالحِزم المعتمَدة:
- قارِن
clientPackageNameبقائمة السماح. - تحقَّق من الشهادة المستخدَمة لتوقيع حزمة APK الخاصة بالحزمة.
إذا تعذّر التحقّق من الحزمة، ارجع إلى null لرفض الوصول إلى المحتوى.
لتزويد تطبيقات النظام، مثل Android Auto وAAOS، بإمكانية الوصول إلى المحتوى الخاص بك، يجب أن تعرض خدمتك قيمة غير فارغة BrowserRoot عندما تستدعي تطبيقات النظام هذه الطريقة onGetRoot.
تختلف توقيعات تطبيقات نظام التشغيل Android Automotive حسب ماركة السيارة وطرازها. احرص على السماح بالاتصالات من جميع تطبيقات النظام لتوفير الدعم لنظام التشغيل Android Automotive.
يوضّح مقتطف الرمز التالي كيف يمكن لخدمتك التحقّق من أنّ الحزمة التي تستدعي الخدمة هي تطبيق نظام:
fun isKnownCaller(
callingPackage: String,
callingUid: Int
): Boolean {
...
val isCallerKnown = when {
// If the system is making the call, allow it.
callingUid == Process.SYSTEM_UID -> true
// If the app was signed by the same certificate as the platform
// itself, also allow it.
callerSignature == platformSignature -> true
// ... more cases
}
return isCallerKnown
}
مقتطف الرمز هذا هو جزء من الفئة PackageValidator في
نموذج تطبيق Universal Android Music Player على GitHub. راجِع هذا الصف للحصول على مثال أكثر تفصيلاً حول كيفية تنفيذ عملية التحقّق من صحة الحزمة لطريقة onGetRoot في خدمتك.
بالإضافة إلى السماح لتطبيقات النظام، يجب السماح لـ "مساعد Google" بالاتصال بجهاز MediaBrowserService. يستخدم "مساعد Google" أسماء حِزم مختلفة لتطبيقاته على الأجهزة الجوّالة وAAOS.
تنفيذ onLoadChildren
بعد تلقّي عنصر العقدة الجذرية، ينشئ كل من Android Auto وAAOS قائمة ذات مستوى أعلى من خلال استدعاء onLoadChildren على عنصر العقدة الجذرية للحصول على العناصر التابعة له. تنشئ تطبيقات العميل القوائم الفرعية من خلال استدعاء الطريقة نفسها
باستخدام عناصر العقدة الفرعية.
يتم تمثيل كل عقدة في التسلسل الهرمي للمحتوى الخاص بك باستخدام عنصر MediaBrowserCompat.MediaItem. يتم تحديد كل عنصر من عناصر الوسائط هذه من خلال سلسلة معرّف فريدة. وتتعامل تطبيقات العميل مع سلاسل المعرّفات هذه على أنّها رموز مميّزة غير شفافة.
عندما يريد تطبيق العميل الانتقال إلى قائمة فرعية أو تشغيل عنصر وسائط، يمرّر الرمز المميز. ويتحمّل تطبيقك مسؤولية ربط الرمز المميز بعنصر الوسائط المناسب.
يعرض مقتطف الرمز هذا عملية تنفيذ onLoadChildren
Kotlin
override fun onLoadChildren(
parentMediaId: String,
result: Result<List<MediaBrowserCompat.MediaItem>>
) {
// Assume for example that the music catalog is already loaded/cached.
val mediaItems: MutableList<MediaBrowserCompat.MediaItem> = mutableListOf()
// Check if this is the root menu:
if (MY_MEDIA_ROOT_ID == parentMediaId) {
// Build the MediaItem objects for the top level
// and put them in the mediaItems list.
} else {
// Examine the passed parentMediaId to see which submenu we're at
// and put the descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems)
}
Java
@Override
public void onLoadChildren(final String parentMediaId,
final Result<List<MediaBrowserCompat.MediaItem>> result) {
// Assume for example that the music catalog is already loaded/cached.
List<MediaBrowserCompat.MediaItem> mediaItems = new ArrayList<>();
// Check if this is the root menu:
if (MY_MEDIA_ROOT_ID.equals(parentMediaId)) {
// Build the MediaItem objects for the top level
// and put them in the mediaItems list.
} else {
// Examine the passed parentMediaId to see which submenu we're at
// and put the descendants of that menu in the mediaItems list.
}
result.sendResult(mediaItems);
}
للاطّلاع على مثال على هذه الطريقة، راجِع onLoadChildren في
نموذج تطبيق Universal Android Music Player على GitHub.
بنية القائمة الرئيسية
يفرض كلّ من Android Auto ونظام التشغيل Android Automotive قيودًا معيّنة على بنية القائمة الجذر. يتم إرسال هذه المعلومات إلى MediaBrowserService
من خلال تلميحات الجذر، ويمكن قراءتها من خلال وسيطة الحزمة التي تم تمريرها إلى
onGetRoot(). وعند اتّباع هذه التلميحات، سيسمح ذلك للنظام بعرض المحتوى الأساسي كعلامات تبويب للتنقّل. في حال عدم اتّباع هذه التلميحات، قد يتم إسقاط بعض المحتوى الأساسي أو يصبح أقل قابلية للاكتشاف من قِبل النظام.

الشكل 1: المحتوى الأساسي المعروض كعلامات تبويب للتنقّل
ومن خلال تطبيق هذه التلميحات، يعرض النظام المحتوى الأساسي على شكل علامات تبويب خاصة بالتنقل. وفي حال عدم تطبيق هذه التلميحات، قد يتم إسقاط بعض المحتوى الأساسي أو جعله أقل قابلية للاكتشاف. يتم إرسال هذه التلميحات:
الحدّ الأقصى لعدد العناصر الفرعية الرئيسية: في معظم الحالات، من المتوقّع أن يكون هذا العدد أربعة، ما يعني أنّه يمكن عرض أربعة علامات تبويب (أو أقل) فقط.
العلامات المتوافقة مع العناصر الفرعية الجذر: من المتوقّع أن تكون هذه القيمة
MediaItem#FLAG_BROWSABLE، ما يعني أنّه يمكن عرض العناصر التي يمكن تصفّحها فقط (وليس العناصر التي يمكن تشغيلها) كعلامات تبويب.الحدّ الأقصى لعدد إجراءات التصفّح المخصّصة: تحقَّق من عدد إجراءات التصفّح المخصّصة المتاحة.
Kotlin
import androidx.media.utils.MediaConstants
override fun onGetRoot(
clientPackageName: String,
clientUid: Int,
rootHints: Bundle
): BrowserRoot {
val maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
/* defaultValue= */ 4)
val supportedRootChildFlags = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ MediaItem.FLAG_BROWSABLE)
// Rest of method...
}
Java
import androidx.media.utils.MediaConstants;
// Later, in your MediaBrowserServiceCompat.
@Override
public BrowserRoot onGetRoot(
String clientPackageName, int clientUid, Bundle rootHints) {
int maximumRootChildLimit = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_LIMIT,
/* defaultValue= */ 4);
int supportedRootChildFlags = rootHints.getInt(
MediaConstants.BROWSER_ROOT_HINTS_KEY_ROOT_CHILDREN_SUPPORTED_FLAGS,
/* defaultValue= */ MediaItem.FLAG_BROWSABLE);
// Rest of method...
}
يمكنك اختيار تقسيم منطق بنية التسلسل الهرمي للمحتوى استنادًا إلى قيم هذه التلميحات، خاصةً إذا كان التسلسل الهرمي يختلف بين عمليات الدمج MediaBrowser خارج Android Auto وAAOS.
على سبيل المثال، إذا كنت تعرض عادةً عنصرًا قابلاً للتشغيل على المستوى الأعلى، قد تحتاج إلى تضمينه ضمن عنصر قابل للتصفّح على المستوى الأعلى بدلاً من ذلك بسبب قيمة تلميح العلامات المتوافقة.
بالإضافة إلى تلميحات الجذر، اتّبِع الإرشادات التالية لعرض علامات التبويب على النحو الأمثل:
رموز أحادية اللون (يُفضّل أن تكون بيضاء) لكل عنصر من عناصر علامات التبويب
تسميات قصيرة وواضحة لكل عنصر من عناصر علامات التبويب (تؤدي التسميات القصيرة إلى تقليل احتمالية اقتطاع التسميات)