Creare un'app multimediale basata su modelli

Le app multimediali basate su modelli sono in versione beta
Al momento, chiunque può pubblicare app multimediali basate su modelli nei canali di test interni e chiusi del Google Play Store. La pubblicazione nei canali aperti e di produzione sarà consentita in un secondo momento.

Le app multimediali che utilizzano i modelli della libreria di app per auto possono personalizzare la propria esperienza di riproduzione e navigazione dei contenuti multimediali, garantendo al contempo che l'esperienza sia ottimizzata per gli schermi delle auto e riduca al minimo le distrazioni durante la guida.

Questa guida presuppone che tu abbia già un'app multimediale che riproduce audio su uno smartphone e che la tua app multimediale sia conforme all'architettura delle app multimediali per Android. La libreria di app per auto ti consente di sostituire l'esperienza in-app con modelli anziché con quelli creati utilizzando la struttura dei dati Crea app multimediali per auto MediaBrowser. Devi comunque fornire un MediaSession per i controlli di riproduzione e un MediaBrowserService o MediaLibraryService, che viene utilizzato per i consigli e altre esperienze intelligenti.

Configurare il manifest dell'app

Oltre ai passaggi descritti in Utilizzare la libreria di app Android for Cars, le seguenti operazioni sono richieste per le app multimediali basate su modelli:

Dichiarare il supporto delle categorie nel manifest

La tua app deve dichiarare la androidx.car.app.category.MEDIA categoria di app per auto nel filtro per intent del relativo 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>

Per accedere a MediaPlaybackTemplate, la tua app deve anche dichiarare l'autorizzazione androidx.car.app.MEDIA_TEMPLATES nel file manifest:

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

Impostare il livello API minimo dell'app per auto

Le app multimediali che utilizzano MediaPlaybackTemplate sono supportate solo nell'API CAL 8 e versioni successive. Assicurati che il valore minimo di Car App API level sia impostato su 8.

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

Fornire un'icona di attribuzione

Assicurati di aggiungere un'icona di attribuzione per le app multimediali create utilizzando la raccolta di app per auto.

Dichiara il supporto di Android Auto

Assicurati che nel manifest dell'app sia incluso quanto segue:

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

Poi, aggiungi la dichiarazione del modello a automotive_app_desc.xml nelle risorse XML. Dovrebbe avere il seguente aspetto:

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

Dichiarare il supporto di Android Automotive OS

Esistono due modi diversi per distribuire un'app multimediale abilitata per la libreria di app per auto su Android Automotive OS: come singolo APK o come due APK separati. Se distribuisci un singolo APK, questo supporterà i veicoli abilitati per Android Automotive OS con l'host Car App Library e tornerà a un'applicazione MediaBrowserService o MediaLibraryService in caso contrario, anche per versioni precedenti di Android (Android 10 - Android 13). Se scegli di distribuire due APK separati, puoi aggiornare più facilmente le nuove aggiunte alla versione della libreria di app per auto senza temere di influire sulla versione MediaBrowserService o MediaLibraryService della tua app.

Distribuire un singolo APK

Quando distribuisci un singolo APK per la libreria di app per auto e le versioni MediaBrowserService o MediaLibraryService della tua app, è fondamentale impostare "" su android:required="false".

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

Poi, segui le linee guida della libreria di app per auto per AAOS e introduci un'attività CarAppActivity avviabile (o trampoline). Devi impostare l'attività su android:enabled="false" nel manifest. A questo punto, aggiungi un tag di metadati alla dichiarazione MediaBrowserService che indica il componente CarAppActivity come sostituzione. Vedi il seguente esempio di file manifest:

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

Distribuzione su Google Play

L'APK con la libreria di app per auto e MediaBrowserService o MediaLibraryService deve essere abilitato con un codice della versione superiore e minSdk che ha come target Android 14 (34).

Distribuzione con due APK

Per distribuire due APK separati, uno che utilizza la libreria di app per auto e l'altro che utilizza MediaBrowserService o MediaLibraryService, segui questi passaggi per assicurarti che le funzionalità del veicolo corrette siano prese di mira correttamente.

Quando crei un APK separato per la versione della tua app della libreria di app per auto, devi impostare android.software.car.templates_host.media su android:required=true. In questo modo, l'app viene distribuita solo su build di Android Automotive OS certificate con supporto per l'host Car App Library.

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

Oltre a utilizzare android.software.car.templates_host.media e impostarlo su android:required=true sopra, segui questi passaggi per attivare Android Automotive OS per l'attività avviabile della raccolta di app per auto.

Play Distribution

L'APK che utilizza la raccolta di app per auto deve essere distribuito nel canale dedicato ad Android Automotive OS.

Supportare le azioni vocali

Attiva i comandi vocali nella tua app per consentire agli utenti di completare le azioni comuni senza usare le mani. Per istruzioni di implementazione più dettagliate, consulta Supportare le azioni vocali per i contenuti multimediali. Con un'app multimediale basata su modelli, se ricevi un comando vocale, non devi aggiornare MediaBrowserService o MediaLibraryService con i risultati di ricerca. Valuta invece la possibilità di aggiungere un'azione nel modello di riproduzione dei contenuti multimediali per consentire all'utente di trovare altri contenuti in base alla riproduzione o alla query di ricerca. Il supporto dei comandi vocali è necessario per soddisfare le linee guida per la qualità VC-1.

Creare il modello di riproduzione

MediaPlaybackTemplate mostra le informazioni sulla riproduzione dei contenuti multimediali nell'app multimediale della raccolta di app per l'auto. Questo modello consente di impostare un'intestazione con un titolo e azioni personalizzabili, mentre le informazioni sui contenuti multimediali e i controlli di riproduzione vengono compilati dall'host in base allo stato di MediaSession dell'app.

Un lettore musicale mostra Sounds of Spring di Summer Fielding con un
     ritratto quadrato di una donna che suona la chitarra.

Figura 1: MediaPlaybackTemplate con un'azione di intestazione per aprire la coda in alto.

Questo esempio di codice mostra come creare un modello di riproduzione di esempio che imposta un'azione di intestazione che consente all'utente di passare a una schermata con la coda di brani.

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

Quando utilizzi MediaPlaybackTemplate, registra un token MediaSession utilizzando MediaPlaybackManager in CarAppService. In caso contrario, viene visualizzato un errore quando viene inviato un MediaPlaybackTemplate all'host.

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 è necessario per mostrare informazioni e controlli di riproduzione dei contenuti multimediali ad Android Auto. Questo è importante anche per l'host per creare notifiche specifiche per i contenuti multimediali.

Per le app che utilizzano la libreria Media3, che utilizzano un PlatformToken anziché un MediaSessionCompat.Token standard, dovrai implementare un SessionCommand personalizzato nel tuo MediaLibrarySession.Callback che restituisce il token della piattaforma sottostante della sessione: session.platformToken. In CarAppService invia questo comando personalizzato alla sessione. Una volta ricevuto il token della piattaforma, convertilo utilizzando MediaSessionCompat.Token.fromToken(platformToken) e trasmetti questo token di compatibilità alla libreria di app per auto in .registerMediaPlaybackToken().

Organizzare i contenuti multimediali utilizzando i modelli

Per organizzare i contenuti multimediali da sfogliare, come brani o album, ti consigliamo di utilizzare SectionedItemTemplate, che ti consente di utilizzare GridSection e RowSection insieme per creare layout che combinano elenchi di immagini e elementi di testo.

L&#39;interfaccia di un&#39;app musicale mostra brani e album ascoltati di recente,
     tra cui due righe verticali e tre ritratti orizzontali di copertine di album.

Figura 2: un SectionedItemTemplate contenente un RowSection seguito da un GridSection

Utilizzo di SectionedItemTemplate all'interno di TabTemplate

Un modo pratico per classificare i contenuti multimediali all'interno dell'app è utilizzare SectionedItemTemplate all'interno di un TabTemplate.

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

Componenti e funzionalità della libreria di app per auto 1.9

La versione 1.9 dell'API Car App Library introduce componenti personalizzati per funzionalità di navigazione uniche, come chip, barre di avanzamento, elementi compressi, intestazione interattiva ed espansa, sezioni in evidenza e banner.

L&#39;interfaccia di un&#39;app musicale mostra brani e album ascoltati di recente,
     tra cui due righe verticali e tre ritratti orizzontali di copertine di album.

Figura 3: un SectionedItemTemplate contenente Chips, Condensed Items, un Interactive Header, Grid Items e un Minimized Control Panel

L&#39;interfaccia di un&#39;app musicale mostra brani e album ascoltati di recente,
     tra cui due righe verticali e tre ritratti orizzontali di copertine di album.

Figura 4: due schermate di navigazione multimediale con Expanded Header, Spotlight Sections e Progress Bars

Per ulteriori dettagli su come progettare l'interfaccia utente della tua app multimediale utilizzando questi modelli, consulta App multimediali.

Quando sfoglia i contenuti multimediali, è importante che l'utente possa passare rapidamente alla MediaPlaybackTemplate con distrazioni minime.Per soddisfare il requisito di qualità MFT-1, la tua app deve avere un modo per accedere alla MediaPlaybackTemplate da tutte le schermate di navigazione dei contenuti multimediali.

Se utilizzi SectionedItemTemplate, puoi farlo aggiungendo un pulsante di azione che ti porta alla schermata di riproduzione dei contenuti multimediali. Utilizza l'azione standard della libreria di app per auto Action.MEDIA_PLAYBACK. Un'app multimediale mostrerà questa azione come un pannello di controllo ridotto al minimo, che è necessario per soddisfare il requisito di qualità MFT-1 se utilizzi l'API Car App Library 1.9 o versioni successive. Per altri modelli, un'azione di intestazione è un altro modo per raggiungere questo obiettivo.

Gestire gli intent di riproduzione multimediale del sistema

È necessario indirizzare l'utente a MediaPlaybackTemplate quando un'applicazione viene avviata da una superficie di riproduzione multimediale del sistema, ad esempio una scheda multimediale. Richiediamo che le applicazioni multimediali gestiscano questo Intent Action per offrire agli utenti un'esperienza fluida.

Aggiungi l'azione androidx.car.app.media.action.SHOW_MEDIA_PLAYBACK al filtro per intent del componente della libreria di app per auto (CarAppActivity o Activity).

Assicurati che l'attività utilizzi un launchMode di singleTask o singleTop in modo che venga richiamato onNewIntent().

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

Nella classe Session, esegui l'override di onNewIntent() per analizzare l'intent in entrata. Se l'azione dell'intent in entrata corrisponde a SHOW_MEDIA_PLAYBACK, indirizza l'utente alla schermata In riproduzione.

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

Se utilizzi un'attività di trampolino elastico, controlla l'azione di intent all'interno di onCreate(). Passa questa azione all'intent di creazione CarAppActivity prima di chiamare 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();
    }
}