テンプレートを使用するメディアアプリを作成する

テンプレート化されたメディアアプリはベータ版です
現時点では、テンプレート化されたメディアアプリを Google Play ストアの内部テスト トラックとクローズド テスト トラックに公開できます。オープントラックと製品版トラックへの公開は、後日可能となります。

自動車向けアプリ ライブラリのテンプレートを使用するメディアアプリでは、メディアのブラウジングと再生のエクスペリエンスをカスタマイズしながら、車載画面に最適化し、運転中の注意散漫を最小限に抑えることができます。

このガイドは、音声を再生するメディアアプリがスマートフォンにすでにインストールされており 、そのメディアアプリが Android メディアアプリ アーキテクチャに準拠していることを前提としています。自動車向けメディアアプリを作成するの Build media apps for cars MediaBrowser データ構造を使用して作成されたアプリではなく、自動車向けアプリ ライブラリのテンプレートを使用してアプリ内のエクスペリエンスを置き換えることができます。再生コントロール用の MediaSession と、おすすめやその他のスマート エクスペリエンスに使用される MediaBrowserService または MediaLibraryService は引き続き提供する必要があります。

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

自動車向け Android アプリ ライブラリを使用するで説明されている手順に加えて、テンプレート化されたメディアアプリには次の要件があります。

マニフェストでカテゴリのサポートを宣言する

アプリでは、androidx.car.app.category.MEDIA 自動車アプリのカテゴリを、CarAppServiceのインテント フィルタで宣言する必要があります。

<application>
    ...
   <service
       ...
        android:name=".MyCarAppService"
        android:exported="true">
      <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.MEDIA"/>
      </intent-filter>
    </service>
    ...
<application>

MediaPlaybackTemplate にアクセスするには、アプリのマニフェスト ファイルで androidx.car.app.MEDIA_TEMPLATES 権限を宣言する必要があります。

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.MEDIA_TEMPLATES"/>
  ...
</manifest>

自動車向けアプリの最小 API レベルを設定する

MediaPlaybackTemplate を使用するメディアアプリは、CAL API 8 以降でのみサポートされます。最小 Car App API level が 8 に設定されていることを確認してください。

<application ...>
  ...
  <meta-data
    android:name="androidx.car.app.minCarApiLevel"
    android:value="8"/>
  ...
</application>

アトリビューション アイコンを提供する

自動車向け アプリ ライブラリを使用して作成されたメディアアプリには、アトリビューション アイコンを追加してください。

Android Auto のサポートを宣言する

アプリのマニフェストに次のものが含まれていることを確認します。

<application>
  ...
  <meta-data android:name="com.google.android.gms.car.application"
      android:resource="@xml/automotive_app_desc"/>
  ...
</application>

次に、xml リソースの automotive_app_desc.xmlテンプレート 宣言を追加します。次のようになります。

<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
 <uses name="media"/>
 <uses name="template"/>
</automotiveApp>

Android Automotive OS のサポートを宣言する

自動車向けアプリ ライブラリ対応のメディアアプリを Android Automotive OS に配信するには、単一の APK として配信する方法と、2 つの別々の APK として配信する方法があります。単一の APK を配信する場合、自動車向けアプリ ライブラリ ホストで Android Automotive OS が有効になっている車両をサポートし、有効になっていない場合は、古い Android バージョン(Android 10 ~ Android 13)でも MediaBrowserService または MediaLibraryService アプリケーションにフォールバックします。2 つの別々の APK を配信する場合は、アプリの MediaBrowserService または MediaLibraryService バージョンに影響を与えることなく、自動車向けアプリ ライブラリのバージョンに新しい追加機能を簡単に更新できます。

単一の APK を配信する

自動車向けアプリ ライブラリとアプリの MediaBrowserService または MediaLibraryService バージョンに単一の APK を配信する場合は、 "" を android:required="false" に設定することが重要です。

<uses-feature android:name="android.software.car.templates_host.media" android:required="false"/>

次に、AAOS の自動車向けアプリ ライブラリのガイドラインに沿って、 起動可能な CarAppActivity(またはトランポリン アクティビティ)を導入します。マニフェストでアクティビティを android:enabled="false" に設定する必要があります。次に、メタデータタグを MediaBrowserService 宣言に追加して、CarAppActivity コンポーネントを代替として示します。以下のマニフェストの例をご覧ください。

<service android:name=".media.MyMediaService"
    android:exported="true"
    android:label="@string/app_name">
    <intent-filter>
        <action android:name="androidx.media3.session.MediaLibraryService"/>
    </intent-filter>

    <!-- Link to Car App Library Activity -->
    <meta-data
        android:name="androidx.car.app.media.CalMediaActivityComponent" 
        android:value="com.example.mediaapp.LaunchableTrampoline"/>
</service>

<activity
    android:name=".LaunchableTrampoline"
    android:exported="true"
    android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
    android:launchMode="singleTask"
    android:label="@string/app_name_cal"
    android:enabled="false"> <!-- Set to false -->

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

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

Google Play で配信する

