Skip to content

Android node: support location.enabledMode: always (background location via foreground service) #68581

Description

@jkobject

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal backlog priority with limited blast radius.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:needs-security-reviewClawSweeper marked this issue as needing security-sensitive review.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:securitySecurity boundary, credential, authz, sandbox, or sensitive-data risk.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.staleMarked as stale due to inactivity

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions