API של אשכול כלים

השתמשו ב-Instrument Cluster API (API ל-Android) כדי להציג אפליקציות ניווט. כולל מפות Google, במסך משני ברכב, למשל מאחורי את ההגה על לוח המכשירים. בדף הזה נסביר איך ליצור שירות כדי לשלוט בתצוגה המשנית ולשלב את השירות עם CarService כדי שאפליקציות ניווט יוכלו להציג ממשק משתמש גרפי.

טרמינולוגיה

המונחים הבאים מופיעים בדף הזה.

מנהל אשכול מכוניות
מופע של CarManager שמאפשר לאפליקציות חיצוניות להפעיל פעילות ב- אשכול הכלים ולקבל קריאות חוזרות (callback) כשאשכול הכלים מוכן להצגה פעילויות.
מנהל/ת רכב
סיווג הבסיס של כל המנהלים שמשמשים אפליקציות חיצוניות לביצוע פעולות במכשירים ספציפיים לרכב שירותים שהוטמעו על ידי CarService.
CarService
שירות פלטפורמת Android שמספק תקשורת בין אפליקציות חיצוניות (כולל מפות Google) ותכונות ספציפיות לרכב, כמו גישה לאשכול כלים.
יעד
היעד הסופי שאליו ינווט הרכב.
זמן ההגעה המשוער
זמן ההגעה המשוער ליעד.
יחידה ראשית (HU)
יחידת חישוב ראשית שמוטמעת במכונית. ה-HU מריץ את כל קודי Android, שמחובר למסך המרכזי ברכב.
אשכול כלים
מסך משני שנמצא מאחורי ההגה ובין הרכב כלי נגינה. זו יכולה להיות יחידת חישוב עצמאית שמחוברת HU דרך הרשת הפנימית של הרכב (CAN bus) או דרך מסך משני שמחובר ל-HU.
שירות ClusterRenderingService
סיווג הבסיס של השירות שמשמש לממשק עם אשכול הכלים מסך. יצרני ציוד מקורי חייבים לספק הארכה של הקטגוריה הזו שמקיימת אינטראקציה עם לחומרה הספציפית של ה-OEM.
אפליקציית KitchenSink
אפליקציית הבדיקה כלולה ב-Android Automotive.
מסלול
נתיב ספציפי שבו רכב מנווט כדי להגיע ליעד.
שירות Singleton
שירות Android עם המאפיין android:singleUser. בשעה בכל זמן נתון, מופע אחד לפחות של השירות פועל במערכת Android.

דרישות מוקדמות

לפני שממשיכים, חשוב לוודא שהתנאים הבאים מתקיימים:

  • סביבת הפיתוח של Android. כדי להגדיר את Android בסביבת הפיתוח, דרישות Build.
  • מורידים את קוד המקור של Android. כדאי להוריד את הגרסה האחרונה של את קוד המקור של Android מסניף pi-car-אוטומטית (ואילך) https://android.googlesource.com.
  • יחידה ראשית (HU). מכשיר Android שיכול לפעול Android 9 (ואילך). למכשיר הזה צריכה להיות מסך משלו והוא יכול: את המסך החכם עם גרסאות build חדשות של Android.
  • אשכול כלים הוא אחד מהבאים:
    • מסך משני פיזי שמחובר ל-HU. אם החומרה והליבה של המכשיר תומכות בניהול מסכים מרובים.
    • יחידה עצמאית. כל יחידה חישובית שמחוברת HU באמצעות חיבור לרשת, המסוגל לקבל ולהציג וידאו בסטרימינג בתצוגה נפרדת.
    • תצוגה שעברה אמולציה. במהלך הפיתוח, אפשר להשתמש באחד האמולציה של הסביבות הבאות:
      • הדמיה של מסכים משניים. כדי להפעיל סימולציה במסך משני בכל הפצת AOSP ל-Android, עוברים אל אפשרויות למפתחים ההגדרות באפליקציית המערכת הגדרות ולאחר מכן בוחרים Simulate משני מציג את התצורה הזו מקבילה לחיבור פיזי משני להצגת מודעות, עם המגבלה שלפיה תצוגה זו מופיעה מעל מסך.
      • אשכול כלים אמולציה. האמולטור Android כלול עם AAOS אפשר להציג אשכול כלים עם ClusterRenderingService.

ארכיטקטורת שילוב

רכיבי שילוב

כל שילוב של Instrument Cluster API מורכב משלושת הרכיבים הבאים:

  • CarService
  • אפליקציות ניווט
  • שירות אשכול מכשירים של OEM (יצרן ציוד מקורי)

רכיבי שילוב

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 ומכשיר הרינדור של אשכול הכלים (מטרת הדף הזה).
  • המערכת מקבלת ומעבדת עדכונים על מצב הניווט, כמו מסלול מפורט הנחיות ניווט.

למטרה הראשונה, הטמעות של ה-OEM (יצרן הציוד המקורי) של InstrumentClusterRendererService חייב לאתחל את המסך המשני שמשמש לעיבוד מידע על המסכים בתא הנהג ברכב להעביר את המידע הזה אל CarService באמצעות פנייה אל InstrumentClusterRendererService.setClusterActivityOptions() והקבוצה InstrumentClusterRendererService.setClusterActivityState() methods.

עבור הפונקציה השנייה, שירות אשכול הכלים חייב לספק יישום של ClusterRenderingService בממשק שמקבל אירועים לעדכון סטטוס הניווט, שמקודדים eventType ונתוני אירועים מקודדים בחבילה.

רצף אינטגרציה

התרשים הבא ממחיש את ההטמעה של מצב ניווט לעיבוד עדכונים:

רצף אינטגרציה

באיור הזה, הצבעים מציינים את הדברים הבאים:

  • צהוב. CarService ו-CarNavigationStatusManager שסופקו על ידי פלטפורמת Android. מידע נוסף זמין במאמר הבא: רכב וגם Car_NAVIGATION_SERVICE.
  • ציאן. בוצעה הטמעה של InstrumentClusterRendererService על ידי ה-OEM.
  • סגול. אפליקציית הניווט שהוטמעה על ידי Google וצד שלישי למפתחים.
  • ירוק. CarAppFocusManager. מידע נוסף זמין במאמר הבא: באמצעות CarAppFocusManager API מתחת ל- 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 להפעלת הפעילות, כולל מאפייני התצוגה של אשכול הכלים כתוספות ב-Intent.

משלבים את ה-API

ההטמעה של 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. הכיתה הזו קובע את התצוגה של אשכול הכלים ויכול (אופציונלי) לעבד את מצב הניווט נתוני API.
  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() ומידע על סטטוס הדיווח שיהיה שימושי עבור ניפוי באגים (ראו 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 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 API מספק שיטה בשם getAppTypeOwner(), שמאפשרת שירות האשכולות שנכתב על ידי יצרני ציוד מקורי (OEM) כדי לדעת באיזו אפליקציית ניווט מתמקדים בכל רגע נתון בזמן האימון. יצרני ציוד מקורי יכולים להשתמש בשיטת 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. גרסת ה-build וה-Flash של Android Auto ב-HU נתמך. משתמשים ב הוראות לפיתוח והבהוב של Android שספציפיות למכשיר שלכם. הוראות מופיעות שימוש בלוחות עזר.
  2. מחברים מסך פיזי משני ל-HU (אם נתמך) או מפעילים את הווירטואלי HU משני:
    1. בוחרים באפשרות מצב פיתוח באפליקציית ההגדרות.
    2. עוברים אל הגדרות > מערכת > מתקדם > אפשרויות למפתחים > ליצור הדמיה של מסכים משניים.
  3. הפעלה מחדש של HU
  4. כדי להפעיל את אפליקציית KitchenSink:
    1. פותחים את חלונית ההזזה.
    2. עוברים אל Inst. אשכול.
    3. לוחצים על הפעלת מטא-נתונים.

היא מבקשת התמקדות ב-NAVIGATION של KitchenSink, לפי הוראה DirectRenderingCluster שירות להצגת ממשק משתמש מדומה באשכול הכלים.