يستدعي 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.
يختلف توقيع تطبيق نظام التشغيل AAOS حسب طراز السيارة وماركتها. احرص على السماح بالاتصالات من جميع تطبيقات النظام لإتاحة نظام التشغيل AAOS.
يوضّح مقتطف الرمز البرمجي هذا كيف يمكن أن تتحقّق خدمتك من أنّ الحزمة التي تجري الطلب هي تطبيق نظام:
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 في خدمتك.
بالإضافة إلى السماح لتطبيقات النظام، عليك السماح لـ Gemini أو "مساعد 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.
على سبيل المثال، إذا كنت تعرض عادةً عنصرًا قابلاً للتشغيل في الجذر، قد ترغب في وضعه ضِمن عنصر قابل للتصفّح في الجذر بدلاً من ذلك بسبب قيمة تلميح العلامات المتاحة.
بالإضافة إلى التلميحات الجذرية، استخدِم هذه الإرشادات لعرض علامات التبويب على النحو الأمثل:
رموز أحادية اللون (يفضّل أن تكون بيضاء) لكل عنصر من عناصر علامة التبويب
تصنيفات قصيرة وذات معنى لكل عنصر من عناصر علامة التبويب (تقلّل التصنيفات القصيرة من احتمالية اقتطاع التصنيفات)