Adicionar um mapa 3D ao seu app

Selecionar plataforma: Android iOS JavaScript

Um mapa 3D mostrando a cidade de Nova York

Esta página mostra um exemplo de como adicionar um mapa 3D básico a um app Android usando o SDK do Maps 3D para Android. As instruções nesta página pressupõem que você já concluiu as etapas na página de configuração e tem o seguinte:

  • Um projeto na nuvem do Google Cloud com o SDK do Maps 3D para Android ativado
  • Uma chave de API configurada para uso com o SDK do Maps 3D para Android
  • Um projeto do Android Studio configurado para uso com o SDK do Maps 3D para Android

Para mais informações sobre esses pré-requisitos, consulte Configuração.

Parte 1: atualizar o arquivo de layout (activity_main.xml) para adicionar o componente Map3DView

O componente Map3DView é a visualização que renderiza o mapa 3D no app. As etapas a seguir adicionam o componente e configuram o estado inicial do mapa, incluindo a posição da câmera e os atributos relacionados:

  1. Abra o arquivo de layout da atividade principal, que geralmente está localizado em app/src/main/res/layout/activity_main.xml.

  2. Na raiz ConstraintLayout (ou no elemento de layout raiz), adicione o namespace XML map3d:

    xmlns:map3d="http://schemas.android.com/apk/res-auto"
    
  3. Exclua o <TextView> padrão que mostra "Hello World!".

  4. Adicione o componente Map3DView ao layout. É possível personalizar a posição da câmera e outros atributos:

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:app="http://schemas.android.com/apk/res-auto"
      xmlns:map3d="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"
      android:id="@+id/main"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      tools:context=".MainActivity">
    
      <com.google.android.gms.maps3d.Map3DView
        android:id="@+id/map3dView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        map3d:mode="hybrid"
        map3d:centerLat="38.544012"
        map3d:mode="hybrid"
        map3d:centerLng="-107.670428"
        map3d:centerAlt="2427.6"
        map3d:heading="310"
        map3d:tilt="63"
        map3d:range="8266"
        map3d:roll="0"
        map3d:minAltitude="0"
        map3d:maxAltitude="1000000"
        map3d:minHeading="0"
        map3d:maxHeading="360"
        map3d:minTilt="0"
        map3d:maxTilt="90"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
    

Parte 2: atualizar o MainActivity.kt

As etapas a seguir inicializam o componente Map3DView adicionado ao arquivo activity_main.xml na Parte 1 e gerenciam eventos de ciclo de vida do componente.

O SDK do Maps 3D para Android oferece suporte a apenas uma instância Map3DView ativa por vez. A exibição de várias instâncias Map3DView simultaneamente (por exemplo, no mesmo layout ou em atividades ou fragmentos visíveis diferentes) não é compatível e pode levar a problemas de renderização, como telas pretas em visualizações secundárias.

Além disso, todos os Map3DView vão compartilhar e refletir o mesmo estado do mapa (por exemplo, posição da câmera, marcadores adicionados, polígonos etc.), que vai persistir mesmo que um Map3DView seja destruído (usando onDestroy) e outro seja criado, a menos que seja limpo manualmente. Por exemplo, se você adicionar marcadores ao Map3DView1, destruí-lo e criar Map3DView2, esses mesmos marcadores ainda estarão presentes no Map3DView2.

