駐車時向けアプリに Android Automotive OS のサポートを追加する

Android Automotive OS デバイスにアプリを配信する際は、フォーム ファクタに固有の考慮事項があります。このガイドでは、これらの考慮事項について説明します。

Android Automotive OS エミュレータで既存のアプリをテストする

Android Automotive OS 用のアプリを作成するには、まず Android Automotive OS エミュレータで既存のアプリをテストします。エミュレータをセットアップするには、Android Automotive OS エミュレータを使用してテストするの手順に沿って行ってください。その後、エミュレータでアプリを実行するの手順に沿ってアプリを実行します。

アプリを実行するときは、次のような互換性の問題に注意します。

  • インフォテインメント画面は向きが固定されています。自動車向けアプリの品質に関するガイドラインに沿って、アプリは縦向きと横向きの両方をサポートする必要があります。
  • 他のデバイスで利用可能な API が Android Automotive OS では利用できない場合があります。たとえば、一部の Google Play 開発者サービス API は Android Automotive OS では利用できません。こうした問題に対処する方法について詳しくは、機能を無効にするセクションをご覧ください。

アプリのマニフェスト ファイルを構成する

Android Automotive OS デバイスをターゲットにするには、アプリに特定のマニフェスト エントリが必要です。Android Automotive OS デバイスへの配信を有効にすると、Google Play は互換性のあるアプリを審査し、車で安全に使用できることを確認します。詳しくは、自動車に配布するをご覧ください。

必須の Android Automotive OS の機能

Android Automotive OS 向けにビルドされたアプリは、Google Play を使用して配信されるために、特定の要件を満たしている必要があります。詳しくは、Google Play の機能要件を満たすをご覧ください。

カテゴリ固有のマニフェスト エントリ

駐車中のすべてのアプリに適用される上記の要件に加えて、動画とゲームのカテゴリには追加の要件があります。

ドライバーの注意散漫に関する要件を満たす

アプリを車に導入する際は、運転中の注意散漫を避けることが重要です。駐車時向けアプリの場合、これは主に、DD-2DD-3 の品質に関するガイドラインで規定されているように、ユーザー エクスペリエンス(UX)の制限が有効な間はアプリの使用や音声の再生を禁止することで実現されます。

ユーザー エクスペリエンスの制限が有効な間は使用できないようにする

デフォルトでは、UX 制限が有効になっている間は、アクティビティを使用または起動できません。この動作がアプリに適用されるようにするには、マニフェスト内の <activity> 要素に次の <meta-data> 要素を含めないでください。

<!-- NOT ALLOWED -->
<meta-data
  android:name="distractionOptimized"
  android:value="true"/>

UX 制限が有効になったときにアプリのアクティビティが再開されると、OS が所有するアクティビティによって隠されます。

少なくとも、アプリのアクティビティは一時停止ライフサイクル状態に移行します。これは onPause ライフサイクル コールバックとして発生し、その間はアプリでの動画と音声の再生をともに一時停止する必要があります。

Android Automotive OS 互換モードが搭載されているデバイスでは、システムのブロックにより、アプリのアクティビティが一時停止状態から停止状態に移行します。

再生を停止し、再生の再開を防止する

一部のアプリでは、onPause() 中に再生を一時停止し、onResume() まで再生が再開されないように状態を追跡することで、運転中の注意散漫に関する要件を満たすことができます。

ライフサイクル コールバックへの対応がアプリにとって十分でない場合は、次のセクションで説明するように、UX 制限状態を直接リッスンできます。たとえば、ピクチャー イン ピクチャーをサポートするアプリは、ライフサイクル コールバックで条件チェックを行うのではなく、直接リッスンすることを好むかもしれません。

ユーザー エクスペリエンス制限をリッスンする

UX 制限をリッスンするには、まずアプリ モジュールの build.gradle ファイルで android.car ライブラリへの依存関係を追加します。これは、Android Automotive OS 固有の API を提供する Android SDK の拡張機能です。

android {
    ...
    useLibrary("android.car")
}

CarUxRestrictionsManager を使用して UX 制限の状態を読み取ります。UX 制限は車両内のディスプレイごとに異なる可能性があるため、ギアや速度などの他のハードウェア状態から UX 制限の状態を判断しようとしないでください。

val car = Car.createCar(context) ?: return
val carUxRestrictionsManager =
    car.getCarManager(Car.CAR_UX_RESTRICTION_SERVICE) as? CarUxRestrictionsManager ?: return

// You can either read the state directly ...
val currentUxRestrictions = carUxRestrictionsManager.currentCarUxRestrictions

// or listen to state changes
carUxRestrictionsManager.registerListener { carUxRestrictions: CarUxRestrictions ->
    // Handle UX restrictions
}

// Don't forget to teardown and release resources when they're no longer needed
carUxRestrictionsManager.unregisterListener()
car.disconnect()

アプリが参照する CarUxRestrictions によって提供される値は、isRequiresDistractionOptimization の戻り値のみです。他の値は、注意散漫を抑えるように最適化されたアクティビティにのみ関連します。

実装をテストする

次の手順で、アプリがドライバーの注意散漫に関する要件を満たしていることを検証します。

  1. Google Play ストアまたは互換モードのないシステム イメージにアプリをインストールします。
  2. ランチャー アプリグリッドを開き、運転をシミュレートして、アプリを開けないことを確認します。
  3. 運転のシミュレーションを停止し、アプリを開いて再生画面を表示して再生を開始します。
  4. 運転を再度シミュレートし、再生が一時停止することを確認します。
    1. アプリが MediaSession との統合をサポートしている場合は、adb shell cmd media_session dispatch play を使用して、再生が再開されないことを確認します。

Android Automotive OS 用のアプリを最適化する

車内で最高のユーザー エクスペリエンスを提供するために、Android Automotive OS 用のアプリをビルドする際は、次の点に注意してください。

ウィンドウ インセットとディスプレイ カットアウトを使用する

他のフォーム ファクタと同様に、Android Automotive OS には、ステータスバーやナビゲーション バーなどのシステム UI 要素が含まれており、非矩形ディスプレイをサポートしています。

デフォルトでは、アプリはシステムバーやディスプレイ カットアウトと重ならない領域に描画を行います。ただし、ウィンドウ インセット内でアプリを配置するで説明されているように、アプリでシステムバーを非表示にしたり、システムバーの背後にコンテンツを描画したり、ディスプレイ カットアウトにコンテンツを表示したりすることもできます。アプリが上記のいずれかを行う場合は、Android Automotive OS デバイスのエコシステム全体でアプリを適切に動作させる方法の詳細について、以降のサブセクションをご覧ください。

システムバー、没入モード、エッジ ツー エッジのレンダリング

自動車のシステムバーは、サイズと配置が他のフォーム ファクタとは異なる場合があります。たとえば、ナビゲーション バーを画面の左側、右側、下部に配置できます。ほとんどのスマートフォンやタブレットのように、上部にステータスバー、下部にナビゲーション バーがある場合でも、自動車ではこれらの要素のサイズがはるかに大きくなる可能性があります。

また、Android Automotive OS では、アプリが没入モードの開始と終了に合わせてシステムバーの表示と非表示を切り替えられるかどうかを OEM が制御できます。たとえば、OEM は、アプリがシステムバーを非表示にできないようにして、空調などの車両制御に常に画面からアクセスできるようにすることができます。アプリによるシステムバーの制御を OEM が禁止している場合、アプリがWindowInsetsController(またはWindowInsetsControllerCompat) API を呼び出しても何も起こりません。アプリがインセットを変更できたかどうかを検出する方法については、showhide のドキュメントをご覧ください。

同様に OEM は、システムバーの色と透明度をアプリが設定できるかどうかを制御して、システムバーとそこに含まれる要素が常に明確に表示されるようにすることもできます。アプリがエッジ ツー エッジで描画する場合は、重要でないコンテンツのみがシステムバーの背後に描画されるようにします。デバイスの OEM がシステムバーの色や透明度の設定を許可しない場合、このコンテンツは表示されないことがあります。

<!-- Depending on OEM configuration, these style declarations
     (and the corresponding runtime calls) may be ignored -->
<style name="...">
  <item name="android:statusBarColor">...</item>
  <item name="android:navigationBarColor">...</item>
  <item name="android:windowTranslucentStatus">...</item>
  <item name="android:windowTranslucentNavigation">...</status>
</style>

アプリをエッジ ツー エッジで表示する場合は、システムバーのサイズ、数、タイプ、位置について想定しないでください。代わりに、ウィンドウ インセットの API を使用して、システムバーを基準として相対的にアプリのコンテンツを配置します。これらの API の使用方法について詳しくは、アプリ内でコンテンツをエッジ ツー エッジで表示するをご覧ください。パディング値のハードコードはどのフォーム ファクタでも推奨されませんが、自動車ではセーフエリアにコンテンツを保持するのにまったく機能しない可能性があります。

不規則な形状のディスプレイに適応する

ディスプレイは長方形のものだけでなく、車両によっては図 1 に示すように不規則な形状の画面もあります。

右側が湾曲したディスプレイを備えた Android Automotive OS デバイス。
図 1: ディスプレイの右側が湾曲した形状の Android Automotive OS デバイス。緑色の領域は、曲線のディスプレイ カットアウトの境界ボックスと重ならない安全な長方形です。

アプリがエッジ ツー エッジでレンダリングしない場合、セーフエリア内でレンダリングするために何かをする必要はありません。

アプリがエッジ ツー エッジでレンダリングする場合は、ディスプレイ カットアウトに関する動作を選択できます。リソースを使用してこれを実現するには、アプリのテーマandroid:windowLayoutInDisplayCutoutMode 属性を設定するか、実行時にウィンドウの layoutInDisplayCutoutMode 属性を変更します。

Android Automotive OS デバイスでのディスプレイ カットアウトの種類はモバイル デバイスのものとは異なるため、LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT または LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES は使用しないでください。これらはモバイル デバイスのカットアウトに合わせて動作が最適化されています。代わりに、LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER または LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS を使用して、常にカットアウトを回避するか、常にカットアウトに入るようにします。後者を選択する場合は、ディスプレイ カットアウトをサポートするで、ディスプレイ カットアウトに関連する API の詳細をご覧ください。

ディスプレイ カットアウト領域にレンダリングするアプリで、この動作を Android Automotive OS とモバイルで異なるものにする場合、実行時にアプリでこの動作を設定するなら機能を無効にするを、アプリがリソース ファイルを使用してこの動作を設定するなら代替リソースを使用するをご覧ください。

機能を無効にする

既存のモバイルアプリを Android Automotive OS で利用できるようにしている場合、一部の機能は関連性を持たないか、使用できない場合があります。たとえば一般的に、車ではカメラへのアクセスを提供していません。また、Android Automotive OS では Google Play 開発者サービスのサブセットのみを使用できます。詳しくは、自動車用の Google Play 開発者サービスをご覧ください。

PackageManager.hasSystemFeature API を使用すると、次の例で示すとおり、FEATURE_AUTOMOTIVE 機能を確認することで、アプリが Android Automotive OS で実行されているかどうかを検出できます。

val isCar = packageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)
if (isCar) {
    // Enable or disable a given feature
}

または、アプリに Android Auto コンポーネントも含まれる場合には、自動車向け Android アプリ ライブラリCarConnection API を使用して、アプリが Android Automotive OS または Android Auto で実行されているか、もしくは車にまったく接続されていないかを検出できます。

ピクチャー イン ピクチャー(PIP)については、実績のあるベスト プラクティスに沿って、この機能が利用可能かどうかを確認し、適切に対応します。

オフラインのシナリオに対応する

インターネットに接続されている車が増えていますが、次に示すように、アプリはインターネット接続がない状態で実行することをおすすめします。

  • ユーザーは、自動車メーカーが定期購入パッケージの一部として提供しているモバイルデータをオプトアウトする場合があります。
  • 一部の地域ではモバイルデータへのアクセスが制限される場合があります。
  • Wi-Fi 無線通信のある自動車でも、Wi-Fi の通信範囲外にある場合や、OEM がモバイル ネットワークを優先して Wi-Fi をオフにしている場合があります。

アプリがこのようなシナリオに対応できるように、オフライン コンテンツを提供するなどして、インターネット アクセスに依存する機能のグレースフル デグラデーションを行ってください。詳しくは、ネットワークを最適化するためのおすすめの方法をご覧ください。

代替リソースを使用する

Android Automotive OS 車両で動作させる場合、アプリを自動車に適応させるために、car リソース修飾子を使用して代替リソースを指定できます。たとえば、ディメンション リソースを使用してパディング値を格納する場合は、より大きな値を car リソースセットに指定して、タップ ターゲットを大きくすることができます。