Mit der Android for Cars App Library können Sie Ihre Navigations--, POI--, IoT-- oder Wetter-App im Auto nutzen. Dazu werden Vorlagen bereitgestellt, die den Standards für Ablenkung des Fahrers entsprechen. Außerdem werden Details wie die Vielfalt der Faktoren für Autodisplays und Eingabemodalitäten berücksichtigt.
Dieser Leitfaden bietet einen Überblick über die wichtigsten Funktionen und Konzepte der Bibliothek und führt Sie durch die Einrichtung einer einfachen App.
Hinweis
- Design für Android for Cars – hier finden Sie Informationen zur Auto-App-Bibliothek.
- Übersicht über Navigations-Apps und andere Apps für Autofahrer
- Apps mit Vorlagen erstellen – Übersicht
- Bausteine, die Vorlagen und Vorlagenkomponenten abdecken
- Beispielhafte Abläufe, die gängige UX-Muster veranschaulichen
- Anforderungen an Vorlagen-Apps
- Sehen Sie sich die wichtigen Begriffe und Konzepte im folgenden Abschnitt an.
- Machen Sie sich mit der Android Auto-System-UI und dem Android Automotive OS-Design vertraut.
- Lesen Sie die Versionshinweise.
- Sehen Sie sich die Beispiele an.
Wichtige Begriffe und Konzepte
- Modelle und Vorlagen
- Die Benutzeroberfläche wird durch einen Graphen von Modellobjekten dargestellt, die entsprechend der Vorlage, zu der sie gehören, auf unterschiedliche Weise angeordnet werden können. Vorlagen sind eine Teilmenge der Modelle, die als Stamm in diesen Diagrammen fungieren können. Modelle enthalten die Informationen, die dem Nutzer in Form von Text und Bildern angezeigt werden sollen, sowie Attribute zum Konfigurieren von Aspekten der visuellen Darstellung dieser Informationen, z. B. Textfarben oder Bildgrößen. Der Host konvertiert die Modelle in Ansichten, die den Standards für Ablenkung des Fahrers entsprechen, und berücksichtigt Details wie die Vielfalt der Faktoren für den Autobildschirm und die Eingabemodalitäten.
- Host
- Der Host ist die Backend-Komponente, die die von den APIs der Bibliothek angebotenen Funktionen implementiert, damit Ihre App im Auto ausgeführt werden kann. Die Aufgaben des Hosts reichen vom Auffinden Ihrer App und der Verwaltung ihres Lebenszyklus über die Umwandlung Ihrer Modelle in Ansichten bis hin zur Benachrichtigung Ihrer App über Nutzerinteraktionen. Auf Mobilgeräten wird dieser Host von Android Auto implementiert. Unter Android Automotive OS wird dieser Host als System-App installiert.
- Vorlageneinschränkungen
- Verschiedene Vorlagen erzwingen Einschränkungen im Inhalt ihrer Modelle. Bei Listenvorlagen ist beispielsweise die Anzahl der Elemente begrenzt, die dem Nutzer präsentiert werden können. Auch bei Vorlagen gibt es Einschränkungen hinsichtlich der Art und Weise, wie sie verbunden werden können, um den Ablauf einer Aufgabe zu bilden. Die App kann beispielsweise nur bis zu fünf Vorlagen in den Bildschirmstapel einfügen. Weitere Informationen finden Sie unter Vorlageneinschränkungen.
Screen
Screen
ist eine Klasse, die von der Bibliothek bereitgestellt wird und die Apps implementieren, um die Benutzeroberfläche zu verwalten, die dem Nutzer präsentiert wird. EinScreen
hat einen Lebenszyklus und bietet den Mechanismus, mit dem die App die Vorlage sendet, die angezeigt werden soll, wenn der Bildschirm sichtbar ist.Screen
-Instanzen können auch in einenScreen
-Stack eingefügt und daraus entfernt werden. So wird sichergestellt, dass sie den Einschränkungen für den Vorlagenablauf entsprechen.CarAppService
CarAppService
ist eine abstrakteService
-Klasse, die Ihre App implementieren und exportieren muss, damit sie vom Host erkannt und verwaltet werden kann. DieCarAppService
Ihrer App ist dafür verantwortlich, mitcreateHostValidator
zu prüfen, ob eine Hostverbindung vertrauenswürdig ist, und anschließend mitonCreateSession
für jede VerbindungSession
-Instanzen bereitzustellen.Session
Session
ist eine abstrakte Klasse, die Ihre App implementieren und mitCarAppService.onCreateSession
zurückgeben muss. Sie dient als Einstiegspunkt für die Anzeige von Informationen auf dem Display des Autos. Sie hat einen Lebenszyklus, der den aktuellen Status Ihrer App auf dem Display des Autos angibt, z. B. wenn Ihre App sichtbar oder ausgeblendet ist.Wenn ein
Session
gestartet wird, z. B. beim ersten Starten der App, fordert der Host die ersteScreen
zur Anzeige mit der MethodeonCreateScreen
an.
Car App Library installieren
Auf der Seite mit den Jetpack-Bibliotheksversionen finden Sie eine Anleitung zum Hinzufügen der Bibliothek zu Ihrer App.
Manifestdateien Ihrer App konfigurieren
Bevor Sie Ihre Auto-App erstellen können, müssen Sie die Manifestdateien Ihrer App so konfigurieren:
CarAppService deklarieren
Der Host stellt über Ihre CarAppService
-Implementierung eine Verbindung zu Ihrer App her. Sie deklarieren diesen Dienst in Ihrem Manifest, damit der Host Ihre App erkennen und eine Verbindung zu ihr herstellen kann.
Sie müssen die Kategorie Ihrer App auch im Element <category>
des Intent-Filters Ihrer App deklarieren. Eine Liste der zulässigen Werte für dieses Element finden Sie unter Unterstützte App-Kategorien.
Das folgende Code-Snippet zeigt, wie Sie einen Car App-Dienst für eine POI-App in Ihrem Manifest deklarieren:
<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>
Unterstützte App-Kategorien
Deklarieren Sie die Kategorie Ihrer App, indem Sie dem Intent-Filter einen oder mehrere der folgenden Kategoriewerte hinzufügen, wenn Sie CarAppService
wie im vorherigen Abschnitt beschrieben deklarieren:
androidx.car.app.category.NAVIGATION
: Eine App, die eine detaillierte Navigation bietet. Weitere Informationen finden Sie unter Navigations-Apps für Autos entwickeln.androidx.car.app.category.POI
: Eine App, die Funktionen zum Auffinden von Points of Interest wie Parkplätzen, Ladestationen und Tankstellen bietet. Weitere Informationen finden Sie unter Apps für interessante Orte für Autos entwickeln.androidx.car.app.category.IOT
: Eine App, mit der Nutzer relevante Aktionen auf verbundenen Geräten im Auto ausführen können. Weitere Informationen finden Sie unter IoT-Apps für Autos entwickeln.androidx.car.app.category.WEATHER
: Eine App, in der Nutzer relevante Wetterinformationen zu ihrem aktuellen Standort oder entlang ihrer Route sehen können. Weitere Informationen finden Sie unter Wetter-Apps für Autos entwickeln.androidx.car.app.category.MEDIA
: Eine App, mit der Nutzer im Auto Musik, Radio, Hörbücher und andere Audioinhalte suchen und abspielen können. Weitere Informationen finden Sie unter Medien-Apps mit Vorlagen für Autos entwickeln.androidx.car.app.category.MESSAGING
: Eine App, mit der Nutzer über kurze Textnachrichten kommunizieren können. Weitere Informationen finden Sie unter Templated Messaging-Funktionen für Android Auto entwickeln.androidx.car.app.category.CALLING
: Eine App, mit der Nutzer per Sprachanruf kommunizieren können. Weitere Informationen finden Sie unter Anruffunktionen für Android Auto entwickeln.
Qualitätsrichtlinien für Android-Apps für Autos: Hier findest du detaillierte Beschreibungen der einzelnen Kategorien und Kriterien für Apps, die in diese Kategorien fallen.
App-Name und ‑Symbol angeben
Sie müssen einen App-Namen und ein App-Symbol angeben, die der Host verwenden kann, um Ihre App in der System-UI darzustellen.
Sie können den App-Namen und das Symbol, mit dem Ihre App dargestellt wird, mit den Attributen label
und icon
Ihres CarAppService
angeben:
...
<service
android:name=".MyCarAppService"
android:exported="true"
android:label="@string/my_app_name"
android:icon="@drawable/my_app_icon">
...
</service>
...
Wenn das Label oder das Symbol nicht im Element <service>
deklariert sind, greift der Host auf die für das Element <application>
angegebenen Werte zurück.
Benutzerdefiniertes Design festlegen
Wenn Sie ein benutzerdefiniertes Design für Ihre Auto-App festlegen möchten, fügen Sie Ihrer Manifestdatei ein <meta-data>
-Element hinzu:
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
Deklarieren Sie dann Ihre Stilressource, um die folgenden Attribute für Ihr benutzerdefiniertes Auto-App-Design festzulegen:
<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>
API-Level für Auto-Apps
In der Car App Library werden eigene API-Levels definiert, damit Sie wissen, welche Bibliotheksfunktionen vom Template-Host auf einem Fahrzeug unterstützt werden.
Verwenden Sie die Methode getCarAppApiLevel()
, um das höchste von einem Host unterstützte Car App API-Level abzurufen.
Deklarieren Sie das von Ihrer App unterstützte Mindest-Car App API-Level in der Datei AndroidManifest.xml
:
<manifest ...>
<application ...>
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1"/>
</application>
</manifest>
In der Dokumentation zur Annotation RequiresCarApi
finden Sie Informationen dazu, wie Sie die Abwärtskompatibilität aufrechterhalten und die Mindest-API-Ebene deklarieren, die für die Verwendung eines Features erforderlich ist. Eine Definition, welches API-Level für die Verwendung einer bestimmten Funktion der Car App Library erforderlich ist, finden Sie in der Referenzdokumentation für CarAppApiLevels
.
CarAppService und ‑Sitzung erstellen
Ihre App muss die Klasse CarAppService
erweitern und die Methode onCreateSession
implementieren, die eine Session
-Instanz zurückgibt, die der aktuellen Verbindung zum Host entspricht:
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(); } ... }
Die Session
-Instanz ist dafür verantwortlich, die Screen
-Instanz zurückzugeben, die beim ersten Start der App verwendet wird:
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()); } ... }
Wenn Ihre Auto-App von einem Bildschirm aus gestartet werden muss, der nicht der Startbildschirm oder die Landingpage Ihrer App ist, z. B. bei der Verarbeitung von Deeplinks, können Sie vor der Rückgabe von onCreateScreen
einen Backstack von Bildschirmen mit ScreenManager.push
vorab festlegen.
Durch Pre-Seeding können Nutzer vom ersten Bildschirm, der in Ihrer App angezeigt wird, zu vorherigen Bildschirmen zurückkehren.
Startbildschirm erstellen
Sie erstellen die von Ihrer App angezeigten Bildschirme, indem Sie Klassen definieren, die die Klasse Screen
erweitern, und die Methode onGetTemplate
implementieren, die die Template
-Instanz zurückgibt, die den Zustand der Benutzeroberfläche darstellt, die auf dem Display des Fahrzeugs angezeigt werden soll.
Das folgende Snippet zeigt, wie Sie ein Screen
deklarieren, das eine PaneTemplate
-Vorlage verwendet, um einen einfachen „Hallo Welt!“-String anzuzeigen:
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(); } }
Die Klasse „CarContext“
Die Klasse CarContext
ist eine ContextWrapper
-Unterklasse, auf die über Ihre Session
- und Screen
-Instanzen zugegriffen werden kann. Sie bietet Zugriff auf Autoservices wie ScreenManager
zum Verwalten des Bildschirmstapels, AppManager
für allgemeine appbezogene Funktionen wie den Zugriff auf das Surface
-Objekt zum Zeichnen von Karten und NavigationManager
, das von Apps für die Turn-by-Turn-Navigation verwendet wird, um Navigationsmetadaten und andere navigationsbezogene Ereignisse an den Host zu senden.
Eine umfassende Liste der Bibliotheksfunktionen, die für Navigations-Apps verfügbar sind, finden Sie unter Auf die Navigationsvorlagen zugreifen.
CarContext
bietet auch andere Funktionen, z. B. das Laden von Drawables-Ressourcen mithilfe der Konfiguration des Autodisplays, das Starten einer App im Auto mithilfe von Intents und das Signalisieren, ob Ihre App ihre Karte im dunklen Design anzeigen soll.
Bildschirmnavigation implementieren
Apps haben oft mehrere verschiedene Bildschirme, auf denen jeweils unterschiedliche Vorlagen verwendet werden können. Nutzer können durch die Bildschirme navigieren, während sie mit der auf dem Bildschirm angezeigten Benutzeroberfläche interagieren.
Die Klasse ScreenManager
bietet einen Bildschirmstapel, mit dem Sie Bildschirme einfügen können, die automatisch entfernt werden können, wenn der Nutzer auf dem Bildschirm im Auto eine Schaltfläche „Zurück“ auswählt oder die in einigen Autos verfügbare Hardware-Schaltfläche „Zurück“ verwendet.
Das folgende Snippet zeigt, wie Sie einer Nachrichtenvorlage eine „Zurück“-Aktion sowie eine Aktion hinzufügen, die bei Auswahl durch den Nutzer einen neuen Bildschirm aufruft:
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();
Das Action.BACK
-Objekt ist ein Standard-Action
, das ScreenManager.pop
automatisch aufruft.
Dieses Verhalten kann mit der OnBackPressedDispatcher
-Instanz überschrieben werden, die über CarContext
verfügbar ist.
Damit die App während der Fahrt sicher verwendet werden kann, darf der Bildschirmstapel maximal fünf Bildschirme umfassen. Weitere Informationen finden Sie im Abschnitt Vorlageneinschränkungen.
Inhalte einer Vorlage aktualisieren
Ihre App kann die Ungültigkeit des Inhalts eines Screen
anfordern, indem sie die Methode Screen.invalidate
aufruft.
Der Host ruft dann die Methode Screen.onGetTemplate
Ihrer App auf, um die Vorlage mit den neuen Inhalten abzurufen.
Beim Aktualisieren einer Screen
ist es wichtig, die spezifischen Inhalte in der Vorlage zu kennen, die aktualisiert werden können, damit die neue Vorlage nicht auf das Vorlagenkontingent des Hosts angerechnet wird.
Weitere Informationen finden Sie im Abschnitt Vorlageneinschränkungen.
Wir empfehlen, die Bildschirme so zu strukturieren, dass es eine 1:1-Beziehung zwischen einem Screen
und dem Typ der Vorlage gibt, die über die onGetTemplate
-Implementierung zurückgegeben wird.
Karten zeichnen
Navigations-, POI- und Wetter-Apps, die die folgenden Vorlagen verwenden, können Karten zeichnen, indem sie auf eine Surface
zugreifen.
Damit Sie die folgenden Vorlagen verwenden können, muss für Ihre App eine der entsprechenden Berechtigungen in einem <uses-permission>
-Element in der AndroidManifest.xml
-Datei deklariert sein.
Vorlage | Vorlagenberechtigung | Kategorieanleitung |
---|---|---|
NavigationTemplate |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigation |
MapWithContentTemplate |
androidx.car.app.NAVIGATION_TEMPLATES ODER androidx.car.app.MAP_TEMPLATES |
Navigation, POI, Wetter |
MapTemplate (eingestellt) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigation |
PlaceListNavigationTemplate (eingestellt) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigation |
RoutePreviewNavigationTemplate (eingestellt) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigation |
Berechtigung für die Oberfläche deklarieren
Zusätzlich zu der für die Vorlage, die Ihre App verwendet, erforderlichen Berechtigung muss Ihre App die Berechtigung androidx.car.app.ACCESS_SURFACE
in der Datei AndroidManifest.xml
deklarieren, um Zugriff auf die Oberfläche zu erhalten:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
...
</manifest>
Auf die Plattform zugreifen
Um auf die Surface
zuzugreifen, die der Host bereitstellt, müssen Sie eine SurfaceCallback
implementieren und diese Implementierung dem AppManager
-Autodienst zur Verfügung stellen. Die aktuelle Surface
wird an Ihre SurfaceCallback
im Parameter SurfaceContainer
der Callbacks onSurfaceAvailable()
und onSurfaceDestroyed()
übergeben.
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
Sichtbaren Bereich der Oberfläche verstehen
Der Host kann Benutzeroberflächenelemente für die Vorlagen über der Karte zeichnen. Der Host teilt den Bereich der Oberfläche mit, der garantiert frei und für den Nutzer vollständig sichtbar ist, indem er die Methode SurfaceCallback.onVisibleAreaChanged
aufruft. Um die Anzahl der Änderungen zu minimieren, ruft der Host die Methode SurfaceCallback.onStableAreaChanged
mit dem kleinsten Rechteck auf, das basierend auf der aktuellen Vorlage immer sichtbar ist.
Wenn beispielsweise eine Navigations-App die NavigationTemplate
mit einem Aktionsstreifen oben verwendet, kann der Aktionsstreifen ausgeblendet werden, wenn der Nutzer eine Weile nicht mit dem Display interagiert hat, um mehr Platz für die Karte zu schaffen. In diesem Fall gibt es einen Callback zu onStableAreaChanged
und onVisibleAreaChanged
mit demselben Rechteck. Wenn die Aktionsleiste ausgeblendet ist, wird nur onVisibleAreaChanged
mit dem größeren Bereich aufgerufen. Wenn der Nutzer mit dem Bildschirm interagiert, wird wieder nur onVisibleAreaChanged
mit dem ersten Rechteck aufgerufen.
Dunkles Design unterstützen
Apps müssen ihre Karte auf der Surface
-Instanz mit den richtigen dunklen Farben neu zeichnen, wenn der Host dies aufgrund der Bedingungen erfordert, wie in den Qualitätsrichtlinien für Android-Apps für Autos beschrieben.
Mit der Methode CarContext.isDarkMode
können Sie entscheiden, ob eine dunkle Karte gezeichnet werden soll. Immer wenn sich der Status des dunklen Designs ändert, erhalten Sie einen Aufruf an Session.onCarConfigurationChanged
.
Karten auf dem Clusterdisplay anzeigen
Navigations-Apps können nicht nur Karten auf dem Hauptdisplay zeichnen, sondern auch auf dem Kombiinstrument-Display hinter dem Lenkrad. Weitere Informationen finden Sie unter Auf dem Clusterdisplay zeichnen.
Nutzern die Möglichkeit geben, mit Ihrer Karte zu interagieren
Wenn Sie die folgenden Vorlagen verwenden, können Sie Nutzern die Interaktion mit den von Ihnen gezeichneten Karten ermöglichen, z. B. durch Zoomen und Schwenken.
Vorlage | Interaktivität wird seit Car App API-Level unterstützt |
---|---|
NavigationTemplate |
2 |
PlaceListNavigationTemplate (veraltet) |
4 |
RoutePreviewNavigationTemplate (veraltet) |
4 |
MapTemplate (veraltet) |
5 (Einführung der Vorlage) |
MapWithContentTemplate |
7 (Einführung der Vorlage) |
Interaktivitäts-Callbacks implementieren
Die SurfaceCallback
-Schnittstelle enthält mehrere Callback-Methoden, die Sie implementieren können, um Karten, die mit den Vorlagen im vorherigen Abschnitt erstellt wurden, interaktiver zu gestalten:
Interaktion | SurfaceCallback -Methode |
Unterstützt seit Car App API-Level |
---|---|---|
Tippen | onClick |
5 |
Zum Zoomen auseinander- und zusammenziehen | onScale |
2 |
Ziehen mit einem Finger | onScroll |
2 |
Übertragung durch einmaliges Tippen | onFling |
2 |
Doppeltippen | onScale (mit Skalierungsfaktor, der vom Vorlagenhost bestimmt wird) |
2 |
Drehknopf-Geste im Schwenkmodus | onScroll (mit Entfernungsfaktor, der vom Vorlagenhost bestimmt wird) |
2 |
Kartenaktionsleiste hinzufügen
Diese Vorlagen können eine Kartenaktionsleiste für kartenbezogene Aktionen wie das Ein- und Auszoomen, das Zentrieren, das Anzeigen eines Kompasses und andere Aktionen enthalten, die Sie anzeigen möchten. Der Kartenaktionsbereich kann bis zu vier Schaltflächen nur mit Symbolen enthalten, die aktualisiert werden können, ohne die Tiefe der Aufgabe zu beeinträchtigen. Sie wird im Leerlauf ausgeblendet und im aktiven Zustand wieder eingeblendet.
Wenn Sie Interaktivitäts-Callbacks für die Karte erhalten möchten, müssen Sie der Aktionsleiste der Karte eine Action.PAN
-Schaltfläche hinzufügen. Wenn der Nutzer die Schwenkschaltfläche drückt, wechselt der Host in den Schwenkmodus, wie im folgenden Abschnitt beschrieben.
Wenn in Ihrer App die Schaltfläche Action.PAN
im Aktionsstreifen der Karte fehlt, werden keine Nutzereingaben aus den SurfaceCallback
-Methoden empfangen und der Host beendet alle zuvor aktivierten Schwenkmodi.
Auf einem Touchscreen wird die Schaltfläche zum Schwenken nicht angezeigt.
Informationen zum Schwenkmodus
Im Schwenkmodus übersetzt der Vorlagenhost Nutzereingaben von Eingabegeräten ohne Touchfunktion, z. B. Drehreglern und Touchpads, in die entsprechenden SurfaceCallback
-Methoden. Reagiere auf die Nutzeraktion zum Aufrufen oder Beenden des Schwenkmodus mit der Methode setPanModeListener
in der NavigationTemplate.Builder
. Der Host kann andere UI-Komponenten in der Vorlage ausblenden, während sich der Nutzer im Schwenkmodus befindet.
Mit dem Nutzer interagieren
Ihre App kann mit dem Nutzer interagieren, indem sie ähnliche Muster wie eine mobile App verwendet.
Nutzereingaben verarbeiten
Ihre App kann auf Nutzereingaben reagieren, indem sie die entsprechenden Listener an die Modelle übergibt, die sie unterstützen. Das folgende Snippet zeigt, wie Sie ein Action
-Modell erstellen, das einen OnClickListener
festlegt, der eine Methode aufruft, die im Code Ihrer App definiert ist:
Kotlin
val action = Action.Builder() .setTitle("Navigate") .setOnClickListener(::onClickNavigate) .build()
Java
Action action = new Action.Builder() .setTitle("Navigate") .setOnClickListener(this::onClickNavigate) .build();
Mit der Methode onClickNavigate
kann dann die Standard-Navigations-Car-App mit der Methode CarContext.startCarApp
gestartet werden:
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); }
Weitere Informationen zum Starten von Apps, einschließlich des Formats des ACTION_NAVIGATE
-Intents, finden Sie im Abschnitt Auto-App mit einem Intent starten.
Einige Aktionen, z. B. solche, bei denen der Nutzer aufgefordert wird, die Interaktion auf seinem Mobilgerät fortzusetzen, sind nur zulässig, wenn das Auto geparkt ist.
Sie können die Aktionen mit dem ParkedOnlyOnClickListener
implementieren. Wenn das Auto nicht geparkt ist, wird dem Nutzer angezeigt, dass die Aktion in diesem Fall nicht zulässig ist. Wenn das Auto geparkt ist, wird der Code normal ausgeführt. Das folgende Snippet zeigt, wie Sie mit ParkedOnlyOnClickListener
einen Einstellungsbildschirm auf dem Mobilgerät öffnen:
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();
Benachrichtigungen anzeigen
Benachrichtigungen, die an das Mobilgerät gesendet werden, werden nur dann auf dem Display des Autos angezeigt, wenn sie mit einem CarAppExtender
erweitert werden.
Einige Benachrichtigungsattribute wie Inhaltstitel, Text, Symbol und Aktionen können in CarAppExtender
festgelegt werden. Dadurch werden die Attribute der Benachrichtigung überschrieben, wenn sie auf dem Autodisplay angezeigt werden.
Im folgenden Snippet sehen Sie, wie Sie eine Benachrichtigung an den Bildschirm des Autos senden, auf dem ein anderer Titel als auf dem Mobilgerät angezeigt wird:
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();
Benachrichtigungen können sich auf die folgenden Bereiche der Benutzeroberfläche auswirken:
- Dem Nutzer wird möglicherweise eine wichtige Benachrichtigung (HUN) angezeigt.
- Es kann ein Eintrag im Benachrichtigungscenter hinzugefügt werden, optional mit einem Badge, das im Bereich sichtbar ist.
- Bei Navigations-Apps kann die Benachrichtigung im Streifen-Widget angezeigt werden, wie unter Turn-by-Turn-Benachrichtigungen beschrieben.
Sie können festlegen, wie sich die Benachrichtigungen Ihrer App auf die einzelnen Elemente der Benutzeroberfläche auswirken sollen. Verwenden Sie dazu die Priorität der Benachrichtigung, wie in der Dokumentation zu CarAppExtender
beschrieben.
Wenn NotificationCompat.Builder.setOnlyAlertOnce
mit dem Wert true
aufgerufen wird, wird eine Benachrichtigung mit hoher Priorität nur einmal als HUN angezeigt.
Weitere Informationen zum Gestalten von Benachrichtigungen für Ihre Auto-App finden Sie im Google-Leitfaden „Design für Android for Cars“ unter Benachrichtigungen.
Toasts anzeigen
Ihre App kann mit CarToast
einen Toast anzeigen, wie in diesem Snippet gezeigt:
Kotlin
CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()
Java
CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();
Berechtigungen anfordern
Wenn Ihre App Zugriff auf eingeschränkte Daten oder Aktionen benötigt, z. B. auf den Standort, gelten die Standardregeln für Android-Berechtigungen. Mit der Methode CarContext.requestPermissions()
können Sie eine Berechtigung anfordern.
Der Vorteil der Verwendung von CarContext.requestPermissions()
im Gegensatz zu Standard-Android-APIs besteht darin, dass Sie keine eigene Activity
starten müssen, um das Berechtigungsdialogfeld zu erstellen. Außerdem können Sie denselben Code sowohl für Android Auto als auch für Android Automotive OS verwenden, anstatt plattformabhängige Abläufe erstellen zu müssen.
Berechtigungsdialog in Android Auto gestalten
In Android Auto wird das Berechtigungsdialogfeld für den Nutzer auf dem Smartphone angezeigt.
Standardmäßig wird kein Hintergrund hinter dem Dialogfeld angezeigt. Wenn Sie einen benutzerdefinierten Hintergrund festlegen möchten, deklarieren Sie in Ihrer AndroidManifest.xml
-Datei ein Car App-Design und legen Sie das Attribut carPermissionActivityLayout
für Ihr Car App-Design fest.
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
Legen Sie dann das Attribut carPermissionActivityLayout
für das Design Ihrer Auto-App fest:
<resources> <style name="MyCarAppTheme"> <item name="carPermissionActivityLayout">@layout/my_custom_background</item> </style> </resources>
Auto-App mit einem Intent starten
Mit der Methode CarContext.startCarApp
können Sie eine der folgenden Aktionen ausführen:
- Öffnen Sie die Wähltastatur, um einen Anruf zu starten.
- Starten Sie die detaillierte Routenführung zu einem Ort mit der Standard-Navigations-App für Autos.
- Eigene App mit einem Intent starten
Das folgende Beispiel zeigt, wie Sie eine Benachrichtigung mit einer Aktion erstellen, die Ihre App mit einem Bildschirm öffnet, auf dem die Details einer Parkreservierung angezeigt werden.
Sie erweitern die Benachrichtigungsinstanz mit einer Content-Intent, die ein PendingIntent
enthält, das eine explizite Intent für die Aktion Ihrer App umschließt:
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());
Ihre App muss auch einen BroadcastReceiver
deklarieren, der aufgerufen wird, um den Intent zu verarbeiten, wenn der Nutzer die Aktion in der Benachrichtigungsoberfläche auswählt und CarContext.startCarApp
mit einem Intent aufruft, der den Daten-URI enthält:
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))); } } }
Schließlich verarbeitet die Methode Session.onNewIntent
in Ihrer App diesen Intent, indem sie den Bildschirm für die Parkreservierung auf den Stapel legt, sofern er sich nicht bereits oben befindet:
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())); } } }
Weitere Informationen zum Verarbeiten von Benachrichtigungen für die Auto-App finden Sie im Abschnitt Benachrichtigungen anzeigen.
Vorlageneinschränkungen
Der Host begrenzt die Anzahl der Vorlagen, die für eine bestimmte Aufgabe angezeigt werden, auf maximal fünf. Die letzte Vorlage muss einen der folgenden Typen haben:
NavigationTemplate
PaneTemplate
MessageTemplate
MediaPlaybackTemplate
SignInTemplate
LongMessageTemplate
Dieses Limit gilt für die Anzahl der Vorlagen und nicht für die Anzahl der Screen
-Instanzen im Stack. Wenn eine App beispielsweise auf Bildschirm A zwei Vorlagen sendet und dann Bildschirm B aufruft, kann sie jetzt drei weitere Vorlagen senden. Wenn jeder Bildschirm so strukturiert ist, dass nur eine Vorlage gesendet wird, kann die App alternativ fünf Bildschirminstanzen auf den ScreenManager
-Stack legen.
Für diese Einschränkungen gibt es Sonderfälle: Vorlagenaktualisierungen sowie Zurück- und Zurücksetzen-Vorgänge.
Vorlagenaktualisierungen
Bestimmte Inhaltsaktualisierungen werden nicht auf das Vorlagenlimit angerechnet. Wenn eine App eine neue Vorlage pusht, die vom selben Typ ist und dieselben Hauptinhalte wie die vorherige Vorlage enthält, wird die neue Vorlage im Allgemeinen nicht auf das Kontingent angerechnet. Wenn Sie beispielsweise den Ein/Aus-Status einer Zeile in einem ListTemplate
aktualisieren, wird das nicht auf das Kontingent angerechnet. In der Dokumentation der einzelnen Vorlagen erfahren Sie mehr darüber, welche Arten von Inhaltsaktualisierungen als Aktualisierung gelten.
Vorgänge für die Rückseite
Damit Unterläufe innerhalb einer Aufgabe aktiviert werden können, erkennt der Host, wenn eine App ein Screen
aus dem ScreenManager
-Stack entfernt, und aktualisiert das verbleibende Kontingent basierend auf der Anzahl der Vorlagen, die die App zurücklegt.
Wenn die App beispielsweise auf Bildschirm A zwei Vorlagen sendet, dann Bildschirm B pusht und zwei weitere Vorlagen sendet, hat die App noch ein Kontingent übrig. Wenn die App dann wieder zu Bildschirm A zurückkehrt, setzt der Host das Kontingent auf drei zurück, da die App zwei Vorlagen zurückgegangen ist.
Wenn eine App zu einem Bildschirm zurückkehrt, muss sie eine Vorlage senden, die denselben Typ hat wie die zuletzt von diesem Bildschirm gesendete Vorlage. Das Senden eines anderen Vorlagentyps führt zu einem Fehler. Solange der Typ jedoch während eines Back-Vorgangs gleich bleibt, kann eine App den Inhalt der Vorlage frei ändern, ohne dass sich dies auf das Kontingent auswirkt.
Vorgänge zurücksetzen
Bestimmte Vorlagen haben eine spezielle Semantik, die das Ende einer Aufgabe signalisiert. Die NavigationTemplate
ist beispielsweise eine Ansicht, die auf dem Bildschirm bleiben und mit neuen Schritt-für-Schritt-Anleitungen für den Nutzer aktualisiert werden soll. Wenn der Host eine dieser Vorlagen erreicht, wird das Vorlagenkontingent zurückgesetzt und die Vorlage wird so behandelt, als wäre sie der erste Schritt einer neuen Aufgabe. Dadurch kann die App eine neue Aufgabe starten.
In der Dokumentation der einzelnen Vorlagen finden Sie Informationen dazu, bei welchen Vorlagen ein Zurücksetzen auf dem Host ausgelöst wird.
Wenn der Host eine Absicht zum Starten der App über eine Benachrichtigungsaktion oder über den Launcher empfängt, wird das Kontingent ebenfalls zurückgesetzt. Mit diesem Mechanismus kann eine App einen neuen Aufgabenablauf über Benachrichtigungen starten. Das gilt auch, wenn eine App bereits gebunden ist und sich im Vordergrund befindet.
Weitere Informationen zum Anzeigen von Benachrichtigungen Ihrer App auf dem Display des Autos finden Sie im Abschnitt Benachrichtigungen anzeigen. Informationen dazu, wie Sie Ihre App über eine Benachrichtigungsaktion starten, finden Sie im Abschnitt Auto-App mit einem Intent starten.
Connection API
Sie können mithilfe der CarConnection
API zur Laufzeit Verbindungsinformationen abrufen, um festzustellen, ob Ihre App unter Android Auto oder Android Automotive OS ausgeführt wird.
Initialisieren Sie beispielsweise in der Session
Ihrer Auto-App ein CarConnection
und abonnieren Sie LiveData
-Updates:
Kotlin
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
Java
new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);
Im Observer können Sie dann auf Änderungen des Verbindungsstatus reagieren:
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(); }
Constraints API
In verschiedenen Autos kann dem Nutzer möglicherweise eine unterschiedliche Anzahl von Item
-Instanzen gleichzeitig angezeigt werden. Mit dem ConstraintManager
können Sie das Inhaltslimit zur Laufzeit prüfen und die entsprechende Anzahl von Elementen in Ihren Vorlagen festlegen.
Rufen Sie zuerst ein ConstraintManager
von der CarContext
ab:
Kotlin
val manager = carContext.getCarService(ConstraintManager::class.java)
Java
ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);
Anschließend können Sie das abgerufene ConstraintManager
-Objekt nach dem entsprechenden Inhaltslimit abfragen. Wenn Sie beispielsweise die Anzahl der Elemente abrufen möchten, die in einem Raster angezeigt werden können, rufen Sie getContentLimit
mit CONTENT_LIMIT_TYPE_GRID
auf:
Kotlin
val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)
Java
int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);
Anmeldevorgang hinzufügen
Wenn Ihre App eine Anmeldung für Nutzer anbietet, können Sie Vorlagen wie SignInTemplate
und LongMessageTemplate
mit Car App API-Level 2 und höher verwenden, um die Anmeldung in Ihrer App auf dem Infotainmentsystem des Autos zu verarbeiten.
Um eine SignInTemplate
zu erstellen, müssen Sie eine SignInMethod
definieren. Die Car App Library unterstützt derzeit die folgenden Anmeldemethoden:
InputSignInMethod
für die Anmeldung mit Nutzername/Passwort.PinSignInMethod
für die Anmeldung mit PIN, bei der der Nutzer sein Konto über sein Smartphone mit einer auf dem Infotainmentsystem angezeigten PIN verknüpft.ProviderSignInMethod
für die Anmeldung über einen Anbieter, z. B. Über Google anmelden und One Tap.QRCodeSignInMethod
für die Anmeldung per QR-Code, bei der der Nutzer einen QR-Code scannt, um die Anmeldung auf seinem Smartphone abzuschließen. Diese Funktion ist ab Car API-Level 4 verfügbar.
Wenn Sie beispielsweise eine Vorlage implementieren möchten, mit der das Passwort des Nutzers erfasst wird, erstellen Sie zuerst ein InputCallback
, um die Nutzereingabe zu verarbeiten und zu validieren:
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. } };
Für die InputSignInMethod
Builder
ist eine InputCallback
erforderlich.
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();
Verwenden Sie schließlich Ihre neue InputSignInMethod
, um eine SignInTemplate
zu erstellen.
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();
AccountManager verwenden
Android Automotive OS-Apps mit Authentifizierung müssen AccountManager verwenden. Das hat folgende Gründe:
- Bessere Nutzerfreundlichkeit und einfache Kontoverwaltung: Nutzer können alle ihre Konten ganz einfach über das Kontomenü in den Systemeinstellungen verwalten, einschließlich An- und Abmeldung.
- Gastmodus: Da Autos gemeinsam genutzte Geräte sind, können OEMs einen Gastmodus im Fahrzeug aktivieren, in dem keine Konten hinzugefügt werden können.
Varianten für Textstrings hinzufügen
Je nach Größe des Displays im Auto wird unterschiedlich viel Text angezeigt. Mit der Car App API ab Stufe 2 können Sie mehrere Varianten eines Textstrings angeben, damit er optimal auf den Bildschirm passt. Wenn Sie sehen möchten, wo Textvarianten akzeptiert werden, suchen Sie nach Vorlagen und Komponenten, die ein CarText
verwenden.
Sie können einem CarText
mit der Methode CarText.Builder.addVariant()
Varianten von Textstrings hinzufügen:
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();
Sie können diesen CarText
dann beispielsweise als primären Text eines GridItem
verwenden.
Kotlin
GridItem.Builder() .addTitle(itemTitle) ... .build()
Java
new GridItem.Builder() .addTitle(itemTitle) ... build();
Fügen Sie Strings in der Reihenfolge von der bevorzugtesten zur am wenigsten bevorzugten hinzu, z. B. vom längsten zum kürzesten. Der Host wählt den String mit der passenden Länge aus, je nachdem, wie viel Platz auf dem Display des Autos verfügbar ist.
Inline-CarIcons für Zeilen hinzufügen
Mit CarIconSpan
können Sie Inline-Symbole in Text einfügen, um die visuelle Attraktivität Ihrer App zu steigern.
Weitere Informationen zum Erstellen dieser Spannen finden Sie in der Dokumentation zu CarIconSpan.create
. Eine Übersicht über die Funktionsweise der Textformatierung mit Spans finden Sie unter Spantastic text styling with Spans.
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();
APIs für Fahrzeughardware
Ab Car App API-Level 3 enthält die Car App Library APIs, mit denen Sie auf Fahrzeugeigenschaften und Sensoren zugreifen können.
Voraussetzungen
Wenn Sie die APIs mit Android Auto verwenden möchten, fügen Sie zuerst eine Abhängigkeit von androidx.car.app:app-projected
zur Datei build.gradle
für Ihr Android Auto-Modul hinzu. Fügen Sie für Android Automotive OS der Datei build.gradle
für Ihr Android Automotive OS-Modul eine Abhängigkeit von androidx.car.app:app-automotive
hinzu.
Außerdem müssen Sie in Ihrer AndroidManifest.xml
-Datei die relevanten Berechtigungen deklarieren, die zum Anfordern der gewünschten Fahrzeugdaten erforderlich sind. Diese Berechtigungen müssen Ihnen auch vom Nutzer erteilt werden. Sie können denselben Code sowohl für Android Auto als auch für Android Automotive OS verwenden, anstatt plattformabhängige Abläufe erstellen zu müssen. Die erforderlichen Berechtigungen sind jedoch unterschiedlich.
CarInfo
In dieser Tabelle werden die Attribute beschrieben, die von den CarInfo
-APIs bereitgestellt werden, sowie die Berechtigungen, die Sie zum Verwenden der Attribute anfordern müssen:
Methoden | Properties | Android Auto-Berechtigungen | Android Automotive OS-Berechtigungen | Unterstützt seit Car App API-Level |
---|---|---|---|---|
fetchModel |
Marke, Modell, Baujahr | android.car.permission.CAR_INFO |
3 | |
fetchEnergyProfile |
Ladesteckertypen für Elektrofahrzeuge, Kraftstofftypen | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_INFO |
3 |
fetchExteriorDimensions
Diese Daten sind nur für einige Android Automotive OS-Fahrzeuge mit API 30 oder höher verfügbar. |
Außenabmessungen | – | android.car.permission.CAR_INFO |
7 |
addTollListener
removeTollListener |
Status der Mautkarte, Typ der Mautkarte | 3 | ||
addEnergyLevelListener
removeEnergyLevelListener |
Akkustand, Kraftstoffstand, Kraftstoffstand niedrig, verbleibende Reichweite | 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 |
Rohgeschwindigkeit, angezeigte Geschwindigkeit (auf dem Kombiinstrument des Autos) | com.google.android.gms.permission.CAR_SPEED |
android.car.permission.CAR_SPEED ,android.car.permission.READ_CAR_DISPLAY_UNITS |
3 |
addMileageListener
removeMileageListener
Achtung: Die Methode |
Kilometerzähler | com.google.android.gms.permission.CAR_MILEAGE |
Diese Daten sind für Apps, die über den Play Store installiert wurden, unter Android Automotive OS nicht verfügbar. | 3 |
Um beispielsweise den verbleibenden Bereich abzurufen, instanziieren Sie ein CarInfo
-Objekt und erstellen und registrieren Sie dann ein 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);
Gehen Sie nicht davon aus, dass die Daten des Fahrzeugs jederzeit verfügbar sind.
Wenn Sie einen Fehler erhalten, prüfen Sie den Status des angeforderten Werts, um besser zu verstehen, warum die angeforderten Daten nicht abgerufen werden konnten. Die vollständige Klassendefinition für CarInfo
finden Sie in der Referenzdokumentation.
CarSensors
Über die Klasse CarSensors
haben Sie Zugriff auf die Daten des Beschleunigungsmessers, des Gyroskops, des Kompasses und des Standorts des Fahrzeugs. Die Verfügbarkeit dieser Werte kann vom OEM abhängen. Das Format für die Daten vom Beschleunigungsmesser, Gyroskop und Kompass ist dasselbe wie bei der SensorManager
API. So prüfen Sie beispielsweise den Kurs des Fahrzeugs:
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);
Wenn Sie auf Standortdaten des Autos zugreifen möchten, müssen Sie außerdem die Berechtigung android.permission.ACCESS_FINE_LOCATION
deklarieren und anfordern.
Testen
Informationen zum Simulieren von Sensordaten beim Testen auf Android Auto finden Sie in den Abschnitten Sensors und Sensor configuration im Leitfaden für Desktop Head Unit. Informationen zum Simulieren von Sensordaten beim Testen unter Android Automotive OS finden Sie im Abschnitt Hardwarestatus emulieren des Emulatorleitfadens für Android Automotive OS.
Lebenszyklen von CarAppService, Session und Screen
Die Klassen Session
und Screen
implementieren die Schnittstelle LifecycleOwner
. Wenn der Nutzer mit der App interagiert, werden die Lebenszyklus-Callbacks Ihrer Session
- und Screen
-Objekte aufgerufen, wie in den folgenden Diagrammen beschrieben.
Lebenszyklen von CarAppService und Sitzung

Session
-LebenszyklusAusführliche Informationen finden Sie in der Dokumentation zur Methode Session.getLifecycle
.
Lebenszyklus eines Bildschirms

Screen
-LebenszyklusAusführliche Informationen finden Sie in der Dokumentation zur Methode Screen.getLifecycle
.
Über das Mikrofon des Autos aufnehmen
Mit der CarAppService
-Methode Ihrer App und der CarAudioRecord
-API können Sie Ihrer App Zugriff auf das Mikrofon des Autos des Nutzers gewähren. Nutzer müssen Ihrer App die Berechtigung zum Zugriff auf das Fahrzeugmikrofon erteilen. Ihre App kann die Eingaben des Nutzers in Ihrer App aufzeichnen und verarbeiten.
Berechtigung zur Aufzeichnung
Bevor Sie Audio aufzeichnen, müssen Sie zuerst die Berechtigung zur Aufzeichnung in Ihrem AndroidManifest.xml
deklarieren und den Nutzer auffordern, sie zu erteilen.
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
...
</manifest>
Sie müssen die Berechtigung zum Aufzeichnen zur Laufzeit anfordern. Weitere Informationen zum Anfordern einer Berechtigung in Ihrer Auto-App finden Sie im Abschnitt Berechtigungen anfordern.
Audio aufnehmen
Nachdem der Nutzer die Berechtigung zur Aufzeichnung erteilt hat, können Sie das Audio aufzeichnen und die Aufnahme verarbeiten.
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();
Audiofokus
Wenn Sie über das Mikrofon des Autos aufnehmen, müssen Sie zuerst den Audiofokus abrufen, damit laufende Medienwiedergaben beendet werden. Wenn Sie den Audiofokus verlieren, beenden Sie die Aufnahme.
Hier ein Beispiel für das Erhalten des Audiofokus:
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-Bibliothek
Die Testing Library für Android for Cars bietet Hilfsklassen, mit denen Sie das Verhalten Ihrer App in einer Testumgebung validieren können.
Mit SessionController
können Sie beispielsweise eine Verbindung zum Host simulieren und prüfen, ob die richtigen Screen
und Template
erstellt und zurückgegeben werden.
Problem mit der Android for Cars-App-Bibliothek melden
Wenn Sie ein Problem mit der Bibliothek finden, melden Sie es über den Google Issue Tracker. Achten Sie darauf, dass Sie alle erforderlichen Informationen in der Problemvorlage angeben.
Bevor Sie ein neues Problem melden, sehen Sie bitte in den Versionshinweisen der Bibliothek oder in der Liste der Probleme nach, ob es bereits aufgeführt ist. Sie können Probleme abonnieren und dafür stimmen, indem Sie im Tracker auf den Stern klicken. Weitere Informationen finden Sie unter Probleme abonnieren.