Utilizzare la libreria di app di Android for Cars

La libreria di app Android for Cars ti consente di portare nell'auto le app di navigazione, punto d'interesse (PDI) e Internet of Things (IOT). Per farlo, fornisce una serie di modelli progettati per soddisfare gli standard relativi alla distrazione del conducente e si prende cura di dettagli come la varietà di fattori dello schermo dell'auto e le modalità di immissione.

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

Prima di iniziare

  1. Consulta le pagine Progettazione per la guida relative alla raccolta di app per auto.
  2. Esamina i termini e concetti chiave nella sezione seguente.
  3. Acquisisci familiarità con l'interfaccia utente del sistema Android Auto e la progettazione del sistema operativo Android Automotive.
  4. Consulta le Note di rilascio.
  5. Esamina gli esempi.

Termini e concetti chiave

Modelli e modelli
L'interfaccia utente è rappresentata da un grafico di oggetti del modello che possono essere organizzati in vari modi, secondo quanto 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é 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 viste progettate per soddisfare gli standard relativi alla distrazione del conducente e si prende cura di dettagli come la varietà dei fattori dello schermo dell'auto e le modalità di immissione.
Moderatore
L'host è il componente di backend che implementa la funzionalità offerta dalle API della libreria in modo che l'app possa essere eseguita nell'auto. Le responsabilità dell'host vanno dalla scoperta della tua app e dalla sua gestione del ciclo di vita alla conversione dei modelli in viste, alla notifica all'app delle interazioni degli utenti. Sui dispositivi mobili, questo host è implementato da Android Auto. Su Android Automotive OS, questo host è installato come app di sistema.
Limitazioni relative al modello
Diversi modelli applicano limitazioni nei contenuti dei rispettivi modelli. Ad esempio, i modelli di elenco impongono dei limiti al numero di elementi che possono essere presentati all'utente. I modelli hanno anche delle restrizioni nel modo di connetterli al flusso di un'attività. Ad esempio, l'app può eseguire il push solo di cinque modelli nell'elenco filtri. Per ulteriori dettagli, consulta Limitazioni dei modelli.
Screen
Screen è una classe fornita dalla libreria implementata dalle app per gestire l'interfaccia utente presentata all'utente. Un elemento Screen ha un ciclo di vita e fornisce il meccanismo mediante il quale l'app invia il modello da visualizzare quando lo schermo è visibile. È anche possibile eseguire il push e il push delle istanze Screen da e verso uno stack Screen, per garantire il rispetto delle restrizioni del flusso del modello.
CarAppService
CarAppService è una classe Service astratta che l'app deve implementare ed esportare per essere rilevata e gestita dall'host. Il CarAppService della tua app è responsabile di verificare che una connessione host sia attendibile utilizzando createHostValidator e di fornire successivamente istanze Session per ogni connessione mediante onCreateSession.
Session

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

All'avvio di Session, ad esempio al primo avvio dell'app, l'host richiede la visualizzazione dell'elemento Screen iniziale utilizzando il metodo onCreateScreen.

Installa la raccolta di app dell'auto

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

Configurare i file manifest dell'app

Per poter creare un'app per auto, configura i file manifest dell'app come segue.

Dichiara il tuo servizio 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 la tua app e connettersi.

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 conoscere 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 d'interesse nel tuo 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 di navigazione passo passo. Consulta la pagina Creare app di navigazione per le auto per ulteriori informazioni su questa categoria.
  • androidx.car.app.category.POI: un'app che offre funzionalità pertinenti per la ricerca di punti d'interesse come parcheggi, stazioni di ricarica e stazioni di servizio. Consulta la pagina Creare app per punti di interesse per le auto per ulteriori documentazione su questa categoria.
  • 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 internet delle cose per le auto per ulteriori documentazione su questa categoria.

Consulta la pagina Qualità delle app per Android per le auto per le descrizioni dettagliate di ogni categoria e i criteri per le app di appartenenza.

Specifica il nome e l'icona dell'app

Devi specificare il nome e l'icona dell'app che l'host può utilizzare per rappresentare la tua app nella UI di sistema.

Puoi specificare il nome e l'icona dell'app utilizzati per rappresentare la tua app utilizzando gli attributi label e icon di 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 vengono dichiarate nell'elemento <service>, l'host utilizza i valori specificati per l'elemento <application>.

Impostare un tema personalizzato

Per impostare un tema personalizzato per la tua 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 />

Poi, dichiara la tua risorsa per lo stile per impostare i seguenti attributi per il tema dell'app personalizzato per auto:

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

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 più alto dell'app Car App supportato da un host, utilizza il metodo getCarAppApiLevel().

Dichiara il livello API minimo dell'app Car App supportato dalla tua app nel tuo file AndroidManifest.xml:

<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 API necessario per utilizzare una determinata funzionalità della libreria di app per auto, consulta la documentazione di riferimento per CarAppApiLevels.

Crea il tuo CarAppService e la sessione

La tua app deve estendere la classe CarAppService e implementare il metodo onCreateSession, che restituisce un'istanza Session corrispondente alla connessione attuale 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 della restituzione dell'istanza Screen in modo 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 scenari in cui la tua app per auto deve partire da una schermata diversa dalla schermata Home o di destinazione dell'app, ad esempio per gestire i link diretti, puoi pre-separare uno stack di schermate posteriore utilizzando ScreenManager.push prima di tornare da onCreateScreen. Il pre-seeding consente agli utenti di tornare alle schermate precedenti dalla prima schermata mostrata dall'app.

Crea la tua 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 della UI da visualizzare sullo schermo dell'auto.

Il seguente snippet 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 ContextWrapper accessibile alle tue istanze Session e Screen. Fornisce l'accesso ai servizi per auto, quali ScreenManager per la gestione dello stack di schermo, AppManager per le funzionalità generali relative alle app, come l'accesso all'oggetto Surface per disegno di mappe, e NavigationManager utilizzati dalle app di navigazione passo passo per comunicare metadati di navigazione e altri eventi{1617}.

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 la possibilità di caricare risorse utilizzabili utilizzando la configurazione dallo schermo dell'auto, di avviare un'app nell'auto utilizzando gli intent e di indicare se l'app deve visualizzare la mappa in tema scuro.

Implementazione della navigazione nelle schermate

Le app spesso presentano una serie di schermate diverse, ognuna delle quali potrebbe utilizzare modelli diversi in cui l'utente può navigare mentre interagisce con l'interfaccia visualizzata sullo schermo.

La classe ScreenManager fornisce una serie di schermate che puoi utilizzare per spingere le schermate che possono essere visualizzate automaticamente quando l'utente seleziona un pulsante Indietro nello schermo dell'auto o utilizza il pulsante Indietro disponibile in alcune auto.

Lo snippet seguente mostra come aggiungere un'azione Indietro a un modello di messaggio e un'azione che forza il push di una nuova schermata quando 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 è uno standard Action che richiama automaticamente ScreenManager.pop. Questo comportamento può essere sostituito utilizzando l'istanza OnBackPressedDispatcher disponibile in CarContext.

Per garantire che l'app sia sicura da usare durante la guida, la pila 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

La tua app può richiedere l'annullamento della validità 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 conteggi il nuovo modello nella quota del modello. Per ulteriori dettagli, consulta la sezione Limitazioni dei modelli.

Ti consigliamo di strutturare le schermate in modo che ci sia una mappatura one-to-one tra un Screen e il tipo di modello che restituisce tramite la sua implementazione di onGetTemplate.

Disegna mappe

Le app di navigazione e di punti di interesse (PDI) che utilizzano i seguenti modelli possono disegnare le mappe accedendo a una Surface:

Modello Autorizzazione modello Indicazioni per la categoria
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES Navigazione
MapWithContentTemplate androidx.car.app.NAVIGATION_TEMPLATES OPPURE
androidx.car.app.MAP_TEMPLATES
Navigazione, PDI
MapTemplate (deprecato) androidx.car.app.NAVIGATION_TEMPLATES Navigazione
PlaceListNavigationTemplate (deprecato) androidx.car.app.NAVIGATION_TEMPLATES Navigazione
RoutePreviewNavigationTemplate (deprecato) androidx.car.app.NAVIGATION_TEMPLATES Navigazione

Dichiara l'autorizzazione di accesso alla piattaforma

Oltre all'autorizzazione richiesta per il modello utilizzato dalla tua app, la tua app deve dichiarare l'autorizzazione androidx.car.app.ACCESS_SURFACE nel relativo file AndroidManifest.xml per poter accedere alla piattaforma:

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

Accedi alla piattaforma

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

Kotlin

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

Java

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

Comprendi l'area visibile della superficie

L'host può disegnare elementi dell'interfaccia utente per i modelli nella parte superiore della mappa. L'host comunica l'area della superficie che non è ostruita e che è 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 NavigationTemplate con una striscia delle azioni nella parte superiore, questa può nascondersi quando l'utente non interagisce con lo schermo per un po' di tempo per creare più spazio per la mappa. In questo caso, viene richiamato onStableAreaChanged e onVisibleAreaChanged con lo stesso rettangolo. Quando la barra di azioni è nascosta, viene chiamata solo onVisibleAreaChanged con l'area più ampia. Se l'utente interagisce con lo schermo, viene chiamato di nuovo solo onVisibleAreaChanged con il primo rettangolo.

Supporto del tema scuro

Le app devono ridisegnare la propria mappa sull'istanza Surface con i colori scuri adeguati quando l'host determina che le condizioni lo giustificano, come descritto in 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 a Session.onCarConfigurationChanged.

Consentire agli utenti di interagire con la mappa

Quando utilizzi i seguenti modelli, puoi consentire agli utenti di interagire con le mappe che disegni, ad esempio consentendo loro di vedere diverse parti di una mappa mediante lo zoom e la panoramica.

Modello Interattività supportata dal livello API Car App
NavigationTemplate 2
PlaceListNavigationTemplate (ritirato) 4
RoutePreviewNavigationTemplate (ritirato) 4
MapTemplate (ritirato) 5 (introduzione del modello)
MapWithContentTemplate 7 (introduzione del modello)

Implementa callback di interattività

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

