Utilisez l'API Instrument Cluster (une API Android) pour afficher les applications de navigation, y compris Google Maps, sur un écran secondaire dans une voiture, par exemple derrière le volant du tableau de bord. Cette page décrit comment créer un service pour contrôler cet affichage secondaire, puis intégrer le service à
afin que les applications de navigation puissent afficher une interface utilisateur.CarService
Terminologie
Les termes suivants sont utilisés sur cette page :
Terme | Description |
---|---|
CarInstrumentClusterManager | Une instance CarManager qui permet aux applications externes de lancer une activité sur le groupe d'instruments et de recevoir des rappels lorsque le groupe d'instruments est prêt à afficher des activités. |
CarManager | Classe de base de tous les gestionnaires utilisés par les applications externes pour interagir avec les services spécifiques à la voiture implémentés par CarService . |
CarService | Service de plate-forme Android qui assure la communication entre les applications externes (y compris Google Maps) et les fonctionnalités spécifiques à la voiture, telles que l'accès au groupe d'instruments. |
Destination | La destination finale vers laquelle le véhicule naviguera. |
ETA | Heure estimée d'arrivée à destination. |
Unité principale (HU) | Unité de calcul primaire embarquée dans une voiture. Le HU exécute tout le code Android et est connecté à l’écran central de la voiture. |
Groupe d'instruments | Écran secondaire situé derrière le volant et entre les instruments de la voiture. Il peut s'agir d'une unité de calcul indépendante connectée au HU via le réseau interne de la voiture (bus CAN) ou d'un écran secondaire connecté au HU. |
InstrumentClusterRenderingService | Classe de base pour le service utilisé pour s'interfacer avec l'affichage du groupe d'instruments. Les OEM doivent fournir une extension de cette classe qui interagit avec le matériel spécifique à l'OEM. |
Application KitchenSink | Application de test incluse avec Android Automotive. |
Itinéraire | Un chemin spécifique le long duquel un véhicule navigue pour arriver à une destination. |
Service simple | Un service Android avec l'attribut android:singleUser . À tout moment, au plus une instance du service s'exécute sur le système Android. |
Conditions préalables
Pour développer l’intégration, assurez-vous d’avoir ces éléments :
- Environnement de développement Android. Pour configurer l'environnement de développement Android, consultez Exigences de build .
- Téléchargez le code source Android. Obtenez la dernière version du code source Android depuis la branche pi-car-release (ou version ultérieure) sur https://android.googlesource.com .
- Unité principale (HU). Un appareil Android capable d'exécuter Android 9 (ou version ultérieure). Cet appareil doit avoir son propre écran et être capable de faire clignoter l'écran avec les nouvelles versions d'Android.
- Le groupe d'instruments est l'un des éléments suivants :
- Écran secondaire physique attaché au HU. Si le matériel et le noyau de l'appareil prennent en charge la gestion de plusieurs écrans.
- Unité indépendante. Toute unité de calcul connectée au HU via une connexion réseau, capable de recevoir et d'afficher un flux vidéo sur son propre écran.
- Affichage émulé. Pendant le développement, vous pouvez utiliser l'un de ces environnements émulés :
- Affichages secondaires simulés. Pour activer un affichage secondaire simulé sur n'importe quelle distribution AOSP Android, accédez aux paramètres Options du développeur dans l'application système Paramètres, puis sélectionnez Simuler les affichages secondaires. Cette configuration équivaut à fixer un écran secondaire physique, avec la limitation que cet écran est superposé à l'écran principal.
- Groupe d'instruments émulé. L'émulateur Android inclus avec Android Automotive offre une option permettant d'afficher un groupe d'instruments avec le service ClusterRenderingService connecté à l'écran secondaire. émulateur _qemu-pipes . Le service ClusterRenderingService est connecté à l’affichage secondaire.
implémentation du groupe d'instruments de référence pour se connecter à cet écran externe émulé.
Architecture d'intégration
Composants d'intégration
Toute intégration de l'API Instrument Cluster se compose de ces trois composants :
-
CarService
- Applications de navigation
- Service de groupe d'instruments OEM
Service automobile
CarService
sert d'intermédiaire entre les applications de navigation et la voiture, garantissant qu'une seule application de navigation est active à un moment donné et que seules les applications disposant de l'autorisation android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
peuvent envoyer des données à la voiture.
CarService
démarre tous les services spécifiques à la voiture et donne accès à ces services via une série de gestionnaires. Pour interagir avec les services, les applications exécutées dans la voiture peuvent accéder à ces gestionnaires.
Pour la mise en œuvre du groupe d'instruments, les constructeurs automobiles doivent créer une implémentation personnalisée d'InstrumentClusterRendererService et mettre à jour le service ClusterRenderingService connecté à l'écran secondaire.
Lors du rendu d'un groupe d'instruments, pendant le processus de démarrage, le CarService
lit la clé InstrumentClusterRendererService
du service ClusterRenderingService qui est connecté à l'écran secondaire. pour localiser une implémentation de InstrumentClusterService
. Dans AOSP, cette entrée pointe vers l’exemple de service de rendu d’implémentation de cluster de l’API Navigation State :
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
Le service mentionné dans cette entrée est initialisé et lié à CarService
. Lorsque des applications de navigation, comme Google Maps, demandent un CarInstrumentClusterManager
, CarService
fournit un gestionnaire qui met à jour l'état du cluster d'instruments à partir du InstrumentClusterRenderingService
lié. (Dans ce cas, lié fait référence aux services Android .)
Service du groupe d'instruments
Les OEM doivent créer un package Android (APK) contenant une sous-classe du service ClusterRenderingService connecté à l’affichage secondaire. Le service ClusterRenderingService est connecté à l’affichage secondaire. pour un échantillon.
Cette classe répond à deux objectifs :
- Fournit une interface Android et le dispositif de rendu Instrument Cluster (le but de cette page).
- Reçoit et restitue des mises à jour de l'état de navigation, telles que le guidage de navigation étape par étape.
Pour le premier objectif, les implémentations OEM de InstrumentClusterRendererService
doivent initialiser l'affichage secondaire utilisé pour restituer les informations sur les écrans de l'habitacle de la voiture et communiquer ces informations à CarService
en appelant les méthodes InstrumentClusterRendererService.setClusterActivityOptions()
et InstrumentClusterRendererService.setClusterActivityState()
.
Pour la deuxième fonction, le service Instrument Cluster doit fournir une implémentation du service ClusterRenderingService connecté à l'écran secondaire. interface qui reçoit les événements de mise à jour de l'état de navigation, qui sont codés en tant que eventType
et les données d'événement codées dans un bundle.
Séquence d'intégration
Le diagramme suivant illustre l'implémentation d'un état de navigation qui restitue les mises à jour :
Dans cette illustration, les couleurs désignent les éléments suivants :
- Jaune.
CarService
etCarNavigationStatusManager
fournis par la plateforme Android. Pour en savoir plus, consultez Car et CAR_NAVIGATION_SERVICE . - Cyan.
InstrumentClusterRendererService
implémenté par l'OEM. - Violet. L'application de navigation mise en œuvre par Google et des développeurs tiers.
- Vert.
CarAppFocusManager
. Pour en savoir plus, consultez Utilisation de l'API CarAppFocusManager ci-dessous et CarAppFocusManager .
Le flux d’informations sur l’état de navigation suit cette séquence :
-
CarService
initialise leInstrumentClusterRenderingService
. - Lors de l'initialisation,
InstrumentClusterRenderingService
met à jourCarService
avec :- Propriétés d'affichage du groupe d'instruments, telles que les limites non obscurcies (voir plus de détails sur les limites non obscurcies plus tard).
- Options d'activité nécessaires pour lancer des activités dans l'affichage du groupe d'instruments (voir plus de détails sur ActivityOptions .
- Une application de navigation (telle que Google Maps pour Android Automotive ou toute application de cartes disposant des autorisations requises) :
- Obtient un
CarAppFocusManager
en utilisant la classe Car de car-lib. - Avant le début des instructions détaillées, appels à
CarAppFocusManager.requestFocus()
pour transmettreCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
comme paramètreappType
.
- Obtient un
-
CarAppFocusManager
communique cette demande àCarService
. Si cela est accordé,CarService
inspecte le package de l'application de navigation et localise une activité marquée avec la catégorieandroid.car.cluster.NAVIGATION
. - Si elle est trouvée, l'application de navigation utilise les
ActivityOptions
signalées parInstrumentClusterRenderingService
pour lancer l'activité et inclut les propriétés d'affichage du groupe d'instruments en tant qu'extras dans l'intention.
Intégrer l'API
L'implémentation InstrumentClusterRenderingService
doit :
- Soyez désigné comme service singleton en ajoutant la valeur suivante au fichier AndroidManifest.xml. Cela est nécessaire pour garantir qu'une seule copie du service Instrument Cluster s'exécute, même pendant l'initialisation et le changement d'utilisateur :
android:singleUser="true"
- Détenez l’autorisation système
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
. Cela garantit que seul le service de rendu du groupe d'instruments inclus dans l'image système Android est toujours lié parCarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Implémenter InstrumentClusterRenderingService
Pour créer le service :
- Écrivez une classe qui s'étend du service ClusterRenderingService et est connectée à l'affichage secondaire. puis ajoutez une entrée correspondante à votre fichier
- Pendant
onCreate()
, utilisez ce service pour initialiser la communication avec le matériel de rendu. Les options incluent :- Déterminez l’affichage secondaire à utiliser pour le groupe d’instruments.
- Créez un affichage virtuel afin que l'application Instrument Cluster restitue et transmette l'image rendue à une unité externe (en utilisant un format de streaming vidéo, tel que H.264).
- Lorsque l'affichage indiqué ci-dessus est prêt, ce service doit appeler
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
pour définir lesActivityOptions
exactes qui doivent être utilisées pour afficher une activité sur le cluster d'instruments. Utilisez ces paramètres :- catégorie. Le service ClusterRenderingService est connecté à l’affichage secondaire.
-
ActivityOptions.
Une instanceActivityOptions
qui peut être utilisée pour lancer une activité dans le cluster d'instruments. Par exemple, à partir de l'exemple d'implémentation d'Instrument Cluster sur AOSP :getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Lorsque le cluster d'instruments est prêt à afficher les activités, ce service doit appeler
InstrumentClusterRenderingService#setClusterActivityState()
. Utilisez ces paramètres :- Le service
category
ClusterRenderingService est connecté à l’affichage secondaire. - Le bundle
state
généré avec le service ClusterRenderingService est connecté à l'affichage secondaire. Assurez-vous de fournir les données suivantes : -
visible
Spécifie le groupe d'instruments comme étant visible et prêt à afficher le contenu. -
unobscuredBounds
Un rectangle qui définit la zone de l'affichage du groupe d'instruments dans laquelle il est possible d'afficher du contenu en toute sécurité. Par exemple, les zones couvertes par des cadrans et des jauges.
- Le service
- Remplacez la méthode
Service#dump()
et signalez les informations d'état utiles pour le débogage (voir dumpsys pour plus d'informations).
AndroidManifest.xml
. Cette classe contrôle l'affichage du groupe d'instruments et peut ( en option ) restituer les données de l'API d'état de navigation.Exemple d’implémentation d’InstrumentClusterRenderingService
L'exemple suivant décrit une implémentation InstrumentClusterRenderingService
, qui crée un VirtualDisplay
pour présenter le contenu du cluster d'instruments sur un écran physique distant.
Alternativement, ce code pourrait transmettre le displayId
d’un affichage secondaire physique connecté au HU, s’il est connu qu’il en existe un.
/** * Sample {@link InstrumentClusterRenderingService} implementation */ public class SampleClusterServiceImpl extends InstrumentClusterRenderingService { // Used to retrieve or create displays private final DisplayManager mDisplayManager; // Unique identifier for the display to be used for instrument // cluster private final String mUniqueId = UUID.randomUUID().toString(); // Format of the instrument cluster display private static final int DISPLAY_WIDTH = 1280; private static final int DISPLAY_HEIGHT = 720; private static final int DISPLAY_DPI = 320; // Area not covered by instruments private static final int DISPLAY_UNOBSCURED_LEFT = 40; private static final int DISPLAY_UNOBSCURED_TOP = 0; private static final int DISPLAY_UNOBSCURED_RIGHT = 1200; private static final int DISPLAY_UNOBSCURED_BOTTOM = 680; @Override public void onCreate() { super.onCreate(); // Create a virtual display to render instrument cluster activities on mDisplayManager = getSystemService(DisplayManager.class); VirtualDisplay display = mDisplayManager.createVirtualDisplay( mUniqueId, DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, null, 0 /* flags */, null, null); // Do any additional initialization (e.g.: start a video stream // based on this virtual display to present activities on a remote // display). onDisplayReady(display.getDisplay()); } private void onDisplayReady(Display display) { // Report activity options that should be used to launch activities on // the instrument cluster. String category = CarInstrumentClusterManager.CATEGORY_NAVIGATION; ActionOptions options = ActivityOptions.makeBasic() .setLaunchDisplayId(display.getDisplayId()); setClusterActivityOptions(category, options); // Report instrument cluster state. Rect unobscuredBounds = new Rect(DISPLAY_UNOBSCURED_LEFT, DISPLAY_UNOBSCURED_TOP, DISPLAY_UNOBSCURED_RIGHT, DISPLAY_UNOBSCURED_BOTTOM); boolean visible = true; ClusterActivityState state = ClusterActivityState.create(visible, unobscuredBounds); setClusterActivityState(category, options); } }
Utilisez l'API CarAppFocusManager
L'API CarAppFocusManager fournit une méthode nommée getAppTypeOwner()
, qui permet au service de cluster écrit par les OEM de savoir quelle application de navigation a le focus de navigation à un moment donné. Les OEM peuvent utiliser la méthode CarAppFocusManager#addFocusListener()
existante, puis utiliser getAppTypeOwner()
pour savoir quelle application a le focus. Grâce à ces informations, les OEM peuvent :
- Basculez l’activité affichée dans le cluster vers l’activité de cluster fournie par l’application de navigation détenant le focus.
- Peut détecter si l'application de navigation ciblée a une activité de cluster ou non. Si l'application de navigation ciblée n'a pas d'activité de cluster (ou si cette activité est désactivée), les constructeurs OEM peuvent envoyer ce signal au DIM de la voiture afin que la facette de navigation du cluster soit complètement ignorée.
Utilisez CarAppFocusManager
pour définir et écouter le focus actuel de l'application, comme la navigation active ou une commande vocale. Habituellement, une seule instance d’une telle application est activement exécutée (ou ciblée) dans le système.
Utilisez la méthode CarAppFocusManager#addFocusListener(..)
pour écouter les changements de focus de l'application :
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); mAppFocusManager.addFocusListener(this, CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); ... public void onAppFocusChanged(int appType, boolean active) { // Use the CarAppFocusManager#getAppTypeOwner(appType) method call // to retrieve a list of active package names }
Utilisez la méthode CarAppFocusManager#getAppTypeOwner(..)
pour récupérer les noms de package du propriétaire actuel d’un type d’application donné qui est sélectionné. Cette méthode peut renvoyer plusieurs noms de package si le propriétaire actuel utilise la fonctionnalité android:sharedUserId
.
import android.car.CarAppFocusManager; ... Car car = Car.createCar(this); mAppFocusManager = (CarAppFocusManager)car.getCarManager(Car.APP_FOCUS_SERVICE); List<String> focusOwnerPackageNames = mAppFocusManager.getAppTypeOwner( CarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION); if (focusOwnerPackageNames == null || focusOwnerPackageNames.isEmpty()) { // No Navigation app has focus // OEM may choose to show their default cluster view } else { // focusOwnerPackageNames // Use the PackageManager to retrieve the cluster activity for the package(s) // returned in focusOwnerPackageNames } ...
Annexe : Utiliser l'exemple d'application
AOSP fournit un exemple d'application qui implémente l'API Navigation State.
Pour exécuter cet exemple d'application :
- Créez et flashez Android Auto sur un HU pris en charge. Utilisez les instructions de création et de clignotement Android spécifiques à votre appareil. Pour obtenir des instructions, voir Utilisation des tableaux de référence .
- Connectez un écran secondaire physique au HU (si pris en charge) ou allumez le HU secondaire virtuel :
- Sélectionnez Mode développeur dans l'application Paramètres.
- Accédez à Paramètres > Système > Avancé > Options du développeur > Simuler les affichages secondaires .
- Redémarrez le HU. Le service ClusterRenderingService est connecté à l'affichage secondaire.
- Pour lancer l'application KitchenSink :
- Ouvrez le tiroir.
- Allez dans Inst. Grappe .
- Cliquez sur DÉMARRER LES MÉTADONNÉES .
KitchenSink demande le focus NAVIGATION, qui demande au service DirectRenderingCluster
d'afficher une interface utilisateur simulée sur le groupe d'instruments.