Android for Cars App-Bibliothek verwenden

Über die Android for Cars-App-Bibliothek können Sie Ihre Navigations-, POI- und IoT-Apps in Ihr Auto einbinden. Dazu werden eine Reihe von Vorlagen bereitgestellt, die die Ablenkungsstandards für Autofahrer erfüllen, und Details wie die verschiedenen Autodisplay-Faktoren und Eingabemodalitäten werden berücksichtigt.

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

Vorbereitung

  1. Sehen Sie sich die Seiten Design für Fahrten im Auto an, die die Bibliothek für Auto-Apps abdecken:
  2. Sehen Sie sich die wichtigen Begriffe und Konzepte im folgenden Abschnitt an.
  3. Mach dich mit der System-UI von Android Auto 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 je nach Vorlage, zu der sie gehören, auf unterschiedliche Weise angeordnet werden können. Vorlagen sind eine Teilmenge der Modelle, die als Wurzel in diesen Grafiken fungieren können. Modelle umfassen die Informationen, die dem Nutzer in Form von Text und Bildern angezeigt werden sollen, sowie Attribute zum Konfigurieren von Aspekten der visuellen Darstellung solcher Informationen, z. B. Textfarben oder Bildgrößen. Der Host wandelt die Modelle in Ansichten um, die darauf ausgelegt sind, die Ablenkungsstandards für Autofahrer zu erfüllen. Dabei werden Details wie die verschiedenen Bildschirmfaktoren des Autos und Eingabemodalitäten berücksichtigt.
Host
Der Host ist die Back-End-Komponente, die die Funktionen der APIs der Bibliothek implementiert, damit deine App im Auto ausgeführt werden kann. Die Aufgaben des Hosts reichen von der Erkennung Ihrer Anwendung und der Verwaltung ihres Lebenszyklus bis hin zur Umwandlung Ihrer Modelle in Ansichten und der Benachrichtigung Ihrer Anwendung ü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
Für die verschiedenen Vorlagen gelten inhaltliche Einschränkungen. Bei Listenvorlagen ist beispielsweise die Anzahl der Elemente begrenzt, die dem Nutzer präsentiert werden können. Vorlagen haben auch Einschränkungen in Bezug auf die Art und Weise, wie sie verbunden werden können, um den Ablauf einer Aufgabe zu bilden. Die App kann beispielsweise nur bis zu 5 Vorlagen in den Bildschirm-Stack verschieben. Weitere Informationen finden Sie unter Vorlageneinschränkungen.
Screen
Screen ist eine von der Bibliothek bereitgestellte Klasse, die von Apps implementiert wird, um die dem Nutzer präsentierte Benutzeroberfläche zu verwalten. Ein Screen hat einen Lebenszyklus und stellt den Mechanismus für die Anwendung bereit, die Vorlage zu senden, wenn der Bildschirm sichtbar ist. Screen-Instanzen können auch per Push-Funktion in einen oder aus einem Screen-Stack übertragen werden. Dadurch wird sichergestellt, dass sie den Ablaufbeschränkungen der Vorlage entsprechen.
CarAppService
CarAppService ist eine abstrakte Service-Klasse, die von Ihrer Anwendung implementiert und exportiert werden muss, damit sie vom Host erkannt und verwaltet werden kann. Mit der CarAppService Ihrer Anwendung wird überprüft, ob eine Hostverbindung mithilfe von createHostValidator als vertrauenswürdig eingestuft werden kann. Anschließend werden Session-Instanzen für jede Verbindung mithilfe von onCreateSession bereitgestellt.
Session

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

Wenn eine Session gestartet wird, z. B. beim ersten Start der Anwendung, fordert der Host mit der Methode onCreateScreen an, die anfängliche Screen anzuzeigen.

Car 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 du die Auto-App erstellen kannst, musst du die Manifestdateien der App so konfigurieren.

CarAppService deklarieren

Der Host stellt über die CarAppService-Implementierung eine Verbindung zu Ihrer Anwendung her. Du kannst diesen Dienst in deinem Manifest deklarieren, damit der Host deine App finden und sich mit ihr verbinden kann.

Außerdem musst du die Kategorie deiner App im Element <category> des Intent-Filters deiner App deklarieren. Die für dieses Element zulässigen Werte finden Sie in der Liste der unterstützten App-Kategorien.

Das folgende Code-Snippet zeigt, wie du in deinem Manifest einen Auto-App-Dienst für eine POI-App deklarieren kannst:

<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

Gib die Kategorie deiner App an, indem du einen oder mehrere der folgenden Kategoriewerte im Intent-Filter hinzufügst, wenn du dein CarAppService wie im vorherigen Abschnitt beschrieben deklarierst:

  • androidx.car.app.category.NAVIGATION: eine App, die eine detaillierte Routenführung bereitstellt. Weitere Informationen zu dieser Kategorie finden Sie unter Navigations-Apps für Autos entwickeln.
  • androidx.car.app.category.POI: eine App, die Funktionen zum Auffinden von POIs wie Parkplätzen, Ladestationen und Tankstellen bietet Weitere Informationen zu dieser Kategorie finden Sie unter POI-Apps für Autos erstellen.
  • androidx.car.app.category.IOT: Eine App, mit der Nutzer im Auto relevante Aktionen auf verbundenen Geräten ausführen können. Weitere Informationen zu dieser Kategorie finden Sie unter Apps für das Internet der Dinge für Autos entwickeln.

Unter Qualität von Android-Apps für Autos findest du genaue Beschreibungen der einzelnen Kategorien und Kriterien für die entsprechenden Apps.

Name und Symbol der App angeben

Sie müssen einen Anwendungsnamen und ein Symbol angeben, die der Host zur Darstellung Ihrer Anwendung in der System-UI verwenden kann.

Sie können den Namen und das Symbol der Anwendung, die zur Darstellung Ihrer Anwendung verwendet werden, mithilfe der Attribute label und icon von 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 der Manifestdatei ein <meta-data>-Element hinzu:

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

Deklariere anschließend deine Stilressource, um die folgenden Attribute für dein 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>

Car App API-Level

In der Car App Library sind eigene API-Ebenen definiert, damit du weißt, welche Bibliotheksfunktionen vom Vorlagenhost für ein Fahrzeug unterstützt werden. Verwenden Sie die Methode getCarAppApiLevel(), um das höchste von einem Host unterstützte Car App-API-Level abzurufen.

Deklariere in der Datei AndroidManifest.xml das von deiner App unterstützte mindestens erforderliche Car App-API-Level:

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

In der Dokumentation zur Annotation RequiresCarApi finden Sie weitere Informationen dazu, wie Sie die Abwärtskompatibilität aufrechterhalten und das für die Verwendung einer Funktion erforderliche Mindest-API-Level angeben können. Welche API-Ebene erforderlich ist, um eine bestimmte Funktion der Auto-App-Bibliothek zu verwenden, ist in der Referenzdokumentation zu CarAppApiLevels angegeben.

CarAppService und Sitzung erstellen

Ihre Anwendung muss die CarAppService-Klasse erweitern und ihre onCreateSession-Methode 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 Instanz Session ist dafür verantwortlich, die Instanz Screen für den ersten Start der Anwendung zurückzugeben:

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 deine Auto-App z. B. bei der Verarbeitung von Deeplinks auf einem Bildschirm starten muss, der nicht der Start- oder Landingpage-Bildschirm der App ist, kannst du mit ScreenManager.push vorab einen Back-Stack von Bildschirmen erstellen, bevor du von onCreateScreen zurückkehrst. Mit Pre-Seeding können Nutzer vom ersten Bildschirm, den Ihre App angezeigt wird, zu vorherigen Bildschirmen zurückkehren.

Startbildschirm erstellen

Zum Erstellen der von Ihrer App angezeigten Bildschirme definieren Sie Klassen, die die Klasse Screen erweitern, und implementieren ihre Methode onGetTemplate, die die Template-Instanz zurückgibt, die den Status der UI darstellt, die auf dem Autodisplay angezeigt werden soll.

Das folgende Snippet zeigt, wie ein Screen deklariert wird, das eine PaneTemplate-Vorlage verwendet, um einen einfachen „Hello world!“-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();
    }
}

CarContext-Klasse

Die Klasse CarContext ist eine abgeleitete Klasse ContextWrapper, auf die für die Instanzen Session und Screen zugegriffen werden kann. 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 auf die NavigationManager, die von Apps für die detaillierte Routenführung verwendet werden, um Navigationsmetadaten und andere Navigationsereignisse des Hosts zu kommunizieren.

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

CarContext bietet auch weitere Funktionen, z. B. zum Laden von Drawable-Ressourcen über die Konfiguration über das Autodisplay, zum Starten einer App im Auto mithilfe von Intents und zum Signalen, ob die Karte in deiner App im dunklen Design angezeigt werden soll.

Bildschirmnavigation implementieren

Anwendungen zeigen oft eine Reihe verschiedener Bildschirme an, die jeweils unterschiedliche Vorlagen verwenden, durch die der Nutzer navigieren kann, während er mit der auf dem Bildschirm angezeigten Oberfläche interagiert.

Die Klasse ScreenManager stellt einen Screenstack bereit, mit dem Sie Bildschirme verschieben können, die automatisch eingeblendet werden können, wenn der Nutzer auf dem Autodisplay 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 Aktion „Zurück“ hinzufügen und eine Aktion, die einen neuen Bildschirm öffnet, wenn der Nutzer sie ausgewählt hat:

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 automatisch ScreenManager.pop aufruft. Dieses Verhalten kann mit der OnBackPressedDispatcher-Instanz überschrieben werden, die in CarContext verfügbar ist.

Damit die App während der Fahrt sicher verwendet werden kann, kann der Screen Stack eine maximale Tiefe von fünf Bildschirmen haben. Weitere Informationen finden Sie im Abschnitt Vorlageneinschränkungen.

Inhalt einer Vorlage aktualisieren

Deine App kann durch Aufrufen der Methode Screen.invalidate anfordern, dass der Inhalt einer Screen ungültig wird. Anschließend ruft der Host die Methode Screen.onGetTemplate Ihrer App auf, um die Vorlage mit den neuen Inhalten abzurufen.

Beim Aktualisieren einer Screen ist es wichtig, den spezifischen Inhalt in der Vorlage zu kennen, der aktualisiert werden kann, damit der Host die neue Vorlage nicht auf das Vorlagenkontingent angerechnet. Weitere Informationen finden Sie im Abschnitt Vorlageneinschränkungen.

Wir empfehlen, Ihre Bildschirme so zu strukturieren, dass eine 1:1-Zuordnung zwischen einem Screen und dem Vorlagentyp besteht, der durch seine onGetTemplate-Implementierung zurückgegeben wird.

Karten zeichnen

In Navigations- und POI-Apps, die die folgenden Vorlagen verwenden, können Karten durch Zugriff auf ein Surface gezeichnet werden:

Vorlage Vorlagenberechtigung Hilfe zu Kategorien
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES Navigation
MapWithContentTemplate androidx.car.app.NAVIGATION_TEMPLATES ODER
androidx.car.app.MAP_TEMPLATES
Navigation, POI
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

Neben 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 deklarieren, um Zugriff auf die Oberfläche zu erhalten:

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

Zugriff auf die Oberfläche

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

Kotlin

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

Java

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

Den sichtbaren Bereich der Oberfläche verstehen

Der Host kann Benutzeroberflächenelemente für die Vorlagen auf der Karte zeichnen. Durch Aufrufen der Methode SurfaceCallback.onVisibleAreaChanged sendet der Host den Bereich der Oberfläche, der garantiert nicht verdeckt und für den Nutzer vollständig sichtbar ist. Außerdem ruft der Host die Methode SurfaceCallback.onStableAreaChanged mit dem kleinsten Rechteck auf, das basierend auf der aktuellen Vorlage immer sichtbar ist, um die Anzahl der Änderungen zu minimieren.

Wenn eine Navigations-App beispielsweise die NavigationTemplate mit einer Aktionsleiste oben verwendet, kann sich die Aktionsleiste ausblenden, wenn der Nutzer eine Zeit lang nicht mit dem Bildschirm interagiert hat, um mehr Platz für die Karte zu schaffen. In diesem Fall gibt es einen Callback von 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 auch hier nur onVisibleAreaChanged mit dem ersten Rechteck aufgerufen.

Dunkles Design unterstützen

Apps müssen ihre Karte mit den richtigen dunklen Farben auf die Surface-Instanz zeichnen, wenn der Host bestimmte Bedingungen bevorzugt. Eine Beschreibung hierzu finden Sie unter Qualität von Android-Apps für Autos.

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

Nutzern die Interaktion mit Ihrer Karte ermöglichen

Wenn Sie die folgenden Vorlagen verwenden, können Sie Nutzer bei der Interaktion mit den von Ihnen gezeichneten Karten unterstützen und ihnen z. B. durch Zoomen und Schwenken verschiedene Teile einer Karte anzeigen lassen.

Vorlage Interaktivität wird seit dem API-Level der Car App unterstützt
NavigationTemplate 2
PlaceListNavigationTemplate (eingestellt) 4
RoutePreviewNavigationTemplate (eingestellt) 4
MapTemplate (eingestellt) 5 (Einführung der Vorlage)
MapWithContentTemplate 7 (Einführung der Vorlage)

Interaktivitäts-Callbacks implementieren

Die SurfaceCallback-Schnittstelle bietet mehrere Callback-Methoden, die Sie implementieren können, um Karten interaktiv zu gestalten, die mit den Vorlagen im vorherigen Abschnitt erstellt wurden:

Interaktion SurfaceCallback-Methode Unterstützt seit Car App-API-Level
Tap onClick 5
Zum Zoomen auseinander- und zusammenziehen onScale 2
Ziehen mit nur einer Berührung onScroll 2
One-Touch-Schiebe onFling 2
doppeltippen onScale (mit Skalierungsfaktor, der durch den Vorlagenhost bestimmt wird) 2
Automatische Erinnerung im Schwenkmodus onScroll (mit Entfernungsfaktor, der durch den Vorlagenhost bestimmt wird) 2

Kartenaktionsleiste hinzufügen

Diese Vorlagen können eine Aktionsleiste für Karten für kartenbezogene Aktionen enthalten, z. B. zum Heran- und Herauszoomen, zum Zentrieren, zum Anzeigen eines Kompasses und zu anderen Aktionen, die Sie selbst auswählen können. Die Kartenaktionsleiste kann bis zu vier Schaltflächen enthalten, die nur Symbolen enthalten und die aktualisiert werden können, ohne die Aufgabentiefe zu beeinträchtigen. Im Ruhezustand wird sie ausgeblendet und im aktiven Zustand wieder angezeigt.

Wenn Sie Interaktions-Callbacks für Karten erhalten möchten, müssen Sie der Kartenaktionsleiste eine Action.PAN-Schaltfläche hinzufügen. Wenn der Nutzer die Schaltfläche zum Schwenken drückt, wechselt der Host in den Schwenkmodus, wie im folgenden Abschnitt beschrieben.

Wenn in Ihrer App die Schaltfläche Action.PAN im Kartenaktionsbereich fehlt, erhält sie keine Nutzereingabe ü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 Nutzereingabe von berührungslosen Eingabegeräten wie Drehsteuerungen und Touchpads in die entsprechenden SurfaceCallback-Methoden. Mit der Methode setPanModeListener in NavigationTemplate.Builder auf die Nutzeraktion zum Aufrufen oder Beenden des Schwenkmodus reagieren. Der Host kann andere UI-Komponenten in der Vorlage ausblenden, während sich der Nutzer im Schwenkmodus befindet.

Mit den Nutzenden interagieren

Ihre App kann mithilfe von Mustern, die denen in einer mobilen App ähneln, mit dem Nutzer interagieren.

Nutzereingaben verarbeiten

Ihre App kann auf Nutzereingaben reagieren, indem sie die entsprechenden Listener an die Modelle übergeben, die sie unterstützen. Das folgende Snippet zeigt, wie Sie ein Action-Modell erstellen, das ein OnClickListener festlegt, das auf eine durch den Code Ihrer App definierte Methode zurückruft:

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-Navigationsauto-App mithilfe 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 des Intents ACTION_NAVIGATE, finden Sie im Abschnitt Auto-App mit einem Intent starten.

Einige Aktionen, z. B. solche, bei denen der Nutzer aufgefordert werden muss, die Interaktion auf seinen Mobilgeräten fortzusetzen, sind nur zulässig, wenn das Auto geparkt ist. Sie können diese Aktionen mit dem ParkedOnlyOnClickListener implementieren. Wenn das Auto nicht geparkt ist, zeigt der Host den Nutzer an, dass die Aktion in diesem Fall nicht zulässig ist. Ist das Auto geparkt, wird der Code normal ausgeführt. Das folgende Snippet zeigt, wie du mit ParkedOnlyOnClickListener auf dem Mobilgerät einen Einstellungsbildschirm öffnen kannst:

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

