Skip to content

Support app-provided tracked location sources for native puck and follow mode #760

@klemensz

Description

@klemensz

While migrating Ferrostar to org.maplibre.compose here: stadiamaps/ferrostar#853 I ran into a gap for navigation use cases.

Use case

In navigation, the displayed user location is often not raw GPS.

Instead, apps typically use a preferred location:

  • snapped-to-route while the user is still on-route
  • raw location when off-route

This avoids the puck jumping around because of GPS noise.

How Ferrostar handles this on iOS

On iOS with MapLibreSwiftUI, Ferrostar already does this successfully:

  • NavigationState.preferredUserLocation returns snapped or raw location depending on route state
  • NavigationMapView feeds that into a StaticLocationManager
  • MapLibre native tracking (followWithCourse) uses that location source directly

So on iOS:

  • native puck
  • native follow camera
  • snapped location

all use the same native pipeline.

Problem on Android Compose

maplibre-compose already has:

  • LocationProvider
  • UserLocationState
  • rememberUserLocationState
  • LocationPuck
  • LocationTrackingEffect

But there does not seem to be a way to let the map’s native tracking / native puck use an app-provided location source.

Because of that, libraries like Ferrostar currently have to:

  • compute a snapped location themselves
  • move the camera manually
  • render a custom puck separately

That works to some extend, but it is not as robust as the iOS approach.

What we would like

A way to provide a custom tracked location source to MaplibreMap, so native tracking and native puck rendering can use it.

Conceptually something like:

val preferredLocationState = rememberUserLocationState(preferredLocationProvider)

MaplibreMap(
    baseStyle = baseStyle,
    cameraState = cameraState,
    trackedLocationState = preferredLocationState,
    trackingMode = TrackingMode.FollowWithCourse,
    locationPuck = LocationPuck.Default,
)

Why this matters

For navigation, this would allow:

  1. app computes preferred location
  • snapped on-route
  • raw off-route
  1. map consumes that source directly
  2. native puck + native follow camera stay in sync

This is preferable to rendering a separate custom puck.

KMP angle

Since maplibre-compose is a KMP library, this seems like a good fit for:

  • a shared common API
  • platform-specific implementations underneath

At least Android and iOS seem relevant here.

iOS in particular looks like a natural fit, because this model already exists conceptually there via native tracking + app-provided location source.

Native platform hooks already seem to exist

From what I can tell, this may only require exposing existing native SDK capability cleanly in maplibre-compose.

  • On iOS, MLNMapView already has a locationManager property. Ferrostar uses this with a StaticLocationManager to feed a preferred navigation location into the native puck / native tracking pipeline.
  • On Android, this appears to map to LocationComponent, which already supports custom location input via a custom LocationEngine, and also manual updates via forceLocationUpdate(...) when default engine management is disabled.

So the missing piece seems to be mainly at the maplibre-compose API layer: exposing these native tracked-location hooks in a multiplatform-friendly way.

Backward compatibility

This seems possible to add in a fully backward-compatible way.

The existing Compose-based APIs could remain unchanged, especially:

  • LocationPuck
  • LocationTrackingEffect
  • CameraState

A native tracked-location pipeline could be introduced as an additional opt-in path for navigation use cases, while existing apps continue to use the current Compose-based location puck and camera-tracking approach.

That would allow:

  • existing apps to keep using LocationPuck as they do today
  • navigation apps to opt into a native puck + native follow mode driven by an app-provided location source

The important part is that this would be additive, not a replacement of the current APIs.

Environment

  • org.maplibre.compose:maplibre-compose:0.12.1
  • Android
  • navigation / follow-camera UI
  • app-computed snapped route location

I will try to work on a PR for this soon, since this would significantly improve the Ferrostar navigation integration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions