La bibliothèque d'applications Android for Cars vous permet d'utiliser votre application de navigation, de point d'intérêt, d'Internet des objets (IoT) ou de météo dans votre voiture. Pour ce faire, il fournit un ensemble de modèles conçus pour répondre aux normes de distraction du conducteur et s'occupe de détails tels que la variété des facteurs d'écran de voiture et des modalités d'entrée.
Ce guide présente les principales fonctionnalités et les principaux concepts de la bibliothèque, et vous explique comment configurer une application de base.
Avant de commencer
- Consultez les pages Concevoir pour la conduite qui couvrent la bibliothèque Car App.
- Présentation des catégories Applications de navigation et Autres applications liées à la conduite
- Présentation de Créer des applications avec des modèles
- Composants de base couvrant les modèles et les composants de modèle
- Exemples de parcours illustrant des schémas UX courants
- Conditions requises pour les applications basées sur des modèles
- Passez en revue les termes et concepts clés dans la section suivante.
- Familiarisez-vous avec l'UI du système Android Auto et la conception d'Android Automotive OS.
- Consultez les notes de version.
- Consultez les exemples.
Termes et concepts clés
- Modèles et modèles
- L'interface utilisateur est représentée par un graphique d'objets de modèle qui peuvent être organisés de différentes manières, selon le modèle auquel ils appartiennent. Les modèles sont un sous-ensemble des modèles pouvant servir de racine dans ces graphiques. Les modèles incluent les informations à afficher à l'utilisateur sous forme de texte et d'images, ainsi que des attributs permettant de configurer des aspects de l'apparence visuelle de ces informations (par exemple, les couleurs du texte ou la taille des images). L'hôte convertit les modèles en vues conçues pour répondre aux normes de distraction du conducteur et gère des détails tels que la variété des facteurs d'écran de voiture et des modalités d'entrée.
- Hôte
- L'hôte est le composant de backend qui implémente les fonctionnalités proposées par les API de la bibliothèque afin que votre application puisse s'exécuter dans la voiture. Les responsabilités de l'hôte vont de la découverte de votre application et de la gestion de son cycle de vie à la conversion de vos modèles en vues et à la notification à votre application des interactions utilisateur. Sur les appareils mobiles, cet hôte est implémenté par Android Auto. Sur Android Automotive OS, cet hôte est installé en tant qu'application système.
- Restrictions concernant les modèles
- Différents modèles appliquent des restrictions au contenu de leurs modèles. Par exemple, les modèles de liste ont des limites sur le nombre d'éléments qui peuvent être présentés à l'utilisateur. Les modèles sont également soumis à des restrictions concernant la manière dont ils peuvent être connectés pour former le flux d'une tâche. Par exemple, l'application ne peut envoyer que cinq modèles à la pile d'écrans. Pour en savoir plus, consultez Restrictions concernant les modèles.
Screen
Screen
est une classe fournie par la bibliothèque que les applications implémentent pour gérer l'interface utilisateur présentée à l'utilisateur. UnScreen
possède un cycle de vie et fournit le mécanisme permettant à l'application d'envoyer le modèle à afficher lorsque l'écran est visible. Les instancesScreen
peuvent également être insérées et retirées d'une pileScreen
, ce qui garantit qu'elles respectent les restrictions de flux de modèle.CarAppService
CarAppService
est une classe abstraiteService
que votre application doit implémenter et exporter pour être découverte et gérée par l'hôte. LeCarAppService
de votre application est chargé de valider qu'une connexion hôte peut être approuvée à l'aide decreateHostValidator
, puis de fournir des instancesSession
pour chaque connexion à l'aide deonCreateSession
.Session
Session
est une classe abstraite que votre application doit implémenter et renvoyer à l'aide deCarAppService.onCreateSession
. Il sert de point d'entrée pour afficher des informations sur l'écran de la voiture. Il possède un cycle de vie qui indique l'état actuel de votre application sur l'écran de la voiture, par exemple lorsqu'elle est visible ou masquée.Lorsqu'un
Session
est démarré, par exemple lorsque l'application est lancée pour la première fois, l'hôte demande l'Screen
initial à afficher à l'aide de la méthodeonCreateScreen
.
Installer la bibliothèque d'applications automobiles
Consultez la page de publication de la bibliothèque Jetpack pour savoir comment ajouter la bibliothèque à votre application.
Configurer les fichiers manifestes de votre application
Avant de pouvoir créer votre application automobile, configurez les fichiers manifestes de votre application comme suit.
Déclarer votre CarAppService
L'hôte se connecte à votre application via votre implémentation CarAppService
. Vous déclarez ce service dans votre fichier manifeste pour permettre à l'hôte de découvrir votre application et de s'y connecter.
Vous devez également déclarer la catégorie de votre application dans l'élément <category>
du filtre d'intent de votre application. Consultez la liste des catégories d'applications compatibles pour connaître les valeurs autorisées pour cet élément.
L'extrait de code suivant montre comment déclarer un service d'application automobile pour une application de points d'intérêt dans votre fichier manifeste :
<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>
Catégories d'applications compatibles
Déclarez la catégorie de votre application en ajoutant une ou plusieurs des valeurs de catégorie suivantes dans le filtre d'intent lorsque vous déclarez votre CarAppService
, comme décrit dans la section précédente :
androidx.car.app.category.NAVIGATION
: application qui fournit des instructions de navigation détaillées. Consultez Créer des applications de navigation pour voitures.androidx.car.app.category.POI
: application qui fournit des fonctionnalités permettant de trouver des points d'intérêt tels que des places de parking, des bornes de recharge et des stations-service. Consultez Créer des applications de point d'intérêt pour voitures.androidx.car.app.category.IOT
: application qui permet aux utilisateurs d'effectuer des actions pertinentes sur des appareils connectés depuis leur voiture. Consultez Développer des applications IoT (Internet des objets) pour voitures.androidx.car.app.category.WEATHER
: application qui permet aux utilisateurs de consulter des informations météo pertinentes concernant leur position actuelle ou leur itinéraire. Consultez Créer des applications météo pour voitures.androidx.car.app.category.MEDIA
: application qui permet aux utilisateurs de parcourir et d'écouter de la musique, la radio, des livres audio et d'autres contenus audio dans la voiture. Consultez Créer des applications multimédias basées sur des modèles pour voitures.androidx.car.app.category.MESSAGING
: application permettant aux utilisateurs de communiquer à l'aide de messages texte courts. Consultez Créer des expériences de messagerie basées sur des modèles pour Android Auto.androidx.car.app.category.CALLING
: application permettant aux utilisateurs de communiquer par appel vocal. Consultez Créer des expériences d'appel pour Android Auto.
Consultez Qualité des applications Android pour les voitures pour obtenir des descriptions détaillées de chaque catégorie et des critères d'appartenance des applications à ces catégories.
Spécifier le nom et l'icône de l'application
Vous devez spécifier un nom et une icône d'application que l'hôte peut utiliser pour représenter votre application dans l'UI du système.
Vous pouvez spécifier le nom et l'icône de l'application utilisés pour représenter votre application à l'aide des attributs label
et icon
de votre CarAppService
:
...
<service
android:name=".MyCarAppService"
android:exported="true"
android:label="@string/my_app_name"
android:icon="@drawable/my_app_icon">
...
</service>
...
Si le libellé ou l'icône ne sont pas déclarés dans l'élément <service>
, l'hôte revient aux valeurs spécifiées pour l'élément <application>
.
Définir un thème personnalisé
Pour définir un thème personnalisé pour votre application automobile, ajoutez un élément <meta-data>
dans votre fichier manifeste, comme suit :
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
Ensuite, déclarez votre ressource de style pour définir les attributs suivants pour votre thème d'application automobile personnalisé :
<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>
Niveau d'API de Car App
La bibliothèque Car App définit ses propres niveaux d'API pour que vous puissiez savoir quelles fonctionnalités de la bibliothèque sont prises en charge par l'hôte de modèle sur un véhicule.
Pour récupérer le niveau d'API Car App le plus élevé compatible avec un hôte, utilisez la méthode getCarAppApiLevel()
.
Déclarez le niveau d'API Car App minimal pris en charge par votre application dans votre fichier AndroidManifest.xml
:
<manifest ...>
<application ...>
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="1"/>
</application>
</manifest>
Consultez la documentation de l'annotation RequiresCarApi
pour savoir comment assurer la rétrocompatibilité et déclarer le niveau d'API minimal requis pour utiliser une fonctionnalité. Pour savoir quel niveau d'API est requis pour utiliser une fonctionnalité spécifique de la bibliothèque d'applications pour voitures, consultez la documentation de référence pour CarAppApiLevels
.
Créer votre CarAppService et Session
Votre application doit étendre la classe CarAppService
et implémenter sa méthode onCreateSession
, qui renvoie une instance Session
correspondant à la connexion actuelle à l'hôte :
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(); } ... }
L'instance Session
est responsable du renvoi de l'instance Screen
à utiliser lors du premier démarrage de l'application :
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()); } ... }
Pour gérer les scénarios dans lesquels votre application automobile doit démarrer à partir d'un écran autre que l'écran d'accueil ou la page de destination de votre application (par exemple, la gestion des liens profonds), vous pouvez préremplir une pile "Retour" d'écrans à l'aide de ScreenManager.push
avant de revenir de onCreateScreen
.
Le pré-seeding permet aux utilisateurs de revenir aux écrans précédents à partir du premier écran affiché par votre application.
Créer votre écran de démarrage
Vous créez les écrans affichés par votre application en définissant des classes qui étendent la classe Screen
et en implémentant sa méthode onGetTemplate
, qui renvoie l'instance Template
représentant l'état de l'UI à afficher sur l'écran de la voiture.
L'extrait suivant montre comment déclarer un Screen
qui utilise un modèle PaneTemplate
pour afficher une simple chaîne "Hello world !" :
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(); } }
Classe CarContext
La classe CarContext
est une sous-classe ContextWrapper
accessible à vos instances Session
et Screen
. Il permet d'accéder aux services automobiles, tels que ScreenManager
pour gérer la pile d'écrans, AppManager
pour les fonctionnalités générales liées aux applications, comme l'accès à l'objet Surface
pour dessiner des cartes, et NavigationManager
utilisé par les applications de navigation guidée pour communiquer les métadonnées de navigation et d'autres événements liés à la navigation avec l'hôte.
Consultez Accéder aux modèles de navigation pour obtenir une liste complète des fonctionnalités de la bibliothèque disponibles pour les applications de navigation.
CarContext
offre également d'autres fonctionnalités, comme le chargement de ressources dessinables à l'aide de la configuration de l'écran de la voiture, le démarrage d'une application dans la voiture à l'aide d'intents et l'indication de l'affichage ou non de la carte de votre application dans le thème sombre.
Implémenter la navigation entre les écrans
Les applications présentent souvent plusieurs écrans différents, chacun pouvant utiliser des modèles différents. L'utilisateur peut naviguer entre ces écrans lorsqu'il interagit avec l'interface affichée à l'écran.
La classe ScreenManager
fournit une pile d'écrans que vous pouvez utiliser pour envoyer des écrans qui peuvent être fermés automatiquement lorsque l'utilisateur sélectionne un bouton "Retour" sur l'écran de la voiture ou utilise le bouton "Retour" matériel disponible dans certaines voitures.
L'extrait suivant montre comment ajouter une action de retour à un modèle de message, ainsi qu'une action qui affiche un nouvel écran lorsque l'utilisateur la sélectionne :
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();
L'objet Action.BACK
est un Action
standard qui appelle automatiquement ScreenManager.pop
.
Ce comportement peut être remplacé à l'aide de l'instance OnBackPressedDispatcher
disponible à partir de CarContext
.
Pour s'assurer que l'application peut être utilisée en toute sécurité pendant la conduite, la pile d'écrans ne peut pas dépasser cinq écrans. Pour en savoir plus, consultez la section Restrictions concernant les modèles.
Actualiser le contenu d'un modèle
Votre application peut demander l'invalidation du contenu d'un Screen
en appelant la méthode Screen.invalidate
.
L'hôte rappelle ensuite la méthode Screen.onGetTemplate
de votre application pour récupérer le modèle avec le nouveau contenu.
Lorsque vous actualisez un Screen
, il est important de comprendre le contenu spécifique du modèle qui peut être mis à jour afin que l'hôte ne comptabilise pas le nouveau modèle dans le quota de modèles.
Pour en savoir plus, consultez la section Restrictions concernant les modèles.
Nous vous recommandons de structurer vos écrans de manière à ce qu'il existe une correspondance un-à-un entre un Screen
et le type de modèle qu'il renvoie via son implémentation onGetTemplate
.
Dessiner des cartes
Les applications de navigation, de points d'intérêt (POI) et de météo qui utilisent les modèles suivants peuvent dessiner des cartes en accédant à une Surface
.
Pour utiliser les modèles suivants, votre application doit disposer de l'une des autorisations correspondantes déclarées dans un élément <uses-permission>
de son fichier AndroidManifest.xml
.
Template | Autorisation du modèle | Conseils par catégorie |
---|---|---|
NavigationTemplate |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigation |
MapWithContentTemplate |
androidx.car.app.NAVIGATION_TEMPLATES OU androidx.car.app.MAP_TEMPLATES |
Navigation, POI, Weather |
MapTemplate (obsolète) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigation |
PlaceListNavigationTemplate (obsolète) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigation |
RoutePreviewNavigationTemplate (obsolète) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navigation |
Déclarer l'autorisation de surface
En plus de l'autorisation requise pour le modèle utilisé par votre application, celle-ci doit déclarer l'autorisation androidx.car.app.ACCESS_SURFACE
dans son fichier AndroidManifest.xml
pour accéder à la surface :
<manifest ...>
...
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
...
</manifest>
Accéder à la plate-forme
Pour accéder au Surface
fourni par l'hôte, vous devez implémenter un SurfaceCallback
et fournir cette implémentation au service automobile AppManager
. Le Surface
actuel est transmis à votre SurfaceCallback
dans le paramètre SurfaceContainer
des rappels onSurfaceAvailable()
et onSurfaceDestroyed()
.
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
Comprendre la zone visible de la surface
L'hôte peut dessiner des éléments d'interface utilisateur pour les modèles situés au-dessus de la carte. L'hôte communique la zone de la surface qui sera non masquée et entièrement visible par l'utilisateur en appelant la méthode SurfaceCallback.onVisibleAreaChanged
. En outre, pour minimiser le nombre de modifications, l'hôte appelle la méthode SurfaceCallback.onStableAreaChanged
avec le plus petit rectangle, qui est toujours visible en fonction du modèle actuel.
Par exemple, lorsqu'une application de navigation utilise le NavigationTemplate
avec une bande d'actions dans la partie supérieure, celle-ci peut se masquer lorsque l'utilisateur n'a pas interagi avec l'écran depuis un certain temps afin de libérer de l'espace pour la carte. Dans ce cas, un rappel de onStableAreaChanged
et onVisibleAreaChanged
est effectué avec le même rectangle. Lorsque la bande d'actions est masquée, seul onVisibleAreaChanged
est appelé avec la plus grande zone. Si l'utilisateur interagit avec l'écran, seul onVisibleAreaChanged
est appelé avec le premier rectangle.
Prendre en charge le thème sombre
Les applications doivent redessiner leur carte sur l'instance Surface
avec les couleurs sombres appropriées lorsque l'hôte détermine que les conditions le justifient, comme décrit dans Qualité des applications Android pour les voitures.
Pour décider si vous devez dessiner une carte sombre, vous pouvez utiliser la méthode CarContext.isDarkMode
. Chaque fois que l'état du thème sombre change, vous recevez un appel de Session.onCarConfigurationChanged
.
Dessiner des cartes sur l'écran du cluster
En plus de dessiner des cartes sur l'écran principal, les applications de navigation peuvent également dessiner des cartes sur l'écran du cluster derrière le volant. Pour en savoir plus, consultez Dessiner sur l'écran du cluster.
Permettre aux utilisateurs d'interagir avec votre carte
Lorsque vous utilisez les modèles suivants, vous pouvez permettre aux utilisateurs d'interagir avec les cartes que vous dessinez, par exemple en effectuant des zooms et en passant en mode panoramique afin d'en voir différentes parties.
Template | Interactivité prise en charge depuis le niveau d'API de Car App |
---|---|
NavigationTemplate |
2 |
PlaceListNavigationTemplate (obsolète) |
4 |
RoutePreviewNavigationTemplate (obsolète) |
4 |
MapTemplate (obsolète) |
5 (introduction du modèle) |
MapWithContentTemplate |
7 (introduction du modèle) |
Implémenter des rappels d'interactivité
L'interface SurfaceCallback
comporte plusieurs méthodes de rappel que vous pouvez implémenter pour ajouter de l'interactivité aux cartes créées avec les modèles de la section précédente :
Interaction | Méthode SurfaceCallback |
Prise en charge depuis le niveau d'API de Car App |
---|---|---|
Appuyer | onClick |
5 |
Pincer pour zoomer | onScale |
2 |
Faire glisser d'un simple geste | onScroll |
2 |
Faire glisser d'un simple geste vif | onFling |
2 |
Appuyer deux fois | onScale (avec un facteur de scaling déterminé par l'hôte du modèle) |
2 |
Geste de rotation en mode panoramique | onScroll (avec facteur de distance déterminé par l'hôte du modèle) |
2 |
Ajouter une bande d'actions de la carte
Ces modèles peuvent comporter une bande d'actions pour les actions associées à la carte, telles que le zoom avant et arrière, le recentrage, l'affichage d'une boussole et toute autre action que vous choisissez d'afficher. La bande d'actions sur la carte peut comporter jusqu'à quatre boutons ne contenant qu'une icône, qui peuvent être actualisés sans affecter la profondeur de la tâche. Elle est masquée pendant l'état inactif et réapparaît à l'état actif.
Pour recevoir des rappels d'interactivité sur la carte, vous devez ajouter un bouton Action.PAN
dans la bande d'actions de la carte. Lorsque l'utilisateur appuie sur le bouton panoramique, l'hôte passe en mode panoramique, comme décrit dans la section suivante.
Si votre application omet le bouton Action.PAN
dans la bande d'actions de la carte, elle ne reçoit pas les entrées utilisateur provenant des méthodes SurfaceCallback
, et l'hôte quittera tout mode panoramique précédemment activé.
Sur un écran tactile, le bouton panoramique n'est pas affiché.
Comprendre le mode panoramique
En mode panoramique, l'hôte du modèle traduit les entrées utilisateur des appareils d'entrées non tactiles, tels que les contrôleurs rotatifs et les pavés tactiles dans les méthodes SurfaceCallback
appropriées. Répondez à l'action de l'utilisateur visant à ouvrir ou quitter le mode panoramique à l'aide de la méthode setPanModeListener
dans le NavigationTemplate.Builder
. L'hôte peut masquer d'autres composants d'interface utilisateur dans le modèle lorsque l'utilisateur est en mode panoramique.
Interagir avec l'utilisateur
Votre application peut interagir avec l'utilisateur à l'aide de schémas semblables à ceux d'une application mobile.
Gérer les entrées utilisateur
Votre application peut répondre aux saisies de l'utilisateur en transmettant les écouteurs appropriés aux modèles qui les acceptent. L'extrait suivant montre comment créer un modèle Action
qui définit un OnClickListener
qui rappelle une méthode définie par le code de votre application :
Kotlin
val action = Action.Builder() .setTitle("Navigate") .setOnClickListener(::onClickNavigate) .build()
Java
Action action = new Action.Builder() .setTitle("Navigate") .setOnClickListener(this::onClickNavigate) .build();
La méthode onClickNavigate
peut ensuite démarrer l'application de navigation par défaut pour voiture à l'aide de la méthode CarContext.startCarApp
:
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); }
Pour en savoir plus sur le lancement d'applications, y compris sur le format de l'intent ACTION_NAVIGATE
, consultez la section Lancer une application automobile avec un intent.
Certaines actions, comme celles qui nécessitent de demander à l'utilisateur de poursuivre l'interaction sur son appareil mobile, ne sont autorisées que lorsque la voiture est à l'arrêt.
Vous pouvez utiliser ParkedOnlyOnClickListener
pour implémenter ces actions. Si la voiture n'est pas garée, l'hôte indique à l'utilisateur que l'action n'est pas autorisée dans ce cas. Si la voiture est garée, le code s'exécute normalement. L'extrait de code suivant montre comment utiliser ParkedOnlyOnClickListener
pour ouvrir un écran de paramètres sur l'appareil mobile :
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();
Afficher les notifications
Les notifications envoyées à l'appareil mobile ne s'affichent sur l'écran de la voiture que si elles sont étendues avec un CarAppExtender
.
Certains attributs de notification, tels que le titre, le texte, l'icône et les actions du contenu, peuvent être définis dans CarAppExtender
, ce qui remplace les attributs de la notification lorsqu'ils s'affichent sur l'écran de la voiture.
L'extrait suivant montre comment envoyer une notification à l'écran de la voiture qui affiche un titre différent de celui affiché sur l'appareil mobile :
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();
Les notifications peuvent affecter les parties suivantes de l'interface utilisateur :
- Une notification prioritaire peut s'afficher à l'intention de l'utilisateur.
- Une entrée peut être ajoutée au centre de notifications, éventuellement avec un badge visible dans le rail.
- Pour les applications de navigation, la notification peut s'afficher dans le widget de rail, comme décrit dans Notifications de navigation détaillée.
Vous pouvez choisir comment configurer les notifications de votre application pour affecter chacun de ces éléments d'interface utilisateur en utilisant la priorité de la notification, comme décrit dans la documentation CarAppExtender
.
Si NotificationCompat.Builder.setOnlyAlertOnce
est appelé avec la valeur true
, une notification à priorité élevée s'affiche sous forme de notification prioritaire une seule fois.
Pour en savoir plus sur la conception des notifications de votre application automobile, consultez le guide Google Design for Driving sur les notifications.
Afficher les toasts
Votre application peut afficher un toast à l'aide de CarToast
, comme indiqué dans cet extrait :
Kotlin
CarToast.makeText(carContext, "Hello!", CarToast.LENGTH_SHORT).show()
Java
CarToast.makeText(getCarContext(), "Hello!", CarToast.LENGTH_SHORT).show();
Demander des autorisations
Si votre application a besoin d'accéder à des données ou des actions restreintes (par exemple, la localisation), les règles standards des autorisations Android s'appliquent. Pour demander une autorisation, vous pouvez utiliser la méthode CarContext.requestPermissions()
.
L'avantage d'utiliser CarContext.requestPermissions()
par rapport aux API Android standards est que vous n'avez pas besoin de lancer votre propre Activity
pour créer la boîte de dialogue des autorisations. De plus, vous pouvez utiliser le même code sur Android Auto et Android Automotive OS, au lieu de devoir créer des flux dépendants de la plate-forme.
Mettre en forme la boîte de dialogue des autorisations sur Android Auto
Sur Android Auto, la boîte de dialogue d'autorisation s'affiche sur le téléphone de l'utilisateur.
Par défaut, aucune arrière-plan ne s'affiche derrière la boîte de dialogue. Pour définir un arrière-plan personnalisé, déclarez un thème d'application automobile dans votre fichier AndroidManifest.xml
et définissez l'attribut carPermissionActivityLayout
pour votre thème d'application automobile.
<meta-data android:name="androidx.car.app.theme" android:resource="@style/MyCarAppTheme />
Définissez ensuite l'attribut carPermissionActivityLayout
pour le thème de votre application automobile :
<resources> <style name="MyCarAppTheme"> <item name="carPermissionActivityLayout">@layout/my_custom_background</item> </style> </resources>
Démarrer une application automobile avec un intent
Vous pouvez appeler la méthode CarContext.startCarApp
pour effectuer l'une des actions suivantes :
- Ouvrez le clavier téléphonique pour passer un appel.
- Lancez la navigation détaillée vers un lieu avec l'application de navigation par défaut pour voiture.
- Démarrez votre propre application avec un intent.
L'exemple suivant montre comment créer une notification avec une action qui ouvre votre application sur un écran affichant les détails d'une réservation de parking.
Vous étendez l'instance de notification avec un intent de contenu qui contient un PendingIntent
encapsulant un intent explicite vers l'action de votre application :
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());
Votre application doit également déclarer un BroadcastReceiver
qui est appelé pour traiter l'intent lorsque l'utilisateur sélectionne l'action dans l'interface de notification et appelle CarContext.startCarApp
avec un intent incluant l'URI de données :
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))); } } }
Enfin, la méthode Session.onNewIntent
de votre application gère cet intent en ajoutant l'écran de réservation de parking à la pile, s'il ne se trouve pas déjà en haut :
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())); } } }
Pour en savoir plus sur la gestion des notifications pour l'application automobile, consultez la section Afficher les notifications.
Restrictions concernant les modèles
L'hôte limite le nombre de modèles à afficher pour une tâche donnée à cinq maximum, dont le dernier modèle doit être l'un des types suivants :
NavigationTemplate
PaneTemplate
MessageTemplate
MediaPlaybackTemplate
SignInTemplate
LongMessageTemplate
Notez que cette limite s'applique au nombre de modèles et non au nombre d'instances Screen
dans la pile. Par exemple, si une application envoie deux modèles sur l'écran A, puis envoie l'écran B, elle peut désormais envoyer trois modèles supplémentaires. Si chaque écran est structuré pour envoyer un seul modèle, l'application peut envoyer cinq instances d'écran dans la pile ScreenManager
.
Il existe des cas particuliers à ces restrictions : l'actualisation des modèles, ainsi que les opérations de retour et de réinitialisation.
Actualisations des modèles
Certaines mises à jour de contenu ne sont pas comptabilisées dans la limite de modèles. En général, si une application envoie un nouveau modèle du même type et contenant le même contenu principal que le modèle précédent, le nouveau modèle n'est pas comptabilisé dans le quota. Par exemple, la modification de l'état d'activation d'une ligne dans un ListTemplate
n'est pas comptabilisée dans le quota. Consultez la documentation des modèles individuels pour en savoir plus sur les types de mises à jour de contenu qui peuvent être considérés comme une actualisation.
Opérations de retour
Pour activer les sous-flux dans une tâche, l'hôte détecte lorsqu'une application supprime un Screen
de la pile ScreenManager
et met à jour le quota restant en fonction du nombre de modèles par lesquels l'application recule.
Par exemple, si l'application envoie deux modèles sur l'écran A, puis envoie l'écran B et deux autres modèles, il lui reste un quota. Si l'application revient à l'écran A, l'hôte réinitialise le quota à trois, car l'application a reculé de deux modèles.
Notez que, lors du retour à un écran, une application doit envoyer un modèle du même type que celui envoyé en dernier par cet écran. L'envoi de tout autre type de modèle entraîne une erreur. Toutefois, tant que le type reste le même lors d'une opération de retour, une application peut modifier librement le contenu du modèle sans affecter le quota.
Opérations de réinitialisation
Certains modèles ont une sémantique spéciale qui indique la fin d'une tâche. Par exemple, NavigationTemplate
est une vue qui est censée rester à l'écran et être actualisée avec de nouvelles instructions détaillées pour l'utilisateur. Lorsqu'il atteint l'un de ces modèles, l'hôte réinitialise le quota de modèles, en traitant ce modèle comme s'il s'agissait de la première étape d'une nouvelle tâche. Cela permet à l'application de commencer une nouvelle tâche.
Consultez la documentation des modèles individuels pour savoir lesquels déclenchent une réinitialisation sur l'hôte.
Si l'hôte reçoit un intent pour démarrer l'application à partir d'une action de notification ou du lanceur d'applications, le quota est également réinitialisé. Ce mécanisme permet à une application de démarrer un nouveau flux de tâches à partir des notifications, et ce, même si une application est déjà liée et au premier plan.
Pour en savoir plus sur l'affichage des notifications de votre application sur l'écran de la voiture, consultez la section Afficher les notifications. Consultez la section Démarrer une application automobile avec un intent pour savoir comment démarrer votre application à partir d'une action de notification.
API Connection
Vous pouvez déterminer si votre application s'exécute sur Android Auto ou Android Automotive OS en utilisant l'API CarConnection
pour récupérer les informations de connexion au moment de l'exécution.
Par exemple, dans le Session
de votre application pour voitures, initialisez un CarConnection
et abonnez-vous aux mises à jour LiveData
:
Kotlin
CarConnection(carContext).type.observe(this, ::onConnectionStateUpdated)
Java
new CarConnection(getCarContext()).getType().observe(this, this::onConnectionStateUpdated);
Dans l'observateur, vous pouvez ensuite réagir aux changements d'état de la connexion :
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(); }
API Constraints
Le nombre d'instances Item
pouvant être affichées à l'utilisateur à la fois peut varier selon les voitures. Utilisez ConstraintManager
pour vérifier la limite de contenu au moment de l'exécution et définir le nombre d'éléments approprié dans vos modèles.
Commencez par obtenir un ConstraintManager
à partir de CarContext
:
Kotlin
val manager = carContext.getCarService(ConstraintManager::class.java)
Java
ConstraintManager manager = getCarContext().getCarService(ConstraintManager.class);
Vous pouvez ensuite interroger l'objet ConstraintManager
récupéré pour connaître la limite de contenu pertinente. Par exemple, pour obtenir le nombre d'éléments pouvant être affichés dans une grille, appelez getContentLimit
avec CONTENT_LIMIT_TYPE_GRID
:
Kotlin
val gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID)
Java
int gridItemLimit = manager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_GRID);
Ajouter un flux de connexion
Si votre application propose une expérience de connexion aux utilisateurs, vous pouvez utiliser des modèles tels que SignInTemplate
et LongMessageTemplate
avec le niveau d'API 2 et supérieur de l'API Car App pour gérer la connexion à votre application sur l'unité principale de la voiture.
Pour créer un SignInTemplate
, définissez un SignInMethod
. La bibliothèque d'applications pour voiture est actuellement compatible avec les méthodes de connexion suivantes :
InputSignInMethod
pour la connexion avec un nom d'utilisateur et un mot de passe.PinSignInMethod
pour la connexion par code PIN, où l'utilisateur associe son compte depuis son téléphone à l'aide d'un code PIN affiché sur l'unité principale.ProviderSignInMethod
pour la connexion au fournisseur, comme Se connecter avec Google et One Tap.QRCodeSignInMethod
pour la connexion par code QR, où l'utilisateur scanne un code QR pour se connecter sur son téléphone. Cette fonctionnalité est disponible avec le niveau d'API 4 de Car et les versions ultérieures.
Par exemple, pour implémenter un modèle qui collecte le mot de passe de l'utilisateur, commencez par créer un InputCallback
pour traiter et valider l'entrée de l'utilisateur :
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. } };
Un InputCallback
est requis pour le Builder
InputSignInMethod
.
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();
Enfin, utilisez votre nouveau InputSignInMethod
pour créer un SignInTemplate
.
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();
Utiliser AccountManager
Les applications Android Automotive OS avec authentification doivent utiliser AccountManager pour les raisons suivantes :
- Meilleure expérience utilisateur et gestion de compte simplifiée : les utilisateurs peuvent facilement gérer tous leurs comptes à partir du menu "Comptes" dans les paramètres système, y compris la connexion et la déconnexion.
- Expériences des invités : les voitures étant des appareils partagés, les OEM peuvent activer l'expérience "Invité" dans le véhicule, lorsque l'ajout de comptes n'est pas permis.
Ajouter des variantes de chaîne de texte
La quantité de texte affichée peut varier en fonction de la taille de l'écran de la voiture. Avec le niveau d'API Car App 2 et supérieur, vous pouvez spécifier plusieurs variantes d'une chaîne de texte pour l'adapter au mieux à l'écran. Pour savoir où les variantes de texte sont acceptées, recherchez les modèles et les composants qui acceptent un CarText
.
Vous pouvez ajouter des variantes de chaîne de texte à un CarText
avec la méthode CarText.Builder.addVariant()
:
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();
Vous pouvez ensuite utiliser ce CarText
, par exemple comme texte principal d'un GridItem
.
Kotlin
GridItem.Builder() .addTitle(itemTitle) ... .build()
Java
new GridItem.Builder() .addTitle(itemTitle) ... build();
Ajoutez les chaînes dans l'ordre de préférence, par exemple de la plus longue à la plus courte. L'hôte choisit la chaîne de longueur appropriée en fonction de l'espace disponible sur l'écran de la voiture.
Ajouter des CarIcons intégrées pour les lignes
Vous pouvez ajouter des icônes en ligne avec du texte pour enrichir l'attrait visuel de votre application à l'aide de CarIconSpan
.
Pour en savoir plus sur la création de ces spans, consultez la documentation de CarIconSpan.create
. Pour obtenir une présentation du fonctionnement du style de texte avec des spans, consultez Appliquer des styles à du texte avec des objets Span.
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();
API Car Hardware
À partir du niveau d'API 3 de Car App, la bibliothèque Car App propose des API que vous pouvez utiliser pour accéder aux propriétés et aux capteurs du véhicule.
Conditions requises
Pour utiliser les API avec Android Auto, commencez par ajouter une dépendance sur androidx.car.app:app-projected
au fichier build.gradle
de votre module Android Auto. Pour Android Automotive OS, ajoutez une dépendance à androidx.car.app:app-automotive
au fichier build.gradle
de votre module Android Automotive OS.
De plus, dans votre fichier AndroidManifest.xml
, vous devez déclarer les autorisations pertinentes nécessaires pour demander les données de voiture que vous souhaitez utiliser. Notez que ces autorisations doivent également vous être accordées par l'utilisateur. Vous pouvez utiliser le même code sur Android Auto et Android Automotive OS, au lieu de devoir créer des flux dépendants de la plate-forme. Toutefois, les autorisations requises sont différentes.
CarInfo
Ce tableau décrit les propriétés exposées par les API CarInfo
et les autorisations que vous devez demander pour les utiliser :
Méthodes | Propriétés | Autorisations Android Auto | Autorisations Android Automotive OS | Prise en charge depuis le niveau d'API de Car App |
---|---|---|---|---|
fetchModel |
Marque, modèle, année | android.car.permission.CAR_INFO |
3 | |
fetchEnergyProfile |
Types de connecteurs pour véhicules électriques, types de carburant | com.google.android.gms.permission.CAR_FUEL |
android.car.permission.CAR_INFO |
3 |
fetchExteriorDimensions
Ces données ne sont disponibles que sur certains véhicules Android Automotive OS exécutant l'API 30 ou version ultérieure. |
Dimensions extérieures | N/A | android.car.permission.CAR_INFO |
7 |
addTollListener
removeTollListener |
État de la carte de péage, type de carte de péage | 3 | ||
addEnergyLevelListener
removeEnergyLevelListener |
Niveau de batterie, niveau de carburant, niveau de carburant faible, autonomie restante | 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 |
Vitesse brute, vitesse affichée (sur le tableau de bord de la voiture) | com.google.android.gms.permission.CAR_SPEED |
android.car.permission.CAR_SPEED ,android.car.permission.READ_CAR_DISPLAY_UNITS |
3 |
addMileageListener
removeMileageListener
Avertissement : la méthode |
Distance du compteur kilométrique | com.google.android.gms.permission.CAR_MILEAGE |
Ces données ne sont pas disponibles sur Android Automotive OS pour les applications installées depuis le Play Store. | 3 |
Par exemple, pour obtenir la plage restante, instanciez un objet CarInfo
, puis créez et enregistrez un 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);
Ne partez pas du principe que les données de la voiture sont disponibles à tout moment.
Si vous recevez un message d'erreur, vérifiez l'état de la valeur que vous avez demandée pour mieux comprendre pourquoi les données que vous avez demandées n'ont pas pu être récupérées. Consultez la documentation de référence pour obtenir la définition complète de la classe CarInfo
.
CarSensors
La classe CarSensors
vous donne accès aux données de l'accéléromètre, du gyroscope, de la boussole et de la position du véhicule. La disponibilité de ces valeurs peut dépendre de l'OEM. Le format des données de l'accéléromètre, du gyroscope et de la boussole est le même que celui obtenu à partir de l'API SensorManager
. Par exemple, pour vérifier le cap du véhicule :
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);
Pour accéder aux données de localisation de la voiture, vous devez également déclarer et demander l'autorisation android.permission.ACCESS_FINE_LOCATION
.
Tests
Pour simuler des données de capteurs lors des tests sur Android Auto, consultez les sections Capteurs et Configuration des capteurs du guide de l'unité principale pour ordinateur. Pour simuler des données de capteur lors des tests sur Android Automotive OS, consultez la section Émuler l'état du matériel du guide de l'émulateur Android Automotive OS.
Cycles de vie de CarAppService, Session et Screen
Les classes Session
et Screen
implémentent l'interface LifecycleOwner
. Lorsque l'utilisateur interagit avec l'application, les rappels de cycle de vie de vos objets Session
et Screen
sont appelés, comme décrit dans les diagrammes suivants.
Cycles de vie d'un CarAppService et d'une session

Session
Pour en savoir plus, consultez la documentation de la méthode Session.getLifecycle
.
Cycle de vie d'un écran

Screen
Pour en savoir plus, consultez la documentation de la méthode Screen.getLifecycle
.
Enregistrer à partir du micro de la voiture
En utilisant CarAppService
et l'API CarAudioRecord
de votre application, vous pouvez lui donner accès au micro de la voiture de l'utilisateur. Les utilisateurs doivent autoriser votre application à accéder au micro de la voiture. Votre application peut enregistrer et traiter les saisies de l'utilisateur.
Autorisation d'enregistrement
Avant d'enregistrer un élément audio, vous devez d'abord déclarer l'autorisation d'enregistrement dans votre AndroidManifest.xml
et demander à l'utilisateur de l'accorder.
<manifest ...>
...
<uses-permission android:name="android.permission.RECORD_AUDIO" />
...
</manifest>
Vous devez demander l'autorisation d'enregistrer au moment de l'exécution. Pour savoir comment demander une autorisation dans votre application pour voiture, consultez la section Demander des autorisations.
Enregistrer un fichier audio
Une fois que l'utilisateur a autorisé l'enregistrement, vous pouvez enregistrer l'audio et traiter l'enregistrement.
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();
Priorité audio
Lorsque vous enregistrez à partir du micro de la voiture, obtenez d'abord la priorité audio pour vous assurer que tout contenu multimédia en cours est arrêté. Si vous perdez le focus audio, arrêtez l'enregistrement.
Voici un exemple d'acquisition du focus audio :
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
Bibliothèque de tests
La bibliothèque de test Android for Cars fournit des classes auxiliaires que vous pouvez utiliser pour valider le comportement de votre application dans un environnement de test.
Par exemple, SessionController
vous permet de simuler une connexion à l'hôte et de vérifier que les Screen
et Template
corrects sont créés et renvoyés.
Consultez les exemples pour obtenir des exemples d'utilisation.
Signaler un problème lié à la bibliothèque d'applications Android for Cars
Si vous rencontrez un problème avec la bibliothèque, signalez-le à l'aide de l'outil de suivi des problèmes de Google. Veillez à fournir toutes les informations requises dans le modèle dédié.
Avant de signaler un nouveau problème, veuillez vérifier s'il figure dans les notes de version de la bibliothèque ou dans la liste des problèmes. Vous pouvez vous abonner et voter pour des problèmes en cliquant sur l'étoile correspondant à un problème dans l'outil de suivi. Pour en savoir plus, consultez S'abonner à un problème.