chore: wip
This commit is contained in:
parent
cce4250a84
commit
42d098e9f7
3 changed files with 80 additions and 7 deletions
|
|
@ -161,3 +161,21 @@ Applies to the BackgroundGeolocation integration:
|
||||||
- `onLocation` events
|
- `onLocation` events
|
||||||
- `onHttp` events
|
- `onHttp` events
|
||||||
- pending queue (`BackgroundGeolocation.getCount()` in logs)
|
- pending queue (`BackgroundGeolocation.getCount()` in logs)
|
||||||
|
|
||||||
|
## Android-specific note (stationary-geofence EXIT loop)
|
||||||
|
|
||||||
|
Some Android devices can repeatedly trigger the SDK's internal **stationary geofence EXIT** using a very poor "trigger" fix (eg `hAcc=500m`).
|
||||||
|
This can cause false motion transitions and periodic persisted uploads even when the phone is not moving.
|
||||||
|
|
||||||
|
Mitigation applied:
|
||||||
|
|
||||||
|
- Android IDLE disables `geolocation.stopOnStationary` (we do **not** rely on stationary-geofence mode in IDLE on Android).
|
||||||
|
- See [`BASE_GEOLOCATION_CONFIG.geolocation.stopOnStationary`](src/location/backgroundGeolocationConfig.js:1) and [`TRACKING_PROFILES.idle.geolocation.stopOnStationary`](src/location/backgroundGeolocationConfig.js:1).
|
||||||
|
|
||||||
|
- Android IDLE uses `geolocation.useSignificantChangesOnly: true` to rely on OS-level significant movement events.
|
||||||
|
- See [`TRACKING_PROFILES.idle.geolocation.useSignificantChangesOnly`](src/location/backgroundGeolocationConfig.js:1).
|
||||||
|
|
||||||
|
Diagnostics:
|
||||||
|
|
||||||
|
- `onGeofence` events are logged (identifier/action/accuracy + current BGGeo state) to confirm whether the SDK is emitting stationary geofence events.
|
||||||
|
- See [`setBackgroundGeolocationEventHandlers({ onGeofence })`](src/location/trackLocation.js:1).
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
|
import { Platform } from "react-native";
|
||||||
import BackgroundGeolocation from "react-native-background-geolocation";
|
import BackgroundGeolocation from "react-native-background-geolocation";
|
||||||
import env from "~/env";
|
import env from "~/env";
|
||||||
|
|
||||||
const LOCATION_ACCURACY_GATE_M = 100;
|
const LOCATION_ACCURACY_GATE_M = 100;
|
||||||
|
const IS_ANDROID = Platform.OS === "android";
|
||||||
|
|
||||||
// Native filter to reduce GPS drift and suppress stationary jitter.
|
// Native filter to reduce GPS drift and suppress stationary jitter.
|
||||||
// This is the primary mechanism to prevent unwanted persisted/uploaded points while the device
|
// This is the primary mechanism to prevent unwanted persisted/uploaded points while the device
|
||||||
|
|
@ -39,12 +41,12 @@ export const BASE_GEOLOCATION_CONFIG = {
|
||||||
|
|
||||||
// Logger config
|
// Logger config
|
||||||
logger: {
|
logger: {
|
||||||
// debug: true,
|
debug: true,
|
||||||
// Logging can become large and also adds overhead; keep verbose logs to dev/staging.
|
// Logging can become large and also adds overhead; keep verbose logs to dev/staging.
|
||||||
logLevel:
|
logLevel: BackgroundGeolocation.LogLevel.Verbose,
|
||||||
__DEV__ || env.IS_STAGING
|
// __DEV__ || env.IS_STAGING
|
||||||
? BackgroundGeolocation.LogLevel.Verbose
|
// ? BackgroundGeolocation.LogLevel.Verbose
|
||||||
: BackgroundGeolocation.LogLevel.Error,
|
// : BackgroundGeolocation.LogLevel.Error,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Geolocation config
|
// Geolocation config
|
||||||
|
|
@ -62,6 +64,12 @@ export const BASE_GEOLOCATION_CONFIG = {
|
||||||
// Default to the IDLE profile behaviour.
|
// Default to the IDLE profile behaviour.
|
||||||
distanceFilter: 200,
|
distanceFilter: 200,
|
||||||
|
|
||||||
|
// Ensure deterministic behavior when switching profiles.
|
||||||
|
// If we enable significant-changes mode in Android IDLE, we *must* explicitly
|
||||||
|
// restore it to `false` in ACTIVE (and other modes) to avoid the SDK keeping a
|
||||||
|
// previously-set `true` value.
|
||||||
|
useSignificantChangesOnly: false,
|
||||||
|
|
||||||
// Prevent dynamic distanceFilter shrink.
|
// Prevent dynamic distanceFilter shrink.
|
||||||
// Elasticity can lower the effective threshold (eg while stationary), resulting in
|
// Elasticity can lower the effective threshold (eg while stationary), resulting in
|
||||||
// unexpected frequent updates.
|
// unexpected frequent updates.
|
||||||
|
|
@ -73,7 +81,14 @@ export const BASE_GEOLOCATION_CONFIG = {
|
||||||
// True-stationary strategy: once stop-detection decides we're stationary, stop active
|
// True-stationary strategy: once stop-detection decides we're stationary, stop active
|
||||||
// tracking and rely on the stationary geofence to detect significant movement.
|
// tracking and rely on the stationary geofence to detect significant movement.
|
||||||
// This is intended to eliminate periodic stationary updates on Android.
|
// This is intended to eliminate periodic stationary updates on Android.
|
||||||
stopOnStationary: true,
|
//
|
||||||
|
// HOWEVER: On some Android devices, the stationary-geofence EXIT can be triggered by
|
||||||
|
// extremely poor "trigger" fixes (eg hAcc=500m), causing false motion transitions and
|
||||||
|
// periodic persisted uploads while the phone is actually stationary.
|
||||||
|
//
|
||||||
|
// Mitigation (Android IDLE): do NOT rely on stationary-geofence mode; instead rely on
|
||||||
|
// distanceFilter + native filtering.
|
||||||
|
stopOnStationary: IS_ANDROID ? false : true,
|
||||||
stationaryRadius: 200,
|
stationaryRadius: 200,
|
||||||
|
|
||||||
// Prevent identical/noise locations from being persisted.
|
// Prevent identical/noise locations from being persisted.
|
||||||
|
|
@ -178,7 +193,14 @@ export const TRACKING_PROFILES = {
|
||||||
// IMPORTANT: ACTIVE sets stopOnStationary:false.
|
// IMPORTANT: ACTIVE sets stopOnStationary:false.
|
||||||
// Ensure we restore it when transitioning back to IDLE, otherwise the SDK may
|
// Ensure we restore it when transitioning back to IDLE, otherwise the SDK may
|
||||||
// continue recording while stationary.
|
// continue recording while stationary.
|
||||||
stopOnStationary: true,
|
//
|
||||||
|
// Android mitigation: disable stopOnStationary to avoid stationary-geofence EXIT loops.
|
||||||
|
stopOnStationary: IS_ANDROID ? false : true,
|
||||||
|
|
||||||
|
// Android IDLE: rely on OS-level significant movement only.
|
||||||
|
// This avoids periodic wakeups/records due to poor fused-location fixes while the phone
|
||||||
|
// is stationary (screen-off / locked scenarios).
|
||||||
|
useSignificantChangesOnly: IS_ANDROID,
|
||||||
|
|
||||||
// QA helper: allow easier validation in dev/staging while keeping production at 200m.
|
// QA helper: allow easier validation in dev/staging while keeping production at 200m.
|
||||||
stationaryRadius: 200,
|
stationaryRadius: 200,
|
||||||
|
|
@ -198,6 +220,9 @@ export const TRACKING_PROFILES = {
|
||||||
// ACTIVE target: frequent updates while moving.
|
// ACTIVE target: frequent updates while moving.
|
||||||
distanceFilter: 25,
|
distanceFilter: 25,
|
||||||
|
|
||||||
|
// ACTIVE must not use significant-changes-only (we want continuous distance-based updates).
|
||||||
|
useSignificantChangesOnly: false,
|
||||||
|
|
||||||
// While ACTIVE, do not stop updates simply because the device appears stationary.
|
// While ACTIVE, do not stop updates simply because the device appears stationary.
|
||||||
// Motion-detection + distanceFilter should govern updates.
|
// Motion-detection + distanceFilter should govern updates.
|
||||||
stopOnStationary: false,
|
stopOnStationary: false,
|
||||||
|
|
|
||||||
|
|
@ -1130,6 +1130,36 @@ export default function trackLocation() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onGeofence: async (event) => {
|
||||||
|
// Diagnostic only: geofences are still used internally by the SDK (eg stationary geofence)
|
||||||
|
// even when we don't manage any app-defined geofences.
|
||||||
|
try {
|
||||||
|
const state = await BackgroundGeolocation.getState();
|
||||||
|
locationLogger.info("Geofence event", {
|
||||||
|
identifier: event?.identifier,
|
||||||
|
action: event?.action,
|
||||||
|
accuracy: event?.location?.coords?.accuracy,
|
||||||
|
latitude: event?.location?.coords?.latitude,
|
||||||
|
longitude: event?.location?.coords?.longitude,
|
||||||
|
enabled: state?.enabled,
|
||||||
|
isMoving: state?.isMoving,
|
||||||
|
trackingMode: state?.trackingMode,
|
||||||
|
profile: currentProfile,
|
||||||
|
appState,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
locationLogger.info("Geofence event", {
|
||||||
|
identifier: event?.identifier,
|
||||||
|
action: event?.action,
|
||||||
|
accuracy: event?.location?.coords?.accuracy,
|
||||||
|
latitude: event?.location?.coords?.latitude,
|
||||||
|
longitude: event?.location?.coords?.longitude,
|
||||||
|
profile: currentProfile,
|
||||||
|
appState,
|
||||||
|
error: e?.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
onLocationError: (error) => {
|
onLocationError: (error) => {
|
||||||
locationLogger.warn("Location error", {
|
locationLogger.warn("Location error", {
|
||||||
error: error?.message,
|
error: error?.message,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue