Instrument Cluster API

استخدِم واجهة برمجة التطبيقات Instrument Cluster API (واجهة برمجة تطبيقات Android) لعرض تطبيقات التنقّل، بما في ذلك "خرائط Google"، على شاشة ثانوية في السيارة، مثل الشاشة التي تظهر خلف عجلة القيادة على لوحة العدادات. توضّح هذه الصفحة كيفية إنشاء خدمة للتحكّم في هذا العرض الثانوي ودمج الخدمة مع CarService حتى تتمكّن تطبيقات التنقّل من عرض واجهة مستخدم.

المصطلحات

يتم استخدام المصطلحات التالية في هذه الصفحة.

CarInstrumentClusterManager
مثيل من CarManager يتيح للتطبيقات الخارجية بدء نشاط على مجموعة العدادات وتلقّي عمليات استدعاء عندما تكون مجموعة العدادات جاهزة لعرض الأنشطة
CarManager
الفئة الأساسية لجميع المدراء الذين تستخدمهم التطبيقات الخارجية للتفاعل مع خدمات متعلقة بالسيارة ينفذها CarService
CarService
خدمة نظام Android الأساسي التي توفّر إمكانية التواصل بين التطبيقات الخارجية (بما في ذلك "خرائط Google") والميزات الخاصة بالسيارة، مثل الوصول إلى لوحة العدادات
الوجهة
الوجهة النهائية التي ستنتقل إليها المركبة.
الوقت المقدَّر للوصول
الوقت المقدَّر للوصول إلى وجهة معيّنة
الوحدة الرئيسية (HU)
وحدة الحساب الأساسية المضمّنة في سيارة يشغِّل HU جميع رموز Android ويتم ربطه بالشاشة المركزية في السيارة.
مجموعة العدادات
الشاشة الثانوية التي تقع خلف عجلة القيادة وبين أدوات السيارة يمكن أن تكون هذه وحدة حسابية مستقلة متصلة بالنظام الترفيهي في السيارة من خلال الشبكة الداخلية للسيارة (حافلة CAN) أو شاشة ثانوية مرتبطة بالنظام الترفيهي في السيارة.
InstrumentClusterRenderingService
الفئة الأساسية للخدمة المستخدَمة للتفاعل مع شاشة مجموعة المقاييس على المصنّعين الأصليين للأجهزة تقديم إضافة لهذه الفئة تتفاعل مع الأجهزة الخاصة بالمصنّع الأصلي للجهاز.
تطبيق KitchenSink
تطبيق الاختبار مضمّن في Android Automotive.
مسار الجولة
مسار محدّد تسير المركبة على طوله للوصول إلى وجهة معيّنة.
خدمة Singleton
خدمة Android تتضمّن السمة 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.

يتّبع تدفّق معلومات حالة التنقّل التسلسل التالي:

  1. يبدأ CarService عملية إعداد InstrumentClusterRenderingService.
  2. أثناء الإعداد، يعدّل InstrumentClusterRenderingService CarService باستخدام:
    1. تعرِض مجموعة العدادات خصائص، مثل الحدود غير المموَّهة (اطّلِع على مزيد من التفاصيل عن الحدود غير المموَّهة لاحقًا).
    2. خيارات الأنشطة المطلوبة لبدء الأنشطة داخل شاشة مجموعة العدادات لمزيد من المعلومات، اطّلِع على ActivityOptions.
  3. تطبيق تنقّل (مثل "خرائط Google" لنظام التشغيل Android Automotive أو أي تطبيق خرائط يمتلك الأذونات المطلوبة):
    1. الحصول على CarAppFocusManager باستخدام فئة Car من car-lib
    2. قبل بدء عرض الاتجاهات التفصيلية، يتمّ استدعاء CarAppFocusManager.requestFocus() لضبط CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION كمَعلمة appType.
  4. يُبلغ "CarAppFocusManager" "CarService" بهذا الطلب. في حال منحه الإذن، يفحص CarService حِزمة تطبيق التنقّل ويحدِّد موقع نشاط تم وضع علامة عليه بالفئة android.car.cluster.NAVIGATION.
  5. في حال العثور على التطبيق، يستخدم تطبيق التنقّل 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

