Use la API del panel de instrumentos (una API de Android) para mostrar aplicaciones de navegación, incluido Google Maps, en una pantalla secundaria en un automóvil, como detrás del volante en el panel de instrumentos. Esta página describe cómo crear un servicio para controlar esa pantalla secundaria y luego integrar el servicio con
para que las aplicaciones de navegación puedan mostrar una interfaz de usuario.CarService
Terminología
En esta página se utilizan los siguientes términos:
Término | Descripción |
---|---|
CarInstrumentClusterManager | Un CarManager que permite que las aplicaciones externas inicien una actividad en el grupo de instrumentos y reciban devoluciones de llamada cuando el grupo de instrumentos está listo para mostrar actividades. |
CarManager | Clase base de todos los administradores utilizados por aplicaciones externas para interactuar con servicios específicos del automóvil implementados por CarService . |
CarService | Servicio de la plataforma Android que proporciona comunicación entre aplicaciones externas (incluido Google Maps) y funciones específicas del automóvil, como el acceso al panel de instrumentos. |
Destino | El destino final al que navegará el vehículo. |
hora estimada de llegada | Hora estimada de llegada al destino. |
Unidad principal (HU) | Unidad computacional primaria integrada en un automóvil. La HU ejecuta todo el código de Android y está conectada a la pantalla central del automóvil. |
Combinación de instrumentos | Pantalla secundaria ubicada detrás del volante y entre los instrumentos del automóvil. Puede ser una unidad computacional independiente conectada a la HU a través de la red interna del automóvil (bus CAN) o una pantalla secundaria adjunta a la HU. |
InstrumentClusterRenderingService | Clase base para el servicio utilizado para interactuar con la pantalla del grupo de instrumentos. Los OEM deben proporcionar una extensión de esta clase que interactúe con el hardware específico del OEM. |
Aplicación KitchenSink | Aplicación de prueba incluida con Android Automotive. |
Ruta | Una ruta específica a lo largo de la cual navega un vehículo para llegar a un destino. |
Servicio único | Un servicio de Android con el atributo android:singleUser . En un momento dado, como máximo se ejecuta una instancia del servicio en el sistema Android. |
requisitos previos
Para desarrollar la integración, asegúrese de tener estos elementos:
- Entorno de desarrollo Android. Para configurar el entorno de desarrollo de Android, consulte Requisitos de compilación .
- Descarga el código fuente de Android. Obtenga la última versión del código fuente de Android de la rama pi-car-release (o posterior) en https://android.googlesource.com .
- Unidad de Cabecera (HU). Un dispositivo Android capaz de ejecutar Android 9 (o posterior). Este dispositivo debe tener su propia pantalla y ser capaz de actualizar la pantalla con nuevas versiones de Android.
- El grupo de instrumentos es uno de los siguientes:
- Pantalla secundaria física adjunta a la HU. Si el hardware y el kernel del dispositivo admiten la gestión de varias pantallas.
- Unidad independiente. Cualquier unidad computacional conectada a la HU a través de una conexión de red, capaz de recibir y mostrar un flujo de video en su propia pantalla.
- Pantalla emulada. Durante el desarrollo, puede utilizar uno de estos entornos emulados:
- Pantallas secundarias simuladas. Para habilitar una pantalla secundaria simulada en cualquier distribución de Android AOSP, vaya a la configuración de Opciones de desarrollador en la aplicación del sistema Configuración y luego seleccione Simular pantallas secundarias. Esta configuración es equivalente a adjuntar una pantalla secundaria física, con la limitación de que esta pantalla se superpone a la pantalla principal.
- Cuadro de instrumentos emulado. El emulador de Android incluido con Android Automotive ofrece una opción para mostrar un grupo de instrumentos con el emulador de Android _qemu-pipes . Use la implementación del grupo de instrumentos de referencia DirectRenderingCluster para conectarse a esta pantalla externa emulada.
Arquitectura de integración
Componentes de integración
Cualquier integración de Instrument Cluster API consta de estos tres componentes:
-
CarService
- Aplicaciones de navegación
- Servicio de grupo de instrumentos OEM
Servicio de auto
CarService
media entre las aplicaciones de navegación y el automóvil, lo que garantiza que solo una aplicación de navegación esté activa en un momento dado y que solo las aplicaciones con el permiso android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
puedan enviar datos al automóvil.
CarService
todos los servicios específicos del automóvil y brinda acceso a estos servicios a través de una serie de administradores. Para interactuar con los servicios, las aplicaciones que se ejecutan en el automóvil pueden acceder a estos administradores.
Para la implementación del grupo de instrumentos, los OEM automotrices deben crear una implementación personalizada de InstrumentClusterRendererService y actualizar el archivo config.xml
para señalar esa implementación personalizada.
Al representar un grupo de instrumentos, durante el proceso de arranque, CarService
lee la clave InstrumentClusterRendererService
del archivo config.xml
para ubicar una implementación de InstrumentClusterService
. En AOSP, esta entrada apunta al servicio de procesamiento de implementación de clúster de muestra de Navigation State API:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
El servicio al que se hace referencia en esta entrada se inicializa y vincula a CarService
. Cuando las aplicaciones de navegación, como Google Maps, solicitan un CarInstrumentClusterManager
, CarService
proporciona un administrador que actualiza el estado del grupo de instrumentos desde el InstrumentClusterRenderingService
vinculado. (En este caso, enlazado se refiere a los servicios de Android ).
Servicio de grupo de instrumentos
Los OEM deben crear un paquete de Android (APK) que contenga una subclase de InstrumentClusterRendererService .
Consulte ClusterRenderingService
para obtener una muestra.
Esta clase tiene dos propósitos:
- Proporciona una interfaz de Android y el dispositivo de representación del grupo de instrumentos (el propósito de esta página).
- Recibe y presenta actualizaciones del estado de navegación, como una guía de navegación paso a paso.
Para el primer propósito, las implementaciones OEM de InstrumentClusterRendererService
deben inicializar la pantalla secundaria que se usa para representar información en las pantallas de la cabina del automóvil y comunicar esta información a CarService
llamando a los métodos InstrumentClusterRendererService.setClusterActivityOptions()
e InstrumentClusterRendererService.setClusterActivityState()
.
Para la segunda función, el servicio del grupo de instrumentos debe proporcionar una implementación de la interfaz NavigationRenderer
que recibe eventos de actualización del estado de navegación, que se codifican como eventType
y datos de eventos codificados en un paquete.
Secuencia de integración
El siguiente diagrama ilustra la implementación de un estado de navegación que genera actualizaciones:
En esta ilustración, los colores indican lo siguiente:
- Amarillo.
CarService
yCarNavigationStatusManager
proporcionados por la plataforma Android. - cian.
InstrumentClusterRendererService
implementado por el OEM. - Violeta. La aplicación de navegación implementada por Google y desarrolladores externos.
- Verde.
CarAppFocusManager
.
El flujo de información del estado de navegación sigue esta secuencia:
-
CarService
inicializaInstrumentClusterRenderingService
. - Durante la inicialización,
InstrumentClusterRenderingService
actualizaCarService
con:- Las propiedades de visualización del grupo de instrumentos, como los límites claros (vea más detalles sobre los límites claros más adelante).
- Opciones de actividad necesarias para iniciar actividades dentro de la pantalla del grupo de instrumentos (ver más detalles en Opciones de actividad .
- Una aplicación de navegación (como Google Maps para Android Automotive o cualquier aplicación de mapas con los permisos necesarios):
- Obtiene un
CarAppFocusManager
usando la clase Car de car-lib. - Antes de que comiencen las indicaciones paso a paso, llama a
CarAppFocusManager.requestFocus()
para pasarCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
como el parámetroappType
.
- Obtiene un
-
CarAppFocusManager
comunica esta solicitud aCarService
. Si se concede,CarService
inspecciona el paquete de la aplicación de navegación y localiza una actividad marcada con la categoríaandroid.car.cluster.NAVIGATION
. - Si la encuentra, la aplicación de navegación utiliza las opciones de
ActivityOptions
informadas porInstrumentClusterRenderingService
para iniciar la actividad e incluye las propiedades de visualización del grupo de instrumentos como extras en la intención.
Integrando la API
La implementación de InstrumentClusterRenderingService
debe:
- Ser designado como un servicio singleton agregando el siguiente valor a AndroidManifest.xml. Esto es necesario para garantizar que se ejecutará una única copia del servicio del grupo de instrumentos, incluso durante la inicialización y el cambio de usuario:
android:singleUser="true"
- Tener el permiso del sistema
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
. Esto garantiza que solo el servicio de representación del grupo de instrumentos incluido como parte de la imagen del sistema Android esté vinculado porCarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Implementación de InstrumentClusterRenderingService
Para construir el servicio:
- Escriba una clase que se extienda desde
InstrumentClusterRenderingService
y luego agregue una entrada correspondiente a su archivoAndroidManifest.xml
. Esta clase controla la visualización del grupo de instrumentos y puede ( opcionalmente ) representar datos de API de estado de navegación. - Durante
onCreate()
, utilice este servicio para inicializar la comunicación con el hardware de representación. Las opciones incluyen:- Determine la pantalla secundaria que se usará para el grupo de instrumentos.
- Cree una pantalla virtual para que la aplicación Instrument Cluster renderice y transmita la imagen renderizada a una unidad externa (usando un formato de transmisión de video, como H.264).
- Cuando la pantalla indicada arriba esté lista, este servicio debe llamar a
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
para definir las opciones deActivityOptions
exactas que se deben usar para mostrar una actividad en el grupo de instrumentos. Utilice estos parámetros:- categoría. CarInstrumentClusterManager#CATEGORY_NAVIGATION
-
ActivityOptions.
Una instancia deActivityOptions
que se puede usar para iniciar una actividad en el grupo de instrumentos. Por ejemplo, de la implementación del grupo de instrumentos de muestra en AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Cuando el grupo de instrumentos está listo para mostrar actividades, este servicio debe invocar
InstrumentClusterRenderingService#setClusterActivityState()
. Utilice estos parámetros:-
category
CarInstrumentClusterManager#CATEGORY_NAVIGATION
- paquete de
state
generado con ClusterActivityState . Asegúrese de proporcionar los siguientes datos:-
visible
Especifica el grupo de instrumentos como visible y listo para mostrar contenido. -
unobscuredBounds
Un rectángulo que define el área dentro de la pantalla del grupo de instrumentos en la que es seguro mostrar contenido. Por ejemplo, áreas cubiertas por diales y medidores.
-
-
- Anule el método
Service#dump()
y presente información de estado útil para la depuración (consulte dumpsys para obtener más información).
Ejemplo de implementación de InstrumentClusterRenderingService
El siguiente ejemplo describe una implementación de InstrumentClusterRenderingService
, que crea una pantalla VirtualDisplay
para presentar el contenido del grupo de instrumentos en una pantalla física remota.
Alternativamente, este código podría pasar el displayId
de una pantalla secundaria física conectada a la HU, si se sabe que hay una 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); } }
Uso de CarAppFocusManager
La API CarAppFocusManager proporciona un método llamado getAppTypeOwner()
, que permite que el servicio de clúster escrito por los OEM sepa qué aplicación de navegación tiene el foco de navegación en un momento dado. Los OEM pueden usar el CarAppFocusManager#addFocusListener()
existente y luego usar getAppTypeOwner()
para saber qué aplicación tiene el foco. Con esta información, los OEM pueden:
- Cambie la actividad que se muestra en el grupo a la actividad del grupo proporcionada por la aplicación de navegación que mantiene el foco.
- Puede detectar si la aplicación de navegación enfocada tiene una actividad de clúster o no. Si la aplicación de navegación enfocada no tiene una actividad de clúster (o si dicha actividad está deshabilitada), los OEM pueden enviar esta señal al DIM del automóvil para que la faceta de navegación del clúster se omita por completo.
Use CarAppFocusManager
para configurar y escuchar el enfoque de la aplicación actual, como la navegación activa o un comando de voz. Por lo general, solo una instancia de dicha aplicación se ejecuta activamente (o está enfocada) en el sistema.
Use el CarAppFocusManager#addFocusListener(..)
para escuchar los cambios de enfoque de la aplicación:
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 }
Utilice el CarAppFocusManager#getAppTypeOwner(..)
para recuperar los nombres de los paquetes del propietario actual de un tipo de aplicación determinado que está enfocado. Este método puede devolver más de un nombre de paquete si el propietario actual usa la función 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 } ...
Apéndice: uso de la aplicación de muestra
AOSP proporciona una aplicación de muestra que implementa la API de estado de navegación.
Para ejecutar esta aplicación de muestra:
- Compile y actualice Android Auto en una HU compatible. Use las instrucciones de compilación y flasheo de Android específicas para su dispositivo. Para obtener instrucciones, consulte Uso de tableros de referencia .
- Conecte una pantalla secundaria física a la HU (si es compatible) o encienda la HU secundaria virtual:
- Selecciona Modo desarrollador en la aplicación Configuración.
- Vaya a Configuración > Sistema > Avanzado > Opciones de desarrollador > Simular pantallas secundarias .
- Reinicie la HU. El servicio ClusterRenderingService está conectado a la pantalla secundaria.
- Para iniciar la aplicación KitchenSink:
- Abre el cajón.
- Ir a Inst. racimo
- Haga clic en INICIAR METADATOS .
KitchenSink solicita el enfoque de NAVEGACIÓN, que indica al servicio DirectRenderingCluster
que muestre una interfaz de usuario simulada en el grupo de instrumentos.