Skip to main content

Current and continuous location requests

“Where am I?” and “track my route” are different contracts.

  • Current location: one bounded answer with freshness/accuracy trade-offs.
  • Last location: cheap cached value that may be null or old.
  • Continuous updates: an ongoing stream consuming more power and requiring lifecycle ownership.

One current fix​

suspend fun FusedLocationProviderClient.awaitCurrentLocation(
cancellationToken: CancellationToken,
): Location? = getCurrentLocation(
CurrentLocationRequest.Builder()
.setPriority(Priority.PRIORITY_BALANCED_POWER_ACCURACY)
.setDurationMillis(10_000)
.setMaxUpdateAgeMillis(15_000)
.build(),
cancellationToken,
).await()

Set a bounded duration and decide whether a cached value up to a given age is acceptable. A food-delivery pickup pin may need tighter criteria than regional recommendations.

Continuous route tracking​

val request = LocationRequest.Builder(
Priority.PRIORITY_HIGH_ACCURACY,
5_000L,
)
.setMinUpdateIntervalMillis(2_000L)
.setMinUpdateDistanceMeters(10f)
.setMaxUpdateDelayMillis(15_000L)
.build()

The interval is a request, not a guarantee. Batching can reduce wakeups and may produce batches that must be ordered using location timestamps. Remove updates when ownership ends.

override fun onStop() {
fusedClient.removeLocationUpdates(callback)
super.onStop()
}

For a user-started navigation/tracking session expected to continue in background, use the appropriate location foreground service and notification rather than leaving an Activity callback registered.

Battery versus accuracy​

ChoiceAccuracy/latencyBattery
passive/balanced, longer intervallower/slowerlower
high accuracy, short intervalhigher/fasterhigher
min distanceremoves unhelpful stationary callbackslower
batching/max delaydelayed batcheslower wake cost

Select values from product needs. “High accuracy every second” is not a professional default.

Filtering and ordering​

  • Reject impossible coordinate ranges and non-finite values.
  • Keep accuracy and time; do not average points blindly.
  • Sort/compare by measurement elapsed realtime, not callback arrival order.
  • A jump can be real (transport) or noise; use speed/accuracy/context rules and flag uncertainty.
  • Do not discard mock locations solely as “fraud”; emulators, accessibility/testing, and developer settings can produce them. Server-side risk decisions require multiple signals.

Error states are part of the API​

sealed interface LocateResult {
data class Success(val sample: LocationSample) : LocateResult
data object PermissionMissing : LocateResult
data object SettingsDisabled : LocateResult
data object TimedOut : LocateResult
data object NoAcceptableFix : LocateResult
}

Avoid one generic “location failed.” Each state has a different user action.

Sources​

Interview question​

Why not use lastLocation for checkout delivery position? It is cached, may be null/stale, and has no guarantee of current relevance. Validate age/accuracy or request a bounded current fix.