Repository navigation
Conversation
…Android and MapKit on iOS
…aps iOS SDK via CocoaPods
…anch Adds common-code clustering to maps-compose-multiplatform via the experimental KMP modules of android-maps-utils (maps-model, clustering): clusterMarkers() runs NonHierarchicalDistanceBasedAlgorithm in commonMain and ClusteredGoogleMap renders the resulting clusters, so Android and iOS produce identical clusters from shared code. Consumption paths (see settings.gradle.kts): publishToMavenLocal from ../android-maps-utils plus -PuseMavenLocal=true (full build works, this is the default), or -PuseLocalMapsUtils=true for a composite build (platform compilations work; shared-metadata compilation is skipped by Kotlin's granular-metadata transform across included builds and fails). Note: linkPodDebugFrameworkIosArm64 fails on this branch with or without this change (Kotlin/Native cache failure on compose-ui 1.7.3 uikitarm64); simulator link and all target compilations pass. Claude-Session: https://claude.ai/code/session_01225X6MnAqkyCF7Xones6WY
The maps-compose-multiplatform module now depends on com.google.maps.android:maps-model and :clustering from the feat/experimental-kmp-clustering branch of android-maps-utils, which are not published to any remote repository. Check out that branch and publish the two modules to the runner's mavenLocal in the lint, test and instrumentation workflows, and set USE_MAVEN_LOCAL so the compose build resolves them from there. Claude-Session: https://claude.ai/code/session_01225X6MnAqkyCF7Xones6WY
com.google.maps.android:clustering duplicated the classes of the android-maps-utils-clustering AAR that maps-compose-utils pulls from Maven Central, failing maps-app's checkDebugDuplicateClasses. Depend on android-maps-utils-clustering / android-maps-utils-maps-model instead (matching the renamed KMP publications) so Gradle resolves both paths to one module; mavenLocal shadows the Central AAR with the API-compatible KMP artifact. Claude-Session: https://claude.ai/code/session_01225X6MnAqkyCF7Xones6WY
…OS CI - KmpPublishingConventionPlugin: explicit API mode, iosArm64 and iosSimulatorArm64, lint, Kover and Maven Central publishing as maps-compose-multiplatform - Public API checks for the iOS klibs (Kotlin ABI validation) and the Android target (binary-compatibility-validator), in api/ - Publishing a release fails while it depends on a maps-utils snapshot - New macOS workflow builds the iOS targets and the iOS demo app - The publish workflow runs on macOS, which the iOS klibs need
…ment the KMP build - commonTest for clusterMarkers, run as Android host tests and on the iOS simulator - iosApp/README.md replaces BUILD_KMP.md; the Xcode project is generated by create_project.rb and no longer checked in - AGENTS.md describes the multiplatform module, its API checks and the snapshot dependency
…-multiplatform
Replaces the prototype API with one that follows maps-compose:
- GoogleMap(cameraPositionState, properties, uiSettings, onMapClick,
onMapLongClick, onMapLoaded) { content }
- CameraPositionState follows the map both ways and can animate
- Marker with MarkerState (draggable, tappable, tinted pin), Polyline,
Polygon with holes and Circle; each keeps one native object per call
instead of clearing the map on every update
- Clustering reclusters as the camera zooms and zooms in on cluster taps
- Line widths are density-independent on both platforms
Demos move to maps-compose-multiplatform-demo, shared by maps-app and the
iOS app, which now hosts them instead of a Swift list. Tests cover the
camera state, content registration and clustering on the JVM and iOS.
…ormLocationSource.android.kt
Coverage (unit tests)Compared against
Line and branch coverage from unit test reports. History is recorded on the |
Code Coverage
|
| LaunchedEffect(appContext) { | ||
| while (true) { | ||
| hasPermission = appContext.hasAnyLocationPermission() | ||
| delay(500L) | ||
| } | ||
| } |
There was a problem hiding this comment.
Polling the permission every 500ms works, but it keeps a loop running for as long as the demo is on screen. Could we re-check it on ON_RESUME with a LifecycleEventObserver instead? That covers both the system dialog and coming back from Settings. What do you think?
There was a problem hiding this comment.
Good call! Replaced the 500ms polling loop in PlatformLocationSource.android.kt with a LifecycleEventObserver in DisposableEffect(lifecycleOwner, appContext) that re-checks permission on Lifecycle.Event.ON_RESUME (and also replaced the polling loop on iOS with CLLocationManagerDelegateProtocol.locationManagerDidChangeAuthorization + UIApplicationDidBecomeActiveNotification).
| Handler(Looper.getMainLooper()).postDelayed({ | ||
| if (!appContext.hasAnyLocationPermission() && activity.hasWindowFocus()) { | ||
| openAppSettings() | ||
| } | ||
| }, 300L) |
There was a problem hiding this comment.
I am thinking out loud if the 300ms window focus heuristic could misfire on slower devices, where the permission dialog takes longer to appear and we would open Settings on top of it. Would it make sense to use shouldShowRequestPermissionRationale (or an ActivityResultLauncher) to detect the permanently denied case instead?
There was a problem hiding this comment.
Agreed—switched to rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) combined with checking shouldShowRequestPermissionRationale before and after the request (!rationaleBeforeRequest && !rationaleAfterRequest) so permanently denied permissions are detected deterministically in the result callback without any timer or window-focus heuristic.
| <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> | ||
| <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> |
There was a problem hiding this comment.
Just to understand it: do we need the location permissions in maps-app, or is this demo only launched from the multiplatform demo module? If maps-app does not use location, we could keep these permissions out of its manifest.
There was a problem hiding this comment.
On Android, :maps-compose-multiplatform-demo is an Android KMP library module hosted by KmpMapActivity inside :maps-app. I reverted maps-app/src/main/AndroidManifest.xml and moved the <uses-permission> declarations into maps-compose-multiplatform-demo/src/androidMain/AndroidManifest.xml so maps-app's own manifest stays untouched while AGP's manifest merger still contributes the permissions for KmpMapActivity.
| if (trail.lastOrNull() != target) { | ||
| trail += target | ||
| } |
There was a problem hiding this comment.
nit: the trail grows without limit while the demo is open. For a demo it is probably fine, but should we cap it (e.g. last 500 points) to avoid an ever growing polyline?
There was a problem hiding this comment.
Done—added MAX_TRAIL_POINTS = 500 in Demos.kt to cap the trail list at the most recent 500 points.
cda70c2 to
54c5bb8
Compare
Coverage (instrumentation tests)
|
Summary
Adds a shared Location Flow demo (
LocationFlowDemo) to:maps-compose-multiplatform-demoexercising the multiplatformLocation,LocationSource, andLocationPriorityAPIs fromgooglemaps/android-maps-utils#1817across Android and iOS:gradle/libs.versions.toml,maps-compose-multiplatform/build.gradle.kts,settings.gradle.kts):maps-utils-kmp-core(com.google.maps.android:android-maps-utils-core) and exposes it viaapi(libs.maps.utils.kmp.core)in:maps-compose-multiplatformcommonMain.mavenLocal()insettings.gradle.kts(when useMavenLocal=true) toincludeGroup("com.google.maps.android")so local KMP snapshot testing does not conflict with external dependencies.PlatformLocationSource.kt,PlatformLocationSource.android.kt,PlatformLocationSource.ios.kt):rememberPlatformLocationController()backed byLocationManageron Android andCLLocationManager.asLocationSource()on iOS, tracking runtime location permission state and providing permission request / system settings actions.LocationFlowDemo(DemoApp.kt,Demos.kt):LocationSource.locationEvents()incommonMainto animate the camera, update a liveMarker, render a horizontal accuracyCircle, and draw a breadcrumbPolylinetrail, with interactiveHigh Accuracy/Balancedpriority switching and runtime permission recovery controls.maps-app/src/main/AndroidManifest.xml,iosApp/iosApp/Info.plist,iosApp/create_project.rb):ACCESS_COARSE_LOCATIONandACCESS_FINE_LOCATIONinmaps-appandNSLocationWhenInUseUsageDescriptioniniosApp.iosApp/create_project.rbto checkIOS_MAPS_API_KEYinsecrets.propertiesbefore falling back toMAPS_API_KEY.Testing