自動車向け Android アプリ ライブラリを使用する

自動車向け Android アプリ ライブラリ ナビゲーション、スポット(POI)、モノのインターネット(IoT) 車載アプリなどです そのために、ドライバーの注意散漫に対応するよう設計された一連のテンプレートを提供しています。 車の画面要素に関するさまざまな要素や 細かい条件に基づいて 入力モダリティがあります。

このガイドでは、ライブラリの主な機能とコンセプトの概要を説明し、 基本的なアプリを設定するプロセスを順を追って説明します。

始める前に

  1. 運転に適したデザインを確認する 自動車向けアプリ ライブラリを扱うページ <ph type="x-smartling-placeholder">
  2. 次の主な用語とコンセプトを確認する 。
  3. Android Auto システムについて十分に理解してください UI Android Automotive OS 設計をご覧ください。
  4. リリースノートを確認してください。
  5. サンプルを確認してください。

主な用語と概念

モデルとテンプレート
ユーザー インターフェースは、モデル オブジェクトのグラフで表現され、 所属しているテンプレートで許可されるように、さまざまな方法で構成されている できます。テンプレートはモデルのサブセットであり、 分析できますモデルには、 属性の形式を使用して、インフラストラクチャの 情報の外観(例: テキストの色、画像) あります。ホストはモデルを、次の要件を満たすように設計されたビューに変換します。 ドライバーの注意散漫に関する基準と 車載画面の要素と入力モダリティです。
ホスト
ホストは、提供される機能を実装するバックエンド コンポーネントです。 ライブラリの 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 を宣言した場合のインテント フィルタの値。 (前のセクション)をご覧ください。

で確認できます。

詳しくは、自動車向け Android アプリの品質をご覧ください。 各カテゴリの詳細な説明と、そのカテゴリに属するアプリの条件。

アプリの名前とアイコンを指定する

ホストがシステム UI でアプリを表すために使用するアプリ名とアイコンを指定する必要があります。

アプリを表すために使用するアプリ名とアイコンを指定するには、 labelicon 個の属性 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 の関係があるように画面を構成することをおすすめします。 ScreenonGetTemplate の実装を通じて返されるテンプレート。

地図を描画する

次のテンプレートを使用するナビゲーション アプリとスポット(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.BuildersetPanModeListener メソッドで応答します。ユーザーがパンモードのときは、テンプレートの他の 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.setOnlyAlertOncetrue で呼び出された場合、優先度の高い通知は 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 から 実行時に接続情報を取得できます。

たとえば、自動車アプリの SessionCarConnection を初期化し、 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 のライフサイクル

SessionScreen クラスは、 LifecycleOwner インターフェースを使用します。として ユーザーがアプリを操作した(Session オブジェクトと Screen オブジェクト)ライフサイクル 各コールバックが呼び出されます。

CarAppService とセッションのライフサイクル

図 1. Session ライフサイクル。

詳細については、このモジュールのコースリソースにある Session.getLifecycle メソッドを呼び出します。

画面のライフサイクル

図 2. Screen ライフサイクル。

詳細については、このモジュールのコースリソースにある 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 を使用すると、ホストへの接続をシミュレートして、 ScreenTemplate が作成され、 返されます。

詳しくは、 サンプル をご覧ください。

自動車向け Android アプリ ライブラリに関する問題を報告する

ライブラリに問題がある場合は、 Google Issue Tracker 問題テンプレートに必要な情報をすべて記入してください。

新しい問題を報告する

新しい問題を報告する前に、その問題がライブラリのリリースに含まれているかどうかを確認してください メモまたは報告された問題です。Issue Tracker 内で各問題の横にあるスターアイコンをクリックすると、問題を登録して投票することができます。詳細については、問題を登録する手順をご覧ください。