פיתוח אפליקציית ניווט

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

הצהרת תמיכה בניווט במניפסט

אפליקציית הניווט צריכה להצהיר על androidx.car.app.category.NAVIGATION קטגוריית אפליקציית הרכב במסנן ה-Intent של CarAppService:

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

תמיכה בכוונות ניווט

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

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

  • Android Auto: ברכיב המניפסט <activity> של Activity שמשמש לטיפול בכוונה כשהמשתמש לא משתמש ב-Android Auto.
  • Android Automotive OS: ברכיב המניפסט <activity> של CarAppActivity.

לאחר מכן, קוראים את הכוונות ומטפלים בהן גם ב-callbacks של onCreateScreen() וגם ב-callbacks של onNewIntent() בהטמעת Session של האפליקציה.

פורמטים נדרשים של כוונות

כדי לעמוד בדרישת האיכות של NF-6, האפליקציה צריכה לטפל בכוונות ניווט.

פורמטים אופציונליים של כוונה

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

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

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

  • NavigationTemplate: מוצגת גם הודעה מידע אופציונלית ותחזיות זמן הגעה במהלך ניווט פעיל.
  • MapWithContentTemplate: תבנית שמאפשרת לאפליקציה ליצור ריבועי מפה עם תוכן כלשהו (לדוגמה, רשימה). בדרך כלל, התוכן מוצג כשכבת-על מעל לאריחי המפה, והמפה גלויה ואזורים יציבים מתאימים לתוכן.

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

כדי לקבל גישה לתבניות הניווט, האפליקציה צריכה להצהיר על ההרשאה androidx.car.app.NAVIGATION_TEMPLATES בקובץ AndroidManifest.xml שלה:

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

כדי לצייר מפות, נדרשת הרשאה נוספת.

מעבר ל-MapWithContentTemplate

החל מרמת API 7 של אפליקציות לרכב, הוצאנו משימוש את הקריאות MapTemplate,‏ PlaceListNavigationTemplate ו-RoutePreviewNavigationTemplate. התמיכה בתבניות הקודמות תמשיך, אבל מומלץ מאוד לעבור ל-MapWithContentTemplate.

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

MapTemplate

KotlinJava
// MapTemplate (deprecated)
val template = MapTemplate.Builder()
    .setPane(paneBuilder.build())
    .setActionStrip(actionStrip)
    .setHeader(header)
    .setMapController(mapController)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        PaneTemplate.Builder(paneBuilder.build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(mapController)
    .build()
// MapTemplate (deprecated)
MapTemplate template = new MapTemplate.Builder()
    .setPane(paneBuilder.build())
    .setActionStrip(actionStrip)
    .setHeader(header)
    .setMapController(mapController)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new PaneTemplate.Builder(paneBuilder.build())
        .setHeader(header)
        build())
    .setActionStrip(actionStrip)
    .setMapController(mapController)
    .build();

PlaceListNavigationTemplate

KotlinJava
// PlaceListNavigationTemplate (deprecated)
val template = PlaceListNavigationTemplate.Builder()
    .setItemList(itemListBuilder.build())
    .setHeader(header)
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        ListTemplate.Builder()
            .setSingleList(itemListBuilder.build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(
        MapController.Builder()
            .setMapActionStrip(mapActionStrip)
            .build())
    .build()
// PlaceListNavigationTemplate (deprecated)
PlaceListNavigationTemplate template = new PlaceListNavigationTemplate.Builder()
    .setItemList(itemListBuilder.build())
    .setHeader(header)
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new ListTemplate.Builder()
        .setSingleList(itemListBuilder.build())
        .setHeader(header)
        .build())
    .setActionStrip(actionStrip)
    .setMapController(new MapController.Builder()
        .setMapActionStrip(mapActionStrip)
        .build())
    .build();

RoutePreviewNavigationTemplate

KotlinJava
// RoutePreviewNavigationTemplate (deprecated)
val template = RoutePreviewNavigationTemplate.Builder()
    .setItemList(
        ItemList.Builder()
            .addItem(
                Row.Builder()
                    .setTitle(title)
                    .build())
            .build())
    .setHeader(header)
    .setNavigateAction(
        Action.Builder()
            .setTitle(actionTitle)
            .setOnClickListener { ... }
            .build())
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build()

// MapWithContentTemplate
val template = MapWithContentTemplate.Builder()
    .setContentTemplate(
        ListTemplate.Builder()
            .setSingleList(
                ItemList.Builder()
                    .addItem(
                        Row.Builder()
                            .setTitle(title)
                            .addAction(
                                Action.Builder()
                                    .setTitle(actionTitle)
                                    .setOnClickListener { ... }
                                    .build())
                            .build())
                    .build())
            .setHeader(header)
            .build())
    .setActionStrip(actionStrip)
    .setMapController(
        MapController.Builder()
            .setMapActionStrip(mapActionStrip)
            .build())
    .build()
// RoutePreviewNavigationTemplate (deprecated)
RoutePreviewNavigationTemplate template = new RoutePreviewNavigationTemplate.Builder()
    .setItemList(new ItemList.Builder()
        .addItem(new Row.Builder()
            .setTitle(title))
            .build())
        .build())
    .setHeader(header)
    .setNavigateAction(new Action.Builder()
        .setTitle(actionTitle)
        .setOnClickListener(() -> { ... })
        .build())
    .setActionStrip(actionStrip)
    .setMapActionStrip(mapActionStrip)
    .build();

// MapWithContentTemplate
MapWithContentTemplate template = new MapWithContentTemplate.Builder()
    .setContentTemplate(new ListTemplate.Builder()
        .setSingleList(new ItemList.Builder()
            .addItem(new Row.Builder()
                  .setTitle(title))
                  .addAction(new Action.Builder()
                      .setTitle(actionTitle)
                      .setOnClickListener(() -> { ... })
                      .build())
                  .build())
            .build()))
        .setHeader(header)
        .build())
    .setActionStrip(actionStrip)
    .setMapController(new MapController.Builder()
        .setMapActionStrip(mapActionStrip)
        .build())
    .build();

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

המטא-נתונים של הניווט ניתנים דרך שירות הרכב NavigationManager שאפשר לגשת אליו דרך CarContext:

KotlinJava
val navigationManager = carContext.getCarService(NavigationManager::class.java)
NavigationManager navigationManager = carContext.getCarService(NavigationManager.class);

הפעלה, סיום ועצירה של הניווט

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

צריך להפעיל את NavigationManager.navigationEnded רק כשהמשתמש מסיים לנווט. לדוגמה, אם צריך לחשב מחדש את המסלול באמצע הנסיעה, משתמשים במקום זאת ב-Trip.Builder.setLoading(true).

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

עדכון פרטי הנסיעה

במהלך ניווט פעיל, מקישים על NavigationManager.updateTrip. המידע שסופק בקריאה הזו יכול לשמש את קבוצת המחוונים ואת התצוגה העילית של הרכב. בהתאם לרכב הספציפי שבו נוהגים, לא כל המידע מוצג למשתמש. לדוגמה, ב-Desktop Head Unit (DHU) מוצג הערך Step שנוסף ל-Trip, אבל לא מוצג המידע של Destination.

ציור בלוח המחוונים האשכולי

כדי לספק את חוויית המשתמש הכי מרתקת, כדאי להציג יותר ממטא-נתונים בסיסיים בלוח המחוונים של הרכב. החל מרמה 6 של Car App API, לאפליקציות ניווט יש אפשרות להציג את התוכן שלהן ישירות במסך האשכולות (ברכבים נתמכים), עם המגבלות הבאות:

  • ממשק ה-API של תצוגת האשכולות לא תומך באמצעי בקרה על קלט
  • הנחיה בנושא איכות של אפליקציה לכלי רכב NF-9: צריך להציג בלוח המחוונים רק אריחי מפה. אפשר גם להציג בכרזות האלה מסלול ניווט פעיל.
  • ב-Cluster Display API יש תמיכה רק בשימוש ב-NavigationTemplate
    • בניגוד למסכים הראשיים, יכול להיות שבמסכי האשכולות לא יוצגו באופן עקבי כל אלמנטים של ממשק המשתמש של NavigationTemplate, כמו הוראות מפורטות, כרטיסי זמן הגעה משוער ופעולות. המשבצות של המפה הן הרכיב היחיד בממשק המשתמש שמוצג באופן עקבי.