لإنشاء الخدمة:

  1. اكتب فئة تمتد من ClusterRenderingService ثم أضِف إدخالًا متوافقًا إلى ملف AndroidManifest.xml. تتحكّم هذه الفئة في شاشة مجموعة العدادات ويمكنها (اختياريًا) عرض بيانات واجهة برمجة التطبيقات الخاصة بحالة التنقل.
  2. أثناء onCreate()، استخدِم هذه الخدمة لبدء الاتصال بأحد مكونات الأجهزة المسؤولة عن العرض. تشمل الخيارات ما يلي:
    • حدِّد الشاشة الثانوية التي سيتم استخدامها في مجموعة العدادات.
    • أنشئ شاشة افتراضية لكي يعرض تطبيق "مجموعة العدادات" وينقل الصورة المعروضة إلى وحدة خارجية (باستخدام تنسيق بث فيديو، مثل H.264).
  3. عندما تكون الشاشة المُشار إليها أعلاه جاهزة، يجب أن تستدعي هذه الخدمة InstrumentClusterRenderingService#setClusterActivityLaunchOptions() لتحديد ActivityOptions الدقيق الذي يجب استخدامه لعرض نشاط على مجموعة العدادات. استخدِم المَعلمات التالية:
    • category. ClusterRenderingService.
    • ActivityOptions. مثيل ActivityOptions يمكن استخدامه لبدء نشاط في مجموعة العدادات على سبيل المثال، من المثال على تنفيذ مجموعة العدادات على AOSP:
      getService().setClusterActivityLaunchOptions(
        CATEGORY_NAVIGATION,
        ActivityOptions.makeBasic()
            .setLaunchDisplayId(displayId));
  4. عندما تكون مجموعة العدادات جاهزة لعرض الأنشطة، يجب أن تستدعي هذه الخدمة InstrumentClusterRenderingService#setClusterActivityState(). استخدِم المَعلمات التالية:
    • category ClusterRenderingService.
    • state حِزمة تم إنشاؤها باستخدام ClusterRenderingService احرص على تقديم هذه البيانات:
      • visible يحدِّد "مجموعة العدادات" على أنّها مرئية وجاهزة ل عرض المحتوى.
      • unobscuredBounds مستطيل يحدّد المنطقة ضمن شاشة مجموعة العدادات التي يمكن فيها عرض المحتوى بأمان على سبيل المثال، المناطق التي تغطّيها لوحات المقاييس
  5. يمكنك إلغاء طريقة 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.

لتشغيل نموذج التطبيق هذا:

  1. إنشاء نظام Android Auto وفلاشه على وحدة تحكّم رئيسية متوافقة استخدِم التعليمات الخاصة بإنشاء نظام التشغيل Android وتثبيته على جهازك. للحصول على التعليمات، يُرجى الاطّلاع على استخدام لوحات المراجع.
  2. وصِّل شاشة عرض ثانوية خارجية بالشاشة (إذا كان ذلك متاحًا) أو فعِّل شاشة العرض الافتراضية الثانوية:
    1. اختَر وضع المطوّر في تطبيق "الإعدادات".
    2. انتقِل إلى الإعدادات > النظام > الإعدادات المتقدّمة > خيارات المطوّرين > محاكاة الشاشات الثانوية.
  3. إعادة تشغيل HU
  4. لتشغيل تطبيق KitchenSink:
    1. افتح الدرج.
    2. انتقِل إلى Inst. Cluster (مجموعة النشر).
    3. انقر على بدء عملية إضافة البيانات الوصفية.

يطلب KitchenSink التركيز على NAVIGATION، ما يوجّه DirectRenderingCluster الخدمة إلى عرض واجهة مستخدم مصمّمة على لوحة العدادات.