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 elemento <uses-permission> no arquivo AndroidManifest.xml.

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, Ponto de interesse, Clima

MapTemplate

(descontinuado)

androidx.car.app.NAVIGATION_TEMPLATES Navegação

PlaceListNavigationTemplate

(descontinuado)

androidx.car.app.NAVIGATION_TEMPLATES Navegação

RoutePreviewNavigationTemplate

(descontinuado)

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 exibição

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 à plataforma:

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

Acessar a plataforma

Para acessar o Surface fornecido pelo host, implemente um SurfaceCallback e forneça essa implementação ao serviço de carro AppManager. O Surface atual é transmitido para seu SurfaceCallback no parâmetro SurfaceContainer 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 no Surface usando a API Canvas, você também pode renderizar Views no 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 um ComposeView como a visualização de conteúdo do Presentation. Como ComposeView é usado fora de uma atividade, confirme se ele ou uma visualização principal propaga um LifecycleOwner e um SavedStateRegistryOwner. Para 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. O host chama o método SurfaceCallback.onVisibleAreaChanged para comunicar a área da superfície que provavelmente não estará obstruída e visível para o usuário.

Para minimizar o número de mudanças, o host chama o método SurfaceCallback.onStableAreaChanged 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 liberar mais espaço na tela, a faixa de ação pode ser ocultada quando o usuário não interage com a tela. Nesse caso, há 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.

Oferecer suporte ao tema escuro

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

Para desenhar um mapa escuro, use o método CarContext.isDarkMode. 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 desenhar mapas na tela do cluster atrás do volante. Para saber mais, consulte Desenhar na tela do cluster.