Utilizzare la libreria di app di Android for Cars

La libreria di app Android for Cars consente di portare nell'auto le app di navigazione, PDI (Punti d'interesse) e IoT (Internet of Things). Lo fa fornendo un insieme di modelli progettati per soddisfare gli standard di distrazione del conducente e prendendosi cura di dettagli come la varietà di fattori dello schermo dell'auto e le modalità di inserimento.

Questa guida fornisce una panoramica dei concetti e delle funzionalità principali della libreria e illustra la procedura di configurazione di un'app di base.

Prima di iniziare

  1. Consulta le pagine Progettazione per la guida che riguardano la raccolta di app per auto
  2. Esamina i termini e i concetti chiave nella sezione seguente.
  3. Acquisisci familiarità con l'interfaccia utente del sistema Android Auto e con il design di Android Automotive OS.
  4. Consulta le note di rilascio.
  5. Esamina i Samples.

Termini e concetti chiave

Modelli e modelli
L'interfaccia utente è rappresentata da un grafo di oggetti modello che possono essere disposti in modi diversi, come consentito dal modello a cui appartengono. I modelli sono un sottoinsieme dei modelli che possono fungere da radice in questi grafici. I modelli includono le informazioni da mostrare all'utente sotto forma di testo e immagini, nonché gli attributi per configurare aspetti dell'aspetto visivo di queste informazioni, ad esempio i colori del testo o le dimensioni delle immagini. L'host converte i modelli in visualizzazioni progettate per soddisfare gli standard di distrazione del conducente e si occupa di dettagli come la varietà di fattori dello schermo dell'auto e le modalità di input.
Moderatore
L'host è il componente di backend che implementa le funzionalità offerte dalle API della libreria in modo che la tua app possa essere eseguita nell'auto. Le responsabilità dell'host vanno dalla scoperta della tua app e dalla gestione del suo ciclo di vita alla conversione dei modelli in visualizzazioni e alla notifica all'app delle interazioni degli utenti. Sui dispositivi mobili, questo host è implementato da Android Auto. Su Android Automotive OS, questo host viene installato come app di sistema.
Limitazioni dei modelli
Modelli diversi applicano limitazioni ai contenuti dei modelli. Ad esempio, i modelli di elenco hanno limiti al numero di elementi che possono essere presentati all'utente. I modelli hanno anche limitazioni nel modo in cui possono essere collegati per formare il flusso di un'attività. Ad esempio, l'app può inviare al massimo cinque modelli alla serie di schermate. Per ulteriori dettagli, consulta la sezione Limitazioni dei modelli.
Screen
Screen è una classe fornita dalla biblioteca che le app implementano per gestire l'interfaccia utente presentata all'utente. Un Screen ha un ciclo di vita e fornisce il meccanismo per l'app per inviare il modello da visualizzare quando lo schermo è visibile. Le istanze Screen possono anche essere spostate in un stack Screen e viceversa, il che garantisce che rispettino le limitazioni del flusso dei modelli.
CarAppService
CarAppService è una classe Service astratta che l'app deve implementare ed esportare per essere scoperta e gestita dall'host. Il CarAppService della tua app è responsabile di verificare che una connessione all'host sia attendibile utilizzando createHostValidator e successivamente di fornire istanze Session per ogni connessione utilizzando onCreateSession.
Session

Session è una classe astratta che la tua app deve implementare e restituire utilizzando CarAppService.onCreateSession. Serve come punto di accesso per visualizzare le informazioni sullo schermo dell'auto. Ha un ciclo di vita che indica lo stato corrente dell'app sullo schermo dell'auto, ad esempio quando è visibile o nascosta.

Quando viene avviato un Session, ad esempio al primo avvio dell'app, l'host richiede la visualizzazione del Screen iniziale utilizzando il metodo onCreateScreen.

Installare la libreria di app per auto

Consulta la pagina di rilascio della libreria Jetpack per istruzioni su come aggiungerla alla tua app.

Configura i file manifest dell'app

Prima di poter creare l'app per auto, configura i file manifest dell'app come segue.

Dichiara il tuo CarAppService

L'host si connette alla tua app tramite l'implementazione di CarAppService. Dichiari questo servizio nel file manifest per consentire all'host di rilevare e connettersi alla tua app.

Devi anche dichiarare la categoria dell'app nell'elemento <category> del filtro per intent dell'app. Consulta l'elenco delle categorie di app supportate per i valori consentiti per questo elemento.

Il seguente snippet di codice mostra come dichiarare un servizio di app per auto per un'app di punti di interesse nel file manifest:

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

Categorie di app supportate

Dichiara la categoria della tua app aggiungendo uno o più dei seguenti valori di categoria nel filtro per intent quando dichiari CarAppService come descritto nella sezione precedente:

  • androidx.car.app.category.NAVIGATION: un'app che fornisce indicazioni stradali passo passo. Consulta Creare app di navigazione per auto.
  • androidx.car.app.category.POI: un'app che fornisce funzionalità pertinenti per trovare punti d'interesse come parcheggi, stazioni di ricarica e stazioni di servizio. Consulta Creare app di punti d'interesse per auto.
  • androidx.car.app.category.IOT: un'app che consente agli utenti di eseguire azioni pertinenti sui dispositivi connessi dall'interno dell'auto. Consulta Creare app per l'internet of things per le auto.
  • androidx.car.app.category.WEATHER: un'app che consente agli utenti di visualizzare informazioni meteorologiche pertinenti relative alla loro posizione attuale o al loro percorso. Consulta Creare app meteo per le auto.

Consulta l'articolo Qualità delle app per Android per le auto per le descrizioni dettagliate di ogni categoria e dei criteri per l'appartenenza delle app a una categoria.

Specifica il nome e l'icona dell'app

Devi specificare un nome e un'icona per l'app che l'host può utilizzare per rappresentare la tua app nell'interfaccia utente di sistema.

Puoi specificare il nome e l'icona dell'app utilizzati per rappresentarla utilizzando gli attributi label e icon del CarAppService:

...
<service
   android:name=".MyCarAppService"
   android:exported="true"
   android:label="@string/my_app_name"
   android:icon="@drawable/my_app_icon">
   ...
</service>
...

Se l'etichetta o l'icona non sono dichiarate nell'elemento <service>, l'host ricorre ai valori specificati per l'elemento <application>.

Impostare un tema personalizzato

Per impostare un tema personalizzato per l'app per auto, aggiungi un elemento <meta-data> nel file manifest, come segue:

<meta-data
    android:name="androidx.car.app.theme"
    android:resource="@style/MyCarAppTheme />

Dichiara poi la risorsa di stile per impostare i seguenti attributi per il tema dell'app per auto personalizzata:

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

Livello API app per auto

La libreria di app per auto definisce i propri livelli API in modo che tu possa sapere quali funzionalità della libreria sono supportate dall'host del modello su un veicolo. Per recuperare il livello API dell'app per auto più elevato supportato da un host, utilizza il metodo getCarAppApiLevel().

Dichiara il livello API dell'app per auto minimo supportato dalla tua app nel AndroidManifest.xml file:

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

Consulta la documentazione relativa all'annotazione RequiresCarApi per informazioni dettagliate su come mantenere la compatibilità con le versioni precedenti e dichiarare il livello API minimo richiesto per utilizzare una funzionalità. Per una definizione del livello di API richiesto per utilizzare una determinata funzionalità della libreria di app per auto, consulta la documentazione di riferimento di CarAppApiLevels.

Crea CarAppService e Session

L'app deve estendere la classe CarAppService e implementare il suo metodo onCreateSession, che restituisce un'istanza Session corrispondente alla connessione corrente all'host:

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

L'istanza Session è responsabile di restituire l'istanza Screen da utilizzare la prima volta che l'app viene avviata:

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

Per gestire gli scenari in cui l'app per auto deve essere avviata da una schermata diversa dalla schermata Home o di destinazione dell'app, ad esempio la gestione dei link diretti, puoi precompilare una serie di schermate precedenti utilizzando ScreenManager.push prima di tornare da onCreateScreen. Il pre-seeding consente agli utenti di tornare alle schermate precedenti dalla prima schermata visualizzata dalla tua app.

Creare la schermata iniziale

Puoi creare le schermate visualizzate dalla tua app definendo classi che estendono la classe Screen e implementando il relativo metodo onGetTemplate, che restituisce l'istanza Template che rappresenta lo stato dell'interfaccia utente da visualizzare nello schermo dell'auto.

Lo snippet seguente mostra come dichiarare un Screen che utilizza un modello PaneTemplate per visualizzare una semplice stringa "Hello world!":

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

La classe CarContext

La classe CarContext è una sottoclasse di ContextWrapper accessibile alle istanze Session e Screen. Fornisce accesso ai servizi per auto, ad esempio ScreenManager per la gestione della pila di schermate, AppManager per le funzionalità generali relative alle app, come l'accesso all'oggetto Surface per disegnare mappe e NavigationManager utilizzato dalle app di navigazione passo passo per comunicare metadati di navigazione e altri eventi correlati alla navigazione con l'host.

Consulta Accedere ai modelli di navigazione per un elenco completo delle funzionalità della libreria disponibili per le app di navigazione.

CarContext offre anche altre funzionalità, ad esempio consente di caricare risorse drawable utilizzando la configurazione sullo schermo dell'auto, avviare un'app nell'auto utilizzando gli intent e indicare se la tua app deve mostrare la mappa in tema scuro.

Implementare la navigazione tra le schermate

Le app spesso presentano una serie di schermate diverse, ciascuna con possibly differenti modelli che l'utente può esplorare mentre interagisce con la interfaccia visualizzata nella schermata.

La classe ScreenManager fornisce un insieme di schermate che puoi utilizzare per inviare schermate che possono essere visualizzate automaticamente quando l'utente seleziona un pulsante Indietro sullo schermo dell'auto o utilizza il pulsante Indietro hardware disponibile in alcune auto.

Lo snippet seguente mostra come aggiungere un'azione Indietro a un modello di messaggio, nonché un'azione che mostra una nuova schermata quando viene selezionata dall'utente:

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

L'oggetto Action.BACK è un Action standard che richiama automaticamente ScreenManager.pop. Questo comportamento può essere ignorato utilizzando l'istanza OnBackPressedDispatcher disponibile nel CarContext.

Per garantire che l'app sia sicura da usare durante la guida, la serie di schermate può avere una profondità massima di cinque schermate. Per ulteriori dettagli, consulta la sezione Limitazioni dei modelli.

Aggiornare i contenuti di un modello

L'app può richiedere l'invalidazione dei contenuti di un Screen chiamando il metodo Screen.invalidate. Successivamente, l'host richiama il metodo Screen.onGetTemplate della tua app per recuperare il modello con i nuovi contenuti.

Quando aggiorni un Screen, è importante comprendere i contenuti specifici del modello che possono essere aggiornati in modo che l'host non conteggia il nuovo modello ai fini della quota dei modelli. Per ulteriori dettagli, consulta la sezione Limitazioni dei modelli.

Ti consigliamo di strutturare le schermate in modo che esista una mappatura uno a uno tra un Screen e il tipo di templata restituito tramite l'implementazione di onGetTemplate.

Disegnare mappe

Le app di navigazione e relative a punti d'interesse (PDI) che utilizzano i seguenti modelli possono elaborare mappe accedendo a un Surface:

Modello Autorizzazione del modello Indicazioni sulle categorie
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES Navigazione
MapWithContentTemplate androidx.car.app.NAVIGATION_TEMPLATES OPPURE
androidx.car.app.MAP_TEMPLATES
Navigazione, PDV, Meteo
MapTemplate (disponibile) androidx.car.app.NAVIGATION_TEMPLATES Navigazione
PlaceListNavigationTemplate (non più supportato) androidx.car.app.NAVIGATION_TEMPLATES Navigazione
RoutePreviewNavigationTemplate (non più supportato) androidx.car.app.NAVIGATION_TEMPLATES Navigazione

Dichiara l'autorizzazione per la piattaforma

Oltre all'autorizzazione richiesta per il modello utilizzato dall'app, l'app deve dichiarare l'autorizzazione androidx.car.app.ACCESS_SURFACE nel suo AndroidManifest.xml file per ottenere l'accesso alla piattaforma:

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

Accedere alla superficie

Per accedere al Surface fornito dall'host, devi implementare un SurfaceCallback e fornire questa implementazione al servizio di auto AppManager. L'attuale Surface viene passato al SurfaceCallback nel parametro SurfaceContainer dei callback onSurfaceAvailable() e onSurfaceDestroyed().

Kotlin

carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)

Java

carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);

Informazioni sull'area visibile della superficie

L'organizzatore può disegnare gli elementi dell'interfaccia utente per i modelli sopra la mappa. L'host comunica l'area della superficie che è garantita come senza ostacoli e completamente visibile all'utente chiamando il metodo SurfaceCallback.onVisibleAreaChanged. Inoltre, per ridurre al minimo il numero di modifiche, l'host chiama il metodo SurfaceCallback.onStableAreaChanged con il rettangolo più piccolo, che è sempre visibile in base al modello corrente.

Ad esempio, quando un'app di navigazione utilizza il pulsante NavigationTemplate con una barra di azioni in alto, la barra di azioni può nascondersi quando l'utente non interagisce con lo schermo per un po' di tempo per fare spazio alla mappa. In questo caso, è presente un callback a onStableAreaChanged e onVisibleAreaChanged con lo stesso rettangolo. Quando la barra di azioni è nascosta, viene chiamata solo onVisibleAreaChanged con l'area più grande. Se l'utente interagisce con la schermata, viene richiamato di nuovo solo onVisibleAreaChanged con il primo rettangolo.

Supporto del tema scuro

Le app devono ridisegnare la mappa nell'istanza Surface con i colori scuri appropriati quando l'host stabilisce che le condizioni lo richiedono, come descritto nella sezione Qualità delle app per Android per le auto.

Per decidere se disegnare una mappa scura, puoi utilizzare il metodo CarContext.isDarkMode. Ogni volta che lo stato del tema scuro cambia, ricevi una chiamata al numero Session.onCarConfigurationChanged.

Consentire agli utenti di interagire con la mappa

Quando utilizzi i seguenti modelli, puoi aggiungere il supporto per consentire agli utenti di interagire con le mappe che disegni, ad esempio di visualizzare parti diverse di una mappa tramite lo zoom e la panoramica.

Modello Interattività supportata dal livello API dell'app per auto
NavigationTemplate 2
PlaceListNavigationTemplate (non più supportato) 4
RoutePreviewNavigationTemplate (non più supportato) 4
MapTemplate (non più supportato) 5 (introduzione del modello)
MapWithContentTemplate 7 (introduzione del modello)

Implementare i callback di interattività

L'interfaccia SurfaceCallback offre diversi metodi di callback che puoi implementare per aggiungere interattività alle mappe create con i modelli nella sezione precedente:

Interazione SurfaceCallback metodo Supportato dal livello API dell'app per auto
Tocca onClick 5
Pizzica per eseguire lo zoom onScale 2
Trascinamento con un tocco onScroll 2
Spostamento con un solo tocco onFling 2
Tocca due volte onScale (con fattore di scala determinato dall'host del modello) 2
Spostamento rotatorio in modalità panoramica onScroll (con fattore di distanza determinato dall'host del modello) 2

Aggiungere una barra di azioni della mappa

Questi modelli possono avere una barra di azioni della mappa per azioni correlate alla mappa, come aumentare e diminuire lo zoom, recentrare, visualizzare una bussola e altre azioni che scegli di mostrare. La barra delle azioni della mappa può avere fino a quattro pulsanti con solo icone che possono essere aggiornati senza influire sulla profondità delle attività. Si nasconde durante lo stato inattivo e viene visualizzato di nuovo nello stato attivo.

Per ricevere i richiami di interattività della mappa, devi aggiungere un pulsante Action.PAN nella barra delle azioni della mappa. Quando l'utente preme il pulsante di panoramica, l'host entra in modalità di panoramica, come descritto nella sezione seguente.

Se la tua app omette il pulsante Action.PAN nella barra delle azioni della mappa, non riceve input utente dai metodi SurfaceCallback e l'host esce da qualsiasi modalità di panoramica attivata in precedenza.

Su un touchscreen, il pulsante di panoramica non viene visualizzato.

Informazioni sulla modalità panoramica

In modalità panoramica, l'host del modello traduce l'input utente da dispositivi di input non touch, come controller rotatori e touchpad, nei metodi SurfaceCallback appropriati. Rispondere all'azione dell'utente per attivare o disattivare la modalità panoramica con il metodo setPanModeListener in NavigationTemplate.Builder. L'organizzatore può nascondere altri componenti dell'interfaccia utente nel modello mentre l'utente è in modalità panoramica.

Interagire con l'utente

La tua app può interagire con l'utente utilizzando pattern simili a quelli di un'app mobile.

Gestire l'input utente

La tua app può rispondere all'input utente passando gli ascoltatori appropriati ai modelli che li supportano. Lo snippet seguente mostra come creare un modello Action che imposta un OnClickListener che richiama un metodo definito dal codice dell'app:

Kotlin

val action = Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(::onClickNavigate)
    .build()

Java

Action action = new Action.Builder()
    .setTitle("Navigate")
    .setOnClickListener(this::onClickNavigate)
    .build();

Il metodo onClickNavigate può quindi avviare l'app di navigazione predefinita per auto utilizzando il metodo 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);
}

Per maggiori dettagli su come avviare le app, incluso il formato dell'intentACTION_NAVIGATE, consulta la sezione Avvia un'app per auto con un intent.

Alcune azioni, ad esempio quelle che richiedono all'utente di continuare l'interazione sui suoi dispositivi mobili, sono consentite solo quando l'auto è parcheggiata. Puoi utilizzare ParkedOnlyOnClickListener per implementare queste azioni. Se l'auto non è parcheggiata, l'host mostra all'utente un'indicazione che l'azione non è consentita in questo caso. Se l'auto è parcheggiata, il codice viene eseguito normalmente. Lo snippet seguente mostra come usare ParkedOnlyOnClickListener per aprire una schermata delle impostazioni sul dispositivo mobile:

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

Mostra notifiche

Le notifiche inviate al dispositivo mobile vengono visualizzate sullo schermo dell'auto solo se vengono estese con un CarAppExtender. Alcuni attributi di notifica, come titolo, testo, icona e azioni dei contenuti, possono essere impostati in CarAppExtender, sostituendo gli attributi della notifica quando vengono visualizzati sullo schermo dell'auto.

Lo snippet seguente mostra come inviare una notifica sullo schermo dell'auto che visualizza un titolo diverso da quello mostrato sul dispositivo mobile:

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

Le notifiche possono influire sulle seguenti parti dell'interfaccia utente:

  • All'utente potrebbe essere mostrata una notifica in primo piano (HUN).
  • È possibile aggiungere una voce nel centro notifiche, eventualmente con un badge visibile nella barra laterale.
  • Per le app di navigazione, la notifica potrebbe essere visualizzata nel widget della barra come descritto in Notifiche passo passo.

Puoi scegliere come configurare le notifiche dell'app in modo che influiscano su ciascuno di questi elementi dell'interfaccia utente utilizzando la priorità della notifica, come descritto nella documentazione di CarAppExtender.

Se NotificationCompat.Builder.setOnlyAlertOnce viene chiamato con un valore di true, una notifica con priorità elevata viene visualizzata come HUN solo una volta.

Per ulteriori informazioni su come progettare le notifiche dell'app per l'auto, consulta la guida di Google Design for Driving sulle notifiche.

Mostrare avvisi popup

La tua app può mostrare un messaggio popup utilizzando CarToast come mostrato in questo snippet:

Kotlin

CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()

Java

CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();

Richiedi autorizzazioni

Se la tua app ha bisogno di accedere a dati o azioni con limitazioni, ad esempio la posizione, si applicano le regole standard delle autorizzazioni Android. Per richiedere un'autorizzazione, puoi utilizzare il metodo CarContext.requestPermissions().

Il vantaggio dell'utilizzo di CarContext.requestPermissions(), rispetto all'utilizzo delle API Android standard, è che non devi avviare il tuo Activity per creare la finestra di dialogo delle autorizzazioni. Inoltre, puoi utilizzare lo stesso codice sia su Android Auto sia su Android Automotive OS, anziché dover creare flussi dipendenti dalla piattaforma.

Personalizzare la finestra di dialogo delle autorizzazioni su Android Auto

Su Android Auto, la finestra di dialogo delle autorizzazioni per l'utente viene visualizzata sullo smartphone. Per impostazione predefinita, non è presente alcun sfondo dietro la finestra di dialogo. Per impostare un sfondo personalizzato, dichiara un tema dell'app per auto nel file AndroidManifest.xml e imposta l'attributo carPermissionActivityLayout per il tema dell'app per auto.

<meta-data
    android:name="androidx.car.app.theme"
    android:resource="@style/MyCarAppTheme />

Imposta quindi l'attributo carPermissionActivityLayout per il tema dell'app per auto:

<resources>
  <style name="MyCarAppTheme">
    <item name="carPermissionActivityLayout">@layout/my_custom_background</item>
  </style>
</resources>

Avviare un'app per auto con un'intent

Puoi chiamare il metodo CarContext.startCarApp per eseguire una delle seguenti azioni:

L'esempio seguente mostra come creare una notifica con un'azione che apre la tua app con una schermata che mostra i dettagli di una prenotazione del parcheggio. Estendi l'istanza di notifica con un'intenzione di contenuto che contiene un PendingIntent che racchiude un'intenzione esplicita per l'azione della tua app:

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

L'app deve anche dichiarare un BroadcastReceiver che viene invocato per elaborare l'intent quando l'utente seleziona l'azione nell'interfaccia di notifica e invoca CarContext.startCarApp con un intent che include l'URI dati:

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

Infine, il metodo Session.onNewIntent nella tua app gestisce questo intent inviando la schermata di prenotazione del parcheggio nella pila, se non è già in primo piano:

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

Per ulteriori informazioni su come gestire le notifiche per l'app dell'auto, consulta la sezione Mostrare le notifiche.

Limitazioni dei modelli

L'host limita il numero di modelli da visualizzare per una determinata attività a un massimo di cinque, di cui l'ultimo deve essere uno dei seguenti tipi:

Tieni presente che questo limite si applica al numero di modelli e non al numero di istanze Screen nello stack. Ad esempio, se un'app invia due modelli nella schermata A e poi passa alla schermata B, ora può inviare altri tre modelli. In alternativa, se ogni schermata è strutturata per inviare un singolo modello, l'app può inviare cinque istanze di schermata nell'ScreenManager stack.

Esistono casi speciali per queste limitazioni: aggiornamenti dei modelli e operazioni di annullamento e reimpostazione.

Aggiornamenti dei modelli

Alcuni aggiornamenti dei contenuti non vengono conteggiati ai fini del limite di modelli. In generale, se un'app invia un nuovo modello dello stesso tipo e contenente gli stessi contenuti principali del modello precedente, il nuovo modello non viene conteggiato ai fini della quota. Ad esempio, l'aggiornamento dello stato di attivazione/disattivazione di una riga in un ListTemplate non viene conteggiato nei confronti della quota. Consulta la documentazione dei singoli modelli per scoprire di più sui tipi di aggiornamenti dei contenuti che possono essere considerati un aggiornamento.

Operazioni di arretramento

Per attivare i flussi secondari all'interno di un'attività, l'host rileva quando un'app estrae un Screen dallo stack ScreenManager e aggiorna la quota rimanente in base al numero di modelli per i quali l'app esegue il rollback.

Ad esempio, se l'app invia due modelli nella schermata A, poi spinge la schermata B e invia altri due modelli, l'app ha una quota rimanente. Se l'app torna alla schermata A, l'host reimposta la quota su tre, perché l'app è tornata indietro di due modelli.

Tieni presente che, quando torna a una schermata, un'app deve inviare un modello dello stesso tipo di quello inviato per ultimo da quella schermata. L'invio di qualsiasi altro tipo di modello causa un errore. Tuttavia, a condizione che il tipo rimanga invariato durante un'operazione di ritorno, un'app può modificare liberamente i contenuti del modello senza influire sulla quota.

Operazioni di reimpostazione

Alcuni modelli hanno una semantica speciale che indica la fine di un'attività. Ad esempio, NavigationTemplate è una visualizzazione che dovrebbe rimanere sullo schermo e essere aggiornata con nuove istruzioni passo passo per l'utente. Quando raggiunge uno di questi modelli, l'host reimposta la quota del modello, trattandolo come se fosse il primo passaggio di una nuova attività. In questo modo l'app può iniziare una nuova attività. Consulta la documentazione dei singoli modelli per scoprire quali attivano un ripristino sull'host.

Se l'attività ospitante riceve un'intenzione di avviare l'app da un'azione di notifica o dal programma di avvio, la quota viene reimpostata. Questo meccanismo consente a un'app di avviare un nuovo flusso di attività dalle notifiche e vale anche se un'app è già associata e in primo piano.

Per ulteriori dettagli su come visualizzare le notifiche della tua app sullo schermo dell'auto, consulta la sezione Mostrare le notifiche. Consulta la sezione Avvia un'app per auto con un'intent per informazioni su come avviare l'app da un'azione di notifica.

API Connection

Puoi determinare se la tua app è in esecuzione su Android Auto o Android Automotive OS utilizzando l'API CarConnection per recuperare le informazioni sulla connessione in fase di esecuzione.

Ad esempio, nella sezione Session dell'app dell'auto, inizializza un CarConnection e abbonati agli aggiornamenti LiveData:

Kotlin

CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)

Java

new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);

Nell'osservatore, puoi quindi reagire alle modifiche dello stato della connessione:

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 Constraints

Automobili diverse possono consentire di mostrare all'utente un numero diverso di istanze di Item alla volta. Utilizza ConstraintManager per controllare il limite di contenuti in fase di esecuzione e impostare il numero appropriato di elementi nei tuoi modelli.

Per iniziare, richiedi un ConstraintManager dal CarContext:

Kotlin

val manager = carContext.getCarService(ConstraintManager::class.java)

Java

ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);

Puoi quindi eseguire una query sull'oggetto ConstraintManager recuperato per il limite di contenuti pertinente. Ad esempio, per ottenere il numero di elementi che possono essere visualizzati in una griglia, chiama getContentLimit con CONTENT_LIMIT_TYPE_GRID:

Kotlin

val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)

Java

int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);

Aggiungere un flusso di accesso

Se la tua app offre un'esperienza di accesso per gli utenti, puoi utilizzare modelli come SignInTemplate e LongMessageTemplate con l'API Car App 2.0 e versioni successive per gestire l'accesso alla tua app sull'unità principale dell'auto.

Per creare un SignInTemplate, definisci un SignInMethod. La raccolta di app per auto supporta attualmente i seguenti metodi di accesso:

  • InputSignInMethod per l'accesso con nome utente/password.
  • PinSignInMethod per l'accesso con PIN, in cui l'utente collega il proprio account dallo smartphone utilizzando un PIN visualizzato sull'unità principale.
  • ProviderSignInMethod per l'accesso al fornitore, ad esempio Accedi con Google e One Tap.
  • QRCodeSignInMethod per l'accesso tramite codice QR, in cui l'utente scansiona un codice QR per completare l'accesso sul suo smartphone. Questa funzionalità è disponibile con il livello API Car 4 e versioni successive.

Ad esempio, per implementare un modello che raccoglie la password dell'utente, inizia creando un InputCallback per elaborare e convalidare l'input dell'utente:

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.
    }
};

È obbligatorio un InputCallback per il InputSignInMethod Builder.

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

Infine, utilizza il nuovo InputSignInMethod per creare un 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();

Utilizzare AccountManager

Le app per il sistema operativo Android Automotive che dispongono dell'autenticazione devono utilizzare AccountManager per i seguenti motivi:

  • Miglioramento dell'esperienza utente e facilità di gestione degli account: gli utenti possono gestire facilmente tutti i loro account dal menu Account nelle impostazioni di sistema, inclusi l'accesso e la disconnessione.
  • Esperienza "Ospite": poiché le auto sono dispositivi condivisi, gli OEM possono attivare nel veicolo esperienze "Ospite" in cui non è possibile aggiungere account.

Aggiungere varianti di stringhe di testo

Dimensioni dello schermo dell'auto diverse possono mostrare quantità diverse di testo. Con l'API Car App di livello 2 e versioni successive, puoi specificare più varianti di una stringa di testo per adattarla al meglio allo schermo. Per sapere dove sono accettate le varianti di testo, cerca i modelli e i componenti che accettano un CarText.

Puoi aggiungere varianti di stringhe di testo a un CarText con il metodo 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();

Puoi quindi utilizzare questo CarText, ad esempio come testo principale di un GridItem.

Kotlin

GridItem.Builder()
    .addTitle(itemTitle)
    ...
    .build()

Java

new GridItem.Builder()
    .addTitle(itemTitle)
    ...
    build();

Aggiungi le stringhe in ordine dalla più alla meno preferita, ad esempio dalla più lunga alla più breve. L'host sceglie la stringa di lunghezza appropriata in base allo spazio disponibile sullo schermo dell'auto.

Aggiungere CarIcons in linea per le righe

Puoi aggiungere icone in linea con il testo per arricchire l'impatto visivo della tua app utilizzando CarIconSpan. Per ulteriori informazioni sulla creazione di questi intervalli, consulta la documentazione di CarIconSpan.create. Consulta Stili di testo fantastici con gli spazi per una panoramica del funzionamento degli stili di testo con gli spazi.

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 per l'hardware delle auto

A partire dal livello 3 dell'API Car App, la libreria Car App include API che puoi utilizzare per accedere alle proprietà e ai sensori del veicolo.

Requisiti

Per utilizzare le API con Android Auto, inizia aggiungendo una dipendenza da androidx.car.app:app-projected al file build.gradle per il tuo modulo Android Auto. Per Android Automotive OS, aggiungi una dipendenza da androidx.car.app:app-automotive al file build.gradle per il modulo Android Automotive OS.

Inoltre, nel file AndroidManifest.xml devi dichiarare le autorizzazioni pertinenti necessarie per richiedere i dati dell'auto che vuoi utilizzare. Tieni presente che queste autorizzazioni devono essere anche concedute dall'utente. Puoi utilizzare lo stesso codice sia su Android Auto che su Android Automotive OS, anziché dover creare flussi dipendenti dalla piattaforma. Tuttavia, le autorizzazioni necessarie sono diverse.

CarInfo

Questa tabella descrive le proprietà visualizzate dalle API CarInfo e le autorizzazioni che devi richiedere per utilizzarle:

Metodi Proprietà Autorizzazioni Android Auto Autorizzazioni Android Automotive OS Supportato dal livello API dell'app per auto
fetchModel Marca, modello, anno android.car.permission.CAR_INFO 3
fetchEnergyProfile Tipi di connettori EV, tipi di carburante com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_INFO 3
fetchExteriorDimensions

Questi dati sono disponibili solo su alcuni veicoli con sistema operativo Android Automotive che eseguono l'API 30 o versioni successive

Dimensioni esterne N/D android.car.permission.CAR_INFO 7
addTollListener
removeTollListener
Stato della tessera pedaggi, tipo di tessera pedaggi 3
addEnergyLevelListener
removeEnergyLevelListener
Livello batteria, livello carburante, livello carburante basso, autonomia rimanente 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
Velocità non elaborata, velocità visualizzata (mostrata sul display del cruscotto dell'auto) com.google.android.gms.permission.CAR_SPEED android.car.permission.CAR_SPEED,
android.car.permission.READ_CAR_DISPLAY_UNITS
3
addMileageListener
removeMileageListener
Distanza indicata dal contachilometri com.google.android.gms.permission.CAR_MILEAGE Questi dati non sono disponibili su Android Automotive OS per le app installate dal Play Store. 3

Ad esempio, per ottenere l'intervallo rimanente, crea un oggetto CarInfo, quindi crea e registra un 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);

Non dare per scontato che i dati dell'auto siano disponibili in ogni momento. Se ricevi un errore, controlla lo stato del valore richiesto per capire meglio perché i dati richiesti non sono stati recuperati. Fai riferimento alla documentazione di riferimento per la definizione completa della classe CarInfo.

CarSensors

La classe CarSensors consente di accedere ai dati di accelerometro, giroscopio, bussola e posizione del veicolo. La disponibilità di questi valori potrebbe dipendere dall'OEM. Il formato dei dati dell'accelerometro, del giroscopio e della bussola è lo stesso che otterresti dall'API SensorManager. Ad esempio, per controllare la direzione del veicolo:

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

Per accedere ai dati sulla posizione dall'auto, devi anche dichiarare e richiedere l'autorizzazione android.permission.ACCESS_FINE_LOCATION.

Test

Per simulare i dati dei sensori durante i test su Android Auto, consulta le sezioni Sensori e Configurazione dei sensori della guida sull'unità principale per computer. Per simulare i dati dei sensori durante i test su Android Automotive OS, consulta la sezione Emulare stato hardware della guida dell'emulatore Android Automotive OS.

I cicli di vita di CarAppService, Session e Screen

Le classi Session e Screen implementano l'interfaccia LifecycleOwner. Quando l'utente interagisce con l'app, vengono richiamati i callback del ciclo di vita degli oggetti Session e Screen, come descritto nei seguenti diagrammi.

I cicli di vita di un CarAppService e di una sessione

Figura 1. Il Sessionciclo di vita
.

Per informazioni dettagliate, consulta la documentazione del metodo Session.getLifecycle.

Il ciclo di vita di una schermata

Figura 2. Il Screenciclo di vita
.

Per tutti i dettagli, consulta la documentazione del metodo Screen.getLifecycle.

Registrare dal microfono dell'auto

Utilizzando CarAppService e l'API CarAudioRecord della tua app, puoi dare all'app l'accesso al microfono dell'auto dell'utente. Gli utenti devono concedere alla tua app l'autorizzazione per accedere al microfono dell'auto. La tua app può registrare e elaborare l'input dell'utente all'interno dell'app.

Autorizzazione per la registrazione

Prima di registrare qualsiasi audio, devi dichiarare l'autorizzazione di registrazione nel tuo AndroidManifest.xml e chiedere all'utente di concederla.

<manifest ...>
   ...
   <uses-permission android:name="android.permission.RECORD_AUDIO" />
   ...
</manifest>

Devi richiedere l'autorizzazione per la registrazione in fase di runtime. Per informazioni dettagliate su come richiedere una autorizzazione nell'app per l'auto, consulta la sezione Richiedi autorizzazioni.

Registra l'audio

Dopo che l'utente ha concesso l'autorizzazione alla registrazione, puoi registrare l'audio ed elaborare la registrazione.

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

Focus audio

Quando registri dal microfono dell'auto, acquisisci prima l'attenzione audio per assicurarti che i contenuti multimediali in riproduzione vengano interrotti. Se perdi il focus sull'audio, interrompi la registrazione.

Ecco un esempio di come acquisire l'attenzione audio:

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
 

Testing Library

La Testing Library di Android per auto fornisce classi di supporto che puoi utilizzare per convalidare il comportamento della tua app in un ambiente di test. Ad esempio, il messaggio SessionController ti consente di simulare una connessione all'host e verificare che i valori Screen e Template corretti vengano creati e restituito.

Per esempi di utilizzo, consulta la sezione Samples.

Segnalare un problema relativo alla libreria di app Android for Cars

Se riscontri un problema con la libreria, segnalalo utilizzando il tracker dei problemi di Google. Assicurati di compilare tutte le informazioni richieste nel modello del problema.

Creare un nuovo problema

Prima di segnalare un nuovo problema, controlla se è elencato nelle note di rilascio della libreria o se è stato segnalato nell'elenco dei problemi. Puoi iscriverti e votare i problemi facendo clic sulla stella accanto a un problema nel tracker. Per ulteriori informazioni, consulta la sezione Iscriversi a un problema.