Interazione SurfaceCallback metodo Supportato dal livello API Car App
Tocca onClick 5
Pizzica per eseguire lo zoom onScale 2
Trascinamento con un solo tocco onScroll 2
Scorrimento single-touch onFling 2
Tocca due volte onScale (con fattore di scala determinato dall'host del modello) 2
Spinta rotatoria in modalità Panoramica onScroll (con il fattore di distanza determinato dall'host del modello) 2

Aggiungi una barra delle azioni sulla mappa

Questi modelli possono avere una barra di azioni sulla mappa per le azioni relative alla mappa, come aumentare e diminuire lo zoom, ricentrare, visualizzare una bussola e altre azioni che scegli di visualizzare. La barra delle azioni sulla mappa può avere fino a quattro pulsanti con sole icone che possono essere aggiornati senza influire sulla profondità dell'attività. Si nasconde in stato di inattività e riappare in stato attivo.

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

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

Su un touchscreen, il pulsante per la panoramica non viene visualizzato.

Informazioni sulla modalità Panoramica

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

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

L'app può rispondere all'input utente trasmettendo i listener appropriati ai modelli che li supportano. Lo snippet seguente mostra come creare un modello Action che imposti un OnClickListener che richiama un metodo definito dal codice della tua 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'intent ACTION_NAVIGATE, consulta la sezione Avviare un'app per auto con un intent.

Alcune azioni, come quelle che richiedono all'utente di continuare l'interazione sui propri dispositivi mobili, sono consentite solo quando l'auto è parcheggiata. Per implementare queste azioni, puoi utilizzare la ParkedOnlyOnClickListener. Se l'auto non è parcheggiata, l'host mostra all'utente che l'azione non è consentita in questo caso. Se l'auto è parcheggiata, il codice funziona normalmente. Il seguente snippet mostra come utilizzare 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 sono estese con un CarAppExtender. Alcuni attributi delle notifiche, come titolo dei contenuti, testo, icona e azioni, possono essere impostati in CarAppExtender, sostituendo gli attributi delle notifiche quando vengono visualizzate sullo schermo dell'auto.

Il seguente snippet mostra come inviare allo schermo dell'auto una notifica 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 interessare le seguenti parti dell'interfaccia utente:

  • All'utente potrebbe essere visualizzata una notifica di avviso (HUN).
  • È possibile aggiungere una voce nel centro notifiche, facoltativamente con un badge visibile nella barra.
  • Per le app di navigazione, la notifica potrebbe essere visualizzata nel widget ferroviario 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 il valore true, la notifica ad alta priorità viene visualizzata come HUN solo una volta.

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

Mostra toast

La tua app può mostrare un toast 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 deve accedere ad azioni o dati con restrizioni, ad esempio la posizione, si applicano le regole standard delle autorizzazioni Android. Per richiedere un'autorizzazione, puoi usare il metodo CarContext.requestPermissions().

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

Applicare uno stile alla finestra di dialogo delle autorizzazioni su Android Auto

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

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

Dopodiché, imposta 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 apri la tua app con una schermata che mostra i dettagli di una prenotazione di parcheggio. Estendi l'istanza di notifica con un intent di contenuti che contiene un elemento PendingIntent che aggrega un intent esplicito all'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());

La tua app deve inoltre dichiarare un BroadcastReceiver che viene richiamato per elaborare l'intent quando l'utente seleziona l'azione nell'interfaccia di notifica e richiama CarContext.startCarApp con un intent che includa l'URI dei 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 spostando la schermata di prenotazione del parcheggio in 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()));
        }
    }
}

Consulta la sezione Mostra notifiche per ulteriori informazioni su come gestire le notifiche per l'app dell'auto.

Limitazioni relative al modello

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 Screen istanze nello stack. Ad esempio, se un'app invia due modelli nella schermata A e poi esegue il push sulla schermata B, ora può inviare altri tre modelli. In alternativa, se ogni schermata è strutturata in modo da inviare un singolo modello, l'app può eseguire il push di cinque istanze di schermata nell'elenco ScreenManager.

Esistono casi speciali per queste limitazioni: aggiornamento dei modelli e operazioni di ripristino e annullamento.

Aggiornamenti del modello

Alcuni aggiornamenti dei contenuti non concorrono al raggiungimento del limite di modelli. In generale, se un'app esegue il push di 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 una ListTemplate non viene conteggiato ai fini della quota. Consulta la documentazione dei singoli modelli per saperne di più sui tipi di aggiornamenti dei contenuti che possono essere considerati aggiornamenti.

Operazioni dorsali

Per abilitare i flussi secondari all'interno di un'attività, l'host rileva quando un'app apre un Screen dallo stack ScreenManager e aggiorna la quota rimanente in base al numero di modelli precedenti all'app.

Ad esempio, se l'app invia due modelli nella schermata A, quindi esegue il push della schermata B e ne invia altri due, all'app rimane una quota. 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 torni a una schermata, un'app deve inviare un modello dello stesso tipo dell'ultimo inviato da quella schermata. L'invio di qualsiasi altro tipo di modello causa un errore. Tuttavia, finché il tipo rimane lo stesso 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 aggiornata con nuove istruzioni passo passo per il consumo dell'utente. Quando raggiunge uno di questi modelli, l'host reimposta la quota per il modello, considerandolo 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 vedere quali attivano una reimpostazione sull'host.

Se l'host riceve un intent per avviare l'app da un'azione di notifica o da Avvio app, viene reimpostata anche la quota. 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 dell'app sullo schermo dell'auto, consulta la sezione Mostra notifiche. Consulta la sezione Avviare 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 è installata su Android Auto o Android Automotive OS utilizzando l'API CarConnection per recuperare le informazioni di connessione in fase di runtime.

Ad esempio, nel Session dell'app dell'auto, inizializza un CarConnection e iscriviti agli aggiornamenti di LiveData:

Kotlin

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

Java

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

Nell'osservatore, puoi quindi reagire ai cambiamenti nello stato di 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

Auto diverse possono consentire all'utente di visualizzare contemporaneamente un numero diverso di istanze di Item. Utilizza ConstraintManager per verificare il limite di contenuti in fase di runtime e impostare il numero appropriato di elementi nei modelli.

Inizia ricevendo un ConstraintManager da 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 determinare il limite di contenuti pertinenti. 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);

Aggiungi un flusso di accesso

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

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

  • InputSignInMethod per l'accesso con nome utente e password.
  • PinSignInMethod per l'accesso con PIN, dove l'utente collega il proprio account dal telefono utilizzando un PIN visualizzato nell'unità principale.
  • ProviderSignInMethod per l'accesso del fornitore, ad esempio Accedi con Google e One Tap.
  • QRCodeSignInMethod per l'accesso con codice QR, in cui l'utente scansiona un codice QR per completare l'accesso sul proprio smartphone. Questa funzionalità è disponibile con API Car di livello 4 e successivi.

Ad esempio, per implementare un modello che raccoglie la password dell'utente, inizia creando una InputCallback per elaborare e convalidare l'input 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.
    }
};

È richiesto un InputCallback per 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();

Utilizza AccountManager

Le app per Android Automotive OS con autenticazione devono utilizzare AccountManager per i seguenti motivi:

  • Esperienza utente migliore e facilità di gestione degli account: gli utenti possono gestire facilmente tutti i propri account dal menu degli account nelle impostazioni di sistema, compresi i livelli di accesso e uscita.
  • Esperienze"Ospite": poiché le auto sono dispositivi condivisi, gli OEM possono attivare esperienza ospite nel veicolo, per cui non è possibile aggiungere account.

Aggiungi varianti della stringa di testo

Gli schermi delle auto di dimensioni diverse possono mostrare testo diverso. Con l'API Car App di livello 2 e superiore, puoi specificare più varianti di una stringa di testo per adattarle al meglio allo schermo. Per capire dove vengono accettate le varianti di testo, cerca i modelli e i componenti che supportano una CarText.

Puoi aggiungere varianti della stringa 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 CarText, ad esempio, come testo principale di GridItem.

Kotlin

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

Java

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

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

Aggiungi elementi CarIcon incorporati per le righe

Puoi aggiungere icone incorporate nel testo per arricchire l'aspetto visivo della tua app utilizzando CarIconSpan. Consulta la documentazione di CarIconSpan.create per ulteriori informazioni sulla creazione di questi intervalli. Per una panoramica del funzionamento degli stili del testo con le sezioni, consulta Stili del testo spantistici con le sezioni.

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 hardware per auto

A partire dal livello 3 dell'API Car App, la libreria di app auto dispone di API che puoi utilizzare per accedere alle proprietà e ai sensori dei veicoli.

Requisiti

Per utilizzare le API con Android Auto, inizia aggiungendo una dipendenza su androidx.car.app:app-projected al file build.gradle per il modulo Android Auto. Per Android Automotive OS, aggiungi una dipendenza su androidx.car.app:app-automotive al file build.gradle per il tuo modulo di 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 concesse anche dall'utente. Puoi utilizzare lo stesso codice sia su Android Auto che sul sistema operativo Android Automotive, anziché creare flussi dipendenti dalla piattaforma. Tuttavia, le autorizzazioni necessarie sono diverse.

