Skip to content

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 fix, and LocationTrackingEffect keeps the camera in sync with location changes:

App.kt
val cameraState = rememberCameraState()
val locationProvider = rememberDefaultLocationProvider()
val orientationProvider =
rememberDefaultOrientationProvider() // optional: get device orientation from sensors
val locationState =
rememberLocationState(
provider = locationProvider,
orientationProvider = orientationProvider,
)
MaplibreMap(cameraState = cameraState) {
LocationPuck(
idPrefix = "user",
location = locationState.location,
// optional: combine course and orientation bearing
bearing = locationState.mostAccurateBearing(),
cameraState = cameraState,
)
LocationTrackingEffect(locationState = locationState) {
cameraState.animateTo(CameraPosition(target = currentLocation.position.value, zoom = 15.0))
}
}

All platforms provide default location providers. Android and iOS also provide default orientation providers. LocationState.status reports an unsupported or misconfigured platform without throwing.

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

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 permission is not granted, 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") }
}
}

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 orientation 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 status through LocationState.status.