Select platform: [Android](https://developers.google.com/maps/documentation/maps-3d/android-sdk/add-a-3d-map.md.txt "View this page for the Android platform docs.") [iOS](https://developers.google.com/maps/documentation/maps-3d/ios-sdk/add-a-3d-map.md.txt "View this page for the iOS platform docs.") [JavaScript](https://developers.google.com/maps/documentation/javascript/3d/get-started.md.txt "View this page for the JavaScript platform docs.")

<br />

![A 3D map showing New York City](https://developers.google.com/static/maps/documentation/maps-3d/android-sdk/images/hello-map.png)

This page walks through an example of how to add a basic 3D map to an
Android app using the Maps 3D SDK for Android. The instructions on this page
assume that you have already completed the steps in the
[Setup](https://developers.google.com/maps/documentation/maps-3d/android-sdk/setup.md.txt) page and have the
following:

- A Google Cloud project with the Maps 3D SDK for Android enabled
- An API key configured to use with the Maps 3D SDK for Android
- An Android Studio project set up to use with the Maps 3D SDK for Android

For more information about these prerequisites, see
[Setup](https://developers.google.com/maps/documentation/maps-3d/android-sdk/setup.md.txt).

## Part 1: Update Layout File (`activity_main.xml`) to add the `Map3DView` component

The `Map3DView` component is the view that renders the 3D map within the app.
The following steps add the component and configure the initial state of the
map, including the camera position and related attributes:

> [!NOTE]
> **Note:** The steps in this section assume that you have created and configured your Android Studio project using the process described in [Setup](https://developers.google.com/maps/documentation/maps-3d/android-sdk/setup.md.txt), or that you have added a new View activity to an existing project. If you create a new Android Studio project without adding a View activity, your project won't contain an `activity_main.xml` file.

1. Open your main activity's layout file, which is usually located at
   `app/src/main/res/layout/activity_main.xml`.

2. In the root `ConstraintLayout` (or your root layout element), add the `map3d`
   XML namespace:

   ```xml
   xmlns:map3d="http://schemas.android.com/apk/res-auto"
   ```
3. Delete the default `<TextView>` that displays "Hello World!".

4. Add the `Map3DView` component to your layout. You can customize the camera
   position and other attributes:

   ```xml
   <?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:mapMode="hybrid"
       map3d:centerLat="38.544012"
       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>
   ```

## Part 2: Update MainActivity.kt

The following steps initialize the `Map3DView` component added to the
`activity_main.xml` file in Part 1 and manage component lifecycle events.

Note that the Maps 3D SDK for Android only supports **one active `Map3DView`
instance at a time** . Displaying multiple `Map3DView` instances simultaneously
(e.g., in the same layout or different visible Activities or Fragments) isn't
supported and can lead to rendering issues, such as black screens on secondary
views.

Moreover, all the `Map3DView` will share and reflect the same map state (e.g.
camera position, added markers, polygons, etc.), which will persist even if one
`Map3DView` is destroyed (using `onDestroy`) and another is created, unless
manually cleared. For example, if you add markers to `Map3DView1`, then destroy
it and create `Map3DView2`, those same markers will still be present on
`Map3DView2`.

*Developer Responsibilities:*

- *One view at a time:* Ensure only one `Map3DView` is in an active part of your view hierarchy at any moment.
- *Manual cleanup:* When switching from one `Map3DView` (e.g., `Map3DView1`) to another (e.g., `Map3DView2`), you must call `onDestroy()` on the old instance (`Map3DView1`). Because the underlying map state is shared, to ensure `Map3DView2` starts with a fresh or specific state, you are responsible for manually clearing any state set by `Map3DView1`. This includes removing markers, overlays, etc., and resetting the camera position using the `GoogleMap3D` object obtained in the `OnMap3DViewReadyCallback`.

1. Open your `MainActivity.kt` file, which is usually located at
   `app/src/main/java/com/example/yourpackagename/MainActivity.kt`.

2. Add the necessary imports for the Maps 3D SDK for Android:

   ```kotlin
   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. Modify the `MainActivity` class to implement `OnMap3DViewReadyCallback`:

   ```kotlin
   class MainActivity : AppCompatActivity(), OnMap3DViewReadyCallback {
   ```
4. Declare variables for `Map3DView` and `GoogleMap3D`:

   ```kotlin
   private lateinit var map3DView: Map3DView
   private var googleMap3D: GoogleMap3D? = null
   ```
5. In the `onCreate` method, after `setContentView(...)` and the
   `ViewCompat.setOnApplyWindowInsetsListener` block, initialize the
   `map3DView`, call its `onCreate` lifecycle method, and request the map
   asynchronously:

   ```kotlin
   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. Override the [`onMap3DViewReady`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/OnMap3DViewReadyCallback.md.txt#onMap3DViewReady(com.google.android.gms.maps3d.GoogleMap3D)) and [`onError`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/OnMap3DViewReadyCallback.md.txt#onError(java.lang.Exception)) methods. These callbacks are triggered when
   the map is ready to be used, or when an error occurs during initialization:

   ```kotlin
   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.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. Forward lifecycle events from your Activity to the `Map3DView` by adding
   the following overrides to the `MainActivity`:

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

## Part 3: Sync Gradle and Run

Now that you've updated your app's layout and activity, you can build and
run the app to see the 3D map view.

1. To sync your project with Gradle, select
   **File \> Sync Project with Gradle Files.**

2. To build and run your app on an emulator or a physical device, select
   **Run \> Run**.

If everything is configured correctly, you should see a 3D map displayed in
your app, centered near the coordinates specified in your
`activity_main.xml`.

## Map loading and error states

The Maps 3D SDK for Android automatically displays built-in visual feedback while
managing the state of the map:

- **Loading overlay:** A centered progress indicator is displayed when the map view is first initialized or loading its initial viewport.
- **Error overlay:** A styled error card is displayed if a critical failure occurs, such as an invalid API key, network error, or when running on an unsupported device.

You can capture these initialization or loading errors programmatically by
overriding [`onError(error:
Exception)`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/OnMap3DViewReadyCallback#onError(java.lang.Exception))
within your
[`OnMap3DViewReadyCallback`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/OnMap3DViewReadyCallback.md.txt)
implementation.

## Listen for map click events

To listen for click events on the map, call
[`setMap3DClickListener`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/GoogleMap3D.md.txt#setMap3DClickListener(com.google.android.gms.maps3d.OnMap3DClickListener))
on
[`GoogleMap3D`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/GoogleMap3D.md.txt).
When a user clicks on the map, the
[`onMap3DClick`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/OnMap3DClickListener.md.txt#onMap3DClick(com.google.android.gms.maps3d.model.Map3DClickEvent))
callback receives a
[`Map3DClickEvent`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/model/Map3DClickEvent.md.txt)
object that provides the
[`location`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/model/Map3DClickEvent.md.txt#getLocation())
and
[`placeId`](https://developers.google.com/maps/documentation/maps-3d/android-sdk/reference/com/google/android/gms/maps3d/model/Map3DClickEvent.md.txt#getPlaceId())
of the clicked point, and returns a `Boolean` (`true` to suppress the default
Places UI widget, or `false` to display it). For more information, see
[Interact with points of interest](https://developers.google.com/maps/documentation/maps-3d/android-sdk/points-of-interest.md.txt).

The following example shows how to set a map click listener:

```kotlin
googleMap3D.setMap3DClickListener { event: Map3DClickEvent ->
    Log.d(
        "MainActivity",
        "Clicked at ${event.location}, placeId: ${event.placeId}"
    )
    false
}
```

> [!NOTE]
> **Note:** The click listener doesn't run on the main UI thread. Switch to the main thread before updating UI elements.

## Next steps

Now that you've added a basic 3D map to your app, you can explore more
advanced features of the Maps 3D SDK for Android, such as
[camera path animations](https://developers.google.com/maps/documentation/maps-3d/android-sdk/custom-camera-paths.md.txt),
[3D markers](https://developers.google.com/maps/documentation/maps-3d/android-sdk/add-a-marker.md.txt), or
[polygons](https://developers.google.com/maps/documentation/maps-3d/android-sdk/add-polygons.md.txt).