openclaw - 💡(How to fix) Fix Android node: support `location.enabledMode: always` (background location via foreground service) [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#68581Fetched 2026-04-19 15:09:57
View on GitHub
Comments
0
Participants
1
Timeline
0
Reactions
0
Author
Participants

On the Android node app, nodes location get currently only works when the OpenClaw app is in the foreground. Any background call fails with LOCATION_BACKGROUND_UNAVAILABLE. The Location Command docs already spec location.enabledMode: always and describe the intended Android behavior under a "Background behavior (future)" heading, but the Android app only exposes Off / While Using in Settings today.

This issue is a request to ship that future behavior: let users opt into Always mode on Android, backed by a foreground service, so an agent can fetch location on a schedule (cron, heartbeat, activity tracker, etc.) without having to keep the app visible.

Error Message

Returns a clean payload with lat, lon, accuracyMeters, isPrecise, timestamp. Error codes are already stable (LOCATION_DISABLED, LOCATION_PERMISSION_REQUIRED, LOCATION_BACKGROUND_UNAVAILABLE, LOCATION_TIMEOUT, LOCATION_UNAVAILABLE). 5. Error matrix stays the same — just stop emitting LOCATION_BACKGROUND_UNAVAILABLE when mode is always and background grant is present. (Keep the code, because it still applies when mode is whileUsing + backgrounded.) If the LOCATION_BACKGROUND_UNAVAILABLE emitter is a single when branch gating on isAppForeground, the real fix is probably small: replace that branch with "if mode is always and we have background permission, start the foreground service and fulfill the request; otherwise emit the existing error."

Root Cause

  1. Add Always to the Android Settings selector, with the same tri-state UX already documented for iOS/macOS: Off / While Using / Always.
  2. Request ACCESS_BACKGROUND_LOCATION when user picks Always. Android 11+ sends the user into system Settings for that grant — follow that flow and gracefully revert to whileUsing if denied, as the spec prescribes ("If OS denies requested level, revert to the highest granted level and show status").
  3. Run a foreground service when Always is active, declared with foregroundServiceType="location" (required on Android 14+). Show a small persistent notification while the service is active — Android requires visibility anyway.
  4. On a location.get invoke while backgrounded, if mode is always + grant is present → start a short-lived location request via that service, return the fix, stop. No need for continuous tracking: episodic wake-and-fix is enough for the scheduled-cron use case.
  5. Error matrix stays the same — just stop emitting LOCATION_BACKGROUND_UNAVAILABLE when mode is always and background grant is present. (Keep the code, because it still applies when mode is whileUsing + backgrounded.)

Code Example

openclaw nodes location get --node <nodeId> --json

---

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<!-- Needed only if targeting Android 14+ -->

<service
    android:name=".location.LocationForegroundService"
    android:foregroundServiceType="location"
    android:exported="false" />
RAW_BUFFERClick to expand / collapse

Summary

On the Android node app, nodes location get currently only works when the OpenClaw app is in the foreground. Any background call fails with LOCATION_BACKGROUND_UNAVAILABLE. The Location Command docs already spec location.enabledMode: always and describe the intended Android behavior under a "Background behavior (future)" heading, but the Android app only exposes Off / While Using in Settings today.

This issue is a request to ship that future behavior: let users opt into Always mode on Android, backed by a foreground service, so an agent can fetch location on a schedule (cron, heartbeat, activity tracker, etc.) without having to keep the app visible.

Motivation / real use case

I'm running a 30-minute activity-tracker cron on my Gateway that logs where I am + what I'm doing. Today:

  • macOS node → openclaw nodes location get --node "Jeremie's MacBook Air" returns GPS fine. ✅
  • Android node (Pixel, paired, app installed, location permission granted while using) → fails with LOCATION_BACKGROUND_UNAVAILABLE unless I manually foreground the app. ❌

So when I'm out of the house with only my phone, the tracker falls back to heuristics (agenda, last known location) instead of real GPS. Across a user base this is a common pattern — any scheduled agent that wants mobile location will hit this.

Current state (as of 2026.4.15)

CLI side (works):

openclaw nodes location get --node <nodeId> --json

Returns a clean payload with lat, lon, accuracyMeters, isPrecise, timestamp. Error codes are already stable (LOCATION_DISABLED, LOCATION_PERMISSION_REQUIRED, LOCATION_BACKGROUND_UNAVAILABLE, LOCATION_TIMEOUT, LOCATION_UNAVAILABLE).

Android app side (partial):

  • Settings selector: Off / While Using only (no Always).
  • Single toggle: Precise Location.
  • Behavior: any location.get while backgrounded returns LOCATION_BACKGROUND_UNAVAILABLE.
  • Docs already note: "Android app currently supports foreground location only."

Proposed change

Ship the "Background behavior (future)" section from the current spec:

  1. Add Always to the Android Settings selector, with the same tri-state UX already documented for iOS/macOS: Off / While Using / Always.
  2. Request ACCESS_BACKGROUND_LOCATION when user picks Always. Android 11+ sends the user into system Settings for that grant — follow that flow and gracefully revert to whileUsing if denied, as the spec prescribes ("If OS denies requested level, revert to the highest granted level and show status").
  3. Run a foreground service when Always is active, declared with foregroundServiceType="location" (required on Android 14+). Show a small persistent notification while the service is active — Android requires visibility anyway.
  4. On a location.get invoke while backgrounded, if mode is always + grant is present → start a short-lived location request via that service, return the fix, stop. No need for continuous tracking: episodic wake-and-fix is enough for the scheduled-cron use case.
  5. Error matrix stays the same — just stop emitting LOCATION_BACKGROUND_UNAVAILABLE when mode is always and background grant is present. (Keep the code, because it still applies when mode is whileUsing + backgrounded.)

Manifest bits (sketch)

If the app doesn't already declare them (can't easily check from outside):

