Las apps de navegación, de lugares de interés (POI) y del clima que usan las siguientes plantillas pueden dibujar mapas accediendo a un Surface.
Para usar las siguientes plantillas, tu app debe declarar uno de estos permisos correspondientes en un elemento <uses-permission> en el archivo AndroidManifest.xml.
| Plantilla | Permiso | Orientación |
|---|---|---|
NavigationTemplate |
androidx.car.app.NAVIGATION_TEMPLATES |
Navegación |
MapWithContentTemplate |
o
|
Navigation, POI, Weather |
|
(obsoleto) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navegación |
|
(obsoleto) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navegación |
(obsoleto) |
androidx.car.app.NAVIGATION_TEMPLATES |
Navegación |
Consulta la implementación de referencia
Para ver una implementación de referencia completa, consulta el ejemplo de Navigation.
Declara el permiso de superficie
Además del permiso requerido para la plantilla que usa tu app, esta debe declarar el permiso androidx.car.app.ACCESS_SURFACE en su archivo AndroidManifest.xml para obtener acceso a la plataforma:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
...
</manifest>
Accede a la superficie
Para acceder al Surface que proporciona el host, debes implementar un SurfaceCallback y proporcionar esa implementación al servicio de automóvil AppManager. El Surface actual se pasa a tu SurfaceCallback en el parámetro SurfaceContainer de las devoluciones de llamada onSurfaceAvailable() y onSurfaceDestroyed().
Kotlin
carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)
Java
carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);
Cómo usar una pantalla virtual para renderizar contenido
Además de renderizar directamente en el Surface con la API de Canvas, también puedes renderizar Views en el Surface con las APIs de VirtualDisplay y Presentation, como se muestra en este ejemplo:
class HelloWorldSurfaceCallback(context: Context) : SurfaceCallback {
lateinit var virtualDisplay: VirtualDisplay
lateinit var presentation: Presentation
override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
virtualDisplay = context
.getSystemService(DisplayManager::class.java)
.createVirtualDisplay(
VIRTUAL_DISPLAY_NAME ,
surfaceContainer.width,
surfaceContainer.height,
surfaceContainer.dpi,
surfaceContainer.surface,
0
)
presentation = Presentation(context, virtualDisplay.display)
// Instantiate the view to be used as the content view
val view = ...
presentation.setContentView(view)
presentation.show()
}
override fun onSurfaceDestroyed(surfaceContainer: SurfaceContainer) {
presentation.dismiss()
// This handles releasing the Surface provided when creating the VirtualDisplay
virtualDisplay.release()
}
}
Usa Compose para renderizar en la pantalla virtual
Puedes usar un ComposeView como vista de contenido del Presentation. Como ComposeView se usa fuera de una actividad, confirma que este o una vista principal propaguen un LifecycleOwner y un SavedStateRegistryOwner. Para ello, usa setViewTreeLifecycleOwner y setViewTreeSavedStateRegistryOwner.
Session ya implementa LifecycleOwner. Para cumplir con ambos roles, tu implementación también puede implementar SavedStateRegistryOwner.
class HelloWorldSession() : Session(), SavedStateRegistryOwner { ... }
class HelloWorldSurfaceCallback(session: HelloWorldSession) : SurfaceCallback {
...
override fun onSurfaceAvailable(surfaceContainer: SurfaceContainer) {
...
val view = ComposeView(session.carContext)
view.setViewTreeLifecycleOwner(session)
view.setViewTreeSavedStateRegistryOwner(session)
view.setContent {
// Composable content
}
presentation.setContentView(view)
presentation.show()
}
...
}
Comprende el área visible de la superficie
El host puede dibujar elementos de la interfaz de usuario para las plantillas en la parte superior del mapa.
El host llama al método SurfaceCallback.onVisibleAreaChanged para comunicar el área de la superficie que es más probable que no esté obstruida y que sea visible para el usuario.
Para minimizar la cantidad de cambios, el host llama al método SurfaceCallback.onStableAreaChanged con el rectángulo más pequeño, que siempre está visible según la plantilla actual.
Por ejemplo, cuando una app de navegación usa la NavigationTemplate con una barra de acción en la parte superior, para dejar más espacio en la pantalla, la barra de acción se puede ocultar cuando el usuario no interactúa con la pantalla. En este caso, se genera una devolución de llamada a onStableAreaChanged y onVisibleAreaChanged con el mismo rectángulo.
Cuando la barra de acciones está oculta, solo se llama a onVisibleAreaChanged con el área más grande. Si el usuario interactúa con la pantalla, solo se llamará a onVisibleAreaChanged con el primer rectángulo.
Admite el tema oscuro
Las apps deben volver a dibujar su mapa en la instancia de Surface con los colores oscuros apropiados cuando el host determine que las condiciones lo requieren, como se describe en Calidad de las apps para Android para vehículos.
Para dibujar un mapa oscuro, usa el método CarContext.isDarkMode. Cuando cambia el estado del tema oscuro, recibes una llamada a Session.onCarConfigurationChanged.
Cómo dibujar mapas en la pantalla del clúster
Además de dibujar mapas en la pantalla principal, las apps de navegación también pueden dibujar mapas en la pantalla del clúster detrás del volante. Para obtener más información, consulta Cómo dibujar en la pantalla del clúster.