自動車向け Android アプリ ライブラリ ナビゲーション、スポット(POI)、モノのインターネット(IoT) 車載アプリなどです そのために、ドライバーの注意散漫に対応するよう設計された一連のテンプレートを提供しています。 車の画面要素に関するさまざまな要素や 細かい条件に基づいて 入力モダリティがあります。
このガイドでは、ライブラリの主な機能とコンセプトの概要を説明し、 基本的なアプリを設定するプロセスを順を追って説明します。
始める前に
- 運転に適したデザインを確認する
自動車向けアプリ ライブラリを扱うページ
<ph type="x-smartling-placeholder">
- </ph>
- ナビゲーション アプリ およびその他の運転関連アプリ カテゴリの概要
- テンプレートを使用してアプリを構築するの概要
- 構成要素 テンプレートとテンプレート コンポーネントをカバーしている
- フローの例 一般的な UX パターンのデモンストレーション
- テンプレート化されたアプリの要件
- 次の主な用語とコンセプトを確認する 。
- Android Auto システムについて十分に理解してください UI Android Automotive OS 設計をご覧ください。
- リリースノートを確認してください。
- サンプルを確認してください。
主な用語と概念
- モデルとテンプレート
- ユーザー インターフェースは、モデル オブジェクトのグラフで表現され、 所属しているテンプレートで許可されるように、さまざまな方法で構成されている できます。テンプレートはモデルのサブセットであり、 分析できますモデルには、 属性の形式を使用して、インフラストラクチャの 情報の外観(例: テキストの色、画像) あります。ホストはモデルを、次の要件を満たすように設計されたビューに変換します。 ドライバーの注意散漫に関する基準と 車載画面の要素と入力モダリティです。
- ホスト
- ホストは、提供される機能を実装するバックエンド コンポーネントです。 ライブラリの API によって制御されるため、車内でアプリを実行できます。「 アプリの検出から管理まで、ホストが担う責任は モデルをビューに変換してアプリに通知するまで、ライフサイクルが モニタリングします。モバイル デバイスでは、このホストは Android によって実装されます。 自動。Android Automotive OS では、このホストはシステムアプリとしてインストールされます。
- テンプレートの制限事項
- テンプレートに応じて、そのモデルのコンテンツに制限が課されます。対象 たとえば リストテンプレートでは 追加可能なアイテム数に 表示されます。テンプレートには、作成方法に関する制限があります。 タスクのフローを形成します。たとえば、アプリは 最大 5 つのテンプレートを画面スタックに追加できます詳しくは、 テンプレートの制限をご覧ください。
Screen
Screen
は ユーザーに提示されるユーザー インターフェースを管理するためにアプリが実装するライブラリ できます。Screen
には、 ライフサイクルを提供し、 画面が表示されたときに表示するテンプレートを送信します。Screen
個のインスタンスを push できます。Screen
スタックとの間でポップされ、 確実に遵守し、 テンプレート フローの制限。CarAppService
CarAppService
は アプリが作成する、Service
の抽象クラス ホストで検出および管理できるように、実装とエクスポートを行う必要がある。 アプリのCarAppService
: 使用してホスト接続が信頼できるかどうかを検証する責任はcreateHostValidator
その後にSession
を指定します。 使用して各接続のインスタンスをonCreateSession
。Session
Session
は、Pod を 実装して返す必要があります。CarAppService.onCreateSession
。 車の画面に情報を表示するためのエントリ ポイントとして機能します。これは、 ライフサイクルにより アプリの現在の状態(アプリが動作している状態など)を 表示または非表示になります。次のような
Session
が開始されると、 アプリが最初に起動されるとき、ホストは最初のScreen
を使用して、onCreateScreen
メソッドを呼び出します。
自動車向けアプリ ライブラリをインストールする
Jetpack ライブラリを確認する リリースページ アプリにライブラリを追加する手順
アプリのマニフェスト ファイルを構成する
自動車向けアプリを作成する前に、アプリの マニフェスト ファイルを以下のように変更します。
CarAppService を宣言する
ホストは、以下を介してアプリに接続します。
CarAppService
の実装。マイページ
マニフェストでこのサービスを宣言して、ホストが検出と接続を行えるようにします。
追加できます
また、アプリのインテント フィルタの <category>
要素でアプリのカテゴリを宣言する必要もあります。詳しくは、
サポートされているアプリのカテゴリ
この要素を使用します。
次のコード スニペットは、 次のようにしてマニフェストに追加します。
<application>
...
<service
...
android:name=".MyCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService"/>
<category android:name="androidx.car.app.category.POI"/>
</intent-filter>
</service>
...
<application>
サポートされているアプリのカテゴリ
次のカテゴリを 1 つ以上追加して、アプリのカテゴリを宣言します
次のように CarAppService
を宣言した場合のインテント フィルタの値。
(前のセクション)をご覧ください。
androidx.car.app.category.NAVIGATION
: ターンバイターン方式を提供するアプリ ルート案内を利用できます。 自動車向けナビゲーション アプリを作成するをご覧ください を参照してください。androidx.car.app.category.POI
: 関連する機能を提供するアプリ 駐車場、充電スタンド ガソリンスタンドチェックアウト 自動車向けスポットアプリを作成する: 追加のドキュメントをご覧ください。androidx.car.app.category.IOT
: ユーザーが関連性のあるトピックを コネクテッド デバイスで車内から操作できます。チェックアウト 自動車向けモノのインターネット アプリを作成し、 追加のドキュメントをご覧ください。
詳しくは、自動車向け Android アプリの品質をご覧ください。 各カテゴリの詳細な説明と、そのカテゴリに属するアプリの条件。
アプリの名前とアイコンを指定する
ホストがシステム UI でアプリを表すために使用するアプリ名とアイコンを指定する必要があります。
アプリを表すために使用するアプリ名とアイコンを指定するには、
label
と
icon
個の属性
CarAppService
:
...
<service
android:name=".MyCarAppService"
android:exported="true"
android:label="@string/my_app_name"
android:icon="@drawable/my_app_icon">
...
</service>
...
ラベルまたはアイコンが
<service>
要素: ホスト
ルールに指定された値に
<application>
要素。
カスタムテーマを設定する
自動車向けアプリのカスタムテーマを設定するには、
<meta-data>
要素:
次のように指定します。
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
次に、スタイル リソースを宣言します。 自動車向けアプリのカスタムテーマには、次の属性を設定します。
<resources> <style name="MyCarAppTheme"> <item name="carColorPrimary">@layout/my_primary_car_color</item> <item name="carColorPrimaryDark">@layout/my_primary_dark_car_color</item> <item name="carColorSecondary">@layout/my_secondary_car_color</item> <item name="carColorSecondaryDark">@layout/my_secondary_dark_car_color</item> <item name="carPermissionActivityLayout">@layout/my_custom_background</item> </style> </resources>
自動車向けアプリの API レベル
自動車向けアプリ ライブラリは独自の API レベルを定義しているため、
車両のテンプレート ホストでサポートされているライブラリ機能。
ホストでサポートされている自動車向けアプリの最も高い API レベルを取得するには、
getCarAppApiLevel()
メソッドを呼び出します。
アプリがサポートする自動車向けアプリの最小 API レベルを
AndroidManifest.xml
ファイル:
<manifest ...>
<application ...>
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1"/>
</application>
</manifest>
詳細については、
RequiresCarApi
アノテーションを使用して、下位互換性を維持し、
機能を使用するために必要な最小 API レベル。どの API の定義が
自動車向けアプリ ライブラリの特定の機能を使用するには、
参照ドキュメント
CarAppApiLevels
。
CarAppService とセッションを作成する
アプリは
CarAppService
クラスと実装
onCreateSession
メソッドが呼び出されます。このメソッドは Session
を返します。
インスタンスを実行します。
Kotlin
class HelloWorldService : CarAppService() { ... override fun onCreateSession(): Session { return HelloWorldSession() } ... }
Java
public final class HelloWorldService extends CarAppService { ... @Override @NonNull public Session onCreateSession() { return new HelloWorldSession(); } ... }
Session
インスタンスは次の役割を担います。
Screen
インスタンスを返して
アプリが初めて起動したとき:
Kotlin
class HelloWorldSession : Session() { ... override fun onCreateScreen(intent: Intent): Screen { return HelloWorldScreen(carContext) } ... }
Java
public final class HelloWorldSession extends Session { ... @Override @NonNull public Screen onCreateScreen(@NonNull Intent intent) { return new HelloWorldScreen(getCarContext()); } ... }
自動車向けアプリを、起動していない画面から起動する必要があるシナリオに対処するため
ディープリンクの処理など、アプリのホーム画面やランディング スクリーンで
を使用して画面のバックスタックを
ScreenManager.push
到着する前の
onCreateScreen
。
事前に埋め込むことで、ユーザーはアプリによって表示された最初の画面から前の画面に戻ることができます。
起動画面を作成する
アプリに表示される画面を作成するには、アプリの UI を拡張するクラスを定義します。
Screen
クラスを使用してそのクラスを実装し、
onGetTemplate
メソッドを呼び出し、
表す Template
インスタンス
車の画面に表示する UI の状態。
次のスニペットは、
Screen
:
PaneTemplate
テンプレートを
「Hello World!」というシンプルな「Hello World!」string:
Kotlin
class HelloWorldScreen(carContext: CarContext) : Screen(carContext) { override fun onGetTemplate(): Template { val row = Row.Builder().setTitle("Hello world!").build() val pane = Pane.Builder().addRow(row).build() return PaneTemplate.Builder(pane) .setHeaderAction(Action.APP_ICON) .build() } }
Java
public class HelloWorldScreen extends Screen { @NonNull @Override public Template onGetTemplate() { Row row = new Row.Builder().setTitle("Hello world!").build(); Pane pane = new Pane.Builder().addRow(row).build(); return new PaneTemplate.Builder(pane) .setHeaderAction(Action.APP_ICON) .build(); } }
CarContext クラス
CarContext
クラスは、
ContextWrapper
サブクラス
Session
にアクセスでき、
Screen
個のインスタンス。Kubernetes では、
車のサービスに、
ScreenManager
:
画面スタック
AppManager
: 一般的なアプリ関連
機能(地図を描画するための Surface
オブジェクトへのアクセスなど)
NavigationManager
ターンバイターン方式ナビアプリがナビゲーションを伝達するために使用する
メタデータなど、
ナビゲーション関連
イベントで
できます。
ナビゲーションにアクセスする テンプレート ナビゲーション アプリで利用できるライブラリ機能の包括的なリスト。
CarContext
では、他にも
構成を使用してドローアブル リソースを読み込むなど、
車の画面で操作する、インテントを使用して車内でアプリを起動する
アプリがダークモードで地図を表示するかどうかを指定できます。
画面ナビゲーションを実装する
多くの場合、アプリはさまざまな画面を用意し、それぞれで 操作に応じてナビゲーションできるさまざまなテンプレート 表示されるインターフェースです。
ScreenManager
クラスは、
自動的にポップできる画面をプッシュするために使用できる画面スタック
ユーザーが車の画面で [戻る] ボタンを選択したとき、またはハードウェアの戻るボタンを使用した場合
ボタンは一部の車種で使用できます。
次のスニペットは、「戻る」アクションをメッセージ テンプレートに追加する方法を示しています。 ユーザーが選択すると新しい画面をプッシュするアクションも指定できます。
Kotlin
val template = MessageTemplate.Builder("Hello world!") .setHeaderAction(Action.BACK) .addAction( Action.Builder() .setTitle("Next screen") .setOnClickListener { screenManager.push(NextScreen(carContext)) } .build()) .build()
Java
MessageTemplate template = new MessageTemplate.Builder("Hello world!") .setHeaderAction(Action.BACK) .addAction( new Action.Builder() .setTitle("Next screen") .setOnClickListener( () -> getScreenManager().push(new NextScreen(getCarContext()))) .build()) .build();
Action.BACK
オブジェクトは、自動的に ScreenManager.pop
を呼び出す標準的な Action
です。この動作は、次を使用してオーバーライドできます:
OnBackPressedDispatcher
マネージド インスタンス グループから
CarContext
。
運転中にアプリを安全に使用できるように、画面スタックには 最大 5 画面に分割できます。テンプレートの制限事項をご覧ください。 セクションをご覧ください。
テンプレートのコンテンツを更新する
アプリは、
Screen
を無効化するには、
Screen.invalidate
メソッドを使用します。
その後、ホストはアプリの呼び出しに
Screen.onGetTemplate
メソッドを使用して、新しいコンテンツを含むテンプレートを取得します。
Screen
を更新すると、次のようになります。
更新可能なテンプレートの
具体的な内容を理解することが重要です
新しいテンプレートはテンプレートの割り当てにカウントされません。
詳しくは、テンプレートの制限をご覧ください。
1 対 1 の関係があるように画面を構成することをおすすめします。
Screen
と
onGetTemplate
の実装を通じて返されるテンプレート。
地図を描画する
次のテンプレートを使用するナビゲーション アプリとスポット(POI)アプリでは、
Surface
にアクセスして地図を描画します。
テンプレート | テンプレートの権限 | カテゴリに関するガイダンス |
---|---|---|
NavigationTemplate |
androidx.car.app.NAVIGATION_TEMPLATES |
ナビゲーション |
MapWithContentTemplate |
androidx.car.app.NAVIGATION_TEMPLATES または androidx.car.app.MAP_TEMPLATES |
ナビゲーション、スポット |
MapTemplate (非推奨) |
androidx.car.app.NAVIGATION_TEMPLATES |
ナビゲーション |
PlaceListNavigationTemplate (非推奨) |
androidx.car.app.NAVIGATION_TEMPLATES |
ナビゲーション |
RoutePreviewNavigationTemplate (非推奨) |
androidx.car.app.NAVIGATION_TEMPLATES |
ナビゲーション |
サーフェスの権限を宣言する
アプリで使用するテンプレートに必要な権限に加えて、
アプリはアプリで androidx.car.app.ACCESS_SURFACE
権限を宣言する必要があります。
AndroidManifest.xml
ファイルを開いてサーフェスにアクセスできるようにします。
<manifest ...>
...
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
...
</manifest>
サーフェスにアクセス
ホストが提供する Surface
にアクセスするには、
SurfaceCallback
を作成し、
その実装を AppManager
カーサービスを利用できます。現在の Surface
が
パラメータの SurfaceContainer
パラメータの SurfaceCallback
onSurfaceAvailable()
コールバックと onSurfaceDestroyed()
コールバック。
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
サーフェスの可視領域について
ホストはテンプレートのユーザー インターフェース要素を地図上に描画できます。ホストは、Google が保証するサーフェスの面積を
ユーザーが遮るものがなく、完全に見えるようにするために
SurfaceCallback.onVisibleAreaChanged
メソッドを呼び出します。また、変更回数を最小限に抑えるために、ホストは SurfaceCallback.onStableAreaChanged
メソッドを呼び出します。この呼び出しでは現在のテンプレートに基づいて常に表示される最小の長方形が使用されます。
たとえば、ナビゲーション アプリが
NavigationTemplate
上部にアクション ストリップがある場合は、アクション ストリップを非表示にして、
ユーザーがしばらく画面を操作していないと、自動的に認識され、
スペースが表示されます。この例では、onStableAreaChanged
へのコールバックがあり、
onVisibleAreaChanged
を同じ長方形に置き換えます。アクションストリップが非表示になると
onVisibleAreaChanged
のみが、より大きな領域で呼び出されます。ユーザーが
画面とやり取りすると、再び onVisibleAreaChanged
のみが呼び出されます。
作成します。
ダークモードをサポートする
アプリは、地図を適切なダークで Surface
インスタンスに再描画する必要があります。
ホストが条件が満たされると判断した場合に、色
自動車向け Android アプリの品質。
暗い色の地図を描画するかどうかの判断には、CarContext.isDarkMode
メソッドを使用できます。ダークモードのステータスが変更されるたびに、
Session.onCarConfigurationChanged
。
ユーザーが地図を操作できるようにする
次のテンプレートを使用すると、ユーザーが操作するためのサポートを追加できます。 さまざまな角度からマップのさまざまな部分を 使用できます。
テンプレート | インタラクティビティをサポートする Car App API レベル |
---|---|
NavigationTemplate |
2 |
PlaceListNavigationTemplate (非推奨) |
4 |
RoutePreviewNavigationTemplate (非推奨) |
4 |
MapTemplate (非推奨) |
5(テンプレートの導入) |
MapWithContentTemplate |
7(テンプレートの導入) |
インタラクティビティ コールバックを実装する
SurfaceCallback
インターフェース
には、構築済みの地図にインタラクティビティを追加するために実装できる、複数のコールバック メソッドがあります。
次のラボ テンプレートを使用しました。
インタラクション | SurfaceCallback メソッド |
サポートする Car App API レベル |
---|---|---|
タップ | onClick |
5 |
ピンチしてズーム | onScale |
2 |
シングルタップ ドラッグ | onScroll |
2 |
シングルタップ フリング | onFling |
2 |
ダブルタップ | onScale (スケール ファクタはテンプレート ホストによって決まります) |
2 |
パンモードの回転ナッジ | onScroll (距離係数はテンプレート ホストによって決まります) |
2 |
地図アクション ストリップを追加する
これらのテンプレートには、次のような地図関連のアクションのための地図アクション ストリップを含めることができます。 ズームイン / ズームアウト、センタリング、コンパスの表示、その他の操作 表示されます。地図のアクション ストリップには、アイコンのみのボタンを 4 つまで設定できます。 タスクの深さに影響を与えずに更新できる リソースを定義できますアイドル状態のときは非表示になります アクティブ状態になると再表示されます。
地図のインタラクティビティ コールバックを受信するには、次の操作を行います。
地図のアクション ストリップに Action.PAN
ボタンを追加する必要があります。ユーザーが
パンボタンを押すと、ホストは以下の説明のようにパンモードに入ります。
。
アプリのマップ アクション ストリップに Action.PAN
ボタンを設定しない場合、SurfaceCallback
メソッドからユーザー入力を取得できず、ホストで有効になっていたパンモードが終了します。
パンボタンはタッチスクリーンには表示されません。
パンモードについて
パンモードでは、ノンタッチの入力デバイス(ロータリー コントローラやタッチパッドなど)からのユーザー入力が、テンプレート ホストによって適切な SurfaceCallback
メソッドに変換されます。パンモードを開始または終了するユーザー操作には、NavigationTemplate.Builder
の setPanModeListener
メソッドで応答します。ユーザーがパンモードのときは、テンプレートの他の UI コンポーネントを非表示にできます。
ユーザーとやり取りする
アプリは、モバイルアプリと同様のパターンを使用してユーザーとやり取りできます。
ユーザー入力を処理する
アプリは、適切なリスナーをそれらをサポートするモデルに渡すことで、ユーザー入力に応答できます。次のスニペットは、Cloud Storage バケットを作成する
次の値を設定する Action
モデル
OnClickListener
。
は、アプリのコードで定義されたメソッドにコールバックします。
Kotlin
val action = Action.Builder() .setTitle("Navigate") .setOnClickListener(::onClickNavigate) .build()
Java
Action action = new Action.Builder() .setTitle("Navigate") .setOnClickListener(this::onClickNavigate) .build();
その後、onClickNavigate
メソッドは
デフォルトのナビゲーション自動車アプリ
使用して
CarContext.startCarApp
メソッド:
Kotlin
private fun onClickNavigate() { val intent = Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address)) carContext.startCarApp(intent) }
Java
private void onClickNavigate() { Intent intent = new Intent(CarContext.ACTION_NAVIGATE, Uri.parse("geo:0,0?q=" + address)); getCarContext().startCarApp(intent); }
アプリの起動方法(
ACTION_NAVIGATE
インテント(インテントを使用して自動車アプリを開始するをご覧ください)
。
インタラクションの続きをモバイル デバイスで行うようにユーザーをガイドするアクションなど、特定のアクションは車がパーキング状態にあるときに限り許可されます。こちらの
ParkedOnlyOnClickListener
これらのアクションを実装できます車が駐車していない場合は、
この場合、操作が許可されていないことをユーザーに通知します。車が
駐車中の場合、コードは通常どおり実行されます。次のスニペットは、
ParkedOnlyOnClickListener
を使用する
モバイル デバイスで設定画面を開くには:
Kotlin
val row = Row.Builder() .setTitle("Open Settings") .setOnClickListener(ParkedOnlyOnClickListener.create(::openSettingsOnPhone)) .build()
Java
Row row = new Row.Builder() .setTitle("Open Settings") .setOnClickListener(ParkedOnlyOnClickListener.create(this::openSettingsOnPhone)) .build();
通知を表示する
モバイル デバイスに送信された通知は、次の場合にのみ表示されます。
拡張性に優れ、
CarAppExtender
。
コンテンツのタイトル、テキスト、アイコン、アクションなどの通知属性。
CarAppExtender
で設定して、通知の属性をオーバーライドできます
自動車の画面に表示されたときに通知を受け取れます。
次のスニペットは、モバイル デバイスとは異なるタイトルで、通知を車の画面に送信する方法を示しています。
Kotlin
val notification = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setContentTitle(titleOnThePhone) .extend( CarAppExtender.Builder() .setContentTitle(titleOnTheCar) ... .build()) .build()
Java
Notification notification = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setContentTitle(titleOnThePhone) .extend( new CarAppExtender.Builder() .setContentTitle(titleOnTheCar) ... .build()) .build();
通知は、ユーザー インターフェースの次の部分に影響する場合があります。
- ヘッドアップ通知(HUN)がユーザーに表示されることがあります。
- 通知センターにエントリが追加されたり、必要に応じて、レールにバッジが表示されたりすることがあります。
- ナビゲーション アプリの場合、通知はレール ウィジェットに 説明 ターンバイターン通知。
アプリの通知をどのように構成すれば、
通知の優先順位を使用して、ユーザー インターフェース要素を
の
CarAppExtender
ご覧ください
条件
NotificationCompat.Builder.setOnlyAlertOnce
値 true
で呼び出された場合、優先度の高い通知は
HUN は 1 回のみです。
自動車向けアプリの通知を設計する方法について詳しくは、 Google Design for Driving ガイド: 通知。
トーストを表示する
アプリでトーストを表示するには、
CarToast
を次のスニペットのようになります。
Kotlin
CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()
Java
CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();
権限をリクエストする
アプリが制限付きのデータやアクションにアクセスする必要がある場合。例:
- Android の標準ルール
権限
適用されます。権限をリクエストするには、
CarContext.requestPermissions()
メソッドを呼び出します。
Google Cloud で
CarContext.requestPermissions()
(
標準 Android API です。
独自の Activity
を起動する必要がないことを
権限ダイアログを作成します。さらに、両方のデバイスで同じコードを
Android Auto と Android Automotive OS 用の
プラットフォーム依存フローに対応しています。
Android Auto の権限ダイアログのスタイルを設定する
Android Auto では、ユーザーの権限ダイアログがスマートフォンに表示されます。
デフォルトでは、ダイアログの背景は表示されません。カスタム
自動車向けアプリのテーマを
AndroidManifest.xml
ファイルで carPermissionActivityLayout
属性を設定する
自動車アプリのテーマを選択します
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
次に、自動車向けアプリのテーマの carPermissionActivityLayout
属性を設定します。
<resources> <style name="MyCarAppTheme"> <item name="carPermissionActivityLayout">@layout/my_custom_background</item> </style> </resources>
インテントを使用して自動車アプリを起動する
この関数を呼び出すには、
CarContext.startCarApp
メソッドを使用して、次のいずれかの操作を行います。
- 電話アプリを開いて電話をかける。
- ターンバイターン方式ナビを開始して デフォルトのナビゲーション自動車アプリ。
- インテントを使用して独自のアプリを起動する。
次の例は、駐車予約の詳細を表示する画面でアプリを開く、というアクションを含む通知を作成する方法を示しています。コンテンツ インテントで通知インスタンスを拡張します。コンテンツ インテントには、
PendingIntent
明示的な
インテントを指定できます。
Kotlin
val notification = notificationBuilder ... .extend( CarAppExtender.Builder() .setContentIntent( PendingIntent.getBroadcast( context, ACTION_VIEW_PARKING_RESERVATION.hashCode(), Intent(ACTION_VIEW_PARKING_RESERVATION) .setComponent(ComponentName(context, MyNotificationReceiver::class.java)), 0)) .build())
Java
Notification notification = notificationBuilder ... .extend( new CarAppExtender.Builder() .setContentIntent( PendingIntent.getBroadcast( context, ACTION_VIEW_PARKING_RESERVATION.hashCode(), new Intent(ACTION_VIEW_PARKING_RESERVATION) .setComponent(new ComponentName(context, MyNotificationReceiver.class)), 0)) .build());
アプリは、
BroadcastReceiver
:
ユーザーがアクションを選択したときに、インテントを処理するために呼び出されます。
通知インターフェースを呼び出して、
CarContext.startCarApp
データ URI を含むインテントを渡します。
Kotlin
class MyNotificationReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val intentAction = intent.action if (ACTION_VIEW_PARKING_RESERVATION == intentAction) { CarContext.startCarApp( intent, Intent(Intent.ACTION_VIEW) .setComponent(ComponentName(context, MyCarAppService::class.java)) .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction))) } } }
Java
public class MyNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String intentAction = intent.getAction(); if (ACTION_VIEW_PARKING_RESERVATION.equals(intentAction)) { CarContext.startCarApp( intent, new Intent(Intent.ACTION_VIEW) .setComponent(new ComponentName(context, MyCarAppService.class)) .setData(Uri.fromParts(MY_URI_SCHEME, MY_URI_HOST, intentAction))); } } }
最後に、
Session.onNewIntent
メソッドが、駐車場の予約画面をプッシュすることで、このインテントを処理します。
スタック上にあります(まだ最上位にない場合)。
Kotlin
override fun onNewIntent(intent: Intent) { val screenManager = carContext.getCarService(ScreenManager::class.java) val uri = intent.data if (uri != null && MY_URI_SCHEME == uri.scheme && MY_URI_HOST == uri.schemeSpecificPart && ACTION_VIEW_PARKING_RESERVATION == uri.fragment ) { val top = screenManager.top if (top !is ParkingReservationScreen) { screenManager.push(ParkingReservationScreen(carContext)) } } }
Java
@Override public void onNewIntent(@NonNull Intent intent) { ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class); Uri uri = intent.getData(); if (uri != null && MY_URI_SCHEME.equals(uri.getScheme()) && MY_URI_HOST.equals(uri.getSchemeSpecificPart()) && ACTION_VIEW_PARKING_RESERVATION.equals(uri.getFragment()) ) { Screen top = screenManager.getTop(); if (!(top instanceof ParkingReservationScreen)) { screenManager.push(new ParkingReservationScreen(getCarContext())); } } }
詳細については、通知を表示するセクションをご覧ください 自動車向けアプリの通知を処理する方法に関する情報。
テンプレートの制限事項
ホストは、特定のタスクに対して表示するテンプレートの数を最大限に制限する 最大 5 個。最後のテンプレートは次のいずれかのタイプにする必要があります。
この上限はテンプレートの数に適用されるものであり、
スタック内の Screen
個のインスタンス。対象
例: 画面 A でアプリが 2 つのテンプレートを送信してから画面をプッシュした場合
さらに 3 つのテンプレートを送信できるようになりました。または、各画面が構造化され、
1 つのテンプレートを送信すると、アプリは 5 つの画面インスタンスを
ScreenManager
スタック。
これらの制限には、テンプレートの更新や「戻る」などの特殊なケースがあります。 オペレーションをリセットします。
テンプレートの更新
一部のコンテンツの更新は、テンプレートの制限にカウントされません。一般的に
同じタイプの新しいテンプレートをアプリがプッシュすると、
新しいテンプレートは変更されず、
カウントされます。たとえば、ListTemplate
内で行の切り替え状態を更新しても、割り当てに対するカウントは行われません。どのような種類のコンテンツ更新がテンプレートの更新としてカウントされるかについて詳しくは、個々のテンプレートのドキュメントをご覧ください。
戻る操作
タスク内でサブフローを有効にするために、ホストはアプリが
ScreenManager
スタックからの Screen
と更新
残りの割り当て(アプリが使用するテンプレートの数に基づく)
戻ります。
たとえば、アプリが画面 A で 2 つのテンプレートを送信すると、 2 つのテンプレートを送信すると、アプリの割り当ては 1 つになります。条件 その後アプリが画面 A に戻るため、ホストは割り当てを 3 にリセットします。これは、 2 つのテンプレートを遡って移動されます
注意して画面に戻る場合は、アプリから送信されるテンプレートに その画面で最後に送信されたのと同じタイプの関数です。その他の送信 エラーが発生します。ただし、戻る操作時にタイプが同じのままであれば、アプリは割り当てに影響を与えることなくテンプレートのコンテンツを自由に変更できます。
リセット操作
一部のテンプレートには、タスクの終了を示す特別なセマンティクスがあります。対象
たとえば
NavigationTemplate
画面に表示され続け、
ターンバイターン方式の指示をユーザーに提供します。このいずれかに達すると
設定すると、ホストはテンプレートの割り当てをリセットし、テンプレートを
新しいタスクの最初のステップです。これにより、アプリは新しいタスクを開始できるようになります。
ホスト上でリセットがトリガーされるテンプレートについては、個々のテンプレートのドキュメントをご覧ください。
ホストが通知アクションからアプリを起動するインテントを受け取った場合、または 割り当てもリセットされます。このメカニズムにより、アプリは 通知から新しいタスクフローを開始できます。また、通知から新しいタスクフローを開始できます。 フォアグラウンドにあることを確認します。
詳しくは、通知を表示するセクションをご覧ください アプリの通知を車の画面に表示する方法についてご紹介します。詳しくは、 詳しくは、インテントを使用して自動車用アプリを起動するをご覧ください。 通知アクションからアプリを起動できます。
接続 API
アプリが Android Auto と Android のどちらで実行されているかを判断できる
Automotive OS です。
CarConnection
API から
実行時に接続情報を取得できます。
たとえば、自動車アプリの Session
で CarConnection
を初期化し、
LiveData
の最新情報を受け取る:
Kotlin
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
Java
new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);
オブザーバーで、接続状態の変化に対応できます。
Kotlin
fun onConnectionStateUpdated(connectionState: Int) { val message = when(connectionState) { CarConnection.CONNECTION_TYPE_NOT_CONNECTED -> "Not connected to a head unit" CarConnection.CONNECTION_TYPE_NATIVE -> "Connected to Android Automotive OS" CarConnection.CONNECTION_TYPE_PROJECTION -> "Connected to Android Auto" else -> "Unknown car connection type" } CarToast.makeText(carContext, message, CarToast.LENGTH_SHORT).show() }
Java
private void onConnectionStateUpdated(int connectionState) { String message; switch(connectionState) { case CarConnection.CONNECTION_TYPE_NOT_CONNECTED: message = "Not connected to a head unit"; break; case CarConnection.CONNECTION_TYPE_NATIVE: message = "Connected to Android Automotive OS"; break; case CarConnection.CONNECTION_TYPE_PROJECTION: message = "Connected to Android Auto"; break; default: message = "Unknown car connection type"; break; } CarToast.makeText(getCarContext(), message, CarToast.LENGTH_SHORT).show(); }
制約 API
選択できる数は車によって異なります
表示先の Item
インスタンス
一度に 1 つずつですこちらの
ConstraintManager
実行時にコンテンツの上限を確認し、適切な数のアイテムを設定する
使用できます。
まず、CarContext
から ConstraintManager
を取得します。
Kotlin
val manager = carContext.getCarService(ConstraintManager::class.java)
Java
ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);
次に、取得した ConstraintManager
オブジェクトをクエリし、
。たとえば、次のコマンドで表示できるアイテム数を取得するには、
グリッドと
getContentLimit
CONTENT_LIMIT_TYPE_GRID
:
Kotlin
val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)
Java
int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);
ログインフローを追加する
アプリでユーザーのログイン操作を提供する場合は、次のようなテンプレートを使用できます。
SignInTemplate
および LongMessageTemplate
Car App API レベル 2 以上を使用して、
車のヘッドユニットを取り付けることもできます。
SignInTemplate
を作成するには、SignInMethod
を定義します。車
現在、アプリ ライブラリは次のログイン方法をサポートしています。
InputSignInMethod
ログインに使用できます。PinSignInMethod
PIN ログイン(ユーザーがスマートフォンからアカウントをリンク) ヘッドユニットに表示される PIN を使用しますProviderSignInMethod
ファイアウォール ルールなど、 Google ログイン ワンタップ。QRCodeSignInMethod
QR コード ログイン(ユーザーが QR コードをスキャンしてログインを完了) できます。これは、Car API レベル 4 以降で使用できます。
たとえば、ユーザーのパスワードを収集するテンプレートを実装するには、まず InputCallback
を作成してユーザー入力の処理と検証を行います。
Kotlin
val callback = object : InputCallback { override fun onInputSubmitted(text: String) { // You will receive this callback when the user presses Enter on the keyboard. } override fun onInputTextChanged(text: String) { // You will receive this callback as the user is typing. The update // frequency is determined by the host. } }
Java
InputCallback callback = new InputCallback() { @Override public void onInputSubmitted(@NonNull String text) { // You will receive this callback when the user presses Enter on the keyboard. } @Override public void onInputTextChanged(@NonNull String text) { // You will receive this callback as the user is typing. The update // frequency is determined by the host. } };
InputSignInMethod
Builder
には InputCallback
が必要です。
Kotlin
val passwordInput = InputSignInMethod.Builder(callback) .setHint("Password") .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD) ... .build()
Java
InputSignInMethod passwordInput = new InputSignInMethod.Builder(callback) .setHint("Password") .setInputType(InputSignInMethod.INPUT_TYPE_PASSWORD) ... .build();
最後に、新しい InputSignInMethod
を使用して SignInTemplate
を作成します。
Kotlin
SignInTemplate.Builder(passwordInput) .setTitle("Sign in with username and password") .setInstructions("Enter your password") .setHeaderAction(Action.BACK) ... .build()
Java
new SignInTemplate.Builder(passwordInput) .setTitle("Sign in with username and password") .setInstructions("Enter your password") .setHeaderAction(Action.BACK) ... .build();
AccountManager を使用する
認証が必要な Android Automotive OS アプリでは、次の理由により AccountManager を使用する必要があります。
- ユーザー エクスペリエンスの向上とアカウント管理の容易さ: ユーザーは、 ログインを含め、システム設定のアカウント メニューから自分のアカウントにアクセスできます。 便利です。
- 「ゲスト」エクスペリエンス: 自動車は共有デバイスであるため、OEM は アカウントを追加することはできません。
テキスト文字列のバリエーションを追加する
自動車の画面サイズに応じて、表示されるテキストの量は異なります。自動車向けアプリの API レベル 2 以上では、画面に合う最適なテキスト文字列のバリエーションを複数指定できます。テキストのバリエーションを使用できる場所を確認するには、CarText
を使用するテンプレートとコンポーネントを探してください。
CarText
にテキスト文字列のバリエーションを追加するには、
CarText.Builder.addVariant()
メソッド:
Kotlin
val itemTitle = CarText.Builder("This is a very long string") .addVariant("Shorter string") ... .build()
Java
CarText itemTitle = new CarText.Builder("This is a very long string") .addVariant("Shorter string") ... .build();
この CarText
を、たとえばスペース内のメインのテキストとして
GridItem
。
Kotlin
GridItem.Builder() .addTitle(itemTitle) ... .build()
Java
new GridItem.Builder() .addTitle(itemTitle) ... build();
文字列を優先度の高いものから順に追加します。たとえば、長いものから 記述できますホストは、構成に応じて適切な長さの文字列を 車の画面スペースの空きスペース。
行にインライン CarIcons を追加する
テキストと一緒にアイコンをインラインで追加して、
CarIconSpan
。
次のドキュメントをご覧ください:
CarIconSpan.create
これらのスパンの作成について詳しくはこちらをご覧ください詳しくは、
宇宙
スパンを使用したテキストのスタイル設定の仕組みの概要」をご覧ください。
Kotlin
val rating = SpannableString("Rating: 4.5 stars") rating.setSpan( CarIconSpan.create( // Create a CarIcon with an image of four and a half stars CarIcon.Builder(...).build(), // Align the CarIcon to the baseline of the text CarIconSpan.ALIGN_BASELINE ), // The start index of the span (index of the character '4') 8, // The end index of the span (index of the last 's' in "stars") 16, Spanned.SPAN_INCLUSIVE_INCLUSIVE ) val row = Row.Builder() ... .addText(rating) .build()
Java
SpannableString rating = new SpannableString("Rating: 4.5 stars"); rating.setSpan( CarIconSpan.create( // Create a CarIcon with an image of four and a half stars new CarIcon.Builder(...).build(), // Align the CarIcon to the baseline of the text CarIconSpan.ALIGN_BASELINE ), // The start index of the span (index of the character '4') 8, // The end index of the span (index of the last 's' in "stars") 16, Spanned.SPAN_INCLUSIVE_INCLUSIVE ); Row row = new Row.Builder() ... .addText(rating) .build();
自動車ハードウェア API
自動車向けアプリの API レベル 3 以降、自動車向けアプリ ライブラリには、 車両プロパティとセンサーへのアクセスに使用できます。
要件
Android Auto で API を使用するには、まず依存関係を追加します。
androidx.car.app:app-projected
(Android の build.gradle
ファイル)
自動モジュール。Android Automotive OS の場合、以下への依存関係を追加する
androidx.car.app:app-automotive
(Android の build.gradle
ファイル)
Automotive OS モジュールです。
また、AndroidManifest.xml
ファイルで次のようにします。
関連する権限を宣言できます。
使用する車のデータをリクエストします。なお、これらの権限は、
付与します。こちらの
同じコードではなく、Android Auto と Android Automotive OS の両方で
プラットフォーム依存のフローを作成する必要はありません。ただし、この IAM ロールに
異なります
自動車情報
次の表に、
CarInfo
API と
必要な権限のみに制限します。
メソッド | プロパティ | Android Auto の権限 | Android Automotive OS の権限 | サポートする Car App API レベル |
---|---|---|---|---|
fetchModel |
メーカー、モデル、年 | android.car.permission.CAR_INFO |
3 | |
fetchEnergyProfile |
EV コネクタの種類、燃料の種類 | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_INFO |
3 |
fetchExteriorDimensions
<ph type="x-smartling-placeholder"></ph> このデータは、一部の Android Automotive OS 搭載自動車でのみ利用できます API 30 以降を実行していること |
外装寸法 | なし | android.car.permission.CAR_INFO |
7 |
addTollListener
removeTollListener |
通行料金カードのステータス、通行料金カードの種類 | 3 | ||
addEnergyLevelListener
removeEnergyLevelListener |
バッテリー残量、燃料残量、燃料残量、残量 | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_ENERGY ,android.car.permission.CAR_ENERGY_PORTS ,android.car.permission.READ_CAR_DISPLAY_UNITS
|
3 |
addSpeedListener
removeSpeedListener |
未加工の速度、表示速度(車のクラスタ ディスプレイに表示) | com.google.android.gms.permission.CAR_SPEED |
android.car.permission.CAR_SPEED ,android.car.permission.READ_CAR_DISPLAY_UNITS |
3 |
addMileageListener
removeMileageListener |
走行距離計 | com.google.android.gms.permission.CAR_MILEAGE |
このデータは、Google Play ストアからインストールしたアプリでは Android Automotive OS では利用できません。 | 3 |
たとえば、残りの範囲を取得するには、結果をインスタンス化して
CarInfo
オブジェクトの場合、
OnCarDataAvailableListener
を作成して登録します。
Kotlin
val carInfo = carContext.getCarService(CarHardwareManager::class.java).carInfo val listener = OnCarDataAvailableListener<EnergyLevel> { data -> if (data.rangeRemainingMeters.status == CarValue.STATUS_SUCCESS) { val rangeRemaining = data.rangeRemainingMeters.value } else { // Handle error } } carInfo.addEnergyLevelListener(carContext.mainExecutor, listener) … // Unregister the listener when you no longer need updates carInfo.removeEnergyLevelListener(listener)
Java
CarInfo carInfo = getCarContext().getCarService(CarHardwareManager.class).getCarInfo(); OnCarDataAvailableListener<EnergyLevel> listener = (data) -> { if(data.getRangeRemainingMeters().getStatus() == CarValue.STATUS_SUCCESS) { float rangeRemaining = data.getRangeRemainingMeters().getValue(); } else { // Handle error } }; carInfo.addEnergyLevelListener(getCarContext().getMainExecutor(), listener); … // Unregister the listener when you no longer need updates carInfo.removeEnergyLevelListener(listener);
自動車からのデータが常に利用できるとは限りません。
エラーが発生した場合は、
ステータス:
リクエストしたデータが正しく表示されない理由を
取得されません。詳しくは、
リファレンス ドキュメント
CarInfo
クラスの完全な定義。
自動車用センサー
CarSensors
クラス
車の加速度計、ジャイロスコープ、コンパス、
位置情報。これらの値を使用できるかどうかは、
OEM。加速度計、ジャイロスコープ、コンパスのデータの形式は次のとおりです。
通常の Pod の
SensorManager
API。たとえば
車両の向きを確認するには:
Kotlin
val carSensors = carContext.getCarService(CarHardwareManager::class.java).carSensors val listener = OnCarDataAvailableListener<Compass> { data -> if (data.orientations.status == CarValue.STATUS_SUCCESS) { val orientation = data.orientations.value } else { // Data not available, handle error } } carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, carContext.mainExecutor, listener) … // Unregister the listener when you no longer need updates carSensors.removeCompassListener(listener)
Java
CarSensors carSensors = getCarContext().getCarService(CarHardwareManager.class).getCarSensors(); OnCarDataAvailableListener<Compass> listener = (data) -> { if (data.getOrientations().getStatus() == CarValue.STATUS_SUCCESS) { List<Float> orientations = data.getOrientations().getValue(); } else { // Data not available, handle error } }; carSensors.addCompassListener(CarSensors.UPDATE_RATE_NORMAL, getCarContext().getMainExecutor(), listener); … // Unregister the listener when you no longer need updates carSensors.removeCompassListener(listener);
車から位置情報にアクセスするには、
android.permission.ACCESS_FINE_LOCATION
権限。
テスト
Android Auto でのテスト時にセンサーデータをシミュレートするには、 センサーとセンサー 構成セクションの デスクトップ ヘッドユニット ガイドAndroid でのテスト時にセンサーデータをシミュレートする Automotive OS については、ハードウェアのエミュレートに関するページ state セクションにある Automotive OS エミュレータ ガイド
CarAppService、Session、Screen のライフサイクル
Session
と
Screen
クラスは、
LifecycleOwner
インターフェースを使用します。として
ユーザーがアプリを操作した(Session
オブジェクトと Screen
オブジェクト)ライフサイクル
各コールバックが呼び出されます。
CarAppService とセッションのライフサイクル
詳細については、このモジュールのコースリソースにある
Session.getLifecycle
メソッドを呼び出します。
画面のライフサイクル
詳細については、このモジュールのコースリソースにある
Screen.getLifecycle
メソッドを使用します。
車のマイクから録音する
アプリの
CarAppService
および
CarAudioRecord
API、
アプリにユーザーの車のマイクへのアクセス権を付与できます。ユーザーはリソースへのアクセスを
車のマイクにアクセスする権限。アプリでは、
ユーザーの入力を処理する。
録音の許可
録音する前に、まず録音の権限を申告する必要があります。
AndroidManifest.xml
を実行して、ユーザーに許可するようリクエストします。
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
...
</manifest>
録画の権限を実行時にリクエストする必要がある。詳しくは、リクエスト 権限のセクションで、 許可する必要があります。
音声を記録する
ユーザーから録音の許可が得られたら、音声を録音して クリックします。
Kotlin
val carAudioRecord = CarAudioRecord.create(carContext) carAudioRecord.startRecording() val data = ByteArray(CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) while(carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) { // Use data array // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech } carAudioRecord.stopRecording()
Java
CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext()); carAudioRecord.startRecording(); byte[] data = new byte[CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE]; while (carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) { // Use data array // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech } carAudioRecord.stopRecording();
音声フォーカス
車のマイクから録音するときは、まず音声を 焦点を当てる 進行中のメディアがすべて停止することを確認します音声フォーカスが失われた場合は 録画を停止します。
音声フォーカスを取得する方法の例を次に示します。
Kotlin
val carAudioRecord = CarAudioRecord.create(carContext) // Take audio focus so that user's media is not recorded val audioAttributes = AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) // Use the most appropriate usage type for your use case .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE) .build() val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) .setAudioAttributes(audioAttributes) .setOnAudioFocusChangeListener { state: Int -> if (state == AudioManager.AUDIOFOCUS_LOSS) { // Stop recording if audio focus is lost carAudioRecord.stopRecording() } } .build() if (carContext.getSystemService(AudioManager::class.java) .requestAudioFocus(audioFocusRequest) != AudioManager.AUDIOFOCUS_REQUEST_GRANTED ) { // Don't record if the focus isn't granted return } carAudioRecord.startRecording() // Process the audio and abandon the AudioFocusRequest when done
Java
CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext()); // Take audio focus so that user's media is not recorded AudioAttributes audioAttributes = new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) // Use the most appropriate usage type for your use case .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE) .build(); AudioFocusRequest audioFocusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) .setAudioAttributes(audioAttributes) .setOnAudioFocusChangeListener(state -> { if (state == AudioManager.AUDIOFOCUS_LOSS) { // Stop recording if audio focus is lost carAudioRecord.stopRecording(); } }) .build(); if (getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest) != AUDIOFOCUS_REQUEST_GRANTED) { // Don't record if the focus isn't granted return; } carAudioRecord.startRecording(); // Process the audio and abandon the AudioFocusRequest when done
テスト ライブラリ
自動車向け Android のテスト
Library は、
テスト環境でアプリの動作を検証するために使用できるクラス。
たとえば、
SessionController
を使用すると、ホストへの接続をシミュレートして、
Screen
、
Template
が作成され、
返されます。
詳しくは、 サンプル をご覧ください。
自動車向け Android アプリ ライブラリに関する問題を報告する
ライブラリに問題がある場合は、 Google Issue Tracker 問題テンプレートに必要な情報をすべて記入してください。
新しい問題を報告する前に、その問題がライブラリのリリースに含まれているかどうかを確認してください メモまたは報告された問題です。Issue Tracker 内で各問題の横にあるスターアイコンをクリックすると、問題を登録して投票することができます。詳細については、問題を登録する手順をご覧ください。