สร้างแอปการนำทาง

หน้านี้จะแสดงรายละเอียดฟีเจอร์ต่างๆ ของคลังแอปรถยนต์ที่คุณสามารถใช้เพื่อนำฟังก์ชันการทำงานของแอปการนำทางแบบเลี้ยวต่อเลี้ยวไปใช้

ประกาศการรองรับการนําทางในไฟล์ Manifest

แอปการนำทางต้องประกาศ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>

รองรับ Intent การนำทาง

หากต้องการรองรับ Intent การนำทางไปยังแอปของคุณ ซึ่งรวมถึง Intent ที่มาจาก Google Assistant โดยใช้การค้นหาด้วยเสียง แอปของคุณต้องจัดการ Intent CarContext.ACTION_NAVIGATE ใน Session.onCreateScreen และ Session.onNewIntent

ดูรายละเอียดเกี่ยวกับรูปแบบของ Intent ได้ในเอกสารประกอบเกี่ยวกับ CarContext.startCarApp

เข้าถึงเทมเพลตการนำทาง

แอปการนำทางสามารถเข้าถึงเทมเพลตต่อไปนี้ ซึ่งจะแสดงพื้นผิวในเบื้องหลังพร้อมแผนที่ และเส้นทางแบบเลี้ยวต่อเลี้ยวระหว่างการนำทาง

  • NavigationTemplate: แสดงข้อความที่ให้ข้อมูลและเวลาเดินทางโดยประมาณ (ไม่บังคับ) ขณะนำทาง
  • MapWithContentTemplate: เทมเพลตที่ช่วยให้แอปแสดงผลไทล์แผนที่ที่มีเนื้อหาบางประเภท (เช่น รายการ) โดยปกติแล้วระบบจะแสดงผลเนื้อหาเป็นการวางซ้อนบนส่วนที่เป็นชิ้นส่วนแผนที่ โดยที่แผนที่จะมองเห็นได้และพื้นที่ที่มั่นคงจะปรับตามเนื้อหา

ดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีออกแบบอินเทอร์เฟซผู้ใช้ของแอปนำทางโดยใช้เทมเพลตเหล่านี้ได้ที่แอปนำทาง

หากต้องการเข้าถึงเทมเพลตการนำทาง แอปของคุณจะต้องประกาศสิทธิ์ androidx.car.app.NAVIGATION_TEMPLATES ในไฟล์ AndroidManifest.xml ดังนี้

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

ต้องมีสิทธิ์เพิ่มเติมจึงจะวาดแผนที่ได้

ย้ายข้อมูลไปยัง MapWithContentTemplate

ตั้งแต่วันที่ 1 ตุลาคม 2019 เป็นต้นไป เราจะเลิกใช้งาน MapTemplate, PlaceListNavigationTemplate และ RoutePreviewNavigationTemplate ใน Car App API ระดับ 7 ระบบจะยังคงรองรับเทมเพลตที่เลิกใช้งาน แต่เราขอแนะนําอย่างยิ่งให้เปลี่ยนไปใช้ MapWithContentTemplate

คุณสามารถติดตั้งใช้งานฟังก์ชันการทำงานที่เทมเพลตเหล่านี้มีให้โดยใช้ MapWithContentTemplate ดูตัวอย่างได้จากข้อมูลโค้ดต่อไปนี้

MapTemplate

Kotlin

// 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()

Java

// 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

Kotlin

// 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()

Java

// 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

Kotlin

// 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()

Java

// 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

Kotlin

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

Java

NavigationManager navigationManager = carContext.getCarService(NavigationManager.class);

เริ่ม สิ้นสุด และหยุดการนำทาง

โฮสต์ต้องทราบสถานะปัจจุบันของการนําทางจึงจะจัดการแอปการนําทางหลายแอป การแจ้งเตือนการกำหนดเส้นทาง และข้อมูลคลัสเตอร์ของยานพาหนะได้ เมื่อผู้ใช้เริ่มการนําทาง ให้เรียกใช้ NavigationManager.navigationStarted ในทํานองเดียวกัน เมื่อการนําทางสิ้นสุดลง เช่น เมื่อผู้ใช้ไปถึงจุดหมายหรือผู้ใช้ยกเลิกการนําทาง ให้เรียกใช้ NavigationManager.navigationEnded

เรียก NavigationManager.navigationEnded ก็ต่อเมื่อผู้ใช้ไปยังส่วนต่างๆ เสร็จแล้ว เช่น หากต้องการคํานวณเส้นทางใหม่ระหว่างการเดินทาง ให้ใช้ Trip.Builder.setLoading(true) แทน

ในบางครั้ง โฮสต์อาจต้องใช้แอปเพื่อหยุดการนำทางและเรียกใช้ onStopNavigation ในออบเจ็กต์ NavigationManagerCallback ที่ได้จากแอปของคุณผ่าน NavigationManager.setNavigationManagerCallback จากนั้นแอปต้องหยุดแสดงข้อมูลการเลี้ยวถัดไปในจอแสดงผลคลัสเตอร์ การแจ้งเตือนการนำทาง และคำแนะนำด้วยเสียง

อัปเดตข้อมูลการเดินทาง

ในระหว่างที่ใช้การนำทาง ให้โทรไปที่ NavigationManager.updateTrip ข้อมูลที่ได้รับในการเรียกนี้สามารถใช้กับแผงหน้าปัดและจอแสดงผลที่กระจกหน้ารถ ระบบอาจไม่แสดงข้อมูลทั้งหมดแก่ผู้ใช้ ทั้งนี้ขึ้นอยู่กับยานพาหนะที่ขับ เช่น หน่วยส่วนหัวของเดสก์ท็อป (DHU) แสดงข้อมูล Step ที่เพิ่มลงใน Trip แต่จะไม่แสดงข้อมูล Destination

การวาดไปยังจอแผงหน้าปัด

คุณอาจต้องดำเนินการมากกว่าการแสดงข้อมูลเมตาพื้นฐานบนจอแสดงผลคลัสเตอร์ของยานพาหนะ เพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่สมจริงมากที่สุด ตั้งแต่ Car App API ระดับ 6 เป็นต้นไป แอปการนำทางจะมีตัวเลือกในการแสดงผลเนื้อหาของตนเองบนจอแผงหน้าปัดโดยตรง (ในยานพาหนะที่รองรับ) โดยมีข้อจำกัดต่อไปนี้

  • Cluster Display API ไม่รองรับการควบคุมอินพุต
  • หลักเกณฑ์ด้านคุณภาพของแอปรถยนต์ NF-9: จอแผงหน้าปัดควรแสดงเฉพาะไทล์แผนที่ คุณเลือกที่จะแสดงเส้นทางการนำทางที่ใช้งานอยู่บนการ์ดเหล่านี้ได้
  • Cluster Display API รองรับเฉพาะการใช้ NavigationTemplate เท่านั้น
    • จอแสดงผลคลัสเตอร์อาจไม่แสดงองค์ประกอบ UI NavigationTemplate ทั้งหมดอย่างสม่ำเสมอ เช่น เส้นทางแบบเลี้ยวต่อเลี้ยว การ์ดเวลาถึงโดยประมาณ และการดําเนินการต่างๆ ซึ่งแตกต่างจากจอแสดงผลหลัก ชิ้นส่วนแผนที่เป็นองค์ประกอบ UI เดียวที่แสดงอย่างสม่ำเสมอ

ประกาศการรองรับคลัสเตอร์

หากต้องการให้แอปพลิเคชันโฮสต์ทราบว่าแอปของคุณรองรับการแสดงผลภาพในคลัสเตอร์ คุณต้องเพิ่มองค์ประกอบ 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>

การจัดการวงจรและสถานะ

ตั้งแต่ API ระดับ 6 เป็นต้นไป ขั้นตอนในวงจรของแอปรถยนต์จะยังคงเหมือนเดิม แต่ตอนนี้ CarAppService::onCreateSession จะใช้พารามิเตอร์ประเภท SessionInfo ซึ่งให้ข้อมูลเพิ่มเติมเกี่ยวกับ Session ที่สร้าง (ได้แก่ ประเภทการแสดงผลและชุดเทมเพลตที่รองรับ)

แอปมีตัวเลือกในการใช้คลาส Session เดียวกันเพื่อจัดการทั้งคลัสเตอร์และจอแสดงผลหลัก หรือสร้าง Sessions สำหรับจอแสดงผลแต่ละจอเพื่อปรับแต่งลักษณะการทำงาน (ดังที่แสดงในข้อมูลโค้ดต่อไปนี้)

Kotlin

override fun onCreateSession(sessionInfo: SessionInfo): Session {
  return if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER) {
    ClusterSession()
  } else {
    MainDisplaySession()
  }
}

Java

@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 (เช่น โดยใช้การออกอากาศ ซิงเกิลตันที่แชร์ หรืออย่างอื่น)

การทดสอบการสนับสนุนคลัสเตอร์

คุณสามารถทดสอบการติดตั้งใช้งานทั้งใน Android Auto และ Android Automotive OS สำหรับ Android Auto ให้ทำโดยกำหนดค่าเครื่องเล่นวิทยุบนเดสก์ท็อปให้จําลองจอแสดงผลคลัสเตอร์รอง สำหรับ Android Automotive OS ภาพระบบทั่วไปสำหรับ API ระดับ 30 ขึ้นไปจะจำลองการแสดงผลคลัสเตอร์

ปรับแต่งเวลาเดินทางโดยประมาณด้วยข้อความหรือไอคอน

หากต้องการปรับแต่งเวลาเดินทางโดยประมาณด้วยข้อความ ไอคอน หรือทั้ง 2 อย่าง ให้ใช้เมธอดของคลาส TravelEstimate.Builder หรือ setTripIcon หรือ setTripText NavigationTemplate ใช้ TravelEstimate เพื่อตั้งค่าข้อความและไอคอนควบคู่ไปกับหรือแทนเวลาถึงโดยประมาณ เวลาที่เหลือ และระยะทางที่เหลือ (ไม่บังคับ)

รูปที่ 1 เวลาเดินทางโดยประมาณพร้อมไอคอนและข้อความที่กำหนดเอง

ข้อมูลโค้ดต่อไปนี้ใช้ setTripIcon และ setTripText เพื่อปรับแต่งเวลาเดินทางโดยประมาณ

Kotlin

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

Java

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

แสดงการแจ้งเตือนแบบเลี้ยวต่อเลี้ยว

ให้คำแนะนำการนำทางแบบเลี้ยวต่อเลี้ยว (TBT) โดยใช้การแจ้งเตือนการนำทางที่อัปเดตบ่อยครั้ง เครื่องมือสร้างการแจ้งเตือนต้องดำเนินการต่อไปนี้เพื่อให้ระบบถือว่าเป็นการแจ้งเตือนการนำทางในหน้าจอของรถยนต์

  1. ทําเครื่องหมายการแจ้งเตือนว่าดําเนินอยู่ด้วยวิธี NotificationCompat.Builder.setOngoing
  2. ตั้งค่าหมวดหมู่ของการแจ้งเตือนเป็น Notification.CATEGORY_NAVIGATION
  3. ขยายการแจ้งเตือนด้วย CarAppExtender

การแจ้งเตือนการนำทางจะแสดงในวิดเจ็ตแถบข้างที่ด้านล่างของหน้าจอรถยนต์ หากตั้งค่าระดับความสำคัญของการแจ้งเตือนเป็น IMPORTANCE_HIGH ระบบจะแสดงการแจ้งเตือนเป็นการแจ้งเตือนล่วงหน้า (HUN) ด้วย หากไม่ได้ตั้งค่าความสำคัญด้วยวิธี CarAppExtender.Builder.setImportance ระบบจะใช้ความสำคัญของช่องทางการแจ้งเตือน

แอปสามารถตั้งค่า PendingIntent ใน CarAppExtender ที่ส่งไปยังแอปเมื่อผู้ใช้แตะ HUN หรือวิดเจ็ตโฆษณา

หากเรียกใช้ NotificationCompat.Builder.setOnlyAlertOnce ด้วยค่า true ระบบจะส่งการแจ้งเตือนสำคัญสูงเพียงครั้งเดียวใน HUN

ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้างการแจ้งเตือนการนำทาง

Kotlin

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()

Java

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();