Info auto

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

Metodi Proprietà Autorizzazioni di Android Auto Autorizzazioni di Android Automotive OS Supportato dal livello API Car App
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 con API 30 o versioni successive

Dimensioni esterne N/A android.car.permission.CAR_INFO 7
addTollListener
removeTollListener
Stato tessera pedaggio, tipo di carta pedaggio 3
addEnergyLevelListener
removeEnergyLevelListener
Livello batteria, livello carburante, livello 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à del display (visualizzate sul display del cluster 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 del contachilometri com.google.android.gms.permission.CAR_MILEAGE Su Android Automotive OS, questi dati non sono disponibili per le app installate dal Play Store. 3

Ad esempio, per ottenere l'intervallo rimanente, crea un'istanza di 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 sempre disponibili. Se ricevi un messaggio di errore, controlla lo stato del valore richiesto per comprendere meglio perché non è stato possibile recuperare i dati richiesti. Consulta la documentazione di riferimento per la definizione completa della classe CarInfo.

Sensori auto

La classe CarSensors ti permette di accedere ai dati relativi ad accelerometro, giroscopio, bussola e posizione del veicolo. La disponibilità di questi valori può dipendere dall'OEM. Il formato dei dati dell'accelerometro, del giroscopio e della bussola è uguale a quello che otterresti dall'API SensorManager. Ad esempio, per controllare l'intestazione 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 dell'unità principale desktop. Per simulare i dati dei sensori durante i test su Android Automotive OS, consulta la sezione Emula stato hardware della guida dell'emulatore del sistema operativo Android Automotive.

Ciclo di vita di CarAppService, della sessione e dello schermo

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

I cicli di vita di un servizio CarAppService e di una sessione

Figura 1. Il ciclo di vita di Session.

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

Il ciclo di vita di una schermata

Figura 2. Il ciclo di vita di Screen.

Per informazioni dettagliate, consulta la documentazione relativa al metodo Screen.getLifecycle.

Registra dal microfono dell'auto

Con CarAppService e l'API CarAudioRecord della tua app, puoi consentire all'app di accedere al microfono dell'auto dell'utente. Gli utenti devono concedere all'app l'autorizzazione ad accedere al microfono dell'auto. L'app può registrare ed elaborare l'input dell'utente al suo interno.

Autorizzazione alla registrazione

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

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

Devi richiedere l'autorizzazione per registrare in fase di runtime. Consulta la sezione Richiedere autorizzazioni per i dettagli su come richiedere un'autorizzazione nell'app dell'auto.

Registra l'audio

Dopo che l'utente concede 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 la messa a fuoco audio per assicurarti che tutti i contenuti multimediali in corso vengano interrotti. Se perdi il focus audio, interrompi la registrazione.

Ecco un esempio di come acquisire il focus 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
 

Libreria di test

La libreria di test di Android for Cars fornisce classi ausiliarie che puoi utilizzare per convalidare il comportamento della tua app in un ambiente di test. Ad esempio, SessionController ti consente di simulare una connessione all'host e verificare che vengano creati e restituiti i valori Screen e Template corretti.

Consulta i Campioni per esempi di utilizzo.

Segnalare un problema relativo alla libreria di app Android for Cars

Se rilevi un problema con la libreria, segnalalo utilizzando Google Issue Tracker. Assicurati di compilare tutte le informazioni richieste nel modello di problema.

Crea un nuovo numero

Prima di inviare un nuovo problema, controlla se è presente nelle note di rilascio della raccolta o se è stato segnalato nell'elenco dei problemi. Puoi iscriverti e votare per risolvere i problemi facendo clic sulla stella per un problema nel tracker. Per ulteriori informazioni, consulta la sezione Abbonarsi a un problema.