שימוש בספריית האפליקציות של Android למכוניות

ספריית האפליקציות של Android למכוניות מאפשר להביא את הניווט, את נקודת העניין (POI) ואת האינטרנט של הדברים (IOT) את האפליקציות ברכב. לשם כך, המערכת מספקת קבוצה של תבניות שנועדו לצמצם את הסחות הדעת של הנהג וטיפול בפרטים כמו מגוון הגורמים של המסך ברכב ואת שיטות הקלט.

מדריך זה מספק סקירה כללית על התכונות והמושגים המרכזיים של הספרייה ידריך אותך בתהליך ההגדרה של אפליקציה בסיסית.

לפני שמתחילים

  1. למידע נוסף על עיצוב לנהיגה דפים שמכילים את ספריית האפליקציות של הרכב
  2. כדאי לקרוא את המונחים והמושגים המרכזיים .
  3. מומלץ לקרוא על מערכת Android Auto UI ו-Android Automotive OS עיצוב.
  4. בודקים את נתוני הגרסה.
  5. כדאי לעיין בטעימות.

מונחי מפתח ומושגים מרכזיים

מודלים ותבניות
ממשק המשתמש מיוצג על ידי גרף של אובייקטים של מודל שיכולים להיות מסודרות יחד בדרכים שונות, בהתאם למותר בתבנית שהם שייכים ל. תבניות הן קבוצת משנה של המודלים שיכולים לשמש כבסיס גרפים. מודלים כוללים את המידע שיוצג למשתמש טקסט ותמונות וגם מאפיינים להגדרה של היבטים מראה חזותי של מידע כזה — לדוגמה, צבעי טקסט או תמונות בגדלים שונים. המארח ממיר את המודלים לתצוגות שנועדו להתאים התקנים שמסיחים את הדעת של הנהג, ומטפלים בפרטים כמו של גורמי המסך במכונית ומודלים של קלט.
מארח
המארח הוא רכיב הקצה העורפי שמטמיע את הפונקציונליות המוצעת על ידי ממשקי ה-API של הספרייה כדי שהאפליקציה תוכל לפעול במכונית. תחומי האחריות של המארח הם, החל מאיתור האפליקציה ועד לניהול מחזור החיים שלו להמרת המודלים לצפיות ושליחת התראות לאפליקציה של אינטראקציות משתמשים. במכשירים ניידים, המארח הזה מוטמע על ידי Android אוטומטי. ב-Android Automotive OS, המארח הזה מותקן כאפליקציית מערכת.
הגבלות על תבניות
תבניות שונות אוכפות הגבלות על תוכן המודלים שלהן. עבור לדוגמה, לתבניות של רשימות יש מגבלות על מספר הפריטים שניתן יוצגו למשתמש. לתבניות יש גם הגבלות באופן שבו הן יכולות להיות מחוברות כדי ליצור רצף של משימה. לדוגמה, האפליקציה יכולה רק עד חמש תבניות למקבץ המסך. צפייה הגבלות על תבניות לקבלת פרטים נוספים.
Screen
Screen היא כיתה שמסופקת על ידי שהאפליקציות מטמיעות כדי לנהל את ממשק המשתמש שמוצג משתמש. לScreen יש מחזור חיים ומספק את המנגנון לאפליקציה לשלוח את התבנית כדי שתוצג במסך גלוי. אפשר גם לדחוף Screen מכונות וחלון קופץ אל מקבץ Screen וממנו, ומוודא שהם פועלים בהתאם הגבלות על תהליך היצירה.
CarAppService
CarAppService הוא שיעור מופשט Service שהאפליקציה שלכם צריך להטמיע ולייצא כדי שהמארח יוכל לגלות ולנהל אותו. CarAppService של האפליקציה הוא והם אחראים לוודא שהחיבור למארח יכול להיות מהימן באמצעות createHostValidator ולאחר מכן לספק Session לכל חיבור באמצעות onCreateSession.
Session

Session היא מחלקה מופשטת צריך להטמיע באפליקציה ולהחזיר אותה באמצעות CarAppService.onCreateSession היא משמשת כנקודת הכניסה להצגת מידע במסך המכונית. הוא כולל מחזור חיים שמיידע את המצב הנוכחי של האפליקציה במסך הרכב, למשל כאשר האפליקציה גלוי או מוסתר.

כשSession מופעל, כמו כשהאפליקציה מופעלת בפעם הראשונה, המארח מבקש לבצע Screen להצגה באמצעות onCreateScreen .

התקנה של ספריית האפליקציות של הרכב

לעיון בספרייה של Jetpack דף גרסה של להוראות להוספת הספרייה לאפליקציה.

הגדרת קובצי המניפסט של האפליקציה

לפני שיוצרים אפליקציה לרכב, צריך להגדיר את האפליקציה קובצי מניפסט כפי שמפורט בהמשך.

להצהיר על שירות CarAppService

המארח מתחבר לאפליקציה דרך CarAppService. שלך להצהיר על השירות הזה במניפסט כדי לאפשר למארח לגלות ולהתחבר לאפליקציה.

צריך גם להצהיר על הקטגוריה של האפליקציה בקטע אלמנט <category> של האפליקציה מסנן Intent. לצפייה ברשימה של קטגוריות נתמכות של אפליקציות לערכים המותרים של מהרכיב הזה.

קטע הקוד הבא מראה איך להצהיר (declare) על שירות של אפליקציה לרכב בנקודת זמן של תחום עניין במניפסט שלך:

<application>
    ...
   <service
       ...
        android:name=".MyCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService"/>
        <category android:name="androidx.car.app.category.POI"/>
      </intent-filter>
    </service>

    ...
<application>

קטגוריות נתמכות של אפליקציות

צריך להצהיר על קטגוריית האפליקציה על ידי הוספה של אחת או יותר מהקטגוריה הבאה ערכים במסנן Intent כשמצהירים על CarAppService כפי שמתואר בקטע הקודם:

אפשר לעיין במאמר איכות האפליקציות ל-Android למכוניות עבור תיאורים מפורטים של כל קטגוריה וקריטריונים לאפליקציות שמשויכות אליהן.

ציון השם והסמל של האפליקציה

עליך לציין את השם והסמל של האפליקציה שהמארח יכול להשתמש בהם כדי לייצג את אפליקציה בממשק המשתמש של המערכת.

אפשר לציין את השם והסמל של האפליקציה שמשמשים לייצוג האפליקציה באמצעות label icon מאפיינים של CarAppService:

...
<service
   android:name=".MyCarAppService"
   android:exported="true"
   android:label="@string/my_app_name"
   android:icon="@drawable/my_app_icon">
   ...
</service>
...

אם התווית או הסמל לא מוצהרים רכיב <service>, המארח חוזר לערכים שצוינו רכיב <application>.

הגדרת עיצוב בהתאמה אישית

כדי להגדיר עיצוב מותאם אישית לאפליקציה לרכב, צריך להוסיף רכיב <meta-data> קובץ מניפסט, באופן הבא:

<meta-data
    android:name="androidx.car.app.theme"
    android:resource="@style/MyCarAppTheme />

לאחר מכן צריך להצהיר על משאב הסגנון מגדירים את המאפיינים הבאים לעיצוב המותאם אישית של האפליקציה לרכב:

<resources>
  <style name="MyCarAppTheme">
    <item name="carColorPrimary">@layout/my_primary_car_color</item>
    <item name="carColorPrimaryDark">@layout/my_primary_dark_car_color</item>
    <item name="carColorSecondary">@layout/my_secondary_car_color</item>
    <item name="carColorSecondaryDark">@layout/my_secondary_dark_car_color</item>
    <item name="carPermissionActivityLayout">@layout/my_custom_background</item>
  </style>
</resources>

רמת ה-API של האפליקציה לרכב

ספריית האפליקציות של הרכב מגדירה רמות API משלה, כדי שתוכלו לדעת תכונות ספריה נתמכות על ידי מארח התבניות ברכב. כדי לאחזר את רמת ה-API הגבוהה ביותר של אפליקציות לרכב שנתמכת על ידי מארח, צריך להשתמש בפונקציה getCarAppApiLevel() .

להצהיר על רמת ה-API המינימלית של אפליקציית Car באפליקציה שלך קובץ AndroidManifest.xml:

<manifest ...>
    <application ...>
        <meta-data
            android:name="androidx.car.app.minCarApiLevel"
            android:value="1"/>
    </application>
</manifest>

אפשר לעיין במסמכי התיעוד עבור RequiresCarApi הערה לגבי הנחיות לשמירה על תאימות לאחור והצהרה רמת ה-API המינימלית שנדרשת כדי להשתמש בתכונה. פירוט של איזה API כדי להשתמש בתכונה מסוימת בספריית האפליקציות של הרכב נדרשת רמה. צריך לבדוק את מאמרי עזרה עבור CarAppApiLevels

יצירת CarAppService וסשן

האפליקציה שלך צריכה להרחיב את מחלקה CarAppService והטמעה שלו onCreateSession , שתחזיר Session במופע שתואם לחיבור הנוכחי למארח:

Kotlin

class HelloWorldService : CarAppService() {
    ...
    override fun onCreateSession(): Session {
        return HelloWorldSession()
    }
    ...
}

Java

public final class HelloWorldService extends CarAppService {
    ...
    @Override
    @NonNull
    public Session onCreateSession() {
        return new HelloWorldSession();
    }
    ...
}

המכונה Session אחראית להחזיר את המכונה Screen כדי להשתמש ב בפעם הראשונה שהאפליקציה מופעלת:

Kotlin

class HelloWorldSession : Session() {
    ...
    override fun onCreateScreen(intent: Intent): Screen {
        return HelloWorldScreen(carContext)
    }
    ...
}

Java

public final class HelloWorldSession extends Session {
    ...
    @Override
    @NonNull
    public Screen onCreateScreen(@NonNull Intent intent) {
        return new HelloWorldScreen(getCarContext());
    }
    ...
}

כדי לטפל בתרחישים שבהם האפליקציה לרכב צריכה להתחיל במסך שלא במסך הבית או במסך הנחיתה של האפליקציה, למשל טיפול בקישורי עומק, אתם יכולים לישיבה מראש ערימה של מסכים באמצעות ScreenManager.push לפני חזרה מ onCreateScreen תהליך ההגדרה מראש מאפשר למשתמשים לנווט חזרה למסכים קודמים מה המסך שהאפליקציה מוצגת.

יצירת מסך פתיחה

כדי ליצור את המסכים שהאפליקציה מציגה, מגדירים כיתות ש כיתה אחת (Screen) והטמעה שלה onGetTemplate , שתחזיר את הפונקציה מכונה של Template שמייצגת את המצב של ממשק המשתמש להצגה במסך הרכב.

בקטע הקוד הבא מוסבר איך להצהיר (declare) על Screen שמשתמש ב תבנית של PaneTemplate ל תציג הודעת "שלום עולם!" פשוטה string:

Kotlin

class HelloWorldScreen(carContext: CarContext) : Screen(carContext) {
    override fun onGetTemplate(): Template {
        val row = Row.Builder().setTitle("Hello world!").build()
        val pane = Pane.Builder().addRow(row).build()
        return PaneTemplate.Builder(pane)
            .setHeaderAction(Action.APP_ICON)
            .build()
    }
}

Java

public class HelloWorldScreen extends Screen {
    @NonNull
    @Override
    public Template onGetTemplate() {
        Row row = new Row.Builder().setTitle("Hello world!").build();
        Pane pane = new Pane.Builder().addRow(row).build();
        return new PaneTemplate.Builder(pane)
            .setHeaderAction(Action.APP_ICON)
            .build();
    }
}

המחלקה CarContext

הכיתה CarContext היא תת-מחלקה ContextWrapper נגיש אל Session וגם Screen מופעים. הוא מספק גישה לשירותי רכב, כמו ScreenManager לניהול מקבץ מסך; ה AppManager להגדרות כלליות שקשורות לאפליקציות פונקציונליות, כמו גישה לאובייקט Surface שרטוט מפות; וגם NavigationManager שמשמשות אפליקציות ניווט מפורטות כדי לתקשר ניווט מטא-נתונים ועוד קשור לניווט אירועים עם המארח.

למידע נוסף, ניתן לעיין בקטע גישה לניווט של תבניות רשימה מלאה של פונקציות הספרייה שזמינות לאפליקציות ניווט.

ב-CarContext יש גם אפשרויות אחרות פונקציונליות, כמו מתן אפשרות לטעון משאבים ניתנים להזזה באמצעות ההגדרות האישיות ממסך המכונית, הפעלת אפליקציה במכונית באמצעות כוונות, ולציין אם להציג את המפה של האפליקציה בעיצוב כהה.

הטמעת ניווט במסך

בדרך כלל, אפליקציות מציגות מספר מסכים שונים, וכל אחד מהם יכול להשתמש תבניות שונות שהמשתמש יכול לנווט דרכן בזמן האינטראקציה איתן הממשק שמוצג במסך.

הכיתה ScreenManager מספקת ערימת מסך שאפשר להשתמש בה כדי לדחוף מסכים שיכולים להקפיץ אוטומטית כשהמשתמש לוחץ על לחצן 'הקודם' במסך הרכב או משתמש בחומרה האחורית. הלחצן זמין במכוניות מסוימות.

קטע הקוד הבא מראה איך להוסיף פעולת החזרה לתבנית של הודעה בתור וגם פעולה שדוחפת מסך חדש כאשר המשתמש בוחר בה:

Kotlin

val template = MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener { screenManager.push(NextScreen(carContext)) }
            .build())
    .build()

Java

MessageTemplate template = new MessageTemplate.Builder("Hello world!")
    .setHeaderAction(Action.BACK)
    .addAction(
        new Action.Builder()
            .setTitle("Next screen")
            .setOnClickListener(
                () -> getScreenManager().push(new NextScreen(getCarContext())))
            .build())
    .build();

האובייקט Action.BACK הוא Action רגיל שבאופן אוטומטי להפעלה של ScreenManager.pop. אפשר לשנות את ההתנהגות הזו באמצעות OnBackPressedDispatcher שבמכונה CarContext

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

רענון התוכן של תבנית

האפליקציה שלך יכולה לבקש את התוכן של כדי לבטל את התוקף של Screen, שולחים אל Screen.invalidate. לאחר מכן המארח מתקשר חזרה לאפליקציה Screen.onGetTemplate כדי לאחזר את התבנית עם התכנים החדשים.

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

אנחנו ממליצים לבנות את המסכים כך שיהיו בין Screen לבין הסוג שהיא מחזירה באמצעות ההטמעה של onGetTemplate.

שרטוט מפות

אפליקציות ניווט ונקודות עניין (POI) שמשתמשות בתבניות הבאות יכולות שרטט מפות באמצעות גישה אל Surface:

תבנית הרשאת גישה לתבנית הנחיות לגבי קטגוריות
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES ניווט
MapWithContentTemplate androidx.car.app.NAVIGATION_TEMPLATES או
androidx.car.app.MAP_TEMPLATES
ניווט, POI
MapTemplate (הוצאה משימוש) androidx.car.app.NAVIGATION_TEMPLATES ניווט
PlaceListNavigationTemplate (הוצאה משימוש) androidx.car.app.NAVIGATION_TEMPLATES ניווט
RoutePreviewNavigationTemplate (הוצאה משימוש) androidx.car.app.NAVIGATION_TEMPLATES ניווט

הצהרה על ההרשאה לפלטפורמה

בנוסף להרשאה הנדרשת לתבנית שבה משתמשים באפליקציה, האפליקציה שלך חייבת להצהיר על ההרשאה androidx.car.app.ACCESS_SURFACE AndroidManifest.xml כדי לקבל גישה למשטח:

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
  ...
</manifest>

גישה לפלטפורמה

כדי לגשת אל Surface שהמארח מספק, צריך להטמיע SurfaceCallback ומספקים שמיישמים בAppManager מרכז שירות לרכב. הסכום הנוכחי של Surface מועבר אל SurfaceCallback בפרמטר SurfaceContainer של onSurfaceAvailable() ו-onSurfaceDestroyed() התקשרות חזרה.

Kotlin

carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)

Java

carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);

הבנת השטח הגלוי של פני השטח

המארח יכול לשרטט רכיבים של ממשק המשתמש עבור התבניות מעל את המפה. המארח מעביר את האזור של פני השטח שמובטח שיהיה גלויות למשתמש באופן מלא, באמצעות קריאה SurfaceCallback.onVisibleAreaChanged . כמו כן, כדי לצמצם את מספר השינויים, המארח קורא SurfaceCallback.onStableAreaChanged עם המלבן הקטן ביותר, שמוצג תמיד על בסיס התבנית הנוכחית.

לדוגמה, כשאפליקציית ניווט משתמשת ב- NavigationTemplate עם שורת פעולה מעל שורת הפעולות, יכול להיות עצמו, כשהמשתמש לא יוצר אינטראקציה עם המסך במשך זמן מה כדי מקום למפה. במקרה הזה, תהיה קריאה חוזרת אל onStableAreaChanged onVisibleAreaChanged עם אותו מלבן. כששורת הפעולות מוסתרת, רק onVisibleAreaChanged נקרא עם האזור הגדול יותר. אם המשתמש מקיים אינטראקציה עם המסך, ואז שוב תתקשר רק אל onVisibleAreaChanged במלבן הראשון.

תמיכה בעיצוב כהה

אפליקציות חייבות לשכתב את המפה שלהן במכונה Surface עם צבע כהה מתאים צבעים כאשר המארח קובע שהתנאים מצדיקים זאת, כפי שמתואר האיכות של אפליקציות ל-Android למכוניות.

כדי להחליט אם לשרטט מפה כהה, אפשר להשתמש CarContext.isDarkMode . בכל פעם שהסטטוס של העיצוב הכהה ישתנה, תקבלו הודעה למספר Session.onCarConfigurationChanged

איך לאפשר למשתמשים ליצור אינטראקציה עם המפה שלכם

כשמשתמשים בתבניות הבאות, אפשר להוסיף תמיכה שתעזור למשתמשים לבצע אינטראקציה למפות שציירת, למשל לאפשר להם לראות חלקים שונים במפה על ידי שינוי מרחק התצוגה ותזוזה.

תבנית האינטראקטיבית נתמכת מאז רמת ה-API של האפליקציה לרכב
NavigationTemplate 2
PlaceListNavigationTemplate (הוצאה משימוש) 4
RoutePreviewNavigationTemplate (הוצאה משימוש) 4
MapTemplate (הוצאה משימוש) 5 (הצגת התבנית)
MapWithContentTemplate 7 (הצגת התבנית)

הטמעת קריאה חוזרת (callbacks) של אינטראקטיביות

הממשק של SurfaceCallback יש מספר שיטות להתקשרות חזרה שניתן ליישם כדי להוסיף אינטראקטיביות למפות שנוצרו בתבניות שבקטע הקודם:

אינטראקציה אמצעי תשלום אחד (SurfaceCallback) נתמכת החל מרמת ה-API של האפליקציה לרכב
אפשר להקיש onClick 5
אפשר לצבוט כדי לשנות את מרחק התצוגה onScale 2
גרירה בנגיעה אחת onScroll 2
הנפה בנגיעה אחת onFling 2
הקשה כפולה onScale (כשהגורם לקביעת קנה המידה נקבע על ידי מארח התבנית) 2
נדנוד סיבובי במצב הזזה onScroll (כשגורם המרחק נקבע על ידי מארח התבנית) 2

הוספה של שורת פעולות במפה

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

כדי לקבל קריאות חוזרות (callback) של אינטראקטיביות במפה, חובה להוסיף לחצן Action.PAN בשורת הפעולות במפה. כשהמשתמש לוחץ על לחצן התנועה, המארח עובר למצב 'הזזה', כפי שמתואר .

אם האפליקציה לא תכיל את Action.PAN בשורת הפעולות במפה, הוא לא מקבל קלט של משתמשים SurfaceCallback methods, והמארח יוצא מכל מכשיר קודם לכן הזזה.

במסך מגע, לחצן ההזזה לא מוצג.

הסבר על מצב הזזה

במצב הזזה, מארח התבניות מתרגם קלט של משתמשים מקלט ללא מגע כגון בקרים סיבוביים ולוחות מגע, SurfaceCallback אמצעי תשלום. צריך להגיב לפעולת המשתמש כדי להיכנס למצב הזזה או לצאת ממנו עם setPanModeListener ב-NavigationTemplate.Builder. המארח יכול להסתיר את ממשק המשתמש האחר הרכיבים בתבנית בזמן שהמשתמש נמצא במצב הזזה.

אינטראקציה עם המשתמש

האפליקציה שלך יכולה לקיים אינטראקציה עם המשתמש באמצעות דפוסים דומים לאפליקציה לנייד.

טיפול בקלט של משתמשים

האפליקציה יכולה להגיב לקלט של משתמשים על ידי העברת המאזינים המתאימים אל שתומכים בהם. בקטע הקוד הבא מוסבר איך ליצור מודל Action שמגדיר OnClickListener ש קריאה חוזרת לשיטה שהוגדרה על ידי קוד האפליקציה:

Kotlin

val action = Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(::onClickNavigate)
    .build()

Java

Action action = new Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(this::onClickNavigate)
    .build();

השיטה onClickNavigate יכולה להפעיל את אפליקציית ברירת המחדל למכונית באמצעות CarContext.startCarApp method:

Kotlin

private fun onClickNavigate() {
    val intent = Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address))
    carContext.startCarApp(intent)
}

Java

private void onClickNavigate() {
    Intent intent = new Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address));
    getCarContext().startCarApp(intent);
}

לקבלת פרטים נוספים על הפעלת אפליקציות, כולל הפורמט של Intent מסוג ACTION_NAVIGATE. אפשר לעיין במאמר איך להתניע אפליקציה לרכב עם כוונה .

פעולות מסוימות, כמו אלה שמחייבות את המשתמש להמשיך את אינטראקציה במכשירים הניידים שלהם. מותרת רק כשהמכונית בחנייה. אפשר להשתמש ParkedOnlyOnClickListener כדי לבצע את הפעולות האלה. אם הרכב לא חונה, המארח מציג הוראה למשתמש שהפעולה אסורה במקרה הזה. אם הרכב בהמתנה, הקוד פועל כרגיל. בקטע הקוד הבא מוסבר איך להשתמש בParkedOnlyOnClickListener כדי לפתוח מסך הגדרות במכשיר הנייד:

Kotlin

val row = Row.Builder()
    .setTitle("Open Settings")
    .setOnClickListener(ParkedOnlyOnClickListener.create(::openSettingsOnPhone))
    .build()

Java

Row row = new Row.Builder()
    .setTitle("Open Settings")
    .setOnClickListener(ParkedOnlyOnClickListener.create(this::openSettingsOnPhone))
    .build();

הצגת התראות

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

בקטע הבא מוסבר איך לשלוח התראה למסך המכונית מציגה כותרת שונה מהכותרת שמופיעה במכשיר הנייד:

Kotlin

val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setContentTitle(titleOnThePhone)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(titleOnTheCar)
            ...
            .build())
    .build()

Java

Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    .setContentTitle(titleOnThePhone)
    .extend(
        new CarAppExtender.Builder()
            .setContentTitle(titleOnTheCar)
            ...
            .build())
    .build();

התראות יכולות להשפיע על החלקים הבאים בממשק המשתמש:

  • ייתכן שתוצג למשתמש התראה 'שימו לב' (HUN).
  • ניתן להוסיף רשומה במרכז ההתראות, אם יש כזו עם תג גלויה ברכבת.
  • באפליקציות ניווט, ייתכן שההתראה תוצג בווידג'ט הרכבת בתור מתואר ב: התראות מפורטות.

ניתן לבחור איך להגדיר את ההתראות של האפליקציה כך שישפיעו על כל אחד רכיבים אלה של ממשק המשתמש באמצעות שימוש בעדיפות ההתראה, כפי שמתואר ב CarAppExtender התיעוד.

אם המיקום NotificationCompat.Builder.setOnlyAlertOnce מופעלת עם ערך של true, התראה בעדיפות גבוהה מוצגת HUN רק פעם אחת.

אפשר למצוא מידע נוסף על עיצוב ההתראות באפליקציית הרכב בקטע המדריך של Google Design לנהיגה על התראות.

הצגת הודעות קופצות

האפליקציה שלך יכולה להציג הודעה קופצת באמצעות CarToast כפי שמוצג בקטע הקוד הזה:

Kotlin

CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()

Java

CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();

בקשת הרשאות

אם לאפליקציה שלך נדרשת גישה לפעולות או לנתונים מוגבלים – לדוגמה, מיקום - הכללים הרגילים של Android הרשאות חלות. כדי לבקש הרשאה, אפשר להשתמש CarContext.requestPermissions() .

היתרון של שימוש CarContext.requestPermissions(), בניגוד לשימוש ממשקי API רגילים של Android, הם שאתה לא צריך להפעיל Activity משלך כדי יוצרים את תיבת הדו-שיח של ההרשאות. בנוסף, תוכלו להשתמש באותו קוד בשני המכשירים את Android Auto ו-Android Automotive OS, במקום ליצור ותהליכי עבודה תלויי פלטפורמה.

עיצוב תיבת הדו-שיח להרשאות ב-Android Auto

ב-Android Auto, תיבת הדו-שיח להרשאות של המשתמש תופיע בטלפון. כברירת מחדל, לא יופיע רקע מאחורי תיבת הדו-שיח. כדי להגדיר התאמה אישית רקע, צריך להצהיר על עיצוב של אפליקציה לרכב קובץ AndroidManifest.xml והגדרת המאפיין carPermissionActivityLayout לעיצוב של האפליקציה לרכב.

<meta-data
    android:name="androidx.car.app.theme"
    android:resource="@style/MyCarAppTheme />

לאחר מכן, מגדירים את המאפיין carPermissionActivityLayout לעיצוב של האפליקציה לרכב:

<resources>
  <style name="MyCarAppTheme">
    <item name="carPermissionActivityLayout">@layout/my_custom_background</item>
  </style>
</resources>

איך מפעילים אפליקציה לרכב עם כוונה

אפשר לקרוא ל- CarContext.startCarApp כדי לבצע אחת מהפעולות הבאות:

בדוגמה הבאה אפשר לראות איך ליצור התראה עם פעולה פותח את האפליקציה באמצעות מסך שמציג את הפרטים של הזמנת חניה. אתם מרחיבים את מופע ההתראה באמצעות כוונת תוכן שמכילה PendingIntent גלישת טקסט בוטה כוונה לפעולה של האפליקציה:

Kotlin

val notification = notificationBuilder
    ...
    .extend(
        CarAppExtender.Builder()
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_VIEW_PARKING_RESERVATION.hashCode(),
                    Intent(ACTION_VIEW_PARKING_RESERVATION)
                        .setComponent(ComponentName(context, MyNotificationReceiver::class.java)),
                    0))
            .build())

Java

Notification notification = notificationBuilder
    ...
    .extend(
        new CarAppExtender.Builder()
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_VIEW_PARKING_RESERVATION.hashCode(),
                    new Intent(ACTION_VIEW_PARKING_RESERVATION)
                        .setComponent(new ComponentName(context, MyNotificationReceiver.class)),
                    0))
            .build());

האפליקציה שלך צריכה גם להצהיר על BroadcastReceiver כלומר מופעלת לעיבוד הכוונה כשהמשתמש בוחר בפעולה ממשק התראות והפעלה CarContext.startCarApp עם Intent, כולל ה-URI של הנתונים:

Kotlin

class MyNotificationReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        val intentAction = intent.action
        if (ACTION_VIEW_PARKING_RESERVATION == intentAction) {
            CarContext.startCarApp(
                intent,
                Intent(Intent.ACTION_VIEW)
                    .setComponent(ComponentName(context, MyCarAppService::class.java))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)))
        }
    }
}

Java

public class MyNotificationReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        String intentAction = intent.getAction();
        if (ACTION_VIEW_PARKING_RESERVATION.equals(intentAction)) {
            CarContext.startCarApp(
                intent,
                new Intent(Intent.ACTION_VIEW)
                    .setComponent(new ComponentName(context, MyCarAppService.class))
                    .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction)));
        }
    }
}

לבסוף, Session.onNewIntent באפליקציה שלך, לטיפול בכוונה הזו, לוחצים על המסך של הזמנת החניה של המקבץ, אם הוא עדיין לא נמצא למעלה:

Kotlin

override fun onNewIntent(intent: Intent) {
    val screenManager = carContext.getCarService(ScreenManager::class.java)
    val uri = intent.data
    if (uri != null
        && MY_URI_SCHEME == uri.scheme
        && MY_URI_HOST == uri.schemeSpecificPart
        && ACTION_VIEW_PARKING_RESERVATION == uri.fragment
    ) {
        val top = screenManager.top
        if (top !is ParkingReservationScreen) {
            screenManager.push(ParkingReservationScreen(carContext))
        }
    }
}

Java

@Override
public void onNewIntent(@NonNull Intent intent) {
    ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
    Uri uri = intent.getData();
    if (uri != null
        && MY_URI_SCHEME.equals(uri.getScheme())
        && MY_URI_HOST.equals(uri.getSchemeSpecificPart())
        && ACTION_VIEW_PARKING_RESERVATION.equals(uri.getFragment())
    ) {
        Screen top = screenManager.getTop();
        if (!(top instanceof ParkingReservationScreen)) {
            screenManager.push(new ParkingReservationScreen(getCarContext()));
        }
    }
}

מידע נוסף זמין בקטע הצגת התראות מידע על הטיפול בהתראות של האפליקציה לרכב.

הגבלות על תבניות

המארח מגביל את מספר התבניות שאפשר להציג במשימה נתונה לכל היותר מבין חמישה, מתוכם התבנית האחרונה חייבת להיות אחת מהסוגים הבאים:

חשוב לשים לב שהמגבלה הזו חלה על מספר התבניות ולא על מספר התבניות Screen מכונות במקבץ. עבור לדוגמה, אם אפליקציה שולחת שתי תבניות במסך A ואז דוחפת את המסך ב', עכשיו הוא יכול לשלוח שלוש תבניות נוספות. לחלופין, אם כל מסך מובנה לשליחת תבנית אחת, האפליקציה יכולה לדחוף מופעי מסך מקבץ ScreenManager.

יש מקרים מיוחדים להגבלות האלה: רענון תבניות, חזרה אחורה פעולות איפוס.

מתבצע רענון של התבנית

עדכוני תוכן מסוימים לא נספרים כחלק מהמגבלה על התבנית. באופן כללי, אם האפליקציה שולחת תבנית חדשה מאותו סוג ומכילה אותו התוכן הראשי כמו התבנית הקודמת, התבנית החדשה לא נספרים במסגרת המכסה. לדוגמה, עדכון המצב של החלפת המצב בשורה ListTemplate לא נחשב במסגרת המכסה. מידע נוסף זמין במסמכי התיעוד של תבניות ספציפיות סוגים של עדכוני תוכן שיכולים להיחשב כרענון.

פעולות אחורה

כדי להפעיל זרמי משנה בתוך משימה, המארח מזהה מתי אפליקציה קופצת Screen מהמקבץ ScreenManager ועדכונים המכסה שנותרה, על סמך מספר התבניות שהאפליקציה משתמשת בהן אחורה אחורה.

לדוגמה, אם האפליקציה שולחת שתי תבניות במסך א', היא דוחפת במסך ב' ושולחת עוד שתי תבניות, לאפליקציה נותרה מכסה אחת. אם המיקום לאחר מכן האפליקציה חוזרת למסך א', המארח מאפס את המכסה לשלוש, כי האפליקציה הלכה אחורה בשתי תבניות.

הערה: כשחוזרים למסך, האפליקציה חייבת לשלוח תבנית מהסוג האחרון שנשלח במסך הזה. מתבצעת שליחה של סוג התבנית גורם לשגיאה. עם זאת, כל עוד הסוג נשאר בזמן פעולת חזרה, אפליקציה יכולה לשנות באופן חופשי את התוכן של בלי להשפיע על המכסה.

איפוס פעולות

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

אם המארח מקבל כוונה להפעיל את האפליקציה מפעולת התראה, או ממרכז האפליקציות, המכסה מתאפסת גם היא. המנגנון הזה מאפשר לאפליקציה מתחיל תהליך חדש של משימה מהתראות, ומתקיים גם אם אפליקציה שכבר מופיעות בחזית,

מידע נוסף זמין בקטע הצגת התראות לקבלת הסבר על הצגת ההתראות של האפליקציה במסך המכונית. לצפייה הקטע איך מפעילים אפליקציה לרכב עם כוונה לקבלת מידע על האופן שבו כדי להפעיל את האפליקציה מפעולת התראה.

ממשק API לחיבור

אפשר לבדוק אם האפליקציה פועלת ב-Android Auto או ב-Android Automotive OS באמצעות CarConnection API אל לאחזר פרטי חיבור בזמן הריצה.

לדוגמה, ב-Session של האפליקציה לרכב, מאתחלים CarConnection וגם הרשמה לעדכונים של LiveData:

Kotlin

CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)

Java

new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);

במצב הצפייה, אתם יכולים להגיב לשינויים במצב החיבור:

Kotlin

fun onConnectionStateUpdated(connectionState: Int) {
  val message = when(connectionState) {
    CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit"
    CarConnection.CONNECTION_TYPE_NATIVE -> "Connected to Android Automotive OS"
    CarConnection.CONNECTION_TYPE_PROJECTION -> "Connected to Android Auto"
    else -> "Unknown car connection type"
  }
  CarToast.makeText(carContext, message, CarToast.LENGTH_SHORT).show()
}

Java

private void onConnectionStateUpdated(int connectionState) {
  String message;
  switch(connectionState) {
    case CarConnection.CONNECTION_TYPE_NOT_CONNECTED:
      message = "Not connected to a head unit";
      break;
    case CarConnection.CONNECTION_TYPE_NATIVE:
      message = "Connected to Android Automotive OS";
      break;
    case CarConnection.CONNECTION_TYPE_PROJECTION:
      message = "Connected to Android Auto";
      break;
    default:
      message = "Unknown car connection type";
      break;
  }
  CarToast.makeText(getCarContext(), message, CarToast.LENGTH_SHORT).show();
}

ממשק API של מגבלות

ייתכן שבמכוניות שונות יהיו מספר שונה של Item מופעים להצגה כל משתמש בבת אחת. משתמשים ב ConstraintManager כדי לבדוק את מגבלת התוכן בזמן הריצה ולהגדיר את מספר הפריטים המתאים בתבניות שלכם.

כדי להתחיל, צריך לקבל ConstraintManager מ-CarContext:

Kotlin

val manager = carContext.getCarService(ConstraintManager::class.java)

Java

ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);

עכשיו אפשר לשלוח שאילתה לאובייקט ConstraintManager שאוחזר לגבי מגבלת תוכן. לדוגמה, כדי לקבל את מספר הפריטים שניתן להציג רשת, לקרוא getContentLimit עם CONTENT_LIMIT_TYPE_GRID:

Kotlin

val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)

Java

int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);

הוספת תהליך כניסה

אם באפליקציה יש חוויית משתמש מחוברת לחשבון, תוכלו להשתמש בתבניות כמו SignInTemplate ו-LongMessageTemplate עם Car App API ברמה 2 ואילך כדי לטפל בכניסה לאפליקציה ליחידה הראשית של הרכב.

כדי ליצור SignInTemplate, צריך להגדיר SignInMethod. המכונית ספריית האפליקציות תומכת כרגע בשיטות הכניסה הבאות:

לדוגמה: כדי להטמיע תבנית שאוספת את הסיסמה של המשתמש, קודם כל צריך יצירת InputCallback לעיבוד ולאימות של קלט המשתמשים:

Kotlin

val callback = object : InputCallback {
    override fun onInputSubmitted(text: String) {
        // You will receive this callback when the user presses Enter on the keyboard.
    }

    override fun onInputTextChanged(text: String) {
        // You will receive this callback as the user is typing. The update
        // frequency is determined by the host.
    }
}

Java

InputCallback callback = new InputCallback() {
    @Override
    public void onInputSubmitted(@NonNull String text) {
        // You will receive this callback when the user presses Enter on the keyboard.
    }

    @Override
    public void onInputTextChanged(@NonNull String text) {
        // You will receive this callback as the user is typing. The update
        // frequency is determined by the host.
    }
};

נדרש InputCallback לInputSignInMethod Builder.

Kotlin

val passwordInput = InputSignInMethod.Builder(callback)
    .setHint("Password")
    .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
    ...
    .build()

Java

InputSignInMethod passwordInput = new InputSignInMethod.Builder(callback)
    .setHint("Password")
    .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD)
    ...
    .build();

לבסוף, משתמשים ב-InputSignInMethod החדש כדי ליצור SignInTemplate.

Kotlin

SignInTemplate.Builder(passwordInput)
    .setTitle("Sign in with username and password")
    .setInstructions("Enter your password")
    .setHeaderAction(Action.BACK)
    ...
    .build()

Java

new SignInTemplate.Builder(passwordInput)
    .setTitle("Sign in with username and password")
    .setInstructions("Enter your password")
    .setHeaderAction(Action.BACK)
    ...
    .build();

שימוש במנהל החשבון

באפליקציות ל-Android Automotive OS שיש להן אימות חובה להשתמש AccountManager מהסיבות הבאות:

  • חוויית משתמש משופרת וניהול חשבון קל: המשתמשים יכולים לנהל בקלות את כל הפריטים את החשבונות שלהם מתפריט החשבונות בהגדרות המערכת, כולל כניסה ולצאת מהחשבון.
  • 'אורח' חוויות משתמש: מכוניות הן מכשירים משותפים, ולכן יצרני ציוד מקורי יכולים להפעיל אורחים ברכב, שבהם אי אפשר להוסיף חשבונות.

הוספת וריאנטים של מחרוזת טקסט

בגדלים שונים של מסכי הרכב עשויים להופיע כמויות שונות של טקסט. עם Car App API ברמה 2 ומעלה, אפשר לציין כמה וריאנטים של מחרוזת טקסט שמתאימות לגודל המסך. כדי לבדוק איפה אפשר להשתמש בווריאציות של טקסט, אפשר לחפש תבניות מהרכיבים שלוקחים את CarText.

אפשר להוסיף וריאנטים של מחרוזת טקסט ל-CarText עם CarText.Builder.addVariant() method:

Kotlin

val itemTitle = CarText.Builder("This is a very long string")
    .addVariant("Shorter string")
    ...
    .build()

Java

CarText itemTitle = new CarText.Builder("This is a very long string")
    .addVariant("Shorter string")
    ...
    .build();

לאחר מכן אפשר להשתמש בCarText הזה - לדוגמה, כטקסט הראשי של GridItem.

Kotlin

GridItem.Builder()
    .addTitle(itemTitle)
    ...
    .build()

Java

new GridItem.Builder()
    .addTitle(itemTitle)
    ...
    build();

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

הוספת CarIcons מוטבעים בשורות

אפשר להוסיף סמלים מוטבעים עם טקסט כדי להעשיר את מראה האפליקציה באמצעות שימוש CarIconSpan אפשר לעיין במסמכי התיעוד עבור CarIconSpan.create לקבלת מידע נוסף על יצירת טווחי הזמן האלה. צפייה מדהים עיצוב טקסט באמצעות Spans לקבלת סקירה כללית על אופן הפעולה של עיצוב טקסט באמצעות spans.

Kotlin

  
val rating = SpannableString("Rating: 4.5 stars")
rating.setSpan(
    CarIconSpan.create(
        // Create a CarIcon with an image of four and a half stars
        CarIcon.Builder(...).build(),
        // Align the CarIcon to the baseline of the text
        CarIconSpan.ALIGN_BASELINE
    ),
    // The start index of the span (index of the character '4')
    8,
    // The end index of the span (index of the last 's' in "stars")
    16,
    Spanned.SPAN_INCLUSIVE_INCLUSIVE
)

val row = Row.Builder()
    ...
    .addText(rating)
    .build()
  
  

Java

  
SpannableString rating = new SpannableString("Rating: 4.5 stars");
rating.setSpan(
        CarIconSpan.create(
                // Create a CarIcon with an image of four and a half stars
                new CarIcon.Builder(...).build(),
                // Align the CarIcon to the baseline of the text
                CarIconSpan.ALIGN_BASELINE
        ),
        // The start index of the span (index of the character '4')
        8,
        // The end index of the span (index of the last 's' in "stars")
        16,
        Spanned.SPAN_INCLUSIVE_INCLUSIVE
);
Row row = new Row.Builder()
        ...
        .addText(rating)
        .build();
  
  

ממשקי API לחומרה של רכב

החל מרמת 3 של ה-API לאפליקציה של Car, ספריית האפליקציות למכונית כוללת ממשקי API יכול להשתמש בו כדי לגשת לחיישנים ולמאפייני הרכב.

הדרישות

כדי להשתמש בממשקי ה-API עם Android Auto, צריך קודם להוסיף תלות androidx.car.app:app-projected לקובץ build.gradle ב-Android מודול אוטומטי. ב-Android Automotive OS, צריך להוסיף תלות ב- androidx.car.app:app-automotive לקובץ build.gradle ב-Android מודול Automotive OS.

בנוסף, בקובץ AndroidManifest.xml צריך: להצהיר על ההרשאות הרלוונטיות שנדרשות כדי מבקשים את נתוני הרכב שרוצים להשתמש בהם. שימו לב שההרשאות האלה צריכות להיות גם הוענקה לך על ידי המשתמש. אפשר להשתמש אותו קוד גם ב-Android Auto וגם ב-Android Automotive OS, מאשר ליצור תהליכים תלויי-פלטפורמה. עם זאת, ההרשאות הנדרשות הם שונים.

מידע על רכב

בטבלה זו מפורטים המאפיינים שמוצגים CarInfo ממשקי API ההרשאות שנדרשות כדי להשתמש בהן:

שיטות מאפיינים הרשאות של Android Auto הרשאות ל-Android Automotive OS נתמכת החל מרמת ה-API של האפליקציה לרכב
fetchModel יצרן, דגם, שנה android.car.permission.CAR_INFO 3
fetchEnergyProfile סוגי מחברים של רכבים חשמליים (EV), סוגי הדלק com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_INFO 3
fetchExteriorDimensions

הנתונים האלה זמינים רק בחלק מכלי הרכב עם Android Automotive OS משתמש ב-API מגרסה 30 ומעלה

מידות חיצוניות לא רלוונטי android.car.permission.CAR_INFO 7
addTollListener
removeTollListener
מצב כרטיס האגרה, סוג כרטיס האגרה 3
addEnergyLevelListener
removeEnergyLevelListener
רמת הסוללה, רמת הדלק, רמת הדלק נמוכה, הזמן שנותר: טווח com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_ENERGY,
android.car.permission.CAR_ENERGY_PORTS,
android.car.permission.READ_CAR_DISPLAY_UNITS
3
addSpeedListener
removeSpeedListener
מהירות גולמית, מהירות התצוגה (מוצגת במסך האשכול של הרכב) com.google.android.gms.permission.CAR_SPEED android.car.permission.CAR_SPEED,
android.car.permission.READ_CAR_DISPLAY_UNITS
3
addMileageListener
removeMileageListener
המרחק במד המרחק com.google.android.gms.permission.CAR_MILEAGE הנתונים האלה לא זמינים ב-Android Automotive OS לאפליקציות שהותקנו מחנות Play. 3

לדוגמה, כדי לקבל את הטווח שנותר, צריך ליצור אובייקט CarInfo, ואז יוצרים ורושמים OnCarDataAvailableListener:

Kotlin

val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo

val listener = OnCarDataAvailableListener<EnergyLevel> { data ->
    if (data.rangeRemainingMeters.status == CarValue.STATUS_SUCCESS) {
      val rangeRemaining = data.rangeRemainingMeters.value
    } else {
      // Handle error
    }
  }

carInfo.addEnergyLevelListener(carContext.mainExecutor, listener)

// Unregister the listener when you no longer need updates
carInfo.removeEnergyLevelListener(listener)

Java

CarInfo carInfo = getCarContext().getCarService(CarHardwareManager.class).getCarInfo();

OnCarDataAvailableListener<EnergyLevel> listener = (data) -> {
  if(data.getRangeRemainingMeters().getStatus() == CarValue.STATUS_SUCCESS) {
    float rangeRemaining = data.getRangeRemainingMeters().getValue();
  } else {
    // Handle error
  }
};

carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(), listener);

// Unregister the listener when you no longer need updates
carInfo.removeEnergyLevelListener(listener);

אל תניח שהנתונים מהרכב זמינים כל הזמן. אם מופיעה הודעת שגיאה, צריך לבדוק את status מתוך הערך שביקשת, כדי להבין טוב יותר למה הנתונים שביקשת לא ניתן לאחזר. עיינו ב מאמרי עזרה עבור את ההגדרה המלאה של המחלקה CarInfo.

חיישנים לרכב

הכיתה CarSensors מעניק לך גישה למד התאוצה, לג'ירוסקופ, למצפן ולאמצעי הבקרה של הרכב נתוני מיקום. הזמינות של הערכים האלה תלויה יצרן ציוד מקורי. הפורמט של הנתונים ממד התאוצה, מהג'ירוסקופ ומהמצפן הוא בדיוק כמו שהייתם מקבלים API של SensorManager. לדוגמה, כדי לבדוק את כותרת הרכב:

Kotlin

val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors

val listener = OnCarDataAvailableListener<Compass> { data ->
    if (data.orientations.status == CarValue.STATUS_SUCCESS) {
      val orientation = data.orientations.value
    } else {
      // Data not available, handle error
    }
  }

carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, carContext.mainExecutor, listener)

// Unregister the listener when you no longer need updates
carSensors.removeCompassListener(listener)

Java

CarSensors carSensors = getCarContext().getCarService(CarHardwareManager.class).getCarSensors();

OnCarDataAvailableListener<Compass> listener = (data) -> {
  if (data.getOrientations().getStatus() == CarValue.STATUS_SUCCESS) {
    List<Float> orientations = data.getOrientations().getValue();
  } else {
    // Data not available, handle error
  }
};

carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, getCarContext().getMainExecutor(),
    listener);

// Unregister the listener when you no longer need updates
carSensors.removeCompassListener(listener);

כדי לקבל גישה לנתוני המיקום מהרכב, צריך גם להצהיר ולבקש את ההרשאה android.permission.ACCESS_FINE_LOCATION.

בדיקה

כדי לדמות נתוני חיישנים במהלך בדיקה ב-Android Auto, צריך לעיין ב חיישנים וחיישנים ההגדרות האישיות של מדריך ליחידת הראש למחשב. כדי לדמות נתוני חיישנים במהלך בדיקה ב-Android ב-Automotive OS, אפשר לעיין במאמר אמולציה של החומרה הקטע 'מצב' ב-Android מדריך לאמולטור של Automotive OS.

מחזור החיים של CarAppService, הסשן והמסך

Session וגם Screen מחלקות מטמיעות את ממשק LifecycleOwner. בתור המשתמש מקיים אינטראקציה עם האפליקציה, עם האובייקטים Session ו-Screen מחזור חיים מופעלות קריאות חוזרות (callback), כפי שמתואר בתרשימים הבאים.

מחזורי החיים של CarAppService ושל סשן

איור 1. מחזור החיים של Session.

לקבלת פרטים מלאים, אפשר לעיין במסמכי התיעוד של Session.getLifecycle .

מחזור החיים של מסך

איור 2. מחזור החיים של Screen.

לקבלת פרטים מלאים, אפשר לעיין במסמכי התיעוד של Screen.getLifecycle.

הקלטה מהמיקרופון של הרכב

שימוש CarAppService וגם CarAudioRecord API, אפשר להעניק לאפליקציה גישה למיקרופון ברכב של המשתמש. המשתמשים צריכים לתת להעניק לאפליקציה הרשאת גישה למיקרופון של הרכב. האפליקציה שלך יכולה להקליט לעבד את הקלט של המשתמש בתוך האפליקציה.

הרשאה להקליט

לפני הקלטת אודיו כלשהו, עליך להצהיר תחילה על ההרשאה להקלטה AndroidManifest.xml ולבקש מהמשתמש להעניק אותו.

<manifest ...>
   ...
   <uses-permission android:name="android.permission.RECORD_AUDIO" />
   ...
</manifest>

צריך לבקש הרשאה להקלטה בזמן הריצה. מידע נוסף זמין בבקשה הרשאות לפרטים על האופן שבו מבקשים לבקש באפליקציה לרכב.

הקלטת אודיו

אחרי שהמשתמש יאשר את ההקלטה, אפשר יהיה להקליט את האודיו והעיבוד ההקלטה.

Kotlin

val carAudioRecord = CarAudioRecord.create(carContext)
        carAudioRecord.startRecording()

        val data = ByteArray(CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE)
        while(carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) {
            // Use data array
            // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech
        }
        carAudioRecord.stopRecording()
 

Java

CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        carAudioRecord.startRecording();

        byte[] data = new byte[CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE];
        while (carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) {
            // Use data array
            // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech
        }
        carAudioRecord.stopRecording();
 

מיקוד אודיו

כשמקליטים מהמיקרופון ברכב, צריך קודם לרכוש אודיו להתמקד מוודאים שכל המדיה המתמשכת תופסק. אם איבדת את המיקוד של האודיו, הפסקת ההקלטה.

הנה דוגמה לאופן שבו אפשר להתמקד באודיו:

Kotlin

 
val carAudioRecord = CarAudioRecord.create(carContext)
        
        // Take audio focus so that user's media is not recorded
        val audioAttributes = AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            // Use the most appropriate usage type for your use case
            .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
            .build()
        
        val audioFocusRequest =
            AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
                .setAudioAttributes(audioAttributes)
                .setOnAudioFocusChangeListener { state: Int ->
                    if (state == AudioManager.AUDIOFOCUS_LOSS) {
                        // Stop recording if audio focus is lost
                        carAudioRecord.stopRecording()
                    }
                }
                .build()
        
        if (carContext.getSystemService(AudioManager::class.java)
                .requestAudioFocus(audioFocusRequest)
            != AudioManager.AUDIOFOCUS_REQUEST_GRANTED
        ) {
            // Don't record if the focus isn't granted
            return
        }
        
        carAudioRecord.startRecording()
        // Process the audio and abandon the AudioFocusRequest when done

Java

CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        // Take audio focus so that user's media is not recorded
        AudioAttributes audioAttributes =
                new AudioAttributes.Builder()
                        .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                        // Use the most appropriate usage type for your use case
                        .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
                        .build();

        AudioFocusRequest audioFocusRequest =
                new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
                        .setAudioAttributes(audioAttributes)
                        .setOnAudioFocusChangeListener(state -> {
                            if (state == AudioManager.AUDIOFOCUS_LOSS) {
                                // Stop recording if audio focus is lost
                                carAudioRecord.stopRecording();
                            }
                        })
                        .build();

        if (getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)
                != AUDIOFOCUS_REQUEST_GRANTED) {
            // Don't record if the focus isn't granted
            return;
        }

        carAudioRecord.startRecording();
        // Process the audio and abandon the AudioFocusRequest when done
 

ספריית בדיקות

בדיקות של Android למכוניות הספרייה מספקת מחלקות שאפשר להשתמש בהן כדי לאמת את התנהגות האפליקציה בסביבת בדיקה. לדוגמה, SessionController מאפשרת לדמות חיבור למארח ולוודא Screen והקבוצה Template נוצרים הוחזרו.

עיינו ב טעימות כדי לקבל דוגמאות לשימוש.

דיווח על בעיה בספריית האפליקציות של Android למכוניות

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

דיווח על בעיה חדשה

לפני שליחת בעיה חדשה, יש לבדוק אם היא מופיעה בגרסה של הספרייה או ידווחו ברשימת הבעיות. ניתן להירשם ולהצביע על בעיות עד ללחוץ על סמל הכוכב בשביל בעיה במכשיר המעקב. מידע נוסף זמין במאמר הבא: הרשמה לבעיה.