An das Mobilgerät gesendete Benachrichtigungen werden nur dann auf dem Autodisplay angezeigt, wenn sie mit einem CarAppExtender erweitert werden. Einige Benachrichtigungsattribute wie Inhaltstitel, Text, Symbol und Aktionen können im CarAppExtender festgelegt werden. Dadurch werden die Attribute der Benachrichtigung überschrieben, wenn sie auf dem Autodisplay angezeigt werden.

Das folgende Snippet zeigt, wie eine Benachrichtigung an das Autodisplay gesendet wird, in der ein anderer Titel als der 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 kann eine Warnmeldung (HUN) angezeigt werden.
  • Sie können einen Eintrag im Benachrichtigungscenter hinzufügen, optional mit einem Badge, das in der Leiste sichtbar ist.
  • Bei Navigations-Apps kann die Benachrichtigung im Eisenbahn-Widget angezeigt werden, wie unter Detaillierte Benachrichtigungen beschrieben.

Mithilfe der Priorität der Benachrichtigung kannst du festlegen, wie die Benachrichtigungen deiner App so konfiguriert werden sollen, dass sie sich auf die einzelnen Elemente der Benutzeroberfläche auswirken. Weitere Informationen dazu findest du in der Dokumentation zu CarAppExtender.

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 der Benachrichtigungen Ihrer Auto-App finden Sie im Leitfaden „Google Design for Driving“ unter Benachrichtigungen.

Toasts anzeigen

In Ihrer App kann mit CarToast ein Toast 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. Mit der Methode CarContext.requestPermissions() können Sie eine Berechtigung anfordern.

Die Verwendung von CarContext.requestPermissions() hat im Vergleich zur Verwendung von Standard-Android-APIs den Vorteil, dass du zum Erstellen des Berechtigungsdialogfelds kein eigenes Activity starten musst. Außerdem kannst du für Android Auto und Android Automotive OS denselben Code verwenden, anstatt plattformabhängige Abläufe erstellen zu müssen.

Dialogfeld für Berechtigungen 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 du einen benutzerdefinierten Hintergrund festlegen möchtest, deklariere in der Datei AndroidManifest.xml ein Auto-App-Design und lege das Attribut carPermissionActivityLayout für das Design deiner Auto-App 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 Intent starten

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

  • Öffne die Telefon App, um einen Anruf zu tätigen.
  • Mit der Standardnavigations-App für Autos wird die detaillierte Routenführung zu einem Ort gestartet.
  • Starten Sie Ihre eigene App mit einem Intent.

Das folgende Beispiel zeigt, wie du eine Benachrichtigung mit einer Aktion erstellst, durch die deine App mit einem Bildschirm mit den Details einer Parkplatzreservierung geöffnet wird. Sie erweitern die Benachrichtigungsinstanz um einen Inhalts-Intent, der einen PendingIntent enthält, der einen expliziten 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());

In Ihrer App muss außerdem ein BroadcastReceiver deklariert werden, das zur Verarbeitung des Intents aufgerufen wird, wenn der Nutzer die Aktion in der Benachrichtigungsoberfläche auswählt. Außerdem muss CarContext.startCarApp mit einem Intent aufgerufen werden, 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)));
        }
    }
}

Zuletzt verarbeitet die Methode Session.onNewIntent in Ihrer App diesen Intent, indem der Bildschirm für die Parkplatzreservierung im Stapel verschoben 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 der Auto-App finden Sie unter Benachrichtigungen anzeigen.

Vorlageneinschränkungen

Der Host begrenzt die Anzahl der Vorlagen, die für eine bestimmte Aufgabe angezeigt werden, auf maximal fünf. Dabei muss die letzte Vorlage einen der folgenden Typen haben:

Dieses Limit gilt für die Anzahl der Vorlagen und nicht für die Anzahl der Screen-Instanzen im Stapel. Wenn eine Anwendung beispielsweise in Bildschirm A zwei Vorlagen sendet und dann Bildschirm B überträgt, können jetzt drei weitere Vorlagen gesendet werden. Wenn jeder Bildschirm dagegen so strukturiert ist, dass er eine einzige Vorlage sendet, kann die App fünf Bildschirminstanzen in den ScreenManager-Stack verschieben.

Für diese Einschränkungen gibt es Sonderfälle: Aktualisierungs- und Zurücksetzungsvorgänge für Vorlagen.

Vorlage wird aktualisiert

Bestimmte Inhaltsaktualisierungen werden nicht auf die Vorlagenbeschränkung angerechnet. Allgemein gilt: Wenn eine Anwendung eine neue Vorlage sendet, die vom gleichen Typ ist und denselben Hauptinhalt wie die vorherige Vorlage enthält, wird die neue Vorlage nicht auf das Kontingent angerechnet. Beispielsweise wird die Aktualisierung des Umschaltstatus einer Zeile in einer ListTemplate nicht auf das Kontingent angerechnet. Weitere Informationen dazu, welche Arten von Inhaltsaktualisierungen als Aktualisierungen betrachtet werden können, finden Sie in der Dokumentation der einzelnen Vorlagen.

Back-Operationen

Zum Aktivieren von Teilabläufen innerhalb einer Aufgabe erkennt der Host, wenn eine Anwendung eine Screen aus dem ScreenManager-Stapel abruft, und aktualisiert das verbleibende Kontingent basierend auf der Anzahl der Vorlagen, die die Anwendung rückwärts abspielt.

Wenn die Anwendung beispielsweise in Bildschirm A zwei Vorlagen sendet, dann Bildschirm B überträgt und zwei weitere Vorlagen sendet, verbleibt in der Anwendung ein Kontingent. Wenn die Anwendung dann wieder Bildschirm A anzeigt, setzt der Host das Kontingent auf drei zurück, da die Anwendung um zwei Vorlagen zurückgegangen ist.

Wenn eine Anwendung zu einem Bildschirm zurückkehrt, muss sie eine Vorlage vom gleichen Typ wie die zuletzt von diesem Bildschirm gesendete Vorlage senden. Das Senden eines anderen Vorlagentyps verursacht einen Fehler. Solange der Typ jedoch während eines Backvorgangs gleich bleibt, kann eine Anwendung den Inhalt der Vorlage uneingeschränkt ändern, ohne das Kontingent zu beeinträchtigen.

Vorgänge zurücksetzen

Bestimmte Vorlagen haben eine spezielle Semantik, die das Ende einer Aufgabe kennzeichnet. NavigationTemplate ist beispielsweise eine Ansicht, die voraussichtlich auf dem Bildschirm bleibt und mit neuen detaillierten Anleitungen für die Nutzung durch den Nutzer aktualisiert wird. Wenn eine dieser Vorlagen erreicht wird, setzt der Host das Vorlagenkontingent zurück und behandelt diese Vorlage so, als wäre sie der erste Schritt einer neuen Aufgabe. Dadurch kann die App eine neue Aufgabe starten. In der Dokumentation der einzelnen Vorlagen erfahren Sie, welche Vorlagen ein Zurücksetzen auf dem Host auslösen.

Wenn der Host einen Intent zum Starten der App über eine Benachrichtigungsaktion oder den Launcher erhält, wird das Kontingent ebenfalls zurückgesetzt. Mit diesem Mechanismus kann eine App einen neuen Aufgabenfluss aus Benachrichtigungen starten. Dies gilt auch dann, wenn eine App bereits gebunden und im Vordergrund ausgeführt wird.

Weitere Informationen zur Anzeige von App-Benachrichtigungen auf dem Autodisplay findest du im Abschnitt Benachrichtigungen anzeigen. Informationen zum Starten deiner App über eine Benachrichtigungsaktion findest du im Abschnitt Auto-App mit einem Intent starten.

Verbindungs-API

Mit der CarConnection API können Sie prüfen, ob Ihre App unter Android Auto oder Android Automotive OS ausgeführt wird. Damit werden während der Laufzeit Verbindungsinformationen abgerufen.

Initialisiere beispielsweise im Session deiner Auto-App eine CarConnection und abonniere 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 im 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();
}

Einschränkungs-API

Je nach Fahrzeug kann dem Nutzer möglicherweise eine unterschiedliche Anzahl von Item-Instanzen gleichzeitig angezeigt werden. Verwenden Sie ConstraintManager, um das Inhaltslimit während der Laufzeit zu prüfen und die entsprechende Anzahl von Elementen in Ihren Vorlagen festzulegen.

Fordern Sie zuerst ein ConstraintManager von CarContext an:

Kotlin

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

Java

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

Anschließend können Sie das abgerufene ConstraintManager-Objekt im Hinblick auf die entsprechende Inhaltsbeschränkung 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 deine App Nutzern die Anmeldung ermöglicht, kannst du Vorlagen wie SignInTemplate und LongMessageTemplate mit Car App API-Level 2 und höher verwenden, um die Anmeldung in deiner App über die Haupteinheit des Autos zu ermöglichen.

Definieren Sie einen SignInMethod, um eine SignInTemplate zu erstellen. Die Car App Library unterstützt derzeit die folgenden Anmeldemethoden:

  • InputSignInMethod für die Anmeldung mit Nutzername und Passwort.
  • PinSignInMethod für die Anmeldung mit PIN, 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 Anmeldung mit QR-Code, bei der der Nutzer einen QR-Code scannt, um die Anmeldung auf seinem Smartphone abzuschließen. Diese Option ist für Car-API-Level 4 und höher verfügbar.

Wenn Sie beispielsweise eine Vorlage implementieren möchten, mit der das Passwort des Nutzers erfasst wird, müssen Sie zuerst eine InputCallback erstellen, um Nutzereingaben 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 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 schließlich Ihren neuen InputSignInMethod, um einen 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();

Account Manager verwenden

Android Automotive OS-Apps mit Authentifizierung müssen aus folgenden Gründen AccountManager verwenden:

  • Bessere Nutzerfreundlichkeit und einfachere Kontoverwaltung: Nutzer können alle ihre Konten in den Systemeinstellungen über das Menü „Konten“ verwalten, einschließlich der An- und Abmeldung.
  • Gasterlebnisse: Da Autos gemeinsam verwendete Geräte sind, können OEMs die Gasterfahrung im Fahrzeug aktivieren, in dem keine Konten hinzugefügt werden können.

Textstringvarianten hinzufügen

Je nach Größe des Autodisplays können unterschiedliche Textmengen angezeigt werden. Ab Level 2 der Car App API können Sie mehrere Varianten einer Textzeichenfolge angeben, die sich optimal an den Bildschirm anpassen. Wenn Sie wissen möchten, wo Textvarianten akzeptiert werden, suchen Sie nach Vorlagen und Komponenten, die eine CarText verwenden.

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 dieses CarText dann verwenden, z. B. als primären Text eines GridItem.

Kotlin

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

Java

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

Fügen Sie die Strings in absteigender Reihenfolge 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 Autodisplay verfügbar ist.

Inline-CarIcons für Zeilen hinzufügen

Mit CarIconSpan können Sie direkt im Text Symbole hinzufügen, um die App optisch ansprechend zu gestalten. Weitere Informationen zum Erstellen dieser Spans finden Sie in der Dokumentation zu CarIconSpan.create. Einen Überblick über die Funktionsweise des Textstils mit Spans erhalten Sie unter Spantastische Textstile mit 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 Level 3 der Car App API enthält die Car App Library APIs, mit denen du auf Fahrzeugeigenschaften und Sensoren zugreifen kannst.

Voraussetzungen

Wenn du die APIs mit Android Auto verwenden möchtest, füge der Datei build.gradle für dein Android Auto-Modul zuerst eine Abhängigkeit von androidx.car.app:app-projected hinzu. Füge für Android Automotive OS der Datei build.gradle für das Android Automotive OS-Modul eine Abhängigkeit von androidx.car.app:app-automotive hinzu.

Außerdem musst du in der Datei AndroidManifest.xml die entsprechenden Berechtigungen deklarieren, die zum Anfordern der Autodaten erforderlich sind, die du verwenden möchtest. Beachten Sie, dass diese Berechtigungen auch Ihnen vom Nutzer erteilt werden müssen. Du kannst für Android Auto und Android Automotive OS denselben Code verwenden, anstatt plattformabhängige Abläufe erstellen zu müssen. Die erforderlichen Berechtigungen sind jedoch unterschiedlich.

Autoinfo

In der folgenden Tabelle werden die Attribute der CarInfo APIs und die Berechtigungen beschrieben, die Sie anfordern müssen, um sie zu verwenden:

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 Anschlusstypen 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
Staat der Mautkarte, Mautkartentyp 3
addEnergyLevelListener
removeEnergyLevelListener
Akkustand, Batteriestand, niedriger Kraftstoffstand, 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, Geschwindigkeit anzeigen (wird auf dem Display des Autos angezeigt) 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 nicht für Apps verfügbar, die aus dem Play Store installiert wurden. 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 CarInfo-Klassendefinition finden Sie in der Referenzdokumentation.

Autosensoren

Mit der Klasse CarSensors erhältst du 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 für die Daten von Beschleunigungsmesser, Gyroskop und Kompass ist dasselbe wie in der SensorManager API. So können Sie beispielsweise die Richtung des Fahrzeugs prüfen:

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);

Für den Zugriff auf Standortdaten aus dem Auto musst du außerdem die Berechtigung android.permission.ACCESS_FINE_LOCATION deklarieren und anfordern.

Testen

Informationen zum Simulieren von Sensordaten beim Testen mit Android Auto findest du in den Abschnitten Sensoren und Sensorkonfiguration im Leitfaden zu Kopfeinheiten für Computer. Informationen zum Simulieren von Sensordaten beim Testen unter Android Automotive OS finden Sie im Abschnitt Hardwarestatus emulieren der Anleitung zum Emulator für Android Automotive OS.

Die 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 der Session- und Screen-Objekte aufgerufen, wie in den folgenden Diagrammen beschrieben.

Die Lebenszyklen eines CarAppService und einer Sitzung

Abbildung 1. Der Lebenszyklus von Session.

Weitere Informationen finden Sie in der Dokumentation zur Methode Session.getLifecycle.

Der Lebenszyklus eines Bildschirms

Abbildung 2: Der Lebenszyklus von Screen.

Weitere Informationen finden Sie in der Dokumentation zur Methode Screen.getLifecycle.

Über das Mikrofon des Autos aufnehmen

Mit der CarAppService und der CarAudioRecord API deiner App kannst du der App Zugriff auf das Mikrofon des Autos gewähren. Nutzer müssen deiner App die Berechtigung erteilen, auf das Mikrofon des Autos zuzugreifen. Ihre App kann die Eingaben des Nutzers innerhalb der App aufzeichnen und verarbeiten.

Berechtigung zum Aufzeichnen

Bevor du Audioinhalte aufzeichnen kannst, musst du zuerst die Berechtigung zum Aufzeichnen in AndroidManifest.xml erklären und den Nutzer bitten, sie zu gewähren.

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

Sie müssen die Berechtigung zum Aufzeichnen während der Laufzeit anfordern. Weitere Informationen dazu, wie du eine Berechtigung in deiner Auto-App anforderst, findest du im Abschnitt Berechtigungen anfordern.

Audio aufnehmen

Nachdem der Nutzer die Berechtigung zum Aufzeichnen erteilt hat, können Sie das Audio aufzeichnen und die Aufzeichnung 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

Bei Aufnahmen über das Automikrofon müssen Sie zuerst den Audiofokus abrufen, damit alle laufenden Medien angehalten werden. Wenn Sie den Audiofokus verlieren, beenden Sie die Aufnahme.

Hier ist ein Beispiel für die Erfassung 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
 

Testbibliothek

Die Android for Cars-Testbibliothek enthält Hilfsklassen, mit denen du das Verhalten deiner App in einer Testumgebung prüfen kannst. 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 in den Beispielen.

Problem mit der Android for Cars-App-Bibliothek melden

Probleme mit der Bibliothek können Sie über den Google Issue Tracker melden. Geben Sie alle erforderlichen Informationen in der Problemvorlage an.

Neues Problem erstellen

Bevor du ein neues Problem meldest, prüfe bitte, ob es in den Versionshinweisen der Bibliothek aufgeführt oder in der Liste der Probleme aufgeführt ist. Sie können Ausgaben abonnieren und über diese abstimmen, indem Sie im Tracker auf den Stern für ein Problem klicken. Weitere Informationen finden Sie unter Probleme abonnieren.