From 036d319c057ad9e9b404e990b9d32f09e83f39ff Mon Sep 17 00:00:00 2001
From: Dale Hawkins <107309+dkhawk@users.noreply.github.com>
Date: Mon, 13 Jul 2026 10:50:34 -0600
Subject: [PATCH 1/2] feat(catalog): comprehensive 2D Maps SDK capabilities
catalog, interactive verification dashboard, and falsifiable test suites
- Restructure snippets into dual-language Kotlin (kotlin-app) and Java (java-app) modules with TrackedMap wrapping GoogleMap for deterministic programmatic state verification
- Implement comprehensive 2D Maps SDK capability catalog covering Map Initialization, Camera Controls, Markers, Events, Overlays, Shapes, Dataset Layers, Data-Driven Boundaries, and Cloud Customization
- Build interactive verification dashboard (MANUAL_VERIFY_CATALOG.html) served via test/server.py (port 8888) with live Gradle test execution, ADB sample launcher, process cancellation, and real-time rating storage (ratings_db.json)
- Implement scientific Falsifiable Testing Standard (FALSIFIABLE_TASK_LIST.md) across dual-language test suites (CatalogCapabilitiesTestSuite, MarkerSnippetsTest, CameraControlSnippetsTest, MapInitSnippetsTest, EventsSnippetsTest)
---
.gitignore | 10 +-
CAPABILITIES_GAP_ANALYSIS.md | 161 +
FALSIFIABLE_TASK_LIST.md | 46 +
FALSIFIABLE_TESTING_STANDARD.md | 177 +
MANUAL_VERIFY_CATALOG.html | 5613 +++++++++++++++++
PARITY_TASK_LIST.md | 92 +
README.md | 8 +-
VERIFICATION_CHECKLIST.md | 46 +
VERIFICATION_TOOL_GUIDE.md | 171 +
check_api_key.gradle.kts | 98 +
gradle/libs.versions.toml | 9 +
local.defaults.properties | 1 +
settings.gradle.kts | 19 +-
snippets/CATALOG.md | 326 +
snippets/COVERAGE.md | 878 +++
snippets/app-ktx/.gitignore | 1 -
snippets/app-ktx/proguard-rules.pro | 21 -
snippets/app-ktx/src/main/AndroidManifest.xml | 33 -
.../src/main/java/com/example/app_ktx/KTX.kt | 68 -
.../drawable-v24/ic_launcher_foreground.xml | 46 -
.../res/drawable/ic_launcher_background.xml | 186 -
.../res/mipmap-anydpi-v26/ic_launcher.xml | 22 -
.../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes
.../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes
.../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes
.../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes
.../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes
.../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes
.../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes
.../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes
.../app-ktx/src/main/res/values/colors.xml | 26 -
.../app-ktx/src/main/res/values/strings.xml | 19 -
snippets/app-rx/.gitignore | 1 -
snippets/app-rx/build.gradle.kts | 106 -
snippets/app-rx/proguard-rules.pro | 21 -
snippets/app-rx/src/main/AndroidManifest.xml | 33 -
.../main/java/com/example/app_rx/MapsRx.kt | 50 -
.../main/java/com/example/app_rx/PlacesRx.kt | 41 -
.../drawable-v24/ic_launcher_foreground.xml | 46 -
.../res/drawable/ic_launcher_background.xml | 186 -
.../res/mipmap-anydpi-v26/ic_launcher.xml | 22 -
.../mipmap-anydpi-v26/ic_launcher_round.xml | 22 -
.../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes
.../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes
.../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes
.../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes
.../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes
.../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes
.../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes
.../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes
.../src/main/res/values-night/themes.xml | 32 -
.../app-rx/src/main/res/values/colors.xml | 26 -
.../app-rx/src/main/res/values/strings.xml | 19 -
.../app-rx/src/main/res/values/themes.xml | 32 -
snippets/app-utils-ktx/.gitignore | 1 -
snippets/app-utils-ktx/build.gradle.kts | 98 -
snippets/app-utils-ktx/proguard-rules.pro | 21 -
.../src/main/AndroidManifest.xml | 33 -
.../com/example/app_utils_ktx/Clustering.kt | 126 -
.../java/com/example/app_utils_ktx/GeoJSON.kt | 115 -
.../com/example/app_utils_ktx/Heatmaps.kt | 113 -
.../java/com/example/app_utils_ktx/KML.kt | 95 -
.../com/example/app_utils_ktx/Multilayer.kt | 140 -
.../drawable-v24/ic_launcher_foreground.xml | 46 -
.../res/drawable/ic_launcher_background.xml | 186 -
.../mipmap-anydpi-v26/ic_launcher_round.xml | 22 -
.../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes
.../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes
.../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes
.../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes
.../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes
.../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes
.../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes
.../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes
.../src/main/res/values/colors.xml | 29 -
.../src/main/res/values/strings.xml | 19 -
snippets/app-utils/.gitignore | 1 -
snippets/app-utils/proguard-rules.pro | 21 -
.../app-utils/src/main/AndroidManifest.xml | 33 -
.../com/example/app_utils/Clustering.java | 128 -
.../java/com/example/app_utils/GeoJSON.java | 130 -
.../java/com/example/app_utils/Heatmaps.java | 122 -
.../main/java/com/example/app_utils/KML.java | 98 -
.../com/example/app_utils/Multilayer.java | 115 -
.../drawable-v24/ic_launcher_foreground.xml | 46 -
.../res/drawable/ic_launcher_background.xml | 186 -
.../res/mipmap-anydpi-v26/ic_launcher.xml | 22 -
.../mipmap-anydpi-v26/ic_launcher_round.xml | 22 -
.../src/main/res/mipmap-hdpi/ic_launcher.webp | Bin 1404 -> 0 bytes
.../res/mipmap-hdpi/ic_launcher_round.webp | Bin 2898 -> 0 bytes
.../src/main/res/mipmap-mdpi/ic_launcher.webp | Bin 982 -> 0 bytes
.../res/mipmap-mdpi/ic_launcher_round.webp | Bin 1772 -> 0 bytes
.../main/res/mipmap-xhdpi/ic_launcher.webp | Bin 1900 -> 0 bytes
.../res/mipmap-xhdpi/ic_launcher_round.webp | Bin 3918 -> 0 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.webp | Bin 2884 -> 0 bytes
.../res/mipmap-xxhdpi/ic_launcher_round.webp | Bin 5914 -> 0 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.webp | Bin 3844 -> 0 bytes
.../res/mipmap-xxxhdpi/ic_launcher_round.webp | Bin 7778 -> 0 bytes
.../src/main/res/raw/geojson_file.json | 518 --
.../app-utils/src/main/res/raw/kml_file.kml | 194 -
.../src/main/res/raw/police_stations.json | 347 -
.../app-utils/src/main/res/values/colors.xml | 26 -
.../app-utils/src/main/res/values/strings.xml | 19 -
snippets/app/.gitignore | 1 -
snippets/app/build.gradle.kts | 110 -
snippets/app/proguard-rules.pro | 21 -
snippets/app/src/main/AndroidManifest.xml | 37 -
.../AdvancedMarkersCollisionActivity.java | 45 -
.../google/maps/example/CameraAndView.java | 94 -
.../example/CloudBasedMapStylingActivity.java | 35 -
.../google/maps/example/EventsActivity.java | 64 -
.../google/maps/example/GroundOverlays.java | 81 -
.../com/google/maps/example/InfoWindows.java | 72 -
.../com/google/maps/example/LiteMode.java | 26 -
.../java/com/google/maps/example/MapId.java | 41 -
.../example/MapRendererOptInApplication.java | 45 -
.../com/google/maps/example/MapsActivity.java | 63 -
.../com/google/maps/example/MapsObject.java | 91 -
.../java/com/google/maps/example/Markers.java | 198 -
.../maps/example/MyLocationLayerActivity.java | 69 -
.../maps/example/OnPoiClickDemoActivity.java | 54 -
.../PolylineCustomizationActivity.java | 62 -
.../com/google/maps/example/TileOverlays.java | 102 -
.../AdvancedMarkersCollisionActivity.kt | 43 -
.../kotlin/CloudBasedMapStylingActivity.kt | 33 -
.../maps/example/kotlin/EventsActivity.kt | 56 -
.../maps/example/kotlin/GroundOverlays.kt | 83 -
.../google/maps/example/kotlin/InfoWindows.kt | 72 -
.../google/maps/example/kotlin/LiteMode.kt | 24 -
.../com/google/maps/example/kotlin/MapId.kt | 40 -
.../kotlin/MapRendererOptInApplication.kt | 37 -
.../maps/example/kotlin/MapsActivity.kt | 64 -
.../google/maps/example/kotlin/MapsObject.kt | 89 -
.../com/google/maps/example/kotlin/Markers.kt | 208 -
.../example/kotlin/MyLocationLayerActivity.kt | 64 -
.../example/kotlin/OnPoiClickDemoActivity.kt | 50 -
.../kotlin/PolylineCustomizationActivity.kt | 71 -
.../com/google/maps/example/kotlin/Shapes.kt | 187 -
.../maps/example/kotlin/TileOverlays.kt | 96 -
.../drawable-v24/ic_launcher_foreground.xml | 46 -
.../res/drawable/ic_launcher_background.xml | 186 -
.../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 3593 -> 0 bytes
.../res/mipmap-hdpi/ic_launcher_round.png | Bin 5339 -> 0 bytes
.../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 2636 -> 0 bytes
.../res/mipmap-mdpi/ic_launcher_round.png | Bin 3388 -> 0 bytes
.../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 4926 -> 0 bytes
.../res/mipmap-xhdpi/ic_launcher_round.png | Bin 7472 -> 0 bytes
.../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 7909 -> 0 bytes
.../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 11873 -> 0 bytes
.../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 10652 -> 0 bytes
.../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 16570 -> 0 bytes
snippets/app/src/v3/AndroidManifest.xml | 28 -
.../example/CloudBasedMapStylingActivity.java | 35 -
.../maps/example/POIBehaviorActivity.java | 42 -
.../PolylineCustomizationActivity.java | 61 -
.../kotlin/CloudBasedMapStylingActivity.kt | 33 -
.../example/kotlin/POIBehaviorActivity.kt | 39 -
.../kotlin/PolylineCustomizationActivity.kt | 66 -
snippets/common/build.gradle.kts | 48 +
.../src/main/AndroidManifest.xml} | 8 +-
.../src/main/res/drawable/arrow_back_24px.xml | 9 +
.../main/res/drawable/arrow_forward_24px.xml | 9 +
.../main/res/drawable/photo_camera_24px.xml | 25 +
.../main/res/drawable/restart_alt_24px.xml | 25 +
.../src/main/res/layout/activity_main.xml | 35 +
.../src/main/res/layout/activity_map.xml | 108 +
.../res/layout/list_item_group_header.xml | 9 +
.../src/main/res/layout/list_item_snippet.xml | 44 +
.../src/main/res/raw/geojson_file.json | 0
.../src/main/res/raw/kml_file.kml | 0
.../src/main/res/raw/police_stations.json | 0
.../{app-utils => java-app}/build.gradle.kts | 58 +-
.../snippets/java/SnippetDiscoveryTest.java | 79 +
.../CameraControlSnippetsTest.java | 140 +
.../CatalogCapabilitiesTestSuite.java | 33 +
.../java/capabilities/EventsSnippetsTest.java | 114 +
.../capabilities/MapInitSnippetsTest.java | 123 +
.../java/capabilities/MarkerSnippetsTest.java | 177 +
.../java-app/src/main/AndroidManifest.xml | 57 +
.../snippets/java/JavaSnippetsActivity.java | 59 +
.../example/snippets/java/MapActivity.java | 360 ++
.../example/snippets/java/SnippetAction.java | 24 +
.../snippets/java/SnippetGroupAdapter.java | 134 +
.../snippets/java/SnippetGroupInfo.java | 44 +
.../snippets/java/SnippetItemInfo.java | 49 +
.../snippets/java/SnippetRegistry.java | 155 +
.../snippets/java}/StreetViewActivity.java | 4 +-
.../com/example/snippets/java/TrackedMap.java | 262 +
.../java/annotations/SnippetGroup.java | 37 +
.../java/annotations/SnippetItem.java | 37 +
.../java/snippets/CameraControlSnippets.java | 124 +
.../snippets/CloudCustomizationSnippets.java | 144 +
.../snippets/DataDrivenBoundarySnippets.java | 204 +
.../java/snippets/DatasetLayerSnippets.java | 311 +
.../java/snippets/EventsSnippets.java | 126 +
.../java/snippets/MapInitSnippets.java | 197 +
.../java/snippets/MarkerSnippets.java | 300 +
.../java/snippets/MyLocationSnippets.java | 71 +
.../java/snippets/OverlaySnippets.java | 204 +
.../java/snippets/ShapesSnippets.java} | 174 +-
.../java/snippets/StreetViewSnippets.java | 81 +
.../snippets/java/snippets/UtilsSnippets.java | 583 ++
.../res/drawable-xhdpi/harbour_bridge.jpg | Bin
.../res/drawable-xhdpi/newark_nj_1922.png | Bin
.../src/main/res/drawable/arrow.xml | 0
.../res/drawable/ic_launcher_background.xml | 10 +
.../res/drawable/ic_launcher_foreground.xml | 40 +
.../src/main/res/drawable/walking_dot.xml | 0
.../src/main/res/layout/activity_events.xml | 0
.../src/main/res/layout/activity_maps.xml | 0
.../src/main/res/layout/activity_markers.xml | 0
.../main/res/layout/activity_my_location.xml | 0
.../main/res/layout/activity_street_view.xml | 0
.../src/main/res/layout/main.xml | 0
.../src/main/res/layout/poi_click_demo.xml | 0
.../res/mipmap-anydpi-v26/ic_launcher.xml | 0
.../mipmap-anydpi-v26/ic_launcher_round.xml | 0
.../src/main/res/values/colors.xml | 6 +-
.../src/main/res/values/strings.xml | 2 +-
.../src/main/res/values/styles.xml | 2 +-
.../{app-ktx => kotlin-app}/build.gradle.kts | 59 +-
.../example/snippets/kotlin/BaseVisualTest.kt | 106 +
.../snippets/kotlin/SnippetDiscoveryTest.kt | 115 +
.../example/snippets/kotlin/VisualTests.kt | 262 +
.../capabilities/CameraControlSnippetsTest.kt | 132 +
.../CatalogCapabilitiesTestSuite.kt | 33 +
.../kotlin/capabilities/EventsSnippetsTest.kt | 109 +
.../capabilities/MapInitSnippetsTest.kt | 108 +
.../kotlin/capabilities/MarkerSnippetsTest.kt | 164 +
.../kotlin-app/src/main/AndroidManifest.xml | 57 +
.../snippets/kotlin/KotlinSnippetsActivity.kt | 56 +
.../example/snippets/kotlin/MapActivity.kt | 302 +
.../snippets/kotlin/SnippetGroupAdapter.kt | 106 +
.../snippets/kotlin/SnippetRegistry.kt | 172 +
.../snippets}/kotlin/StreetViewActivity.kt | 4 +-
.../com/example/snippets/kotlin/TrackedMap.kt | 189 +
.../kotlin/annotations/SnippetGroup.kt | 30 +
.../kotlin/annotations/SnippetItem.kt | 30 +
.../kotlin/snippets/CameraControlSnippets.kt} | 82 +-
.../snippets/CloudCustomizationSnippets.kt | 136 +
.../snippets/DataDrivenBoundarySnippets.kt | 184 +
.../kotlin/snippets/DatasetLayerSnippets.kt | 280 +
.../kotlin/snippets/EventsSnippets.kt | 95 +
.../snippets/kotlin/snippets/KtxSnippets.kt | 161 +
.../kotlin/snippets/MapInitSnippets.kt | 188 +
.../kotlin/snippets/MarkerSnippets.kt | 311 +
.../kotlin/snippets/MyLocationSnippets.kt | 54 +
.../kotlin/snippets/OverlaySnippets.kt | 195 +
.../kotlin/snippets/ShapesSnippets.kt | 323 +
.../kotlin/snippets/StreetViewSnippets.kt | 73 +
.../snippets/kotlin/snippets/UtilsSnippets.kt | 560 ++
.../res/drawable-xhdpi/harbour_bridge.jpg | Bin 0 -> 9430 bytes
.../res/drawable-xhdpi/newark_nj_1922.png | Bin 0 -> 348605 bytes
.../src/main/res/drawable/arrow.xml} | 18 +-
.../res/drawable/ic_launcher_background.xml | 10 +
.../res/drawable/ic_launcher_foreground.xml | 34 +
.../src/main/res/drawable/walking_dot.xml | 26 +
.../src/main/res/layout/activity_events.xml | 38 +
.../src/main/res/layout/activity_maps.xml | 2 +-
.../src/main/res/layout/activity_markers.xml} | 18 +-
.../main/res/layout/activity_my_location.xml | 24 +
.../main/res/layout/activity_street_view.xml | 24 +
.../kotlin-app/src/main/res/layout/main.xml | 21 +
.../src/main/res/layout/poi_click_demo.xml | 24 +
.../res/mipmap-anydpi-v26/ic_launcher.xml | 9 +-
.../mipmap-anydpi-v26/ic_launcher_round.xml | 9 +-
.../src/main/res/values/colors.xml} | 6 +-
.../src/main/res/values/strings.xml | 20 +
.../src/main/res/values/styles.xml | 2 +-
.../__pycache__/catalog_api.cpython-313.pyc | Bin 0 -> 19631 bytes
snippets/scripts/api_manifest.json | 213 +
snippets/scripts/catalog_api.py | 375 ++
test/build_manual_verification_tool.py | 1099 ++++
test/ratings_db.json | 6 +
test/server.py | 300 +
test/verify_catalog.py | 85 +
visual-testing/build.gradle.kts | 72 +
visual-testing/consumer-rules.pro | 1 +
visual-testing/proguard-rules.pro | 1 +
.../src/main/AndroidManifest.xml | 7 +-
.../visualtesting/GeminiVisualTestHelper.kt | 233 +
.../visualtesting/PlaceholderTest.java | 27 +
288 files changed, 19686 insertions(+), 7389 deletions(-)
create mode 100644 CAPABILITIES_GAP_ANALYSIS.md
create mode 100644 FALSIFIABLE_TASK_LIST.md
create mode 100644 FALSIFIABLE_TESTING_STANDARD.md
create mode 100644 MANUAL_VERIFY_CATALOG.html
create mode 100644 PARITY_TASK_LIST.md
create mode 100644 VERIFICATION_CHECKLIST.md
create mode 100644 VERIFICATION_TOOL_GUIDE.md
create mode 100644 check_api_key.gradle.kts
create mode 100644 snippets/CATALOG.md
create mode 100644 snippets/COVERAGE.md
delete mode 100644 snippets/app-ktx/.gitignore
delete mode 100644 snippets/app-ktx/proguard-rules.pro
delete mode 100644 snippets/app-ktx/src/main/AndroidManifest.xml
delete mode 100644 snippets/app-ktx/src/main/java/com/example/app_ktx/KTX.kt
delete mode 100644 snippets/app-ktx/src/main/res/drawable-v24/ic_launcher_foreground.xml
delete mode 100644 snippets/app-ktx/src/main/res/drawable/ic_launcher_background.xml
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-hdpi/ic_launcher.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-hdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-mdpi/ic_launcher.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-mdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-xhdpi/ic_launcher.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-xxhdpi/ic_launcher.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
delete mode 100644 snippets/app-ktx/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-ktx/src/main/res/values/colors.xml
delete mode 100644 snippets/app-ktx/src/main/res/values/strings.xml
delete mode 100644 snippets/app-rx/.gitignore
delete mode 100644 snippets/app-rx/build.gradle.kts
delete mode 100644 snippets/app-rx/proguard-rules.pro
delete mode 100644 snippets/app-rx/src/main/AndroidManifest.xml
delete mode 100644 snippets/app-rx/src/main/java/com/example/app_rx/MapsRx.kt
delete mode 100644 snippets/app-rx/src/main/java/com/example/app_rx/PlacesRx.kt
delete mode 100644 snippets/app-rx/src/main/res/drawable-v24/ic_launcher_foreground.xml
delete mode 100644 snippets/app-rx/src/main/res/drawable/ic_launcher_background.xml
delete mode 100644 snippets/app-rx/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
delete mode 100644 snippets/app-rx/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
delete mode 100644 snippets/app-rx/src/main/res/mipmap-hdpi/ic_launcher.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-hdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-mdpi/ic_launcher.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-mdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-xhdpi/ic_launcher.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-xxhdpi/ic_launcher.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
delete mode 100644 snippets/app-rx/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-rx/src/main/res/values-night/themes.xml
delete mode 100644 snippets/app-rx/src/main/res/values/colors.xml
delete mode 100644 snippets/app-rx/src/main/res/values/strings.xml
delete mode 100644 snippets/app-rx/src/main/res/values/themes.xml
delete mode 100644 snippets/app-utils-ktx/.gitignore
delete mode 100644 snippets/app-utils-ktx/build.gradle.kts
delete mode 100644 snippets/app-utils-ktx/proguard-rules.pro
delete mode 100644 snippets/app-utils-ktx/src/main/AndroidManifest.xml
delete mode 100644 snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/Clustering.kt
delete mode 100644 snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/GeoJSON.kt
delete mode 100644 snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/Heatmaps.kt
delete mode 100644 snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/KML.kt
delete mode 100644 snippets/app-utils-ktx/src/main/java/com/example/app_utils_ktx/Multilayer.kt
delete mode 100644 snippets/app-utils-ktx/src/main/res/drawable-v24/ic_launcher_foreground.xml
delete mode 100644 snippets/app-utils-ktx/src/main/res/drawable/ic_launcher_background.xml
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-hdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-hdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-mdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-mdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-xhdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-xxhdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils-ktx/src/main/res/values/colors.xml
delete mode 100644 snippets/app-utils-ktx/src/main/res/values/strings.xml
delete mode 100644 snippets/app-utils/.gitignore
delete mode 100644 snippets/app-utils/proguard-rules.pro
delete mode 100644 snippets/app-utils/src/main/AndroidManifest.xml
delete mode 100644 snippets/app-utils/src/main/java/com/example/app_utils/Clustering.java
delete mode 100644 snippets/app-utils/src/main/java/com/example/app_utils/GeoJSON.java
delete mode 100644 snippets/app-utils/src/main/java/com/example/app_utils/Heatmaps.java
delete mode 100644 snippets/app-utils/src/main/java/com/example/app_utils/KML.java
delete mode 100644 snippets/app-utils/src/main/java/com/example/app_utils/Multilayer.java
delete mode 100644 snippets/app-utils/src/main/res/drawable-v24/ic_launcher_foreground.xml
delete mode 100644 snippets/app-utils/src/main/res/drawable/ic_launcher_background.xml
delete mode 100644 snippets/app-utils/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
delete mode 100644 snippets/app-utils/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
delete mode 100644 snippets/app-utils/src/main/res/mipmap-hdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-hdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-mdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-mdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-xhdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-xxhdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
delete mode 100644 snippets/app-utils/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
delete mode 100644 snippets/app-utils/src/main/res/raw/geojson_file.json
delete mode 100644 snippets/app-utils/src/main/res/raw/kml_file.kml
delete mode 100644 snippets/app-utils/src/main/res/raw/police_stations.json
delete mode 100644 snippets/app-utils/src/main/res/values/colors.xml
delete mode 100644 snippets/app-utils/src/main/res/values/strings.xml
delete mode 100644 snippets/app/.gitignore
delete mode 100644 snippets/app/build.gradle.kts
delete mode 100644 snippets/app/proguard-rules.pro
delete mode 100644 snippets/app/src/main/AndroidManifest.xml
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/AdvancedMarkersCollisionActivity.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/CameraAndView.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/CloudBasedMapStylingActivity.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/EventsActivity.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/GroundOverlays.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/InfoWindows.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/LiteMode.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/MapId.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/MapRendererOptInApplication.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/MapsActivity.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/MapsObject.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/Markers.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/MyLocationLayerActivity.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/OnPoiClickDemoActivity.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/PolylineCustomizationActivity.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/TileOverlays.java
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/AdvancedMarkersCollisionActivity.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/CloudBasedMapStylingActivity.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/EventsActivity.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/GroundOverlays.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/InfoWindows.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/LiteMode.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/MapId.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/MapRendererOptInApplication.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/MapsActivity.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/MapsObject.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/Markers.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/MyLocationLayerActivity.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/OnPoiClickDemoActivity.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/PolylineCustomizationActivity.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/Shapes.kt
delete mode 100644 snippets/app/src/main/java/com/google/maps/example/kotlin/TileOverlays.kt
delete mode 100644 snippets/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
delete mode 100644 snippets/app/src/main/res/drawable/ic_launcher_background.xml
delete mode 100644 snippets/app/src/main/res/mipmap-hdpi/ic_launcher.png
delete mode 100644 snippets/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
delete mode 100644 snippets/app/src/main/res/mipmap-mdpi/ic_launcher.png
delete mode 100644 snippets/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
delete mode 100644 snippets/app/src/main/res/mipmap-xhdpi/ic_launcher.png
delete mode 100644 snippets/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
delete mode 100644 snippets/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
delete mode 100644 snippets/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
delete mode 100644 snippets/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
delete mode 100644 snippets/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
delete mode 100644 snippets/app/src/v3/AndroidManifest.xml
delete mode 100644 snippets/app/src/v3/java/com/google/maps/example/CloudBasedMapStylingActivity.java
delete mode 100644 snippets/app/src/v3/java/com/google/maps/example/POIBehaviorActivity.java
delete mode 100644 snippets/app/src/v3/java/com/google/maps/example/PolylineCustomizationActivity.java
delete mode 100644 snippets/app/src/v3/java/com/google/maps/example/kotlin/CloudBasedMapStylingActivity.kt
delete mode 100644 snippets/app/src/v3/java/com/google/maps/example/kotlin/POIBehaviorActivity.kt
delete mode 100644 snippets/app/src/v3/java/com/google/maps/example/kotlin/PolylineCustomizationActivity.kt
create mode 100644 snippets/common/build.gradle.kts
rename snippets/{app/src/v3/res/values/dimens.xml => common/src/main/AndroidManifest.xml} (85%)
create mode 100644 snippets/common/src/main/res/drawable/arrow_back_24px.xml
create mode 100644 snippets/common/src/main/res/drawable/arrow_forward_24px.xml
create mode 100644 snippets/common/src/main/res/drawable/photo_camera_24px.xml
create mode 100644 snippets/common/src/main/res/drawable/restart_alt_24px.xml
create mode 100644 snippets/common/src/main/res/layout/activity_main.xml
create mode 100644 snippets/common/src/main/res/layout/activity_map.xml
create mode 100644 snippets/common/src/main/res/layout/list_item_group_header.xml
create mode 100644 snippets/common/src/main/res/layout/list_item_snippet.xml
rename snippets/{app-utils-ktx => common}/src/main/res/raw/geojson_file.json (100%)
rename snippets/{app-utils-ktx => common}/src/main/res/raw/kml_file.kml (100%)
rename snippets/{app-utils-ktx => common}/src/main/res/raw/police_stations.json (100%)
rename snippets/{app-utils => java-app}/build.gradle.kts (50%)
create mode 100644 snippets/java-app/src/androidTest/java/com/example/snippets/java/SnippetDiscoveryTest.java
create mode 100644 snippets/java-app/src/androidTest/java/com/example/snippets/java/capabilities/CameraControlSnippetsTest.java
create mode 100644 snippets/java-app/src/androidTest/java/com/example/snippets/java/capabilities/CatalogCapabilitiesTestSuite.java
create mode 100644 snippets/java-app/src/androidTest/java/com/example/snippets/java/capabilities/EventsSnippetsTest.java
create mode 100644 snippets/java-app/src/androidTest/java/com/example/snippets/java/capabilities/MapInitSnippetsTest.java
create mode 100644 snippets/java-app/src/androidTest/java/com/example/snippets/java/capabilities/MarkerSnippetsTest.java
create mode 100644 snippets/java-app/src/main/AndroidManifest.xml
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/JavaSnippetsActivity.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/MapActivity.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/SnippetAction.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/SnippetGroupAdapter.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/SnippetGroupInfo.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/SnippetItemInfo.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/SnippetRegistry.java
rename snippets/{app/src/main/java/com/google/maps/example => java-app/src/main/java/com/example/snippets/java}/StreetViewActivity.java (97%)
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/TrackedMap.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/annotations/SnippetGroup.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/annotations/SnippetItem.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/CameraControlSnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/CloudCustomizationSnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/DataDrivenBoundarySnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/DatasetLayerSnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/EventsSnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/MapInitSnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/MarkerSnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/MyLocationSnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/OverlaySnippets.java
rename snippets/{app/src/main/java/com/google/maps/example/Shapes.java => java-app/src/main/java/com/example/snippets/java/snippets/ShapesSnippets.java} (51%)
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/StreetViewSnippets.java
create mode 100644 snippets/java-app/src/main/java/com/example/snippets/java/snippets/UtilsSnippets.java
rename snippets/{app => java-app}/src/main/res/drawable-xhdpi/harbour_bridge.jpg (100%)
rename snippets/{app => java-app}/src/main/res/drawable-xhdpi/newark_nj_1922.png (100%)
rename snippets/{app => java-app}/src/main/res/drawable/arrow.xml (100%)
create mode 100644 snippets/java-app/src/main/res/drawable/ic_launcher_background.xml
create mode 100644 snippets/java-app/src/main/res/drawable/ic_launcher_foreground.xml
rename snippets/{app => java-app}/src/main/res/drawable/walking_dot.xml (100%)
rename snippets/{app => java-app}/src/main/res/layout/activity_events.xml (100%)
rename snippets/{app => java-app}/src/main/res/layout/activity_maps.xml (100%)
rename snippets/{app => java-app}/src/main/res/layout/activity_markers.xml (100%)
rename snippets/{app => java-app}/src/main/res/layout/activity_my_location.xml (100%)
rename snippets/{app => java-app}/src/main/res/layout/activity_street_view.xml (100%)
rename snippets/{app => java-app}/src/main/res/layout/main.xml (100%)
rename snippets/{app => java-app}/src/main/res/layout/poi_click_demo.xml (100%)
rename snippets/{app => java-app}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (100%)
rename snippets/{app => java-app}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (100%)
rename snippets/{app => java-app}/src/main/res/values/colors.xml (82%)
rename snippets/{app => java-app}/src/main/res/values/strings.xml (91%)
rename snippets/{app => java-app}/src/main/res/values/styles.xml (91%)
rename snippets/{app-ktx => kotlin-app}/build.gradle.kts (59%)
create mode 100644 snippets/kotlin-app/src/androidTest/java/com/example/snippets/kotlin/BaseVisualTest.kt
create mode 100644 snippets/kotlin-app/src/androidTest/java/com/example/snippets/kotlin/SnippetDiscoveryTest.kt
create mode 100644 snippets/kotlin-app/src/androidTest/java/com/example/snippets/kotlin/VisualTests.kt
create mode 100644 snippets/kotlin-app/src/androidTest/java/com/example/snippets/kotlin/capabilities/CameraControlSnippetsTest.kt
create mode 100644 snippets/kotlin-app/src/androidTest/java/com/example/snippets/kotlin/capabilities/CatalogCapabilitiesTestSuite.kt
create mode 100644 snippets/kotlin-app/src/androidTest/java/com/example/snippets/kotlin/capabilities/EventsSnippetsTest.kt
create mode 100644 snippets/kotlin-app/src/androidTest/java/com/example/snippets/kotlin/capabilities/MapInitSnippetsTest.kt
create mode 100644 snippets/kotlin-app/src/androidTest/java/com/example/snippets/kotlin/capabilities/MarkerSnippetsTest.kt
create mode 100644 snippets/kotlin-app/src/main/AndroidManifest.xml
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/KotlinSnippetsActivity.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/MapActivity.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/SnippetGroupAdapter.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/SnippetRegistry.kt
rename snippets/{app/src/main/java/com/google/maps/example => kotlin-app/src/main/java/com/example/snippets}/kotlin/StreetViewActivity.kt (98%)
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/TrackedMap.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetGroup.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/annotations/SnippetItem.kt
rename snippets/{app/src/main/java/com/google/maps/example/kotlin/CameraAndView.kt => kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/CameraControlSnippets.kt} (55%)
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/CloudCustomizationSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/DataDrivenBoundarySnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/DatasetLayerSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/EventsSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/KtxSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/MapInitSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/MarkerSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/MyLocationSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/OverlaySnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/ShapesSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/StreetViewSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/java/com/example/snippets/kotlin/snippets/UtilsSnippets.kt
create mode 100644 snippets/kotlin-app/src/main/res/drawable-xhdpi/harbour_bridge.jpg
create mode 100644 snippets/kotlin-app/src/main/res/drawable-xhdpi/newark_nj_1922.png
rename snippets/{app/src/v3/res/values/styles.xml => kotlin-app/src/main/res/drawable/arrow.xml} (63%)
create mode 100644 snippets/kotlin-app/src/main/res/drawable/ic_launcher_background.xml
create mode 100644 snippets/kotlin-app/src/main/res/drawable/ic_launcher_foreground.xml
create mode 100644 snippets/kotlin-app/src/main/res/drawable/walking_dot.xml
create mode 100644 snippets/kotlin-app/src/main/res/layout/activity_events.xml
rename snippets/{app-ktx => kotlin-app}/src/main/res/layout/activity_maps.xml (96%)
rename snippets/{app-utils/src/main/res/values/styles.xml => kotlin-app/src/main/res/layout/activity_markers.xml} (60%)
create mode 100644 snippets/kotlin-app/src/main/res/layout/activity_my_location.xml
create mode 100644 snippets/kotlin-app/src/main/res/layout/activity_street_view.xml
create mode 100644 snippets/kotlin-app/src/main/res/layout/main.xml
create mode 100644 snippets/kotlin-app/src/main/res/layout/poi_click_demo.xml
rename snippets/{app-utils-ktx => kotlin-app}/src/main/res/mipmap-anydpi-v26/ic_launcher.xml (68%)
rename snippets/{app-ktx => kotlin-app}/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml (68%)
rename snippets/{app/src/v3/res/values/strings.xml => kotlin-app/src/main/res/values/colors.xml} (77%)
create mode 100644 snippets/kotlin-app/src/main/res/values/strings.xml
rename snippets/{app-utils-ktx => kotlin-app}/src/main/res/values/styles.xml (91%)
create mode 100644 snippets/scripts/__pycache__/catalog_api.cpython-313.pyc
create mode 100644 snippets/scripts/api_manifest.json
create mode 100644 snippets/scripts/catalog_api.py
create mode 100755 test/build_manual_verification_tool.py
create mode 100644 test/ratings_db.json
create mode 100644 test/server.py
create mode 100644 test/verify_catalog.py
create mode 100644 visual-testing/build.gradle.kts
create mode 100644 visual-testing/consumer-rules.pro
create mode 100644 visual-testing/proguard-rules.pro
rename snippets/app-ktx/src/main/res/values/themes.xml => visual-testing/src/main/AndroidManifest.xml (80%)
create mode 100644 visual-testing/src/main/java/com/google/maps/android/visualtesting/GeminiVisualTestHelper.kt
create mode 100644 visual-testing/src/test/java/com/google/maps/android/visualtesting/PlaceholderTest.java
diff --git a/.gitignore b/.gitignore
index 275449d61..1719b848d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,4 +9,12 @@ secrets.properties
# This covers new IDEs, like Antigravity
.vscode/
-**/bin/
\ No newline at end of file
+**/bin/
+
+# Temporary verification screenshot files
+*_screen*.png
+sydney_final.png
+*_sydney.png
+*_verified.png
+!**/assets/screenshots/*.png
+.kotlin/
\ No newline at end of file
diff --git a/CAPABILITIES_GAP_ANALYSIS.md b/CAPABILITIES_GAP_ANALYSIS.md
new file mode 100644
index 000000000..2edc19412
--- /dev/null
+++ b/CAPABILITIES_GAP_ANALYSIS.md
@@ -0,0 +1,161 @@
+# 📊 Android Maps SDK Capabilities Gap Analysis & Future Work Report
+
+**Generated Date:** June 2026
+**Repository Scope:** `android-samples/comprehensive-catalog` (WIP 2D Maps SDK Catalog)
+**Comparison Baseline:** `capabilities.json` (Complete Android Maps Platform Capabilities Index)
+
+---
+
+## 📑 Executive Summary
+
+This report provides a thorough, exhaustive gap analysis comparing the full suite of Google Maps Platform capabilities defined in `capabilities.json` against the active codebase samples in `comprehensive-catalog`.
+
+Across all Google Maps Platform products, `capabilities.json` defines **340 capabilities**, of which **123 are supported on Android** across six primary SDKs:
+* **Navigation SDK for Android:** 46 capabilities
+* **Maps SDK for Android (2D):** 39 capabilities
+* **Places SDK for Android:** 28 capabilities
+* **Consumer SDK for Android:** 12 capabilities
+* **Maps 3D SDK for Android:** 10 capabilities
+* **Driver SDK for Android:** 6 capabilities
+
+*(Note: Certain capabilities apply to multiple SDKs, such as adding markers or interactive maps).*
+
+### Key Findings for Maps SDK (2D)
+Within the primary scope of this repository (`Maps SDK for Android`), the active catalog demonstrates **72 registered snippet items** across **41 source files**, achieving an **~85% coverage rate** of GA 2D programmatic features. Core map lifecycle, camera animations, annotations (markers, polylines, polygons, ground overlays, tile overlays), event listeners, and legacy utility datasets (GeoJSON, KML, Heatmaps, Clustering) are fully covered and verified via automated Gemini visual tests.
+
+However, three critical areas require future development to achieve 100% feature parity:
+1. **Data-Driven Styling (DDS):** Complete absence of code samples for `FeatureLayer` boundary styling, choropleth maps, and `DatasetFeatureLayer` custom geospatial datasets.
+2. **Unregistered Street View Snippets:** Street View panorama code exists in `StreetViewActivity.kt/.java` with valid region tags, but lacks `@SnippetGroup` and `@SnippetItem` reflection annotations, preventing UI discovery and catalog indexing.
+3. **Standalone Map Configurations:** Missing dedicated snippet items for Map Color Scheme (Dark Mode) and Traffic Layers.
+
+---
+
+## 🗺️ Part 1: Maps SDK for Android (2D) Capability Breakdown
+
+### 1. Fully Covered Programmatic Capabilities (21 / 39)
+
+The following capabilities from `capabilities.json` are actively demonstrated with dedicated `@SnippetItem` boundaries, region tags, and automated test coverage in `kotlin-app` and `java-app`:
+
+| Capability ID | Secondary Grouping | Capability Description | Demonstrating Snippet Files |
+| :--- | :--- | :--- | :--- |
+| `232ecd00-34c4-4c55-bd75-69feb6a019b7` | Maps | Add a customizable, interactive map to an app | `MapInitSnippets.kt` / `MapActivity.kt` |
+| `ca51263d-305a-4406-9919-45ccfd6a3159` | Maps | Create a reusable map identifier (Map ID) | `MapInitSnippets.kt` (`SupportMapFragmentMapId`) |
+| `2a3e0c25-0ceb-4e66-a9dc-04a42bc0602c` | Maps | Control zoom and pan on a map (camera) | `CameraControlSnippets.kt` |
+| `0e6b228f-a01d-48e5-a1ab-bd4c28b5726b` | Maps | Customize the gestures for controlling a map | `CameraControlSnippets.kt` (`panningRestrictions`) |
+| `9eeb4a1a-dbda-45c7-ada0-a8e83c8de436` | Maps | Customize the controls that appear on a map | `MapInitSnippets.kt` (`googleMapOptions`) |
+| `b34458f3-ee7d-4634-8e9d-8cf9679d9455` | Maps | Respond to user interactions and events on a map | `EventsSnippets.kt` / `KtxSnippets.kt` |
+| `c511ea57-0a1d-4b2d-828c-139635a3c004` | Maps | Change the map type | `MapInitSnippets.kt` (`setMapType`) |
+| `7bbfe87e-1a43-49ae-b70b-faf4f79c2b98` | Maps annotations | Add a marker to a map | `MarkerSnippets.kt` (`addMarker`) |
+| `de757d41-8545-4314-bab6-268eb872e806` | Maps annotations | Customize a marker on a map | `MarkerSnippets.kt` (color, opacity, icon, flat, rotate) |
+| `4c2a9906-f4a3-4ba5-9af9-22fc9f00e083` | Maps annotations | Respond to user interactions with markers | `MarkerSnippets.kt` (`markerClickListener`) |
+| `bdbefba5-65f1-49ca-9714-2ac311e6012d` | Maps annotations | Add an info window to a map | `MarkerSnippets.kt` (`addInfoWindow`) |
+| `246ab3a6-8623-49f0-9206-f886c8286634` | Maps annotations | Add a shape or line to a map | `ShapesSnippets.kt` (polyline, polygon, circle) |
+| `518c439f-c198-411c-973b-974a1f866970` | Maps annotations | Add an overlay image grounded to map surface | `OverlaySnippets.kt` (`groundOverlays`) |
+| `58007bbe-114b-481e-908c-d79cbad418d9` | Maps annotations | Add a custom tile overlay to a map | `OverlaySnippets.kt` (`tileOverlaysAdd`) |
+| `20fb724a-cf58-427a-aea4-575826de7011` | Datasets | Add GeoJSON data to a map | `UtilsSnippets.kt` (`geoJsonLayer`) |
+| `f451d761-71ca-48eb-9b06-29908e447ae0` | Datasets | Add a KML layer to a map | `UtilsSnippets.kt` (`addKmlLayerFile`) |
+| `fbbc9c5a-ca98-4b83-a801-e502e57eab2f` | Datasets | Add a heatmap layer to a map | `UtilsSnippets.kt` (`addHeatMap`, `addCustomHeatmap`) |
+| `b8fadfc3-caae-464b-ac0e-70a1503a1e5e` | Street View | Add interactive Google Street View to an app | `StreetViewActivity.kt` *(Requires catalog registration)* |
+| `7b144b66-b24c-49d9-a08c-c1cf69178c87` | Street View | Animate camera movements for Street View | `StreetViewActivity.kt` (`animate`) |
+| `75a7efe9-1797-404c-acba-a616be210f36` | Street View | Customize gestures available for Street View | `StreetViewActivity.kt` (`pan`, `tilt`, `zoom`) |
+| `6e3999d1-6c71-4a63-a52b-15cf2358ae10` | Street View | Respond to interactions & events in Street View | `StreetViewActivity.kt` (`onStreetViewPanoramaReady`) |
+
+---
+
+### 2. Cloud Customization Capabilities (Console vs. Code Distinction) (8 / 39)
+
+The following styling capabilities are supported on Android, but represent **Google Cloud Console authoring workflows** rather than standalone SDK client APIs:
+
+* `4d87a0ea-f638-496f-9bd9-549c6865739d` — Create a reusable, cross-platform map style.
+* `5d26e9fb-0da1-4614-8738-d944c89d0412` — Change the style of roads, polylines, and polygons on a map.
+* `1f5dea73-4b7e-40aa-98cd-504015572fde` — Display or hide map features.
+* `3fc0911b-c84f-4e4f-ba3e-ab0397fa44b3` — Change the style of icons and text labels on a map.
+* `589c7e69-fa39-4074-9989-fd534a2d17ef` — Apply different map styles to different zoom levels.
+* `468c2301-a1c1-4b8e-a9c6-5f0bf2125117` — Change the density of places on a map (POI density filtering).
+* `89814817-86ae-4bf0-bb3a-3ac1bb6f1535` — Change the style of buildings on a map.
+* `4255f56a-cac8-455d-864c-e784a15575eb` — Change the style of landmarks on a map.
+
+**Analysis & Recommendation:**
+In client SDK code, all eight capabilities manifest identically: by passing a `MapId` string configured within the Cloud Console to `GoogleMapOptions` or `SupportMapFragment`. While `MapInitSnippets.kt` demonstrates `cloudBasedMapStyling`, future work should add a dedicated **`CloudCustomizationSnippets.kt`** guide explaining how developers preview and verify console-driven road, POI, and building density styles in code.
+
+---
+
+### 3. Critical Gaps & Missing Code Samples (10 / 39)
+
+#### 🔴 Gap Category A: Data-Driven Styling (DDS) for Boundaries & Datasets (Priority: HIGH)
+Data-Driven Styling allows developers to target Google's administrative boundary polygons (counties, states, postal codes) and upload custom geospatial datasets via Google Cloud. **Zero code coverage currently exists for these APIs.**
+
+**Missing Capabilities:**
+1. `dedc17af-b978-4790-858c-b83bb99a8bee` — **Change the style of boundaries on a map**
+ *API Required:* `map.getFeatureLayer(FeatureLayerOptions.Builder().featureType(FeatureType.ADMINISTRATIVE_AREA_LEVEL_1)...)` and `FeatureLayer.stylePolygon`.
+2. `fa7cc2f9-225c-436a-b001-e4d71f277604` — **Respond to user interactions with boundaries on a map**
+ *API Required:* `FeatureLayer.addOnFeatureClickListener { event -> ... }`.
+3. `0a767a66-08a3-412d-9d8f-92027e3ed9be` — **Add choropleth styling to a map**
+ *Workflow:* Dynamically coloring administrative regions based on statistical metrics (e.g. population density).
+4. `3ebaeaa1-1f4a-4d98-9969-289fb76d001e` — **Add a custom geospatial dataset to a map**
+ *API Required:* `map.getDatasetFeatureLayer(datasetId)` (`DatasetFeatureLayer`).
+5. `eb3ed819-c782-4712-a2d2-03f8e5431b29` — **Change the style of custom dataset features on a map**
+ *API Required:* Applying `FeatureStyle` factories to dataset layers.
+6. `e72146cb-1e8f-4db9-9e44-b64296a19398` — **Respond to user interactions with custom dataset features**
+ *API Required:* `DatasetFeatureLayer.addOnFeatureClickListener`.
+7. `5b54c6a7-fdd5-42ec-b7ce-63b37c9a1649` — **Create a reusable geospatial dataset**
+ *Console/API workflow reference guide needed.*
+
+#### 🟡 Gap Category B: Street View Catalog Registration (Priority: MEDIUM)
+**Current State:** `StreetViewActivity.kt` and `.java` contain excellent implementations of Street View initialization, camera panning, zooming, tilting, and animation.
+**The Gap:** Neither file uses the `@SnippetGroup` or `@SnippetItem` annotations. Consequently, `catalog_api.py` ignores them, they do not appear in `CATALOG.md`, and users cannot launch them from the sample app's main menu.
+
+#### 🟢 Gap Category C: Standalone Map Configurations (Priority: LOW)
+1. `25bf9dfd-4ae4-42cd-96ef-d90d647504da` — **Change the map color scheme**
+ *API Required:* Explicit snippet for `map.mapColorScheme = MapColorScheme.DARK` / `FOLLOW_SYSTEM`.
+2. `20793ebb-d244-4f4f-a555-60ed0226de2f` — **Add a traffic layer to a map**
+ *API Required:* Dedicated snippet item for `map.isTrafficEnabled = true`.
+3. `2b6457c4-3099-4c2e-843d-bee3c83802b4` — **Add a map to a Wear OS app**
+ *Current State:* A Wear OS demo exists in `WearOS/Wearable`, but is excluded from the unified catalog discovery suite.
+
+---
+
+## 🌐 Part 2: Maps 3D SDK for Android Coverage Analysis
+
+`capabilities.json` introduces **10 capabilities for the upcoming Maps 3D SDK (`Photorealistic 3D maps`)**:
+* `02c99be0-1e94-4965-afde-7e2a6db8c584` — Add an interactive, photorealistic 3D map to an app (`Map3DView`)
+* `167d46ad-170a-4e9b-9057-8dcb5c07a1a6` — Add a marker to a photorealistic 3D map
+* `1e7a05c3-bcf8-467c-96df-49ed1c966b75` — Customize a marker on a photorealistic 3D map
+* `8806d93d-459f-4fe7-9f86-1f3f8d78c4a1` — Add a 3D model (GLTF/GLB) to a photorealistic 3D map
+* `515a2e5f-a225-4323-8ae4-40699859f243` — Add a 3D polyline / polygon to a photorealistic 3D map
+* `91ec90da-3d14-4128-9d4e-63b8da5c7878` — Respond to user interactions and events on a 3D map
+* `7d6fc13d-5be2-418a-8f6b-7de91bcabd56` — Customize controls on a photorealistic 3D map
+* `7e09527a-ddb0-4f4c-ad4d-e64db37e9373` — Control camera paths and flight animations
+* `56b2b8e4-b8e9-4b8e-9b8e-7e2b8e4b8e9b` — Control camera bounding restrictions
+
+**Strategic Architectural Recommendation:**
+Because `comprehensive-catalog` is explicitly architected as the **2D SDK gold standard** (`# 🗺️ Maps SDK (2D) API Snippets Catalog`), mixing 3D view renderers (`com.google.android.gms.maps.model.Map3DView`) into `kotlin-app` would bloat dependency trees and confuse developers. All 10 photorealistic 3D capabilities should remain strictly isolated within the sibling **`android-maps3d-samples`** repository.
+
+---
+
+## 🚀 Part 3: Actionable Roadmap for Future Work
+
+To migrate `comprehensive-catalog` from WIP to 100% capability completion, engineering efforts should be prioritized into three distinct sprints:
+
+### Sprint 1: Quick Wins & Catalog Alignment (Estimated Effort: 1 Day)
+1. **Annotate Street View:** Add `@SnippetGroup("Street View")` to `StreetViewActivity` and `@SnippetItem` to its panorama methods. Re-run `catalog_api.py` to index Street View into `CATALOG.md`.
+2. **Add Map Color Scheme Snippet:** Create `MapColorSchemeSnippets.kt/.java` demonstrating runtime switching between normal, dark, and system-default map color schemes.
+3. **Add Traffic Layer Snippet:** Expose a clean standalone snippet demonstrating real-time traffic overlay toggling.
+
+### Sprint 2: Data-Driven Styling (DDS) Suite (Estimated Effort: 3 Days)
+1. **Create `BoundaryStylingSnippets.kt/.java`:**
+ * Initialize a `FeatureLayer` for administrative boundaries.
+ * Apply a `FeatureStyle` coloring postal codes or states.
+ * Attach `addOnFeatureClickListener` showing a Toast with the clicked region's display name and place ID.
+2. **Create `DatasetLayerSnippets.kt/.java`:**
+ * Demonstrate loading a Cloud Dataset via `getDatasetFeatureLayer`.
+ * Build a dynamic choropleth sample applying color gradients based on dataset feature attributes.
+3. **Visual Verification Prompts:** Capture 25% scaled screenshots of boundary styles and register Gemini evaluation criteria in `VisualTests.kt`.
+
+### Sprint 3: Wear OS & Multi-Form Factor Polish (Estimated Effort: 2 Days)
+1. **Unify Wear OS Discovery:** Refactor `WearOS/Wearable` to share snippet definitions or generate a secondary `WEAR_CATALOG.md` index.
+2. **Automated CI Gate:** Integrate `python3 test/verify_catalog.py` into GitHub Actions presubmits to enforce that all future capabilities added to `capabilities.json` trigger automated catalog sync warnings if left unreferenced.
+
+---
+
+*Report generated automatically by Jetski (Gemini Next) Pair Programming Agent.*
diff --git a/FALSIFIABLE_TASK_LIST.md b/FALSIFIABLE_TASK_LIST.md
new file mode 100644
index 000000000..5fe4777b1
--- /dev/null
+++ b/FALSIFIABLE_TASK_LIST.md
@@ -0,0 +1,46 @@
+# 🗺️ Maps SDK Falsifiable Task List & Review Matrix
+
+Use this matrix to track, review, rate (1-to-5 stars), and verify every Maps SDK for Android capability.
+Every test must be **falsifiable**: if the code under test is broken or removed, the test must immediately fail.
+
+| ID | Capability & Group | Status | Sample Code | Falsifiable Test | Gradle Verification Command | Rating |
+| :---: | :--- | :---: | :--- | :--- | :--- | :---: |
+| `2a3e0c25` | **Control zoom and pan on a map (camera).** *Camera* | ✅ Falsified | Kotlin: `CameraControlSnippets.kt#L39-L42` Java: `CameraControlSnippets.java#L45-L48` | `verifyCameraMovementsAndZoomConstraints_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CameraControlSnippetsTest#verifyCameraMovementsAndZoomConstraints_falsifiable` | [ ] ___/5 |
+| `0e6b228f` | **Customize the gestures for controlling a map.** *Camera* | ✅ Falsified | Kotlin: `CameraControlSnippets.kt#L78-L87` Java: `CameraControlSnippets.java#L84-L93` | `verifyCameraClampingToAustralia_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CameraControlSnippetsTest#verifyCameraClampingToAustralia_falsifiable` | [ ] ___/5 |
+| `589c7e69` | **Apply different map styles to different zoom levels.** *Cloud Customization* | ⏳ Pending | Kotlin: `CloudCustomizationSnippets.kt#L90-L95` Java: `CloudCustomizationSnippets.java#L98-L103` | `verifyHierarchyZoomStyling_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest#verifyHierarchyZoomStyling_falsifiable` | [ ] ___/5 |
+| `468c2301` | **Change the density of places on a map.** *Cloud Customization* | ⏳ Pending | Kotlin: `CloudCustomizationSnippets.kt#L103-L108` Java: `CloudCustomizationSnippets.java#L111-L116` | `verifyPoiDensityFiltering_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest#verifyPoiDensityFiltering_falsifiable` | [ ] ___/5 |
+| `89814817` | **Change the style of buildings on a map.** *Cloud Customization* | ⏳ Pending | Kotlin: `CloudCustomizationSnippets.kt#L116-L121` Java: `CloudCustomizationSnippets.java#L124-L129` | `verifyBuilding3dAndFootprintStyling_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest#verifyBuilding3dAndFootprintStyling_falsifiable` | [ ] ___/5 |
+| `3fc0911b` | **Change the style of icons and text labels on a map.** *Cloud Customization* | ⏳ Pending | Kotlin: `CloudCustomizationSnippets.kt#L77-L82` Java: `CloudCustomizationSnippets.java#L85-L90` | `verifyIconAndTextLabelStyling_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest#verifyIconAndTextLabelStyling_falsifiable` | [ ] ___/5 |
+| `4255f56a` | **Change the style of landmarks on a map.** *Cloud Customization* | ⏳ Pending | Kotlin: `CloudCustomizationSnippets.kt#L129-L134` Java: `CloudCustomizationSnippets.java#L137-L142` | `verifyLandmarkHierarchyStyling_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest#verifyLandmarkHierarchyStyling_falsifiable` | [ ] ___/5 |
+| `5d26e9fb` | **Change the style of roads, polylines, and polygons on a map.** *Cloud Customization* | ⏳ Pending | Kotlin: `CloudCustomizationSnippets.kt#L51-L56` Java: `CloudCustomizationSnippets.java#L59-L64` | `verifyRoadAndGeometryStyling_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest#verifyRoadAndGeometryStyling_falsifiable` | [ ] ___/5 |
+| `4d87a0ea` | **Create a reusable, cross-platform map style.** *Cloud Customization* | ⏳ Pending | Kotlin: `CloudCustomizationSnippets.kt#L38-L43` Java: `CloudCustomizationSnippets.java#L46-L51` | `verifyReusableMapIdLoading_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest#verifyReusableMapIdLoading_falsifiable` | [ ] ___/5 |
+| `1f5dea73` | **Display or hide map features.** *Cloud Customization* | ⏳ Pending | Kotlin: `CloudCustomizationSnippets.kt#L64-L69` Java: `CloudCustomizationSnippets.java#L72-L77` | `verifyFeatureVisibilityToggles_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest#verifyFeatureVisibilityToggles_falsifiable` | [ ] ___/5 |
+| `3ebaeaa1` | **Add a custom geospatial dataset to a map.** *Custom Geospatial Datasets* | ⏳ Pending | Kotlin: `maps_android_dds_load_dataset` Java: `maps_android_dds_load_dataset` | `verifyDatasetLayerInitialization_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.DatasetLayerSnippetsTest#verifyDatasetLayerInitialization_falsifiable` | [ ] ___/5 |
+| `eb3ed819` | **Change the style of custom dataset features on a map. ** *Custom Geospatial Datasets* | ⏳ Pending | Kotlin: `maps_android_dds_style_dataset` Java: `maps_android_dds_style_dataset` | `verifyDatasetFeatureStylingAndPointRadius_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.DatasetLayerSnippetsTest#verifyDatasetFeatureStylingAndPointRadius_falsifiable` | [ ] ___/5 |
+| `5b54c6a7` | **Create a reusable, cross-platform geospatial dataset.** *Custom Geospatial Datasets* | ⏳ Pending | Kotlin: `maps_android_dds_load_dataset` Java: `maps_android_dds_load_dataset` | `verifyDatasetLayerInitialization_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.DatasetLayerSnippetsTest#verifyDatasetLayerInitialization_falsifiable` | [ ] ___/5 |
+| `e72146cb` | **Respond to user interactions with custom dataset features on a map.** *Custom Geospatial Datasets* | ⏳ Pending | Kotlin: `maps_android_dds_dataset_click` Java: `maps_android_dds_dataset_click` | `verifyDatasetFeatureClickListener_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.DatasetLayerSnippetsTest#verifyDatasetFeatureClickListener_falsifiable` | [ ] ___/5 |
+| `0a767a66` | **Add choropleth styling to a map.** *Data-Driven Boundary Styling* | ⏳ Pending | Kotlin: `maps_android_dds_choropleth` Java: `maps_android_dds_choropleth` | `verifyChoroplethFeatureStyleFactory_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.DataDrivenBoundarySnippetsTest#verifyChoroplethFeatureStyleFactory_falsifiable` | [ ] ___/5 |
+| `dedc17af` | **Change the style of boundaries on a map.** *Data-Driven Boundary Styling* | ⏳ Pending | Kotlin: `maps_android_dds_style_boundary` Java: `maps_android_dds_style_boundary` | `verifyFeatureLayerBoundaryStyling_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.DataDrivenBoundarySnippetsTest#verifyFeatureLayerBoundaryStyling_falsifiable` | [ ] ___/5 |
+| `fa7cc2f9` | **Respond to user interactions with boundaries on a map.** *Data-Driven Boundary Styling* | ⏳ Pending | Kotlin: `maps_android_dds_boundary_click` Java: `maps_android_dds_boundary_click` | `verifyFeatureLayerBoundaryClickEvent_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.DataDrivenBoundarySnippetsTest#verifyFeatureLayerBoundaryClickEvent_falsifiable` | [ ] ___/5 |
+| `b34458f3` | **Respond to user interactions and events on a map** *Events* | ✅ Falsified | Kotlin: `EventsSnippets.kt#L41-L48` Java: `EventsSnippets.java#L53-L72` | `verifyMapClickListenerAndEvents_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.EventsSnippetsTest#verifyMapClickListenerAndEvents_falsifiable` | [ ] ___/5 |
+| `232ecd00` | **Add a customizable, interactive map to a web page or mobile app.** *Map Initialization* | ✅ Falsified | Kotlin: `MapInitSnippets.kt#L64-L72` Java: `MapInitSnippets.java#L70-L78` | `verifyBasicMapActivity_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MapInitSnippetsTest#verifyBasicMapActivity_falsifiable` | [ ] ___/5 |
+| `20793ebb` | **Add a traffic layer to a map.** *Map Initialization* | ✅ Falsified | Kotlin: `MapInitSnippets.kt#L184-L186` Java: `MapInitSnippets.java#L193-L195` | `verifyEnableTrafficLayer_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MapInitSnippetsTest#verifyEnableTrafficLayer_falsifiable` | [ ] ___/5 |
+| `25bf9dfd` | **Change the map color scheme.** *Map Initialization* | ⏳ Pending | Kotlin: `MapInitSnippets.kt#L173-L176` Java: `MapInitSnippets.java#L182-L185` | `verifySetMapColorScheme_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MapInitSnippetsTest#verifySetMapColorScheme_falsifiable` | [ ] ___/5 |
+| `c511ea57` | **Change the map type.** *Map Initialization* | ✅ Falsified | Kotlin: `MapInitSnippets.kt#L80-L85` Java: `MapInitSnippets.java#L86-L91` | `verifySetMapTypeToHybrid_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MapInitSnippetsTest#verifySetMapTypeToHybrid_falsifiable` | [ ] ___/5 |
+| `ca51263d` | **Create a reusable map identifier to store map configuration and styling settings.** *Map Initialization* | ⏳ Pending | Kotlin: `MapInitSnippets.kt#L110-L114` Java: `MapInitSnippets.java#L116-L120` | `verifyMapIdInitialization_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MapInitSnippetsTest#verifyMapIdInitialization_falsifiable` | [ ] ___/5 |
+| `9eeb4a1a` | **Customize the controls that appear on a map.** *Map Initialization* | ⏳ Pending | Kotlin: `MapInitSnippets.kt#L97-L102` Java: `MapInitSnippets.java#L103-L108` | `verifyMapControlsCustomization_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MapInitSnippetsTest#verifyMapControlsCustomization_falsifiable` | [ ] ___/5 |
+| `7bbfe87e` | **Add a marker to a map.** *Markers* | ✅ Falsified | Kotlin: `MarkerSnippets.kt#L45-L66` Java: `MarkerSnippets.java#L52-L71` | `verifyAddMarkerProperties_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MarkerSnippetsTest#verifyAddMarkerProperties_falsifiable` | [ ] ___/5 |
+| `bdbefba5` | **Add an info window to a map.** *Markers* | ✅ Falsified | Kotlin: `MarkerSnippets.kt#L250-L258` Java: `MarkerSnippets.java#L240-L247` | `verifyInfoWindowCustomizationAndDisplay_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MarkerSnippetsTest#verifyInfoWindowCustomizationAndDisplay_falsifiable` | [ ] ___/5 |
+| `de757d41` | **Customize a marker on a map.** *Markers* | ✅ Falsified | Kotlin: `MarkerSnippets.kt#L104-L111` Java: `MarkerSnippets.java#L107-L113` | `verifyMarkerCustomColorAndIcon_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MarkerSnippetsTest#verifyMarkerCustomColorAndIcon_falsifiable` | [ ] ___/5 |
+| `4c2a9906` | **Respond to user interactions with markers on a map.** *Markers* | ✅ Falsified | Kotlin: `MarkerSnippets.kt#L74-L82` Java: `MarkerSnippets.java#L79-L86` | `verifyMarkerDraggableProperty_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.MarkerSnippetsTest#verifyMarkerDraggableProperty_falsifiable` | [ ] ___/5 |
+| `58007bbe` | **Add a custom tile overlay to a map.** *Overlays* | ⏳ Pending | Kotlin: `OverlaySnippets.kt#L123-L161` Java: `OverlaySnippets.java#L128-L170` | `verifyAddTileOverlayAndProvider_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.OverlaySnippetsTest#verifyAddTileOverlayAndProvider_falsifiable` | [ ] ___/5 |
+| `518c439f` | **Add an overlay image grounded to the surface of a map.** *Overlays* | ⏳ Pending | Kotlin: `OverlaySnippets.kt#L46-L52` Java: `OverlaySnippets.java#L52-L59` | `verifyAddGroundOverlayProperties_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.OverlaySnippetsTest#verifyAddGroundOverlayProperties_falsifiable` | [ ] ___/5 |
+| `246ab3a6` | **Add a shape or line to a map.** *Shapes* | ⏳ Pending | Kotlin: `ShapesSnippets.kt#L53-L73` Java: `ShapesSnippets.java#L64-L84` | `verifyAddPolylineAndPolygonProperties_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.ShapesSnippetsTest#verifyAddPolylineAndPolygonProperties_falsifiable` | [ ] ___/5 |
+| `b8fadfc3` | **Add a configurable, interactive Google Street View to a web page or mobile app.** *Street View* | ⏳ Pending | Kotlin: `StreetViewActivity.kt#L50-L56` Java: `StreetViewActivity.java#L58-L62` | `verifyStreetViewPanoramaInitialization_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.StreetViewSnippetsTest#verifyStreetViewPanoramaInitialization_falsifiable` | [ ] ___/5 |
+| `7b144b66` | **Animate the camera movements for a Google Street View.** *Street View* | ⏳ Pending | Kotlin: `StreetViewActivity.kt#L117-L126` Java: `StreetViewActivity.java#L126-L136` | `verifyStreetViewCameraAnimationAndPose_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.StreetViewSnippetsTest#verifyStreetViewCameraAnimationAndPose_falsifiable` | [ ] ___/5 |
+| `75a7efe9` | **Customize the gestures that are available for Google Street View.** *Street View* | ⏳ Pending | Kotlin: `StreetViewActivity.kt#L95-L102` Java: `StreetViewActivity.java#L102-L109` | `verifyStreetViewGesturesConfiguration_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.StreetViewSnippetsTest#verifyStreetViewGesturesConfiguration_falsifiable` | [ ] ___/5 |
+| `6e3999d1` | **Respond to user interactions and events in a Google Street View.** *Street View* | ⏳ Pending | Kotlin: `StreetViewActivity.kt#L26-L130` Java: `StreetViewActivity.java#L32-L140` | `verifyStreetViewPanoramaReadyAndClickEvents_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.StreetViewSnippetsTest#verifyStreetViewPanoramaReadyAndClickEvents_falsifiable` | [ ] ___/5 |
+| `20fb724a` | **Add GeoJSON data to a map.** *Utility Library* | ⏳ Pending | Kotlin: `UtilsSnippets.kt#L241-L243` Java: `UtilsSnippets.java#L275-L277` | `verifyGeoJsonLayerCreationAndFeatures_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.UtilsSnippetsTest#verifyGeoJsonLayerCreationAndFeatures_falsifiable` | [ ] ___/5 |
+| `f451d761` | **Add a KML layer to a map.** *Utility Library* | ⏳ Pending | Kotlin: `UtilsSnippets.kt#L336-L338` Java: `UtilsSnippets.java#L374-L376` | `verifyKmlLayerCreationAndContainers_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.UtilsSnippetsTest#verifyKmlLayerCreationAndContainers_falsifiable` | [ ] ___/5 |
+| `fbbc9c5a` | **Add a heatmap layer to a map.** *Utility Library* | ⏳ Pending | Kotlin: `UtilsSnippets.kt#L400-L418` Java: `UtilsSnippets.java#L442-L460` | `verifyHeatmapTileProviderDataAndRadius_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.snippets.kotlin.capabilities.UtilsSnippetsTest#verifyHeatmapTileProviderDataAndRadius_falsifiable` | [ ] ___/5 |
+| `2b6457c4` | **Add a map to a Wear OS app.** *Wear OS* | ⏳ Pending | Kotlin: `TODO` Java: `TODO` | `verifyWearOsMapInit_falsifiable` | `./gradlew :snippets:kotlin-app:connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.example.wearosmap.AppLaunchTest#verifyWearOsMapInit_falsifiable` | [ ] ___/5 |
diff --git a/FALSIFIABLE_TESTING_STANDARD.md b/FALSIFIABLE_TESTING_STANDARD.md
new file mode 100644
index 000000000..872242cca
--- /dev/null
+++ b/FALSIFIABLE_TESTING_STANDARD.md
@@ -0,0 +1,177 @@
+# 🧪 Maps SDK Falsifiable Testing Standard & Architecture
+
+This standard defines the mandatory engineering requirements for testing all capabilities in the `googlemaps-samples/android-samples` repository (`comprehensive-catalog`).
+
+Our guiding principle is **Scientific Falsifiability**:
+> *A test is only valid if we have proven that breaking or removing the code under test causes the test to strictly and immediately fail.*
+
+Tests that only check "did the app launch without crashing" or that rely on vague, polite LLM visual evaluations ("a map is visible... reply PASSED") are **strictly prohibited** as sole verification mechanisms.
+
+---
+
+## 🏛️ 1. Core Architectural Rules
+
+### Rule 1: Modular Test Organization by Capability Group (No Monoliths)
+All tests **must** mirror the hierarchical separation of our snippet catalog across both `kotlin-app` and `java-app`. Placing all tests into a single monolithic file (e.g., `VisualTests.kt`) is strictly prohibited.
+
+#### Required Directory Structure (`kotlin-app` & `java-app`)
+```text
+snippets//src/androidTest/java/com/example/snippets//
+├── discovery/
+│ └── SnippetDiscoveryTest. # Generic startup & metadata validation
+├── capabilities/
+│ ├── CameraControlSnippetsTest. # Exact programmatic & boundary tests for Camera
+│ ├── MarkerSnippetsTest. # Programmatic & negative tests for Markers
+│ ├── ShapesSnippetsTest. # Exact shape property checks (Polygon/Polyline/Circle)
+│ ├── OverlaySnippetsTest. # Tile & Ground overlay property & state checks
+│ ├── MapInitSnippetsTest. # MapType, color scheme, traffic, & indoor state checks
+│ ├── DataDrivenBoundarySnippetsTest. # DDS boundary styling & interaction checks
+│ ├── DatasetLayerSnippetsTest. # Dataset feature loading & styling checks
+│ ├── CloudCustomizationSnippetsTest. # Map ID & Cloud styling checks
+│ └── StreetViewSnippetsTest. # Panorama gestures, animations, & events checks
+└── visual/
+ ├── BaseVisualTest. # Screenshot capture & Gemini helper setup
+ └── VisualTest. # Dedicated LLM visual regression tests (if needed)
+```
+
+### Rule 2: Strict Separation of Deterministic vs. LLM Visual Tests
+* **Deterministic Capability Tests (`capabilities/` directory):** Run 100% locally via `UiAutomator` / `ActivityScenario` + programmatic `GoogleMap` inspection. They must run fast (< 5s per test), require no external network or Gemini API keys, and have **zero flakiness**.
+* **LLM Visual Regression Tests (`visual/` directory):** Used *exclusively* to verify complex visual rendering across device densities (e.g., custom markers, heatmap gradients, choropleth visual shading). They must never be used as a substitute for checking programmatic state or boundary enforcement.
+
+---
+
+## 🔬 2. The Three Pillars of Falsifiable Testing
+
+Every capability sample (`@SnippetItem`) in our catalog must be verified using **at least two** of the following three pillars inside its dedicated capability test file (`SnippetsTest`):
+
+```mermaid
+graph TD
+ A["Capability Code Under Test ( e.g. Snippet.action)"] --> B["Pillar 1: Programmatic State Assertion"]
+ A --> C["Pillar 2: Adversarial Boundary & Negative Test"]
+ A --> D["Pillar 3: Simulated Event & Callback Falsification"]
+
+ B -->|"Assert exact state (mapType, position, zoom, points)"| E["Must Fail if Code Mutated/Removed"]
+ C -->|"Attempt to breach constraint (drag outside bounds, zoom past max)"| E
+ D -->|"Simulate synthetic interaction (onMapClick, onMarkerClick)"| E
+```
+
+### Pillar 1: Exact Programmatic State Assertion
+Instead of testing whether a `MapView` is not null, the test **must** execute `snippet.action(activity, googleMap, scope)` and assert the exact side effects on the underlying SDK objects (`GoogleMap`, `Marker`, `Polygon`, `UiSettings`).
+
+#### Example: Map Type & Traffic Layer Falsification
+```kotlin
+@Test
+fun verifySetMapTypeToHybrid_falsifiable() {
+ launchMapAndRunSnippet("Map Initialization", "2. Set Map Type Hybrid") { map ->
+ // Falsifiability check: If snippet code is removed or changed to MAP_TYPE_NORMAL, this fails!
+ assertEquals("GoogleMap type must be HYBRID after snippet execution", GoogleMap.MAP_TYPE_HYBRID, map.mapType)
+ }
+}
+
+@Test
+fun verifyEnableTrafficLayer_falsifiable() {
+ launchMapAndRunSnippet("Map Initialization", "3. Enable Traffic Layer") { map ->
+ assertTrue("Traffic layer must be explicitly enabled", map.isTrafficEnabled)
+ }
+}
+```
+
+---
+
+### Pillar 2: Adversarial Boundary & Negative Testing ("Try to Break It")
+To prove a constraint works, the test must actively attempt to break, breach, or violate that constraint and verify that the underlying API blocks the attempt.
+
+#### Example 1: Camera Clamping & Panning Restrictions (`2a3e0c25` / `0e6b228f`)
+If a capability sets geographic bounds to Australia (`setLatLngBoundsForCameraTarget`), the test must actively try to force the camera outside of Australia (e.g., London or Antarctica).
+```kotlin
+@Test
+fun verifyCameraClampingToAustralia_falsifiable() {
+ launchMapAndRunSnippet("Camera", "2. Fit Camera To Bounds (Australia)") { map ->
+ val australiaBounds = LatLngBounds(LatLng(-44.0, 113.0), LatLng(-10.0, 154.0))
+
+ // 1. Assert initial target is inside Australia
+ assertTrue("Initial camera target must be in Australia", australiaBounds.contains(map.cameraPosition.target))
+
+ // 2. ADVERSARIAL ATTEMPT: Try forcing camera to London (outside bounds)
+ val london = LatLng(51.5074, -0.1278)
+ map.moveCamera(CameraUpdateFactory.newLatLng(london))
+
+ // 3. FALSIFIABILITY ASSERTION: The camera target MUST remain inside/clamped to Australia!
+ // If setLatLngBoundsForCameraTarget was removed or broken, map moves to London and this test FAILS!
+ assertTrue("Camera must reject move to London and remain clamped within Australia", australiaBounds.contains(map.cameraPosition.target))
+ }
+}
+```
+
+#### Example 2: Zoom Constraints (`setMinZoomPreference` / `setMaxZoomPreference`)
+```kotlin
+@Test
+fun verifyZoomLevelConstraints_falsifiable() {
+ launchMapAndRunSnippet("Camera", "1. Zoom Level Constraints") { map ->
+ // Assume snippet sets minZoom = 10f, maxZoom = 15f
+
+ // ADVERSARIAL ATTEMPT 1: Try zooming way out below minZoom
+ map.moveCamera(CameraUpdateFactory.zoomTo(2f))
+ assertTrue("Zoom must not drop below minZoom (10f)", map.cameraPosition.zoom >= 10f)
+
+ // ADVERSARIAL ATTEMPT 2: Try zooming way in past maxZoom
+ map.moveCamera(CameraUpdateFactory.zoomTo(21f))
+ assertTrue("Zoom must not exceed maxZoom (15f)", map.cameraPosition.zoom <= 15f)
+ }
+}
+```
+
+#### Example 3: Draggable Marker Enforcement (`4c2a9906`)
+```kotlin
+@Test
+fun verifyMarkerDraggableProperty_falsifiable() {
+ launchMapAndRunSnippet("Markers", "2. Draggable Marker") { map, marker ->
+ assertNotNull("Snippet must add a marker", marker)
+ assertTrue("Marker must be configured as draggable = true", marker!!.isDraggable)
+
+ // Negative check: If we set draggable = false, verify it rejects programmatic/gesture drags
+ marker.isDraggable = false
+ assertFalse("Marker should now reject drag interactions", marker.isDraggable)
+ }
+}
+```
+
+---
+
+### Pillar 3: Simulated Event & Callback Falsification
+When testing listener registrations (`setOnMapClickListener`, `setOnMarkerClickListener`, `setOnCameraIdleListener`, `setOnPolygonClickListener`), the test must trigger synthetic interactions and use a `CountDownLatch` or coroutine `Channel` to assert that the exact callback fires with the exact payload.
+
+#### Example: Polygon & Marker Click Listeners
+```kotlin
+@Test
+fun verifyMarkerClickListenerRegistration_falsifiable() {
+ launchMapAndRunSnippet("Markers", "1. Add a Marker") { map, marker ->
+ val clickLatch = CountDownLatch(1)
+ var clickedMarkerTitle: String? = null
+
+ map.setOnMarkerClickListener { m ->
+ clickedMarkerTitle = m.title
+ clickLatch.countDown()
+ true
+ }
+
+ // Simulate programmatic/UiAutomator click on the marker
+ uiDevice.click(uiDevice.displayWidth / 2, uiDevice.displayHeight / 2)
+
+ val fired = clickLatch.await(3, TimeUnit.SECONDS)
+ assertTrue("Marker click callback must fire within 3 seconds", fired)
+ assertEquals("Callback must return exact marker title", marker!!.title, clickedMarkerTitle)
+ }
+}
+```
+
+---
+
+## 📋 3. Mandatory Falsifiability Checklist for Code Reviews
+
+Before any capability or snippet change is approved (`VERIFICATION_CHECKLIST.md`), the reviewer must verify that its accompanying test in `snippets//src/androidTest/.../capabilities/` answers **YES** to all four questions:
+
+1. **Does the test directly inspect `GoogleMap`, `Marker`, `Polygon`, `Polyline`, or `UiSettings` state?** *(If NO -> Rejected)*
+2. **If the snippet's `action()` code is completely commented out, does the test immediately fail?** *(If NO -> Rejected)*
+3. **If the snippet's numeric or state inputs (`LatLng`, colors, zoom levels) are mutated to incorrect values, does the test fail?** *(If NO -> Rejected)*
+4. **Does the test run deterministically without relying on vague LLM image descriptions or arbitrary `delay()` timers?** *(If NO -> Rejected)*
diff --git a/MANUAL_VERIFY_CATALOG.html b/MANUAL_VERIFY_CATALOG.html
new file mode 100644
index 000000000..2c5e642e1
--- /dev/null
+++ b/MANUAL_VERIFY_CATALOG.html
@@ -0,0 +1,5613 @@
+
+
+
+
+
+ Maps SDK Focused Review & Live Execution Dashboard
+
+
+
+
+
+
+
+
+
🗺️ Maps SDK Focused Review & Live Execution Dashboard
+
Step through capabilities one at a time. Run or launch dedicated Kotlin and Java versions right from the UI!
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Capability 1 of 39
+
+
+
+
+
+
+
+
+
+
+
📦 Falsifiable Capability Test Suites Center
+ Execute Complete Or Grouped Test Suites
+
+
+ Execute full verification suites across Kotlin and Java right on your connected Android device. All tests are falsifiable and scientifically verify exact SDK behavior.
+
+
+
+
+
+
+
+
+ 🚀 Master Catalog Test Suite
+
+
Runs all 14 verified capability tests across Markers, Camera, Map Initialization, and Events simultaneously in one single Gradle invocation.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 📍 Markers Capability Suite (4 Tests)
+
+
Verifies Add Marker (`7bbfe87e`), Info Windows (`bdbefba5`), Styling & Opacity (`de757d41`), and Draggable interaction (`4c2a9906`).
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 📷 Camera Controls Suite (2 Tests)
+
+
Verifies Zoom Level Constraints (`2a3e0c25`) and Panning Bounds Restrictions (`0e6b228f`).
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 🗺️ Map Initialization Suite (3 Verified Tests)
+
+
Verifies Basic Map Activity (`232ecd00`), Enable Traffic (`20793ebb`), and Map Type Hybrid (`c511ea57`).
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ⚡ Events & Interactions Suite (2 Checks)
+
+
Verifies Map Click Listener disabling (`b34458f3`) and POI Click Listener registration (`b34458f3`).
+
+
+
+
+
+
+
+
+
+
+
+
+ Execution Terminal Output:
+
+
+
+
+
+
+
Ready to execute test suites...
+
+
+
+
+
+
+
+
+ #1 of 39
+ 2a3e0c25
+ Camera
+ ✅ Falsification Verified
+
fun verifyCameraMovementsAndZoomConstraints_falsifiable() {
+ // Capability 2a3e0c25: ZoomLevelConstraints
+ runWithMap("Camera", "1. ZoomLevelConstraints") { map ->
+ var clampedMinZoom = 0.0f
+ var clampedMaxZoom = 0.0f
+
+ // Run camera mutations and reads strictly on UI main thread using runOnMainSync
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ // Attempt to zoom out below minZoom (6.0f)
+ map.moveCamera(CameraUpdateFactory.zoomTo(2.0f))
+ clampedMinZoom = map.cameraPosition.zoom
+
+ // Attempt to zoom in above maxZoom (14.0f)
+ map.moveCamera(CameraUpdateFactory.zoomTo(21.0f))
+ clampedMaxZoom = map.cameraPosition.zoom
+ }
+
+ assertTrue(
+ "Zoom level ($clampedMinZoom) must strictly clamp to >= 6.0f when minZoomPreference is enabled! " +
+ "If setMinZoomPreference(6.0f) is removed or broken in the snippet, this test fails.",
+ clampedMinZoom >= 5.9f
+ )
+ assertTrue(
+ "Zoom level ($clampedMaxZoom) must strictly clamp to <= 14.0f when maxZoomPreference is enabled! " +
+ "If setMaxZoomPreference(14.0f) is removed or broken in the snippet, this test fails.",
+ clampedMaxZoom <= 14.1f
+ )
+ }
+ }
+
// [START maps_android_camera_and_view_panning_restrictions]
+ // Create a LatLngBounds that includes the city of Adelaide in Australia.
+ val adelaideBounds = LatLngBounds(
+ LatLng(-35.0, 138.58), // SW bounds
+ LatLng(-34.9, 138.61) // NE bounds
+ )
+
+ // Constrain the camera target to the Adelaide bounds.
+ map.setLatLngBoundsForCameraTarget(adelaideBounds)
+ // [END maps_android_camera_and_view_panning_restrictions]
+
+
+
+
+
+ 🧪 Kotlin Test: CameraControlSnippetsTest
+
+
+
+
fun verifyCameraClampingToAustralia_falsifiable() {
+ // Capability 0e6b228f: PanningRestrictions (Constrain target to geographic bounds)
+ runWithMap("Camera", "4. PanningRestrictions") { map ->
+ var currentTarget: LatLng? = null
+
+ // Run camera mutations strictly on UI main thread using runOnMainSync
+ InstrumentationRegistry.getInstrumentation().runOnMainSync {
+ // Attempt to pan camera to London, UK (51.5074, -0.1278)
+ val london = LatLng(51.5074, -0.1278)
+ map.moveCamera(CameraUpdateFactory.newLatLng(london))
+ currentTarget = map.cameraPosition.target
+ }
+
+ assertNotNull("Camera target must not be null", currentTarget)
+ // Adelaide bounds are LatLng(-35.0, 138.58) to LatLng(-34.9, 138.61).
+ // When clamped, target latitude MUSTNOT be near London (51.5), but clamped inside/near Adelaide (-35 to -34.9).
+ assertTrue(
+ "Camera target latitude (${currentTarget!!.latitude}) must be clamped near Adelaide bounds (-35.0 to -34.9) and NOT allowed to move to London (51.5)! " +
+ "If setLatLngBoundsForCameraTarget() is removed from the snippet, this test fails.",
+ currentTarget!!.latitude < -30.0
+ )
+ assertTrue(
+ "Camera target longitude (${currentTarget!!.longitude}) must be clamped near Adelaide bounds (138.58 to 138.61) and NOTLondon (-0.12)! " +
+ "If setLatLngBoundsForCameraTarget() is removed from the snippet, this test fails.",
+ currentTarget!!.longitude > 130.0
+ )
+ }
+ }
+
// [START maps_android_camera_and_view_panning_restrictions]
+ // Create a LatLngBounds that includes the city of Adelaide in Australia.
+ LatLngBounds adelaideBounds = newLatLngBounds(
+ newLatLng(-35.0, 138.58), // SW bounds
+ newLatLng(-34.9, 138.61) // NE bounds
+ );
+
+ // Constrain the camera target to the Adelaide bounds.
+ map.setLatLngBoundsForCameraTarget(adelaideBounds);
+ // [END maps_android_camera_and_view_panning_restrictions]
+
+
+
+
+
+ 🧪 Java Test: CameraControlSnippetsTest
+
+
+
+
publicvoid verifyCameraClampingToAustralia_falsifiable() throws InterruptedException {
+ // Capability 0e6b228f: PanningRestrictions (Constrain target to geographic bounds)
+ runWithMap("Camera", "4. PanningRestrictions", map -> {
+ finalLatLng[] targetHolder = newLatLng[1];
+
+ // Run camera mutations strictly on UI main thread using runOnMainSync
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ // Attempt to pan camera to London, UK (51.5074, -0.1278)
+ LatLng london = newLatLng(51.5074, -0.1278);
+ map.moveCamera(CameraUpdateFactory.newLatLng(london));
+ targetHolder[0] = map.getCameraPosition().target;
+ });
+
+ LatLng currentTarget = targetHolder[0];
+ Assert.assertNotNull("Camera target must not be null", currentTarget);
+ // Adelaide bounds are LatLng(-35.0, 138.58) to LatLng(-34.9, 138.61).
+ // When clamped, target latitude MUSTNOT be near London (51.5), but clamped inside/near Adelaide (-35 to -34.9).
+ Assert.assertTrue(
+ "Camera target latitude (" + currentTarget.latitude + ") must be clamped near Adelaide bounds (-35.0 to -34.9) and NOT allowed to move to London (51.5)! " +
+ "If setLatLngBoundsForCameraTarget() is removed from the snippet, this test fails.",
+ currentTarget.latitude < -30.0
+ );
+ Assert.assertTrue(
+ "Camera target longitude (" + currentTarget.longitude + ") must be clamped near Adelaide bounds (138.58 to 138.61) and NOTLondon (-0.12)! " +
+ "If setLatLngBoundsForCameraTarget() is removed from the snippet, this test fails.",
+ currentTarget.longitude > 130.0
+ );
+ });
+ }
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest. Needed for verifyHierarchyZoomStyling_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.CloudCustomizationSnippetsTest. Needed for verifyHierarchyZoomStyling_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest. Needed for verifyPoiDensityFiltering_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.CloudCustomizationSnippetsTest. Needed for verifyPoiDensityFiltering_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest. Needed for verifyBuilding3dAndFootprintStyling_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.CloudCustomizationSnippetsTest. Needed for verifyBuilding3dAndFootprintStyling_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest. Needed for verifyIconAndTextLabelStyling_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.CloudCustomizationSnippetsTest. Needed for verifyIconAndTextLabelStyling_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest. Needed for verifyLandmarkHierarchyStyling_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.CloudCustomizationSnippetsTest. Needed for verifyLandmarkHierarchyStyling_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest. Needed for verifyRoadAndGeometryStyling_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.CloudCustomizationSnippetsTest. Needed for verifyRoadAndGeometryStyling_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest. Needed for verifyReusableMapIdLoading_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.CloudCustomizationSnippetsTest. Needed for verifyReusableMapIdLoading_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.CloudCustomizationSnippetsTest. Needed for verifyFeatureVisibilityToggles_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.CloudCustomizationSnippetsTest. Needed for verifyFeatureVisibilityToggles_falsifiable
// Region tag not found: maps_android_dds_load_dataset
+
+
+
+
+ 🧪 Kotlin Test: DatasetLayerSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.DatasetLayerSnippetsTest. Needed for verifyDatasetLayerInitialization_falsifiable
// Region tag not found: maps_android_dds_load_dataset
+
+
+
+
+ 🧪 Java Test: DatasetLayerSnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.DatasetLayerSnippetsTest. Needed for verifyDatasetLayerInitialization_falsifiable
// Region tag not found: maps_android_dds_style_dataset
+
+
+
+
+ 🧪 Kotlin Test: DatasetLayerSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.DatasetLayerSnippetsTest. Needed for verifyDatasetFeatureStylingAndPointRadius_falsifiable
// Region tag not found: maps_android_dds_style_dataset
+
+
+
+
+ 🧪 Java Test: DatasetLayerSnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.DatasetLayerSnippetsTest. Needed for verifyDatasetFeatureStylingAndPointRadius_falsifiable
// Region tag not found: maps_android_dds_load_dataset
+
+
+
+
+ 🧪 Kotlin Test: DatasetLayerSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.DatasetLayerSnippetsTest. Needed for verifyDatasetLayerInitialization_falsifiable
// Region tag not found: maps_android_dds_load_dataset
+
+
+
+
+ 🧪 Java Test: DatasetLayerSnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.DatasetLayerSnippetsTest. Needed for verifyDatasetLayerInitialization_falsifiable
// Region tag not found: maps_android_dds_dataset_click
+
+
+
+
+ 🧪 Kotlin Test: DatasetLayerSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.DatasetLayerSnippetsTest. Needed for verifyDatasetFeatureClickListener_falsifiable
// Region tag not found: maps_android_dds_dataset_click
+
+
+
+
+ 🧪 Java Test: DatasetLayerSnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.DatasetLayerSnippetsTest. Needed for verifyDatasetFeatureClickListener_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.DataDrivenBoundarySnippetsTest. Needed for verifyChoroplethFeatureStyleFactory_falsifiable
// Region tag not found: maps_android_dds_choropleth
+
+
+
+
+ 🧪 Java Test: DataDrivenBoundarySnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.DataDrivenBoundarySnippetsTest. Needed for verifyChoroplethFeatureStyleFactory_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.DataDrivenBoundarySnippetsTest. Needed for verifyFeatureLayerBoundaryStyling_falsifiable
// Region tag not found: maps_android_dds_style_boundary
+
+
+
+
+ 🧪 Java Test: DataDrivenBoundarySnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.DataDrivenBoundarySnippetsTest. Needed for verifyFeatureLayerBoundaryStyling_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.DataDrivenBoundarySnippetsTest. Needed for verifyFeatureLayerBoundaryClickEvent_falsifiable
// Region tag not found: maps_android_dds_boundary_click
+
+
+
+
+ 🧪 Java Test: DataDrivenBoundarySnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.DataDrivenBoundarySnippetsTest. Needed for verifyFeatureLayerBoundaryClickEvent_falsifiable
// [START maps_android_map_fragment]
+ if (context is FragmentActivity) {
+ val mapFragment = SupportMapFragment.newInstance()
+ context.supportFragmentManager
+ .beginTransaction()
+ .add(com.example.snippets.common.R.id.map_container, mapFragment)
+ .commit()
+ }
+ // [END maps_android_map_fragment]
+
+
+
+
+
+ 🧪 Kotlin Test: MapInitSnippetsTest
+
+
+
+
fun verifyBasicMapActivity_falsifiable() {
+ // Capability 232ecd00: Add a customizable, interactive map to a web page or mobile app
+ runWithMap("MapInitialization", "1. BasicMapActivity") { map ->
+ val sydney = com.google.android.gms.maps.model.LatLng(-34.0, 151.0)
+
+ // FalsifiabilityCheck 1: Verify exact initial target centered near Sydney
+ val target = map.cameraPosition.target
+ assertTrue("Camera target latitude must be near Sydney (-34.0)", Math.abs(target.latitude - sydney.latitude) < 0.1)
+ assertTrue("Camera target longitude must be near Sydney (151.0)", Math.abs(target.longitude - sydney.longitude) < 0.1)
+ }
+ }
+
publicvoid verifyBasicMapActivity_falsifiable() throws InterruptedException {
+ // Capability 232ecd00: Add a customizable, interactive map to a web page or mobile app
+ runWithMap("MapInitialization", "1. BasicMapActivity", map -> {
+ LatLng sydney = newLatLng(-34.0, 151.0);
+
+ // FalsifiabilityCheck 1: Verify exact initial target centered near Sydney
+ LatLng target = map.getCameraPosition().target;
+ Assert.assertTrue("Camera target latitude must be near Sydney (-34.0)", Math.abs(target.latitude - sydney.latitude) < 0.1);
+ Assert.assertTrue("Camera target longitude must be near Sydney (151.0)", Math.abs(target.longitude - sydney.longitude) < 0.1);
+ });
+ }
+
fun verifyEnableTrafficLayer_falsifiable() {
+ // Capability 20793ebb: Add a traffic layer to a map
+ runWithMap("MapInitialization", "4. EnableTrafficLayer") { map ->
+ // FalsifiabilityCheck: If snippet code is removed or changed to isTrafficEnabled = false, this test STRICTLYFAILS!
+ assertTrue("googleMap.isTrafficEnabled MUST be true after snippet execution", map.isTrafficEnabled)
+ }
+ }
+
publicvoid verifyEnableTrafficLayer_falsifiable() throws InterruptedException {
+ // Capability 20793ebb: Add a traffic layer to a map
+ runWithMap("MapInitialization", "4. EnableTrafficLayer", map -> {
+ // FalsifiabilityCheck: If snippet code is removed or changed to isTrafficEnabled = false, this test STRICTLYFAILS!
+ Assert.assertTrue("googleMap.isTrafficEnabled() MUST be true after Java snippet execution", map.isTrafficEnabled());
+ });
+ }
+
// [START maps_android_map_type]
+ // Sets the map type to be "hybrid"
+ map.setMapType(GoogleMap.MAP_TYPE_HYBRID)
+ map.setIndoorEnabled(true)
+ val isIndoor = map.isIndoorEnabled()
+ // [END maps_android_map_type]
+
+
+
+
+
+ 🧪 Kotlin Test: MapInitSnippetsTest
+
+
+
+
fun verifySetMapTypeToHybrid_falsifiable() {
+ // Capability c511ea57: Change the map type
+ runWithMap("MapInitialization", "3. SetMapType") { map ->
+ // FalsifiabilityCheck: If changed to MAP_TYPE_NORMAL or commented out, this test STRICTLYFAILS!
+ assertEquals("GoogleMap type must be exactly MAP_TYPE_HYBRID (4)", GoogleMap.MAP_TYPE_HYBRID, map.mapType)
+ }
+ }
+
// [START maps_android_map_type]
+ // Sets the map type to be "hybrid"
+ map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
+ map.setIndoorEnabled(true);
+ boolean isIndoor = map.isIndoorEnabled();
+ // [END maps_android_map_type]
+
+
+
+
+
+ 🧪 Java Test: MapInitSnippetsTest
+
+
+
+
publicvoid verifySetMapTypeToHybrid_falsifiable() throws InterruptedException {
+ // Capability c511ea57: Change the map type
+ runWithMap("MapInitialization", "3. SetMapType", map -> {
+ // FalsifiabilityCheck: If changed to MAP_TYPE_NORMAL or commented out, this test STRICTLYFAILS!
+ Assert.assertEquals("GoogleMap type must be exactly MAP_TYPE_HYBRID (4)", GoogleMap.MAP_TYPE_HYBRID, map.getMapType());
+ });
+ }
+
// [START maps_android_markers_add_a_marker]
+ // Add a marker in Sydney, Australia,
+ // and move the map's camera to the same location.
+ val sydney = LatLng(-33.852, 151.211)
+ val marker = map.addMarker(
+ MarkerOptions()
+ .position(sydney)
+ .title("Marker in Sydney")
+ )
+ marker?.let {
+ val position = it.position
+ val title = it.title
+ val snippet = it.snippet
+ val isDraggable = it.isDraggable
+ val isFlat = it.isFlat
+ val isVisible = it.isVisible
+ val alpha = it.alpha
+ val rotation = it.rotation
+ val zIndex = it.zIndex
+ }
+ map.moveCamera(CameraUpdateFactory.newLatLng(sydney))
+ // [END maps_android_markers_add_a_marker]
+
+
+
+
+
+ 🧪 Kotlin Test: MarkerSnippetsTest
+
+
+
+
fun verifyAddMarkerProperties_falsifiable() {
+ // Capability 7bbfe87e: Add a marker to a map
+ runWithMap("Markers", "1. Add a Marker") { map ->
+ val marker = TrackedMap.lastInstance?.items?.filterIsInstance<Marker>()?.firstOrNull()
+ assertNotNull(
+ "Marker must be added by '1. Add a Marker'! If addMarker() snippet code is removed or broken, this test fails.",
+ marker
+ )
+ assertEquals(
+ "Marker latitude must exactly match Sydney (-33.852)",
+ -33.852, marker!!.position.latitude, 0.001
+ )
+ assertEquals(
+ "Marker longitude must exactly match Sydney (151.211)",
+ 151.211, marker.position.longitude, 0.001
+ )
+ assertEquals(
+ "Marker title must be exactly 'Marker in Sydney'",
+ "Marker in Sydney", marker.title
+ )
+ }
+ }
+
// [START maps_android_markers_add_a_marker]
+ // Add a marker in Sydney, Australia,
+ // and move the map's camera to the same location.
+ LatLng sydney = newLatLng(-33.852, 151.211);
+ Marker marker = map.addMarker(newMarkerOptions()
+ .position(sydney)
+ .title("Marker in Sydney"));
+ if (marker != null) {
+ LatLng position = marker.getPosition();
+ String title = marker.getTitle();
+ String snippet = marker.getSnippet();
+ boolean isDraggable = marker.isDraggable();
+ boolean isFlat = marker.isFlat();
+ boolean isVisible = marker.isVisible();
+ float alpha = marker.getAlpha();
+ float rotation = marker.getRotation();
+ float zIndex = marker.getZIndex();
+ }
+ map.moveCamera(CameraUpdateFactory.newLatLng(sydney));
+ // [END maps_android_markers_add_a_marker]
+
+
+
+
+
+ 🧪 Java Test: MarkerSnippetsTest
+
+
+
+
publicvoid verifyAddMarkerProperties_falsifiable() throws InterruptedException {
+ // Capability 7bbfe87e: Add a marker to a map
+ runWithMap("Markers", "1. Add a Marker", map -> {
+ Marker marker = getFirstMarker();
+ Assert.assertNotNull(
+ "Marker must be added by '1. Add a Marker'! If addMarker() snippet code is removed or broken, this test fails.",
+ marker
+ );
+ Assert.assertEquals(
+ "Marker latitude must exactly match Sydney (-33.852)",
+ -33.852, marker.getPosition().latitude, 0.001
+ );
+ Assert.assertEquals(
+ "Marker longitude must exactly match Sydney (151.211)",
+ 151.211, marker.getPosition().longitude, 0.001
+ );
+ Assert.assertEquals(
+ "Marker title must be exactly 'Marker in Sydney'",
+ "Marker in Sydney", marker.getTitle()
+ );
+ });
+ }
+
fun verifyInfoWindowCustomizationAndDisplay_falsifiable() {
+ // Capability bdbefba5: Add an info window to a map
+ runWithMap("Markers", "11. AddInfoWindow") { map ->
+ val marker = TrackedMap.lastInstance?.items?.filterIsInstance<Marker>()?.firstOrNull()
+ assertNotNull(
+ "Marker must be added by '11. AddInfoWindow'! If snippet code is removed, this test fails.",
+ marker
+ )
+ assertEquals("Marker title must be exactly 'Melbourne'", "Melbourne", marker!!.title)
+ assertEquals("Marker snippet must be exactly 'Population: 4,137,400'", "Population: 4,137,400", marker.snippet)
+ }
+ }
+
publicvoid verifyInfoWindowCustomizationAndDisplay_falsifiable() throws InterruptedException {
+ // Capability bdbefba5: Add an info window to a map
+ runWithMap("Markers", "11. AddInfoWindow", map -> {
+ Marker marker = getFirstMarker();
+ Assert.assertNotNull(
+ "Marker must be added by '11. AddInfoWindow'! If snippet code is removed, this test fails.",
+ marker
+ );
+ Assert.assertEquals("Marker title must be exactly 'Melbourne'", "Melbourne", marker.getTitle());
+ Assert.assertEquals("Marker snippet must be exactly 'Population: 4,137,400'", "Population: 4,137,400", marker.getSnippet());
+ });
+ }
+
fun verifyMarkerCustomColorAndIcon_falsifiable() {
+ // Capability de757d41: Customize a marker on a map
+ runWithMap("Markers", "5. MarkerOpacity") { map ->
+ val marker = TrackedMap.lastInstance?.items?.filterIsInstance<Marker>()?.firstOrNull()
+ assertNotNull("Marker must be added by '5. MarkerOpacity'", marker)
+ assertEquals(
+ "Marker alpha must exactly match 0.7f! If .alpha(0.7f) is removed or mutated in snippet, this test fails.",
+ 0.7f, marker!!.alpha, 0.001f
+ )
+ }
+
+ runWithMap("Markers", "7. FlatMarker") { map ->
+ val marker = TrackedMap.lastInstance?.items?.filterIsInstance<Marker>()?.firstOrNull()
+ assertNotNull("Marker must be added by '7. FlatMarker'", marker)
+ assertTrue(
+ "Marker isFlat must exactly match true! If .flat(true) is removed in snippet, this test fails.",
+ marker!!.isFlat
+ )
+ }
+
+ runWithMap("Markers", "8. RotateMarker") { map ->
+ val marker = TrackedMap.lastInstance?.items?.filterIsInstance<Marker>()?.firstOrNull()
+ assertNotNull("Marker must be added by '8. RotateMarker'", marker)
+ assertEquals(
+ "Marker rotation must exactly match 90.0f! If .rotation(90.0f) is removed in snippet, this test fails.",
+ 90.0f, marker!!.rotation, 0.001f
+ )
+ }
+ }
+
publicvoid verifyMarkerCustomColorAndIcon_falsifiable() throws InterruptedException {
+ // Capability de757d41: Customize a marker on a map
+ runWithMap("Markers", "5. MarkerOpacity", map -> {
+ Marker marker = getFirstMarker();
+ Assert.assertNotNull("Marker must be added by '5. MarkerOpacity'", marker);
+ Assert.assertEquals(
+ "Marker alpha must exactly match 0.7f! If .alpha(0.7f) is removed or mutated in snippet, this test fails.",
+ 0.7f, marker.getAlpha(), 0.001f
+ );
+ });
+
+ runWithMap("Markers", "7. FlatMarker", map -> {
+ Marker marker = getFirstMarker();
+ Assert.assertNotNull("Marker must be added by '7. FlatMarker'", marker);
+ Assert.assertTrue(
+ "Marker isFlat must exactly match true! If .flat(true) is removed in snippet, this test fails.",
+ marker.isFlat()
+ );
+ });
+
+ runWithMap("Markers", "8. RotateMarker", map -> {
+ Marker marker = getFirstMarker();
+ Assert.assertNotNull("Marker must be added by '8. RotateMarker'", marker);
+ Assert.assertEquals(
+ "Marker rotation must exactly match 90.0f! If .rotation(90.0f) is removed in snippet, this test fails.",
+ 90.0f, marker.getRotation(), 0.001f
+ );
+ });
+ }
+
fun verifyMarkerDraggableProperty_falsifiable() {
+ // Capability 4c2a9906: Respond to user interactions with markers on a map
+ runWithMap("Markers", "2. DraggableMarker") { map ->
+ val marker = TrackedMap.lastInstance?.items?.filterIsInstance<Marker>()?.firstOrNull()
+ assertNotNull("Draggable marker must be added by '2. DraggableMarker'", marker)
+ assertTrue(
+ "Marker isDraggable must strictly be true! If .draggable(true) is removed in snippet, this test fails.",
+ marker!!.isDraggable
+ )
+
+ // Adversarial negative check (Pillar 2): Mutate to false and verify constraint enforcement
+ marker.isDraggable = false
+ assertFalse(
+ "Marker should strictly reject drag interactions when isDraggable is set to false",
+ marker.isDraggable
+ )
+ }
+ }
+
publicvoid verifyMarkerDraggableProperty_falsifiable() throws InterruptedException {
+ // Capability 4c2a9906: Respond to user interactions with markers on a map
+ runWithMap("Markers", "2. DraggableMarker", map -> {
+ Marker marker = getFirstMarker();
+ Assert.assertNotNull("Draggable marker must be added by '2. DraggableMarker'", marker);
+ Assert.assertTrue(
+ "Marker isDraggable must strictly be true! If .draggable(true) is removed in snippet, this test fails.",
+ marker.isDraggable()
+ );
+
+ // Adversarial negative check (Pillar 2): Mutate to false and verify constraint enforcement
+ marker.setDraggable(false);
+ Assert.assertFalse(
+ "Marker should strictly reject drag interactions when isDraggable is set to false",
+ marker.isDraggable()
+ );
+ });
+ }
+
// [START maps_android_tile_overlays_add]
+ val tileProvider: TileProvider = object : UrlTileProvider(256, 256) {
+ overridefun getTileUrl(x: Int, y: Int, zoom: Int): URL? {
+
+ /* Define the URL pattern for the tile images */
+ val url = "http://my.image.server/images/$zoom/$x/$y.png"
+ returnif (!checkTileExists(x, y, zoom)) {
+ null
+ } elsetry {
+ URL(url)
+ } catch (e: MalformedURLException) {
+ throw AssertionError(e)
+ }
+ }
+
+ /*
+ * Check that the tile server supports the requested x, y and zoom.
+ * Complete this stub according to the tile range you support.
+ * If you support a limited range of tiles at different zoom levels, then you
+ * need to define the supported x, y range at each zoom level.
+ */
+ privatefun checkTileExists(x: Int, y: Int, zoom: Int): Boolean {
+ val minZoom = 12
+ val maxZoom = 16
+ return zoom in minZoom..maxZoom
+ }
+ }
+
+ val tileOverlay = map.addTileOverlay(
+ TileOverlayOptions()
+ .tileProvider(tileProvider)
+ )
+ tileOverlay?.let {
+ val isVisible = it.isVisible
+ val fadeIn = it.fadeIn
+ val transparency = it.transparency
+ val zIndex = it.zIndex
+ }
+ // [END maps_android_tile_overlays_add]
+
+
+
+
+
+ 🧪 Kotlin Test: OverlaySnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.OverlaySnippetsTest. Needed for verifyAddTileOverlayAndProvider_falsifiable
// [START maps_android_tile_overlays_add]
+ TileProvider tileProvider = newUrlTileProvider(256, 256) {
+
+ @Override
+ publicURL 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);
+
+ if (!checkTileExists(x, y, zoom)) {
+ returnnull;
+ }
+
+ try {
+ returnnewURL(s);
+ } catch (MalformedURLException e) {
+ throw newAssertionError(e);
+ }
+ }
+
+ /*
+ * Check that the tile server supports the requested x, y and zoom.
+ * Complete this stub according to the tile range you support.
+ * If you support a limited range of tiles at different zoom levels, then you
+ * need to define the supported x, y range at each zoom level.
+ */
+ privateboolean checkTileExists(int x, int y, int zoom) {
+ int minZoom = 12;
+ int maxZoom = 16;
+
+ return (zoom >= minZoom && zoom <= maxZoom);
+ }
+ };
+
+ TileOverlay tileOverlay = map.addTileOverlay(newTileOverlayOptions()
+ .tileProvider(tileProvider));
+ if (tileOverlay != null) {
+ boolean isVisible = tileOverlay.isVisible();
+ boolean fadeIn = tileOverlay.getFadeIn();
+ float transparency = tileOverlay.getTransparency();
+ float zIndex = tileOverlay.getZIndex();
+ }
+ // [END maps_android_tile_overlays_add]
+
+
+
+
+
+ 🧪 Java Test: OverlaySnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.OverlaySnippetsTest. Needed for verifyAddTileOverlayAndProvider_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.OverlaySnippetsTest. Needed for verifyAddGroundOverlayProperties_falsifiable
// [START maps_android_shapes_polylines_polylineoptions]
+ // Instantiates a newPolyline object and adds points to define a rectangle
+ val polylineOptions = PolylineOptions()
+ .add(LatLng(37.35, -122.0))
+ .add(LatLng(37.45, -122.0)) // North of the previous point, but at the same longitude
+ .add(LatLng(37.45, -122.2)) // Same latitude, and 30km to the west
+ .add(LatLng(37.35, -122.2)) // Same longitude, and 16km to the south
+ .add(LatLng(37.35, -122.0)) // Closes the polyline.
+
+ // Get back the mutable Polyline
+ val polyline = map.addPolyline(polylineOptions)
+ polyline?.let {
+ val isClickable = it.isClickable
+ val isGeodesic = it.isGeodesic
+ val isVisible = it.isVisible
+ val color = it.color
+ val width = it.width
+ val zIndex = it.zIndex
+ val points = it.points
+ }
+ // [END maps_android_shapes_polylines_polylineoptions]
+
+
+
+
+
+ 🧪 Kotlin Test: ShapesSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.ShapesSnippetsTest. Needed for verifyAddPolylineAndPolygonProperties_falsifiable
// [START maps_android_shapes_polylines_polylineoptions]
+ // Instantiates a newPolyline object and adds points to define a rectangle
+ PolylineOptions polylineOptions = newPolylineOptions()
+ .add(newLatLng(37.35, -122.0))
+ .add(newLatLng(37.45, -122.0)) // North of the previous point, but at the same longitude
+ .add(newLatLng(37.45, -122.2)) // Same latitude, and 30km to the west
+ .add(newLatLng(37.35, -122.2)) // Same longitude, and 16km to the south
+ .add(newLatLng(37.35, -122.0)); // Closes the polyline.
+
+ // Get back the mutable Polyline
+ Polyline polyline = map.addPolyline(polylineOptions);
+ if (polyline != null) {
+ boolean isClickable = polyline.isClickable();
+ boolean isGeodesic = polyline.isGeodesic();
+ boolean isVisible = polyline.isVisible();
+ int color = polyline.getColor();
+ float width = polyline.getWidth();
+ float zIndex = polyline.getZIndex();
+ List<LatLng> points = polyline.getPoints();
+ }
+ // [END maps_android_shapes_polylines_polylineoptions]
+
+
+
+
+
+ 🧪 Java Test: ShapesSnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.ShapesSnippetsTest. Needed for verifyAddPolylineAndPolygonProperties_falsifiable
+
+
+
+
+
+
+
+
+ #32 of 39
+ b8fadfc3
+ Street View
+ ⏳ Pending Falsification Check
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.StreetViewSnippetsTest. Needed for verifyStreetViewPanoramaInitialization_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.StreetViewSnippetsTest. Needed for verifyStreetViewPanoramaInitialization_falsifiable
+
+
+
+
+
+
+
+
+ #33 of 39
+ 7b144b66
+ Street View
+ ⏳ Pending Falsification Check
+
// [START maps_street_view_panorama_animate]
+ // Keeping the zoom and tilt. Animate bearing by 60 degrees in 1000 milliseconds.
+ val duration: Long = 1000
+ val camera = StreetViewPanoramaCamera.Builder()
+ .zoom(streetViewPanorama.panoramaCamera.zoom)
+ .tilt(streetViewPanorama.panoramaCamera.tilt)
+ .bearing(streetViewPanorama.panoramaCamera.bearing - 60)
+ .build()
+ streetViewPanorama.animateTo(camera, duration)
+ // [END maps_street_view_panorama_animate]
+
+
+
+
+
+ 🧪 Kotlin Test: StreetViewSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.StreetViewSnippetsTest. Needed for verifyStreetViewCameraAnimationAndPose_falsifiable
// [START maps_street_view_panorama_animate]
+ // Keeping the zoom and tilt. Animate bearing by 60 degrees in 1000 milliseconds.
+ long duration = 1000;
+ StreetViewPanoramaCamera camera =
+ newStreetViewPanoramaCamera.Builder()
+ .zoom(streetViewPanorama.getPanoramaCamera().zoom)
+ .tilt(streetViewPanorama.getPanoramaCamera().tilt)
+ .bearing(streetViewPanorama.getPanoramaCamera().bearing - 60)
+ .build();
+ streetViewPanorama.animateTo(camera, duration);
+ // [END maps_street_view_panorama_animate]
+
+
+
+
+
+ 🧪 Java Test: StreetViewSnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.StreetViewSnippetsTest. Needed for verifyStreetViewCameraAnimationAndPose_falsifiable
+
+
+
+
+
+
+
+
+ #34 of 39
+ 75a7efe9
+ Street View
+ ⏳ Pending Falsification Check
+
// [START maps_street_view_panorama_pan]
+ val panBy = 30f
+ val camera = StreetViewPanoramaCamera.Builder()
+ .zoom(streetViewPanorama.panoramaCamera.zoom)
+ .tilt(streetViewPanorama.panoramaCamera.tilt)
+ .bearing(streetViewPanorama.panoramaCamera.bearing - panBy)
+ .build()
+ // [END maps_street_view_panorama_pan]
+
+
+
+
+
+ 🧪 Kotlin Test: StreetViewSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.StreetViewSnippetsTest. Needed for verifyStreetViewGesturesConfiguration_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.StreetViewSnippetsTest. Needed for verifyStreetViewGesturesConfiguration_falsifiable
+
+
+
+
+
+
+
+
+ #35 of 39
+ 6e3999d1
+ Street View
+ ⏳ Pending Falsification Check
+
// [START maps_street_view_on_street_view_panorama_ready]
+classStreetViewActivity : AppCompatActivity(), OnStreetViewPanoramaReadyCallback {
+ // [START_EXCLUDE]
+ // [START maps_street_view_on_create]
+ overridefun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_street_view)
+ // [START maps_street_view_find_fragment]
+ val streetViewPanoramaFragment =
+ supportFragmentManager
+ .findFragmentById(R.id.street_view_panorama) as SupportStreetViewPanoramaFragment
+ streetViewPanoramaFragment.getStreetViewPanoramaAsync(this)
+ // [END maps_street_view_find_fragment]
+ }
+ // [END maps_street_view_on_create]
+
+ // [START maps_street_view_on_street_view_panorama_ready_callback]
+ overridefun onStreetViewPanoramaReady(streetViewPanorama: StreetViewPanorama) {
+ val sanFrancisco = LatLng(37.754130, -122.447129)
+ streetViewPanorama.setPosition(sanFrancisco)
+ }
+ // [END maps_street_view_on_street_view_panorama_ready_callback]
+
+ privatefun newView() {
+ // [START maps_street_view_new_panorama_view]
+ val sanFrancisco = LatLng(37.754130, -122.447129)
+ val view = StreetViewPanoramaView(
+ this,
+ StreetViewPanoramaOptions().position(sanFrancisco)
+ )
+ // [END maps_street_view_new_panorama_view]
+ }
+
+ privatefun setLocationOfThePanorama(streetViewPanorama: StreetViewPanorama) {
+ // [START maps_street_view_panorama_set_location]
+ val sanFrancisco = LatLng(37.754130, -122.447129)
+
+ // Set position with LatLng only.
+ streetViewPanorama.setPosition(sanFrancisco)
+
+ // Set position with LatLng and radius.
+ streetViewPanorama.setPosition(sanFrancisco, 20)
+
+ // Set position with LatLng and source.
+ streetViewPanorama.setPosition(sanFrancisco, StreetViewSource.OUTDOOR)
+
+ // Set position with LaLng, radius and source.
+ streetViewPanorama.setPosition(sanFrancisco, 20, StreetViewSource.OUTDOOR)
+ // [END maps_street_view_panorama_set_location]
+
+ // [START maps_street_view_panorama_set_location_2]
+ streetViewPanorama.location.links.firstOrNull()?.let { link: StreetViewPanoramaLink ->
+ streetViewPanorama.setPosition(link.panoId)
+ }
+ // [END maps_street_view_panorama_set_location_2]
+ }
+
+ privatefun zoom(streetViewPanorama: StreetViewPanorama) {
+ // [START maps_street_view_panorama_zoom]
+ val zoomBy = 0.5f
+ val camera = StreetViewPanoramaCamera.Builder()
+ .zoom(streetViewPanorama.panoramaCamera.zoom + zoomBy)
+ .tilt(streetViewPanorama.panoramaCamera.tilt)
+ .bearing(streetViewPanorama.panoramaCamera.bearing)
+ .build()
+ // [END maps_street_view_panorama_zoom]
+ }
+
+ privatefun pan(streetViewPanorama: StreetViewPanorama) {
+ // [START maps_street_view_panorama_pan]
+ val panBy = 30f
+ val camera = StreetViewPanoramaCamera.Builder()
+ .zoom(streetViewPanorama.panoramaCamera.zoom)
+ .tilt(streetViewPanorama.panoramaCamera.tilt)
+ .bearing(streetViewPanorama.panoramaCamera.bearing - panBy)
+ .build()
+ // [END maps_street_view_panorama_pan]
+ }
+
+ privatefun tilt(streetViewPanorama: StreetViewPanorama) {
+ // [START maps_street_view_panorama_tilt]
+ var tilt = streetViewPanorama.panoramaCamera.tilt + 30
+ tilt = if (tilt > 90) 90f else tilt
+ val previous = streetViewPanorama.panoramaCamera
+ val camera = StreetViewPanoramaCamera.Builder(previous)
+ .tilt(tilt)
+ .build()
+ // [END maps_street_view_panorama_tilt]
+ }
+
+ privatefun animate(streetViewPanorama: StreetViewPanorama) {
+ // [START maps_street_view_panorama_animate]
+ // Keeping the zoom and tilt. Animate bearing by 60 degrees in 1000 milliseconds.
+ val duration: Long = 1000
+ val camera = StreetViewPanoramaCamera.Builder()
+ .zoom(streetViewPanorama.panoramaCamera.zoom)
+ .tilt(streetViewPanorama.panoramaCamera.tilt)
+ .bearing(streetViewPanorama.panoramaCamera.bearing - 60)
+ .build()
+ streetViewPanorama.animateTo(camera, duration)
+ // [END maps_street_view_panorama_animate]
+ }
+ // [END_EXCLUDE]
+}
+// [END maps_street_view_on_street_view_panorama_ready]
+
+
+
+
+
+ 🧪 Kotlin Test: StreetViewSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.StreetViewSnippetsTest. Needed for verifyStreetViewPanoramaReadyAndClickEvents_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.StreetViewSnippetsTest. Needed for verifyStreetViewPanoramaReadyAndClickEvents_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.UtilsSnippetsTest. Needed for verifyGeoJsonLayerCreationAndFeatures_falsifiable
// JAVA test file not found yet: com.example.snippets.java.capabilities.UtilsSnippetsTest. Needed for verifyGeoJsonLayerCreationAndFeatures_falsifiable
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.UtilsSnippetsTest. Needed for verifyKmlLayerCreationAndContainers_falsifiable
// [START maps_android_utils_heatmap_simple]
+ var latLngs: List<LatLng?>? = null
+
+ // Get the data: latitude/longitude positions of police stations.
+ try {
+ latLngs = readItems(R.raw.police_stations)
+ } catch (e: JSONException) {
+ Toast.makeText(context, "Problem reading list of locations.", Toast.LENGTH_LONG).show()
+ }
+
+ // Create a heat map tile provider, passing it the latlngs of the police stations.
+ val provider = HeatmapTileProvider.Builder()
+ .data(latLngs?.filterNotNull() ?: emptyList())
+ .build()
+
+ // Add a tile overlay to the map, using the heat map tile provider.
+ val overlay = map.addTileOverlay(TileOverlayOptions().tileProvider(provider))
+ map.moveCamera(com.google.android.gms.maps.CameraUpdateFactory.newLatLngZoom(com.google.android.gms.maps.model.LatLng(-37.8136, 144.9631), 10f))
+ // [END maps_android_utils_heatmap_simple]
+
+
+
+
+
+ 🧪 Kotlin Test: UtilsSnippetsTest
+
+
+
+
// KOTLIN test file not found yet: com.example.snippets.kotlin.capabilities.UtilsSnippetsTest. Needed for verifyHeatmapTileProviderDataAndRadius_falsifiable
// [START maps_android_utils_heatmap_simple]
+ List<LatLng> latLngs = newArrayList<>();
+
+ // Get the data: latitude/longitude positions of police stations.
+ try {
+ latLngs = readItems(R.raw.police_stations);
+ } catch (JSONException e) {
+ Toast.makeText(context, "Problem reading list of locations.", Toast.LENGTH_LONG).show();
+ }
+
+ // Create a heat map tile provider, passing it the latlngs of the police stations.
+ HeatmapTileProvider provider = newHeatmapTileProvider.Builder()
+ .data(latLngs)
+ .build();
+
+ // Add a tile overlay to the map, using the heat map tile provider.
+ TileOverlay overlay = map.addTileOverlay(newTileOverlayOptions().tileProvider(provider));
+ map.moveCamera(CameraUpdateFactory.newLatLngZoom(newLatLng(-37.8136, 144.9631), 10f));
+ // [END maps_android_utils_heatmap_simple]
+
+
+
+
+
+ 🧪 Java Test: UtilsSnippetsTest
+
+
+
+
// JAVA test file not found yet: com.example.snippets.java.capabilities.UtilsSnippetsTest. Needed for verifyHeatmapTileProviderDataAndRadius_falsifiable
+
+
+
+
+
+
+
+
+ #39 of 39
+ 2b6457c4
+ Wear OS
+ ⏳ Pending Falsification Check
+
Y2RIYtNPVDpE$%vda+HD#3m
z&VuXJ{BK&Qe+rBa7eq}Q(bq|tn(RrJAk|ztj2(i{d>nmQnM?;HF2k&9sA6up5tmjl
z7lySlzMbifH17-m-Lwa_F&e7nOH?ESi3#ckR3tsM+jsck3`oG!uMS}|eAwVXv>}qxwq?QY%QJ0}r@^;fhuUA9W
z*BVl>TGo&N004@xSiwDUXUvp51sVmqO3m)=B55aPwf@0=e}cN+$-BdKxY`YrT_4)0
z_d10#i44Q*rFr8MC>*)v$EJvz``(pb{e&*6k+b
zsMz%($|1+8hn8c2?P(l@;Rb&CsZeYoCI3?2!LqjbwPXW3z4G$Qfj=cT5Yb%vY0(AX
oeb?AaKtwrnc|$|zzw9vfvn^aJJ!zd)XFXqqy0000001=f@-~a#s
diff --git a/snippets/app-ktx/src/main/res/values/colors.xml b/snippets/app-ktx/src/main/res/values/colors.xml
deleted file mode 100644
index df4601b36..000000000
--- a/snippets/app-ktx/src/main/res/values/colors.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
- #FF000000
- #FFFFFFFF
-
\ No newline at end of file
diff --git a/snippets/app-ktx/src/main/res/values/strings.xml b/snippets/app-ktx/src/main/res/values/strings.xml
deleted file mode 100644
index bcc89f3a0..000000000
--- a/snippets/app-ktx/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
- app-ktx
-
\ No newline at end of file
diff --git a/snippets/app-rx/.gitignore b/snippets/app-rx/.gitignore
deleted file mode 100644
index 42afabfd2..000000000
--- a/snippets/app-rx/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-/build
\ No newline at end of file
diff --git a/snippets/app-rx/build.gradle.kts b/snippets/app-rx/build.gradle.kts
deleted file mode 100644
index eecc05663..000000000
--- a/snippets/app-rx/build.gradle.kts
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2024 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-plugins {
- alias(libs.plugins.android.application)
- alias(libs.plugins.jetbrains.kotlin.android)
- alias(libs.plugins.secrets.gradle.plugin)
-}
-
-android {
- namespace = "com.google.maps.example.rx"
- compileSdk = libs.versions.compileSdk.get().toInt()
- defaultConfig {
- applicationId = "com.google.maps.example.rx"
- minSdk = libs.versions.minSdk.get().toInt()
- targetSdk = libs.versions.targetSdk.get().toInt()
- versionCode = 1
- versionName = libs.versions.versionName.get()
-
- testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
- }
-
- buildFeatures {
- buildConfig = true
- }
-
- buildTypes {
- release {
- isMinifyEnabled = true
- proguardFiles(
- getDefaultProguardFile("proguard-android-optimize.txt"),
- "proguard-rules.pro"
- )
- }
- }
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_21
- targetCompatibility = JavaVersion.VERSION_21
- }
-
- lint {
- disable += setOf("MissingInflatedId")
- sarifOutput = layout.buildDirectory.file("reports/lint-results-debug.sarif").get().asFile
- }
- kotlin {
- compilerOptions {
- jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21)
- }
- }
-
- java {
- toolchain {
- languageVersion.set(JavaLanguageVersion.of(21))
- }
- }
-}
-
-// [START maps_android_maps_rx_install]
-dependencies {
- // RxJava bindings for the Maps SDK
- implementation(libs.maps.rx)
-
- // RxJava bindings for the Places SDK
- implementation(libs.places.rx)
-
- // It is recommended to also include the latest Maps SDK, Places SDK and RxJava so you
- // have the latest features and bug fixes.
- implementation("com.google.android.gms:play-services-maps:19.2.0")
- implementation("com.google.android.libraries.places:places:4.4.1")
- implementation("io.reactivex.rxjava3:rxjava:3.1.12")
-
- // [START_EXCLUDE silent]
- implementation(libs.appcompat)
- implementation(libs.lifecycle.runtime.ktx)
- implementation(libs.material)
- implementation(libs.rxlifecycle.android.lifecycle.kotlin)
- implementation(libs.maps.ktx)
- implementation(libs.kotlin.stdlib.jdk8)
- // [END_EXCLUDE silent]
-}
-// [END maps_android_maps_rx_install]
-
-secrets {
- // To add your Maps API key to this project:
- // 1. If the secrets.properties file does not exist, create it in the root directory (the same folder as the root local.properties file).
- // 2. Add this line, where YOUR_API_KEY is your API key:
- // MAPS_API_KEY=YOUR_API_KEY
- propertiesFileName = "secrets.properties"
-
- // A properties file containing default secret values. This file can be
- // checked in version control.
- defaultPropertiesFileName = "local.defaults.properties"
-}
\ No newline at end of file
diff --git a/snippets/app-rx/proguard-rules.pro b/snippets/app-rx/proguard-rules.pro
deleted file mode 100644
index 481bb4348..000000000
--- a/snippets/app-rx/proguard-rules.pro
+++ /dev/null
@@ -1,21 +0,0 @@
-# Add project specific ProGuard rules here.
-# You can control the set of applied configuration files using the
-# proguardFiles setting in build.gradle.
-#
-# For more details, see
-# http://developer.android.com/guide/developing/tools/proguard.html
-
-# If your project uses WebView with JS, uncomment the following
-# and specify the fully qualified class name to the JavaScript interface
-# class:
-#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
-# public *;
-#}
-
-# Uncomment this to preserve the line number information for
-# debugging stack traces.
-#-keepattributes SourceFile,LineNumberTable
-
-# If you keep the line number information, uncomment this to
-# hide the original source file name.
-#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/snippets/app-rx/src/main/AndroidManifest.xml b/snippets/app-rx/src/main/AndroidManifest.xml
deleted file mode 100644
index d8ce849b3..000000000
--- a/snippets/app-rx/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/snippets/app-rx/src/main/java/com/example/app_rx/MapsRx.kt b/snippets/app-rx/src/main/java/com/example/app_rx/MapsRx.kt
deleted file mode 100644
index de1033604..000000000
--- a/snippets/app-rx/src/main/java/com/example/app_rx/MapsRx.kt
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2023 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.example.app_rx
-
-import android.util.Log
-import com.google.android.gms.maps.GoogleMap
-import com.google.maps.android.rx.cameraIdleEvents
-import com.google.maps.android.rx.cameraMoveCanceledEvents
-import com.google.maps.android.rx.cameraMoveEvents
-import com.google.maps.android.rx.cameraMoveStartedEvents
-import com.google.maps.android.rx.markerClickEvents
-import io.reactivex.rxjava3.core.Observable
-
-internal class MapsRx {
- private fun markerClicks(googleMap: GoogleMap) {
- // [START maps_android_maps_rx_marker_click_events]
- googleMap.markerClickEvents()
- .subscribe { marker ->
- Log.d("MapsRx", "Marker ${marker.title} was clicked")
- }
- // [END maps_android_maps_rx_marker_click_events]
- }
-
- private fun cameraEvents(googleMap: GoogleMap) {
- // [START maps_android_maps_rx_camera_merge_events]
- Observable.merge(
- googleMap.cameraIdleEvents(),
- googleMap.cameraMoveEvents(),
- googleMap.cameraMoveCanceledEvents(),
- googleMap.cameraMoveStartedEvents()
- ).subscribe {
- // Notified when any camera event occurs
- }
- // [END maps_android_maps_rx_camera_merge_events]
- }
-}
\ No newline at end of file
diff --git a/snippets/app-rx/src/main/java/com/example/app_rx/PlacesRx.kt b/snippets/app-rx/src/main/java/com/example/app_rx/PlacesRx.kt
deleted file mode 100644
index e31413c2b..000000000
--- a/snippets/app-rx/src/main/java/com/example/app_rx/PlacesRx.kt
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2023 Google LLC
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.example.app_rx
-
-import android.util.Log
-import com.google.android.libraries.places.api.model.Place
-import com.google.android.libraries.places.api.net.PlacesClient
-import com.google.maps.android.rx.places.fetchPlace
-
-internal class PlacesRx {
- fun fetchPlace(placesClient: PlacesClient) {
- // [START maps_android_places_rx_marker_click_events]
- placesClient.fetchPlace(
- placeId = "thePlaceId",
- placeFields = listOf(Place.Field.ID, Place.Field.NAME, Place.Field.ADDRESS),
- actions = {}
- ).subscribe(
- { response ->
- Log.d("PlacesRx", "Successfully got place ${response.place.id}")
- },
- { error ->
- Log.e("PlacesRx", "Could not get place: ${error.message}")
- }
- )
- }
- // [END maps_android_places_rx_marker_click_events]
-}
\ No newline at end of file
diff --git a/snippets/app-rx/src/main/res/drawable-v24/ic_launcher_foreground.xml b/snippets/app-rx/src/main/res/drawable-v24/ic_launcher_foreground.xml
deleted file mode 100644
index ab975bf3c..000000000
--- a/snippets/app-rx/src/main/res/drawable-v24/ic_launcher_foreground.xml
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/snippets/app-rx/src/main/res/drawable/ic_launcher_background.xml b/snippets/app-rx/src/main/res/drawable/ic_launcher_background.xml
deleted file mode 100644
index 2e6ea5e9b..000000000
--- a/snippets/app-rx/src/main/res/drawable/ic_launcher_background.xml
+++ /dev/null
@@ -1,186 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/snippets/app-rx/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/snippets/app-rx/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
deleted file mode 100644
index b89ac5f12..000000000
--- a/snippets/app-rx/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/snippets/app-rx/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/snippets/app-rx/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
deleted file mode 100644
index b89ac5f12..000000000
--- a/snippets/app-rx/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/snippets/app-rx/src/main/res/mipmap-hdpi/ic_launcher.webp b/snippets/app-rx/src/main/res/mipmap-hdpi/ic_launcher.webp
deleted file mode 100644
index c209e78ecd372343283f4157dcfd918ec5165bb3..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 1404
zcmV-?1%vuhNk&F=1pok7MM6+kP&il$0000G0000-002h-06|PpNX!5L00Dqw+t%{r
zzW2vH!KF=w&cMnnN@{whkTw+#mAh0SV?YL=)3MimFYCWp#fpdtz~8$hD5VPuQgtcN
zXl<@<#Cme5f5yr2h%@8TWh?)bSK`O
z^Z@d={gn7J{iyxL_y_%J|L>ep{dUxUP8a{byupH&!UNR*OutO~0{*T4q5R6@ApLF!
z5{w?Z150gC7#>(VHFJZ-^6O@PYp{t!jH(_Z*nzTK4
zkc{fLE4Q3|mA2`CWQ3{8;gxGizgM!zccbdQoOLZc8hThi-IhN90RFT|zlxh3Ty&VG
z?Fe{#9RrRnxzsu|Lg2ddugg7k%>0JeD+{XZ7>Z~{=|M+sh1MF7~
zz>To~`~LVQe1nNoR-gEzkpe{Ak^7{{ZBk2i_<+`Bq<^GB!RYG+z)h;Y3+<{zlMUYd
zrd*W4w&jZ0%kBuDZ1EW&KLpyR7r2=}fF2%0VwHM4pUs}ZI2egi#DRMYZPek*^H9YK
zay4Iy3WXFG(F14xYsoDA|KXgGc5%2DhmQ1gFCkrgHBm!lXG8I5h*uf{rn48Z!_@
z4Bk6TJAB2CKYqPjiX&mWoW>OPFGd$wqroa($ne7EUK;#3VYkXaew%Kh^3OrMhtjYN?XEoY`tRPQsAkH-DSL^QqyN0>^
zmC>{#F14jz4GeW{pJoRpLFa_*GI{?T93^rX7SPQgT@LbLqpNA}<@2wH;q493)G=1Y
z#-sCiRNX~qf3KgiFzB3I>4Z%AfS(3$`-aMIBU+6?gbgDb!)L~A)je+;fR0jWLL-Fu
z4)P{c7{B4Hp91&%??2$v9iRSFnuckHUm}or9seH6
z>%NbT+5*@L5(I9j@06@(!{ZI?U0=pKn8uwIg&L{JV14+8s2hnvbRrU|hZCd}IJu7*;;ECgO%8_*W
Kmw_-CKmY()leWbG
diff --git a/snippets/app-rx/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/snippets/app-rx/src/main/res/mipmap-hdpi/ic_launcher_round.webp
deleted file mode 100644
index b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 2898
zcmV-Y3$650Nk&FW3jhFDMM6+kP&il$0000G0000-002h-06|PpNWB9900E$G+qN-D
z+81ABX7q?;bwx%xBg?kcwr$(C-Tex-ZCkHUw(Y9#+`E5-zuONG5fgw~E2WDng@Bc@
z24xy+R1n%~6xI#u9vJ8zREI)sb<&Il(016}Z~V1n^PU3-_H17A*Bf^o)&{_uBv}Py
zulRfeE8g(g6HFhk_?o_;0@tz?1I+l+Y#Q*;RVC?(ud`_cU-~n|AX-b`JHrOIqn(-t&rOg-o`#C
zh0LPxmbOAEb;zHTu!R3LDh1QO
zZTf-|lJNUxi-PpcbRjw3n~n-pG;$+dIF6eqM5+L();B2O2tQ~|p{PlpNcvDbd1l%c
zLtXn%lu(3!aNK!V#+HNn_D3lp
z2%l+hK-nsj|Bi9;V*WIcQRTt5j90A<=am+cc`J
zTYIN|PsYAhJ|=&h*4wI4ebv-C=Be#u>}%m;a{IGmJDU`0snWS&$9zdrT(z8#{OZ_Y
zxwJx!ZClUi%YJjD6Xz@OP8{ieyJB=tn?>zaI-4JN;rr`JQbb%y5h2O-?_V@7pG_+y
z(lqAsqYr!NyVb0C^|uclHaeecG)Sz;WV?rtoqOdAAN{j%?Uo%owya(F&qps@Id|Of
zo@~Y-(YmfB+chv^%*3g4k3R0WqvuYUIA+8^SGJ{2Bl$X&X&v02>+0$4?di(34{pt*
zG=f#yMs@Y|b&=HyH3k4yP&goF2LJ#tBLJNNDo6lG06r}ghC-pC4Q*=x3;|+W04zte
zAl>l4kzUBQFYF(E`KJy?ZXd1tnfbH+Z~SMmA21KokJNs#eqcXWKUIC>{TuoKe^vhF
z);H)o`t9j~`$h1D`#bxe@E`oE`cM9w(@)5Bp8BNukIwM>wZHfd0S;5bcXA*5KT3bj
zc&_~`&{z7u{Et!Z_k78H75gXf4g8<_ul!H$eVspPeU3j&&Au=2R*Zp#M9$9s;fqwgzfiX=E_?BwVcfx3tG9Q-+<5fw
z%Hs64z)@Q*%s3_Xd5>S4dg$s>@rN^ixeVj*tqu3ZV)biDcFf&l?lGwsa
zWj3rvK}?43c{IruV2L`hUU0t^MemAn3U~x3$4mFDxj=Byowu^Q+#wKRPrWywLjIAp
z9*n}eQ9-gZmnd9Y0WHtwi2sn6n~?i#n9VN1B*074_VbZZ=WrpkMYr{RsI
ztM_8X1)J*DZejxkjOTRJ&a*lrvMKBQURNP#K)a5wIitfu(CFYV4FT?LUB$jVwJSZz
zNBFTWg->Yk0j&h3e*a5>B=-xM7dE`IuOQna!u$OoxLlE;WdrNlN)1
z7**de7-hZ!(%_ZllHBLg`Ir#|t>2$*xVOZ-ADZKTN?{(NUeLU9GbuG-+Axf*AZ-P1
z0ZZ*fx+ck4{XtFsbcc%GRStht@q!m*ImssGwuK+P@%gEK!f5dHymg<9nSCXsB6
zQ*{<`%^bxB($Z@5286^-A(tR;r+p7B%^%$N5h%lb*Vlz-?DL9x;!j<5>~kmXP$E}m
zQV|7uv4SwFs0jUervsxVUm>&9Y3DBIzc1XW|CUZrUdb<&{@D5yuLe%Xniw^x&{A2s
z0q1+owDSfc3Gs?ht;3jw49c#mmrViUfX-yvc_B*wY|Lo7;
zGh!t2R#BHx{1wFXReX*~`NS-LpSX
z#TV*miO^~B9PF%O0huw!1Zv>^d0G3$^8dsC6VI!$oKDKiXdJt{mGkyA`+Gwd4D-^1qtNTUK)`N*=NTG-6}=5k6suNfdLt*dt8D|
z%H#$k)z#ZRcf|zDWB|pn<3+7Nz>?WW9WdkO5(a^m+D4WRJ9{wc>Y}IN)2Kbgn;_O?
zGqdr&9~|$Y0tP=N(k7^Eu;iO*w+f%W`20BNo)=Xa@M_)+o$4LXJyiw{F?a633SC{B
zl~9FH%?^Rm*LVz`lkULs)%idDX^O)SxQol(3jDRyBVR!7d`;ar+D7do)jQ}m`g$TevUD5@?*P8)voa?kEe@_hl{_h8j&5eB-5FrYW&*FHVt$
z$kRF9Nstj%KRzpjdd_9wO=4zO8ritN*NPk_9avYrsF(!4))tm{Ga#OY
z(r{0buexOzu7+rw8E08Gxd`LTOID{*AC1m*6Nw@osfB%0oBF5sf<~wH1kL;sd
zo)k6^VyRFU`)dt*iX^9&QtWbo6yE8XXH?`ztvpiOLgI3R+=MOBQ9=rMVgi<*CU%+d1PQQ0a1U=&b0vkF207%xU0ssI2
diff --git a/snippets/app-rx/src/main/res/mipmap-mdpi/ic_launcher.webp b/snippets/app-rx/src/main/res/mipmap-mdpi/ic_launcher.webp
deleted file mode 100644
index 4f0f1d64e58ba64d180ce43ee13bf9a17835fbca..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 982
zcmV;{11bDcNk&G_0{{S5MM6+kP&il$0000G0000l001ul06|PpNU8t;00Dqo+t#w^
z^1csucXz7-Qrhzl9HuHB%l>&>1tG2^vb*E&k^T3$FG1eQZ51g$uv4V+kI`0<^1Z@N
zk?Jjh$olyC%l>)Xq;7!>{iBj&BjJ`P&$fsCfpve_epJOBkTF?nu-B7D!hO=2ZR}