Skip to content

Commit eeb0156

Browse files
kikosodkhawk
andauthored
feat!: rewrite android maps utils (#1658)
* build: modularisation * chore: fixed tests * feat: add check for secrets.properties * chore: add dummy secrets.properties for CI workflows * Fix: Conditionally enforce secrets.properties for demo module builds Previously, the task did not correctly trigger the check, allowing the demo app to attempt building without the necessary API key. This commit refines the logic to: - Enforce presence for all tasks that build the module (e.g., , , , , ). - Allow non-build tasks (e.g., , ) to proceed without the file, printing a warning instead of throwing an error. This ensures that tests can run independently while preventing incomplete demo app builds. * chore: improved messaging for the missing secrets.properties detector # Conflicts: # demo/build.gradle.kts * Refactor: Improve secrets check logic in demo build.gradle.kts The secrets check in `demo/build.gradle.kts` has been refined to address issues with Android Studio Gradle syncs and to more accurately enforce the presence of `secrets.properties` for build-related tasks. Previously, the script would fail during an Android Studio sync (when no specific tasks are requested) due to an overly broad interpretation of "build task." This commit introduces the following changes: - **Graceful handling of IDE syncs:** If no tasks are explicitly requested (common during IDE sync), a warning is now issued instead of a hard failure. This allows the IDE to sync successfully while still informing the developer about the missing secrets. - **Stricter enforcement for build tasks:** For command-line builds or tasks that are not explicitly exempt (e.g., `clean`, `test`, `lint`), the script will now correctly throw an error if `secrets.properties` is missing. This ensures a better developer experience by preventing unnecessary build failures during IDE operations, while maintaining the necessary security check for actual application builds. * chore: fix wrong indent in test.yml file. * fix: Allow test reports to run without secrets The previous logic prevented any task from running without a file. This change allows the task to run if it's accompanied by a test-related task, such as . This enables running test reports without needing to provide API keys. * chore: Fixes task name detection to correctly handle module-prefixed tasks (e.g., `:demo:assembleDebug`) when validating secrets. * test(data-geojson-parser): Strengthen GeoJsonParser tests Improved and expanded assertions in `GeoJsonParserTest` for: - `earthquakes_with_usa.json` - `south_london_line_geojson.json` - `south_london_square_geojson.json` - `usa.json` - `earthquakes.json` Tests now include detailed verification of feature counts, properties, geometry types, and coordinate values to ensure robust GeoJSON parsing. * feat: KML parser (WIP) * WIP: kml parser tests - close but still have some issues to address. * refactor: rename Coords to LatLngAlt * feat(data): restore data module from main * feat: creates new "onion" module which will replace the data module when complete. * feat: more Kml Parser Tests adds Truth Subjects for Points and LatLngAlt.kt * fix(kml): Use the KML object for testing in testAmuBasicPlacemarkPoint Establish the pattern to migrate off GeoData object. Additionally, a minor typo in `testAmuBallonGxPrefix` has been corrected. * fix(kml): Migrates several tests to use the KML model * fix(kml): Migrates more tests to use the KML model * test(kml): add LatLonBoxSubject and refactor parser tests - Add `LatLonBoxSubject` to support cleaner, tolerance-based assertions for KML bounds using Google Truth. - Update `amu_empty_hotspot.kml` to wrap contents in a `<Document>` tag, ensuring valid KML structure for parsing. - Refactor `KmlParserTest` to use new assertions, remove dead code/comments, and fix a resource filename typo ("ballon" -> "balloon"). - Inline variable in `KmlParser.parseAsKml` for brevity. * test(kml): adds IconStyle and LabelStyle to the Style definition * test(kml): multigeometry place marks tests Adds PointSubject.kt * test(kml): fixes testAmuPolyStyleBooleanAlpha * test(kml): fixes final KmlParserTest tests Adds support for rotation in LatLonBox * feat(geojson): Create a data model specific to geojson files Update the geojson tests to use the geojson specific model. * feat: Introduce renderer model Refactor GeoJSON parsing and mapping for type-safe coordinates. This commit refactors GeoJSON parsing to use a new Coordinates data class, simplifying GeoJsonObjects and GeoJsonParser. It also introduces a platform-agnostic renderer model and an initial MapViewRenderer implementation. Test updates are included to reflect these changes and ensure correctness, improving overall code robustness and maintainability. * feat: Add KML to renderer model mapper and tests This commit introduces the `KmlMapper` to transform KML data models into the platform-agnostic renderer model (`Scene` and `Feature` objects). Key changes include: - **`KmlMapper.kt`**: A new mapper that converts existing KML parser model objects into the generic renderer model, handling geometry transformations and nullability. - **`KmlMapperTest.kt`**: Comprehensive unit tests to verify the correct functioning of the `KmlMapper`, ensuring accurate conversion of KML Points, LineStrings, Polygons, and MultiGeometries, as well as handling of nested structures and null-safe coordinate access. This adds support for KML data within the new `onion` rendering architecture, leveraging existing KML parsing capabilities. * refactor(kml): Use LatLngAlt object directly in KmlPoint This commit refactors the KmlPoint class to directly use a LatLngAlt object for its coordinates, improving type safety and consistency with the new serialization approach. Key changes include: - `LatLngAltSerializer.kt`: Created a custom serializer for `LatLngAlt` to handle string parsing and serialization. - `LatLngAlt.kt`: Updated to use the new `@Serializable(with = LatLngAltSerializer::class)` annotation and removed the now redundant `fromString` method. - `KmlModel.kt`, `KmlParser.kt`, `KmlMapper.kt`: Updated to reflect the change in `KmlPoint`s coordinates from `String` to `LatLngAlt`, resolving compilation errors and ensuring correct data flow. - Unit tests (`KmlParserTest.kt`, `PointSubject.kt`, `KmlMapperTest.kt`): Modified to align with the new `LatLngAlt` object usage in `KmlPoint`, verifying the integrity of the parsing and mapping logic. * fix: parse the coordinates for LineString and LinearRing using a custom serializer * refactor(kml): Use custom serializers for Boolean and Color This commit refactors the KML parsing model to use custom serializers for Boolean and Color values, improving type safety and consistency. This change also includes fixing parsing and mapping logic. Key changes include: - `BooleanSerializer.kt`: Created a custom serializer for `Boolean` to handle KMLs "1"/"0" and "true"/"false" string formats. - `ColorSerializer.kt`: Created a custom serializer for `Color` to parse KMLs `aabbggrr` hex string format into an ARGB `Int`. - `KmlModel.kt`: Updated `GroundOverlay`, `Folder`, `Polygon`, and `PolyStyle` classes to use the new `BooleanSerializer` for `visibility`, `extrude`, `fill`, and `outline` properties, removing the transient properties and string-based fields. The `asBoolean()` helper function was removed. - `KmlModel.kt`: Updated `GroundOverlay`, `LabelStyle`, `LineStyle`, and `PolyStyle` to use the new `ColorSerializer` for their `color` properties. - Unit tests (`KmlParserTest.kt`): Modified to align with the new `Boolean` and `Int` usage, correcting assertions for color values. * feat: Integrate and operationalize KML rendering demo This commit integrates the new 'onion' rendering module into the demo application and resolves multiple build and runtime issues to create a functional demonstration. Key changes include: - Adds a new `RendererDemoActivity` to showcase the KML rendering capabilities. - Wires up the new activity in the main navigation and AndroidManifest. - Adds `top_peaks.kml` and `mountain_ranges.kml` as demo assets. - Resolves a duplicate `RendererLogger` class by removing it from the `onion` module. - Fixes a JVM incompatibility issue by enforcing a Java 17 toolchain across all projects. - Updates the `onion` module's namespace and refactors several components to support the demo, including `KmlMapper` and `MapViewRenderer`. * feat: Implement GPX support with parser, mapper, and demo integration * feat: Address PR review comments and refactor build process This commit addresses several review comments from PR #9, focusing on code cleanup and build process improvements: - Ignored `.vscode/settings.json` locally to prevent tracking IDE-specific configurations. - Removed duplicate `PublishingConventionPlugin.kt` from `build-logic/convention/bin` and added `build-logic/convention/bin` to `.gitignore`, cleaning up build artifacts. - Removed commented-out MIME type suggestions from `RendererDemoActivity.kt` to eliminate dead code. - Removed the `lint-checks/bin` directory and added it to `.gitignore`, further cleaning up build artifacts. - Removed the deprecated `installation` block from `onion/build.gradle.kts` as it is no longer useful and will be removed in future Gradle versions. - Kept the `plugins.withId("java")` block in root `build.gradle.kts` as it correctly configures the Java toolchain for multi-module projects. * fix: restore demo/build.gradle.kts changes * Refactor onion module and update demo app - Enable Advanced Markers in RendererDemoActivity - Fix GroundOverlay NPE in MapViewRenderer - Clean up RendererDemoActivity code - Add test coverage for onion module - Refactor onion module to use DataLayer/DataScene/DataRenderer - Add KML/GeoJSON/GPX parsing and rendering support * feat: Address PR comments - Add toast for successful layer loading in RendererDemoActivity - Use imports instead of FQDNs in RendererDemoActivity - Reuse icon loading jobs in MapViewRenderer to avoid redundant requests * refactor(renderer-demo): fix additional imports. * feat: using Gemini to perform UI tests (#8) * feat: genAi test * feat: added an NLP helper * chore: removed unused imports * feat: modularisation * feat: PR comments * feat: Refactor IconProvider (#12) * feat(demo): improve renderer demo UI - Add toggleable chips for layer visibility - Add bottom sheet toggle button - Remove unnecessary Toast messages * feat(onion): add unified DataLayerLoader and supported extensions - Create DataLayerLoader for unified asset and stream loading - Add SUPPORTED_EXTENSIONS to all parsers - Implement content sniffing and extension matching logic * fix(onion): improve icon loading job management in MapViewRenderer - Track icon loading jobs per Feature instead of per URL to prevent premature cancellation - Fix potential race conditions in icon caching and assignment * feat(demo): improve renderer demo UI - Add toggleable chips for layer visibility - Add bottom sheet toggle button - Remove unnecessary Toast messages * feat(onion): add unified DataLayerLoader and supported extensions - Create DataLayerLoader for unified asset and stream loading - Add SUPPORTED_EXTENSIONS to all parsers - Implement content sniffing and extension matching logic * fix(onion): improve icon loading job management in MapViewRenderer - Track icon loading jobs per Feature instead of per URL to prevent premature cancellation - Fix potential race conditions in icon caching and assignment * Refactor IconProvider to use suspend functions and fix build errors * Optimize UrlIconProvider with thundering herd fix and add unit tests * chore: remove debug log message * feat: using Gemini to perform UI tests (#8) * feat: genAi test * feat: added an NLP helper * chore: removed unused imports * feat: modularisation * feat: PR comments * fix(onion): improve icon loading job management in MapViewRenderer - Track icon loading jobs per Feature instead of per URL to prevent premature cancellation - Fix potential race conditions in icon caching and assignment # Conflicts: # onion/src/main/java/com/google/maps/android/data/renderer/mapview/MapViewRenderer.kt * chore: manually merging back in the DataLayerLoader. * fix: Fixed icon loading * chore: Update dependencies Also sort the toml file --------- Co-authored-by: Enrique López-Mañas <eenriquelopez@gmail.com> * fix: fix broken catalog file (#13) * feat: Adds gemini-based visual testing to the RendererDemoActivity (#14) * feat(ui): port ui module to Kotlin and refactor visual tests (#15) * feat(ui): port ui module to Kotlin and refactor visual tests Ported IconGenerator, AnimationUtil, BubbleDrawable, RotationLayout, SquareTextView, and BubbleIconFactory to Kotlin. Refactored visual tests to use a shared BaseVisualTest for better maintainability and robustness. * fix(ui): update copyright to 2026 and fix lint issues * feat(ui): address review feedback and include local visual test improvements * fix: make LatLngInterpolator * feat!: refactoring of clustering module (#16) * feat: migrated algorithm and clusters * feat: migrated renderer * chore: refactor algorithms * feat: more algorithms * feat: more algorithms * feat: more algorithms * feat: more arenderers * feat: more arenderers * feat: migrated ClusterManager * feat: removed build error file * docs: add license header * docs: add license header as Google LLC * docs: add license header as 2026 * docs: add license header as a new year * docs: add license header as a new year * docs: add license header as a new year * docs: add license header as a new year * docs: add license header as a new year * docs: add license header as a new year * feat: increased minSdk to 23 * feat: increased minSdk to 23 * feat: increased minSdk to 23 * feat: added test block option * test: added default test * docs: added license header * docs: add AI integration standards (#1668) * docs: add AI integration standards to rewrite branch * chore: add release-please annotation to AI prompts * chore: add AI prompt files to release-please-config.json * docs: bump version in AI prompts to 4.1.1 * docs: remove compose utils reference from AI prompts * chore: Add clustering algorithms benchmark tests (#1665) * chore: add clustering algorithms benchmark tests * docs: added header * chore: add benchmarks for remaining clustering algorithms * chore: add license header to BenchmarkTest.kt * docs: add clustering benchmark dashboard * build: updated AGP (#1670) * feat: Add BoM module and fix modularized artifactIds (#1660) * feat: add BoM module and fix artifactIds * Adds a new module applying the plugin * Adds to standardise publishing of the BoM * Fixes an issue where all modules were being published with the legacy artifact ID, which would cause them to overwrite each other on Maven Central. Modules are now published as , , etc. while correctly retains . * docs: add license * refactor: modularize library and rewrite geospatial data layer - Rewrote the geospatial data layer (`:data`) from scratch using a platform-agnostic architecture for KML and GeoJSON parsing and rendering. - Modernized and rewrote core utilities (`PolyUtil`, `SphericalUtil`, `MathUtil`, etc.) and manager classes in idiomatic Kotlin. - Modularized the codebase into individual submodules (`:library`, `:data`, `:clustering`, `:heatmaps`, `:ui`) to optimize build times and dependency footprints. - Preserved full backward compatibility for existing integrations using the `:maps-utils` aggregator module. - Added a comprehensive migration guide (MIGRATION.md) and integrated release-please support. * style: add license header to maps-utils AndroidManifest * Fix duplicate class issues in navigation flavor by globally excluding play-services-maps * build: update GitHub Actions to latest major versions (#1689) * fix: resolve maven-publish classloader error by applying plugin with apply false - Added 'apply false' declaration for vanniktech maven-publish plugin at root level - This fixes the classloader conflict when multiple modules share the build service - Publishing now works: publishToMavenLocal succeeds, publishToMavenCentral reaches upload stage - Version remains at 4.4.1 * fix: add explicit Dokka task dependency on generateArtifactIdFile This resolves the Gradle task dependency issue where dokkaGeneratePublicationHtml was using the output of generateArtifactIdFile without an explicit dependency. This was causing the gh-pages workflow to fail. * fix: enable filterTouchesWhenObscured on additional WebView layouts Apply the security fix from PR #1703 to amu_info_window.xml and amu_text_bubble.xml. This prevents touch event spoofing when views are obscured by other windows. * fix(geojson): prevent StackOverflowError when parsing deeply nested GeometryCollection objects * chore: upgrade AGP to 9.2.1 and Compile SDK to 37 * fix(kml): prevent StackOverflowError when parsing deeply nested KML Port the depth-limit protection from #1710 to the Kotlin parser. The generated serializers recurse once per nested element, so a depth guard at the XmlReader level aborts parsing of maliciously deep documents (e.g. thousands of nested Folder or MultiGeometry elements) before the stack can overflow. * chore: centralize plugin versions in version catalog --------- Co-authored-by: Dale Hawkins <107309+dkhawk@users.noreply.github.com>
1 parent f513807 commit eeb0156

461 files changed

Lines changed: 49105 additions & 24906 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
name: maps-utils-android
3+
description: Guide for integrating the Google Maps Utility Library for Android (android-maps-utils) into an application. Use when users ask to add features like Marker Clustering, Heatmaps, GeoJSON, KML, or Polyline encoding/decoding.
4+
---
5+
6+
# Google Maps Utility Library for Android Integration
7+
8+
You are an expert Android developer specializing in the Google Maps SDK for Android and its Utility Library. Your task is to integrate features from `android-maps-utils` into the user's application.
9+
10+
## 1. Setup Dependencies
11+
12+
Add the necessary dependency to the app-level `build.gradle.kts` file:
13+
14+
```kotlin
15+
dependencies {
16+
// Google Maps Utility Library
17+
implementation("com.google.maps.android:android-maps-utils:4.1.1") // x-release-please-version
18+
}
19+
```
20+
21+
## 2. Core Features & Usage Patterns
22+
23+
When a user asks for advanced features, implement them using these established patterns from the Utility Library:
24+
25+
### Marker Clustering
26+
Used to manage multiple markers at different zoom levels.
27+
1. Create a `ClusterItem` data class.
28+
2. Initialize a `ClusterManager` inside `onMapReady`.
29+
3. Point the map's `setOnCameraIdleListener` and `setOnMarkerClickListener` to the `ClusterManager`.
30+
4. Add items using `clusterManager.addItem()`.
31+
32+
### Heatmaps
33+
Used to represent the density of data points.
34+
1. Provide a `Collection<LatLng>` or `Collection<WeightedLatLng>`.
35+
2. Create a `HeatmapTileProvider` with the builder `HeatmapTileProvider.Builder().data(list).build()`.
36+
3. Add the overlay to the map: `map.addTileOverlay(TileOverlayOptions().tileProvider(provider))`.
37+
38+
### GeoJSON and KML
39+
Used to import geographic data from external files.
40+
* **GeoJSON:** `val layer = GeoJsonLayer(map, R.raw.geojson_file, context); layer.addLayerToMap()`
41+
* **KML:** `val layer = KmlLayer(map, R.raw.kml_file, context); layer.addLayerToMap()`
42+
43+
### Polyline Decoding and Spherical Geometry
44+
Used for server-client coordinate compression and distance calculations.
45+
* **Decoding:** `PolyUtil.decode(encodedPathString)`
46+
* **Distance:** `SphericalUtil.computeDistanceBetween(latLng1, latLng2)`
47+
48+
## 3. Best Practices
49+
1. **Performance:** For massive datasets (e.g., parsing huge GeoJSON files), do not block the main thread. Parse on a background dispatcher and only call `layer.addLayerToMap()` on the UI thread.
50+
2. **Custom Renderers:** If the user wants custom cluster icons, extend `DefaultClusterRenderer` and override `onBeforeClusterItemRendered` and `onBeforeClusterRendered`.

.geminiignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Ignore build and generated directories
2+
build/
3+
**/build/
4+
.gradle/
5+
.idea/
6+
.kotlin/
7+
.vscode/
8+
9+
# Ignore outputs
10+
*.apk
11+
*.ap_
12+
*.aab
13+
*.dex
14+
*.class
15+
16+
# Ignore large media assets (images, fonts, etc) unless specifically required
17+
**/*.png
18+
**/*.jpg
19+
**/*.jpeg
20+
**/*.gif
21+
**/*.webp
22+
**/*.svg
23+
**/*.mp4
24+
**/*.mp3
25+
**/*.wav
26+
**/*.ttf
27+
**/*.woff
28+
**/*.woff2
29+
**/*.otf
30+
31+
# Ignore temporary and cache files
32+
tmp/
33+
**/tmp/
34+
*.log
35+
*.tmp
36+
*.bak
37+
*.swp
38+
*~.nib
39+
local.properties
40+
.DS_Store

.github/blunderbuss.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2024 Google LLC
1+
# Copyright 2026 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

.github/dependabot.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2024 Google LLC
1+
# Copyright 2026 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

.github/header-checker-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2024 Google LLC
1+
# Copyright 2026 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

.github/stale.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2024 Google LLC
1+
# Copyright 2026 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.

.github/workflows/docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2024 Google LLC
1+
# Copyright 2026 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -38,7 +38,7 @@ jobs:
3838
distribution: 'temurin'
3939

4040
- name: Setup Gradle
41-
uses: gradle/actions/setup-gradle@v4
41+
uses: gradle/actions/setup-gradle@v6
4242
- name: Install Go
4343
uses: actions/setup-go@v6
4444
with:

.github/workflows/lint-report.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2024 Google LLC
1+
# Copyright 2026 Google LLC
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -30,23 +30,26 @@ jobs:
3030
- name: Set up JDK 17
3131
uses: actions/setup-java@v5
3232
with:
33-
distribution: 'adopt'
33+
distribution: 'temurin'
3434
java-version: '17'
3535

3636
- name: Setup Gradle
37-
uses: gradle/actions/setup-gradle@v4
37+
uses: gradle/actions/setup-gradle@v6
38+
39+
- name: Create dummy secrets.properties
40+
run: echo "MAPS_API_KEY=dummy" > secrets.properties
3841

3942
- name: Run Android Lint
4043
run: ./gradlew :library:lintDebug :demo:lintStandardDebug
4144

4245
- name: Upload SARIF for library
43-
uses: github/codeql-action/upload-sarif@v3
46+
uses: github/codeql-action/upload-sarif@v4
4447
with:
4548
sarif_file: library/build/reports/lint-results.sarif
4649
category: library
4750

4851
- name: Upload SARIF for demo
49-
uses: github/codeql-action/upload-sarif@v3
52+
uses: github/codeql-action/upload-sarif@v4
5053
with:
5154
sarif_file: demo/build/reports/lint-results.sarif
5255
category: demo

.github/workflows/publish.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,18 @@ jobs:
2424
runs-on: ubuntu-latest
2525
steps:
2626
- name: Checkout
27-
uses: actions/checkout@v5
27+
uses: actions/checkout@v6
2828
with:
2929
token: ${{ secrets.SYNCED_GITHUB_TOKEN_REPO }}
3030

3131
- name: Set up JDK 21
32-
uses: actions/setup-java@v4.7.1
32+
uses: actions/setup-java@v5
3333
with:
3434
java-version: '21'
35-
distribution: 'adopt'
35+
distribution: 'temurin'
3636

3737
- name: Setup Gradle
38-
uses: gradle/actions/setup-gradle@v4
38+
uses: gradle/actions/setup-gradle@v6
3939

4040
- name: Create .gpg key
4141
run: |

.github/workflows/release-please.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
release-please:
2828
runs-on: ubuntu-latest
2929
steps:
30-
- uses: googleapis/release-please-action@v4
30+
- uses: googleapis/release-please-action@v5
3131
with:
3232
token: ${{ secrets.SYNCED_GITHUB_TOKEN_REPO }}
3333
config-file: release-please-config.json

0 commit comments

Comments
 (0)