自動車向けアプリ ライブラリと MediaBrowserService または MediaLibraryService を含む APK は、バージョン コードを大きくし、Android 14(34)をターゲットとする minSdk で有効にする必要があります。

2 つの APK で配信する

自動車向けアプリ ライブラリを使用する APK と MediaBrowserService または MediaLibraryService を使用する APK の 2 つの別々の APK を配信するには、次の手順に沿って、正しい車両機能が正しくターゲットに設定されるようにします。

アプリの自動車向けアプリ ライブラリ バージョン用の別の APK を作成する場合は、android.software.car.templates_host.mediaandroid:required=true に設定する必要があります。これにより、自動車向けアプリ ライブラリ ホストのサポートが認定された Android Automotive OS ビルドでのみアプリが配信されます。

<uses-feature android:name="android.software.car.templates_host.media" android:required="true"/>

上記で android.software.car.templates_host.media を使用して android:required=true に設定する以外に、次の手順に沿って、起動可能な自動車向けアプリ ライブラリ アクティビティで Android Automotive OS を有効 にします。

Google Play で配信する

自動車向けアプリ ライブラリを使用する APK は、Automotive OS 専用トラックで配信する必要があります。

音声操作をサポートする

アプリを音声対応にすることで、ユーザーは一般的な操作をハンズフリーで行うことができます。 実装手順について詳しくは、メディアの音声操作をサポートするをご覧ください。テンプレート化されたメディアアプリで音声コマンドを受信した場合、検索結果で MediaBrowserService または MediaLibraryService を更新する必要はありません。代わりに、メディア再生テンプレートにアクションを追加して、ユーザーが再生クエリや検索クエリに基づいてより多くのコンテンツを見つけられるようにすることを検討してください。音声コマンドのサポートは、VC-1 品質 ガイドラインを満たすために必要です。

再生テンプレートを作成する

MediaPlaybackTemplate は、自動車向けアプリ ライブラリのメディアアプリにメディア再生 情報を表示します。このテンプレートでは、タイトルとカスタマイズ可能なアクションを含む ヘッダーを設定できます。メディア情報と 再生コントロールは、アプリの MediaSessionの状態に基づいてホストによって設定されます。

音楽プレーヤーに、サマー フィールディングの「Sounds of Spring」が表示され、ギターを弾く女性の正方形のポートレートが表示されています。

図 1: 上部にキューを開くヘッダー アクションがある MediaPlaybackTemplate

このコード例は、曲のキューを含む画面に移動できるヘッダー アクションを設定する再生テンプレートの例を作成する方法を示しています。

val playbackTemplate = MediaPlaybackTemplate.Builder()
      .setHeader(
        Header.Builder()
          .setStartHeaderAction(Action.BACK)
          .addEndHeaderAction(
                Action.Builder()
                  .setTitle(model.context.getString(R.string.queue_button_title))
                  .setIcon(
                    CarIcon.Builder(
                        IconCompat.createWithResource(
                          model.context,
                          R.drawable.gs_queue_music_vd_theme_24,
                        ))
                      .build())
                  .setOnClickListener(showQueueScreen())
                  .build())
          .setTitle(model.context.getString(R.string.media_playback_view_title))
          .build())
      .build()

MediaPlaybackTemplate を使用する場合は、 CarAppServiceMediaPlaybackManager を使用して MediaSession トークンを登録します。登録しないと、MediaPlaybackTemplate がホストに送信されたときにエラーが表示されます。

import androidx.car.app.media.MediaPlaybackManager


override fun onCreateSession(sessionInfo: SessionInfo): Session {
    return object : Session() {
        

        init {
          lifecycle.addObserver(
            LifecycleEventObserver { _, event ->
              if (event == ON_CREATE) {
                val token = ... // MediaSessionCompat.Token
                (carContext.getCarService(CarContext.MEDIA_PLAYBACK_SERVICE) as MediaPlaybackManager)
                  .registerMediaPlaybackToken(token)
              }
              ...
            }
          )
        }
    }
}

.registerMediaPlaybackToken は、メディア再生情報とコントロールを Android Auto に公開するために必要です。これは、ホストがメディア固有の通知を作成するためにも重要です。

標準の MediaSessionCompat.Token ではなく PlatformToken を使用する Media3 ライブラリを使用するアプリの場合は、セッションの基盤となるプラットフォーム トークン(session.platformToken)を返すカスタム SessionCommandMediaLibrarySession.Callback に実装する必要があります。CarAppService で、このカスタム コマンドをセッションに送信します。プラットフォーム トークンを受け取ったら、MediaSessionCompat.Token.fromToken(platformToken) を使用して変換し、この互換トークンを .registerMediaPlaybackToken() の自動車向けアプリ ライブラリに渡します。

テンプレートを使用してメディアを整理する

曲やアルバムなどのメディアをブラウジング用に整理するには、 SectionedItemTemplateを使用することをおすすめします。 このテンプレートを使用すると、GridSectionRowSectionを組み合わせて、画像 とテキスト アイテムのリストを混在させたレイアウトを作成できます。

