Android for Cars App-Bibliothek verwenden

Mit der Android for Cars App-Bibliothek können Sie Apps für Navigation, POI und Internet der Dinge (IOT) in Ihr Auto einbinden. Dazu stellt es eine Reihe von Vorlagen zur Verfügung, die die Standards für die Ablenkung des Fahrers erfüllen, und berücksichtigt Details wie die Vielzahl der Faktoren des Autodisplays und der Eingabemodalitäten.

Dieser Leitfaden bietet einen Überblick über die wichtigsten Funktionen und Konzepte der Bibliothek und führt Sie durch die Einrichtung einer einfachen App. Eine vollständige schrittweise Einführung finden Sie im Codelab zu den Grundlagen der Auto-App-Bibliothek.

Vorbereitung

  1. Lesen Sie die Seiten zum Design für das Fahren in der Auto-App-Bibliothek.
  2. Sehen Sie sich die wichtigen Begriffe und Konzepte im folgenden Abschnitt an.
  3. Mach dich mit der Android Auto System-UI und dem Android Automotive OS-Design vertraut.
  4. Lesen Sie die Versionshinweise.
  5. Sehen Sie sich die Beispiele an.

Schlüsselbegriffe und -konzepte

Modelle und Vorlagen
Die Benutzeroberfläche wird durch eine Grafik 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 Grundlage für diese Diagramme dienen können. Modelle enthalten die Informationen, die dem Nutzer in Form von Text und Bildern angezeigt werden sollen, sowie Attribute, mit denen Aspekte der visuellen Darstellung solcher Informationen konfiguriert werden, z. B. Textfarben oder Bildgrößen. Der Host wandelt die Modelle in Ansichten um, die so konzipiert sind, dass sie die Standards für die Ablenkung des Fahrers erfüllen, und berücksichtigt dabei Details wie die Vielfalt der Faktoren des Autodisplays und der Eingabemodalitäten.
Host
Der Host ist die Back-End-Komponente, die die von den APIs der Bibliothek angebotenen Funktionen 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 über die Konvertierung der Modelle in Ansichten bis hin zur Benachrichtigung der Anwendung über Nutzerinteraktionen. Auf Mobilgeräten wird dieser Host von Android Auto implementiert. Unter Android Automotive OS ist dieser Host als System-App installiert.
Vorlageneinschränkungen
Verschiedene Vorlagen erzwingen Einschränkungen für den Inhalt ihrer Modelle. Beispielsweise gelten bei Listenvorlagen Limits für die Anzahl der Elemente, die dem Nutzer angezeigt werden können. Es gibt auch Einschränkungen bei der Verlinkung von Vorlagen, um den Ablauf einer Aufgabe zu bilden. Die App kann dem Bildschirm-Stack beispielsweise nur bis zu fünf Vorlagen hinzufügen. Weitere Informationen finden Sie unter Vorlageneinschränkungen.
Screen
Screen ist eine Klasse, die von der Bibliothek bereitgestellt wird und mit der Apps die dem Nutzer präsentierte Benutzeroberfläche verwalten können. Ein Screen hat einen Lebenszyklus und ermöglicht der Anwendung, die Vorlage zu senden, die angezeigt werden soll, wenn der Bildschirm sichtbar ist. Screen-Instanzen können auch per Push in einen Screen-Stapel verschoben bzw. aus einem Screen-Stapel übertragen werden. Dadurch wird sichergestellt, dass sie die Einschränkungen des Vorlagenflusses einhalten.
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. Die CarAppService Ihrer Anwendung prüft, ob eine Hostverbindung mit createHostValidator vertrauenswürdig ist, und stellt anschließend Session-Instanzen für jede Verbindung mithilfe von onCreateSession bereit.
Session

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

Wenn ein Session gestartet wird, z. B. beim ersten Start der Anwendung, fordert der Host mit der Methode onCreateScreen die Anzeige des anfänglichen Screen an.

Auto-App-Bibliothek installieren

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

Manifestdateien deiner App konfigurieren

Bevor Sie eine Auto-App erstellen können, müssen Sie die Manifestdateien Ihrer App konfigurieren.

CarAppService deklarieren

Der Host stellt über Ihre CarAppService-Implementierung eine Verbindung zu Ihrer Anwendung her. Sie deklarieren diesen Dienst in Ihrem Manifest, damit der Host Ihre App erkennen und eine Verbindung dazu herstellen kann.

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

Das folgende Code-Snippet zeigt, wie Sie in Ihrem Manifest einen Auto-App-Dienst für eine POI-App 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. Fügen Sie dazu beim Deklarieren von CarAppService wie im vorherigen Abschnitt beschrieben einen oder mehrere der folgenden Kategoriewerte in den Intent-Filter ein:

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

Detaillierte Beschreibungen der einzelnen Kategorien und Kriterien dafür, zu welchen Apps sie gehören, finden Sie unter Qualität von Android-Apps für Autos.

Name und Symbol der App angeben

Sie müssen einen Anwendungsnamen und ein Symbol angeben, mit denen der Host Ihre Anwendung in der System-UI darstellen kann.

Sie können den Namen und das Symbol der Anwendung, die zur Darstellung Ihrer App verwendet werden, mit den Attributen label und icon Ihrer 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 die 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 />

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

In der Auto-App-Bibliothek werden eigene API-Ebenen definiert, sodass du weißt, welche Bibliotheksfunktionen vom Vorlagenhost eines Fahrzeugs unterstützt werden. Mit der Methode getCarAppApiLevel() können Sie das höchste API-Level abrufen, das von einem Host unterstützt wird.

Geben Sie in der Datei AndroidManifest.xml das Mindest-API-Level für die Auto-App an, das von Ihrer App unterstützt wird:

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

In der Dokumentation zur Annotation RequiresCarApi finden Sie Details dazu, wie Sie die Abwärtskompatibilität gewährleisten und das für die Verwendung einer Funktion erforderliche Mindest-API-Level angeben können. Eine Definition, welche API-Ebene zur Verwendung einer bestimmten Funktion der Auto-App-Bibliothek erforderlich ist, findest du in der Referenzdokumentation zu CarAppApiLevels.

CarAppService und Session erstellen

Ihre Anwendung 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 Instanz Session ist dafür verantwortlich, dass die Screen-Instanz zurückgegeben wird, um sie beim ersten Start der Anwendung zu verwenden:

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 starten muss, der nicht der Start- oder Zielbildschirm Ihrer App ist, z. B. für die Verwendung von Deeplinks, können Sie mit ScreenManager.push einen Back-Stack von Bildschirmen vorab einrichten, bevor Sie von onCreateScreen zurückkehren. So können Nutzer vom ersten Bildschirm, der in Ihrer App angezeigt wird, zurück zu den vorherigen Bildschirmen wechseln.

Startbildschirm erstellen

Zum Erstellen der von Ihrer App angezeigten Bildschirme definieren Sie Klassen, die die Screen-Klasse erweitern, und implementieren ihre onGetTemplate-Methode, 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();
    }
}

Die CarContext-Klasse

Die Klasse CarContext ist eine abgeleitete ContextWrapper-Klasse, auf die Ihre Instanzen Session und Screen zugreifen können. Sie bietet Zugriff auf Autodienste wie ScreenManager zum Verwalten des Bildschirmstapels, AppManager für allgemeine app-bezogene Funktionen wie den Zugriff auf das Surface-Objekt zum Zeichnen der Karte deiner Navigations-App und die NavigationManager, die von Schritt-für-Schritt-Navigations-Apps zur Kommunikation mit Host- und anderen Navigationsereignissenmit den Host- und anderen Metadatenverwendet werden.

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

CarContext bietet auch noch weitere Funktionen. Beispielsweise kannst du Drawable-Ressourcen mithilfe der Konfiguration über den Autobildschirm laden, eine App im Auto mithilfe von Intents starten und angeben, ob die Karte in deiner Navigations-App im dunklen Modus angezeigt werden soll.

Bildschirmnavigation implementieren

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

Die ScreenManager-Klasse stellt einen Bildschirmstapel bereit, mit dem Sie Bildschirme verschieben können. Diese werden automatisch eingeblendet, wenn der Nutzer eine Schaltfläche „Zurück“ auf dem Autodisplay 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“ sowie eine Aktion hinzufügen, die bei Auswahl des Nutzers einen neuen Bildschirm auslöst:

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 aus CarContext verfügbar ist.

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

Inhalte einer Vorlage aktualisieren

Deine App kann durch Aufrufen der Methode Screen.invalidate anfordern, dass der Inhalt einer Screen ungültig wird. Der Host ruft anschließend die Methode Screen.onGetTemplate Ihrer App auf, um die Vorlage mit dem neuen Inhalt 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 einer Screen und dem Vorlagentyp erfolgt, der über die onGetTemplate-Implementierung zurückgegeben wird.

Mit dem Nutzer interagieren

Ihre App kann über Muster, die denen einer mobilen App ähneln, mit dem Nutzer interagieren.

Nutzereingaben verarbeiten

Ihre Anwendung kann auf Nutzereingaben reagieren, indem die entsprechenden Listener an die Modelle übergeben werden, 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-Navigations-App für Autos 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 seinem Mobilgerät fortzusetzen, sind nur zulässig, wenn das Auto geparkt ist. Diese Aktionen lassen sich mit 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 einen Einstellungsbildschirm auf dem Mobilgerät ö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 CarAppExtender erweitert werden. Einige Benachrichtigungsattribute wie der Titel, Text, Symbol und Aktionen können im CarAppExtender festgelegt werden. Die Attribute der Benachrichtigung, die auf dem Autodisplay angezeigt werden, werden überschrieben.

Das folgende Snippet zeigt, wie du eine Benachrichtigung an das Autodisplay sendest, bei 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 die folgenden Bereiche der Benutzeroberfläche betreffen:

  • Möglicherweise wird dem Nutzer eine Vorabbenachrichtigung (HUN) angezeigt.
  • Es kann ein Eintrag im Benachrichtigungscenter hinzugefügt werden, optional mit einem in der Schienen sichtbaren Kennzeichen.
  • Für Navigations-Apps kann die Benachrichtigung im Schienen-Widget angezeigt werden, wie unter Schritt-für-Schritt-Benachrichtigungen beschrieben.

Mithilfe der Benachrichtigungspriorität können Sie festlegen, wie die Benachrichtigungen Ihrer App so konfiguriert werden sollen, dass sie sich auf diese Elemente der Benutzeroberfläche auswirken. Eine entsprechende Beschreibung finden Sie 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 deiner Auto-App findest du im Leitfaden zum Google-Design für Fahrten unter Benachrichtigungen.

Toast anzeigen

In Ihrer App kann mithilfe von 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. Zum Anfordern einer Berechtigung können Sie die Methode CarContext.requestPermissions() verwenden.

Der Vorteil von CarContext.requestPermissions() im Vergleich zur Verwendung von standardmäßigen Android-APIs besteht darin, dass Sie keinen eigenen Activity starten müssen, um das Berechtigungsdialogfeld zu erstellen. Darüber hinaus kannst du denselben Code sowohl für Android Auto als auch für Android Automotive OS 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 der Dialog ohne Hintergrund angezeigt. Wenn du einen benutzerdefinierten Hintergrund festlegen möchtest, musst du in der Datei AndroidManifest.xml ein Design einer Auto-App deklarieren und das Attribut carPermissionActivityLayout dafür festlegen.

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

Lege dann das Attribut carPermissionActivityLayout für das Design deiner Auto-App fest:

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

Auto-App mit einem Intent starten

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

  • Öffnen Sie das Telefon, um einen Anruf zu tätigen.
  • Starten Sie mit der Standardnavigation für die Auto-App die detaillierte Routenführung zu einem Ort.
  • Erstellen Sie Ihre eigene App mit einer Absicht.

Das folgende Beispiel zeigt, wie Sie eine Benachrichtigung mit einer Aktion erstellen, die Ihre App mit einem Bildschirm öffnet, auf dem die Details einer Parkreservierung angezeigt werden. Sie erweitern die Benachrichtigungsinstanz mit einem Inhalts-Intent, der einen PendingIntent enthält, der einen expliziten Intent in 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());

Außerdem muss Ihre App einen BroadcastReceiver deklarieren, der zur Verarbeitung des Intents aufgerufen wird, wenn der Nutzer die Aktion in der Benachrichtigungsoberfläche auswählt und CarContext.startCarApp mit einem Intent einschließlich des Daten-URI aufruft:

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

Der Intent wird schließlich von der Methode Session.onNewIntent in Ihrer App verarbeitet, indem der Bildschirm zur Parkplatzreservierung auf den 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 für die Auto-App findest du 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 Anwendung beispielsweise in Bildschirm A zwei Vorlagen sendet und dann Bildschirm B überträgt, kann sie jetzt drei weitere Vorlagen senden. Ist jeder Bildschirm so strukturiert, dass eine einzelne Vorlage gesendet wird, kann die Anwendung fünf Bildschirminstanzen in den ScreenManager-Stapel verschieben.

