Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,4 @@ google-services.json
# VS Code
.vscode/
snippets/docs/



.kotlin/
94 changes: 94 additions & 0 deletions MIGRATION_GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Android Maps 3D SDK Migration Guide

This guide assists developers in migrating their codebases to newer versions of the Android Maps 3D SDK.

> [!TIP]
> **AI Migration Prompt**: If you are using an AI coding assistant (such as Gemini, Copilot, or Cursor), you can use this document as a prompt to automatically migrate your codebase.
>
> **Instructions for AI**:
> 1. Read the section corresponding to the version upgrade.
> 2. Analyze the "Before" and "After" patterns.
> 3. Scan the codebase for the "Before" patterns and apply the transformations to match the "After" patterns.
> 4. Ensure all imports are updated accordingly.

---

## Migrating from 0.2.0 to 0.2.2

This release introduces breaking changes to the initialization configuration and view construction.

### 1. Dependency Update
Update the SDK dependency version in your `build.gradle` or `gradle/libs.versions.toml`.

* **Action**: Update `playServicesMaps3d` version to `0.2.2`.

### 2. Replace `Map3DOptions` with `Map3DInitConfig`

The `Map3DOptions` class has been removed. Use `Map3DInitConfig` instead.
* **Rule**: `Map3DInitConfig` cannot be created via a constructor. Use the static `Map3DInitConfig.create()` factory method and chain `.copy(...)` to modify properties.

#### Code Transformation:

**Kotlin**:
```diff
-val options = Map3DOptions(
- centerLat = 21.350,
- centerLng = -157.800,
- centerAlt = 0.0,
- tilt = 60.0,
- range = 25000.0
-)
+val config = Map3DInitConfig.create().copy(
+ centerLat = 21.350,
+ centerLng = -157.800,
+ centerAlt = 0.0,
+ tilt = 60.0,
+ range = 25000.0
+)
```

**Java**:
```diff
-Map3DOptions options = new Map3DOptions();
-options.setCenterLat(21.350);
-options.setCenterLng(-157.800);
+Map3DInitConfig config = Map3DInitConfig.create(
+ 21.350, // centerLat
+ -157.800, // centerLng
+ 0.0, // centerAlt
+ 0.0, // heading
+ 60.0, // tilt
+ 0.0, // roll
+ 25000.0 // range
+);
```

### 3. Update `Map3DView` Construction

The default `Map3DView(Context)` constructor has been removed. You must now pass a `Map3DInitConfig` or a `mapMode`.

#### Code Transformation:

**Kotlin**:
```diff
-val view = Map3DView(context)
+val view = Map3DView(context, Map3DInitConfig.create())
```

**Java**:
```diff
-Map3DView view = new Map3DView(context);
+Map3DView view = new Map3DView(context, Map3DInitConfig.create());
```

### 4. Update Kotlin Named Parameters
If you construct `Map3DView` using named parameters, change `options` to `config`.

#### Code Transformation:
```diff
-val view = Map3DView(context = context, options = myConfig)
+val view = Map3DView(context = context, config = myConfig)
```

### 5. Remove `FacingMode`
The `FacingMode` enum has been removed. Remove all references to `FacingMode.SCREEN` or `FacingMode.BILLBOARD`.
2 changes: 1 addition & 1 deletion Maps3DSamples/ApiDemos/common/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,6 @@ dependencies {
implementation(libs.androidx.material3)

api(libs.play.services.base) // "com.google.android.gms:play-services-base:18.10.0"
api(libs.play.services.maps3d) // "com.google.android.gms:play-services-maps3d:0.2.0"
api(libs.play.services.maps3d) // "com.google.android.gms:play-services-maps3d:0.2.2"
api(libs.maps.utils.ktx)
}
18 changes: 9 additions & 9 deletions Maps3DSamples/ApiDemos/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@ compileSdk = "37"
minSdk = "26"
targetSdk = "36"

activityCompose = "1.12.4"
agp = "8.13.2"
activityCompose = "1.13.0"
agp = "9.2.1"
appcompat = "1.7.1"
composeBom = "2026.02.01"
coreKtx = "1.17.0"
composeBom = "2026.06.01"
coreKtx = "1.19.0"
desugar_jdk_libs = "2.1.5"
espressoCore = "3.7.0"
junit = "4.13.2"
junitVersion = "1.3.0"
kotlin = "2.2.0"
lifecycleRuntimeKtx = "2.10.0"
material = "1.13.0"
kotlin = "2.3.20"
lifecycleRuntimeKtx = "2.11.0"
material = "1.14.0"

playServicesBase = "18.10.0"
playServicesMaps3d = "0.2.0"
playServicesMaps3d = "0.2.2"
secretsGradlePlugin = "2.0.1"
truth = "1.4.5"
uiautomator = "2.3.0"
uiautomator = "2.4.0"
robolectric = "4.16.1"
androidxTestCore = "1.7.0"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ import android.widget.TextView
import android.widget.Toast
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import com.example.maps3dcommon.R
import com.example.maps3dkotlin.sampleactivity.SampleBaseActivity
import com.google.android.gms.maps3d.GoogleMap3D
import com.google.android.gms.maps3d.model.Map3DMode
import com.google.android.gms.maps3d.model.camera
import com.google.android.gms.maps3d.model.latLngAltitude
import kotlinx.coroutines.launch
import com.example.maps3dcommon.R

class MapInteractionsActivity : SampleBaseActivity() {
override val TAG = this::class.java.simpleName
Expand Down Expand Up @@ -63,14 +63,16 @@ class MapInteractionsActivity : SampleBaseActivity() {
// Listeners for map clicks. We use lifecycleScope to ensure coroutines are cancelled when the activity is destroyed.
lifecycleScope.launch {
googleMap3D.setMap3DClickListener { location, placeId ->
val message = if (placeId != null) {
"Clicked Place ID: $placeId"
} else {
"Clicked Location: ${location.latitude}, ${location.longitude}"
runOnUiThread {
val message = if (placeId != null) {
"Clicked Place ID: $placeId"
} else {
"Clicked Location: ${location.latitude}, ${location.longitude}"
}
clickedInfoText.text = message
clickedInfoText.contentDescription = message
showToast(message)
}
clickedInfoText.text = message
clickedInfoText.contentDescription = message
showToast(message)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,8 @@ abstract class SampleBaseActivity : AppCompatActivity(), OnMap3DViewReadyCallbac
Log.d(TAG, "onMap3DViewReady called")
Log.d(TAG, "Setting initial camera: " + initialCamera.toCameraString())
// Wire up the standardized listener
googleMap3D.setOnMapReadyListener {
Log.w(TAG, "on map ready listener")
googleMap3D.setOnMapReadyListener { sceneReadiness->
Log.w(TAG, "on map ready listener $sceneReadiness")
googleMap3D.setOnMapReadyListener(null)
onMapReady(googleMap3D)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import com.example.advancedmaps3dsamples.ui.theme.AdvancedMaps3DSamplesTheme
import com.google.android.gms.maps3d.GoogleMap3D
import com.google.android.gms.maps3d.Map3DOptions
import com.google.android.gms.maps3d.Map3DInitConfig
import com.google.android.gms.maps3d.Map3DView
import com.google.android.gms.maps3d.OnMap3DViewReadyCallback
import com.google.android.gms.maps3d.model.Map3DMode
import java.util.Locale

/**
* A minimal reference example demonstrating how to integrate the Google Maps 3D SDK
Expand Down Expand Up @@ -51,13 +53,26 @@ class BasicComposeMapActivity : ComponentActivity() {
// Composable enters the composition. Without `remember`, a new Map3DView would
// be created on every recomposition, causing severe performance issues and losing state.
val map3DView = remember {
// Map3DOptions allows us to set the initial camera position and orientation.
val options = Map3DOptions(
// Map3DInitConfig allows us to set the initial camera position and orientation.
val options = Map3DInitConfig.create(
centerLat = 21.350,
centerLng = -157.800,
centerAlt = 0.0,
tilt = 60.0,
range = 25000.0
centerAlt = 250.0,
heading = 45.0,
tilt = 65.0,
roll = 0.0,
range = 800.0,
minAltitude = 0.0,
maxAltitude = 1000000.0,
minHeading = 0.0,
maxHeading = 360.0,
minTilt = 0.0,
maxTilt = 90.0,
bounds = null,
mapMode = Map3DMode.HYBRID,
mapId = null,
language = Locale.getDefault().language,
region = Locale.getDefault().country
)
Map3DView(context, options).apply {
// Map3DView loads its resources asynchronously. We must provide a callback
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,39 +80,41 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.content.edit
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.example.advancedmaps3dsamples.BuildConfig
import com.example.advancedmaps3dsamples.R
import com.example.advancedmaps3dsamples.ui.theme.AdvancedMaps3DSamplesTheme
import com.example.advancedmaps3dsamples.utils.GeoMathUtils
import com.example.advancedmaps3dsamples.utils.calculateHeading
import com.example.advancedmaps3dsamples.utils.haversineDistance
import com.example.advancedmaps3dsamples.utils.toHeading
import com.example.advancedmaps3dsamples.utils.toValidCamera
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps3d.GoogleMap3D
import com.google.android.gms.maps3d.Map3DOptions
import com.google.android.gms.maps3d.Map3DInitConfig
import com.google.android.gms.maps3d.Map3DView
import com.google.android.gms.maps3d.OnMap3DViewReadyCallback
import com.google.android.gms.maps3d.model.AltitudeMode
import com.google.android.gms.maps3d.model.ImageView
import com.google.android.gms.maps3d.model.Map3DMode
import com.google.android.gms.maps3d.model.Polyline
import com.google.android.gms.maps3d.model.camera
import com.google.android.gms.maps3d.model.latLngAltitude
import com.google.android.gms.maps3d.model.markerOptions
import com.google.android.gms.maps3d.model.modelOptions
import com.google.android.gms.maps3d.model.orientation
import com.google.android.gms.maps3d.model.polylineOptions
import com.example.advancedmaps3dsamples.utils.GeoMathUtils
import com.google.android.gms.maps3d.model.vector3D
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.delay
import androidx.core.content.edit
import java.util.Locale
import kotlin.math.abs
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.delay

sealed interface RouteTracker {
val name: String
Expand Down Expand Up @@ -335,12 +337,25 @@ private fun Map3DViewport(
) {
val context = LocalContext.current
AndroidView(modifier = Modifier.fillMaxSize().testTag("map3d_view"), factory = {
val options = Map3DOptions(
val options = Map3DInitConfig.create(
centerLat = 21.350,
centerLng = -157.800,
centerAlt = 0.0,
tilt = 60.0,
range = 25000.0
range = 25000.0,
heading = 45.0,
roll = 0.0,
minAltitude = 0.0,
maxAltitude = 1000000.0,
minHeading = 0.0,
maxHeading = 360.0,
minTilt = 0.0,
maxTilt = 90.0,
bounds = null,
mapMode = Map3DMode.HYBRID,
mapId = null,
language = Locale.getDefault().language,
region = Locale.getDefault().country
)
val view = Map3DView(context, options)
view.onCreate(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.example.advancedmaps3dsamples.utils.wrapIn
import com.google.android.gms.maps3d.GoogleMap3D

private val headingSliderRange = -180f..180f
private val tiltSliderRange = 0f..90f
Expand Down Expand Up @@ -71,7 +70,7 @@ fun CameraControlDemoScreen(
Column(modifier = Modifier.fillMaxSize()) {
ThreeDMap(
modifier = Modifier.fillMaxWidth().weight(1f),
options = scenario.mapsOptions,
mapsConfig = scenario.mapsConfig,
viewModel = viewModel,
)
Spacer(modifier = Modifier.height(16.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ package com.example.advancedmaps3dsamples.scenarios

import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource
import com.google.android.gms.maps3d.Map3DOptions
import com.google.android.gms.maps3d.Map3DInitConfig
import com.google.android.gms.maps3d.model.Camera
import com.google.android.gms.maps3d.model.MarkerOptions
import com.google.android.gms.maps3d.model.ModelOptions // Import ModelOptions
Expand All @@ -28,7 +28,7 @@ import com.google.android.gms.maps3d.model.latLngAltitude
data class Scenario(
val name: String,
val titleId: Int,
val mapsOptions: Map3DOptions,
val mapsConfig: Map3DInitConfig,
val animationSteps: List<AnimationStep> = emptyList(),
val markers: List<MarkerOptions> = emptyList(),
val models: List<ModelOptions> = emptyList(), // Add models property
Expand All @@ -38,8 +38,8 @@ data class Scenario(
@Composable fun getTitle() = stringResource(titleId)

fun reset(viewModel: ScenariosViewModel) {
viewModel.setCamera(mapsOptions.toCamera()) // Set initial camera
viewModel.setMapMode(mapsOptions.mapMode)
viewModel.setCamera(mapsConfig.toCamera()) // Set initial camera
viewModel.setMapMode(mapsConfig.mapMode)

viewModel.clearObjects()

Expand Down Expand Up @@ -74,7 +74,7 @@ fun createScenario(
return Scenario(
name = name,
titleId = titleId,
mapsOptions = initialState.toMaps3DOptions(),
mapsConfig = initialState.toMaps3DInitConfig(),
animationSteps = animationString.toAnimation(),
markers = markers.toMarkers(),
models = models.toModels(),
Expand All @@ -83,7 +83,7 @@ fun createScenario(
)
}

fun Map3DOptions.toCamera(): Camera {
fun Map3DInitConfig.toCamera(): Camera {
val options = this
return camera {
center = latLngAltitude {
Expand Down
Loading
Loading