הצהרת תמיכה באשכולות

כדי להודיע לאפליקציית המארח שהאפליקציה תומכת ברינדור במסכים של האשכולות, צריך להוסיף את האלמנט androidx.car.app.category.FEATURE_CLUSTER <category> ל-<intent-filter> של CarAppService, כפי שמוצג בקטע הקוד הבא:

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

ניהול מחזור חיים ומצבים

החל מרמה 6 של ה-API, תהליך מחזור החיים של אפליקציית הרכב נשאר ללא שינוי, אבל עכשיו CarAppService::onCreateSession מקבל פרמטר מסוג SessionInfo שמספק מידע נוסף על Session שנוצר (כלומר, סוג התצוגה וקבוצת התבניות הנתמכות).

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

KotlinJava
override fun onCreateSession(sessionInfo: SessionInfo): Session {
  return if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER) {
    ClusterSession()
  } else {
    MainDisplaySession()
  }
}
@Override
@NonNull
public Session onCreateSession(@NonNull SessionInfo sessionInfo) {
  if (sessionInfo.getDisplayType() == SessionInfo.DISPLAY_TYPE_CLUSTER) {
    return new ClusterSession();
  } else {
    return new MainDisplaySession();
  }
}

אין ערובה לגבי המועד שבו תצוגת האשכולות תסופק, או אם היא תסופק בכלל. ייתכן גם ש-Session של האשכולות יהיה ה-Session היחיד (לדוגמה, המשתמש החליף את המסך הראשי לאפליקציה אחרת בזמן שהאפליקציה שלכם מבצעת ניווט פעיל). ההסכם 'הסטנדרטי' הוא שהאפליקציה מקבלת שליטה על תצוגת האשכולות רק אחרי שמפעילים את NavigationManager::navigationStarted. עם זאת, יכול להיות שהאפליקציה תקבל את תצוגת האשכול גם אם לא מתבצעת ניווט פעיל, או שהיא לא תקבל אותה אף פעם. האפליקציה שלכם צריכה לטפל בתרחישים האלה על ידי עיבוד של מצב ההשבתה של האפליקציה של משבצות המפה.

המארח יוצר מכונות נפרדות של binder ו-CarContext לכל Session. כלומר, כשמשתמשים בשיטות כמו ScreenManager::push או Screen::invalidate, רק ה-Session שממנו הן נקראות מושפע. אם יש צורך בתקשורת בין מכונות Session, האפליקציות צריכות ליצור ערוצי תקשורת משלהם בין המכונות האלה (לדוגמה, באמצעות שידורים, אובייקט singleton משותף או דרך אחרת).

בדיקת התמיכה באשכולות

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

התאמה אישית של 'הערכת זמן הנסיעה' באמצעות טקסט או סמל

כדי להתאים אישית את הערכת הזמן של המסלול באמצעות טקסט, סמל או שניהם, משתמשים ב-methods‏ setTripIcon או setTripText של הכיתה TravelEstimate.Builder. ב-NavigationTemplate אפשר להשתמש ב-TravelEstimate כדי להציג טקסט וסמלים לצד זמן ההגעה המשוער, הזמן שנותר והמרחק שנותר, או במקומם.

איור 1. אומדן נסיעה עם סמל וטקסט בהתאמה אישית.

בקטע הקוד הבא נעשה שימוש ב-setTripIcon וב-setTripText כדי להתאים אישית את האומדן של זמן הנסיעה:

KotlinJava
TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...))
      ...
      .setTripIcon(CarIcon.Builder(...).build())
      .setTripText(CarText.create(...))
      .build()
new TravelEstimate.Builder(Distance.create(...), DateTimeWithZone.create(...))
      ...
      .setTripIcon(CarIcon.Builder(...).build())
      .setTripText(CarText.create(...))
      .build();

לקבל התראות על מסלול מפורט

לספק הוראות ניווט מפורטות (TBT) באמצעות התראה על ניווט שמתעדכנת לעיתים קרובות. כדי שההתראה תטופל כהתראה על ניווט במסך הרכב, ה-builder של ההתראה צריך לבצע את הפעולות הבאות:

  1. מסמנים את ההתראה כפעילות באמצעות השיטה NotificationCompat.Builder.setOngoing.
  2. מגדירים את הקטגוריה של ההתראה כ-Notification.CATEGORY_NAVIGATION.
  3. מקישים על CarAppExtender כדי להרחיב את ההתראה.

התראה על ניווט תוצג בווידג'ט של המסילה בתחתית המסך ברכב. אם רמת החשיבות של ההתראה מוגדרת כ-IMPORTANCE_HIGH, היא תוצג גם כהודעה מראש (HUN). אם לא מגדירים את מידת החשיבות באמצעות השיטה CarAppExtender.Builder.setImportance, המערכת משתמשת במידת החשיבות של ערוץ ההתראות.

האפליקציה יכולה להגדיר PendingIntent ב-CarAppExtender שנשלח לאפליקציה כשהמשתמש מקשיב על HUN או על הווידג'ט של המסילה.

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

בקטע הקוד הבא מוסבר איך ליצור התראה על ניווט:

KotlinJava
NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    ...
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            ...
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    Intent(ACTION_OPEN_APP).setComponent(
                        ComponentName(context, MyNotificationReceiver::class.java)),
                        0))
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build())
    .build()
new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
    ...
    .setOnlyAlertOnce(true)
    .setOngoing(true)
    .setCategory(NotificationCompat.CATEGORY_NAVIGATION)
    .extend(
        new CarAppExtender.Builder()
            .setContentTitle(carScreenTitle)
            ...
            .setContentIntent(
                PendingIntent.getBroadcast(
                    context,
                    ACTION_OPEN_APP.hashCode(),
                    new Intent(ACTION_OPEN_APP).setComponent(
                        new ComponentName(context, MyNotificationReceiver.class)),
                        0))
            .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH)
            .build())
    .build();

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

רענון התוכן של PlaceListNavigationTemplate

אתם יכולים לאפשר לנהגים לרענן את התוכן בלחיצה על כפתור בזמן שהם גולשים ברשימות של מקומות שנוצרו באמצעות PlaceListNavigationTemplate. כדי להפעיל את הרענון של הרשימה, מטמיעים את השיטה onContentRefreshRequested של הממשק OnContentRefreshListener ומשתמשים ב-PlaceListNavigationTemplate.Builder.setOnContentRefreshListener כדי להגדיר את המאזין בתבנית.

בקטע הקוד הבא מוצג איך להגדיר את המאזין בתבנית:

KotlinJava
PlaceListNavigationTemplate.Builder()
    ...
    .setOnContentRefreshListener {
        // Execute any desired logic
        ...
        // Then call invalidate() so onGetTemplate() is called again
        invalidate()
    }
    .build()
new PlaceListNavigationTemplate.Builder()
        ...
        .setOnContentRefreshListener(() -> {
            // Execute any desired logic
            ...
            // Then call invalidate() so onGetTemplate() is called again
            invalidate();
        })
        .build();

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

