Android Auto
この章ではAndroid Autoを使用するための方法を紹介します。
はじめに
Android Autoのナビゲーションアプリを構築するには、Google's documentation for building a navigation appをよく理解しておく必要があります。 独自の CarAppService、独自の minCarApiLevel を宣言し、独自の xml/automotive_app_desc を作成し、独自の自動車アプリ テーマを作成する必要があります。
AndroidManifestと権限設定
AndroidManifest.xmlのuses-permissionタグとapplicationタグに以下設定を追加します。
<!-- Get access to the surface -->
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE"/>
<!-- You must include this in order to use the NavigationTemplate -->
<uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES" />
<!-- Optional. You must include this in order to use the MapWithContentTemplate -->
<uses-permission android:name="androidx.car.app.MAP_TEMPLATES" />
<application
<!-- snip -->
>
<!-- You must add xml/automotive_app_desc -->
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />
<!-- Optional. Create a theme for your app -->
<meta-data
android:name="androidx.car.app.theme"
android:resource= "@style/CarAppTheme" />
<!-- You choose your minCarApiLevel -->
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1" />
<!-- Link to your implementation of CarAppService -->
<service
android:name=".YourCarAppService"
android:exported="true"
tools:ignore="ExportedService">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.NAVIGATION" />
<!-- Optional. If your app supports rendering on cluster displays, you must add an androidx.car.app.category.FEATURE_CLUSTER -->
<category android:name="androidx.car.app.category.FEATURE_CLUSTER"/>
</intent-filter>
</service>
</application>
app/build.gradleの設定
dependenciesに以下の内容を追加してください。
dependencies {
...
// version can change
+ implementation 'androidx.car.app:app:1.4.0'
+ implementation "androidx.car.app:app-projected:1.4.0"
}
AndroidAutoの起動処理
Android Autoの起動検出からinitializeまでについて説明します。
Android Autoは専用のCarAppServiceクラスを起点に動作するため、まずはこのクラスを用意します。
public class YourCarAppService extends CarAppService {
@NonNull
@Override
public HostValidator createHostValidator() {
return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR;
}
@NonNull
@Override
public Session onCreateSession() {
return new YourSession();
}
}
次にSessionを用意します。Sessionクラスでは画面を扱うScreenクラスを生成して返却する必要があります。
public class YourSession extends Session {
@NonNull
@Override
public Screen onCreateScreen(@NonNull Intent intent) {
return new YourScreen(getCarContext());
}
}
最後にScreenを用意します。CarContextとLifecycleを渡してCarMapを生成し、CarMap.initialize()で初期化を行います。
初期化時に設定が必要な項目は、スマートフォン用地図の初期化時設定項目と同じです。
initializeでの初期化完了(onInitializationCompleted受信)後にgetMap()してMapクラスが使用可能になります。
public class YourScreen extends Screen {
private CarMap carMap;
private Map map;
protected YourScreen(@NonNull CarContext carContext) {
super(carContext);
// CarMap生成
carMap = new CarMap(carContext, getLifecycle());
MapSetting mapSetting = new MapSetting();
mapSetting.setServerSettingInfo(createServerSettingInfo());
// CarMap初期化
carMap.initialize(mapSetting, new OnMapEventListener() {
@Override
public void onInitializationCompleted(ErrorCode errorCode) {
if (errorCode == ErrorCode.NONE) {
map = carMap.getMap();
Navi.getInstance().attach(map);
...
}
}
});
...
}
@Override
public Template onGetTemplate() {
...
}
}
Android AutoではMapクラスの一部API(Gesture関連等)は使用できません。
詳細については、API Referenceをご確認ください。
Android Auto画面の監視
CarMap.addOnCarMapObserver()でCarMapObserverを追加することで、SurfaceCallbackの画面表示に関する通知を受け取ることができます。
また、追加したCarMapObserverはCarMap.removeOnCarMapObserver()で削除が可能です。
| 検出する関数 | 動作 |
|---|---|
onAttached() | Surfaceが読み込まれたときに呼び出されます。 |
onDetached() | Surfaceがこのオブザーバーから切り離されたときに呼び出されます。 |
onVisibleAreaChanged() | Surfaceの可視領域を更新するときに呼び出されます。 たとえば、アクションボタンが表示されたり消えたりしたときにトリガーされます。 |
onStableAreaChanged() | Surfaceの安定領域を更新するときに呼び出されます。 この領域は一定のままですが、ビューが表示されたり表示されなくなったりすると表示領域が変化します。 |
これは例えば以下のような用途で使用できます。
onVisibleAreaChanged()が呼び出された時、自車位置のpadding値や各種デザインのオフセット値を更新する。
SDK内部でAppManager.setSurfaceCallbackを使用しており、これは単一のサーフェスコールバックがあることを前提としています。
そのため、アプリ側でsetSurfaceCallback を使用しないでください。
Android Auto地図の操作
CarMap.setGestureHandler()でCarMapGestureHandlerを設定することで、SurfaceCallbackの地図操作(ジェスチャー)に関する通知を受け取ることができます。
また、CarMapGestureHandlerをnullに設定することで、地図操作を無効化できます。
操作に対応する関数と動作は以下の通りです。
| 操作 | 呼び出される関数 | 動作 |
|---|---|---|
| タップ | onClick() | 地図クリック |
| スクロール | onScroll() | 地図移動 |
| フリック | onFling() | 地図移動 |
| ダブルタップ | onScale() | ズームイン |
| ピンチイン | onScale() | ズームアウト |
| ピンチアウト | onScale() | ズームイン |
| クイックズーム ※gesture_controlのクイックズームに 操作方法詳細があります | onScale() | ズームイン/アウト |
Android端末のジェスチャー動作はMapGestureOptionsでジェスチャー種別を検出していますが、AndroidAutoでは検出方法が異なるため、MapGestureOptionsにある回転動作やチルト動作は出来ません。
ウィジェット
画面上の任意の位置に任意の画像を配置可能です。これをウィジェット(Widget)と呼びます。
アプリで好きなウィジェットを表示する場合はBitmapWidgetでアイコンや位置の設定をしてCarMap.addWidget()で配置が可能です。
また、追加したウィジェットはCarMap.updateWidget()で更新、CarMap.removeWidget()で削除が可能です。
// 任意のウィジェット追加
BitmapWidget bitmapWidget = new BitmapWidget(BitmapFactory.decodeResource(carMap.getCarContext().getResources(), R.drawable.widget));
WidgetPosition bitmapPosition = new WidgetPosition(mapWidth, mapHeight);
bitmapPosition.setHorizontalAlignment(WidgetPosition.Horizontal.LEFT);
bitmapPosition.setVerticalAlignment(WidgetPosition.Vertical.BOTTOM);
bitmapWidget.setPosition(bitmapPosition); // WidgetPositionで位置指定
carMap.addWidget(bitmapWidget);
// 任意のウィジェットの画像と位置を更新
bitmapWidget.updateBitmap(bitmap_change)
bitmapWidget.setPosition(new PointF(100, 100)); // Screen座標で位置指定
carMap.updateWidget(bitmapWidget);
// 任意のウィジェット削除
carMap.removeWidget(bitmapWidget);
終了処理
Android Auto切断時、Naviにattachされたmapをdetach(Navi.detach(map))し、CarMapの終了処理CarMap.terminate()を実行し正常に終了させてください。