Utilizza l'API Instrument Cluster (un'API Android) per visualizzare le app di navigazione, incluso Google Maps, su un display secondario in un'auto, ad esempio dietro il volante sul quadro strumenti. Questa pagina descrive come creare un servizio per controllare quel display secondario e quindi integrare il servizio con
in modo che le app di navigazione possano visualizzare un'interfaccia utente.CarService
Terminologia
In questa pagina vengono utilizzati i seguenti termini:
Termine | Descrizione |
---|---|
CarInstrumentClusterManager | Un CarManager che consente alle app esterne di avviare un'attività sul quadro strumenti e ricevere richiamate quando il quadro strumenti è pronto per visualizzare le attività. |
CarManager | Classe di base di tutti i gestori utilizzati dalle app esterne per interagire con i servizi specifici dell'auto implementati da CarService . |
CarService | Servizio della piattaforma Android che fornisce la comunicazione tra app esterne (incluso Google Maps) e funzioni specifiche dell'auto, come l'accesso al quadro strumenti. |
Destinazione | La destinazione finale verso la quale navigherà il veicolo. |
ETA | Ora stimata di arrivo a destinazione. |
Unità principale (HU) | Unità di calcolo primaria incorporata in un'auto. L'HU esegue tutto il codice Android ed è collegato al display centrale dell'auto. |
Strumentazione | Display secondario situato dietro il volante e tra gli strumenti della vettura. Può trattarsi di un'unità di calcolo indipendente collegata all'HU tramite la rete interna dell'auto (CAN bus) o di un display secondario collegato all'HU. |
InstrumentClusterRenderingService | Classe base per il servizio utilizzato per interfacciarsi con il display del quadro strumenti. Gli OEM devono fornire un'estensione di questa classe che interagisce con l'hardware specifico dell'OEM. |
App KitchenLavello | Applicazione di prova inclusa con Android Automotive. |
Itinerario | Un percorso specifico lungo il quale un veicolo naviga per arrivare a una destinazione. |
Servizio unico | Un servizio Android con l'attributo android:singleUser . In qualsiasi momento, al massimo un'istanza del servizio viene eseguita sul sistema Android. |
Prerequisiti
Per sviluppare l'integrazione, assicurati di avere questi elementi:
- Ambiente di sviluppo Android. Per configurare l'ambiente di sviluppo Android, consulta Requisiti di compilazione .
- Scarica il codice sorgente di Android. Scarica l'ultima versione del codice sorgente di Android dal ramo pi-car-release (o successivo) all'indirizzo https://android.googlesource.com .
- Unità di testa (HU). Un dispositivo Android in grado di eseguire Android 9 (o versioni successive). Questo dispositivo deve avere il proprio display ed essere in grado di eseguire il flashing del display con le nuove build di Android.
- Il quadro strumenti è uno dei seguenti:
- Display fisico secondario collegato all'HU. Se l'hardware e il kernel del dispositivo supportano la gestione di più display.
- Unità indipendente. Qualsiasi unità computazionale collegata alla HU tramite una connessione di rete, in grado di ricevere e visualizzare un flusso video sul proprio display.
- Display emulato. Durante lo sviluppo, puoi utilizzare uno di questi ambienti emulati:
- Display secondari simulati. Per abilitare un display secondario simulato su qualsiasi distribuzione Android AOSP, vai alle impostazioni Opzioni sviluppatore nell'applicazione di sistema Impostazioni e quindi seleziona Simula display secondari. Questa configurazione equivale a collegare un display secondario fisico, con la limitazione che questo display è sovrapposto al display principale.
- Quadro strumenti emulato. L'emulatore Android incluso in Android Automotive offre un'opzione per visualizzare un quadro strumenti con l'emulatore Android _qemu-pipes . Utilizza l'implementazione del quadro strumenti di riferimento DirectRenderingCluster per connetterti a questo display esterno emulato.
Architettura di integrazione
Componenti di integrazione
Qualsiasi integrazione dell'API Instrument Cluster è costituita da questi tre componenti:
-
CarService
- App di navigazione
- Servizio quadro strumenti OEM
CarService
CarService
da intermediario tra le app di navigazione e l'auto, assicurando che sia attiva solo un'app di navigazione alla volta e che solo le app con l'autorizzazione android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
possano inviare dati all'auto.
CarService
il bootstrap di tutti i servizi specifici per auto e fornisce l'accesso a questi servizi attraverso una serie di gestori. Per interagire con i servizi, le applicazioni in esecuzione nell'auto possono accedere a questi gestori.
Per l'implementazione del quadro strumenti, gli OEM automobilistici devono creare un'implementazione personalizzata di InstrumentClusterRendererService e aggiornare il file config.xml
in modo che punti a tale implementazione personalizzata.
Durante il rendering di un cluster di strumenti, durante il processo di avvio CarService
legge la chiave InstrumentClusterRendererService
di config.xml
per individuare un'implementazione di InstrumentClusterService
. In AOSP, questa voce punta al servizio di rendering dell'implementazione del cluster di esempio dell'API dello stato di navigazione:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
Il servizio a cui si fa riferimento in questa voce è inizializzato e associato a CarService
. Quando le app di navigazione, come Google Maps, richiedono un CarInstrumentClusterManager
, CarService
fornisce un gestore che aggiorna lo stato del quadro InstrumentClusterRenderingService
dall'InstrumentClusterRenderingService associato. (In questo caso, bound si riferisce a Android Services .)
Servizio quadro strumenti
Gli OEM devono creare un Android Package (APK) che contenga una sottoclasse di InstrumentClusterRendererService .
Vedere ClusterRenderingService
per un esempio.
Questa classe ha due scopi:
- Fornisce un'interfaccia Android e il dispositivo di rendering Instrument Cluster (lo scopo di questa pagina).
- Riceve ed esegue il rendering degli aggiornamenti sullo stato della navigazione, ad esempio indicazioni di navigazione turn-by-turn.
Per il primo scopo, le implementazioni OEM di InstrumentClusterRendererService
devono inizializzare il display secondario utilizzato per eseguire il rendering delle informazioni sugli schermi nell'abitacolo dell'auto e comunicare queste informazioni a CarService
chiamando i metodi InstrumentClusterRendererService.setClusterActivityOptions()
e InstrumentClusterRendererService.setClusterActivityState()
.
Per la seconda funzione, il servizio Instrument Cluster deve fornire un'implementazione dell'interfaccia NavigationRenderer
che riceve gli eventi di aggiornamento dello stato di navigazione , che sono codificati come eventType
e i dati dell'evento codificati in un bundle.
Sequenza di integrazione
Il diagramma seguente illustra l'implementazione di uno stato di navigazione che esegue il rendering degli aggiornamenti:
In questa illustrazione, i colori denotano quanto segue:
- Giallo.
CarService
eCarNavigationStatusManager
forniti dalla piattaforma Android. Per ulteriori informazioni, vedi Auto e CAR_NAVIGATION_SERVICE . - Ciano.
InstrumentClusterRendererService
implementato dall'OEM. - Porpora. L'app di navigazione implementata da Google e sviluppatori di terze parti.
- Verde.
CarAppFocusManager
. Per ulteriori informazioni, consulta Utilizzo dell'API CarAppFocusManager di seguito e CarAppFocusManager .
Il flusso di informazioni sullo stato di navigazione segue questa sequenza:
-
CarService
inizializzaInstrumentClusterRenderingService
. - Durante l'inizializzazione,
InstrumentClusterRenderingService
aggiornaCarService
con:- Proprietà di visualizzazione del quadro strumenti, come i confini non oscuri (vedere ulteriori dettagli sui confini non oscuri più avanti).
- Opzioni di attività necessarie per avviare le attività all'interno del display del quadro strumenti (vedere ulteriori dettagli in ActivityOptions .
- Un'app di navigazione (come Google Maps per Android Automotive o qualsiasi app di mappe con le autorizzazioni richieste):
- Ottiene un
CarAppFocusManager
usando la classe Car da car-lib. - Prima dell'inizio delle indicazioni passo-passo, chiama
CarAppFocusManager.requestFocus()
per passareCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
come parametroappType
.
- Ottiene un
-
CarAppFocusManager
comunica questa richiesta aCarService
. Se concesso,CarService
ispeziona il pacchetto dell'app di navigazione e individua un'attività contrassegnata con la categoriaandroid.car.cluster.NAVIGATION
. - Se trovata, l'app di navigazione utilizza le
ActivityOptions
segnalate daInstrumentClusterRenderingService
per avviare l'attività e include le proprietà di visualizzazione del cluster di strumenti come extra nell'intento.
Integrazione dell'API
L'implementazione InstrumentClusterRenderingService
deve:
- Essere designato come servizio singleton aggiungendo il valore seguente a AndroidManifest.xml. Ciò è necessario per garantire l'esecuzione di un'unica copia del servizio Instrument Cluster, anche durante l'inizializzazione e il cambio utente:
android:singleUser="true"
- Mantieni l'autorizzazione di sistema
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
. Ciò garantisce che solo il servizio di rendering del quadro strumenti incluso come parte dell'immagine del sistema Android sia sempre vincolato daCarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Implementazione di InstrumentClusterRenderingService
Per costruire il servizio:
- Scrivi una classe che si estenda da
InstrumentClusterRenderingService
e quindi aggiungi una voce corrispondente al tuo fileAndroidManifest.xml
. Questa classe controlla la visualizzazione del quadro strumenti e può ( facoltativamente ) eseguire il rendering dei dati dell'API dello stato di navigazione. - Durante
onCreate()
, utilizzare questo servizio per inizializzare la comunicazione con l'hardware di rendering. Le opzioni includono:- Determinare il display secondario da utilizzare per il quadro strumenti.
- Crea un display virtuale in modo che l'app Instrument Cluster esegua il rendering e trasmetta l'immagine renderizzata a un'unità esterna (utilizzando un formato di streaming video, come H.264).
- Quando il display sopra indicato è pronto, questo servizio deve chiamare
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
per definire leActivityOptions
esatte che devono essere utilizzate per visualizzare un'attività sull'Instrument Cluster. Usa questi parametri:- categoria. CarInstrumentClusterManager#CATEGORY_NAVIGATION
-
ActivityOptions.
Un'istanza diActivityOptions
che può essere utilizzata per avviare un'attività nel cluster di strumenti. Ad esempio, dall'implementazione del cluster di strumenti di esempio su AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Quando il cluster di strumenti è pronto per visualizzare le attività, questo servizio deve richiamare
InstrumentClusterRenderingService#setClusterActivityState()
. Usa questi parametri:-
category
CarInstrumentClusterManager#CATEGORY_NAVIGATION
-
state
Bundle generato con ClusterActivityState . Assicurati di fornire i seguenti dati:-
visible
Specifica il quadro strumenti come visibile e pronto per visualizzare il contenuto. -
unobscuredBounds
Un rettangolo che definisce l'area all'interno del display del quadro strumenti in cui è sicuro visualizzare il contenuto. Ad esempio, aree coperte da quadranti e indicatori.
-
-
- Eseguire l'override del metodo
Service#dump()
e riportare informazioni sullo stato utili per il debug (vedere dumpsys per ulteriori informazioni).
Esempio di implementazione di InstrumentClusterRenderingService
L'esempio seguente delinea un'implementazione di InstrumentClusterRenderingService
, che crea un VirtualDisplay
per presentare il contenuto del cluster di strumenti su un display fisico remoto.
In alternativa, questo codice potrebbe passare il displayId
di un display secondario fisico connesso all'HU, se ne è noto uno disponibile.
/** * Sample {@link InstrumentClusterRenderingService} implementation */ public class SampleClusterServiceImpl extends InstrumentClusterRenderingService { // Used to retrieve or create displays private final DisplayManager mDisplayManager; // Unique identifier for the display that will be used for instrument // cluster private final String mUniqueId = UUID.randomUUID().toString(); // Format of the instrument cluster display private static final int DISPLAY_WIDTH = 1280; private static final int DISPLAY_HEIGHT = 720; private static final int DISPLAY_DPI = 320; // Area not covered by instruments private static final int DISPLAY_UNOBSCURED_LEFT = 40; private static final int DISPLAY_UNOBSCURED_TOP = 0; private static final int DISPLAY_UNOBSCURED_RIGHT = 1200; private static final int DISPLAY_UNOBSCURED_BOTTOM = 680; @Override public void onCreate() { super.onCreate(); // Create a virtual display to render instrument cluster activities on mDisplayManager = getSystemService(DisplayManager.class); VirtualDisplay display = mDisplayManager.createVirtualDisplay( mUniqueId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, null, 0 /* flags */, null, null); // Do any additional initialization (e.g.: start a video stream // based on this virtual display to present activities on a remote // display). onDisplayReady(display.getDisplay()); } private void onDisplayReady(Display display) { // Report activity options that should be used to launch activities on // the instrument cluster. String category = CarInstrumentClusterManager.CATEGORY_NAVIGATION; ActionOptions options = ActivityOptions.makeBasic() .setLaunchDisplayId(display.getDisplayId()); setClusterActivityOptions(category, options); // Report instrument cluster state. Rect unobscuredBounds = new Rect(DISPLAY_UNOBSCURED_LEFT, DISPLAY_UNOBSCURED_TOP, DISPLAY_UNOBSCURED_RIGHT, DISPLAY_UNOBSCURED_BOTTOM); boolean visible = true; ClusterActivityState state = ClusterActivityState.create(visible, unobscuredBounds); setClusterActivityState(category, options); } }
Utilizzo dell'API CarAppFocusManager
L'API CarAppFocusManager fornisce un metodo denominato getAppTypeOwner()
, che consente al servizio cluster scritto dagli OEM di sapere quale app di navigazione ha il focus di navigazione in un dato momento. Gli OEM possono utilizzare il CarAppFocusManager#addFocusListener()
esistente e quindi utilizzare getAppTypeOwner()
per sapere quale app ha lo stato attivo. Con queste informazioni, gli OEM possono:
- Passa dall'attività mostrata nel cluster all'attività del cluster fornita dall'app di navigazione che mantiene lo stato attivo.
- Può rilevare se l'app di navigazione focalizzata presenta o meno un'attività del cluster. Se l'app di navigazione focalizzata non ha un'attività del cluster (o se tale attività è disabilitata), gli OEM possono inviare questo segnale al DIM dell'auto in modo che il facet di navigazione del cluster venga ignorato del tutto.
Usa CarAppFocusManager
per impostare e ascoltare il focus dell'applicazione corrente, come la navigazione attiva o un comando vocale. Di solito solo un'istanza di tale applicazione è in esecuzione attiva (o focalizzata) nel sistema.
Utilizza il CarAppFocusManager#addFocusListener(..)
per ascoltare le modifiche allo stato attivo dell'app:
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); mAppFocusManager.addFocusListener(this, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); ... public void onAppFocusChanged(int appType, boolean active) { // Use the CarAppFocusManager#getAppTypeOwner(appType) method call // to retrieve a list of active package names }
Utilizzare il CarAppFocusManager#getAppTypeOwner(..)
per recuperare i nomi dei pacchetti dell'attuale proprietario di un determinato tipo di applicazione attivo. Questo metodo può restituire più di un nome di pacchetto se l'attuale proprietario utilizza la funzionalità android:sharedUserId
.
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); List<String> focusOwnerPackageNames = mAppFocusManager.getAppTypeOwner( CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); if (focusOwnerPackageNames == null || focusOwnerPackageNames.isEmpty()) { // No Navigation application has focus // OEM may choose to show their default cluster view } else { // focusOwnerPackageNames // Use the PackageManager to retrieve the cluster activity for the package(s) // returned in focusOwnerPackageNames } ...
Appendice: utilizzo dell'applicazione di esempio
AOSP fornisce un'applicazione di esempio che implementa l'API dello stato di navigazione.
Per eseguire questa applicazione di esempio:
- Crea e installa Android Auto su un HU supportato. Utilizza le istruzioni per la creazione e il flashing di Android specifiche per il tuo dispositivo. Per istruzioni, vedere Utilizzo delle schede di riferimento .
- Collegare un display secondario fisico all'HU (se supportato) o attivare l'HU secondario virtuale:
- Seleziona Modalità sviluppatore nell'app Impostazioni.
- Vai a Impostazioni > Sistema > Avanzate > Opzioni sviluppatore > Simula schermi secondari .
- Riavvia l'HU. Il servizio ClusterRenderingService è connesso al display secondario.
- Per avviare l'app KitchenSink:
- Apri il cassetto.
- Vai all'Ist. Grappolo .
- Fai clic su METADATI DI INIZIO .
KitchenSink richiede il focus NAVIGAZIONE, che istruisce il servizio DirectRenderingCluster
a visualizzare un'interfaccia utente fittizia su Instrument Cluster.