<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
<!-- Needed only if targeting Android 14+ -->

<service
    android:name=".location.LocationForegroundService"
    android:foregroundServiceType="location"
    android:exported="false" />

Where this likely lives in the codebase

Based on the OpenClaw-Book TOC, the Android node app is under:

  • apps/android/ (Kotlin) in the openclaw/openclaw monorepo, or a sibling repo if split.
  • Section 28.3 of the book: "Android Node App — Kotlin architecture / Canvas / Camera / Screen recording".

Files worth touching (names inferred from Android conventions + existing capabilities):

  • AndroidManifest.xml → permissions + service declaration above.
  • The Kotlin module that handles the location.get RPC from the Gateway (look for the string LOCATION_BACKGROUND_UNAVAILABLE — there should be exactly one emitter).
  • The Settings screen where location.enabledMode is stored (currently off | whileUsing).
  • Add a new LocationForegroundService class handling start/stop + single-shot fix via FusedLocationProviderClient.getCurrentLocation(...).

If the LOCATION_BACKGROUND_UNAVAILABLE emitter is a single when branch gating on isAppForeground, the real fix is probably small: replace that branch with "if mode is always and we have background permission, start the foreground service and fulfill the request; otherwise emit the existing error."

Alternatives considered

  • Push-triggered wake (the iOS pattern described in the spec): would work via FCM data messages, but Android 12+ heavily restricts background starts from data pushes. A foreground service with Always permission is the cleaner, user-visible path.
  • Keeping the app foregrounded: works today, but defeats the point of scheduled agents on a phone.
  • Relying on whileUsing + launching the app from ADB/automation: not a real-user solution.

Privacy / UX considerations

  • Always must remain opt-in with an explicit OS-level prompt. The docs already propose the UX copy: "Allow background location. Requires system permission."
  • The foreground service notification should state clearly that OpenClaw is accessing location in the background. This is a hard Android requirement and also the right thing.
  • Precise vs coarse should stay orthogonal to the mode selector, as already specified.

Acceptance criteria

  • Android Settings selector shows Off / While Using / Always.
  • Selecting Always triggers the ACCESS_BACKGROUND_LOCATION flow.
  • With Always granted, openclaw nodes location get --node <pixel> returns a valid fix while the app is backgrounded.
  • With whileUsing granted and app backgrounded, LOCATION_BACKGROUND_UNAVAILABLE is still returned (existing behavior preserved).
  • Foreground service notification appears while the service is active, and disappears after the fix returns.
  • Docs page Location Command updated: remove the "(future)" marker from "Background behavior", document Android foreground service behavior.

Context

Tested on:

  • OpenClaw 2026.4.15 (041266a), Linux Gateway on VPS.
  • Android node: Pixel, app installed & paired, location.enabledMode = whileUsing, precise enabled.
  • Command that triggers: openclaw nodes location get --node "Pixel de <name>" --json.

Happy to test a pre-release build against my setup if useful.

extent analysis

TL;DR

To fix the issue, add an "Always" option to the Android Settings selector and implement a foreground service to handle location requests when the app is backgrounded.

Guidance

  1. Add "Always" to the Android Settings selector: Update the settings screen to include the "Always" option, as described in the proposed change.
  2. Request ACCESS_BACKGROUND_LOCATION permission: When the user selects "Always", request the ACCESS_BACKGROUND_LOCATION permission and handle the OS-level prompt.
  3. Implement a foreground service: Create a foreground service to handle location requests when the app is backgrounded, using the FusedLocationProviderClient to get the current location.
  4. Update the location.get RPC handler: Modify the location.get RPC handler to start the foreground service and fulfill the request when the mode is "Always" and the background permission is granted.
  5. Test the implementation: Verify that the "Always" option is visible in the settings, that the foreground service is started when the app is backgrounded, and that the location.get RPC returns a valid fix.

Example

// Example of how to request ACCESS_BACKGROUND_LOCATION permission
if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(activity, arrayOf(Manifest.permission.ACCESS_BACKGROUND_LOCATION), REQUEST_CODE)
}

Notes

The implementation should follow the proposed change and ensure that the foreground service is properly declared in the AndroidManifest.xml file. Additionally, the docs page should be updated to reflect the new behavior.

Recommendation

Apply the workaround by implementing the proposed change, as it provides a clear solution to the issue and aligns with the intended Android behavior.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING