as-app/docs/location-tracking-qa.md

6.8 KiB

Location tracking QA checklist

Applies to the BackgroundGeolocation integration:

Goals

  1. Updates only when moved enough
    • IDLE: record/upload only after moving ~200m.
    • ACTIVE: record/upload after moving ~25m.
  2. Works in foreground, background and terminated (Android + iOS).
  3. Avoid uploads while stationary.

Current implementation notes

  • Movement-driven recording only:

    • IDLE relies on the SDK's stop-detection + stationary geofence (geolocation.stopOnStationary + geolocation.stationaryRadius) to avoid periodic stationary updates on Android.
      • We explicitly exit moving mode on entry to IDLE (changePace(false)) to prevent drift-generated periodic locations.
      • If the SDK later reports a real move (onMotionChange(isMoving:true)), JS may request one persisted fix as a fallback.
      • We intentionally do not rely on time-based updates.
    • ACTIVE uses geolocation.distanceFilter: 25.
    • JS may request a persisted fix when entering ACTIVE (see applyProfile()).
  • Upload strategy is intentionally simple:

    • Keep only the latest persisted geopoint: persistence.maxRecordsToPersist: 1.
    • No batching / thresholds: batchSync: false, autoSyncThreshold: 0.
    • When authenticated, each persisted location should upload immediately via native HTTP (works while JS is suspended).
    • Pre-auth: tracking may persist locally but http.url is empty so nothing is uploaded until auth is ready.
  • Stationary noise suppression:

    • Native accuracy gate for persisted/uploaded locations: geolocation.filter.trackingAccuracyThreshold: 100.
    • Identical location suppression: geolocation.allowIdenticalLocations: false.
    • IDLE primarily relies on stop-detection + stationary geofence (stopOnStationary: true) to eliminate periodic stationary updates.
    • Elasticity disabled (disableElasticity: true) to avoid dynamic distanceFilter shrink.
    • Extra safety: any JS-triggered persisted fix requests are tagged and ignored if accuracy > 100m.

Concise testing checklist (Android + iOS)

1) Baseline setup

  • App has foreground + background location permissions.
  • Motion/Activity permission granted (iOS motion, Android activity-recognition if prompted).
  • Logged-in (to validate native HTTP uploads).

2) IDLE (no open alert)

  1. Launch app and confirm there is no open alert owned by the current user.
  2. Leave phone stationary for 10+ minutes (screen on and screen off).
    • Expect: no periodic server uploads.
  3. Walk/drive ~250m.
    • Expect: a movement-triggered persisted location + upload.

3) ACTIVE (open alert)

  1. Open an alert owned by the current user.
  2. Move ~30m.
    • Expect: at least one persisted location reaches server quickly.
  3. Continue moving.
    • Expect: updates align with movement (distanceFilter-based), not time.

4) Lifecycle coverage

  • Foreground → background: repeat IDLE and ACTIVE steps.
  • Terminated:
    • Android: swipe-away from recents, then move the above distances and verify server updates.
    • iOS: swipe-kill, then move significantly and verify app relaunch + upload after relaunch.

Basic preconditions

  • Location permissions: foreground + background granted.
  • Motion permission granted.
  • Network reachable.

Foreground behavior

IDLE (no open alert)

  1. Launch app, ensure no open alert.
  2. Stay stationary for 5+ minutes.
    • Expect: no repeated server updates.
  3. Walk/drive ~250m.
    • Expect: onMotionChange(isMoving:true) then one persisted location + upload.

ACTIVE (open alert)

  1. Open an alert owned by the current user.
  2. Move ~30m.
    • Expect: at least one location persisted + uploaded.
  3. Continue moving.
    • Expect: periodic updates roughly aligned with movement, not time.

Background behavior

IDLE

  1. Put app in background.
  2. Stay stationary.
    • Expect: no periodic uploads.
  3. Move ~250m.
    • Expect: onMotionChange(isMoving:true) then one persisted record and upload.

ACTIVE

  1. Put app in background.
  2. Move ~30m.
    • Expect: updates continue.

Terminated behavior

Android

  1. Ensure tracking enabled and authenticated.
  2. Swipe the app away from recents / kill the task.
  3. Move ~250m in IDLE.
    • Expect: native service still records + uploads.
  4. Move ~30m in ACTIVE.
    • Expect: native service still records + uploads.

Note: This does not include Android Settings → Force stop. Force-stop prevents background services and receivers from running; no SDK can reliably track after that.

iOS

  1. Swipe-kill the app.
  2. Move significantly (expect iOS to relaunch app on stationary-geofence exit).
    • Expect: tracking resumes and uploads after movement.

Test matrix (quick)

Platform App state Profile Move Expected signals
Android foreground IDLE ~250m onMotionChange then onLocation (sample=false), then onHttp
Android background IDLE ~250m same as above
Android swipe-away IDLE ~250m native geofence triggers; verify server update; app may relaunch to deliver JS logs
Android foreground ACTIVE ~30m location + upload continues
iOS background IDLE ~250m movement-driven update; no periodic uploads while stationary
iOS swipe-killed IDLE significant OS relaunch on movement; upload after relaunch

What to look for in logs

  • App lifecycle tagging: updateTrackingContextExtras() should update tracking_ctx.app_state on AppState changes.

  • No time-based uploads: heartbeat is disabled (heartbeatInterval: 0).

  • Movement-only uploads:

    • IDLE: look for Motion change (isMoving=true) and (in rare cases) IDLE movement fallback fix.
    • ACTIVE distance threshold: distanceFilter: 25 in TRACKING_PROFILES.
  • Attribution for getCurrentPosition:

    • Location update received logs include extras.req_reason and extras.req_persist.
    • Persisted-fix reasons to expect: active_profile_enter, moving_edge, startup_fix, identity_fix:*.
  • Accuracy gate signals:

    • A persisted-fix request can be logged but later ignored due to accuracy > 100m.
    • If the server still receives periodic updates while stationary, check that the uploaded record has acceptable accuracy and that the device isn't flapping between moving/stationary.

Debugging tips

  • Observe logs in app:
  • Correlate:
    • onLocation events
    • onHttp events
    • pending queue (BackgroundGeolocation.getCount() in logs)