音楽アプリのインターフェースに、最近再生した曲とアルバムが表示されています。縦に 2 列、横に 3 列のアルバムアートのポートレートが表示されています。

図 2: RowSection の後に GridSection が続く SectionedItemTemplate

TabTemplate 内で SectionedItemTemplate を使用する

アプリ内でメディアを分類する便利な方法の 1 つは、 SectionedItemTemplate 内で TabTemplate を使用することです。

val template =
      SectionedItemTemplate.Builder()...build();
val tabTemplate = 
      TabTemplate.Builder(tabCallback)
          .setTabContents(TabContents.Builder(template).build)
          .setHeaderAction(Action.APP_ICON)
          
          .build();

自動車向けアプリ ライブラリ 1.9 のコンポーネントと機能

自動車向けアプリ ライブラリ API バージョン 1.9 では、チップ、進行状況バー、凝縮アイテム、インタラクティブ ヘッダーと展開ヘッダー、スポットライト セクション、バナーなど、独自のブラウジング機能用のカスタマイズされたコンポーネントが導入されています。

音楽アプリのインターフェースに、最近再生した曲とアルバムが表示されています。縦に 2 列、横に 3 列のアルバムアートのポートレートが表示されています。

図 3: ChipsCondensed ItemsInteractive HeaderGrid ItemsMinimized Control Panel を含む SectionedItemTemplate

音楽アプリのインターフェースに、最近再生した曲とアルバムが表示されています。縦に 2 列、横に 3 列のアルバムアートのポートレートが表示されています。

図 4: Expanded HeaderSpotlight SectionsProgress Bars を備えた 2 つのメディア ブラウジング画面

これらの テンプレートを使用してメディアアプリのユーザー インターフェースを設計する方法について詳しくは、メディアアプリをご覧ください。

メディアをブラウジングする際は、注意散漫を最小限に抑えながら MediaPlaybackTemplateにすばやく移動できるようにすることが重要です。 MFT-1品質要件を満たすには、すべてのメディア ブラウジング画面から MediaPlaybackTemplateにアクセスできる必要があります。

SectionedItemTemplate を使用している場合は、メディア再生画面に移動するアクション ボタンを追加することで、これを実現できます。標準の自動車向けアプリ ライブラリの Action.MEDIA_PLAYBACK アクションを使用します。自動車向けアプリ ライブラリ API 1.9 以降を使用している場合、メディアアプリは 最小化されたコントロール パネルとしてこのアクションを表示します。これは MFT-1品質要件を満たすために必要です。他のテンプレートでは、ヘッダー アクションもこの目的で使用できます。

システムのメディア再生インテントを処理する

メディアカードなどのメディア再生サーフェスからアプリケーションが起動された場合は、ユーザーを MediaPlaybackTemplate に誘導する必要があります。ユーザーにシームレスなエクスペリエンスを提供するため、メディア アプリケーションでこの Intent Action を処理する必要があります。

自動車向けアプリ ライブラリ コンポーネント(CarAppActivity または トランポリン Activity)の インテント フィルタに androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK アクションを追加します。

onNewIntent() が呼び出されるように、アクティビティで singleTask または singleToplaunchMode を使用していることを確認します。

<activity
    android:name=".LaunchableTrampoline"
    android:exported="true"
    android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
    android:launchMode="singleTask"
    android:label="@string/app_name_cal"
    android:enabled="false">

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

    <intent-filter>
        <action android:name="android.intent.action.MAIN"/>
        <action android:name="androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK"/>
        <category android:name="android.intent.category.LAUNCHER"/>
    </intent-filter>
</activity>

Session クラスで onNewIntent() をオーバーライドして、受信したインテントを解析します。受信したインテントのアクションが SHOW_MEDIA_PLAYBACK と一致する場合は、ユーザーを再生中の画面に移動します。

@Override
public void onNewIntent(@NonNull Intent intent) {
    super.onNewIntent(intent);
    if (SHOW_MEDIA_PLAYBACK.equals(intent.getAction())) {
        ScreenManager screenManager = getCarContext().getCarService(ScreenManager.class);
        // Avoid redundant navigation if already on the playing screen
        if (screenManager.getTop() instanceof MyMediaPlayScreen) {
            return;
        }
        screenManager.push(MyMediaPlayScreen.createScreenFromPlaying(
                getCarContext(), mMediaSessionController));
    }
}

トランポリン アクティビティを使用している場合は、onCreate() 内でインテントのアクションを確認します。finish() を呼び出す前に、このアクションを CarAppActivity 作成インテントに渡します。

public class LaunchableTrampoline extends AppCompatActivity {
    private static final String SHOW_MEDIA_PLAYBACK = "androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent receivedIntent = getIntent();
        String action;

        if (SHOW_MEDIA_PLAYBACK.equals(receivedIntent.getAction())) {
            action = SHOW_MEDIA_PLAYBACK;
        } else {
            action = Intent.ACTION_MAIN;
        }

        Intent intent = new Intent(action);
        intent.setClassName(getPackageName(), "androidx.car.app.activity.CarAppActivity");
        startActivity(intent);
        finish();
    }
}