From bd21f512e73a48461637c8e7153e60d61bf46214 Mon Sep 17 00:00:00 2001 From: Dale Hawkins <107309+dkhawk@users.noreply.github.com> Date: Tue, 18 Aug 2026 15:05:02 -0600 Subject: [PATCH] fix(snippets,tutorials): improve null safety, Compose animations, and update dependencies - Bump playServicesLocation to 21.4.0 in gradle/libs.versions.toml - Refactor FireMarkers animation state with rememberUpdatedMarkerState - Fix null safety and field initialization in KML.kt and Multilayer.kt - Clean up test runners and string templates in tutorial samples --- .../com/example/firemarkers/MainActivity.kt | 22 +++++++++++-------- gradle/libs.versions.toml | 2 ++ snippets/app-compose/build.gradle.kts | 3 ++- snippets/app-ktx/build.gradle.kts | 3 ++- .../java/com/example/app_utils_ktx/KML.kt | 4 ++-- .../com/example/app_utils_ktx/Multilayer.kt | 14 ++++++------ .../com/google/maps/example/TileOverlays.java | 5 +++-- tutorials/java/Polygons/app/build.gradle.kts | 4 ++-- .../app/build.gradle.kts | 4 ++-- .../kotlin/Polygons/app/build.gradle.kts | 4 ++-- .../java/com/example/polygons/PolyActivity.kt | 4 ++-- 11 files changed, 39 insertions(+), 30 deletions(-) diff --git a/FireMarkers/app/src/main/java/com/example/firemarkers/MainActivity.kt b/FireMarkers/app/src/main/java/com/example/firemarkers/MainActivity.kt index a970ef38a..fa9689476 100644 --- a/FireMarkers/app/src/main/java/com/example/firemarkers/MainActivity.kt +++ b/FireMarkers/app/src/main/java/com/example/firemarkers/MainActivity.kt @@ -1,4 +1,4 @@ -// Copyright 2025 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.key import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.unit.sp @@ -47,8 +48,8 @@ import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.maps.android.compose.GoogleMap import com.google.maps.android.compose.Marker -import com.google.maps.android.compose.MarkerState import com.google.maps.android.compose.rememberCameraPositionState +import com.google.maps.android.compose.rememberUpdatedMarkerState import dagger.hilt.android.AndroidEntryPoint import androidx.core.view.WindowCompat @@ -149,13 +150,16 @@ fun MapScreen(modifier: Modifier = Modifier) { cameraPositionState = cameraPositionState ) { markers.forEach { markerData -> - Marker( - state = remember(markerData.id) { - MarkerState(position = LatLng(markerData.latitude, markerData.longitude)) - }, - title = markerData.label, - icon = BitmapDescriptorFactory.defaultMarker(markerData.color) - ) + key(markerData.id) { + val markerState = rememberUpdatedMarkerState( + position = LatLng(markerData.latitude, markerData.longitude) + ) + Marker( + state = markerState, + title = markerData.label, + icon = BitmapDescriptorFactory.defaultMarker(markerData.color) + ) + } } } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 189e0dc0c..0f2eeee37 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -40,6 +40,7 @@ mapsCompose = "8.4.0" mapsKtx = "6.3.0" mapsUtils = "5.1.1" places = "5.3.0" +playServicesLocation = "21.4.0" playServicesMaps = "20.0.0" secretsGradlePlugin = "2.0.1" @@ -106,6 +107,7 @@ maps-ktx = { group = "com.google.maps.android", name = "maps-ktx", version.ref = maps-utils = { module = "com.google.maps.android:android-maps-utils", version.ref = "mapsUtils" } maps-utils-ktx = { group = "com.google.maps.android", name = "maps-utils-ktx", version.ref = "mapsKtx" } places = { group = "com.google.android.libraries.places", name = "places", version.ref = "places" } +play-services-location = { group = "com.google.android.gms", name = "play-services-location", version.ref = "playServicesLocation" } play-services-maps = { group = "com.google.android.gms", name = "play-services-maps", version.ref = "playServicesMaps" } # Wear OS diff --git a/snippets/app-compose/build.gradle.kts b/snippets/app-compose/build.gradle.kts index 129c8e19d..83f1bb505 100644 --- a/snippets/app-compose/build.gradle.kts +++ b/snippets/app-compose/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ android { buildTypes { release { isMinifyEnabled = true + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" diff --git a/snippets/app-ktx/build.gradle.kts b/snippets/app-ktx/build.gradle.kts index e305a70b0..6abf9419b 100644 --- a/snippets/app-ktx/build.gradle.kts +++ b/snippets/app-ktx/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +42,7 @@ android { buildTypes { release { isMinifyEnabled = true + isShrinkResources = true proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" diff --git a/snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/KML.kt b/snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/KML.kt index bbc9e09cb..f340ecaac 100644 --- a/snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/KML.kt +++ b/snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/KML.kt @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -68,7 +68,7 @@ internal class KML { // [START maps_android_utils_kml_access_properties] for (container in layer.getContainers()) { if (container.hasProperty("name")) { - Log.i("KML", container.getProperty("name")!!) + Log.i("KML", container.getProperty("name") ?: "") } } // [END maps_android_utils_kml_access_properties] diff --git a/snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/Multilayer.kt b/snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/Multilayer.kt index f87024baa..d05a0d9e1 100644 --- a/snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/Multilayer.kt +++ b/snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/Multilayer.kt @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -35,26 +35,26 @@ import org.xmlpull.v1.XmlPullParserException import java.io.IOException internal class Multilayer { - private val map: GoogleMap? = null - private val context: Context? = null + private lateinit var map: GoogleMap + private lateinit var context: Context @Suppress("IndexOutOfBoundsException") @Throws(IOException::class, JSONException::class, XmlPullParserException::class) private fun init() { // [START maps_android_utils_multilayer_init] val markerManager = MarkerManager(map) - val groundOverlayManager = GroundOverlayManager(map!!) + val groundOverlayManager = GroundOverlayManager(map) val polygonManager = PolygonManager(map) val polylineManager = PolylineManager(map) // [END maps_android_utils_multilayer_init] // [START maps_android_utils_multilayer_manager] val clusterManager = - ClusterManager(context!!, map, markerManager) + ClusterManager(context, map, markerManager) val geoJsonLineLayer = GeoJsonLayer( map, R.raw.geojson_file, - context!!, + context, markerManager, polygonManager, polylineManager, @@ -63,7 +63,7 @@ internal class Multilayer { val kmlPolylineLayer = KmlLayer( map, R.raw.kml_file, - context!!, + context, markerManager, polygonManager, polylineManager, diff --git a/snippets/app/src/main/java/com/google/maps/example/TileOverlays.java b/snippets/app/src/main/java/com/google/maps/example/TileOverlays.java index 82a19879d..00ae4b574 100644 --- a/snippets/app/src/main/java/com/google/maps/example/TileOverlays.java +++ b/snippets/app/src/main/java/com/google/maps/example/TileOverlays.java @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import java.net.MalformedURLException; import java.net.URL; +import java.util.Locale; class TileOverlays implements OnMapReadyCallback { // [START maps_android_tile_overlays_add] @@ -34,7 +35,7 @@ class TileOverlays implements OnMapReadyCallback { public URL getTileUrl(int x, int y, int zoom) { /* Define the URL pattern for the tile images */ - String s = String.format("http://my.image.server/images/%d/%d/%d.png", zoom, x, y); + String s = String.format(Locale.US, "http://my.image.server/images/%d/%d/%d.png", zoom, x, y); if (!checkTileExists(x, y, zoom)) { return null; diff --git a/tutorials/java/Polygons/app/build.gradle.kts b/tutorials/java/Polygons/app/build.gradle.kts index a8ec2ad89..64daa8270 100644 --- a/tutorials/java/Polygons/app/build.gradle.kts +++ b/tutorials/java/Polygons/app/build.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ android { targetSdk = libs.versions.targetSdk.get().toInt() versionCode = libs.versions.versionCode.get().toInt() versionName = libs.versions.versionName.get() - testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildFeatures { diff --git a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/build.gradle.kts b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/build.gradle.kts index a3bbb1b3f..7e62390ee 100644 --- a/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/build.gradle.kts +++ b/tutorials/kotlin/CurrentPlaceDetailsOnMap/app/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget /* - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -73,7 +73,7 @@ dependencies { testImplementation(libs.junit) implementation(libs.coreKtx) implementation(libs.lifecycleViewModelKtx) - implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${libs.versions.kotlin.get()}") + implementation(libs.kotlin.stdlib) implementation(libs.material) } diff --git a/tutorials/kotlin/Polygons/app/build.gradle.kts b/tutorials/kotlin/Polygons/app/build.gradle.kts index d326d26ff..6658c0193 100644 --- a/tutorials/kotlin/Polygons/app/build.gradle.kts +++ b/tutorials/kotlin/Polygons/app/build.gradle.kts @@ -1,7 +1,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget /* - * Copyright 2024 Google LLC + * Copyright 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,7 +30,7 @@ android { targetSdk = libs.versions.targetSdk.get().toInt() versionCode = libs.versions.versionCode.get().toInt() versionName = libs.versions.versionName.get() - testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } buildFeatures { diff --git a/tutorials/kotlin/Polygons/app/src/main/java/com/example/polygons/PolyActivity.kt b/tutorials/kotlin/Polygons/app/src/main/java/com/example/polygons/PolyActivity.kt index 51f4389e3..ffa64df29 100644 --- a/tutorials/kotlin/Polygons/app/src/main/java/com/example/polygons/PolyActivity.kt +++ b/tutorials/kotlin/Polygons/app/src/main/java/com/example/polygons/PolyActivity.kt @@ -1,4 +1,4 @@ -// Copyright 2020 Google LLC +// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -185,7 +185,7 @@ class PolyActivity : AppCompatActivity(), OnMapReadyCallback, OnPolylineClickLis // The default pattern is a solid stroke. polyline.pattern = null } - Toast.makeText(this, "Route type " + polyline.tag.toString(), + Toast.makeText(this, "Route type ${polyline.tag}", Toast.LENGTH_SHORT).show() } // [END maps_poly_activity_on_polyline_click]