Medien-App mit Vorlage erstellen

Auf Vorlagen basierende Media-Apps befinden sich in der Betaphase
Derzeit kann jeder, der möchte, auf Vorlagen basierende Media-Apps in den Tracks für interne und geschlossene Tests im Google Play Store veröffentlichen. Die Veröffentlichung in offenen Tracks und Produktions-Tracks wird zu einem späteren Zeitpunkt zugelassen.

Media-Apps, die die Vorlagen der Car App Library verwenden, können das Browsen und die Wiedergabe von Medien anpassen und gleichzeitig dafür sorgen, dass die Nutzerfreundlichkeit für Autodisplays optimiert wird und Ablenkungen während der Fahrt minimiert werden.

In diesem Leitfaden wird davon ausgegangen, dass Sie bereits eine Media-App haben, die Audio auf einem Smartphone abspielt, und dass Ihre Media-App der Android-Architektur für Media-Apps entspricht. Mit der Car App Library können Sie die In-App-Oberfläche durch Vorlagen ersetzen, anstatt die Datenstruktur Medien-Apps für Autos entwickeln MediaBrowser zu verwenden. Du musst weiterhin ein MediaSession für die Wiedergabesteuerung und ein MediaBrowserService oder MediaLibraryService angeben, das für Empfehlungen und andere intelligente Funktionen verwendet wird.

Manifest der App konfigurieren

Zusätzlich zu den Schritten, die unter Android for Cars-App-Bibliothek verwenden beschrieben werden, sind für Vorlagen-Medien-Apps folgende Anforderungen zu erfüllen:

Kategoriensupport im Manifest deklarieren

In der CarAppService Ihrer App muss die androidx.car.app.category.MEDIA App-Kategorie für Autos im Intent-Filter deklariert werden.

<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>

Damit Ihre App auf die MediaPlaybackTemplate zugreifen kann, muss sie auch die Berechtigung androidx.car.app.MEDIA_TEMPLATES in ihrer Manifestdatei deklarieren:

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

Mindest-API-Level für Car-Apps festlegen

Medien-Apps, die die MediaPlaybackTemplate verwenden, werden nur in CAL API 8 und höher unterstützt. Achten Sie darauf, dass Ihr Mindest-Car App API level auf 8 festgelegt ist.

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

Symbol für die Namensnennung bereitstellen

Fügen Sie Medien-Apps, die mit der Programmbibliothek Car App erstellt wurden, ein Attributionssymbol hinzu.

Android Auto-Unterstützung deklarieren

Das Manifest Ihrer App muss Folgendes enthalten:

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

Fügen Sie dann die template-Deklaration zu automotive_app_desc.xml in Ihren XML-Ressourcen hinzu. Das sollte so aussehen:

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

Android Automotive OS-Unterstützung deklarieren

Es gibt zwei Möglichkeiten, eine Media-App mit aktivierter Car App Library unter Android Automotive OS bereitzustellen: als einzelnes APK oder als zwei separate APKs. Wenn Sie ein einzelnes APK verteilen, wird es auf Fahrzeugen unterstützt, die für Android Automotive OS mit dem Car App Library-Host aktiviert sind. Andernfalls wird auf eine MediaBrowserService- oder MediaLibraryService-Anwendung zurückgegriffen, auch bei älteren Android-Versionen (Android 10 bis Android 13). Wenn Sie zwei separate APKs verwenden, können Sie die neuen Ergänzungen der Car App Library-Version einfacher aktualisieren, ohne dass sich dies auf die MediaBrowserService- oder MediaLibraryService-Version Ihrer App auswirkt.

Einzelnes APK bereitstellen

Wenn Sie ein einzelnes APK für die Car App Library und die MediaBrowserService- oder MediaLibraryService-Versionen Ihrer App verteilen, ist es wichtig, dass Sie auf android:required="false" setzen.

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

Folgen Sie als Nächstes den Richtlinien für die Car App Library für AAOS und führen Sie eine startbare CarAppActivity (oder Trampolin-Aktivität) ein. Sie müssen die Aktivität im Manifest auf android:enabled="false" festlegen. Fügen Sie als Nächstes der MediaBrowserService-Deklaration ein Metadaten-Tag hinzu, das die CarAppActivity-Komponente als Ersatz angibt. Hier ein Beispielmanifest:

<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>

Play-Vertrieb

Ihr APK mit der Car App Library und MediaBrowserService oder MediaLibraryService sollte mit einem höheren Versionscode und minSdk für Android 14 (34) aktiviert werden.

Bereitstellung mit zwei APKs

Wenn Sie zwei separate APKs verteilen möchten, eine mit der Car App Library und eine mit MediaBrowserService oder MediaLibraryService, gehen Sie so vor, um sicherzustellen, dass die richtigen Fahrzeugfunktionen richtig ausgerichtet sind.

Wenn Sie ein separates APK für die Car App Library-Version Ihrer App erstellen, müssen Sie android.software.car.templates_host.media auf android:required=true festlegen. So wird sichergestellt, dass die App nur auf Android Automotive OS-Builds verteilt wird, die für die Unterstützung des Car App Library-Hosts zertifiziert sind.

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

Abgesehen von der Verwendung von android.software.car.templates_host.media und der Einstellung auf android:required=true oben, folgen Sie diesen Schritten, um Android Automotive OS für Ihre startbare Car App Library-Aktivität zu aktivieren.

Google Play-Vertrieb

Das APK, das die Car App Library verwendet, sollte über den speziellen Automotive OS-Track verteilt werden.

Sprachbefehle unterstützen

Wenn Sie Ihre App für die Sprachsteuerung optimieren, können Nutzer häufige Aktionen freihändig ausführen. Weitere Informationen zur Implementierung von Sprachaktionen für Medien Bei einer Media-App mit Vorlagen müssen Sie MediaBrowserService oder MediaLibraryService nicht mit Suchergebnissen aktualisieren, wenn Sie einen Sprachbefehl erhalten. Fügen Sie stattdessen eine Aktion in Ihre Vorlage für die Medienwiedergabe ein, damit der Nutzer basierend auf der Wiedergabe oder Suchanfrage weitere Inhalte finden kann. Die Unterstützung von Sprachbefehlen ist erforderlich, um die Qualitätsrichtlinie VC-1 zu erfüllen.

Wiedergabevorlage erstellen

Auf dem MediaPlaybackTemplate werden Informationen zur Medienwiedergabe in der Medien-App deiner Car App Library angezeigt. Mit dieser Vorlage kann ein Header mit einem Titel und anpassbaren Aktionen festgelegt werden, während die Medieninformationen und Wiedergabesteuerelemente vom Host basierend auf dem Status des MediaSession deiner App ausgefüllt werden.

Ein Musikplayer zeigt „Sounds of Spring“ von Summer Fielding mit einem quadratischen Porträt einer Frau, die Gitarre spielt.

Abbildung 1:MediaPlaybackTemplate mit einer Kopfzeilenaktion zum Öffnen der Warteschlange oben.

In diesem Codebeispiel wird gezeigt, wie Sie eine Beispielvorlage für die Wiedergabe erstellen, in der eine Header-Aktion festgelegt wird, mit der der Nutzer zu einem Bildschirm mit der Warteschlange von Songs navigieren kann.

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()

Wenn Sie MediaPlaybackTemplate verwenden, registrieren Sie ein MediaSession-Token mit dem MediaPlaybackManager in Ihrem CarAppService. Andernfalls wird ein Fehler angezeigt, wenn ein MediaPlaybackTemplate an den Host gesendet wird.

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 ist erforderlich, um Informationen zur Medienwiedergabe und Steuerelemente für Android Auto bereitzustellen. Das ist auch wichtig, damit der Host benachrichtigungen für bestimmte Medien erstellen kann.

Bei Apps, die die Media3-Bibliothek verwenden und einen PlatformToken anstelle eines Standard-MediaSessionCompat.Token verwenden, müssen Sie in Ihrem MediaLibrarySession.Callback einen benutzerdefinierten SessionCommand implementieren, der das zugrunde liegende Plattformtoken der Sitzung zurückgibt: session.platformToken. Senden Sie in CarAppService diesen benutzerdefinierten Befehl an die Sitzung. Sobald Sie das Plattform-Token erhalten haben, konvertieren Sie es mit MediaSessionCompat.Token.fromToken(platformToken) und übergeben Sie dieses kompatible Token an die Car App Library in .registerMediaPlaybackToken().

Medien mithilfe von Vorlagen organisieren

Wenn Sie Medien wie Songs oder Alben zum Durchsuchen organisieren möchten, empfehlen wir die Verwendung von SectionedItemTemplate. Damit können Sie GridSection und RowSection zusammen verwenden, um Layouts zu erstellen, in denen Listen von Bildern und Textelementen kombiniert werden.

Auf der Benutzeroberfläche einer Musik-App werden zuletzt gespielte Songs und Alben angezeigt, darunter zwei vertikale Reihen und drei horizontale Albumcover.

Abbildung 2:Ein SectionedItemTemplate mit einem RowSection, gefolgt von einem GridSection

SectionedItemTemplate in einem TabTemplate verwenden

Eine praktische Möglichkeit, Medien in Ihrer App zu kategorisieren, ist die Verwendung von SectionedItemTemplate in einem TabTemplate.

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

Komponenten und Funktionen der Car App Library 1.9

Mit der Car App Library 1.9 werden benutzerdefinierte Komponenten für einzigartige Browsingfunktionen eingeführt, z. B. Chips, Fortschrittsbalken, komprimierte Elemente, interaktive und erweiterte Kopfzeilen, Spotlight-Bereiche und Banner.

Auf der Benutzeroberfläche einer Musik-App werden zuletzt gespielte Songs und Alben angezeigt, darunter zwei vertikale Reihen und drei horizontale Albumcover.

Abbildung 3:Ein SectionedItemTemplate mit Chips, Condensed Items, einem Interactive Header, Grid Items und einem Minimized Control Panel

Auf der Benutzeroberfläche einer Musik-App werden zuletzt gespielte Songs und Alben angezeigt, darunter zwei vertikale Reihen und drei horizontale Albumcover.

Abbildung 4:Zwei Bildschirme zum Durchsuchen von Medien mit den Symbolen Expanded Header, Spotlight Sections und Progress Bars

Weitere Informationen zum Entwerfen der Benutzeroberfläche Ihrer Media-App mit diesen Vorlagen finden Sie unter Media-Apps.

Beim Durchsuchen von Medien muss der Nutzer schnell und ohne Ablenkung zur MediaPlaybackTemplate gelangen können.Um die Qualitätsanforderung MFT-1 zu erfüllen, muss Ihre App eine Möglichkeit bieten, von allen Medienbrowsing-Bildschirmen aus auf die MediaPlaybackTemplate zuzugreifen.

Wenn Sie SectionedItemTemplate verwenden, können Sie dies erreichen, indem Sie einen Aktionsbutton hinzufügen, der Sie zum Bildschirm für die Medienwiedergabe weiterleitet. Verwenden Sie die Standardaktion Action.MEDIA_PLAYBACK der Car App Library. In einer Media-App wird diese Aktion als minimierte Steuerkonsole angezeigt. Dies ist erforderlich, um die Qualitätsanforderung MFT-1 zu erfüllen, wenn Sie die Car App Library API 1.9 oder höher verwenden. Bei anderen Vorlagen ist eine Header-Aktion eine weitere Möglichkeit, dies zu erreichen.

System-Intents für die Medienwiedergabe verarbeiten

Der Nutzer muss zur MediaPlaybackTemplate weitergeleitet werden, wenn eine Anwendung über eine Systemoberfläche zur Medienwiedergabe, z. B. eine Medienkarte, gestartet wird. Wir verlangen, dass Media-Anwendungen dieses Intent Action verarbeiten, um Nutzern eine nahtlose Nutzung zu ermöglichen.

Fügen Sie die Aktion androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK dem Intent-Filter Ihrer Car App Library-Komponente (entweder CarAppActivity oder Ihrem Trampolin Activity) hinzu.

Achten Sie darauf, dass für Ihre Aktivität ein launchMode von singleTask oder singleTop verwendet wird, damit onNewIntent() aufgerufen wird.

<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>

Überschreiben Sie in der Klasse Session die Methode onNewIntent(), um den eingehenden Intent zu parsen. Wenn die eingehende Intent-Aktion mit SHOW_MEDIA_PLAYBACK übereinstimmt, leite den Nutzer zum Bildschirm „Wird gerade wiedergegeben“ weiter.

@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));
    }
}

Wenn du ein Trampolin-Training verwendest, suche in onCreate() nach der Intent-Aktion. Übergeben Sie diese Aktion an den Intent zum Erstellen von CarAppActivity, bevor Sie finish() aufrufen.

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();
    }
}