อัปเดตการแจ้งเตือน TBT เป็นระยะๆ เพื่อดูการเปลี่ยนแปลงระยะทาง ซึ่งจะอัปเดตวิดเจ็ตรถไฟ และแสดงการแจ้งเตือนเป็น HUN เท่านั้น คุณควบคุมลักษณะการทำงานของ HUN ได้โดยการตั้งค่าความสำคัญของการแจ้งเตือนด้วย CarAppExtender.Builder.setImportance การตั้งค่าความสําคัญเป็น IMPORTANCE_HIGH จะแสดง HUN การตั้งค่าเป็นค่าอื่นจะเป็นการอัปเดตวิดเจ็ตแถบนเท่านั้น

รีเฟรชเนื้อหา PlaceListNavigationTemplate

คุณสามารถอนุญาตให้คนขับรีเฟรชเนื้อหาได้ด้วยการแตะปุ่มเดียวขณะเรียกดูรายการสถานที่ที่สร้างด้วย PlaceListNavigationTemplate หากต้องการเปิดใช้การรีเฟรชรายการ ให้ใช้เมธอดของตัวแปร OnContentRefreshListener ในอินเทอร์เฟซ และใช้ PlaceListNavigationTemplate.Builder.setOnContentRefreshListener เพื่อตั้งค่า Listener ในเทมเพลตonContentRefreshRequested

ข้อมูลโค้ดต่อไปนี้แสดงวิธีตั้งค่า Listener บนเทมเพลต

Kotlin

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

Java

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

ปุ่มรีเฟรชจะแสดงในส่วนหัวของ PlaceListNavigationTemplate เฉพาะในกรณีที่ Listener มีค่าเท่านั้น

เมื่อผู้ใช้คลิกปุ่มรีเฟรช ระบบจะเรียกใช้onContentRefreshRequestedเมธอดของOnContentRefreshListenerการใช้งาน ภายใน onContentRefreshRequested ให้เรียกใช้เมธอด Screen.invalidate จากนั้นโฮสต์จะเรียกใช้เมธอด Screen.onGetTemplate ของแอปเพื่อเรียกข้อมูลเทมเพลตที่มีเนื้อหาที่รีเฟรชแล้ว ดูข้อมูลเพิ่มเติมเกี่ยวกับการรีเฟรชเทมเพลตได้ที่หัวข้อรีเฟรชเนื้อหาของเทมเพลต ตราบใดที่เทมเพลตถัดไปที่onGetTemplateแสดงผลเป็นประเภทเดียวกัน ระบบจะนับเป็นการรีเฟรชและไม่นับรวมในโควต้าของเทมเพลต

ระบุเสียงนำทาง

หากต้องการเล่นคำแนะนำการนำทางผ่านลำโพงรถยนต์ แอปของคุณต้องขอโฟกัสเสียง ในส่วน AudioFocusRequest ให้ตั้งค่าการใช้งานเป็น AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE และตั้งค่าอัตราขยายโฟกัสเป็น AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK

จำลองการนําทาง

หากต้องการยืนยันฟังก์ชันการนําทางของแอปเมื่อส่งแอปไปยัง Google Play Store แอปของคุณต้องใช้การเรียกกลับ 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 แอปการนำทางในรถเริ่มต้นจะสอดคล้องกับแอปการนำทางล่าสุดที่ผู้ใช้เปิด แอปเริ่มต้นจะรับ Intent การนำทางเมื่อผู้ใช้เรียกใช้คำสั่งการนำทางผ่าน Assistant หรือเมื่อแอปอื่นส่ง Intent เพื่อเริ่มการนำทาง

แสดงการแจ้งเตือนการนำทางในบริบท

Alert แสดงข้อมูลสำคัญแก่ผู้ขับขี่พร้อมการดำเนินการที่ไม่บังคับโดยไม่ต้องออกจากบริบทของหน้าจอการนำทาง Alert จะทำงานภายใน NavigationTemplate เพื่อหลีกเลี่ยงการบล็อกเส้นทางการนําทางและลดสิ่งรบกวนไม่ให้ผู้ขับขี่เสียสมาธิ เพื่อให้ผู้ขับขี่ได้รับประสบการณ์การใช้งานที่ดีที่สุด

Alert มีให้บริการภายใน NavigationTemplate เท่านั้น หากต้องการแจ้งเตือนผู้ใช้นอก NavigationTemplate ให้พิจารณาใช้การแจ้งเตือนเพื่อแจ้งให้ทราบล่วงหน้า (HUN) ตามที่อธิบายไว้ในแสดงการแจ้งเตือน

เช่น ใช้ Alert เพื่อทำสิ่งต่อไปนี้

  • แจ้งข้อมูลอัปเดตที่เกี่ยวข้องกับการนําทางปัจจุบันแก่คนขับ เช่น การเปลี่ยนแปลงสภาพการจราจร
  • ขอข้อมูลอัปเดตเกี่ยวกับการนำทางปัจจุบันจากคนขับ เช่น การมีจุดตรวจจับความเร็ว
  • เสนองานที่กำลังจะเกิดขึ้นและถามว่าคนขับยอมรับงานหรือไม่ เช่น ถามว่าคนขับยินดีไปรับผู้โดยสารระหว่างทางไหม

Alert ในรูปแบบพื้นฐานประกอบด้วยชื่อและAlert ระยะเวลา ระยะเวลาจะแสดงด้วยแถบความคืบหน้า คุณเพิ่มคำบรรยายแทนเสียง ไอคอน และAction ออบเจ็กต์ได้สูงสุด 2 รายการ

รูปที่ 2 การแจ้งเตือนการนำทางในบริบท

เมื่อ Alert แสดงแล้ว Alert จะไม่แสดงในเทมเพลตอื่นหากการโต้ตอบของผู้ขับขี่ส่งผลให้ออกจาก NavigationTemplate NavigationTemplate เดิมจะยังคงอยู่ในตำแหน่งเดิมจนกว่าAlertจะหมดเวลา ผู้ใช้ดำเนินการ หรือแอปปิดAlert

สร้างการแจ้งเตือน

ใช้ Alert.Builder เพื่อสร้างอินสแตนซ์ Alert

Kotlin

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()

Java

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 หมดเวลา โฮสต์จะเรียกใช้เมธอด AlertCallback.onCancel ด้วยค่า AlertCallback.REASON_TIMEOUT จากนั้นจะเรียกใช้เมธอด AlertCallback.onDismiss

  • หากคนขับคลิกปุ่มการทำงานใดปุ่มหนึ่ง โฮสต์จะเรียกใช้ Action.OnClickListener แล้วเรียกใช้ AlertCallback.onDismiss

  • หากไม่รองรับ Alert โฮสต์จะเรียกใช้ AlertCallback.onCancel ด้วยค่า AlertCallback.REASON_NOT_SUPPORTED โฮสต์ไม่ได้เรียกใช้ AlertCallback.onDismiss เนื่องจากไม่มีการแสดง Alert

กำหนดค่าระยะเวลาการแจ้งเตือน

เลือกระยะเวลา Alert ที่ตรงกับความต้องการของแอป ระยะเวลาที่แนะนำสำหรับการนําทางAlertคือ 10 วินาที โปรดดูข้อมูลเพิ่มเติมที่การแจ้งเตือนการนำทาง

แสดงการแจ้งเตือน

หากต้องการแสดง Alert ให้เรียกใช้วิธี AppManager.showAlert ที่พร้อมใช้งานผ่าน CarContext ของแอป

// Show an alert
carContext.getCarService(AppManager.class).showAlert(alert)
  • การเรียกใช้ showAlert ด้วย Alert ที่มี alertId เหมือนกับรหัสของ Alert ที่แสดงอยู่ในปัจจุบันจะไม่ทําอะไรเลย Alert ไม่อัปเดต หากต้องการอัปเดต Alert คุณต้องสร้าง Alert ใหม่alertId
  • การเรียก showAlert ด้วย Alert ที่มี alertId แตกต่างจาก Alert ที่แสดงอยู่ในปัจจุบันจะเป็นการปิด Alert ที่แสดงอยู่

ปิดการแจ้งเตือน

แม้ว่า Alert จะปิดโดยอัตโนมัติเนื่องจากหมดเวลาหรือมีการโต้ตอบกับไดรเวอร์ แต่คุณก็ปิด Alert ด้วยตนเองได้ เช่น ในกรณีที่ข้อมูลล้าสมัย หากต้องการปิดAlert ให้เรียกใช้เมธอด dismissAlert ด้วยalertId ของ Alert

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

การเรียก dismissAlert ด้วย alertId ที่ไม่ตรงกับ Alert ที่แสดงอยู่ในปัจจุบันจะไม่ทําอะไรเลย โดยไม่มีข้อยกเว้น