Responsabilidades do desenvolvedor:

  • Uma visualização por vez:garanta que apenas um Map3DView esteja em uma parte ativa da hierarquia de visualização a qualquer momento.
  • Limpeza manual: ao alternar de um Map3DView (por exemplo, Map3DView1) para outro (por exemplo, Map3DView2), chame onDestroy() na instância antiga (Map3DView1). Como o estado do mapa subjacente é compartilhado, para garantir que Map3DView2 comece com um estado novo ou específico, você é responsável por limpar manualmente qualquer estado definido por Map3DView1. Isso inclui remover marcadores, sobreposições etc. e redefinir a posição da câmera usando o objeto GoogleMap3D obtido no OnMap3DViewReadyCallback.
  1. Abra o arquivo MainActivity.kt, que geralmente está localizado em app/src/main/java/com/example/yourpackagename/MainActivity.kt.

  2. Adicione as importações necessárias para o SDK do Maps 3D para Android:

    import android.util.Log
    import com.google.android.gms.maps3d.GoogleMap3D
    import com.google.android.gms.maps3d.Map3DView
    import com.google.android.gms.maps3d.OnMap3DViewReadyCallback
    
  3. Modifique a classe MainActivity para implementar OnMap3DViewReadyCallback:

    class MainActivity : AppCompatActivity(), OnMap3DViewReadyCallback {
    
  4. Declare variáveis para Map3DView e GoogleMap3D:

    private lateinit var map3DView: Map3DView
    private var googleMap3D: GoogleMap3D? = null
    
  5. No método onCreate, depois de setContentView(...) e do bloco ViewCompat.setOnApplyWindowInsetsListener, inicialize o map3DView, chame o método de ciclo de vida onCreate e solicite o mapa de forma assíncrona:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
    
        map3DView = findViewById(R.id.map3dView)
        map3DView.onCreate(savedInstanceState)
        map3DView.getMap3DViewAsync(this)
    }
    
  6. Substitua os métodos onMap3DViewReady e onError. Esses callbacks são acionados quando o mapa está pronto para ser usado ou quando ocorre um erro durante a inicialização:

    override fun onMap3DViewReady(googleMap3D: GoogleMap3D) {
        // Interact with the googleMap3D object here
        this.googleMap3D = googleMap3D
        // You can now make calls to the googleMap3D object, e.g.,
        // googleMap3D.cameraController.flyTo(camera { ... })
    }
    
    override fun onError(error: Exception) {
        // Handle the error gracefully here (for example, show an error dialog or log the error).
        Log.e("MainActivity", "Error loading 3D map", error)
    }
    
  7. Encaminhe eventos de ciclo de vida da sua atividade para o Map3DView adicionando as seguintes substituições ao MainActivity:

    override fun onStart() {
        super.onStart()
        map3DView.onStart()
    }
    
    override fun onResume() {
        super.onResume()
        map3DView.onResume()
    }
    
    override fun onPause() {
        map3DView.onPause()
        super.onPause()
    }
    
    override fun onStop() {
        map3DView.onStop()
        super.onStop()
    }
    
    override fun onDestroy() {
        map3DView.onDestroy()
        super.onDestroy()
    }
    
    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        map3DView.onSaveInstanceState(outState)
    }
    
    override fun onLowMemory() {
        super.onLowMemory()
        map3DView.onLowMemory()
    }
    

Parte 3: sincronizar o Gradle e executar

Agora que você atualizou o layout e a atividade do app, é possível criar e executar o app para conferir a visualização do mapa 3D.

  1. Para sincronizar seu projeto com o Gradle, selecione File > Sync Project with Gradle Files.

  2. Para criar e executar seu app em um emulador ou dispositivo físico, selecione Run > Run.

Se tudo estiver configurado corretamente, você verá um mapa 3D exibido no app, centralizado perto das coordenadas especificadas no activity_main.xml.

Estados de erro e carregamento do mapa

O SDK do Maps 3D para Android mostra automaticamente um feedback visual integrado ao gerenciar o estado do mapa:

  • Sobreposição de carregamento:um indicador de progresso centralizado é mostrado quando a visualização do mapa é inicializada ou carrega a janela de visualização inicial.
  • Sobreposição de erro:um card de erro estilizado é mostrado se ocorrer uma falha crítica, como uma chave de API inválida, um erro de rede ou ao executar em um dispositivo não compatível.

É possível capturar esses erros de inicialização ou carregamento de forma programática substituindo onError(error: Exception) na implementação de OnMap3DViewReadyCallback.

Detectar eventos de clique no mapa

Para detectar eventos de clique no mapa, use GoogleMap3D.setMap3DClickListener. Esse listener é acionado quando um usuário clica no mapa e fornece o local e o ID do lugar do ponto clicado.

O exemplo a seguir mostra como definir um listener de clique no mapa:

googleMap3D.setMap3DClickListener { location, placeId ->
    lifecycleScope.launch(Dispatchers.Main) {
        if (placeId != null) {
            Toast.makeText(this@MainActivity, "Clicked on place with ID: $placeId", Toast.LENGTH_SHORT).show()
        } else {
            Toast.makeText(this@MainActivity, "Clicked on location: $location", Toast.LENGTH_SHORT).show()
        }
    }
}

O gerenciador de cliques não é executado na linha de execução principal (ou de interface). Se você quiser fazer mudanças na interface (como mostrar uma mensagem Toast), mude para a linha de execução principal. Para Kotlin, você pode fazer isso usando lifecycleScope.launch(Dispatchers.Main).

Próximas etapas

Agora que você adicionou um mapa 3D básico ao seu app, é possível explorar recursos mais avançados do SDK do Maps 3D para Android, como animações de caminho da câmera, marcadores 3D, ou polígonos.