Utilisez l'API Instrument Cluster (une API Android) pour afficher des applications de navigation, y compris Google Maps, sur un écran secondaire dans une voiture, comme derrière le volant sur le 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 | La description |
---|---|
CarInstrumentClusterManager | Un 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 mis en œuvre 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 d'arrivée estimé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 | Affichage 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 à l'HU via le réseau interne de la voiture (bus CAN) ou d'un affichage secondaire attaché à l'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 unique | 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 Configuration requise .
- Téléchargez le code source Android. Obtenez la dernière version du code source Android à partir de la branche pi-car-release (ou version ultérieure) sur https://android.googlesource.com .
- Unité de tête (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 suivants :
- Affichage secondaire physique attaché à l'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 Android AOSP, accédez aux paramètres des options du développeur dans l'application système Paramètres, puis sélectionnez Simuler les affichages secondaires. Cette configuration équivaut à attacher un affichage secondaire physique, avec la limitation que cet affichage se superpose à l'affichage principal.
- Combiné d'instruments émulé. L'émulateur Android inclus avec Android Automotive offre une option pour afficher un groupe d'instruments avec l' émulateur Android _qemu-pipes . Utilisez l'implémentation du groupe d'instruments de référence DirectRenderingCluster pour vous 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
assure la médiation 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 avec l'autorisation android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
peuvent envoyer des données à la voiture.
CarService
tous les services spécifiques à la voiture et fournit l'accès à ces services via une série de gestionnaires. Pour interagir avec les services, les applications tournant dans la voiture peuvent accéder à ces gestionnaires.
Pour l'implémentation du groupe d'instruments, les équipementiers automobiles doivent créer une implémentation personnalisée d'InstrumentClusterRendererService et mettre à jour le fichier config.xml
pour qu'il pointe vers cette implémentation personnalisée.
Lors du rendu d'un groupe d'instruments, pendant le processus de démarrage, CarService
lit la clé InstrumentClusterRendererService
du config.xml
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 auquel il est fait référence dans cette entrée est initialisé et lié à CarService
. Lorsque des applications de navigation, telles que 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 de groupe d'instruments
Les OEM doivent créer un package Android (APK) qui contient une sous-classe de InstrumentClusterRendererService .
Voir ClusterRenderingService
pour un exemple.
Cette classe a deux objectifs :
- Fournit une interface Android et le dispositif de rendu Instrument Cluster (le but de cette page).
- Reçoit et restitue les mises à jour de l'état de la navigation, telles que le guidage de navigation étape par étape.
Dans un premier temps, les implémentations OEM d' 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 seconde fonction, le service Instrument Cluster doit fournir une implémentation de l'interface NavigationRenderer
qui reçoit les événements de mise à jour de l'état de navigation, qui sont encodés en tant que eventType
et les données d'événement encodées dans un bundle.
Séquence d'intégration
Le schéma suivant illustre la mise en œuvre d'un état de navigation qui affiche les mises à jour :
Dans cette illustration, les couleurs indiquent ce qui suit :
- Jaune.
CarService
etCarNavigationStatusManager
fournis par la plateforme Android. Pour en savoir plus, consultez Car et CAR_NAVIGATION_SERVICE . - Cyan.
InstrumentClusterRendererService
mis en œuvre 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 la 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 claires (voir plus de détails sur les limites claires plus tard).
- Options d'activité nécessaires pour lancer des activités à l'intérieur de 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 cartographique avec les autorisations requises) :
- Obtient un
CarAppFocusManager
en utilisant la classe Car de car-lib. - Avant le démarrage des instructions détaillées, des appels à
CarAppFocusManager.requestFocus()
pour transmettreCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
en tant que paramètreappType
.
- Obtient un
-
CarAppFocusManager
communique cette demande àCarService
. Si elle est accordée,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 que suppléments dans l'intention.
Intégration de l'API
L'implémentation InstrumentClusterRenderingService
doit :
- Soyez désigné comme service singleton en ajoutant la valeur suivante à AndroidManifest.xml. Ceci est nécessaire pour s'assurer qu'une seule copie du service Instrument Cluster s'exécutera, 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 du système Android est toujours lié par leCarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Implémentation d'InstrumentClusterRenderingService
Pour créer le service :
- Écrivez une classe qui s'étend de
InstrumentClusterRenderingService
, puis ajoutez une entrée correspondante à votre fichierAndroidManifest.xml
. Cette classe contrôle l'affichage du groupe d'instruments et peut ( éventuellement ) restituer les données de l'API Navigation State. - 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 (à l'aide d'un format de diffusion 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 groupe d'instruments. Utilisez ces paramètres :- Catégorie. CarInstrumentClusterManager#CATEGORY_NAVIGATION
-
ActivityOptions.
Une instanceActivityOptions
qui peut être utilisée pour lancer une activité dans le groupe d'instruments. Par exemple, à partir de l'exemple d'implémentation du groupe d'instruments sur AOSP :getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Lorsque le cluster d'instruments est prêt à afficher des activités, ce service doit appeler
InstrumentClusterRenderingService#setClusterActivityState()
. Utilisez ces paramètres :-
category
CarInstrumentClusterManager#CATEGORY_NAVIGATION
-
state
Bundle généré avec ClusterActivityState . Assurez-vous de fournir les données suivantes :-
visible
Indique que le groupe d'instruments est 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.
-
-
- Remplacez la méthode
Service#dump()
et signalez les informations d'état utiles pour le débogage (voir dumpsys pour plus d'informations).
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 groupe d'instruments sur un affichage physique distant.
Alternativement, ce code pourrait transmettre l' displayId
d'affichage d'un affichage secondaire physique connecté au HU, s'il est connu qu'il est disponible.
/** * Sample {@link InstrumentClusterRenderingService} implementation */ public class SampleClusterServiceImpl extends InstrumentClusterRenderingService { // Used to retrieve or create displays private final DisplayManager mDisplayManager; // Unique identifier for the display that will 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); } }
Utilisation de 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 CarAppFocusManager#addFocusListener()
existante, puis utiliser getAppTypeOwner()
pour savoir quelle application a le focus. Avec ces informations, les OEM peuvent :
- Basculez l'activité affichée dans le cluster vers l'activité de cluster fournie par l'application de navigation qui détient 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 une telle activité est désactivée), les 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 en cours d'exécution active (ou focalisée) dans le système.
Utilisez la 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 CarAppFocusManager#getAppTypeOwner(..)
pour récupérer les noms de package du propriétaire actuel d'un type d'application donné qui est ciblé. 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 application 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 : Utilisation de 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 construction et de clignotement d'Android spécifiques à votre appareil. Pour obtenir des instructions, reportez-vous à la section Utilisation des cartes de référence .
- Connectez un affichage secondaire physique au HU (si pris en charge) ou activez le HU secondaire virtuel :
- Sélectionnez Mode développeur dans l'application Paramètres.
- Accédez à Paramètres > Système > Avancé > Options pour les développeurs > Simuler les écrans secondaires .
- Redémarrez le HU. Le service ClusterRenderingService est connecté à l'affichage secondaire.
- Pour lancer l'application KitchenSink :
- Ouvrez le tiroir.
- Allez à 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.