כשהמשתמש לוחץ על לחצן הרענון, מתבצעת קריאה ל-method‏ onContentRefreshRequested של ההטמעה של OnContentRefreshListener. ב-onContentRefreshRequested, קוראים ל-method‏ Screen.invalidate. לאחר מכן, המארח קורא שוב ל-method‏ Screen.onGetTemplate של האפליקציה כדי לאחזר את התבנית עם התוכן המעודכן. מידע נוסף על רענון תבניות זמין במאמר רענון התוכן של תבנית. כל עוד התבנית הבאה שתוחזר על ידי onGetTemplate היא מאותו סוג, היא נחשבת לרענון ולא נכללת במכסת התבניות.

לספק הנחיות קוליות

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

סימולציה של ניווט

כדי לאמת את פונקציונליות הניווט של האפליקציה כששולחים אותה לחנות Google Play, צריך להטמיע באפליקציה את פונקציית ה-callback‏ NavigationManagerCallback.onAutoDriveEnabled. כשהקריאה החוזרת הזו מתבצעת, האפליקציה צריכה לדמות ניווט ליעד שנבחר כשהמשתמש מתחיל לנווט. האפליקציה יכולה לצאת מהמצב הזה בכל שלב שבו מחזור החיים של Session הנוכחי מגיע למצב Lifecycle.Event.ON_DESTROY.

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

adb shell dumpsys activity service CAR_APP_SERVICE_NAME AUTO_DRIVE

הדוגמה הבאה ממחישה זאת:

adb shell dumpsys activity service androidx.car.app.samples.navigation.car.NavigationCarAppService AUTO_DRIVE

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

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

הצגת התראות ניווט בהקשר

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

Alert זמין רק ב-NavigationTemplate. כדי להודיע למשתמש מחוץ ל-NavigationTemplate, מומלץ להשתמש בהתראה מראש (HUN), כפי שמוסבר בקטע הצגת התראות.

לדוגמה, אפשר להשתמש ב-Alert כדי:

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

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

איור 2. התראה על ניווט בהקשר.

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

יצירת התראה

משתמשים ב-Alert.Builder כדי ליצור מכונה של Alert:

KotlinJava
Alert.Builder(
        /*alertId*/ 1,
        /*title*/ CarText.create("Hello"),
        /*durationMillis*/ 5000
    )
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create(...))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(...)
    .build()
new Alert.Builder(
        /*alertId*/ 1,
        /*title*/ CarText.create("Hello"),
        /*durationMillis*/ 5000
    )
    // The fields below are optional
    .addAction(firstAction)
    .addAction(secondAction)
    .setSubtitle(CarText.create(...))
    .setIcon(CarIcon.APP_ICON)
    .setCallback(...)
    .build();

אם רוצים להאזין לביטול או לסגירה של Alert, צריך ליצור הטמעה של הממשק AlertCallback. נתיבי הקריאה של AlertCallback הם:

הגדרת משך ההתראה

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

הצגת התראה

כדי להציג Alert, צריך להפעיל את השיטה AppManager.showAlert שזמינה דרך CarContext של האפליקציה.

// Show an alert
carContext.getCarService(AppManager.class).showAlert(alert)
  • קריאה ל-showAlert עם Alert שיש לו alertId זהה למזהה של Alert שמוצג כרגע לא גורמת לשום דבר. הערך של Alert לא מתעדכן. כדי לעדכן Alert, צריך ליצור אותו מחדש באמצעות alertId חדש.
  • קריאה ל-showAlert עם Alert שיש לו alertId שונה מ-Alert שמוצג כרגע תסגור את Alert שמוצג כרגע.

סגירת התראה

Alert נסגר באופן אוטומטי עקב זמן קצוב לתפוגה או אינטראקציה של הנהג, אבל אפשר גם לסגור Alert באופן ידני, למשל אם המידע שלו לא עדכני. כדי לסגור Alert, צריך לבצע קריאה ל-method‏ dismissAlert עם alertId של ה-Alert.

// Dismiss the same alert
carContext.getCarService(AppManager.class).dismissAlert(alert.getId())

קריאה ל-dismissAlert עם alertId שלא תואם ל-Alert שמוצג כרגע לא גורמת לשום דבר. היא לא מפעילה חריגה.