Auf dieser Seite werden die verschiedenen Funktionen der Car App Library beschrieben, mit denen Sie die Funktionalität Ihrer detaillierten Routenführungs-App implementieren können.
Navigationsunterstützung im Manifest deklarieren
Ihre Navigations-App muss die androidx.car.app.category.NAVIGATION
App-Kategorie im Intent
Filter ihres CarAppService deklarieren:
<application>
...
<service
...
android:name=".MyNavigationCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.NAVIGATION"/>
</intent-filter>
</service>
...
</application>
Navigations-Intents unterstützen
Verschiedene Intent-Formate ermöglichen es Navigations-Apps, mit anderen Apps wie POI-Apps und Sprachassistenten zu arbeiten.
Wenn Sie diese Intent-Formate unterstützen möchten, müssen Sie zuerst die Unterstützung deklarieren, indem Sie Intent-Filter im Manifest Ihrer App hinzufügen. Der Speicherort dieser Intent-Filter hängt von der Plattform ab:
- Android Auto: Im
<activity>Manifestelement für dieActivity, die den Intent verarbeitet, wenn ein Nutzer Android Auto nicht verwendet. - Android Automotive OS: Im
<activity>Manifestelement für dieCarAppActivity.
Lesen und verarbeiten Sie dann die Intents in den onCreateScreen() und
onNewIntent() Callbacks in der Session Implementierung Ihrer App.
Erforderliche Intent-Formate
Um die NF-6 Qualitätsanforderung zu erfüllen, muss Ihre App
Navigations-Intents verarbeiten.
Optionale Intent-Formate
Sie können auch die folgenden Intent-Formate unterstützen, um die Interoperabilität Ihrer App weiter zu verbessern:
Auf die Navigationsvorlagen zugreifen
Navigations-Apps können auf die folgenden Vorlagen zugreifen, die im Hintergrund eine Oberfläche mit der Karte und während der aktiven Navigation detaillierte Routenführung anzeigen.
NavigationTemplate: Eine Vorlage, die während der aktiven Navigation eine optionale Informationsnachricht und Reisezeitprognosen anzeigt.MapWithContentTemplate: Eine Vorlage, mit der eine App Kartenkacheln mit einer Art von Inhalt rendern kann (z. B. eine Liste). Der Inhalt wird in der Regel als Overlay über den Kartenkacheln gerendert, wobei die Karte sichtbar ist und stabile Bereiche an den Inhalt angepasst werden.
Weitere Informationen zum Entwerfen der Benutzeroberfläche Ihrer Navigations-App mit diesen Vorlagen finden Sie unter Navigations-Apps.
Damit Ihre App auf die Navigationsvorlagen zugreifen kann, muss sie die Berechtigung androidx.car.app.NAVIGATION_TEMPLATES in der Datei AndroidManifest.xml deklarieren:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.NAVIGATION_TEMPLATES"/>
...
</manifest>
Zum Zeichnen von Karten ist eine zusätzliche Berechtigung erforderlich.
Zu MapWithContentTemplate migrieren
Ab Car App API Level 7 sind die
MapTemplate,
PlaceListNavigationTemplate,
und RoutePreviewNavigationTemplate
verworfen. Verworfene Vorlagen werden weiterhin unterstützt, aber die Migration zu MapWithContentTemplate wird dringend empfohlen.
Die von diesen Vorlagen bereitgestellte Funktionalität kann mit MapWithContentTemplate implementiert werden. Beispiele finden Sie in den folgenden Snippets:
MapTemplate
// MapTemplate (deprecated) val templateDeprecated = MapTemplate.Builder() .setPane(paneBuilder.build()) .setActionStrip(actionStrip) .setHeader(header) .setMapController(mapController) .build() // MapWithContentTemplate val template = MapWithContentTemplate.Builder() .setContentTemplate( PaneTemplate.Builder(paneBuilder.build()) .setHeader(header) .build() ) .setActionStrip(actionStrip) .setMapController(mapController) .build()
PlaceListNavigationTemplate
// PlaceListNavigationTemplate (deprecated) val templateDeprecated = PlaceListNavigationTemplate.Builder() .setItemList(itemListBuilder.build()) .setHeader(header) .setActionStrip(actionStrip) .setMapActionStrip(mapActionStrip) .build() // MapWithContentTemplate val template = MapWithContentTemplate.Builder() .setContentTemplate( ListTemplate.Builder() .setSingleList(itemListBuilder.build()) .setHeader(header) .build() ) .setActionStrip(actionStrip) .setMapController( MapController.Builder() .setMapActionStrip(mapActionStrip) .build() ) .build()
RoutePreviewNavigationTemplate
// RoutePreviewNavigationTemplate (deprecated) val templateDeprecated = RoutePreviewNavigationTemplate.Builder() .setItemList( ItemList.Builder() .addItem( Row.Builder() .setTitle(title) .build() ) .build() ) .setHeader(header) .setNavigateAction( Action.Builder() .setTitle(actionTitle) .setOnClickListener { /* onClick */ } .build() ) .setActionStrip(actionStrip) .setMapActionStrip(mapActionStrip) .build() // MapWithContentTemplate val template = MapWithContentTemplate.Builder() .setContentTemplate( ListTemplate.Builder() .setSingleList( ItemList.Builder() .addItem( Row.Builder() .setTitle(title) .addAction( Action.Builder() .setTitle(actionTitle) .setOnClickListener { /* onClick */ } .build() ) .build() ) .build() ) .setHeader(header) .build() ) .setActionStrip(actionStrip) .setMapController( MapController.Builder() .setMapActionStrip(mapActionStrip) .build() ) .build()
Navigationsmetadaten kommunizieren
Navigations-Apps müssen zusätzliche Navigationsmetadaten mit dem Host kommunizieren. Der Host verwendet die Informationen, um Informationen für das Infotainmentsystem des Fahrzeugs bereitzustellen und zu verhindern, dass Navigations-Apps um gemeinsam genutzte Ressourcen konkurrieren.
Navigationsmetadaten werden über den
NavigationManager
Car-Dienst bereitgestellt, auf den über den
CarContextzugegriffen werden kann:
val navigationManager = carContext.getCarService(NavigationManager::class.java)
Navigation starten, beenden und stoppen
Damit der Host mehrere Navigations-Apps, Routingbenachrichtigungen und Fahrzeugclusterdaten verwalten kann, muss er den aktuellen Status der Navigation kennen. Wenn ein Nutzer die Navigation startet, rufen Sie
NavigationManager.navigationStarted auf.
Wenn die Navigation beendet wird, z. B. wenn der Nutzer sein
Ziel erreicht oder die Navigation abbricht, rufen Sie
NavigationManager.navigationEnded auf.
Rufen Sie NavigationManager.navigationEnded nur auf, wenn der Nutzer die Navigation beendet. Wenn Sie beispielsweise die Route während einer Fahrt neu berechnen müssen, verwenden Sie stattdessen
Trip.Builder.setLoading(true).
Gelegentlich muss der Host eine App anweisen, die Navigation zu beenden, und ruft
onStopNavigation in einem
NavigationManagerCallback
Objekt auf, das von Ihrer App über
NavigationManager.setNavigationManagerCallback bereitgestellt wird.
Die App muss dann die Ausgabe von Informationen zur nächsten Abzweigung auf dem Cluster-Display, Navigationsbenachrichtigungen und Sprachführung beenden.
Fahrtinformationen aktualisieren
Rufen Sie während der aktiven Navigation
NavigationManager.updateTrip auf.
Die in diesem Aufruf bereitgestellten Informationen können vom Cluster und den Heads-up-Displays des Fahrzeugs verwendet werden. Je nach Fahrzeug werden nicht alle Informationen für den Nutzer angezeigt.
Die Desktop Head Unit (DHU) zeigt beispielsweise
den Step an, der der
Trip hinzugefügt wurde, aber nicht die
Destination
-Informationen.
Auf dem Cluster-Display zeichnen
Um eine möglichst immersive Nutzererfahrung zu bieten, können Sie mehr als nur grundlegende Metadaten auf dem Cluster-Display des Fahrzeugs anzeigen. Ab Car App API Level 6 können Navigations-Apps ihre eigenen Inhalte direkt auf dem Cluster-Display rendern (in unterstützten Fahrzeugen). Dabei gelten die folgenden Einschränkungen:
- Die Cluster-Display-API unterstützt keine Eingabesteuerelemente.
- Qualitätsrichtlinie für Car-Apps
NF-9: Auf dem Cluster-Display sollten nur Kartenkacheln angezeigt werden. Optional kann auf diesen Kacheln eine aktive Navigationsroute angezeigt werden. - Die Cluster-Display-API unterstützt nur die Verwendung von
NavigationTemplate- Im Gegensatz zu Hauptdisplays werden auf Cluster-Displays möglicherweise nicht alle UI-Elemente von
NavigationTemplateangezeigt, z. B. detaillierte Wegbeschreibungen, Karten mit geschätzter Ankunftszeit und Aktionen. Kartenkacheln sind das einzige UI-Element, das immer angezeigt wird.
- Im Gegensatz zu Hauptdisplays werden auf Cluster-Displays möglicherweise nicht alle UI-Elemente von
Clusterunterstützung deklarieren
Damit die Host-Anwendung weiß, dass Ihre App das Rendern auf Cluster
Displays unterstützt, müssen Sie dem <intent-filter> Ihres CarAppService ein androidx.car.app.category.FEATURE_CLUSTER
<category> Element hinzufügen, wie im
folgenden Snippet gezeigt:
<application>
...
<service
...
android:name=".MyNavigationCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.NAVIGATION"/>
<category android:name="androidx.car.app.category.FEATURE_CLUSTER"/>
</intent-filter>
</service>
...
</application>
Lebenszyklus- und Statusverwaltung
Ab API Level 6 bleibt der Lebenszyklusablauf der Car-App
gleich
, aber jetzt verwendet CarAppService::onCreateSession einen Parameter vom
Typ SessionInfo, der zusätzliche Informationen zur erstellten Session enthält (nämlich den Display
typ und die Menge der unterstützten Vorlagen).
Apps können entweder dieselbe Session Klasse verwenden, um sowohl das
Cluster- als auch das Hauptdisplay zu verarbeiten, oder displayspezifische Sessions erstellen, um das
Verhalten auf jedem Display anzupassen (wie im folgenden Snippet gezeigt).
override fun onCreateSession(sessionInfo: SessionInfo): Session { return if (sessionInfo.displayType == SessionInfo.DISPLAY_TYPE_CLUSTER) { ClusterSession() } else { MainDisplaySession() } }
Es gibt keine Garantie dafür, wann oder ob das Cluster-Display bereitgestellt wird. Es ist auch möglich, dass die Cluster-Session die einzige Session ist (z. B. wenn der Nutzer das Hauptdisplay zu einer anderen App gewechselt hat, während Ihre App aktiv navigiert). Standardmäßig erhält die App erst dann die Kontrolle über das Cluster-Display, wenn NavigationManager::navigationStarted aufgerufen wurde. Es ist jedoch möglich, dass die App das Cluster-Display erhält, obwohl keine aktive Navigation stattfindet, oder dass sie das Cluster-Display nie erhält. Es liegt an Ihrer App, diese Szenarien zu verarbeiten, indem sie den inaktiven Zustand der Kartenkacheln Ihrer App rendert.
Der Host erstellt separate Binder- und CarContext-Instanzen pro Session. Wenn Sie Methoden wie ScreenManager::push oder Screen::invalidate verwenden, ist nur die Session betroffen, aus der sie aufgerufen werden. Apps sollten eigene Kommunikationskanäle zwischen diesen
Instanzen erstellen, wenn eine Session Kommunikation erforderlich ist (z. B. durch
Broadcasts, ein gemeinsam genutztes Singleton oder etwas
anderes).
Clusterunterstützung testen
Sie können Ihre Implementierung sowohl unter Android Auto als auch unter Android Automotive OS testen. Unter Android Auto konfigurieren Sie dazu die Desktop Head Unit so, dass sie ein sekundäres Cluster-Display emuliert. Unter Android Automotive OS emulieren die generischen System-Images für API Level 30 und höher ein Cluster-Display.
Reisezeitprognose mit Text oder einem Symbol anpassen
Wenn Sie die Reisezeitprognose mit Text, einem Symbol oder beidem anpassen möchten, verwenden Sie die
TravelEstimate.Builder
Klasse
setTripIcon
oder
setTripText
Methoden. The
NavigationTemplate
verwendet
TravelEstimate, um optional Text und Symbole neben oder anstelle der geschätzten Zeit
der Ankunft, der verbleibenden Zeit und der verbleibenden Entfernung festzulegen.
Im folgenden Snippet werden setTripIcon und setTripText verwendet, um die Reisezeitprognose anzupassen:
TravelEstimate.Builder( Distance.create(350.0, Distance.UNIT_METERS), arrivalTimeAtDestination ) .setTripIcon( CarIcon.Builder( IconCompat.createWithResource(carContext, R.drawable.ic_garage) ).build() ) .setTripText(CarText.create("Custom Text")) .build()
Detaillierte Routenführung bereitstellen
Stellen Sie detaillierte Routenführung mit einer häufig aktualisierten Navigationsbenachrichtigung bereit. Damit Ihre Benachrichtigung auf dem Autobildschirm als Navigationsbenachrichtigung behandelt wird, muss der Builder Ihrer Benachrichtigung Folgendes tun:
- Markieren Sie die Benachrichtigung mit der
NotificationCompat.Builder.setOngoingMethode als laufend. - Legen Sie die Kategorie der Benachrichtigung auf
Notification.CATEGORY_NAVIGATIONfest. - Erweitern Sie die Benachrichtigung mit einem
CarAppExtender.
Eine Navigationsbenachrichtigung wird im Widget in der Leiste unten auf dem Autobildschirm angezeigt. Wenn die Wichtigkeit der Benachrichtigung auf IMPORTANCE_HIGH festgelegt ist, wird sie auch als wichtige Benachrichtigung (HUN) angezeigt.
Wenn die Wichtigkeit nicht mit der
CarAppExtender.Builder.setImportance
Methode festgelegt wird, wird die
Wichtigkeit des Benachrichtigungskanals
verwendet.
Die App kann in das
CarAppExtender ein PendingIntent festlegen, das
an die App gesendet wird, wenn der Nutzer auf die HUN oder das Widget in der Leiste tippt.
Wenn
NotificationCompat.Builder.setOnlyAlertOnce
mit dem Wert true aufgerufen wird, wird eine Benachrichtigung mit hoher Wichtigkeit nur
einmal in der HUN angezeigt.
Das folgende Snippet zeigt, wie Sie eine Navigationsbenachrichtigung erstellen:
NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setOnlyAlertOnce(true) .setOngoing(true) .setCategory(NotificationCompat.CATEGORY_NAVIGATION) .extend( CarAppExtender.Builder() .setContentTitle(carScreenTitle) .setContentIntent( PendingIntent.getBroadcast( context, ACTION_OPEN_APP.hashCode(), Intent(ACTION_OPEN_APP).setComponent( ComponentName(context, MyNotificationReceiver::class.java) ), PendingIntent.FLAG_IMMUTABLE ) ) .setImportance(NotificationManagerCompat.IMPORTANCE_HIGH) .build() ) .build()
Aktualisieren Sie die detaillierte Wegbeschreibung regelmäßig bei Änderungen der Entfernung, wodurch das Widget in der Leiste aktualisiert wird, und zeigen Sie die Benachrichtigung nur als HUN an.
Sie können das HUN-Verhalten steuern, indem Sie die Wichtigkeit der Benachrichtigung mit CarAppExtender.Builder.setImportance festlegen. Wenn Sie die Wichtigkeit auf IMPORTANCE_HIGH festlegen, wird eine HUN angezeigt. Wenn Sie einen anderen Wert festlegen, wird nur das Widget in der Leiste aktualisiert.
Inhalte von PlaceListNavigationTemplate aktualisieren
Sie können Fahrern ermöglichen, Inhalte mit einem Fingertipp zu aktualisieren, während sie
Listen von Orten durchsuchen, die mit
PlaceListNavigationTemplate erstellt wurden.
Wenn Sie die Aktualisierung von Listen aktivieren möchten, implementieren Sie die
OnContentRefreshListener
Schnittstelle's
onContentRefreshRequested
Methode und verwenden Sie
PlaceListNavigationTemplate.Builder.setOnContentRefreshListener
um den Listener für die Vorlage festzulegen.
Das folgende Snippet zeigt, wie Sie den Listener für die Vorlage festlegen:
PlaceListNavigationTemplate.Builder() .setOnContentRefreshListener { // Execute any desired logic // Then call invalidate() so onGetTemplate() is called again screen.invalidate() } .build()
Die Schaltfläche „Aktualisieren“ wird nur im Header von PlaceListNavigationTemplate angezeigt, wenn der Listener einen Wert hat.
Wenn der Nutzer auf die Schaltfläche „Aktualisieren“ klickt, wird die Methode onContentRefreshRequested Ihrer OnContentRefreshListener-Implementierung aufgerufen. Rufen Sie in
onContentRefreshRequested die
Screen.invalidate Methode auf.
Der Host ruft dann die Methode
Screen.onGetTemplate
Ihrer App auf, um die Vorlage mit den aktualisierten Inhalten abzurufen. Weitere Informationen zum Aktualisieren von Vorlagen finden Sie unter
Inhalte einer Vorlage aktualisieren. Solange die nächste Vorlage
zurückgegeben von
onGetTemplate vom
selben Typ ist, gilt sie als Aktualisierung und wird nicht auf das
Vorlagenkontingent angerechnet.
Sprachansagen bereitstellen
Wenn Sie Navigationsanweisungen über die Autolautsprecher wiedergeben möchten, muss Ihre App den
Audiofokus anfordern. Legen Sie im Rahmen Ihrer
AudioFocusRequest die Verwendung als AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE fest. Legen Sie außerdem die Fokusverstärkung als AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK fest.
Navigation simulieren
Wenn Sie die Navigationsfunktion Ihrer App überprüfen möchten, bevor Sie sie im
Google Play Store einreichen, muss Ihre App den
NavigationManagerCallback.onAutoDriveEnabled
Callback implementieren. Wenn dieser Callback aufgerufen wird, muss Ihre App die Navigation zum ausgewählten Ziel simulieren, wenn der Nutzer die Navigation startet. Ihre App kann diesen
Modus beenden, wenn der Lebenszyklus der aktuellen Session
den
Lifecycle.Event.ON_DESTROY
Status erreicht.
Sie können testen, ob Ihre Implementierung von onAutoDriveEnabled aufgerufen wird, indem Sie den folgenden Befehl über die Befehlszeile ausführen:
adb shell dumpsys activity service CAR_APP_SERVICE_NAME AUTO_DRIVE
Dies ist im folgenden Beispiel dargestellt:
adb shell dumpsys activity service androidx.car.app.samples.navigation.car.NavigationCarAppService AUTO_DRIVE
Standardmäßige Navigations-Car-App
In Android Auto entspricht die standardmäßige Navigations-Car-App der letzten Navigations-App, die der Nutzer gestartet hat. Die Standard-App empfängt Navigations-Intents, wenn der Nutzer Navigationsbefehle über den Assistant aufruft oder wenn eine andere App einen Intent zum Starten der Navigation sendet.
Kontextbezogene Navigationsbenachrichtigungen anzeigen
Alert zeigt dem Fahrer wichtige Informationen mit optionalen Aktionen an, ohne den Kontext des Navigationsbildschirms zu verlassen. Um dem Fahrer die bestmögliche Erfahrung zu bieten,
Alert funktioniert in
NavigationTemplate
, um die Navigationsroute nicht zu blockieren und die Ablenkung des Fahrers zu minimieren.
Alert ist nur in NavigationTemplate verfügbar.
Wenn Sie den Nutzer außerhalb von NavigationTemplate benachrichtigen möchten, sollten Sie eine wichtige Benachrichtigung (HUN) verwenden, wie unter Benachrichtigungen anzeigen beschrieben.
Verwenden Sie Alert beispielsweise für Folgendes:
- Den Fahrer über ein Update informieren, das für die aktuelle Navigation relevant ist, z. B. eine Änderung der Verkehrsbedingungen.
- Den Fahrer um ein Update zur aktuellen Navigation bitten, z. B. über das Vorhandensein einer Geschwindigkeitskontrolle.
- Eine bevorstehende Aufgabe vorschlagen und fragen, ob der Fahrer sie akzeptiert, z. B. ob der Fahrer bereit ist, unterwegs jemanden abzuholen.
In der einfachsten Form besteht ein Alert aus einem Titel und der Dauer des Alert. Die Dauer wird durch eine Fortschrittsleiste dargestellt. Optional können Sie einen Untertitel, ein Symbol und bis zu zwei
Action-Objekte hinzufügen.
Sobald ein Alert angezeigt wird, wird er nicht auf eine andere Vorlage übertragen, wenn die Fahrerinteraktion dazu führt, dass NavigationTemplate verlassen wird.
Er bleibt in der ursprünglichen NavigationTemplate, bis das Zeitlimit für Alert abläuft, der Nutzer eine Aktion ausführt oder die App den Alert schließt.
Benachrichtigung erstellen
Verwenden Sie Alert.Builder
zum Erstellen einer Alert-Instanz:
Alert.Builder( 1, // alertId CarText.create("Hello"), // title 5000 // durationMillis ) // The fields below are optional .addAction(firstAction) .addAction(secondAction) .setSubtitle(CarText.create("Subtitle")) .setIcon(CarIcon.APP_ICON) .setCallback(alertCallback) .build()
Wenn Sie auf das Alert
Abbrechen oder Schließen reagieren möchten, erstellen Sie eine Implementierung der
AlertCallback Schnittstelle.
Die Aufruf-Pfade von AlertCallback sind:
Wenn das
AlertZeitlimit abläuft, ruft der Host dieAlertCallback.onCancelMethode mit demAlertCallback.REASON_TIMEOUTWert auf. Anschließend wird dieAlertCallback.onDismissMethode aufgerufen.Wenn der Fahrer auf eine der Aktionsschaltflächen klickt, ruft der Host
Action.OnClickListenerund dannAlertCallback.onDismissauf.Wenn das
Alertnicht unterstützt wird, ruft der HostAlertCallback.onCancelmit demAlertCallback.REASON_NOT_SUPPORTEDWert auf. Der Host ruftAlertCallback.onDismissnicht auf, daAlertnicht angezeigt wurde.
Dauer der Benachrichtigung konfigurieren
Wählen Sie eine Alert-Dauer aus, die
den Anforderungen Ihrer App entspricht. Die empfohlene Dauer für eine Navigations
Alert beträgt 10 Sekunden. Weitere Informationen finden Sie unter Navigationsbenachrichtigungen.
Benachrichtigung anzeigen
Wenn Sie ein Alert anzeigen möchten, rufen Sie die
AppManager.showAlert
Methode auf, die über
CarContext Ihrer App verfügbar ist.
carContext.getCarService(AppManager::class.java).showAlert(alert)
- Wenn Sie
showAlertmit einerAlertaufrufen, die einealertIdhat, die mit der ID der bereits angezeigtenAlertidentisch ist, geschieht nichts. DieAlertwird nicht aktualisiert. Wenn Sie eineAlertaktualisieren möchten, müssen Sie sie mit einer neuenalertIdneu erstellen. - Wenn Sie
showAlertmit einerAlertaufrufen, die eine anderealertIdals die bereits angezeigteAlerthat, wird die angezeigteAlertgeschlossen.
Benachrichtigung schließen
Eine Alert wird automatisch geschlossen, wenn das Zeitlimit abläuft oder der Fahrer interagiert. Sie können eine
Alert aber auch manuell schließen, z. B. wenn die Informationen veraltet sind. Rufen Sie dazu die
dismissAlert
Methode mit der
alertId
des Alert auf.Alert
carContext.getCarService(AppManager::class.java).dismissAlert(alert.id)
Wenn Sie dismissAlert mit einer alertId aufrufen, die nicht mit der bereits
angezeigten Alert übereinstimmt, geschieht nichts. Es wird keine Ausnahme ausgelöst.