建構導航應用程式

本節詳細介紹程式庫的不同功能,您可以利用這些功能為即時路線導航應用程式實作各項功能。

在資訊清單中宣告導航支援

導航應用程式必須在 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.onCreateScreenSession.onNewIntent 中的 CarContext.ACTION_NAVIGATE 意圖。

如要進一步瞭解意圖格式,請參閱 CarContext.startCarApp 詳細說明文件。

存取導航範本

導航應用程式可以存取專為導航應用程式設計的以下專用範本。這些範本能在背景中顯示途徑,使應用程式可存取以繪製地圖,並會顯示其他由應用程式提供的資訊,但這些會依範本而各有不同。

如要瞭解如何運用這些範本來設計導航應用程式的使用者介面,請參閱《車輛專用 Android App Library 設計指南》。

為存取導航範本,應用程式必須在其 AndroidManifest.xml 中宣告 androidx.car.app.NAVIGATION_TEMPLATES 權限:

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

繪製地圖

導航應用程式可以存取 Surface,以在相關範本中繪製地圖。

然後可設定 SurfaceCallback 執行個體 為 AppManager 車輛服務以存取 SurfaceContainer 物件:

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,在使用者有一段時間沒有與畫面互動時,就會隱藏該操作列以為地圖提供更多空間。在這種情況下,系統會使用相同矩形回呼 onStableAreaChangedonVisibleAreaChanged。隱藏操作列時,系統只會使用較大區域呼叫 onVisibleAreaChanged。如果使用者與畫面互動,系統只會使用第一個矩形呼叫 onVisibleAreaChanged

深色模式

當主機判定條件可提供擔保時,導航應用程式必須使用適當的深色顏色在 Surface 上重畫其地圖,如《Android Auto 應用程式品質指南》所述。

如要判斷是否應繪製深色地圖,您可以使用 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.setListener 提供的 NavigationManagerListener 物件中呼叫 stopNavigation。然後應用程式在叢集顯示、導航通知和語音導引中停止發送下一個轉彎的資訊。

行程資訊

啟用導航期間,應用程式應呼叫 NavigationManager.updateTrip。此呼叫中提供的資訊將用於車輛的叢集和看路提醒顯示。視駕駛的特定車輛而定,並非所有資訊都會向使用者顯示。舉例來說,電腦版車用運算主機會顯示已新增至 TripStep,但不會顯示 Destination 資訊。

為了要測試資訊是否送達叢集,電腦版車用運算主機可以設定危險是簡易叢集顯示。請使用以下內容建立 cluster.ini 檔案:

[general]
instrumentcluster = true

然後您可以使用其他指令列參數叫用 DHU:

dhu -c cluster.ini

行車路線導航

即時路線 (TBT) 導航指示可透過經常更新的導航通知提供。為了在汽車螢幕上順利顯示導航通知,通知建構工具必須執行下列操作:

  1. 使用 NotificationCompat.Builder.setOngoing 方法,將通知標示為進行中。
  2. 將通知的類別設為 Notification.CATEGORY_NAVIGATION
  3. 使用 CarAppExtender 擴充通知。

導航通知會在車輛螢幕底部的邊欄工具中顯示。如果通知的重要性等級設為 IMPORTANCE_HIGH,則也會顯示為看路提醒通知 (HUN)。如果沒有使用 CarAppExtender.Builder.setImportance 方法設定重要性,系統就會使用通知管道的重要性

應用程式可設定 CarAppExtender 中的 PendingIntent,並在使用者輕觸 HUN 或邊欄小工具時傳送至應用程式。

如果使用 true 值呼叫 NotificationCompat.Builder.setOnlyAlertOnce,則重要性極高的通知只會在 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) 的形式顯示通知。應用程式可使用 CarAppExtender.Builder.setImportance 方法設定通知的重要性,藉以控 HUN 的行為。將重要性設為 IMPORTANCE_HIGH 即會顯示 HUN,如將其設為任何其他值,將只會更新邊欄小工具。

語音導航

若要透過車輛音響播放語音導航,應用程式必須要求音訊焦點。做為 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 助理叫用導航指令,或其他應用程式傳送意圖以開始導航時,應用程式就會接收導航意圖

允許使用者與地圖互動

從 Car App API 級別 2 開始,您就可以在 NavigationTemplate 中新增地圖縮放及平移功能,方便使用者查看地圖的其他區塊。

SurfaceCallback 方法

SurfaceCallback 有三種回呼方法,可讓您將地圖互動功能加入NavigationTemplateonScaleonScroll 以及 onFling。請參閱下表以瞭解這些回呼與使用者互動之間的關係。

互動 SurfaceCallback 方法
雙指撥動 (縮放) onScale
單點觸控拖曳 onScroll
單點觸控滑動 onFling
輕觸兩下 onScale (由範本主機決定縮放比例係數)
平移模式的旋轉自動提醒 onScroll (由範本主機決定的距離係數)

地圖動作序列

NavigationTemplate 可以有地圖操作列,以執行地圖相關的動作,例如:縮放大小、重新置中對齊、指南針,或任何其他應用程式可以選擇顯示的功能。地圖操作列最多可有四個純圖示按鈕,這些按鈕可重新整理,並且不影響工作深度。如同導航操作列,沒有進行中的活動時,閒置地圖操作列會自動隱藏。

如要接收地圖互動回呼,您必須在地圖操作列中新增 Action.PAN 按鈕。如果應用程式忽略 Action.PAN 地圖操作列的按鈕,您將不會從 SurfaceCallback 方法收到使用者輸入內容,而且主機會結束先前已啟用的平移模式。只要點按平移按鈕,主機即進入平移模式。如果是觸控螢幕,則不會顯示平移按鈕。

平移模式

在平移模式下,使用者透過非觸控輸入裝置 (例如旋轉控制器和觸控板) 輸入的內容,會由範本主機轉譯成適當的 SurfaceCallback 方法。使用 NavigationTemplate Builder 中的 setPanModeListener 方法,可對使用者進入或結束平移模式時做出反應。使用者處於平移模式時,主機會隱藏範本中的其他 UI 元件。

穩定區域

穩定區域會在閒置和啟用狀態之間進行更新。導航應用程式應繪製合乎穩定區域大小的行車相關資訊,以便顯示速度、速限或道路警告等重要資訊,且避免遭到地圖操作列遮住。