Guidance for AI coding agents working on this repository. For human contribution rules (CLA, PR process, AI-assisted contribution policy), see CONTRIBUTING.md.
Jetpack Compose components for the Maps SDK for Android. The published libraries live in three modules; the rest of the repo supports them.
| Module | Purpose |
|---|---|
maps-compose |
Core library: GoogleMap composable, camera state, markers, shapes |
maps-compose-utils |
Utilities layer: clustering and other android-maps-utils integrations |
maps-compose-widgets |
Widget composables built on top of the core library |
maps-app |
Demo app exercising the libraries |
docs |
Dokka documentation aggregation |
Shared Gradle conventions are in build-logic/ (included build).
./gradlew assembleDebug # build everything
./gradlew :maps-compose:testDebugUnitTest # unit tests for one module
./gradlew koverXmlReportDebug # all unit tests and coverage reports
./gradlew lint # Android Lint across all modules
./gradlew :maps-app:validateDebugScreenshotTest # validate screenshot testsCoverage is tracked over time. After every merge to main, the
Record coverage history workflow appends a row per module per suite to
history.csv and regenerates COVERAGE.md, both of which live on the
coverage-history branch. They are generated by
.github/scripts/coverage_history.py. Never edit them by hand.
The data is kept off main deliberately. Branch protection on main uses
strict required status checks, so any commit pushed there marks every open
pull request out-of-date and forces contributors to update their branch and
re-run CI, including the emulator suite.
Two suites are recorded separately, because they instrument different code and cannot be merged from their XML reports:
| Suite | Produced by | Covers |
|---|---|---|
unit |
koverXmlReportDebug |
the three published library modules |
instrumentation |
createDebugCoverageReport and :maps-app:createLibraryCoverageReports (emulator) |
maps-app, plus maps-compose, maps-compose-utils and maps-compose-widgets as exercised by all emulator tests |
Instrumentation coverage is not re-measured after merge; the post-merge workflow reuses the artifact from the pull request's emulator run, so no extra emulator time is spent. That run is usually still going when a pull request merges, because the required checks finish in 6-13 minutes while the emulator takes 16-28, so the workflow records unit coverage first and then waits for the emulator before recording instrumentation. If the run fails, is missing, or does not finish within the wait window, only unit coverage is recorded for that commit.
Note that the library modules currently have almost no unit tests. The bulk of
the suite is instrumentation tests under maps-app/src/androidTest, so the
unit numbers are near zero by nature rather than by regression.
The demo smoke tests in maps-app/src/androidTest/.../compose/smoke run in
their own Demo smoke test workflow on API 36, and are excluded from the
instrumentation workflow above, so they do not count towards instrumentation
coverage. DemoAppSmokeTest launches every demo directly, DemoMenuNavigationTest
opens each one from the menu and navigates back, and DemoRegistryTest keeps the
menu and the manifest in sync. Add new demos to allActivityGroups in Demo.kt
and they are covered automatically. To run them with a device or emulator attached:
./gradlew :maps-app:connectedDebugAndroidTest \
-Pandroid.testInstrumentationRunnerArguments.package=com.google.maps.android.compose.smokeAdd -Pandroid.testInstrumentationRunnerArguments.requireMapLoaded=true to also
wait for map tiles to render, which needs a real key.
Running maps-app requires a Maps API key: put MAPS_API_KEY=... in
secrets.properties at the repo root (see local.defaults.properties for the
template). Never hardcode or commit API keys.
- Adhere to formatting rules defined in
.editorconfig. - Do not use wildcard imports (
import foo.*); use explicit imports. - Avoid fully qualified class names in source code whenever possible; declare explicit imports at the file level instead (except to resolve naming collisions).
- Library modules compile with
-Xexplicit-api=strict. All public classes, functions, and properties must declare explicit visibility (public) and explicit return types. - Published library modules target Java 17 (
JvmTarget.JVM_17,JavaVersion.VERSION_17), matchingandroid-maps-utils6.0+. Do not downgrade bytecode to Java 8 or Java 11. - Follow the Jetpack Compose API guidelines strictly for any public API.
- Composable functions are PascalCase; the first optional parameter of a
composable is
modifier: Modifier = Modifier. - Prefer the library's state holders (
rememberCameraPositionState,MarkerState) over ad-hoc state. - KDoc on all public classes, properties, and functions.
- Avoid
!!; use null-safe operators. - Public API changes must be additive and backward compatible; deprecate before removing.
- Use Conventional Commit messages (
feat:,fix:,docs:, ...). release-please parses them to generate versions and CHANGELOG.md; a wrong prefix causes a wrong release bump. Never edit CHANGELOG.md by hand. - Every behavior change needs a unit test in the affected module.
- All pull requests are to be created as drafts (
gh pr create --draft) until authorization is explicitly given to mark them ready for review. Always inform the user that the PR was created as a draft. - Run the module's tests and
lintbefore declaring work done, and report actual results. - Do not add dependencies to the library modules without discussion in an issue first; the libraries are consumed by many apps and dependency weight matters.
- AI tools must not be listed as authors or co-authors on commits or PRs, and unsolicited bot-generated PRs are prohibited (see CONTRIBUTING.md).