استخدِم واجهة برمجة التطبيقات Instrument Cluster API (واجهة برمجة تطبيقات Android) لعرض تطبيقات التنقّل،
بما في ذلك "خرائط Google"، على شاشة ثانوية في السيارة، مثل الشاشة التي تظهر خلف
عجلة القيادة على لوحة العدادات. توضّح هذه الصفحة كيفية إنشاء
خدمة للتحكّم في هذا العرض الثانوي ودمج الخدمة مع
CarService
حتى تتمكّن تطبيقات التنقّل من عرض
واجهة مستخدم.
المصطلحات
يتم استخدام المصطلحات التالية في هذه الصفحة.
CarManager
يتيح للتطبيقات الخارجية بدء نشاط على
مجموعة العدادات وتلقّي عمليات استدعاء عندما تكون مجموعة العدادات جاهزة لعرض
الأنشطةandroid:singleUser
في
أي وقت معيّن، يتم تشغيل نسخة واحدة على الأكثر من الخدمة على نظام Android.المتطلّبات الأساسية
قبل المتابعة، تأكَّد من توفّر العناصر التالية:
- بيئة تطوير Android: لإعداد بيئة تطوير Android ، يُرجى الاطّلاع على متطلبات الإنشاء.
- تنزيل رمز المصدر لنظام التشغيل Android احصل على أحدث إصدار من رمز المصدر لنظام التشغيل Android من فرع pi-car-release (أو إصدار أحدث) على https://android.googlesource.com.
- وحدة التحكّم (HU) جهاز Android يمكنه تشغيل نظام التشغيل Android 9 (أو إصدار أحدث) يجب أن يكون لهذا الجهاز شاشة خاصة به وأن يكون قادرًا على فلاش الشاشة باستخدام إصدارات جديدة من Android.
- لوحة العدادات هي إحدى العناصر التالية:
- شاشة ثانوية خارجية مرفقة بوحدة التحكّم في الصوت والصورة إذا كان عتاد الجهاز والنواة يتيحان إدارة شاشات متعددة.
- وحدة مستقلة: أي وحدة معالجة متصلة بالوحدة المعالجة (HU) عبر اتصال بالشبكة، ويمكنها تلقّي بث فيديو وعرضه على شاشة خاصة بها
- شاشة محاكية: أثناء التطوير، يمكنك استخدام إحدى
البيئات المحاكية التالية:
- الشاشات الثانوية التي يتمّ محاكاتها: لتفعيل شاشة ثانوية محاكية على أي إصدار من AOSP Android، انتقِل إلى إعدادات خيارات المطوّر في تطبيق الإعدادات، ثم اختَر محاكاة الشاشات الثانوية. ويعادل هذا الإعداد عملية إرفاق شاشة ثانوية فعلية، مع القيد أنّ هذه الشاشة يتم عرضها فوق الشاشة الأساسية.
- مجموعة الأدوات المحاكية: يقدّم محاكي Android المضمّن في نظام التشغيل AAOS خيارًا لعرض مجموعة العدادات باستخدام ClusterRenderingService.
بنية الدمج
مكونات الدمج
يتألف أيّ دمج لواجهة برمجة التطبيقات Instrument Cluster API من المكوّنات الثلاثة التالية:
CarService
- تطبيقات التنقّل
- خدمة مجموعة العدادات لدى المصنّع الأصلي للجهاز
CarService
يعمل الإذن CarService
كوسيط بين تطبيقات التنقّل والسيارة، ما يضمن عدم تفعيل سوى
تطبيق تنقّل واحد في أي وقت، ولا يمكن إلا للتطبيقات التي تمتلك الإذن
android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
إرسال البيانات
إلى السيارة.
يبدأ CarService
جميع الخدمات المتعلّقة بالسيارات ويوفّر إمكانية الوصول إلى
هذه الخدمات من خلال سلسلة من المدراء. للتفاعل مع الخدمات، يمكن للتطبيقات التي تعمل في السيارة الوصول إلى هذه العناصر الإدارية.
لتنفيذ مجموعة العدادات، على المصنّعين الأصليّين للسيارات إنشاء تنفيذ مخصّص لـ InstrumentClusterRendererService وتعديل ClusterRenderingService.
عند عرض مجموعة العدادات، يقرأ المعالج
CarService
مفتاح InstrumentClusterRendererService
في
ClusterRenderingService
لتحديد موقع تنفيذ InstrumentClusterService
أثناء عملية التشغيل. في AOSP، يشير هذا الإدخال
إلى خدمة عرض تنفيذ مجموعة نماذج واجهة برمجة التطبيقات Navigation State API:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
تم إعداد الخدمة المُشار إليها في هذا الإدخال وربطها بملف تعريف الارتباط
CarService
. عندما تطلب تطبيقات التنقّل، مثل "خرائط Google"، CarInstrumentClusterManager
، يوفّر CarService
مديرًا
يعدّل حالة مجموعة العدادات من InstrumentClusterRenderingService
المرتبط.
(في هذه الحالة، يشير bound إلى
خدمات
Android.)
خدمة مجموعة العدادات
على المصنّعين الأصليّين للأجهزة إنشاء حزمة Android (APK) تحتوي على فئة فرعية من ClusterRenderingService.
تخدم هذه الفئة غرضَين:
- يوفّر واجهة Android وجهاز عرض مجموعة العدادات (الغرض من هذه الصفحة).
- تتلقّى هذه الخدمة آخر المعلومات المتعلّقة بحالة التنقّل وتعرضها، مثل الإرشادات المتعلّقة بالتنقّل المفصّلة.
بالنسبة إلى الغرض الأول، يجب أن تبدأ عمليات تنفيذ InstrumentClusterRendererService
من المصنّعين الأصليّين للسيارات شاشة العرض الثانوية المستخدَمة لعرض المعلومات على الشاشات في مقصورة السيارة، ويجب أن تُرسِل
هذه المعلومات إلى CarService
من خلال استدعاء الطريقتَين
InstrumentClusterRendererService.setClusterActivityOptions()
و
InstrumentClusterRendererService.setClusterActivityState()
.
بالنسبة إلى الوظيفة الثانية، يجب أن تقدّم خدمة "مجموعة العدادات" تنفيذًا لواجهة
ClusterRenderingService
التي تتلقّى أحداث تعديل حالة التنقّل، والتي يتم ترميزها على أنّها
eventType
وبيانات الأحداث التي يتم ترميزها في حزمة.
تسلسل الدمج
يوضّح الرسم البياني التالي تنفيذ حالة التنقّل التي تعرِض التعديلات:
في هذه الصورة التوضيحية، تشير الألوان إلى ما يلي:
- اللون الأصفر:
CarService
وCarNavigationStatusManager
المقدَّمة من نظام Android الأساسي لمزيد من المعلومات، يُرجى الاطّلاع على Car و CAR_NAVIGATION_SERVICE. - أزرق سماوي:
InstrumentClusterRendererService
تم تنفيذه من قِبل المصنّع الأصلي للجهاز. - الأرجواني: تطبيق "التنقّل" الذي تنفّذه Google ومطوّرون تابعون لجهات خارجية
- الأخضر:
CarAppFocusManager
. لمزيد من المعلومات، يُرجى الاطّلاع على استخدام واجهة برمجة التطبيقات CarAppFocusManager API أدناه وCarAppFocusManager.
يتّبع تدفّق معلومات حالة التنقّل التسلسل التالي:
- يبدأ
CarService
عملية إعدادInstrumentClusterRenderingService
. - أثناء الإعداد، يعدّل
InstrumentClusterRenderingService
CarService
باستخدام:- تعرِض مجموعة العدادات خصائص، مثل الحدود غير المموَّهة (اطّلِع على مزيد من التفاصيل عن الحدود غير المموَّهة لاحقًا).
- خيارات الأنشطة المطلوبة لبدء الأنشطة داخل شاشة مجموعة العدادات لمزيد من المعلومات، اطّلِع على ActivityOptions.
- تطبيق تنقّل (مثل "خرائط Google" لنظام التشغيل Android Automotive أو أي تطبيق خرائط
يمتلك الأذونات المطلوبة):
- الحصول على
CarAppFocusManager
باستخدام فئة Car من car-lib - قبل بدء عرض الاتجاهات التفصيلية، يتمّ استدعاء
CarAppFocusManager.requestFocus()
لضبطCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
كمَعلمةappType
.
- الحصول على
- يُبلغ "
CarAppFocusManager
" "CarService
" بهذا الطلب. في حال منحه الإذن، يفحصCarService
حِزمة تطبيق التنقّل ويحدِّد موقع نشاط تم وضع علامة عليه بالفئةandroid.car.cluster.NAVIGATION
. - في حال العثور على التطبيق، يستخدم تطبيق التنقّل
ActivityOptions
الذي أبلغ عنهInstrumentClusterRenderingService
لبدء النشاط، ويشمل خصائص شاشة "مجموعة العدادات" كعناصر إضافية في النية.
دمج واجهة برمجة التطبيقات
يجب أن يستوفي تنفيذ InstrumentClusterRenderingService
الشروط التالية:
- أن يتم تصنيفها كخدمة فردية من خلال إضافة القيمة التالية إلىملف AndroidManifest.xml: هذا الإجراء ضروري لضمان تشغيل نسخة واحدة من
خدمة "مجموعة العدادات"، حتى أثناء عملية الإعداد وتبديل المستخدمين:
android:singleUser="true"
- احتفظ بإذن النظام
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
. يضمن ذلك أنّ خدمة عرض لوحة البيانات المضمّنة كجزء من صورة نظام Android هي فقط التي تخضع للقيود المفروضة علىCarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
تنفيذ InstrumentClusterRenderingService
لإنشاء الخدمة:
- اكتب فئة تمتد من
ClusterRenderingService
ثم أضِف إدخالًا متوافقًا إلى ملف
AndroidManifest.xml
. تتحكّم هذه الفئة في شاشة مجموعة العدادات ويمكنها (اختياريًا) عرض بيانات واجهة برمجة التطبيقات الخاصة بحالة التنقل. - أثناء
onCreate()
، استخدِم هذه الخدمة لبدء الاتصال بأحد مكونات الأجهزة المسؤولة عن العرض. تشمل الخيارات ما يلي:- حدِّد الشاشة الثانوية التي سيتم استخدامها في مجموعة العدادات.
- أنشئ شاشة افتراضية لكي يعرض تطبيق "مجموعة العدادات" وينقل الصورة المعروضة إلى وحدة خارجية (باستخدام تنسيق بث فيديو، مثل H.264).
- عندما تكون الشاشة المُشار إليها أعلاه جاهزة، يجب أن تستدعي هذه الخدمة
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
لتحديدActivityOptions
الدقيق الذي يجب استخدامه لعرض نشاط على مجموعة العدادات. استخدِم المَعلمات التالية:category.
ClusterRenderingService.ActivityOptions.
مثيلActivityOptions
يمكن استخدامه لبدء نشاط في مجموعة العدادات على سبيل المثال، من المثال على تنفيذ مجموعة العدادات على AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- عندما تكون مجموعة العدادات جاهزة لعرض الأنشطة، يجب أن تستدعي هذه الخدمة
InstrumentClusterRenderingService#setClusterActivityState()
. استخدِم المَعلمات التالية:category
ClusterRenderingService.state
حِزمة تم إنشاؤها باستخدام ClusterRenderingService احرص على تقديم هذه البيانات:visible
يحدِّد "مجموعة العدادات" على أنّها مرئية وجاهزة ل عرض المحتوى.unobscuredBounds
مستطيل يحدّد المنطقة ضمن شاشة مجموعة العدادات التي يمكن فيها عرض المحتوى بأمان على سبيل المثال، المناطق التي تغطّيها لوحات المقاييس
- يمكنك إلغاء طريقة
Service#dump()
والإبلاغ عن معلومات الحالة المفيدة ل debugging (يمكنك الاطّلاع على dumpsys للحصول على مزيد من المعلومات).
مثال على تنفيذ InstrumentClusterRenderingService
يوضّح المثال التالي عملية InstrumentClusterRenderingService
تنفيذ، والتي تنشئ VirtualDisplay
لعرض محتوى Instrument
Cluster على شاشة جهاز عرض عن بُعد.
بدلاً من ذلك، يمكن أن ينقل هذا الرمز displayId
لشاشة ملفتة للانتباه
ثانوية متصلة بوحدة التحكّم في الصوت، إذا كان من المعروف أنّها متاحة.
/** * Sample {@link InstrumentClusterRenderingService} implementation */ public class SampleClusterServiceImpl extends InstrumentClusterRenderingService { // Used to retrieve or create displays private final DisplayManager mDisplayManager; // Unique identifier for the display to be used for instrument // cluster private final String mUniqueId = UUID.randomUUID().toString(); // Format of the instrument cluster display private static final int DISPLAY_WIDTH = 1280; private static final int DISPLAY_HEIGHT = 720; private static final int DISPLAY_DPI = 320; // Area not covered by instruments private static final int DISPLAY_UNOBSCURED_LEFT = 40; private static final int DISPLAY_UNOBSCURED_TOP = 0; private static final int DISPLAY_UNOBSCURED_RIGHT = 1200; private static final int DISPLAY_UNOBSCURED_BOTTOM = 680; @Override public void onCreate() { super.onCreate(); // Create a virtual display to render instrument cluster activities on mDisplayManager = getSystemService(DisplayManager.class); VirtualDisplay display = mDisplayManager.createVirtualDisplay( mUniqueId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, null, 0 /* flags */, null, null); // Do any additional initialization (e.g.: start a video stream // based on this virtual display to present activities on a remote // display). onDisplayReady(display.getDisplay()); } private void onDisplayReady(Display display) { // Report activity options that should be used to launch activities on // the instrument cluster. String category = CarInstrumentClusterManager.CATEGORY_NAVIGATION; ActionOptions options = ActivityOptions.makeBasic() .setLaunchDisplayId(display.getDisplayId()); setClusterActivityOptions(category, options); // Report instrument cluster state. Rect unobscuredBounds = new Rect(DISPLAY_UNOBSCURED_LEFT, DISPLAY_UNOBSCURED_TOP, DISPLAY_UNOBSCURED_RIGHT, DISPLAY_UNOBSCURED_BOTTOM); boolean visible = true; ClusterActivityState state = ClusterActivityState.create(visible, unobscuredBounds); setClusterActivityState(category, options); } }
استخدام واجهة برمجة التطبيقات CarAppFocusManager API
توفّر واجهة برمجة التطبيقات CarAppFocusManager طريقة باسم getAppTypeOwner()
، ما يسمح
لخدمة الكتلة التي كتبتها المصنّعين الأصليّين للسيارات بمعرفة تطبيق التنقّل الذي يحظى بتركيز التنقّل في أي وقت معيّن. يمكن لمصنّعي الأجهزة الأصليين استخدام طريقة CarAppFocusManager#addFocusListener()
الحالية، ثم استخدام getAppTypeOwner()
لمعرفة التطبيق الذي تم التركيز عليه. باستخدام هذه المعلومات،
يمكن لمصنّعي المعدّات الأصلية إجراء ما يلي:
- تبديل النشاط المعروض في المجموعة إلى نشاط المجموعة المقدَّم من تطبيق التنقّل مع الاحتفاظ بالتركيز
- يمكنه رصد ما إذا كان تطبيق التنقّل المُركّز يتضمّن نشاطًا لمجموعة أم لا. إذا لم يكن تطبيق التنقّل المُركّز عليه يتضمّن نشاطًا للشاشة المتكاملة (أو إذا كان هذا النشاط غير مفعّل)، يمكن لمصنّعي السيارات إرسال هذه الإشارة إلى وحدة التحكّم في الإضاءة (DIM) في السيارة لتخطّي سمة التنقّل في الشاشة المتكاملة تمامًا.
استخدِم CarAppFocusManager
لضبط تركيز التطبيق الحالي والاستماع إليه، مثل
التنقّل النشط أو طلب صوتي. وعادةً ما يكون هناك مثيل واحد فقط من هذا التطبيق يعمل (أو يكون مُركّزًا عليه) في النظام.
استخدِم طريقة CarAppFocusManager#addFocusListener(..)
للاستماع إلى
تغييرات تركيز التطبيق:
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); mAppFocusManager.addFocusListener(this, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); ... public void onAppFocusChanged(int appType, boolean active) { // Use the CarAppFocusManager#getAppTypeOwner(appType) method call // to retrieve a list of active package names }
استخدِم الطريقة CarAppFocusManager#getAppTypeOwner(..)
لاسترداد اسمَي الحزمة
للمالك الحالي لنوع تطبيق معيّن في التركيز. قد تعرض هذه الطريقة
أكثر من اسم حزمة واحد إذا كان المالك الحالي يستخدم ميزة android:sharedUserId
.
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); List<String> focusOwnerPackageNames = mAppFocusManager.getAppTypeOwner( CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); if (focusOwnerPackageNames == null || focusOwnerPackageNames.isEmpty()) { // No Navigation app has focus // OEM may choose to show their default cluster view } else { // focusOwnerPackageNames // Use the PackageManager to retrieve the cluster activity for the package(s) // returned in focusOwnerPackageNames } ...
الملحق: استخدام التطبيق النموذجي
يقدّم AOSP نموذج تطبيق ينفذ واجهة برمجة التطبيقات Navigation State API.
لتشغيل نموذج التطبيق هذا:
- إنشاء نظام Android Auto وفلاشه على وحدة تحكّم رئيسية متوافقة استخدِم التعليمات الخاصة بإنشاء نظام التشغيل Android وتثبيته على جهازك. للحصول على التعليمات، يُرجى الاطّلاع على استخدام لوحات المراجع.
- وصِّل شاشة عرض ثانوية خارجية بالشاشة (إذا كان ذلك متاحًا) أو فعِّل شاشة العرض الافتراضية
الثانوية:
- اختَر وضع المطوّر في تطبيق "الإعدادات".
- انتقِل إلى الإعدادات > النظام > الإعدادات المتقدّمة > خيارات المطوّرين > محاكاة الشاشات الثانوية.
- إعادة تشغيل HU
- لتشغيل تطبيق KitchenSink:
- افتح الدرج.
- انتقِل إلى Inst. Cluster (مجموعة النشر).
- انقر على بدء عملية إضافة البيانات الوصفية.
يطلب KitchenSink التركيز على NAVIGATION، ما يوجّه DirectRenderingCluster
الخدمة إلى عرض واجهة مستخدم مصمّمة على لوحة العدادات.