Usar la API de Instrument Cluster (una API de Android) para mostrar apps de navegación
incluido Google Maps, en una pantalla secundaria de un automóvil, como detrás del
el volante en el panel de instrumentos. En esta página, se describe cómo crear un
para controlar esa pantalla secundaria e integrar el servicio con
CarService
para que las apps de navegación puedan mostrar una
interfaz de usuario.
Terminología
En esta página, se usan los siguientes términos.
CarManager
que permite que apps externas inicien una actividad en
el clúster de instrumentos y recibir devoluciones de llamada cuando esté listo para mostrarse.
de datos.android:singleUser
. En
en un momento dado, como máximo, una instancia del servicio se ejecuta en el sistema Android.Requisitos previos
Antes de continuar, asegúrate de tener estos elementos:
- Entorno de desarrollo de Android. Para configurar la app de Android entorno de desarrollo, consulta Requisitos de compilación.
- Descarga el código fuente de Android. Obtén la última versión de el código fuente de Android de la rama pi-car-release (o una versión posterior) en https://android.googlesource.com
- Unidad central (HU). Un dispositivo Android capaz de ejecutar Android 9 (o versiones posteriores) Este dispositivo debe tener su propia pantalla y ser capaz de escribir en la pantalla con nuevas compilaciones de Android.
- El clúster de instrumentos es una de las siguientes opciones:
- Pantalla física secundaria conectada al HU Si el botón el hardware del dispositivo y el kernel admiten la administración de varias pantallas.
- Unidad independiente. Cualquier unidad de procesamiento conectada al HU a través de una conexión de red, capaz de recibir y mostrar una transmisión de video por Internet en su propia pantalla.
- Pantalla emulada. Durante el desarrollo, puedes usar uno de
estos entornos emulados:
- Pantallas secundarias simuladas. Para habilitar una simulación pantalla secundaria en cualquier distribución de AOSP para Android, ve a Opciones para desarrolladores la configuración en la app del sistema Settings y, luego, selecciona inversión secundaria pantallas Esta configuración es equivalente a conectar una secundaria física gráfico principal, con la limitación de que este se superponga pantalla.
- Clúster de instrumentos emulado: El emulador de Android incluido con AAOS proporciona una opción para mostrar un clúster de instrumentos con ClusterRenderingService.
Arquitectura de la integración
Componentes de integración
Cualquier integración de la API de Instrument Cluster consta de estos tres componentes:
CarService
- Apps de navegación
- Servicio de clústeres de instrumentos de OEM
CarService
CarService
media entre las apps de navegación y el automóvil, lo que garantiza que solo
una app de navegación está activa en un momento dado y solo las apps con el
El permiso android.car.permission.CAR_INSTRUMENT_CLUSTER_CONTROL
puede enviar datos
al automóvil.
CarService
inicia todos los servicios específicos del vehículo y proporciona acceso a
estos servicios
a través de una serie de administradores. Para interactuar con los servicios,
las apps que se ejecutan en el vehículo pueden acceder a estos administradores.
Para la implementación de clústeres de instrumentos, los OEM de la industria automotriz deben crear un clúster personalizado implementación de InstrumentClusterRendererService y actualiza el ClusterRenderingService.
Cuando se renderiza un clúster de instrumentos, durante el proceso de inicio, el
CarService
lee la clave InstrumentClusterRendererService
de la
ClusterRenderingService
para ubicar una implementación de InstrumentClusterService
. En el AOSP, esta entrada
apunta al servicio de renderización de la implementación de clústeres de muestra de la API de Navigation State:
<string name="instrumentClusterRendererService"> android.car.cluster/.ClusterRenderingService </string>
El servicio al que se hace referencia en esta entrada se inicializa y se vincula a
CarService
Cuando las apps de navegación, como Google Maps, solicitan un
CarInstrumentClusterManager
, CarService
proporciona un administrador que
actualiza el estado del clúster de instrumentos desde el InstrumentClusterRenderingService
vinculado.
(En este caso, bound se refiere a
En Android
Servicios).
Servicio del clúster de instrumentos
Los OEMs deben crear un paquete de Android (APK) que contenga una subclase de ClusterRenderingService.
Esta clase tiene dos propósitos:
- Proporciona una interfaz para Android y el dispositivo de renderización del clúster de instrumentos (el propósito de esta página).
- Recibe y renderiza actualizaciones del estado de navegación, como las instrucciones paso a paso la guía de navegación.
En primer lugar, las implementaciones de OEM de InstrumentClusterRendererService
debes inicializar la pantalla secundaria que se usa para renderizar la información en las pantallas de la cabina del vehículo y
comunicarle esta información a CarService
llamando al
InstrumentClusterRendererService.setClusterActivityOptions()
y
InstrumentClusterRendererService.setClusterActivityState()
.
Para la segunda función, el servicio de clúster de instrumentos debe proporcionar un
implementación del
ClusterRenderingService
que recibe eventos de actualización de estado de navegación, que están codificados como un
eventType
y datos de eventos codificados en un paquete.
Secuencia de integración
En el siguiente diagrama, se ilustra la implementación de un estado de navegación que procesa actualizaciones:
En esta ilustración, los colores denotan lo siguiente:
- Amarillo.
CarService
yCarNavigationStatusManager
que proporciona la plataforma de Android. Para obtener más información, consulta Automóvil y CAR_NAVIGATION_SERVICE. - Cian. Se implementaron
InstrumentClusterRendererService
por el OEM. - Púrpura. La app de Navigation implementada por Google y terceros desarrolladores.
- verde.
CarAppFocusManager
. Para obtener más información, consulta Cómo usar la API de CarAppFocusManager a continuación y CarAppFocusManager.
El flujo de información del estado de navegación sigue esta secuencia:
CarService
inicializaInstrumentClusterRenderingService
.- Durante la inicialización,
InstrumentClusterRenderingService
se actualizaCarService
con:- Propiedades de pantalla del clúster de instrumentos, como límites claros (obtén más detalles sobre los límites visibles más adelante).
- Opciones de actividad necesarias para iniciar actividades dentro de la pantalla del clúster de instrumentos. Para obtener más información, consulta ActivityOptions.
- Una app de navegación (como Google Maps para Android Automotive o cualquier app de mapas)
con los permisos necesarios):
- Obtiene un
CarAppFocusManager
con la clase Car de car-lib. - Antes de que comiencen las indicaciones paso a paso, llama a
CarAppFocusManager.requestFocus()
para aprobarCarAppFocusManager.APP_FOCUS_TYPE_NAVIGATION
comoappType
parámetro.
- Obtiene un
CarAppFocusManager
comunica esta solicitud aCarService
. Si se otorga,CarService
inspecciona el paquete de la app de navegación y localiza un actividad marcada con la categoríaandroid.car.cluster.NAVIGATION
.- Si lo encuentra, la app de navegación usa el
ActivityOptions
que informa laInstrumentClusterRenderingService
para iniciar la actividad e incluye el elemento Instrumenta las propiedades de visualización del clúster como extras en el intent.
Integra la API
La implementación de InstrumentClusterRenderingService
debe hacer lo siguiente:
- Agregarás el siguiente valor a
el archivo AndroidManifest.xml. Esto es necesario para garantizar que una única copia del
Se ejecuta el servicio del clúster de instrumentos, incluso durante la inicialización y el cambio de usuario:
android:singleUser="true"
- Conserva el permiso del sistema
BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE
. Esta garantiza que solo el servicio de renderización del clúster de instrumentos se incluya de la imagen del sistema Android se vincula alguna vez aCarService
:<uses-permission android:name="android.car.permission.BIND_INSTRUMENT_CLUSTER_RENDERER_SERVICE"/>
Cómo implementar InstrumentClusterRenderingService
Para compilar el servicio, sigue estos pasos:
- Escribe una clase que se extienda de
ClusterRenderingService
y, luego, agrega la entrada correspondiente a tu archivo
AndroidManifest.xml
. Esta clase controla la pantalla del clúster de instrumentos y puede (opcional) renderizar el estado de navegación de Google Cloud. - Durante
onCreate()
, usa este servicio para inicializar la comunicación con el el hardware de procesamiento. Se incluyen las siguientes opciones:- Determina la pantalla secundaria que se usará para el clúster de instrumentos.
- Crea una pantalla virtual para que la app del clúster de instrumentos renderice y transmita el renderizada en una unidad externa (con un formato de transmisión de video por Internet, como H.264)
- Cuando la pantalla indicada anteriormente esté lista, este servicio debe llamar
InstrumentClusterRenderingService#setClusterActivityLaunchOptions()
para definir elActivityOptions
exacto que se debe usar para mostrar una actividad en la Clúster de instrumentos. Usa estos parámetros:category.
ClusterRenderingServiceActivityOptions.
: Es una instanciaActivityOptions
que se puede que se usa para iniciar una actividad en el clúster de instrumentos. Por ejemplo, a partir de la muestra Implementación del clúster de instrumentos en AOSP:getService().setClusterActivityLaunchOptions( CATEGORY_NAVIGATION, ActivityOptions.makeBasic() .setLaunchDisplayId(displayId));
- Cuando el clúster de instrumentos esté listo para mostrar actividades, este servicio debe invocar
InstrumentClusterRenderingService#setClusterActivityState()
Usar estas opciones parámetros:category
ClusterRenderingServicestate
Paquete generado con ClusterRenderingService Asegúrate de proporcionar estos datos:visible
: Especifica el clúster de instrumentos como visible y listo para mostrar contenido.unobscuredBounds
Es un rectángulo que define el área dentro del Pantalla del clúster de instrumentos en la que es seguro mostrar contenido. Por ejemplo, las áreas cubiertos por diales y medidores.
- Anula el método
Service#dump()
y proporciona información de estado útil para lo siguiente: depuración (consulta dumpsys para obtener más información).
Ejemplo de implementación de InstrumentClusterRenderingService
En el siguiente ejemplo, se muestra a grandes rasgos un InstrumentClusterRenderingService
implementación, que crea un VirtualDisplay
para presentar el objeto Instrument.
Agrupa contenido en una pantalla física remota.
Como alternativa, este código podría pasar el displayId
de una secundaria física
conectada al HU, si se sabe que hay uno 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 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); } }
Usa la API de CarAppFocusManager
La API de CarAppFocusManager proporciona un método llamado getAppTypeOwner()
, que permite
El servicio de clúster escrito por los OEMs para saber qué app de navegación tiene enfoque de navegación en un determinado
tiempo. Los OEM pueden usar el método CarAppFocusManager#addFocusListener()
existente.
Luego, usa getAppTypeOwner()
para conocer qué app se enfoca. Con esta información,
Los OEM pueden hacer lo siguiente:
- Cambia la actividad que se muestra en el clúster a la que proporciona la app de navegación manteniendo el foco.
- Puede detectar si la app de navegación enfocada tiene o no una actividad de clúster. Si el enfoque no tiene una actividad de clúster (o, si esa actividad está inhabilitada), los OEMs pueden enviar esta señal al DIM del vehículo para que se omita por completo la faceta de navegación del clúster.
Usa CarAppFocusManager
para establecer y escuchar el enfoque actual de la app, por ejemplo,
la navegación activa o un comando por voz. Por lo general, solo una instancia de esa app está activa
que se ejecutan (o enfocados) en el sistema.
Usa el método CarAppFocusManager#addFocusListener(..)
para escuchar el enfoque de la app
cambios:
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 }
Usa el método CarAppFocusManager#getAppTypeOwner(..)
para recuperar el paquete.
nombres del propietario actual de un tipo de aplicación determinado que se enfoca. Este método puede mostrar
más de un nombre de paquete si el propietario actual utiliza 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 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 } ...
Apéndice: Usa la app de ejemplo
AOSP proporciona una app de ejemplo que implementa la API de Navigation State.
Para ejecutar esta app de ejemplo, haz lo siguiente:
- Compila y escribe Android Auto en la memoria flash en un HU compatible. Usa el Instrucciones de compilación y escritura en la memoria flash de Android específicas para tu dispositivo Para obtener instrucciones, consulta Cómo usar las placas de referencia.
- Conecta una pantalla secundaria física al HU (si es compatible) o activa el modo
HU secundario:
- Selecciona Modo de desarrollador en la app de Configuración.
- Ve a Configuración > Sistema > Avanzado > Opciones para desarrolladores > Simula pantallas secundarias.
- Reinicia el HU
- Sigue estos pasos para iniciar la app KitchenSink:
- Abre el panel lateral.
- Vaya a Inst. Clúster.
- Haz clic en INICIAR METADATOS.
KitchenSink solicita el foco de NAVIGATION, que le indica a DirectRenderingCluster
.
para mostrar una interfaz de usuario simulada en el clúster de instrumentos.