Skip to content

[Android] Expose LocationRequest maxUpdateAgeMillis so getPositionStream can deliver an initial historical location #1784

Description

@josh-burton

Platform(s)

  • Android

Use case / Problem

On Android, the Fused Location Provider can deliver an "initial historical location" immediately when a new requestLocationUpdates subscription starts. Whether it does so is gated by LocationRequest.Builder.setMaxUpdateAgeMillis, whose default is IMPLICIT_MAX_UPDATE_AGE — i.e. the maximum age of the initial fix equals the request interval.

geolocator_android never calls setMaxUpdateAgeMillis when building the request in FusedLocationClient.java — it only sets the priority, setIntervalMillis, setMinUpdateIntervalMillis, and setMinUpdateDistanceMeters. As a result, the initial-fix window is implicitly and invisibly tied to AndroidSettings.intervalDuration.

Consequence. Apps that need frequent updates and therefore pass a short intervalDuration (e.g. 1 s) unknowingly shrink the initial-historical-location window to ~1 s, effectively disabling initial delivery. At cold start, getPositionStream then stays silent until the FLP derives a completely fresh fix — which can take 10–30+ s (GNSS warmup) or indefinitely indoors — even when a perfectly recent fix exists in the FLP cache.

Confusingly, Geolocator.getCurrentPosition() appears to behave differently in the exact same situation — but only because it internally starts its own updates subscription with the default 5000 ms interval (see MethodCallHandlerImpl.onGetCurrentPosition / LocationOptions.parseArguments), giving it a 5× wider implicit initial-fix window.

The current workaround is to manually merge a one-shot getCurrentPosition() into the position stream.

Steps to reproduce / Expected / Actual

  1. On a device where another app obtained a location fix a few seconds ago, cold-start an app.
  2. Subscribe to Geolocator.getPositionStream(locationSettings: AndroidSettings(intervalDuration: Duration(seconds: 1))).

Expected: an immediate initial position event — the FLP has a recent cached fix that should qualify as an initial historical location.

Actual: no event is emitted until a freshly derived fix arrives, which can take tens of seconds outdoors or never happen indoors.

Observed with geolocator ^14 / current geolocator_android main branch.

Proposal

Add a maxUpdateAge (Duration?) field to AndroidSettings, passed through to LocationRequest.Builder.setMaxUpdateAgeMillis on the builder path:

final stream = Geolocator.getPositionStream(
  locationSettings: AndroidSettings(
    intervalDuration: const Duration(seconds: 1),
    // Accept an initial historical fix up to 30 s old.
    maxUpdateAge: const Duration(seconds: 30),
  ),
);
// FusedLocationClient.java (builder path)
if (locationOptions.getMaxUpdateAgeMillis() != null) {
  builder.setMaxUpdateAgeMillis(locationOptions.getMaxUpdateAgeMillis());
}

On the legacy LocationRequest.create() path the setting could be documented as unsupported (or approximated, if feasible).

Specific requirements or considerations

  • Default null preserves today's implicit behavior, so the change is non-breaking.
  • The key benefit is decoupling "how old may my first fix be" from "how often do I want updates" — two concerns that are currently coupled through an undocumented Play Services default.

Additional information or context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions