Skip to content
This site is a preview of pull request #1363.

Show the user's location

The location module tracks the user’s position and draws it on the map. A LocationProvider supplies location updates, rememberLocationState collects them, LocationPuck draws the latest measurement, and LocationTrackingEffect keeps the camera in sync with location changes:

App.kt
val locationProvider = rememberDefaultLocationProvider()
val headingProvider = rememberDefaultHeadingProvider() // optional: get heading from sensors
val locationState =
rememberLocationState(
provider = locationProvider,
headingProvider = headingProvider,
)
val mapState = rememberMapState {
val mapState = checkNotNull(LocalMapState.current)
LocationPuck(
idPrefix = "user",
locationState = locationState,
)
LocationTrackingEffect(locationState = locationState) {
mapState.animateCameraPosition(CameraPosition(target = currentLocation.position, zoom = 15.0))
}
}
MaplibreMap(state = mapState)

All platforms provide default location providers. Android and iOS also provide default heading providers. LocationState.availability reports an unsupported or misconfigured provider before the application requests permission.

locationState.lastLocation is null until the first measurement arrives, so the puck initially draws nothing. Afterward, the state retains the last measurement when tracking stops or permission changes.

A Bearing is an absolute horizontal direction, such as South or East. A heading is the bearing that the device faces, and a course is the bearing along which the device moves. A Rotation is a relative angular displacement, for example the angle between two bearings.

The library never requests location permission automatically. Call LocationState.requestPermission when the application is ready to present the platform permission UI:

App.kt
if (locationState.permission !is LocationPermission.Granted) {
Button(onClick = locationState::requestPermission) {
Text("Use my location")
}
}

When authorization is absent, LocationPermission.NotGranted reports the next step: explain first when shouldShowRationale is set (Android only), request when canRequest is not false, and send the user to the system settings otherwise. rememberSystemSettingsLauncher opens the settings screens on the platforms that have them.

App.kt
val settings = rememberSystemSettingsLauncher()
val permission = locationState.permission
if (permission is LocationPermission.NotGranted) {
when {
permission.shouldShowRationale ->
LocationRationale(onAccept = locationState::requestPermission)
permission.canRequest != false ->
Button(onClick = locationState::requestPermission) { Text("Use my location") }
settings.canOpenApplicationSettings ->
Button(onClick = { settings.openApplicationSettings() }) { Text("Open settings") }
}
}

LocationPermission.Unknown means the permission check has not completed. Location collection retries the check without prompting. If the check fails, LocationState.status reports LocationTrackingStatus.Unavailable with the cause. Call LocationState.retry to try again.

Declare ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION in the application manifest. Declare ACCESS_BACKGROUND_LOCATION only when the application tracks location in the background.

For fused location on devices with Google Play services, add the optional runtime module. The default providers then use fused location and heading where Google Play services is available, and the framework providers otherwise.

build.gradle.kts
androidMain.dependencies {
implementation("org.maplibre.compose:location-runtime-gms:0.15.0")
}

For Huawei devices, location-runtime-hms provides fused location through HMS Core instead. It requires Huawei’s repository and HMS Core preparation.

Add the location usage description that Apple requires to your Info.plist.

Browsers supply location only in a secure context, except for development origins such as localhost.

On macOS, add the location usage description and the location entitlement that Apple requires. On Linux, location comes from the desktop portal on the D-Bus session bus, commonly backed by GeoClue. On Windows, location comes from Windows Runtime geolocation. A missing backend reports an unsupported value through LocationState.availability.