Bei diesen Einschränkungen gibt es Sonderfälle: Vorlagenaktualisierungen sowie Zurück- und Zurücksetzensvorgänge.

Vorlagen werden aktualisiert

Bestimmte Inhaltsaktualisierungen werden nicht auf das Vorlagenlimit angerechnet. Allgemein gilt: Wenn eine Anwendung eine neue Vorlage überträgt, die vom gleichen Typ ist und denselben Hauptinhalt wie die vorherige Vorlage enthält, wird die neue Vorlage im Allgemeinen nicht auf das Kontingent angerechnet. Das Aktualisieren des Ein/Aus-Status einer Zeile in einem ListTemplate wird beispielsweise nicht auf das Kontingent angerechnet. In der Dokumentation der einzelnen Vorlagen finden Sie weitere Informationen dazu, welche Arten von Inhaltsaktualisierungen als Aktualisierung betrachtet werden können.

Vorherige Vorgänge

Zum Aktivieren von untergeordneten Abläufen innerhalb einer Aufgabe erkennt der Host, wenn eine Anwendung ein Screen aus dem ScreenManager-Stack übergibt, und aktualisiert das verbleibende Kontingent anhand der Anzahl der Vorlagen, um die die Anwendung rückwärts zurückgeht.

Wenn die Anwendung beispielsweise in Bildschirm A zwei Vorlagen sendet, dann Bildschirm B und dann zwei weitere Vorlagen sendet, hat die Anwendung noch ein Kontingent. Wenn die Anwendung anschließend wieder zu Bildschirm A zurückkehrt, setzt der Host das Kontingent auf drei zurück, da die Anwendung um zwei Vorlagen zurückgegangen ist.

Wenn Sie zu einem Bildschirm zurückkehren, muss eine App eine Vorlage senden, deren Typ mit der zuletzt von diesem Bildschirm gesendeten Vorlage identisch ist. Das Senden eines anderen Vorlagentyps verursacht einen Fehler. Solange der Typ jedoch während eines Back-Vorgangs gleich bleibt, kann eine Anwendung den Inhalt der Vorlage frei ändern, ohne das Kontingent zu beeinträchtigen.

Vorgänge zurücksetzen

Bestimmte Vorlagen haben eine spezielle Semantik, die das Ende einer Aufgabe angibt. Beispielsweise ist die Ansicht NavigationTemplate eine Ansicht, die weiterhin auf dem Bildschirm angezeigt und mit neuen detaillierten Anleitungen für 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 sehen Sie, welche Vorlagen ein Zurücksetzen auf dem Host auslösen.

Wenn der Host einen Intent zum Starten der App von einer Benachrichtigungsaktion oder vom Launcher erhält, wird das Kontingent ebenfalls zurückgesetzt. Mit diesem Mechanismus kann eine App über Benachrichtigungen einen neuen Aufgabenfluss starten. Er gilt auch dann, wenn eine App bereits gebunden ist und sich im Vordergrund befindet.

Im Abschnitt Benachrichtigungen anzeigen findest du weitere Informationen dazu, wie du Benachrichtigungen deiner App auf dem Autodisplay anzeigen kannst. Informationen zum Starten Ihrer App über eine Benachrichtigungsaktion finden Sie im Abschnitt Auto-App mit einem Intent starten.

Verbindungs-API

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

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

Constraints API

Je nach Fahrzeug kann dem Nutzer gleichzeitig eine unterschiedliche Anzahl von Item-Instanzen 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.

Rufe als Erstes ein ConstraintManager vom CarContext ab:

Kotlin

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

Java

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

Anschließend können Sie das abgerufene ConstraintManager-Objekt nach dem entsprechenden Inhaltslimit abfragen. Wenn Sie beispielsweise die Anzahl der Elemente abrufen möchten, die in einem Raster angezeigt werden können, rufen Sie getContentLimit mit CONTENT_LIMIT_TYPE_GRID auf:

Kotlin

val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)

Java

int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);

Anmeldevorgang hinzufügen

Wenn deine App Nutzern eine Anmeldung ermöglicht, kannst du Vorlagen wie SignInTemplate und LongMessageTemplate mit Car App API-Level 2 und höher für die Anmeldung in deiner App über das Infotainmentsystem des Autos verwenden.

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

  • InputSignInMethod für die Anmeldung mit Nutzername und Passwort
  • PinSignInMethod für die PIN-Anmeldung, bei der der Nutzer sein Konto auf seinem Smartphone mithilfe der PIN auf dem Infotainmentsystem verknüpft.
  • ProviderSignInMethod für Anbieteranmeldung, 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 dem Smartphone abzuschließen. Diese Funktion ist für Car API-Level 4 und höher verfügbar.

Wenn Sie beispielsweise eine Vorlage implementieren möchten, die das Passwort des Nutzers erfasst, müssen Sie zuerst ein 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 den 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 zum Schluss den neuen 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();

Account Manager verwenden

Für Android Automotive OS-Apps mit Authentifizierung muss aus folgenden Gründen AccountManager verwendet werden:

  • Mehr Nutzerfreundlichkeit und einfachere Kontoverwaltung: Nutzer können alle ihre Konten ganz einfach über das Kontomenü in den Systemeinstellungen verwalten, einschließlich der An- und Abmeldung.
  • Gasterlebnis: Da Autos gemeinsam genutzte Geräte sind, können OEMs ein Gasterlebnis im Fahrzeug ermöglichen, wo keine Konten hinzugefügt werden können.

Textstringvarianten hinzufügen

Je nach Autodisplay kann unterschiedlich viel Text angezeigt werden. Ab Ebene 2 der Car App API können Sie mehrere Varianten eines Textstrings angeben, die sich optimal an den Bildschirm anpassen. Wenn Sie wissen möchten, wo Textvarianten akzeptiert werden, suchen Sie nach Vorlagen und Komponenten, die ein CarText erfordern.

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 verwenden, z. B. als Primärtext einer GridItem.

Kotlin

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

Java

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

Fügen Sie die Strings in der Reihenfolge vom höchsten bis zum niedrigsten Wert hinzu, z. B. vom längsten zum kürzesten. Der Host wählt den String mit der entsprechenden Länge aus, je nachdem, wie viel Platz auf dem Autodisplay verfügbar ist.

CarIcons für Zeilen hinzufügen

Mit CarIconSpan können Sie Symbole in den Text einfügen, um Ihre App ansprechender zu gestalten. Weitere Informationen zum Erstellen dieser Spans finden Sie in der Dokumentation zu CarIconSpan.create. Unter Spantastische Textstile mit Spans finden Sie eine Übersicht zur Funktionsweise der 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 Auto-Hardware

Ab Car App API-Level 3 enthält die Car App Library APIs, über die 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 eine Abhängigkeit von androidx.car.app:app-automotive in die Datei build.gradle für dein Android Automotive OS-Modul ein.

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

Fahrzeuginfo

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

Methoden Properties Android Auto-Berechtigungen Berechtigungen für Android Automotive OS
fetchModel Marke, Modell, Baujahr android.car.permission.CAR_INFO
fetchEnergyProfile Anschlusstypen für Elektrofahrzeuge, Kraftstofftypen com.google.android.gms.permission.CAR_FUEL android.car.permission.CAR_INFO
addTollListener
removeTollListener
Status der Mautkarte, Typ der Mautkarte
addEnergyLevelListener
removeEnergyLevelListener
Akkustand, Benzinstand, niedriger Benzinstand, 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
addSpeedListener
removeSpeedListener
Unverarbeitete Geschwindigkeit, Anzeigegeschwindigkeit (wird auf dem Cluster-Display des Autos angezeigt) com.google.android.gms.permission.CAR_SPEED android.car.permission.CAR_SPEED,
android.car.permission.READ_CAR_DISPLAY_UNITS
addMileageListener
removeMileageListener
Entfernung im Kilometerzähler com.google.android.gms.permission.CAR_MILEAGE Diese Daten sind unter Android Automotive OS nicht für Apps verfügbar, die über den Play Store installiert wurden.

Um den verbleibenden Bereich abzurufen, instanziieren Sie beispielsweise ein CarInfo-Objekt, erstellen und registrieren Sie dann ein OnCarDataAvailableListener-Objekt:

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 Autos jederzeit verfügbar sind. Wenn Sie eine Fehlermeldung 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.

