本頁說明車輛應用程式程式庫的不同功能,方便您實作即時路線導航應用程式中的功能。
在資訊清單中聲明導航支援功能
導航應用程式需要在 CarAppService
的意圖篩選器中聲明 androidx.car.app.category.NAVIGATION
車輛應用程式類別:
<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>
支援導航意圖
為支援應用程式的導航意圖 (包括透過 Google 助理使用語音查詢的導航意圖),應用程式需要處理 Session.onCreateScreen
和 Session.onNewIntent
中的 CarContext.ACTION_NAVIGATE
意圖。
如要進一步瞭解意圖格式,請參閱有關 CarContext.startCarApp
的說明文件。
存取導航範本
導航應用程式可以存取以下專為導航應用程式設計的範本。這些範本都會在地圖的背景顯示介面,並在導航期間顯示即時路線指示。
NavigationTemplate
:在導航期間,也會顯示選擇性的資訊訊息和行程預估時間。MapTemplate
:在地圖旁顯示窄小型清單 (如ListTemplate
中所示),或窄小型窗格 (詳細資訊與醒目動作,如PaneTemplate
中所示)。PlaceListNavigationTemplate
:也會顯示地點清單,且可以在地圖上添加相應的標記。RoutePreviewNavigationTemplate
:也會顯示路徑清單,且可以在地圖中選取路徑並加上醒目標示。
如要進一步瞭解如何運用這些範本設計導航應用程式的使用者介面,請參閱「導航應用程式」。
如要存取導航範本,應用程式需要在 AndroidManifest.xml
檔案中宣告 androidx.car.app.NAVIGATION_TEMPLATES
權限:
<uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES"/>
繪製地圖
導航應用程式可以存取 Surface
,在相關範本中繪製地圖。
如要存取 SurfaceContainer
物件,可以在 AppManager
車輛服務設定上 SurfaceCallback
例項:
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
Surface
屬性有所變更時,SurfaceCallback
就會在可使用 SurfaceContainer
時提供回呼及其他回呼。
如要存取介面,應用程式必須在 AndroidManifest.xml
檔案中聲明 androidx.car.app.ACCESS_SURFACE
權限:
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE"/>
地圖可見區域
主機可在地圖上層為範本繪製使用者介面元素。只要呼叫 SurfaceCallback.onVisibleAreaChanged
方法,主機即可與使用者絕對可見的開放區域通訊。此外,為了盡量減少變更,主機會透過最小矩形呼叫 SurfaceCallback.onStableAreaChanged
方法,這種矩形一律會根據目前的範本顯示。
舉例來說,如果導航應用程式使用有頂端動作列的 NavigationTemplate
,在使用者有一段時間未與畫面互動後,系統就會隱藏該動作列,為地圖提供更多空間。在這種情況下,系統會使用相同矩形回呼 onStableAreaChanged
和 onVisibleAreaChanged
。動作列隱藏時,系統只會使用較大區域呼叫 onVisibleAreaChanged
。如果使用者與畫面互動,系統只會使用第一個矩形呼叫 onVisibleAreaChanged
。
支援深色模式
當主機判定條件可提供擔保時,導航應用程式必須使用適當的深色在 Surface
例項上重新繪製地圖,如「車用 Android 應用程式品質指南」所述。
如要判斷是否應繪製深色地圖,可以使用 CarContext.isDarkMode
方法。每當深色模式狀態有所變更,您就會收到 Session.onCarConfigurationChanged
呼叫。
傳送導航中繼資料
導航應用程式必須向主機傳送額外的導航中繼資料。主機會使用該資訊,為車輛的車用運算主機提供資訊,並避免導航應用程式與共用資源產生衝突。
系統會透過可從 CarContext
存取的 NavigationManager
車輛服務提供導航中繼資料:
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)
。
主機有時會需要應用程式停止導航,然後透過 NavigationManager.setNavigationManagerCallback
在應用程式提供的 NavigationManagerCallback
物件中呼叫 onStopNavigation
。應用程式必須隨後停止在叢集顯示畫面、導航通知和語音導引中發送下一個轉彎資訊。
更新行程資訊
在導航期間,請呼叫 NavigationManager.updateTrip
。此呼叫提供的資訊可用於車輛的叢集和看路提醒顯示畫面。視使用者駕駛的車輛而定,使用者並不會看到所有資訊。舉例來說,電腦版車用運算主機 (DHU) 會顯示加入 Trip
的 Step
,但不會顯示 Destination
資訊。
繪製至儀表板螢幕
為了提供最身歷其境的使用者體驗,您可能會希望在車輛的儀表板螢幕上顯示基本中繼資料以外的資訊。從 Car App API 級別 6 開始,導航應用程式可以選擇在儀表板螢幕上直接顯示自身的內容 (適用於支援的車輛),但有下列限制:
- 儀表板螢幕 API 不支援輸入控制項
- 儀表板螢幕應只顯示地圖圖塊。您可以選擇在這些圖塊上顯示使用中的導航路線。
- 儀表板螢幕 API 僅支援使用
NavigationTemplate
- 與主螢幕不同,儀表板螢幕不一定每次都會顯示所有
NavigationTemplate
UI 元素,例如即時路線指示、預計到達時間資訊卡和動作。地圖圖塊是唯一會持續顯示的 UI 元素。
- 與主螢幕不同,儀表板螢幕不一定每次都會顯示所有
宣告儀表板支援
為了讓主機應用程式知道您的應用程式支援在儀表板螢幕上顯示內容,您必須在 CarAppService
的 <intent-filter>
中新增 androidx.car.app.category.FEATURE_CLUSTER
<category>
元素,如以下程式碼片段所示:
<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
後,應用程式才會取得儀表板螢幕的控制權。但是,系統仍有可能在沒有導航作業發生時為應用程式提供儀表板螢幕,也可能一律不提供儀表板螢幕。您的應用程式可以藉由顯示地圖圖塊的閒置狀態,自行處理這些情況。
主機會為每個 Session
建立獨立的繫結機制和 CarContext
執行個體。也就是說,在您使用 ScreenManager::push
或 Screen::invalidate
等方法時,只有用於呼叫這些方法的 Session
會受到影響。如果需要跨 Session
通訊,應用程式應在這些執行個體間建立自己的通訊管道 (例如使用廣播訊息、共用的單例模式等方法)。
測試儀表板支援
無論是在 Android Auto 還是 Android Automotive OS 上,您都可以測試導入作業。Android Auto 適用的方法,是設定電腦版車用運算主機來模擬次要儀表板螢幕。如果是 Android Automotive OS,則會以 API 級別 30 以上的通用系統映像檔來模擬儀表板螢幕。
使用文字或圖示自訂 TravelEstimate
如要利用文字和/或圖示自訂行程預估時間,請使用 TravelEstimate.Builder
類別的 setTripIcon
或 setTripText
方法。NavigationTemplate
會使用 TravelEstimate
選擇性設定文字和圖示,用來搭配或取代預計到達時間、剩餘時間和剩餘距離。

下列程式碼片段使用 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) 導航指示。為了在汽車螢幕上順利顯示導航通知,通知建構工具必須執行下列操作:
- 使用
NotificationCompat.Builder.setOngoing
方法,將通知標示為進行中。 - 將通知的類別設為
Notification.CATEGORY_NAVIGATION
。 - 使用
CarAppExtender
擴充通知。
導航通知會在車輛螢幕底部的邊欄小工具中顯示。如果通知的重要性等級已設為 IMPORTANCE_HIGH
,則也會顯示為抬頭通知 (HUN)。如果並未使用 CarAppExtender.Builder.setImportance
方法設定重要性,系統就會使用通知管道的重要性。
應用程式可在 CarAppExtender
中設定 PendingIntent
,並在使用者輕觸抬頭通知或邊欄小工具時,將其傳送至應用程式。
如果使用 true
值呼叫 NotificationCompat.Builder.setOnlyAlertOnce
,則重要性高的通知只會在抬頭通知中顯示一次。
下列程式碼片段示範如何建構導航通知:
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();
請根據距離變化定期更新即時路線通知 (邊欄小工具也會隨之更新),並且僅以抬頭通知的形式顯示通知。您可以使用 CarAppExtender.Builder.setImportance
設定通知的重要性,藉此控制抬頭通知的行為。將重要性設為 IMPORTANCE_HIGH
,就會顯示抬頭通知;如果設為任何其他值,則只會更新邊欄小工具。
重新整理 PlaceListNavigationTemplate 內容
您可以允許駕駛人在瀏覽 PlaceListNavigationTemplate
建構的地點清單時,透過輕觸按鈕重新整理內容。如要啟用清單重新整理功能,請實作 OnContentRefreshListener
介面的 onContentRefreshRequested
方法,並使用 PlaceListNavigationTemplate.Builder.setOnContentRefreshListener
為範本設定事件監聽器。
下列程式碼片段示範如何為範本設定事件監聽器:
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
的標頭中。
駕駛人按一下重新整理按鈕時,系統會呼叫 OnContentRefreshListener
實作的 onContentRefreshRequested
方法。請在 onContentRefreshRequested
中,呼叫 Screen.invalidate
方法。主機隨後會呼叫應用程式的 Screen.onGetTemplate
方法,使用經過重新整理的內容擷取範本。如要進一步瞭解如何重新整理範本,請參閱「重新整理範本內容」。只要 onGetTemplate
傳回的下一個範本類型相同,系統就會計為重新整理,而不會計入範本配額。
提供語音導引
如要使用車上音響播放導航指引,應用程式必須申請音訊焦點權限。請在 AudioFocusRequest
中,將用途設為 AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE
。此外,請將焦點增益設為 AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
。
模擬導航
為了將導航功能提交至 Google Play 商店並進行驗證,應用程式必須實作 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 中,使用者最後啟動的導航應用程式會成為預設的車輛導航應用程式。當使用者透過 Google 助理叫用導航指令,或其他應用程式傳送啟動導航的意圖時,預設應用程式會接收導航意圖。
允許使用者與地圖互動
您可以新增使用者與地圖互動的支援功能,例如讓使用者縮放及平移地圖,查看地圖的不同部分。每個範本的車輛應用程式最低 API 級別規定不盡相同。請參閱下表,瞭解您想實作的範本所需的最低級別。
範本 | 開始支援互動功能的 Car App API 級別 |
---|---|
NavigationTemplate | 2 |
PlaceListNavigationTemplate | 4 |
RoutePreviewNavigationTemplate | 4 |
MapTemplate | 5 |
SurfaceCallback 方法
SurfaceCallback
介面提供多種回呼方法,可讓您為使用 NavigationTemplate
、PlaceListNavigationTemplate
、RoutePreviewNavigationTemplate
或 MapTemplate
範本建構的地圖增添互動性:onClick
、onScroll
、onScale
和 onFling
。如要瞭解這些回呼與使用者互動之間的關係,請參閱下表。
互動 | SurfaceCallback 方法 |
開始支援的 Car App API 級別 |
---|---|---|
輕觸 | onClick |
5 |
雙指撥動即可縮放 | onScale |
2 |
單點觸控拖曳 | onScroll |
2 |
單點觸控滑動 | onFling |
2 |
輕觸兩下 | onScale (由範本主機決定縮放比例係數) |
2 |
平移模式的旋轉自動提醒 | onScroll (由範本主機決定距離係數) |
2 |
地圖動作列
NavigationTemplate
、PlaceListNavigationTemplate
、RoutePreviewNavigationTemplate
和 MapTemplate
範本可包含地圖動作列,用來顯示地圖相關動作,例如縮放、重新置中、顯示指南針,以及其他選擇顯示的動作。地圖動作列最多可有四個純圖示按鈕,這些按鈕可重新整理,不會影響工作深度。處於閒置狀態時,這個動作列會隱藏,待回到啟用狀態才會再顯示。
如要接收地圖互動回呼,您必須在地圖動作列中新增 Action.PAN
按鈕。使用者按下平移按鈕時,主機會進入平移模式,如下一節所述。
如果應用程式忽略地圖動作列中的 Action.PAN
的按鈕,就無法從 SurfaceCallback
方法收到使用者輸入內容,而且主機會結束先前啟用的平移模式。
如果是觸控螢幕,畫面上不會顯示平移按鈕。
平移模式
在平移模式下,使用者透過非觸控輸入裝置 (例如旋轉控制器和觸控板) 輸入的內容,會由範本主機轉譯成適當的 SurfaceCallback
方法。使用 NavigationTemplate.Builder
中的 setPanModeListener
方法,可在使用者進入或結束平移模式時做出反應。使用者處於平移模式時,主機可隱藏範本中的其他 UI 元件。
穩定區域
穩定區域會在閒置和啟用狀態之間進行更新。請根據穩定區域的大小,決定是否要繪製行車相關資訊,例如速度、速限或道路警告,避免地圖動作列擋住地圖中的重要資訊。
在導航畫面顯示快訊
Alert
會向駕駛人顯示重要資訊和選用動作,無須離開導航畫面。為了讓駕駛人享有最佳體驗,Alert
會在 NavigationTemplate
中運作,避免遮擋導航路徑,並盡量減少駕駛人分心的情況。
Alert
僅適用於 NavigationTemplate
。如要通知 NavigationTemplate
以外的使用者,請考慮使用抬頭通知 (HUN),詳情請參閱「顯示通知」。
舉例來說,使用 Alert
可執行以下動作:
- 告知駕駛人與目前導航相關的更新內容,例如路況變更。
- 詢問駕駛人與目前導航相關的更新,例如出現移動式測速照相機。
- 提出即將到來的任務,並詢問駕駛人是否要接受,例如駕駛人是否願意順路接送乘客。
Alert
的基本格式中包含標題和 Alert
時間長度。時間長度會以進度列顯示。您可以視需要新增副標題、圖示和最多兩個 Action
物件。

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.REASON_TIMEOUT
值呼叫AlertCallback.onCancel
方法,隨後呼叫AlertCallback.onDismiss
方法。如果駕駛人按一下其中一個動作按鈕,主機會依序呼叫
Action.OnClickListener
和AlertCallback.onDismiss
。如果不支援
Alert
,主機會呼叫含AlertCallback.REASON_NOT_SUPPORTED
值的AlertCallback.onCancel
。主機不會呼叫AlertCallback.onDismiss
,因為Alert
並未顯示。
設定快訊時長
選擇符合應用程式需求的 Alert
持續時長。導航 Alert
的建議時間長度為 10 秒。詳情請參閱「導覽快訊」。
顯示快訊
如要顯示 Alert
,請使用應用程式中的 CarContext
呼叫 AppManager.showAlert
方法。
// Show an alert
carContext.getCarService(AppManager.class).showAlert(alert)
- 使用
Alert
呼叫showAlert
時,如果alertId
與目前顯示的Alert
ID 相同,系統不會執行任何操作。Alert
不會更新。如要更新Alert
,必須使用新的alertId
重新建立快訊。 - 使用
Alert
呼叫showAlert
時,如果alertId
與目前顯示的Alert
ID 不同,系統會關閉目前顯示的Alert
。
關閉快訊
雖然 Alert
會因逾時或駕駛人互動而自動關閉,但在快訊資訊過時等時機,您也可以手動關閉 Alert
。如要關閉 Alert
,請使用 Alert
的 alertId
呼叫 dismissAlert
方法。
// Dismiss the same alert
carContext.getCarService(AppManager.class).dismissAlert(alert.getId())
如果使用與目前顯示的 Alert
不相符的 alertId
呼叫 dismissAlert
,系統不會執行任何動作,也不會擲回例外狀況。