كتلة الصك

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

المصطلح

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

شرط وصف
CarInstrumentClusterManager CarManager يمكّن التطبيقات الخارجية من بدء نشاط على Instrument Cluster وتلقي عمليات الاسترجاعات عندما تكون Instrument Cluster جاهزة لعرض الأنشطة.
كارماناجر الفئة الأساسية لجميع المديرين التي تستخدمها التطبيقات الخارجية للتفاعل مع الخدمات الخاصة بالسيارات التي تنفذها CarService .
CarService خدمة Android Platform التي توفر الاتصال بين التطبيقات الخارجية (بما في ذلك خرائط Google) والميزات الخاصة بالسيارة ، مثل الوصول إلى مجموعة الأجهزة.
وجهة الوجهة النهائية التي ستنتقل إليها المركبة.
إيتا الوقت المقدر للوصول إلى الوجهة.
وحدة الرأس (HU) وحدة حسابية أساسية مدمجة في السيارة. يدير HU جميع أكواد Android ويتصل بالشاشة المركزية في السيارة.
مجموعة الصك شاشة ثانوية موجودة خلف عجلة القيادة وبين أدوات السيارة. يمكن أن تكون هذه وحدة حسابية مستقلة متصلة بـ HU من خلال الشبكة الداخلية للسيارة (ناقل CAN) أو شاشة ثانوية متصلة بـ HU.
InstrumentClusterRenderingService الفئة الأساسية للخدمة المستخدمة للتفاعل مع شاشة مجموعة العدادات. يجب أن توفر الشركات المصنعة للمعدات الأصلية (OEM) امتدادًا لهذه الفئة يتفاعل مع الأجهزة الخاصة بـ OEM.
تطبيق 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. إذا كانت أجهزة الجهاز والنواة يدعمان إدارة شاشات متعددة.
    • وحدة مستقلة. أي وحدة حسابية متصلة بـ HU عبر اتصال شبكة ، قادرة على استقبال وعرض دفق فيديو على شاشتها الخاصة.
    • عرض مقلد. أثناء التطوير ، يمكنك استخدام إحدى هذه البيئات المحاكية:
      • شاشات ثانوية مقلدة. لتمكين عرض ثانوي محاكى على أي توزيع AOSP Android ، انتقل إلى إعدادات خيارات المطور في تطبيق نظام الإعدادات ثم حدد محاكاة شاشات العرض الثانوية. هذا التكوين يكافئ إرفاق شاشة ثانوية مادية ، مع وجود قيود على أن هذه الشاشة متراكبة على الشاشة الأساسية.
      • مجموعة العدادات المقلدة. يوفر محاكي Android المضمن في Android Automotive خيارًا لعرض مجموعة أدوات مع توصيل خدمة ClusterRenderingService بالشاشة الثانوية.
      • محاكي _qemu-الأنابيب. خدمة ClusterRenderingService متصلة بالشاشة الثانوية. تطبيق مجموعة أجهزة مرجعية للاتصال بهذه الشاشة الخارجية التي تمت مضاهاتها.

بنية التكامل

مكونات التكامل

يتكون أي تكامل لـ Instrument Cluster API من هذه المكونات الثلاثة:

  • CarService
  • تطبيقات الملاحة
  • خدمة كتلة صك OEM

مكونات التكامل

خدمة السيارات

تتوسط 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 المقيدة. (في هذه الحالة ، يشير مصطلح "ملزم" إلى خدمات Android .)

خدمة كتلة الصك

يجب على الشركات المصنعة للمعدات الأصلية إنشاء حزمة Android (APK) تحتوي على فئة فرعية من خدمة ClusterRenderingService المتصلة بشاشة العرض الثانوية. خدمة ClusterRenderingService متصلة بالشاشة الثانوية. لعينة.

يخدم هذا الفصل غرضين:

  • يوفر واجهة Android وجهاز عرض Instrument Cluster (الغرض من هذه الصفحة).
  • يتلقى ويعرض تحديثات حالة التنقل ، مثل إرشادات التنقل خطوة بخطوة.

