Android for Cars App-Bibliothek verwenden

Mit der Android for Cars-App-Bibliothek können Sie Ihre Navigations-, POI- und IoT-Apps (Internet of Things) im Auto nutzen. Dazu stellt sie eine Reihe von Vorlagen bereit, die den Standards für die Ablenkung von Fahrern entsprechen und Details wie die Vielfalt der Fahrzeugbildschirme und Eingabemodalitäten berücksichtigen.

Dieser Leitfaden bietet einen Überblick über die wichtigsten Funktionen und Konzepte der Bibliothek und führt Sie durch die Einrichtung einer einfachen App.

Hinweis

  1. Sehen Sie sich die Seiten Design fürs Autofahren an, die die Auto-App-Bibliothek behandeln.
  2. Im folgenden Abschnitt finden Sie die wichtigsten Begriffe und Konzepte.
  3. Machen Sie sich mit der Android Auto-Benutzeroberfläche und dem Design von Android Automotive OS vertraut.
  4. Lesen Sie die Versionshinweise.
  5. Sehen Sie sich die Beispiele an.

Wichtige Begriffe und Konzepte

Modelle und Vorlagen
Die Benutzeroberfläche wird durch einen Graphen von Modellobjekten dargestellt, die auf unterschiedliche Weise angeordnet werden können, sofern dies von der zugehörigen Vorlage zulässig ist. Vorlagen sind eine Teilmenge der Modelle, die als Wurzel in diesen Graphen dienen können. Modelle umfassen die Informationen, die dem Nutzer in Form von Text und Bildern angezeigt werden sollen, sowie Attribute zur Konfiguration von Aspekten des visuellen Erscheinungsbildes solcher Informationen, z. B. Textfarben oder Bildgrößen. Der Host konvertiert die Modelle in Ansichten, die den Standards für Ablenkungen von Fahrern entsprechen, und kümmert sich um Details wie die Vielfalt der Fahrzeugbildschirmfaktoren und 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 von der Entdeckung Ihrer App und der Verwaltung ihres Lebenszyklus bis hin zur Umwandlung Ihrer Modelle in Ansichten und der 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 beim Inhalt ihrer Modelle. So ist beispielsweise bei Listenvorlagen die Anzahl der Elemente begrenzt, die dem Nutzer angezeigt werden können. Außerdem gibt es Einschränkungen bei der Verbindung von Vorlagen, um den Ablauf einer Aufgabe zu bilden. Die App kann beispielsweise nur bis zu fünf Vorlagen in den Bildschirmstapel schieben. Weitere Informationen finden Sie unter Einschränkungen für Vorlagen.
Screen
Screen ist eine von der Bibliothek bereitgestellte Klasse, die von Apps implementiert wird, um die Benutzeroberfläche zu verwalten, die dem Nutzer angezeigt wird. Ein Screen hat einen Lebenszyklus und bietet der App den Mechanismus, die Vorlage zu senden, die angezeigt werden soll, wenn das Display sichtbar ist. Screen-Instanzen können auch in einen Screen-Stack geschoben und daraus entfernt werden, wodurch die Einschränkungen für den Vorlagenfluss eingehalten werden.
CarAppService
CarAppService ist eine abstrakte Service-Klasse, die Ihre App implementieren und exportieren muss, damit sie vom Host erkannt und verwaltet werden kann. Der CarAppService Ihrer App ist dafür verantwortlich, mithilfe von createHostValidator zu prüfen, ob eine Hostverbindung vertrauenswürdig ist, und anschließend mithilfe von onCreateSession Session-Instanzen für jede Verbindung bereitzustellen.
Session

Session ist eine abstrakte Klasse, die Ihre App implementieren und mit CarAppService.onCreateSession zurückgeben muss. Sie dient als Ausgangspunkt für die Anzeige von Informationen auf dem Autodisplay. Sie hat einen Lebenszyklus, der den aktuellen Status Ihrer App auf dem Autodisplay angibt, z. B. ob sie sichtbar oder ausgeblendet ist.

Wenn eine Session gestartet wird, z. B. beim ersten Starten der App, fordert der Host die Anzeige der ersten Screen mit der Methode onCreateScreen an.

Auto-App-Bibliothek installieren

Eine Anleitung zum Hinzufügen der Bibliothek zu Ihrer App finden Sie auf der Releaseseite der Jetpack-Bibliothek.

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 deine CarAppService-Implementierung eine Verbindung zu deiner App her. Sie deklarieren diesen Dienst in Ihrem Manifest, damit der Host Ihre App finden und eine Verbindung herstellen kann.

Außerdem müssen Sie die Kategorie Ihrer App im Element <category> des Intent-Filters Ihrer App angeben. Eine Liste der für dieses Element zulässigen Werte finden Sie in der Liste der unterstützten App-Kategorien.

Im folgenden Code-Snippet wird gezeigt, wie Sie einen Dienst für eine Auto-App 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 einen oder mehrere der folgenden Kategoriewerte in den Intent-Filter einfügen, wenn Sie Ihre CarAppService wie im vorangehenden Abschnitt deklarieren:

  • androidx.car.app.category.NAVIGATION: Eine App, die detaillierte Wegbeschreibungen bietet. Weitere Informationen finden Sie unter Navigations-Apps für Autos erstellen.
  • androidx.car.app.category.POI: Eine App, die Funktionen zur Suche nach interessanten Orten wie Parkplätzen, Ladestationen und Tankstellen bietet. Weitere Informationen finden Sie unter Apps mit POIs für Autos erstellen.
  • androidx.car.app.category.IOT: Eine App, mit der Nutzer relevante Aktionen auf verbundenen Geräten direkt im Auto ausführen können. Weitere Informationen finden Sie unter Internet of Things-Apps für Autos entwickeln.
  • androidx.car.app.category.WEATHER: Eine App, mit der Nutzer relevante Wetterinformationen zu ihrem aktuellen Standort oder entlang ihrer Route abrufen können. Weitere Informationen finden Sie unter Wetter-Apps für Autos entwickeln.

Unter Qualitätsrichtlinien für Android-Apps für Autos finden Sie detaillierte Beschreibungen der einzelnen Kategorien und die Kriterien, die Apps erfüllen müssen, um zu ihnen zu gehören.

App-Name und -Symbol angeben

Sie müssen einen App-Namen und ein Symbol angeben, mit dem der Host Ihre App in der System-UI darstellen kann.

Sie können den App-Namen und das App-Symbol, das für Ihre App verwendet 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 Symbol nicht im Element <service> deklariert ist, verwendet der Host die für das Element <application> angegebenen Werte.

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. Gehen Sie dazu so vor:

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

Deklarieren Sie dann Ihre Stilressource, um die folgenden Attribute für das benutzerdefinierte Design Ihrer Auto-App 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 der Auto-App

Die Car App Library definiert eigene API-Levels, damit Sie wissen, welche Bibliotheksfunktionen vom Vorlagenhost in einem Fahrzeug unterstützt werden. Verwenden Sie die Methode getCarAppApiLevel(), um die höchste Car App API-Ebene abzurufen, die von einem Host unterstützt wird.

Deklarieren Sie in der Datei AndroidManifest.xml die von Ihrer App unterstützte Mindest-Car App API-Ebene:

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

Weitere Informationen zur Beibehaltung der Abwärtskompatibilität und zum Deklarieren der Mindest-API-Version, die für die Verwendung eines Features erforderlich ist, finden Sie in der Dokumentation für die Anmerkung RequiresCarApi. Eine Definition der API-Ebene, die für die Verwendung einer bestimmten Funktion der Auto-App-Bibliothek 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 Starten der App verwendet werden soll:

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 Start- oder Landingpage Ihrer App entspricht, z. B. bei der Verarbeitung von Deeplinks, können Sie mit ScreenManager.push einen Backstack mit Bildschirmen vordefinieren, bevor Sie von onCreateScreen zurückkehren. Mit dem Vorab-Seeding können Nutzer vom ersten Bildschirm Ihrer App aus 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. Diese Methode gibt die Instanz Template zurück, die den Status der Benutzeroberfläche darstellt, der auf dem Autodisplay angezeigt werden soll.

Das folgende Snippet zeigt, wie eine Screen deklariert wird, die mit einer PaneTemplate-Vorlage einen einfachen String „Hallo Welt!“ anzeigt:

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 Ihre Session- und Screen-Instanzen zugreifen können. Sie bietet Zugriff auf Autodienste 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, die von Apps für die Schritt-für-Schritt-Navigation verwendet wird, um Navigationsmetadaten und andere navigationsbezogene Ereignisse mit dem Host zu kommunizieren.

Unter Auf Navigationsvorlagen zugreifen finden Sie eine umfassende Liste der Bibliotheksfunktionen, die für Navigations-Apps verfügbar sind.

CarContext bietet auch andere Funktionen, z. B. das Laden von Zeichnen-Ressourcen über die Konfiguration vom Autodisplay, das Starten einer App im Auto über Intents und das Signalisieren, ob die Karte Ihrer App im dunklen Design angezeigt werden soll.

Bildschirmnavigation implementieren

Apps enthalten häufig eine Reihe verschiedener Bildschirme, die möglicherweise jeweils unterschiedliche Vorlagen verwenden, durch die sich Nutzer bewegen können, während sie mit der auf dem Bildschirm angezeigten Benutzeroberfläche interagieren.

Die Klasse ScreenManager bietet einen Bildschirmstapel, mit dem Sie Bildschirme einblenden können, die automatisch eingeblendet werden, 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.

Im folgenden Snippet wird gezeigt, wie einer Nachrichtenvorlage eine Rückwärtsaktion sowie eine Aktion hinzugefügt wird, die einen neuen Bildschirm anzeigt, wenn sie vom Nutzer ausgewählt wird:

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 standardmäßiges Action, das automatisch ScreenManager.pop aufruft. Dieses Verhalten kann mit der OnBackPressedDispatcher-Instanz überschrieben werden, die über die 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.

Inhalt einer Vorlage aktualisieren

Ihre App kann die Aufhebung des Inhalts einer Screen anfordern, indem die Methode Screen.invalidate aufgerufen wird. Der Host ruft anschließend die Methode Screen.onGetTemplate Ihrer App auf, um die Vorlage mit den neuen Inhalten abzurufen.

Wenn Sie eine Screen aktualisieren, ist es wichtig, die spezifischen Inhalte in der Vorlage zu kennen, die aktualisiert werden können, damit der Host die neue Vorlage nicht auf das Vorlagenkontingent anrechnet. Weitere Informationen finden Sie im Abschnitt Vorlageneinschränkungen.

Wir empfehlen, Ihre Bildschirme so zu strukturieren, dass eine Eins-zu-Eins-Zuordnung zwischen einer Screen und der Art der Vorlage besteht, die über die onGetTemplate-Implementierung zurückgegeben wird.

Karten zeichnen

Navigations- und POI-Apps, die die folgenden Vorlagen verwenden, können Karten zeichnen, indem sie auf eine Surface zugreifen:

Vorlage Vorlagenberechtigung Hinweise zu Kategorien
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES Navigation
MapWithContentTemplate androidx.car.app.NAVIGATION_TEMPLATES ODER
androidx.car.app.MAP_TEMPLATES
Navigation, POI, Wetter
MapTemplate (veraltet) androidx.car.app.NAVIGATION_TEMPLATES Navigation
PlaceListNavigationTemplate (veraltet) androidx.car.app.NAVIGATION_TEMPLATES Navigation
RoutePreviewNavigationTemplate (veraltet) androidx.car.app.NAVIGATION_TEMPLATES Navigation

Oberfläche für Berechtigung deklarieren

Zusätzlich zu der Berechtigung, die für die von Ihrer App verwendete Vorlage erforderlich ist, muss Ihre App die Berechtigung androidx.car.app.ACCESS_SURFACE in der Datei AndroidManifest.xml angeben, um auf die Oberfläche zuzugreifen:

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

Auf die Oberfläche zugreifen

Wenn Sie auf die vom Host bereitgestellte Surface zugreifen möchten, müssen Sie eine SurfaceCallback implementieren und diese Implementierung dem AppManager-Autodienst zur Verfügung stellen. Der aktuelle Surface wird über den Parameter SurfaceContainer der Callbacks onSurfaceAvailable() und onSurfaceDestroyed() an deinen SurfaceCallback übergeben.

Kotlin

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

Java

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

Sichtbarer Bereich der Oberfläche

Der Host kann Benutzeroberflächenelemente für die Vorlagen auf der Karte zeichnen. Der Host gibt den Bereich der Oberfläche an, der für den Nutzer garantiert ungehindert und 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 auf der Grundlage der aktuellen Vorlage immer sichtbar ist.

Wenn in einer Navigations-App beispielsweise die NavigationTemplate mit einem Aktionsstreifen oben verwendet wird, kann sich der Aktionsstreifen ausblenden, wenn der Nutzer eine Weile lang nicht mit dem Display interagiert hat, um mehr Platz für die Karte zu schaffen. In diesem Fall gibt es einen Rückruf zu onStableAreaChanged und onVisibleAreaChanged mit demselben Rechteck. Wenn der Aktionsstreifen 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 in der Surface-Instanz mit den richtigen dunklen Farben neu zeichnen, wenn der Host feststellt, dass die Bedingungen dies erfordern, wie in den Qualitätsrichtlinien für Android-Apps für Autos beschrieben.

Mit der Methode CarContext.isDarkMode können Sie festlegen, ob eine dunkle Karte gezeichnet werden soll. Sobald sich der Status des dunklen Designs ändert, erhalten Sie einen Anruf an Session.onCarConfigurationChanged.

Nutzern die Möglichkeit geben, mit Ihrer Karte zu interagieren

Mit den folgenden Vorlagen können Sie Nutzern die Interaktion mit den von Ihnen erstellten Karten ermöglichen, z. B. durch Zoomen und Schwenken, um verschiedene Teile einer Karte zu sehen.

Vorlage Interaktivität seit API-Level der Auto-App unterstützt
NavigationTemplate 2
PlaceListNavigationTemplate (veraltet) 4
RoutePreviewNavigationTemplate (veraltet) 4
MapTemplate (veraltet) 5 (Einführung der Vorlage)
MapWithContentTemplate 7 (Einführung in die Vorlage)

Callbacks für Interaktivität implementieren

Die SurfaceCallback-Oberfläche bietet mehrere Callback-Methoden, mit denen Sie Karten, die mit den Vorlagen im vorherigen Abschnitt erstellt wurden, interaktiver gestalten können:

Interaktion SurfaceCallback-Methode Unterstützt seit API-Level der Auto-App
Tippen onClick 5
Zum Zoomen auseinander- und zusammenziehen onScale 2
Ziehen mit einer Berührung onScroll 2
Wischen mit einer Berührung onFling 2
Doppeltippen onScale (mit dem vom Vorlagenhost bestimmten Skalierungsfaktor) 2
Drehen im Schwenkmodus onScroll (mit Entfernungsfaktor, der vom Vorlagenhost bestimmt wird) 2

Kartenaktionsleiste hinzufügen

Diese Vorlagen können einen Kartenaktionsstreifen für kartenbezogene Aktionen wie Heranzoomen und Herauszoomen, Neuausrichten, Einblenden eines Kompasses und andere von Ihnen ausgewählte Aktionen enthalten. Der Kartenaktionsstreifen kann bis zu vier Schaltflächen mit nur Symbolen enthalten, die aktualisiert werden können, ohne dass sich die Aufgabentiefe ändert. Im Inaktivitätsstatus wird es ausgeblendet und im aktiven Status wieder angezeigt.

Wenn Sie Interaktivitäts-Callbacks für Karten erhalten möchten, müssen Sie dem Kartenaktionsstreifen die Schaltfläche Action.PAN hinzufügen. Wenn der Nutzer die Schwenktaste drückt, wechselt der Host in den Schwenkmodus, wie im folgenden Abschnitt beschrieben.

Wenn Ihre App die Schaltfläche Action.PAN im Aktionsstreifen der Karte weglässt, erhält sie keine Nutzereingaben über die SurfaceCallback-Methoden und der Host beendet den zuvor aktivierten Schwenkmodus.

Auf einem Touchscreen wird die Schaltfläche zum Schwenken nicht angezeigt.

Schwenkmodus

Im Schwenkmodus übersetzt der Vorlagenhost die Nutzereingaben von Eingabegeräten ohne Touchbedienung, z. B. Drehregler und Touchpads, in die entsprechenden SurfaceCallback-Methoden. Mit der Methode setPanModeListener in der NavigationTemplate.Builder auf die Nutzeraktion zum Aktivieren oder Deaktivieren des Schwenkmodus reagieren 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 über Muster interagieren, die denen einer mobilen App ähneln.

Nutzereingaben verarbeiten

Ihre App kann auf Nutzereingaben reagieren, indem die entsprechenden Listener an die Modelle übergeben werden, die sie unterstützen. Im folgenden Snippet wird gezeigt, wie Sie ein Action-Modell erstellen, das eine OnClickListener festlegt, die eine vom Code Ihrer App definierte Methode aufruft:

Kotlin

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

Java

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

Die Methode onClickNavigate kann dann die Standard-Navigations-App für Autos mit der Methode CarContext.startCarApp starten:

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 der ACTION_NAVIGATE-Intent, finden Sie im Abschnitt Auto-App mit Intent starten.

Einige Aktionen, 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 diese Aktionen mit dem Symbol 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. Im folgenden Snippet wird gezeigt, 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 Autodisplay angezeigt, wenn sie mit einem CarAppExtender erweitert werden. Einige Benachrichtigungsattribute wie Inhaltstitel, Text, Symbol und Aktionen können in der CarAppExtender festgelegt werden, um die Attribute der Benachrichtigung zu überschreiben, wenn sie auf dem Autodisplay angezeigt werden.

Im folgenden Snippet wird gezeigt, wie eine Benachrichtigung an das Autodisplay gesendet wird, die einen anderen Titel als der auf dem Mobilgerät angezeigte hat:

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 Vorschau-Benachrichtigung angezeigt.
  • Es kann ein Eintrag im Benachrichtigungscenter hinzugefügt werden, optional mit einem Symbol, das in der Leiste angezeigt wird.
  • Bei Navigations-Apps wird die Benachrichtigung möglicherweise im Navigationsstreifen-Widget angezeigt, wie unter Wegbeschreibungen beschrieben.

Sie können festlegen, wie die Benachrichtigungen Ihrer App auf diese Elemente der Benutzeroberfläche wirken sollen. Verwenden Sie dazu die Priorität der Benachrichtigung, wie in der CarAppExtender-Dokumentation 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 Entwerfen von Benachrichtigungen für Ihre Auto-App finden Sie im Leitfaden für Google Design for Driving zu Benachrichtigungen.

Toasts anzeigen

In Ihrer App kann eine Toast-Benachrichtigung mit CarToast angezeigt werden, 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. Sie können die Methode CarContext.requestPermissions() verwenden, um eine Berechtigung anzufordern.

Der Vorteil der Verwendung von CarContext.requestPermissions() im Vergleich zu den Standard-Android-APIs besteht darin, dass Sie kein eigenes 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.

Stil des Berechtigungsdialogfelds in Android Auto festlegen

Bei Android Auto wird das Berechtigungsdialogfeld für den Nutzer auf dem Smartphone angezeigt. Standardmäßig gibt es keinen Hintergrund hinter dem Dialogfeld. Wenn Sie einen benutzerdefinierten Hintergrund festlegen möchten, deklarieren Sie in Ihrer AndroidManifest.xml-Datei ein Design für die Auto-App und legen Sie das carPermissionActivityLayout-Attribut für das Design der Auto-App fest.

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

Legen Sie dann das carPermissionActivityLayout-Attribut für das Design Ihrer Auto-App fest:

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

Eine Auto-App mit einem Intent starten

Sie können die Methode CarContext.startCarApp aufrufen, um eine der folgenden Aktionen auszuführen:

  • Öffnen Sie die Telefon App, um einen Anruf zu starten.
  • Starten Sie die detaillierte Routenführung zu einem Ziel mit der Standard-Navigations-App für Autos.
  • Starten Sie Ihre eigene App mit einer Intent-Aktion.

Im folgenden Beispiel wird gezeigt, 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 Benachrichtigungs-Instanz um eine Inhaltsabsicht, die einen PendingIntent enthält, der eine explizite Absicht in die Aktion Ihrer App einbettet:

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 eine BroadcastReceiver deklarieren, die aufgerufen wird, um die Absicht zu verarbeiten, wenn der Nutzer die Aktion in der Benachrichtigungsoberfläche auswählt und CarContext.startCarApp mit einer Absicht aufruft, die 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 Session.onNewIntent-Methode in Ihrer App diesen Intent, indem der Bildschirm für die Parkplatzreservierung in den Stapel geschoben wird, falls 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 Umgang mit 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:

Dieses Limit gilt für die Anzahl der Vorlagen und nicht für die Anzahl der Screen-Instanzen im Stack. Wenn eine App beispielsweise zwei Vorlagen sendet, während sie sich auf Bildschirm A befindet, und dann Bildschirm B anzeigt, kann sie jetzt drei weitere Vorlagen senden. Wenn jeder Bildschirm so strukturiert ist, dass eine einzelne Vorlage gesendet wird, kann die App fünf Bildschirminstanzen auf den ScreenManager-Stack schieben.

Es gibt jedoch Ausnahmen von diesen Einschränkungen: Vorlagenaktualisierungen sowie Rückgängigmachen und Zurücksetzen von Vorgängen.

Vorlagenaktualisierungen

Bestimmte Inhaltsaktualisierungen werden nicht auf das Vorlagenlimit angerechnet. Wenn eine App eine neue Vorlage desselben Typs mit denselben Hauptinhalten wie die vorherige Vorlage sendet, wird die neue Vorlage in der Regel nicht auf das Kontingent angerechnet. Das Aktualisieren des Ein-/Aus-Status einer Zeile in einer ListTemplate wird beispielsweise nicht auf das Kontingent angerechnet. In der Dokumentation der einzelnen Vorlagen erfahren Sie, welche Arten von Inhaltsaktualisierungen als Aktualisierung betrachtet werden können.

Rückwärtsvorgänge

Um Unterflüsse innerhalb einer Aufgabe zu aktivieren, erkennt der Host, wenn eine App eine Screen aus dem ScreenManager-Stack herauspoppt, und aktualisiert das verbleibende Kontingent basierend auf der Anzahl der Vorlagen, um die die App zurückgeht.

Wenn die App beispielsweise zwei Vorlagen sendet, während sie sich auf Bildschirm A befindet, dann Bildschirm B anzeigt 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 um zwei Vorlagen zurückgegangen ist.

Wenn eine App zu einem Bildschirm zurückkehrt, muss sie eine Vorlage desselben Typs senden wie die, die zuletzt von diesem Bildschirm gesendet wurde. Anderen Vorlagentypen können nicht gesendet werden. Solange der Typ jedoch während eines Rückschritts gleich bleibt, kann der Inhalt der Vorlage in einer App frei geändert werden, ohne dass sich das auf das Kontingent auswirkt.

Vorgänge zurücksetzen

Bestimmte Vorlagen haben eine spezielle Semantik, die das Ende einer Aufgabe signalisiert. Die Ansicht NavigationTemplate ist beispielsweise eine Ansicht, die voraussichtlich auf dem Bildschirm verbleibt und mit neuen detaillierten Anweisungen für den Nutzer aktualisiert wird. Wenn er eine dieser Vorlagen erreicht, setzt der Host das Vorlagenkontingent zurück und behandelt die Vorlage so, als wäre sie der erste Schritt einer neuen Aufgabe. So kann die App eine neue Aufgabe starten. In der Dokumentation der einzelnen Vorlagen finden Sie Informationen dazu, welche Vorlagen einen Neustart des Hosts auslösen.

Wenn der Host eine Intent zum Starten der App über eine Benachrichtigungsaktion oder über den Launcher erhält, 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 verknüpft und im Vordergrund ist.

Weitere Informationen dazu, wie Sie die Benachrichtigungen Ihrer App auf dem Autodisplay anzeigen lassen, finden Sie im Abschnitt Benachrichtigungen anzeigen. Im Abschnitt Auto-App mit einem Intent starten finden Sie Informationen dazu, wie Sie Ihre App über eine Benachrichtigungsaktion starten.

Connection API

Sie können mithilfe der CarConnection API Verbindungsinformationen zur Laufzeit abrufen, um festzustellen, ob Ihre App unter Android Auto oder Android Automotive OS ausgeführt wird.

Initialisieren Sie beispielsweise im Session Ihrer Auto-App einen CarConnection und abonnieren Sie LiveData-Updates:

Kotlin

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

Java

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

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

Je nach Fahrzeug können dem Nutzer jeweils eine unterschiedliche Anzahl von Item-Instanzen angezeigt werden. Mit ConstraintManager können Sie das Inhaltslimit zur Laufzeit prüfen und die entsprechende Anzahl von Elementen in Ihren Vorlagen festlegen.

Rufen Sie zuerst eine ConstraintManager vom CarContext ab:

Kotlin

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

Java

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

Anschließend kannst du 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 bietet, können Sie Vorlagen wie SignInTemplate und LongMessageTemplate mit der Car App API ab Level 2 verwenden, um die Anmeldung in Ihrer App auf dem Infotainmentsystem des Autos zu verwalten.

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 Nutzernamen und Passwort.
  • PinSignInMethod für die PIN-Anmeldung, bei der der Nutzer sein Konto über sein Smartphone mit einer PIN verknüpft, die auf dem Infotainmentsystem angezeigt wird.
  • ProviderSignInMethod für die Anmeldung über einen Anbieter, z. B. Google Log-in und One Tap.
  • QRCodeSignInMethod für die QR-Code-Anmeldung, bei der der Nutzer einen QR-Code scannt, um sich auf seinem Smartphone anzumelden. Diese Funktion ist mit der Car API ab Level 4 verfügbar.

Wenn Sie beispielsweise eine Vorlage implementieren möchten, in der das Passwort des Nutzers erfasst wird, erstellen Sie zuerst eine 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 ein 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 abschließend 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 aus den folgenden Gründen AccountManager verwenden:

  • Verbesserte Nutzererfahrung und einfachere Kontoverwaltung: Nutzer können alle ihre Konten über das Kontomenü in den Systemeinstellungen ganz einfach verwalten, einschließlich Anmeldung und Abmeldung.
  • Gastzugriff: Da Autos gemeinsam genutzte Geräte sind, können OEMs im Fahrzeug einen Gastzugriff aktivieren, bei dem keine Konten hinzugefügt werden können.

Textstringvarianten hinzufügen

Auf unterschiedlich großen Bildschirmen kann unterschiedliche Textmenge angezeigt werden. Ab der Car App API-Ebene 2 können Sie mehrere Varianten eines Textstrings angeben, damit er optimal auf dem Bildschirm angezeigt wird. Sie finden Textvarianten in Vorlagen und Komponenten, die ein CarText enthalten.

Mit der Methode CarText.Builder.addVariant() können Sie einem CarText Textstringvarianten 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 diese CarText dann beispielsweise als primären Text einer GridItem verwenden.

Kotlin

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

Java

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

Fügen Sie Strings in der Reihenfolge von der am besten zur am wenigsten bevorzugten hinzu, z. B. vom längsten zum kürzesten. Der Host wählt den String mit der richtigen Länge aus, je nachdem, wie viel Platz auf dem Autodisplay verfügbar ist.

In-line-CarIcons für Zeilen hinzufügen

Mit CarIconSpan können Sie Symbole inline in den Text einfügen, um die visuelle Attraktivität Ihrer App zu erhöhen. Weitere Informationen zum Erstellen dieser Spannen finden Sie in der Dokumentation zu CarIconSpan.create. Eine Übersicht dazu, wie Textstil mit Spans funktioniert, 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 Autohardware

Ab der Car App API-Ebene 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 der Datei build.gradle für Ihr Android Auto-Modul zuerst eine Abhängigkeit von androidx.car.app:app-projected 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. Beachten Sie, dass Ihnen diese Berechtigungen vom Nutzer erteilt werden müssen. Sie können denselben Code sowohl für Android Auto als auch für Android Automotive OS verwenden, anstatt platformabhängige Abläufe erstellen zu müssen. Die erforderlichen Berechtigungen unterscheiden sich jedoch.

CarInfo

In dieser Tabelle werden die Properties beschrieben, die von den CarInfo APIs zurückgegeben werden, und die Berechtigungen, die Sie anfordern müssen, um sie zu verwenden:

Methoden Properties Berechtigungen für Android Auto Berechtigungen für Android Automotive OS Unterstützt seit API-Level der Auto-App
fetchModel Marke, Modell, Baujahr android.car.permission.CAR_INFO 3
fetchEnergyProfile Ladesteckertypen, Kraftstofftypen com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_INFO 3
fetchExteriorDimensions

Diese Daten sind nur in einigen Fahrzeugen mit Android Automotive OS und API 30 oder höher verfügbar.

Außenabmessungen android.car.permission.CAR_INFO 7
addTollListener
removeTollListener
Status und 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
Bruttogeschwindigkeit, angezeigte Geschwindigkeit (auf dem Kombiinstrument des Fahrzeugs) com.google.android.gms.permission.CAR_SPEED android.car.permission.CAR_SPEED,
android.car.permission.READ_CAR_DISPLAY_UNITS
3
addMileageListener
removeMileageListener
Kilometerstand com.google.android.gms.permission.CAR_MILEAGE Diese Daten sind unter Android Automotive OS für Apps, die über den Play Store installiert wurden, nicht verfügbar. 3

Wenn du beispielsweise den verbleibenden Bereich abrufen möchtest, musst du ein CarInfo-Objekt instanziieren und dann eine OnCarDataAvailableListener erstellen und registrieren:

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 aus dem Auto immer verfügbar sind. Wenn Sie einen Fehler erhalten, prüfen Sie den Status des angeforderten Werts, um besser nachvollziehen zu können, warum die angeforderten Daten nicht abgerufen werden konnten. Die vollständige CarInfo-Klassendefinition finden Sie in der Referenzdokumentation.

CarSensors

Die Klasse CarSensors bietet Zugriff auf den Beschleunigungsmesser, das Gyroskop, den Kompass und die Standortdaten des Fahrzeugs. Die Verfügbarkeit dieser Werte hängt vom jeweiligen OEM ab. Das Format der Daten vom Beschleunigungsmesser, Gyroskop und Kompass entspricht dem der SensorManager API. So prüfen Sie beispielsweise die Fahrtrichtung 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 aus dem Auto zugreifen möchten, müssen Sie außerdem die Berechtigung android.permission.ACCESS_FINE_LOCATION angeben und anfordern.

Testen

Informationen zum Simulieren von Sensordaten bei Tests in Android Auto finden Sie in den Abschnitten Sensoren und Sensorkonfiguration des Leitfadens für Desktop-Infotainmentsysteme. Informationen zum Simulieren von Sensordaten bei Tests unter Android Automotive OS finden Sie im Abschnitt Hardwarestatus emulieren des Leitfadens zum Android Automotive OS-Emulator.

Die Lebenszyklen von CarAppService, Sitzung und Bildschirm

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

Lebenszyklen von CarAppService und Sitzung

Abbildung 1: Der Session-Lebenszyklus

Ausführliche Informationen finden Sie in der Dokumentation zur Methode Session.getLifecycle.

Der Lebenszyklus eines Bildschirms

Abbildung 2: Der Screen-Lebenszyklus

Ausführliche Informationen finden Sie in der Dokumentation zur Methode Screen.getLifecycle.

Über das Mikrofon des Autos aufnehmen

Mit der CarAppService-API 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 Mikrofon des Autos erteilen. Ihre App kann die Eingaben der Nutzer in Ihrer App aufzeichnen und verarbeiten.

Berechtigung zur Aufzeichnung

Bevor Sie Audioinhalte aufzeichnen, müssen Sie die Berechtigung zum Aufzeichnen in Ihrer AndroidManifest.xml angeben und den Nutzer bitten, sie zu erteilen.

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

Sie müssen die Berechtigung zur Aufzeichnung zur Laufzeit anfordern. Im Abschnitt Berechtigungen anfordern finden Sie weitere Informationen dazu, wie Sie eine Berechtigung in Ihrer Auto-App anfordern.

Audio aufnehmen

Nachdem der Nutzer die Berechtigung zur Aufzeichnung erteilt hat, können Sie die Audioaufnahme starten und 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öchten, müssen Sie zuerst den Audiofokus aktivieren, damit alle laufenden Medien angehalten werden. Wenn der Audiofokus verloren geht, beenden Sie die Aufnahme.

Hier ein Beispiel dafür, wie Sie den Audiofokus erhalten:

Kotlin

 
val carAudioRecord = CarAudioRecord.create(carContext)
        
        // Take audio focus so that user's media is not recorded
        val audioAttributes = AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
            // Use the most appropriate usage type for your use case
            .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
            .build()
        
        val audioFocusRequest =
            AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
                .setAudioAttributes(audioAttributes)
                .setOnAudioFocusChangeListener { state: Int ->
                    if (state == AudioManager.AUDIOFOCUS_LOSS) {
                        // Stop recording if audio focus is lost
                        carAudioRecord.stopRecording()
                    }
                }
                .build()
        
        if (carContext.getSystemService(AudioManager::class.java)
                .requestAudioFocus(audioFocusRequest)
            != AudioManager.AUDIOFOCUS_REQUEST_GRANTED
        ) {
            // Don't record if the focus isn't granted
            return
        }
        
        carAudioRecord.startRecording()
        // Process the audio and abandon the AudioFocusRequest when done

Java

CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        // Take audio focus so that user's media is not recorded
        AudioAttributes audioAttributes =
                new AudioAttributes.Builder()
                        .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                        // Use the most appropriate usage type for your use case
                        .setUsage(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE)
                        .build();

        AudioFocusRequest audioFocusRequest =
                new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)
                        .setAudioAttributes(audioAttributes)
                        .setOnAudioFocusChangeListener(state -> {
                            if (state == AudioManager.AUDIOFOCUS_LOSS) {
                                // Stop recording if audio focus is lost
                                carAudioRecord.stopRecording();
                            }
                        })
                        .build();

        if (getCarContext().getSystemService(AudioManager.class).requestAudioFocus(audioFocusRequest)
                != AUDIOFOCUS_REQUEST_GRANTED) {
            // Don't record if the focus isn't granted
            return;
        }

        carAudioRecord.startRecording();
        // Process the audio and abandon the AudioFocusRequest when done
 

Testing Library

Die Testbibliothek von Android for Cars bietet Hilfsklassen, mit denen Sie das Verhalten Ihrer App in einer Testumgebung prüfen 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.

Anwendungsbeispiele finden Sie unter Beispiele.

Problem mit der Android for Cars-App-Bibliothek melden

Wenn Sie ein Problem mit der Bibliothek feststellen, melden Sie es über den Google Issue Tracker. Achten Sie darauf, in der Vorlage für Probleme alle angeforderten Informationen anzugeben.

Neues Problem erstellen

Bevor Sie ein neues Problem melden, prüfen Sie bitte, ob es in den Release-Notes der Bibliothek aufgeführt oder in der Liste der Probleme gemeldet wurde. Sie können Probleme abonnieren und dafür stimmen, indem Sie im Tracker auf den Stern für ein Problem klicken. Weitere Informationen finden Sie unter Probleme abonnieren.