Kfz-Sensoren

Die Klasse CarSensors bietet Zugriff auf den Beschleunigungsmesser, das Gyroskop, den Kompass und die Standortdaten des Fahrzeugs. Die Verfügbarkeit dieser Werte kann vom OEM abhängen. Das Format für die Daten des Beschleunigungsmessers, des Gyroskops und des Kompasses entspricht dem Format der SensorManager API. So prüfen Sie beispielsweise die Richtung 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);

Für den Zugriff auf Standortdaten des Autos musst du außerdem die Berechtigung android.permission.ACCESS_FINE_LOCATION erklären und anfordern.

Testen

Informationen zum Simulieren von Sensordaten beim Testen mit Android Auto findest du in den Abschnitten Sensoren und Sensorkonfiguration im Leitfaden für die Desktop-Haupteinheit. Informationen zum Simulieren von Sensordaten beim Testen unter Android Automotive OS finden Sie im Abschnitt Hardwarestatus emulieren im Emulatorhandbuch für Android Automotive OS.

CarAppService-, Sitzungs- und Bildschirmlebenszyklen

Die Klassen Session und Screen implementieren die LifecycleOwner-Schnittstelle. Wenn der Nutzer mit der Anwendung interagiert, werden die Lebenszyklus-Callbacks der Session- und Screen-Objekte aufgerufen, wie in den folgenden Diagrammen beschrieben.

Die Lebenszyklen von CarAppService und Sessions

Abbildung 1: Der Session-Lebenszyklus.

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

Der Lebenszyklus eines Bildschirms

Abbildung 2: Der Screen-Lebenszyklus.

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

Über das Automikrofon aufnehmen

Mit CarAppService und der CarAudioRecord API Ihrer App können Sie der App Zugriff auf das Automikrofon des Nutzers gewähren. Nutzer müssen deiner App den Zugriff auf das Automikrofon erlauben. Die App kann die Eingabe der Nutzer innerhalb der App aufzeichnen und verarbeiten.

Aufzeichnungsberechtigung

Vor der Aufnahme von Audio müssen Sie zuerst die Berechtigung zum Aufnehmen in der AndroidManifest.xml deklarieren und den Nutzer um eine entsprechende Berechtigung bitten.

<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 Sie in der Auto-App eine Berechtigung anfordern, finden Sie im Abschnitt Berechtigungen anfordern.

Audio aufnehmen

Nachdem der Nutzer die Berechtigung zum Aufnehmen erteilt hat, können Sie die Audiodaten aufzeichnen und die Aufnahme verarbeiten.

Kotlin

val carAudioRecord = CarAudioRecord.create(carContext)
        carAudioRecord.startRecording()

        val data = ByteArray(CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE)
        while(carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) {
            // Use data array
            // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech
        }
        carAudioRecord.stopRecording()
 

Java

CarAudioRecord carAudioRecord = CarAudioRecord.create(getCarContext());
        carAudioRecord.startRecording();

        byte[] data = new byte[CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE];
        while (carAudioRecord.read(data, 0, CarAudioRecord.AUDIO_CONTENT_BUFFER_SIZE) >= 0) {
            // Use data array
            // Potentially call carAudioRecord.stopRecording() if your processing finds end of speech
        }
        carAudioRecord.stopRecording();
 

Audiofokus

Erfassen Sie bei der Aufnahme über das Automikrofon zuerst den Audiofokus, damit alle laufenden Medien gestoppt werden. Wenn der Audiofokus verloren geht, beende die Aufnahme.

Hier ist ein Beispiel, wie du den Audiofokus erhalten kannst:

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 Testbibliothek von Android for Cars enthält Hilfsklassen, mit denen du das Verhalten deiner App in einer Testumgebung validieren kannst. Mit dem 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

Wenn du ein Problem mit der Mediathek feststellst, melde es bitte über den Google Issue Tracker. Geben Sie in der Problemvorlage alle erforderlichen Informationen an.

Neues Problem erstellen

Bevor Sie ein neues Problem melden, prüfen Sie, ob es in den Versionshinweisen der Bibliothek aufgeführt oder in der Liste der Probleme gemeldet wurde. Sie können Themen abonnieren und für sie abstimmen, indem Sie im Tracker auf den Stern für ein Problem klicken. Weitere Informationen finden Sie unter Ausgaben abonnieren.