Dodawanie mapy 3D do aplikacji

Wybierz platformę: Android iOS JavaScript

Mapa 3D przedstawiająca Nowy Jork

Na tej stronie znajdziesz przykład dodawania podstawowej mapy 3D do aplikacji na Androida za pomocą pakietu Maps 3D SDK na Androida. Instrukcje na tej stronie zakładają, że masz już za sobą kroki opisane na stronie Konfiguracja i masz następujące:

  • projekt Google Cloud z włączonym pakietem Maps 3D SDK na Androida,
  • klucz interfejsu API skonfigurowany do używania z pakietem Maps 3D SDK na Androida,
  • projekt Android Studio skonfigurowany do używania z pakietem Maps 3D SDK na Androida.

Więcej informacji o tych wymaganiach wstępnych znajdziesz w sekcji Konfiguracja.

Część 1. Zaktualizuj plik układu (activity_main.xml), aby dodać komponent Map3DView

Komponent Map3DView to widok, który renderuje mapę 3D w aplikacji. Poniższe kroki dodają komponent i konfigurują stan początkowy mapy, w tym położenie kamery i powiązane atrybuty:

  1. Otwórz plik układu głównego działania, który zwykle znajduje się w app/src/main/res/layout/activity_main.xml.

  2. W głównym elemencie ConstraintLayout (lub głównym elemencie układu) dodaj przestrzeń nazw XML map3d:

    xmlns:map3d="http://schemas.android.com/apk/res-auto"
    
  3. Usuń domyślny element <TextView>, który wyświetla „Hello World!”.

  4. Dodaj do układu komponent Map3DView. Możesz dostosować położenie kamery i inne atrybuty:

    <?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>
    

Część 2. Zaktualizuj plik MainActivity.kt

Poniższe kroki inicjują komponent Map3DView dodany do pliku activity_main.xml w części 1 i zarządzają zdarzeniami cyklu życia komponentu.

Pamiętaj, że pakiet Maps 3D SDK na Androida obsługuje tylko 1 aktywną Map3DView instancję naraz. Wyświetlanie kilku instancji Map3DView jednocześnie (np. w tym samym układzie lub w różnych widocznych działaniach lub fragmentach) nie jest obsługiwane i może powodować problemy z renderowaniem, takie jak czarne ekrany w widokach dodatkowych.

Ponadto wszystkie instancje Map3DView będą współdzielić i odzwierciedlać ten sam stan mapy (np. położenie kamery, dodane znaczniki, wielokąty itp.), który będzie się utrzymywać nawet wtedy, gdy jedna instancja Map3DView zostanie zniszczona (za pomocą onDestroy) i utworzona zostanie inna, chyba że zostanie ręcznie wyczyszczona. Jeśli na przykład dodasz znaczniki do Map3DView1, a następnie zniszczysz ją i utworzysz Map3DView2, te same znaczniki będą nadal widoczne w Map3DView2.

Obowiązki dewelopera:

  • Jeden widok naraz: upewnij się, że w danym momencie tylko 1 instancja Map3DView znajduje się w aktywnej części hierarchii widoków.
  • Ręczne czyszczenie: gdy przełączasz się z jednej instancji Map3DView (np. Map3DView1) na inną (np. Map3DView2), musisz wywołać onDestroy() w starej instancji (Map3DView1). Ponieważ stan mapy jest współdzielony, aby mieć pewność, że Map3DView2 zaczyna się od nowego lub określonego stanu, musisz ręcznie wyczyścić każdy stan ustawiony przez Map3DView1. Obejmuje to usuwanie znaczników, nakładek itp. oraz resetowanie położenia kamery za pomocą obiektu GoogleMap3D uzyskanego w OnMap3DViewReadyCallback.
  1. Otwórz plik MainActivity.kt, który zwykle znajduje się w app/src/main/java/com/example/yourpackagename/MainActivity.kt.

  2. Dodaj niezbędne importy dla pakietu Maps 3D SDK na Androida:

    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. Zmodyfikuj klasę MainActivity, aby zaimplementować OnMap3DViewReadyCallback:

    class MainActivity : AppCompatActivity(), OnMap3DViewReadyCallback {
    
  4. Zadeklaruj zmienne dla Map3DView i GoogleMap3D:

    private lateinit var map3DView: Map3DView
    private var googleMap3D: GoogleMap3D? = null
    
  5. W metodzie onCreate po setContentView(...) i bloku ViewCompat.setOnApplyWindowInsetsListener zainicjuj map3DView, wywołaj jego metodę cyklu życia onCreate i asynchronicznie poproś o mapę:

    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. Zastąp metody onMap3DViewReady i onError. Te wywołania zwrotne są wywoływane, gdy mapa jest gotowa do użycia lub gdy podczas inicjowania wystąpi błąd:

    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. Przekaż zdarzenia cyklu życia z działania do Map3DView, dodając te zastąpienia do 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()
    }
    

Część 3. Zsynchronizuj Gradle i uruchom

Teraz, gdy zaktualizujesz układ i działanie aplikacji, możesz ją skompilować i uruchomić, aby zobaczyć widok mapy 3D.

  1. Aby zsynchronizować projekt z Gradle, wybierz Plik > Synchronizuj projekt z plikami Gradle.

  2. Aby skompilować i uruchomić aplikację w emulatorze lub na urządzeniu fizycznym, wybierz Uruchom > Uruchom.

Jeśli wszystko jest prawidłowo skonfigurowane, w aplikacji powinna się wyświetlić mapa 3D wyśrodkowana w pobliżu współrzędnych podanych w pliku activity_main.xml.

Stany wczytywania mapy i błędu

Pakiet Maps 3D SDK na Androida automatycznie wyświetla wbudowane informacje wizualne podczas zarządzania stanem mapy:

  • Nakładka wczytywania: gdy widok mapy jest inicjowany po raz pierwszy lub wczytuje początkowy obszar widoczny, wyświetla się wyśrodkowany wskaźnik postępu.
  • Nakładka błędu: jeśli wystąpi krytyczny błąd, np. nieprawidłowy klucz interfejsu API, błąd sieci lub gdy aplikacja jest uruchamiana na nieobsługiwanym urządzeniu, wyświetla się stylizowana karta błędu.

Możesz programowo przechwytywać te błędy inicjowania lub wczytywania, zastępując onError(error: Exception) w implementacji OnMap3DViewReadyCallback.

Nasłuchiwanie zdarzeń kliknięcia mapy

Aby nasłuchiwać zdarzeń kliknięcia na mapie, użyj GoogleMap3D.setMap3DClickListener. Ten odbiornik jest wywoływany, gdy użytkownik kliknie mapę, i podaje lokalizację oraz identyfikator miejsca klikniętego punktu.

Poniższy przykład pokazuje, jak ustawić detektor kliknięć mapy:

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

Pamiętaj, że procedura obsługi kliknięć nie jest uruchamiana w wątku głównym (ani w wątku interfejsu użytkownika). Jeśli chcesz wprowadzić zmiany w interfejsie użytkownika (np. wyświetlić komunikat Toast), musisz przełączyć się na wątek główny. W Kotlinie możesz to zrobić za pomocą lifecycleScope.launch(Dispatchers.Main).

Dalsze kroki

Teraz, gdy dodasz do aplikacji podstawową mapę 3D, możesz poznać bardziej zaawansowane funkcje pakietu Maps 3D SDK na Androida, takie jak animacje ścieżki kamery, znaczniki 3D czy wielokąty.