Desenhar mapas

Os apps de navegação, ponto de interesse (PDI) e clima que usam os seguintes modelos podem desenhar mapas acessando um Surface.

Para usar os modelos a seguir, seu app precisa declarar uma dessas permissões correspondentes em um <uses-permission> elemento no AndroidManifest.xml arquivo.

Modelo Permissão Orientação
NavigationTemplate androidx.car.app.NAVIGATION_TEMPLATES Navegação
MapWithContentTemplate

androidx.car.app.NAVIGATION_TEMPLATES

ou

androidx.car.app.MAP_TEMPLATES

Navegação, PDI, clima

MapTemplate

(obsoleto)

androidx.car.app.NAVIGATION_TEMPLATES Navegação

PlaceListNavigationTemplate

(obsoleto)

androidx.car.app.NAVIGATION_TEMPLATES Navegação

RoutePreviewNavigationTemplate

(obsoleto)

androidx.car.app.NAVIGATION_TEMPLATES Navegação

Consulte a implementação de referência

Para conferir uma implementação de referência completa, consulte o exemplo de navegação.

Declarar a permissão de superfície

Além da permissão necessária para o modelo que seu app está usando, ele precisa declarar a permissão androidx.car.app.ACCESS_SURFACE no arquivo AndroidManifest.xml para ter acesso à superfície:

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

Acessar a superfície

Para acessar o Surface fornecido pelo host, implemente um SurfaceCallback e forneça essa implementação ao AppManager serviço de carro. A Surface atual é transmitida ao SurfaceCallback no SurfaceContainer parâmetro dos callbacks onSurfaceAvailable() e onSurfaceDestroyed().

Kotlin

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

Java

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

Usar uma tela virtual para renderizar conteúdo

Além de renderizar diretamente na Surface usando a API Canvas, também é possível renderizar visualizações na Surface usando as APIs VirtualDisplay e Presentation, como mostra este exemplo:

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

Usar o Compose para renderizar na tela virtual

Você pode usar uma ComposeView como a visualização de conteúdo da Presentation. Como a ComposeView é usada fora de uma Activity, confirme se ela ou uma visualização da família propaga um LifecycleOwner e SavedStateRegistryOwner. Para fazer isso, use setViewTreeLifecycleOwner e setViewTreeSavedStateRegistryOwner.

Session já implementa LifecycleOwner. Para atender às duas funções, sua implementação também pode 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()
  }

  ...
}

Entender a área visível da superfície

O host pode desenhar elementos da interface do usuário para os modelos na parte de cima do mapa. Ele chama o SurfaceCallback.onVisibleAreaChanged método para comunicar a área da superfície com maior probabilidade de não estar obstruída e visível para o usuário.

Para minimizar o número de mudanças, o host chama o SurfaceCallback.onStableAreaChanged método com o menor retângulo, que sempre fica visível de acordo com o modelo atual.

Por exemplo, quando um app de navegação usa o NavigationTemplate com uma faixa de ação na parte de cima, para criar mais espaço na tela, a faixa de ação pode ser ocultada quando o usuário não interage com a tela. Esse caso resulta em um callback para onStableAreaChanged e onVisibleAreaChanged com o mesmo retângulo.

Quando a faixa de ação está oculta, somente onVisibleAreaChanged é chamado com a área maior. Se o usuário interagir com a tela, apenas onVisibleAreaChanged será chamado com o primeiro retângulo.

Suporte ao tema escuro

Os apps precisam redesenhar o mapa na instância de Surface com as cores escuras adequadas quando o host determina que as condições justificam esse uso, conforme descrito em Qualidade do app Android para carros.

Para desenhar um mapa escuro, use o CarContext.isDarkMode método. Quando o status do tema escuro muda, você recebe uma chamada para Session.onCarConfigurationChanged.

Desenhar mapas na tela do cluster

Além de desenhar mapas na tela principal, os apps de navegação também podem oferecer suporte ao desenho de mapas na tela do cluster atrás do volante. Para saber mais, consulte Como desenhar na tela do cluster.