Dessiner des cartes

Les applications de navigation, de points d'intérêt (POI) et météo qui utilisent les modèles suivants peuvent dessiner des cartes en accédant à une Surface.

Pour utiliser les modèles suivants, votre application doit déclarer l'une de ces autorisations correspondantes dans un élément <uses-permission> du fichier AndroidManifest.xml.

Template Autorisation Conseils
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES Navigation
MapWithContentTemplate

androidx.car.app.NAVIGATION_TEMPLATES

androidx.car.app.MAP_TEMPLATES

Navigation, POI, Weather

MapTemplate

(Obsolète)

androidx.car.app.NAVIGATION_TEMPLATES Navigation

PlaceListNavigationTemplate

(Obsolète)

androidx.car.app.NAVIGATION_TEMPLATES Navigation

RoutePreviewNavigationTemplate

(Obsolète)

androidx.car.app.NAVIGATION_TEMPLATES Navigation

Consulter l'implémentation de référence

Pour afficher une implémentation de référence complète, consultez l'exemple de navigation.

Déclarer l'autorisation de surface

En plus de l'autorisation requise pour le modèle utilisé par votre application, celle-ci doit déclarer l'autorisation androidx.car.app.ACCESS_SURFACE dans son fichier AndroidManifest.xml pour accéder à la surface :

<manifest ...>
  ...
  <uses-permission android:name="androidx.car.app.ACCESS_SURFACE" />
  ...
</manifest>

Accéder à la plate-forme

Pour accéder à Surface fourni par l'hôte, vous devez implémenter un SurfaceCallback et fournir cette implémentation au service automobile AppManager. Le Surface actuel est transmis à votre SurfaceCallback dans le paramètre SurfaceContainer des rappels onSurfaceAvailable() et onSurfaceDestroyed().

Kotlin

carContext.getCarService(AppManager::class.java).setSurfaceCallback(surfaceCallback)

Java

carContext.getCarService(AppManager.class).setSurfaceCallback(surfaceCallback);

Utiliser un écran virtuel pour afficher du contenu

En plus d'effectuer le rendu directement dans Surface à l'aide de l'API Canvas, vous pouvez également effectuer le rendu des vues dans Surface à l'aide des API VirtualDisplay et Presentation, comme le montre cet exemple :

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()
  }
}

Utiliser Compose pour effectuer le rendu sur l'écran virtuel

Vous pouvez utiliser un ComposeView comme vue de contenu du Presentation. Étant donné que ComposeView est utilisé en dehors d'une activité, vérifiez qu'il propage un LifecycleOwner et un SavedStateRegistryOwner, ou qu'une vue parente le fait. Pour ce faire, utilisez setViewTreeLifecycleOwner et setViewTreeSavedStateRegistryOwner.

Session implémente déjà LifecycleOwner. Pour remplir les deux rôles, votre implémentation peut également implémenter 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()
  }

  ...
}

Comprendre la zone visible de la surface

L'hôte peut dessiner des éléments d'interface utilisateur pour les modèles situés au-dessus de la carte. L'hôte appelle la méthode SurfaceCallback.onVisibleAreaChanged pour communiquer la zone de la surface la plus susceptible d'être non masquée et visible par l'utilisateur.

Pour minimiser le nombre de modifications, l'hôte appelle la méthode SurfaceCallback.onStableAreaChanged avec le plus petit rectangle, qui est toujours visible en fonction du modèle actuel.

Par exemple, lorsqu'une application de navigation utilise le NavigationTemplate avec une bande d'actions en haut, celle-ci peut être masquée lorsque l'utilisateur n'a pas interagi avec l'écran afin de libérer de l'espace. Dans ce cas, un rappel de onStableAreaChanged et onVisibleAreaChanged est effectué avec le même rectangle.

Lorsque la bande d'actions est masquée, seul onVisibleAreaChanged est appelé avec la plus grande zone. Si l'utilisateur interagit avec l'écran, seul onVisibleAreaChanged est appelé avec le premier rectangle.

Prendre en charge le thème sombre

Les applications doivent redessiner leur carte sur l'instance Surface avec les couleurs sombres appropriées lorsque l'hôte détermine que les conditions le justifient, comme décrit dans Qualité des applications Android pour les voitures.

Pour dessiner une carte sombre, utilisez la méthode CarContext.isDarkMode. Chaque fois que l'état du thème sombre change, vous recevez un appel de Session.onCarConfigurationChanged.

Dessiner des cartes sur l'écran du cluster

En plus de dessiner des cartes sur l'écran principal, les applications de navigation peuvent également dessiner des cartes sur l'écran du combiné d'instruments derrière le volant. Pour en savoir plus, consultez Dessiner sur l'écran du cluster.