Mit der Instrument Cluster API (einer Android-API) können Sie Navigations-Apps wie Google Maps auf einem sekundären Display in einem Auto anzeigen, z. B. hinter dem Lenkrad auf dem Armaturenbrett. Auf dieser Seite wird beschrieben, wie Sie einen Dienst erstellen, um dieses sekundäre Display zu steuern und den Dienst in CarService einzubinden, damit Navigations-Apps eine Benutzeroberfläche anzeigen können.
Terminologie
Auf dieser Seite werden die folgenden Begriffe verwendet.
CarManager, mit der externe Apps eine Aktivität auf dem Kombi-Instrument starten und Rückrufe empfangen können, wenn das Kombi-Instrument bereit ist, Aktivitäten anzuzeigen.android:singleUser. Zu einem bestimmten Zeitpunkt wird höchstens eine Instanz des Dienstes im Android-System ausgeführt.Vorbereitung
Bevor Sie fortfahren, sollten Sie Folgendes parat haben:
- Android-Entwicklungsumgebung Informationen zum Einrichten der Android-Entwicklungsumgebung finden Sie unter Build-Anforderungen.
- Android-Quellcode herunterladen Laden Sie die aktuelle Version des Android-Quellcodes aus dem Branch „pi-car-release“ (oder höher) unter https://android.googlesource.com herunter.
- Infotainmentsystem (HU) Ein Android-Gerät mit Android 9 oder höher. Dieses Gerät muss ein eigenes Display haben und in der Lage sein, das Display mit neuen Android-Builds zu flashen.
- Instrument Cluster ist einer der folgenden Werte:
- Physischer sekundärer Bildschirm, der an die Head-Unit angeschlossen ist: Die Gerätehardware und der Kernel müssen die Verwaltung mehrerer Bildschirme unterstützen.
- Unabhängige Einheit: Jede Recheneinheit, die über eine Netzwerkverbindung mit der HU verbunden ist und einen Videostream auf ihrem eigenen Display empfangen und anzeigen kann.
- Emuliertes Display: Während der Entwicklung können Sie eine der folgenden emulierten Umgebungen verwenden:
- Simulierte sekundäre Displays: Wenn Sie ein simuliertes sekundäres Display in einer beliebigen AOSP-Android-Distribution aktivieren möchten, rufen Sie die Einstellungen Entwickleroptionen in der System-App Einstellungen auf und wählen Sie Sekundäre Displays simulieren aus.Diese Konfiguration entspricht dem Anschließen eines physischen sekundären Displays, mit der Einschränkung, dass dieses Display über dem primären Display eingeblendet wird.
- Emuliertes Kombiinstrument: Der in AAOS enthaltene Android-Emulator bietet die Möglichkeit, ein Kombiinstrument mit ClusterRenderingService anzuzeigen.
Integrationsarchitektur
Integrationskomponenten
Jede Integration der Instrument Cluster API besteht aus diesen drei Komponenten:
CarService- Navigations-Apps
- OEM-Kombiinstrument-Dienst

CarService
CarService fungiert als Vermittler zwischen Navigations-Apps und dem Auto. So wird dafür gesorgt, dass jeweils nur eine Navigations-App aktiv ist und nur Apps mit der Berechtigung android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL Daten an das Auto senden können.
CarService startet alle autospezifischen Dienste und bietet über eine Reihe von Managern Zugriff auf diese Dienste. Um mit den Diensten zu interagieren, können in Ihrem Auto ausgeführte Apps auf diese Manager zugreifen.
Für die Implementierung von Kombiinstrumenten müssen Automobil-OEMs eine benutzerdefinierte Implementierung von InstrumentClusterRendererService erstellen und ClusterRenderingService aktualisieren.
Beim Rendern eines Kombiinstruments liest CarService während des Bootvorgangs den InstrumentClusterRendererService-Schlüssel des ClusterRenderingService, um eine Implementierung von InstrumentClusterService zu finden. In AOSP verweist dieser Eintrag auf den Rendering-Dienst der Beispielclusterimplementierung der Navigation State API:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
Der in diesem Eintrag erwähnte Dienst wird initialisiert und an CarService gebunden. Wenn Navigations-Apps wie Google Maps eine CarInstrumentClusterManager anfordern, stellt CarService einen Manager bereit, der den Kombi-Instrumenten-Status aus dem gebundenen InstrumentClusterRenderingService aktualisiert.
In diesem Fall bezieht sich gebunden auf Android-Dienste.
Kombiinstrument-Dienst
OEMs müssen ein Android-Paket (APK) erstellen, das eine abgeleitete Klasse von ClusterRenderingService enthält.
Diese Klasse dient zwei Zwecken:
- Bietet eine Schnittstelle zwischen Android und dem Gerät für die Darstellung des Kombiinstruments (das ist der Zweck dieser Seite).
- Empfängt und rendert Updates zum Navigationsstatus, z. B. detaillierte Routenführung.
Für den ersten Zweck müssen OEM-Implementierungen von InstrumentClusterRendererService das sekundäre Display initialisieren, das zum Rendern von Informationen auf Bildschirmen in der Fahrerkabine verwendet wird, und diese Informationen an CarService übermitteln, indem die Methoden InstrumentClusterRendererService.setClusterActivityOptions() und InstrumentClusterRendererService.setClusterActivityState() aufgerufen werden.
Für die zweite Funktion muss der Instrument Cluster-Dienst eine Implementierung der ClusterRenderingService-Schnittstelle bereitstellen, die Navigationsstatus-Aktualisierungsereignisse (Ereignisse) empfängt, die als eventType und Ereignisdaten codiert sind, die in einem Bundle codiert sind.
Integrationsreihenfolge
Das folgende Diagramm veranschaulicht die Implementierung eines Navigationsstatus, der Updates rendert:
In dieser Abbildung stehen die Farben für Folgendes:
- Gelb:
CarServiceundCarNavigationStatusManager, die von der Android-Plattform bereitgestellt werden. Weitere Informationen finden Sie unter Auto und CAR_NAVIGATION_SERVICE. - Cyan
InstrumentClusterRendererServicevom OEM implementiert. - Lila: Die von Google und Drittentwicklern implementierte Navigations-App.
- Grün
CarAppFocusManager. Weitere Informationen finden Sie unten unter CarAppFocusManager API verwenden und unter CarAppFocusManager.
Der Informationsfluss des Navigationsstatus folgt dieser Reihenfolge:
CarServiceinitialisiertInstrumentClusterRenderingService.- Während der Initialisierung aktualisiert
InstrumentClusterRenderingServiceCarServicemit:- Eigenschaften der Instrumententafelanzeige, z. B. nicht verdeckte Grenzen (weitere Informationen dazu finden Sie unten).
- Aktivitätsoptionen, die zum Starten von Aktivitäten auf dem Kombi-Instrument erforderlich sind. Weitere Informationen finden Sie unter ActivityOptions.
- Eine Navigations-App wie Google Maps für Android Automotive oder eine beliebige Karten-App mit den erforderlichen Berechtigungen:
- Ruft ein
CarAppFocusManagermithilfe der Car-Klasse aus car-lib ab. - Bevor die detaillierte Routenführung beginnt, werden Aufrufe an
CarAppFocusManager.requestFocus()ausgeführt, umCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATIONalsappType-Parameter zu übergeben.
- Ruft ein
CarAppFocusManagerleitet diese Anfrage anCarServiceweiter. Wenn die Berechtigung erteilt wurde, prüftCarServicedas Navigations-App-Paket und sucht nach einer Aktivität, die mit der Kategorieandroid.car.cluster.NAVIGATIONgekennzeichnet ist.- Wenn die Navigations-App gefunden wird, verwendet sie die von
InstrumentClusterRenderingServicegemeldeteActivityOptions, um die Aktivität zu starten, und fügt die Eigenschaften der Instrumententafel als Extras in den Intent ein.
API einbinden
Die Implementierung von InstrumentClusterRenderingService muss folgende Anforderungen erfüllen:
- Als Singleton-Dienst festgelegt werden, indem der folgende Wert zu AndroidManifest.xml hinzugefügt wird. Dies ist erforderlich, damit nur eine Kopie des Instrument Cluster-Dienstes ausgeführt wird, auch während der Initialisierung und beim Wechseln von Nutzern:
android:singleUser="true" - Die Systemberechtigung
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICEmuss vorhanden sein. Dadurch wird sichergestellt, dass nur der Rendering-Dienst für das Kombiinstrument, der im Android-System-Image enthalten ist, jemals anCarServicegebunden wird:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
InstrumentClusterRenderingService implementieren
So erstellen Sie den Dienst:
- Schreiben Sie eine Klasse, die von ClusterRenderingService abgeleitet wird, und fügen Sie dann einen entsprechenden Eintrag in die Datei
AndroidManifest.xmlein. Diese Klasse steuert die Anzeige des Kombiinstruments und kann (optional) Daten der Navigation State API rendern. - Verwenden Sie diesen Dienst während
onCreate(), um die Kommunikation mit der Rendering-Hardware zu initialisieren. Zu den Optionen gehören: - Bestimmen Sie das sekundäre Display, das für das Kombiinstrument verwendet werden soll.
- Erstellen Sie ein virtuelles Display, damit die Instrument Cluster App das gerenderte Bild rendert und an eine externe Einheit überträgt (mit einem Videostreaming-Format wie H.264).
- Wenn die oben angegebene Anzeige bereit ist, muss dieser Dienst
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()aufrufen, um die genaueActivityOptionszu definieren, die zum Anzeigen einer Aktivität auf dem Kombiinstrument verwendet werden muss. Verwenden Sie diese Parameter:category.ClusterRenderingService.ActivityOptions.EineActivityOptions-Instanz, mit der eine Aktivität im Kombi-Instrument gestartet werden kann. Beispiel aus der Beispielimplementierung des Kombiinstruments in AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Wenn das Kombiinstrument bereit ist, Aktivitäten anzuzeigen, muss dieser Dienst
InstrumentClusterRenderingService#setClusterActivityState()aufrufen. Verwenden Sie diese Parameter:categoryClusterRenderingService.state-Bundle, das mit ClusterRenderingService generiert wurde. Geben Sie unbedingt die folgenden Daten an:visibleGibt an, dass das Kombiinstrument sichtbar und bereit ist, Inhalte anzuzeigen.unobscuredBoundsEin Rechteck, das den Bereich auf dem Kombiinstrument-Display definiert, in dem Inhalte sicher angezeigt werden können. Beispiel: Bereiche, die von Zifferblättern und Messinstrumenten abgedeckt werden.
- Überschreiben Sie die
Service#dump()-Methode und melden Sie Statusinformationen, die für die Fehlerbehebung nützlich sind (weitere Informationen finden Sie unter dumpsys).
Beispielimplementierung von InstrumentClusterRenderingService
Im folgenden Beispiel wird eine InstrumentClusterRenderingService-Implementierung beschrieben, mit der ein VirtualDisplay erstellt wird, um die Inhalte des Instrument-Clusters auf einem physischen Remote-Display zu präsentieren.
Alternativ kann dieser Code die displayId eines physischen sekundären Displays übergeben, das mit der HU verbunden ist, sofern ein solches Display verfügbar ist.
/** * Sample {@link InstrumentClusterRenderingService} implementation */ public class SampleClusterServiceImpl extends InstrumentClusterRenderingService { // Used to retrieve or create displays private final DisplayManager mDisplayManager; // Unique identifier for the display to 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); } }
CarAppFocusManager API verwenden
Die CarAppFocusManager API bietet eine Methode namens getAppTypeOwner(), mit der der von OEMs geschriebene Clusterdienst jederzeit ermitteln kann, welche Navigations-App den Navigationsfokus hat. OEMs können die vorhandene CarAppFocusManager#addFocusListener()-Methode verwenden und dann mit getAppTypeOwner() herausfinden, welche App den Fokus hat. Mit diesen Informationen können OEMs:
- Die im Kombiinstrument angezeigte Aktivität wird auf die Clusteraktivität umgestellt, die von der Navigations-App bereitgestellt wird, die den Fokus hat.
- Kann erkennen, ob die fokussierte Navigations-App eine Clusteraktivität hat oder nicht. Wenn die fokussierte Navigations-App keine Clusteraktivität hat (oder wenn eine solche Aktivität deaktiviert ist), können OEMs dieses Signal an das DIM des Autos senden, damit die Navigationsfacette des Clusters vollständig übersprungen wird.
Mit CarAppFocusManager können Sie den aktuellen App-Fokus festlegen und darauf warten, z. B. aktive Navigation oder einen Sprachbefehl. Normalerweise wird nur eine Instanz einer solchen App im System aktiv ausgeführt (oder fokussiert).
Verwenden Sie die Methode CarAppFocusManager#addFocusListener(..), um auf Änderungen des App-Fokus zu reagieren:
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 }
Mit der Methode CarAppFocusManager#getAppTypeOwner(..) können Sie die Paketnamen des aktuellen Inhabers eines bestimmten App-Typs abrufen, der im Fokus steht. Bei dieser Methode kann mehr als ein Paketname zurückgegeben werden, wenn der aktuelle Inhaber die Funktion android:sharedUserId verwendet.
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 app 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 } ...
Vorlagen-Apps identifizieren
Bei vorlagenbasierten Navigations-Apps, die die Car App-Bibliothek verwenden, gibt CarAppFocusManager#getAppTypeOwner() den Paketnamen des Hosts zurück (z. B. com.google.android.apps.automotive.templates.host), da der Host den Systemfokus im Namen der Client-App hat.
Um die navigierende Client-App zu identifizieren, können OEMs den Paketnamen aus dem Navigationsstatus-Bundle extrahieren, das mit CarNavigationStatusManager gesendet wird. Der Paketname wird im von NavigationRenderer#onNavigationStateChanged(Bundle) empfangenen Bundle unter dem Schlüssel active_app_package_name gespeichert:
// In your NavigationRenderer implementation @Override public void onNavigationStateChanged(Bundle bundle) { if (bundle.containsKey("active_app_package_name")) { String activeAppPackage = bundle.getString("active_app_package_name"); // Use the package name to identify the navigating app (e.g., com.waze) } }
Anhang: Beispiel-App verwenden
AOSP bietet eine Beispiel-App, in der die Navigation State API implementiert ist.
So führen Sie diese Beispielanwendung aus:
- Erstelle und flashe Android Auto auf einem unterstützten Infotainmentsystem. Verwende die Android-Anleitung zum Erstellen und Flashen, die für dein Gerät gilt. Eine Anleitung findest du unter Referenzboards verwenden.
- Schließen Sie ein physisches sekundäres Display an die HU an (falls unterstützt) oder aktivieren Sie die virtuelle sekundäre HU:
- Wählen Sie in den Einstellungen Entwicklermodus aus.
- Gehen Sie zu Einstellungen > System > Erweitert > Entwickleroptionen > Sekundäre Displays simulieren.
- HU neu starten
- So starten Sie die KitchenSink App:
- Öffnen Sie die Schublade.
- Gehen Sie zu Inst. Cluster.
- Klicken Sie auf METADATEN STARTEN.
KitchenSink-Anfragen fordern den NAVIGATIONS-Fokus an, wodurch der DirectRenderingCluster-Dienst eine simulierte Benutzeroberfläche auf dem Kombiinstrument anzeigt.