You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Feature requests are accepted only if the proposed skill fills a verified gap in state-of-the-art LLMs. Evaluations below used a fast model (Cursor Composer 2.5 Fast) and a thinking model (Cursor Grok 4.6). Gemini 3 Flash / Gemini 3.1 Pro were not available in this environment; please re-run the same prompts on those models if needed.
What is the gap in the LLM's knowledge?
android/skills has no location category. Current models already know to reach for FusedLocationProviderClient and they do not grab ACCESS_BACKGROUND_LOCATION for on-screen features. The remaining, repeatable gaps are the decision tree and Android 12 permission semantics, not "does FLP exist".
Four prompts, no web/docs/skills, code from memory only:
Prompt
Fast (Composer 2.5)
Thinking (Grok 4.6)
A. Compose screen, get location once, city-level, targetSdk 35
Pass: ACCESS_COARSE_LOCATION only + getCurrentLocation(PRIORITY_BALANCED_POWER_ACCURACY)
Pass: same + CurrentLocationRequest / GRANULARITY_COARSE
B. Track while screen visible (street-level), must stop when leaving
Fail: requests FINE+COARSE and results.values.all { it }, so an Android 12 approximate-only grant is treated as denied. Also PRIORITY_HIGH_ACCURACY for a one-shot home screen.
Fail: requests FINE+COARSE, then starts unbounded requestLocationUpdates in a ViewModel (not tied to ON_STOP) for a one-shot display. getCurrentLocation(..., null) (no CancellationToken).
D. "I need GPS coordinates… keep them updated as the user moves"
Fail: FLP + HIGH_ACCURACY, but cleanup is only DisposableEffect.onDispose / ViewModel.onCleared. Home / recents does not stop updates (background leak without a background permission).
Fail: same lifecycle hole (DisposableEffect(granted) only). Seeds UI from lastLocation with no age check. Starts PRIORITY_HIGH_ACCURACY even if the user granted only coarse.
When the prompt spelled out "coarse / once / stop on leave", both models complied. When a developer speaks naturally ("show my coordinates", "GPS", "keep updating"), they over-request fine, start a stream they do not stop on ON_STOP, and mishandle Android 12 approximate grants.
None of the eight runs used SettingsClient.checkLocationSettings. Permission granted was treated as "location is on".
Path: location/fused-location/SKILL.md (same layout as camera/camerax).
Scope: foreground only — runtime permissions (coarse vs fine, Android 12+), getCurrentLocation vs requestLocationUpdates, bind updates to ON_START/ON_STOP, location settings. Not Maps, geofencing, or background location.
Full draft:
---name: fused-locationdescription: > Guide Android foreground location with FusedLocationProviderClient. Use when implementing current location, location updates, runtime location permissions, approximate vs precise location on Android 12+, or when an app would otherwise use LocationManager GPS_PROVIDER.license: Complete terms in LICENSE.txtmetadata:
author: community proposallast-updated: '2026-08-29'keywords:
- recipe
- Android
- location
- FusedLocationProvider
- FusedLocationProviderClient
- ACCESS_COARSE_LOCATION
- ACCESS_FINE_LOCATION
- getCurrentLocation
- requestLocationUpdates
- Compose
- permissions
- approximate location
- precise location---
Procedural guidance for **foreground** location on Android using Play services
`FusedLocationProviderClient`. Grounded in
[Request location permissions](https://developer.android.com/develop/sensors-and-location/location/permissions)
and
[Get the last known location](https://developer.android.com/develop/sensors-and-location/location/retrieve-current).
**Out of scope:** Maps SDK, geofencing, activity recognition, and background
location (`ACCESS_BACKGROUND_LOCATION`, location foreground services).
## Step 1: pick accuracy and API
Ask what the feature actually needs. Do not default to GPS / fine / streaming.
| Need | Permission | API || --- | --- | --- || City / weather / "which area" **once**|`ACCESS_COARSE_LOCATION` only |`getCurrentLocation` + `PRIORITY_BALANCED_POWER_ACCURACY` or `PRIORITY_LOW_POWER`|| Street-level **once**|`ACCESS_FINE_LOCATION`**and**`ACCESS_COARSE_LOCATION`|`getCurrentLocation` + `PRIORITY_HIGH_ACCURACY`|| Street-level **while UI is visible**| Fine + coarse |`requestLocationUpdates` + `removeLocationUpdates` on `ON_STOP`|`getLastLocation()` / `lastLocation` is a cache. It can be `null` or hours old.
Do **not** use it as the primary one-shot API.
[Prefer `getCurrentLocation()`](https://developer.android.com/develop/sensors-and-location/location/retrieve-current).
```kotlin// WRONG — GPS provider, no fusion, easy to leak updates
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 2000L, 0f, listener
)
// WRONG — stale cache as the only source
fusedClient.lastLocation.addOnSuccessListener { loc -> show(loc) }
// CORRECT — one-shot, fused, cancellableval cts =CancellationTokenSource()
fusedClient.getCurrentLocation(
Priority.PRIORITY_BALANCED_POWER_ACCURACY,
cts.token,
)
```
Dependency: `com.google.android.gms:play-services-location`.
## Step 2: declare and request permissions### Manifest- City-level: declare **only**`ACCESS_COARSE_LOCATION`.
- Precise: declare **both**`ACCESS_FINE_LOCATION` and `ACCESS_COARSE_LOCATION`.
On Android 12+ the system [ignores a fine-only request](https://developer.android.com/develop/sensors-and-location/location/permissions)
(`ACCESS_FINE_LOCATION must be requested with ACCESS_COARSE_LOCATION`).
- Do **not** declare `ACCESS_BACKGROUND_LOCATION` for on-screen features.
### Runtime
Use `ActivityResultContracts.RequestPermission` (coarse only) or
`RequestMultiplePermissions` (fine + coarse in **one** call).
Android 12+ users can grant **approximate** even when the app asked for precise.
That is a valid grant, not a denial.
```kotlin// WRONG — approximate-only looks like "denied"val granted = results.values.all { it }
// CORRECT — any location grant is success; inspect fine separatelyval hasCoarse = results[Manifest.permission.ACCESS_COARSE_LOCATION] ==true||
context.hasPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
val hasFine = results[Manifest.permission.ACCESS_FINE_LOCATION] ==true||
context.hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)
```
If the feature **requires** street-level accuracy and the user granted only
approximate, keep the feature working at coarse if possible; otherwise explain
why precise is needed and request `ACCESS_FINE_LOCATION` again (upgrade dialog).
Do not block the whole app on first approximate grant unless the UX truly cannot
function.
Do **not** treat the first denial as "permanently denied".
`shouldShowRequestPermissionRationale == false` right after the first dialog is
unreliable.
## Step 3: one-shot current location```kotlin
@SuppressLint("MissingPermission")
suspendfuncurrentLocation(
client:FusedLocationProviderClient,
fineGranted:Boolean,
): Location? {
val cts =CancellationTokenSource()
val priority =if (fineGranted) {
Priority.PRIORITY_HIGH_ACCURACY
} else {
Priority.PRIORITY_BALANCED_POWER_ACCURACY
}
return suspendCancellableCoroutine { cont ->
cont.invokeOnCancellation { cts.cancel() }
client.getCurrentLocation(priority, cts.token)
.addOnSuccessListener { loc ->if (cont.isActive) cont.resume(loc) }
.addOnFailureListener { e ->if (cont.isActive) cont.resumeWithException(e)
}
}
}
```
If the result is `null`, the usual causes are: permission missing, location
services off, or Play services unavailable — not "call `lastLocation` and hope".
## Step 4: updates only while the screen is visible`ViewModel.onCleared()` and `DisposableEffect.onDispose` do **not** run when the
user presses Home or opens recents. Updates keep flowing in the background
without a background permission. Bind to `Lifecycle.Event.ON_START` / `ON_STOP`.
```kotlin// WRONG — Home / recents leaves the callback registeredDisposableEffect(Unit) {
client.requestLocationUpdates(request, callback, Looper.getMainLooper())
onDispose { client.removeLocationUpdates(callback) }
}
// CORRECTDisposableEffect(lifecycleOwner, client) {
val callback =object:LocationCallback() {
overridefunonLocationResult(result:LocationResult) {
result.lastLocation?.let { /* ui state */ }
}
}
val observer =LifecycleEventObserver { _, event ->when (event) {
Lifecycle.Event.ON_START-> client.requestLocationUpdates(
request, callback, Looper.getMainLooper()
)
Lifecycle.Event.ON_STOP-> client.removeLocationUpdates(callback)
else->Unit
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
client.removeLocationUpdates(callback)
}
}
```
Use `LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, intervalMillis)`
(or balanced/low-power for coarse). Do not use the deprecated
`LocationRequest.create()`.
## Step 5: resolve location settings
Permission granted ≠ location enabled. If `getCurrentLocation` returns `null` or
updates never arrive, check settings with
[`SettingsClient.checkLocationSettings`](https://developers.google.com/android/reference/com/google/android/gms/location/SettingsClient)
and, on `ResolvableApiException`, launch the system resolution dialog. Also
handle Play services missing / updating.
## Common pitfalls- Defaulting to `ACCESS_FINE_LOCATION` + `PRIORITY_HIGH_ACCURACY` for "show my
coordinates" on a home screen.
- Starting `requestLocationUpdates` when `getCurrentLocation` is enough.
-`results.values.all { it }` after `RequestMultiplePermissions` (Android 12
approximate grant).
- Requesting `ACCESS_FINE_LOCATION`**without**`ACCESS_COARSE_LOCATION`.
- Pairing `ACCESS_BACKGROUND_LOCATION` with the first foreground request.
- Using `LocationManager` / `GPS_PROVIDER` instead of fused location.
- Passing `null` as the `CancellationToken` to `getCurrentLocation` and never
cancelling.
- Seeding UI from `lastLocation` with no age check.
## Official docs-[Request location permissions](https://developer.android.com/develop/sensors-and-location/location/permissions)-[Get current / last location](https://developer.android.com/develop/sensors-and-location/location/retrieve-current)-[Request location updates](https://developer.android.com/develop/sensors-and-location/location/request-updates)-[Approximate location (Android 12+)](https://developer.android.com/develop/sensors-and-location/location/permissions)
Additional Context
Repo currently has camera, identity, system, and other categories, but no location/ tree.
README says public PRs are not accepted, so this is an issue-only proposal rather than a PR.
The skill is intentionally narrower than "maps + geofence + background" so it stays in the "LLM underperforms" zone (decision tree + Android 12), not a restatement of FLP existence.
Happy to add Maps / background location as separate skills if this one lands.
Note
Feature requests are accepted only if the proposed skill fills a verified gap in state-of-the-art LLMs. Evaluations below used a fast model (Cursor Composer 2.5 Fast) and a thinking model (Cursor Grok 4.6). Gemini 3 Flash / Gemini 3.1 Pro were not available in this environment; please re-run the same prompts on those models if needed.
What is the gap in the LLM's knowledge?
android/skillshas no location category. Current models already know to reach forFusedLocationProviderClientand they do not grabACCESS_BACKGROUND_LOCATIONfor on-screen features. The remaining, repeatable gaps are the decision tree and Android 12 permission semantics, not "does FLP exist".Four prompts, no web/docs/skills, code from memory only:
ACCESS_COARSE_LOCATIONonly +getCurrentLocation(PRIORITY_BALANCED_POWER_ACCURACY)CurrentLocationRequest/GRANULARITY_COARSErequestLocationUpdates,ON_START/ON_STOPresults.values.all { it }, so an Android 12 approximate-only grant is treated as denied. AlsoPRIORITY_HIGH_ACCURACYfor a one-shot home screen.requestLocationUpdatesin a ViewModel (not tied toON_STOP) for a one-shot display.getCurrentLocation(..., null)(noCancellationToken).DisposableEffect.onDispose/ViewModel.onCleared. Home / recents does not stop updates (background leak without a background permission).DisposableEffect(granted)only). Seeds UI fromlastLocationwith no age check. StartsPRIORITY_HIGH_ACCURACYeven if the user granted only coarse.When the prompt spelled out "coarse / once / stop on leave", both models complied. When a developer speaks naturally ("show my coordinates", "GPS", "keep updating"), they over-request fine, start a stream they do not stop on
ON_STOP, and mishandle Android 12 approximate grants.None of the eight runs used
SettingsClient.checkLocationSettings. Permission granted was treated as "location is on".These match documented platform rules:
getCurrentLocation()over managing updates / stalegetLastLocation(): https://developer.android.com/develop/sensors-and-location/location/retrieve-currentProposed Skill
Path:
location/fused-location/SKILL.md(same layout ascamera/camerax).Scope: foreground only — runtime permissions (coarse vs fine, Android 12+),
getCurrentLocationvsrequestLocationUpdates, bind updates toON_START/ON_STOP, location settings. Not Maps, geofencing, or background location.Full draft:
Additional Context
camera,identity,system, and other categories, but nolocation/tree.