このセクションでは、ターンバイターン方式のナビゲーション アプリの機能を実装するための、ライブラリの各機能について詳しく説明します。
マニフェストでナビゲーション サポートを宣言する
ナビゲーション アプリでは、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
: 地図を表示します。必要に応じて、アクティブなナビゲーション中に、情報メッセージ、経路案内、所要時間も表示します。PlaceListNavigationTemplate
: 場所のリストを表示します。これらの場所に対応するマーカーを地図上に描画できます。RoutePreviewNavigationTemplate
: 経路のリストを表示します。これらの経路のひとつを選択して、地図上でハイライト表示できます。
これらのテンプレートを使用してナビゲーション アプリのユーザー インターフェースを設計する方法について詳しくは、自動車向け Android アプリ ライブラリの設計ガイドラインをご覧ください。
ナビゲーション テンプレートにアクセスするには、アプリは AndroidManifest.xml
で androidx.car.app.NAVIGATION_TEMPLATES
権限を宣言する必要があります。
<uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES"/>
地図の描画
ナビゲーション アプリは、適用するテンプレート上で地図を描画するために Surface
にアクセスできます。
SurfaceContainer
オブジェクトにアクセスするには、SurfaceCallback
インスタンスを AppManager
自動車サービスに設定します。
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
SurfaceCallback
は、SurfaceContainer
が利用可能な場合のコールバックのほか、Surface
のプロパティが変更された場合の他のコールバックを提供します。
サーフェスにアクセスするには、アプリは 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
のみが再度呼び出されます。
ダークモード
条件が満たされているとホストが判断した場合、ナビゲーション アプリは、Android Auto アプリの品質に関するガイドラインの説明のとおり、適切な暗い色を使用して Surface
インスタンスに地図を再描画する必要があります。
暗い地図を描くかどうかを決定するには、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
を呼び出す必要があります。この呼び出しで提供される情報は、車のクラスタとヘッドアップ ディスプレイで使用されます。運転中の車によっては、一部の情報がユーザーに表示されない場合があります。たとえば、デスクトップ ヘッドユニットには、Trip
に追加された Step
は表示されますが、Destination
情報は表示されません。
情報がクラスタに到達しているかどうかをテストするため、簡単なクラスタ表示を行うようにデスクトップ ヘッドユニット(DHU)ツールを構成できます。次の内容の cluster.ini
ファイルを作成します。
[general]
instrumentcluster = true
その後、コマンドライン パラメータを追加して DHU を呼び出すことができます。
dhu -c cluster.ini
ターンバイターン通知
頻繁に更新されるナビゲーション通知とともに、ターンバイターン(TBT)方式のナビゲーション指示を提供できます。車の画面でナビゲーション通知として処理されるようにするには、通知ビルダーで以下を行う必要があります。
NotificationCompat.Builder.setOngoing
メソッドを使用して、通知を進行中としてマークします。- 通知のカテゴリを
Notification.CATEGORY_NAVIGATION
に設定します。 CarAppExtender
を使用して通知を拡張します。
ナビゲーション通知は車の画面下部にあるレール ウィジェットに表示されます。通知の重要度レベルが IMPORTANCE_HIGH
に設定されている場合は、ヘッドアップ通知(HUN)としても表示されます。CarAppExtender.Builder.setImportance
メソッドで重要度が設定されていない場合は、通知チャンネルの重要度が使用されます。
アプリは、ユーザーが HUN またはレール ウィジェットをタップしたときにアプリに送信される PendingIntent
を CarAppExtender
で設定できます。
値を true
に指定して NotificationCompat.Builder.setOnlyAlertOnce
が呼び出された場合、重要度の高い通知は HUN で 1 回だけアラートを送信します。
次のスニペットは、ナビゲーション通知を作成する方法を示しています。
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 では、デフォルトのナビゲーション自動車アプリは、ユーザーが最後に起動したナビゲーション アプリに対応します。たとえば、ユーザーがアシスタントを介してナビゲーション コマンドを呼び出した場合や、他のアプリからナビゲーションを開始するためにインテントを送信すると、このアプリがナビゲーション インテントを受信します。
ユーザーに地図の操作を許可する
自動車向けアプリの API レベル 2 以降では、NavigationTemplate
で地図にズームとパンを追加することで、地図のさまざまな部分をユーザーに表示できます。
SurfaceCallback メソッド
SurfaceCallback
には、NavigationTemplate
に地図のインタラクティブ機能を追加するためのコールバック メソッドが 3 つあります(onScale
、onScroll
、onFling
)。
これらのコールバックとユーザーの操作との関連については、次の表をご覧ください。
操作 | SurfaceCallback メソッド |
---|---|
ピンチ(ズーム) | onScale |
シングルタップ ドラッグ | onScroll |
シングルタップ フリング | onFling |
ダブルタップ | onScale (テンプレート ホストによってスケーリング ファクタが決定される) |
パンモードの回転ナッジ | onScroll (テンプレート ホストによって距離ファクタが決定される) |
マップ アクション ストリップ
NavigationTemplate
では、地図に関連する操作(拡大 / 縮小、センタリング、コンパスの表示など、アプリで可能にする操作)に対応する、マップ アクション ストリップを設定できます。マップ アクション ストリップには、タスクの階層を変更することなく更新できる、アイコンのみのボタンを 4 つまで設定できます。アクション ストリップと同様に、マップ アクション ストリップはアイドル状態には非表示になり、アクティブ状態になると表示されます。
マップ インタラクティビティ コールバックを受け取るようにするには、マップ アクション ストリップに Action.PAN
ボタンを追加する必要があります。アプリのマップ アクション ストリップに Action.PAN
ボタンを設定しないと、SurfaceCallback
メソッドからユーザー入力を取得できず、ホストで有効になっていたパンモードが終了します。ユーザーがパンボタンを押すと、ホストがパンモードに切り替わります。パンボタンはタッチスクリーンには表示されません。
パンモード
パンモードでは、ノンタップの入力デバイス(ロータリー コントローラやタッチパッドなど)からのユーザー入力が、テンプレート ホストによって適切な SurfaceCallback
メソッドに変換されます。パンモードを開始または終了するユーザー操作に応答するには、NavigationTemplate
Builder
の setPanModeListener
メソッドを使用します。ユーザーがパンモードになっている間は、他の UI コンポーネントを非表示にできます。
安定領域
安定領域は、アイドル状態とアクティブ状態の間に更新されます。アプリで速度、速度制限、道路警告などの運転関連の情報を表示させる場合は、地図上の重要な情報がマップ アクション ストリップによって遮られないように、安定領域のサイズに応じて情報が取得されるようにします。