للغرض الأول ، يجب أن تقوم تطبيقات OEM الخاصة بـ InstrumentClusterRendererService بتهيئة العرض الثانوي المستخدم لتقديم المعلومات على الشاشات الموجودة في مقصورة السيارة وإبلاغ هذه المعلومات إلى CarService من خلال الاتصال بأساليب InstrumentClusterRendererService.setClusterActivityOptions() و InstrumentClusterRendererService.setClusterActivityState() .

بالنسبة للوظيفة الثانية ، يجب أن توفر خدمة مجموعة الأدوات تنفيذًا متصلًا بخدمة ClusterRenderingService بالشاشة الثانوية. الواجهة التي تتلقى أحداث تحديث حالة التنقل ، والتي تم ترميزها على أنها eventType وبيانات الحدث المشفرة في حزمة.

تسلسل التكامل

يوضح الرسم البياني التالي تنفيذ حالة التنقل التي تعرض التحديثات:

تسلسل التكامل

في هذا الرسم التوضيحي ، تشير الألوان إلى ما يلي:

  • أصفر. يتم توفير CarService و CarNavigationStatusManager بواسطة نظام Android الأساسي. لمعرفة المزيد ، راجع السيارة و CAR_NAVIGATION_SERVICE .
  • ازرق سماوي. تم تنفيذ InstrumentClusterRendererService بواسطة الشركة المصنعة للمعدات الأصلية.
  • أرجواني. تطبيق التنقل الذي تم تنفيذه بواسطة Google والمطورين الخارجيين.
  • أخضر. CarAppFocusManager . لمعرفة المزيد ، راجع استخدام واجهة برمجة تطبيقات CarAppFocusManager أدناه و CarAppFocusManager .

يتبع تدفق معلومات حالة الملاحة هذا التسلسل:

  1. تقوم CarService بتهيئة InstrumentClusterRenderingService .
  2. أثناء التهيئة ، تقوم InstrumentClusterRenderingService بتحديث CarService بـ:
    1. خصائص عرض مجموعة الأدوات ، مثل الحدود غير الواضحة (انظر المزيد من التفاصيل حول الحدود غير المحجوبة لاحقًا).
    2. خيارات النشاط المطلوبة لبدء الأنشطة داخل شاشة مجموعة العدادات (انظر المزيد من التفاصيل في ActivityOptions .
  3. تطبيق الملاحة (مثل خرائط Google لـ Android Automotive أو أي تطبيق خرائط بالأذونات المطلوبة):
    1. يحصل على CarAppFocusManager باستخدام فئة السيارة من car-lib.
    2. قبل بدء الاتجاهات خطوة بخطوة ، يتم الاتصال بـ CarAppFocusManager.requestFocus() لتمرير CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION كمعامل appType .
  4. يقوم CarAppFocusManager بإرسال هذا الطلب إلى CarService . في حالة منحها ، تقوم CarService بفحص حزمة تطبيق التنقل وتحديد موقع نشاط مميز بالفئة android.car.cluster.NAVIGATION .
  5. إذا تم العثور عليه ، فإن تطبيق التنقل يستخدم ActivityOptions التي تم الإبلاغ عنها بواسطة InstrumentClusterRenderingService لبدء النشاط ويتضمن خصائص عرض Instrument Cluster كإضافات في النية.

دمج API

يجب أن يقوم تنفيذ InstrumentClusterRenderingService بما يلي:

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

نموذج تنفيذ InstrumentClusterRenderingService

يوضح المثال التالي تنفيذ InstrumentClusterRenderingService ، والذي يقوم بإنشاء VirtualDisplay لتقديم محتوى مجموعة الأدوات على شاشة فعلية بعيدة.

بدلاً من ذلك ، يمكن أن يمرر هذا الرمز displayId لشاشة ثانوية مادية متصلة بـ HU ، إذا كان من المعروف أن أحدها متاح.

/**
* Sample {@link InstrumentClusterRenderingService} implementation
*/
public class SampleClusterServiceImpl extends InstrumentClusterRenderingService {
   // Used to retrieve or create displays
   private final DisplayManager mDisplayManager;
   // Unique identifier for the display that will 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

توفر واجهة برمجة تطبيقات 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 application 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.

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

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

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