Créer une application multimédia basée sur des modèles

Les applications multimédias basées sur des modèles sont en version bêta
Pour le moment, tout le monde peut publier des applications multimédias basées sur des modèles dans les canaux de test interne et de test fermé du Google Play Store. La publication dans les canaux ouverts et de production sera autorisée ultérieurement.

Les applications multimédias qui utilisent les modèles de la bibliothèque Car App peuvent personnaliser leur expérience de navigation et de lecture multimédia tout en s'assurant qu'elle est optimisée pour les écrans de voiture et qu'elle minimise les distractions pendant la conduite.

Dans ce guide, nous partons du principe que vous disposez déjà d'une application multimédia qui lit du contenu audio sur un téléphone et que cette application est conforme à l'architecture des applications multimédias Android. La bibliothèque Car App vous permet de remplacer l'expérience intégrée à l'application par des modèles au lieu de ceux créés à l'aide de la structure de données Créer des applications multimédias pour voitures MediaBrowser. Vous devez toujours fournir un MediaSession pour les commandes de lecture, ainsi qu'un MediaBrowserService ou un MediaLibraryService, qui est utilisé pour les recommandations et d'autres expériences intelligentes.

Configurer le fichier manifeste de votre application

En plus des étapes décrites dans Utiliser la bibliothèque d'applications Android for Cars, les éléments suivants sont requis pour les applications multimédias basées sur des modèles :

Déclarer la catégorie compatible dans votre fichier manifeste

Votre application doit déclarer la androidx.car.app.category.MEDIA catégorie d'applications automobiles dans le filtre d'intent de son 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>

Pour accéder à MediaPlaybackTemplate, votre application doit également déclarer l'autorisation androidx.car.app.MEDIA_TEMPLATES dans son fichier manifeste :

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

Définir le niveau d'API minimal de l'application pour voiture

Les applications multimédias qui utilisent le MediaPlaybackTemplate ne sont compatibles qu'avec l'API CAL 8 et versions ultérieures. Assurez-vous que votre Car App API level minimal est défini sur 8.

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

Fournir une icône d'attribution

Veillez à ajouter une icône d'attribution pour les applications multimédias créées à l'aide de la bibliothèque Car App.

Déclarer la prise en charge d'Android Auto

Assurez-vous que les éléments suivants sont inclus dans le fichier manifeste de votre application :

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

Ajoutez ensuite la déclaration template à automotive_app_desc.xml dans vos ressources XML. Elle doit se présenter comme suit :

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

Déclarer la prise en charge d'Android Automotive OS

Vous pouvez distribuer une application multimédia compatible avec la bibliothèque Car App sur Android Automotive OS de deux manières différentes : sous forme d'un seul APK ou de deux APK distincts. Si vous distribuez un seul APK, il sera compatible avec les véhicules compatibles avec Android Automotive OS avec l'hôte de la bibliothèque Car App et reviendra à une application MediaBrowserService ou MediaLibraryService si ce n'est pas le cas, même pour les anciennes versions d'Android (Android 10 à Android 13). Si vous choisissez de distribuer deux APK distincts, vous pouvez plus facilement mettre à jour les nouvelles fonctionnalités de la version de la bibliothèque Car App sans craindre d'impacter la version MediaBrowserService ou MediaLibraryService de votre application.

Distribuer un seul APK

Lorsque vous distribuez un seul APK pour les versions de la bibliothèque Car App et MediaBrowserService ou MediaLibraryService de votre application, il est essentiel de définir le "" sur android:required="false".

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

Suivez ensuite les consignes de la bibliothèque Car App pour AAOS et introduisez une CarAppActivity lançable (ou une activité de trampoline). Vous devez définir l'activité sur android:enabled="false" dans le fichier manifeste. Ajoutez ensuite un tag de métadonnées à la déclaration MediaBrowserService indiquant le composant CarAppActivity comme remplacement. Consultez l'exemple de fichier manifeste ci-dessous :

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

Distribution Play

Votre APK avec la bibliothèque Car App et MediaBrowserService ou MediaLibraryService doit être activé avec un code de version supérieur et un minSdk ciblant Android 14 (34).

Distribuer avec deux APK

Pour distribuer deux APK distincts, l'un utilisant la bibliothèque Car App et l'autre utilisant MediaBrowserService ou MediaLibraryService, procédez comme suit pour vous assurer que les fonctionnalités appropriées du véhicule sont correctement ciblées.

Lorsque vous créez un APK distinct pour la version de la bibliothèque Car App de votre application, vous devez définir android.software.car.templates_host.media sur android:required=true. Cela garantit que l'application n'est distribuée que sur les builds Android Automotive OS certifiés compatibles avec l'hôte de la bibliothèque Car App.

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

En plus d'utiliser android.software.car.templates_host.media et de le définir sur android:required=true ci-dessus, procédez comme suit pour activer Android Automotive OS pour votre activité lançable de la bibliothèque Car App.

Distribution Play

L'APK qui utilise la bibliothèque Car App doit être distribué dans le canal dédié à Automotive OS.

Accepter les commandes vocales

Activez les commandes vocales dans votre application pour permettre aux utilisateurs d'effectuer des actions courantes en mode mains libres. Pour obtenir des instructions d'implémentation plus détaillées, consultez Accepter les commandes vocales pour les contenus multimédias. Avec une application multimédia basée sur des modèles, si vous recevez une commande vocale, vous n'avez pas besoin de mettre à jour votre MediaBrowserService ou MediaLibraryService avec les résultats de recherche. Envisagez plutôt d'ajouter une action dans votre modèle de lecture multimédia pour permettre à l'utilisateur de trouver plus de contenu en fonction de cette lecture ou de cette requête de recherche. La prise en charge des commandes vocales est requise pour respecter la VC-1 consigne de qualité guideline.

Créer votre modèle de lecture

Le MediaPlaybackTemplate affiche les informations de lecture multimédia dans votre application multimédia de la bibliothèque Car App. Ce modèle permet de définir un en-tête avec un titre et des actions personnalisables, tandis que les informations multimédias et les commandes de lecture sont renseignées par l'hôte en fonction de l'état du MediaSession de votre application.

Un lecteur de musique affiche &quot;Sounds of Spring&quot; de Summer Fielding avec un portrait carré d&#39;une femme jouant de la guitare.

Figure 1 : MediaPlaybackTemplate avec une action d'en-tête permettant d'ouvrir la file d'attente en haut.

Cet exemple de code montre comment créer un exemple de modèle de lecture qui définit une action d'en-tête permettant à l'utilisateur d'accéder à un écran contenant la file d'attente des titres.

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

Lorsque vous utilisez MediaPlaybackTemplate, enregistrez un MediaSession jeton à l'aide de MediaPlaybackManager dans votre CarAppService. Si vous ne le faites pas, une erreur s'affiche lorsqu'un MediaPlaybackTemplate est envoyé à l'hôte.

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 est nécessaire pour exposer les informations et les commandes de lecture multimédia à Android Auto. Il est également important que l'hôte crée des notifications spécifiques aux contenus multimédias.

Pour les applications qui utilisent la bibliothèque Media3, qui utilise un PlatformToken plutôt qu'un MediaSessionCompat.Token standard, vous devrez implémenter une SessionCommand personnalisée dans votre MediaLibrarySession.Callback qui renvoie le jeton de plate-forme sous-jacent de la session : session.platformToken. Dans votre CarAppService, envoyez cette commande personnalisée à la session. Une fois que vous avez reçu le jeton de plate-forme, convertissez-le à l'aide de MediaSessionCompat.Token.fromToken(platformToken) et transmettez ce jeton de compatibilité à la bibliothèque Car App dans .registerMediaPlaybackToken().

Organiser les contenus multimédias à l'aide de modèles

Pour organiser les contenus multimédias à parcourir, tels que des titres ou des albums, nous vous recommandons d'utiliser le SectionedItemTemplate, qui vous permet d'utiliser les GridSection et RowSection ensemble pour créer des mises en page qui combinent des listes d'images et des éléments de texte.

L&#39;interface d&#39;une application musicale affiche les titres et albums récemment écoutés, y compris deux rangées verticales et trois rangées horizontales de pochettes d&#39;album.

Figure 2 : SectionedItemTemplate contenant un RowSection suivi d'un GridSection

Utiliser SectionedItemTemplate dans un TabTemplate

Un moyen pratique de classer les contenus multimédias dans votre application consiste à utiliser les SectionedItemTemplate dans un TabTemplate.

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

Composants et fonctionnalités de la bibliothèque Car App 1.9

La version 1.9 de l'API de la bibliothèque Car App introduit des composants personnalisés pour des fonctionnalités de navigation uniques, tels que des chips, des barres de progression, des éléments condensés, un en-tête interactif et développé, des sections de mise en avant et des bannières.

L&#39;interface d&#39;une application musicale affiche les titres et albums récemment écoutés, y compris deux rangées verticales et trois rangées horizontales de pochettes d&#39;album.

Figure 3 : SectionedItemTemplate contenant des Chips, des Condensed Items, un Interactive Header, des Grid Items et un Minimized Control Panel

L&#39;interface d&#39;une application musicale affiche les titres et albums récemment écoutés, y compris deux rangées verticales et trois rangées horizontales de pochettes d&#39;album.

Figure 4 : Deux écrans de navigation multimédia présentant l'Expanded Header, les Spotlight Sections et les Progress Bars

Pour en savoir plus sur la conception de l'interface utilisateur de votre application multimédia à l'aide de ces modèles, consultez Applications multimédias.

Lorsque vous parcourez des contenus multimédias, il est important que l'utilisateur puisse accéder rapidement à MediaPlaybackTemplate avec un minimum de distraction.Pour répondre à l'exigence de qualité MFT-1, votre application doit permettre d'accéder à MediaPlaybackTemplate depuis tous les écrans de navigation multimédia.

Si vous utilisez SectionedItemTemplate, vous pouvez y parvenir en ajoutant un bouton d'action qui vous redirige vers l'écran de lecture multimédia. Utilisez l'action standard Action.MEDIA_PLAYBACK de la bibliothèque Car App. Une application multimédia affichera cette action sous la forme d'un panneau de commande réduit, ce qui est nécessaire pour répondre à l'exigence de qualité MFT-1 si vous utilisez l'API 1.9 ou une version ultérieure de la bibliothèque Car App. Pour les autres modèles, une action d'en-tête est une autre façon d'y parvenir.

Gérer les intents de lecture multimédia du système

Il est nécessaire de rediriger l'utilisateur vers MediaPlaybackTemplate lorsqu'une application est lancée à partir d'une surface de lecture multimédia du système, telle qu'une fiche multimédia. Nous exigeons que les applications multimédias gèrent cette Intent Action afin d' offrir une expérience fluide aux utilisateurs.

Ajoutez l'action androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK au filtre d'intent de votre composant de la bibliothèque Car App (soit CarAppActivity ou votre trampoline Activity).

Assurez-vous que votre activité utilise un launchMode de singleTask ou singleTop afin que onNewIntent() soit appelé.

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

Dans votre classe Session, remplacez onNewIntent() pour analyser l'intent entrant. Si l'action d'intent entrant correspond à SHOW_MEDIA_PLAYBACK, redirigez l'utilisateur vers l'écran de lecture en cours.

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

Si vous utilisez une activité de trampoline, recherchez l'action d'intent dans onCreate(). Transmettez cette action à l'intent de création CarAppActivity avant d'appeler finish().

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