@josuelmm/cordova-background-geolocation 4.5.1 → 4.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/README.md +261 -41
- package/android/CDVBackgroundGeolocation/src/main/java/com/marianhello/bgloc/cordova/ConfigMapper.java +10 -0
- package/android/CDVBackgroundGeolocation/src/main/java/com/tenforwardconsulting/bgloc/cordova/BackgroundGeolocationPlugin.java +1 -1
- package/android/common/src/main/java/com/marianhello/bgloc/BootCompletedReceiver.java +14 -0
- package/android/common/src/main/java/com/marianhello/bgloc/Config.java +22 -0
- package/android/common/src/main/java/com/marianhello/bgloc/data/ConfigJsonMapper.java +6 -0
- package/android/common/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java +48 -1
- package/android/common/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java +105 -6
- package/android/common/src/main/java/com/marianhello/bgloc/provider/DistanceFilterLocationProvider.java +318 -247
- package/android/common/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java +69 -19
- package/ios/CDVBackgroundGeolocation/CDVBackgroundGeolocation.m +1 -1
- package/ios/common/BackgroundGeolocation/MAURActivityLocationProvider.m +208 -70
- package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m +21 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.h +5 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.m +22 -1
- package/ios/common/BackgroundGeolocation/MAURDistanceFilterLocationProvider.m +10 -1
- package/ios/common/BackgroundGeolocation/MAURLocationManager.m +19 -1
- package/ios/common/BackgroundGeolocation/MAURRawLocationProvider.m +10 -1
- package/package.json +1 -1
- package/plugin.xml +1 -9
- package/www/BackgroundGeolocation.d.ts +29 -0
- package/HISTORY.md +0 -938
- package/ios/common/BackgroundGeolocation/SOMotionDetector/CHANGELOG.md +0 -2
- package/ios/common/BackgroundGeolocation/SOMotionDetector/LICENSE +0 -21
- package/ios/common/BackgroundGeolocation/SOMotionDetector/README.md +0 -135
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOLocationManager.h +0 -80
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOLocationManager.m +0 -147
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOMotionActivity.h +0 -30
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOMotionActivity.m +0 -42
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOMotionDetector.h +0 -99
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOMotionDetector.m +0 -327
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOStepDetector.h +0 -44
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOStepDetector.m +0 -94
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,63 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.5.2](https://github.com/josuelmm/cordova-background-geolocation/tree/4.5.2) (2026-05-10)
|
|
4
|
+
|
|
5
|
+
### Added — Provider Hardening
|
|
6
|
+
- **`activityConfidenceThreshold` (0-100, default 50)**: las transiciones STILL/ACTIVE por debajo de este umbral se ignoran. Antes, ACTIVITY_PROVIDER reaccionaba a cualquier ruido de baja confianza → bursts espurios de start/stop GPS. iOS normaliza `CMMotionActivityConfidence` (Low/Medium/High → 20/40/80) para que el umbral signifique lo mismo en ambas plataformas.
|
|
7
|
+
- **`maxAcceptedAccuracy` (m, opcional)**: filtro global que descarta fixes con accuracy peor a este valor antes de persistir/POST/emitir al JS. Aplica a los 3 providers.
|
|
8
|
+
|
|
9
|
+
### Fixed (BLOQUEANTES — ACTIVITY_PROVIDER)
|
|
10
|
+
- **Android `ACTIVITY_PROVIDER` ignoraba `distanceFilter`**: el `LocationRequest.Builder` no llamaba a `setMinUpdateDistanceMeters`. Resultado: con `interval` bajo se bombardeaba al consumidor sin throttling por distancia.
|
|
11
|
+
- **Android sin verificación de Google Play Services**: si GPS estaba ausente/desactualizado, `FusedLocationProviderClient` + `ActivityRecognitionClient` fallaban silenciosamente. Ahora `onCreate` emite `SERVICE_ERROR` y queda inerte.
|
|
12
|
+
- **Android `ACTIVITY_RECOGNITION` denegado en Android 10+**: `requestActivityUpdates` retornaba sin emitir nada y STILL/ACTIVE nunca cambiaba → tracking continuo accidental. Ahora `attachRecorder` emite `PERMISSION_DENIED_ERROR` una vez y desiste.
|
|
13
|
+
- **Android `onConfigure` siempre stop+start**: incluso si la config nueva era idéntica, se dropeaba el callback y se reanudaba. Ahora compara `desiredAccuracy/interval/fastestInterval/distanceFilter/activitiesInterval/stopOnStillActivity` y solo reinicia si cambió algo relevante.
|
|
14
|
+
- **iOS `onLocationsChanged` durante NotMoving emitía DOBLE**: invocaba `onStationaryChanged` + un `onLocationChanged` por cada CLLocation. Resultado: rows "moving" fantasma durante ventana STILL. Ahora retorna tras stationary.
|
|
15
|
+
- **iOS confidence cruda (0/1/2 enum) comparada con threshold 0-100**: cualquier umbral > 2 ignoraba TODO. Normalizada a 0-100 en el provider.
|
|
16
|
+
- **iOS ACTIVITY/RAW/DISTANCE `onDestroy` no soltaba `delegate`**: `MAURLocationManager` y `SOMotionDetector` son singletons compartidos; un swap de provider dejaba el destruido recibiendo callbacks. `delegate = nil` en `onDestroy` + `dealloc`.
|
|
17
|
+
|
|
18
|
+
### Fixed — Provider Errors
|
|
19
|
+
- **Android DISTANCE_FILTER + RAW `onProviderDisabled`**: era no-op silencioso. Ahora emite `SERVICE_ERROR` cuando no queda ningún provider disponible (el JS puede repromptear al usuario).
|
|
20
|
+
- **iOS `MAURLocationManager` no implementaba el callback iOS 14+ `locationManagerDidChangeAuthorization:`**: solo el legacy deprecado. RAW + ACTIVITY (que usan la singleton) no veían cambios de "Always → While Using" sin reinicio del proceso. Añadido, con guard `@available(iOS 14, *)` en el legacy para evitar doble notificación.
|
|
21
|
+
- **Android RAW solo usaba GPS-o-Network (excluyente)** ignorando `desiredAccuracy`. Ahora `pickProviders` mapea: HIGH (<10 m) → GPS only, BALANCED → GPS+Network, LOW (≥1000 m) → Network only. Suscripción simultánea cuando ambos son útiles.
|
|
22
|
+
- **`AbstractLocationProvider` warning si `stopOnStillActivity: false` con ACTIVITY_PROVIDER**: el provider depende del state machine STILL/ACTIVE; con eso desactivado tracking continuo accidental. Warning en logcat.
|
|
23
|
+
|
|
24
|
+
### Internal
|
|
25
|
+
- `AbstractLocationProvider` ahora expone `handlePermissionDenied(msg)` y `handleServiceError(msg)` para que los providers emitan `PluginException` sin tocar `mDelegate` directamente.
|
|
26
|
+
|
|
27
|
+
### Fixed (post-revisión 4.5.2, cuarta iteración — hardening)
|
|
28
|
+
- **`BootCompletedReceiver` ahora valida el `intent.getAction()`**: el receiver está declarado `exported="true"` para recibir `BOOT_COMPLETED` del sistema; sin validar la action, una app maliciosa podría enviarle un intent explícito y disparar el auto-start del servicio. Ahora solo acepta `BOOT_COMPLETED`, `MY_PACKAGE_REPLACED`, y los quickboot OEM (HTC/Samsung); lo demás se ignora con un log warn.
|
|
29
|
+
|
|
30
|
+
### Fixed (post-revisión 4.5.2, tercera iteración)
|
|
31
|
+
- **iOS `ACTIVITY_PROVIDER` no arrancaba GPS si la app abría con el usuario quieto**: `onStart` subscribía a `CMMotionActivityManager` pero NO llamaba `startTracking`. Si CoreMotion disparaba STILL antes del primer fix, `handleActivityUpdate` (cuya regla es "ACTIVE → start") nunca arrancaba el location manager, así que no llegaba ningún fix y el `onStationaryChanged` inicial nunca se emitía. Restaurado el patrón del SOMotionDetector legacy: `startTracking` se invoca inmediatamente al `onStart`. Si CoreMotion confirma STILL después, el primer fix dispara `onStationaryChanged` + `stopTracking` automáticamente — el consumo de batería sigue acotado.
|
|
32
|
+
|
|
33
|
+
### Fixed (post-revisión 4.5.2, segunda iteración)
|
|
34
|
+
- **iOS `MAURActivityLocationProvider` UNKNOWN seguía mutando `lastMotionType`**: en la corrección anterior el `return` por UNKNOWN ocurría DESPUÉS de actualizar `lastMotionType`. Si la secuencia era STILL → UNKNOWN, el próximo fix ya no se trataba como stationary porque `lastMotionType` había pasado a `Unknown`. Ahora el `return` es lo primero — UNKNOWN no toca estado ni emite (silenciado además para no spamear consecutivos).
|
|
35
|
+
- **Android `singleUpdatePI` con `FLAG_IMMUTABLE` en API 31+**: `LocationManager.requestSingleUpdate(provider, PendingIntent)` rellena la `Location` en los extras del intent en delivery; con `FLAG_IMMUTABLE` el OS bloquea esa población y el receiver nunca veía el fix. Solo el `singleUpdatePI` se cambió a `FLAG_MUTABLE`; los demás siguen `IMMUTABLE` (alarms y monitor reciben PI sin payload).
|
|
36
|
+
- **`AbstractLocationProvider.hasMockLocationsEnabled` NPE**: `Settings.Secure.getString(...)` puede devolver `null` (clave ausente en el provider de Settings del dispositivo); el `.equals("1")` crasheaba. Invertido a `"1".equals(value)` — null-safe.
|
|
37
|
+
- **DISTANCE_FILTER legacy ahora suscribe GPS+Network simultáneo en modo moving normal**: antes elegía uno (GPS-o-Network excluyente). En Androids baratos/vehiculares donde GPS está "enabled" pero tarda en dar fix, esto perdía la oportunidad de un fix rápido por Network. Burst mode (acquisition) ya lo hacía; ahora moving también.
|
|
38
|
+
|
|
39
|
+
### Fixed (post-revisión 4.5.2)
|
|
40
|
+
- **iOS `MAURActivityLocationProvider` trataba UNKNOWN como NotMoving**: el branch `activity.stationary || activity.unknown` colapsaba ambos casos a `MAURMotionTypeNotMoving`, lo que paraba GPS al recibir un fix de baja confianza ("unknown" puede llegar con confianza alta). Ahora UNKNOWN se procesa como un tipo aparte: emite `onActivityChanged` pero **no toca el estado de tracking** y **no actualiza `lastMotionType`** (así un STILL/ACTIVE posterior produce la transición correcta). Contradecía el propio comentario "UNKNOWN keeps previous behavior (don't pause on uncertainty)".
|
|
41
|
+
- **README desactualizado**: la tabla de `locationProvider` decía que `DISTANCE_FILTER_PROVIDER` era "Pure Android LocationManager" y "Works without Google Play Services". Actualizada a "hybrid (v4.5.2+)": usa FLP cuando hay Play Services, fallback a LocationManager si no.
|
|
42
|
+
- **README caveats v4.5.2 añadidos**:
|
|
43
|
+
- `maxAcceptedAccuracy` está apagado por defecto (`null`); recomendaciones por escenario.
|
|
44
|
+
- `ACTIVITY_PROVIDER` sin `ACTIVITY_RECOGNITION` degrada a tracking continuo (caveat).
|
|
45
|
+
|
|
46
|
+
### Refactor — Provider internals (sin cambio de API JS, sin pérdida de cobertura)
|
|
47
|
+
- **iOS `ACTIVITY_PROVIDER` migrado a `CMMotionActivityManager` directo** (CoreMotion). Se eliminó la dependencia `SOMotionDetector` (sources + plugin.xml entries). Threading propio (NSOperationQueue) y manejo de permiso "Motion & Fitness" denegado (iOS 11+: `CMMotionActivityManager.authorizationStatus`) con emisión de error.
|
|
48
|
+
- **Android `DISTANCE_FILTER_PROVIDER` ahora es híbrido**: detecta Google Play Services en `onCreate` y elige backend en runtime.
|
|
49
|
+
- **Play Services disponible** → `FusedLocationProviderClient` + `LocationCallback` (mezcla GPS+Network, mejor batería, `setMinUpdateDistanceMeters`/Priority).
|
|
50
|
+
- **Play Services ausente** (Huawei/HMS, AOSP, ChinaROMs) → fallback a `android.location.LocationManager` + `LocationListener` (preservando el comportamiento previo a v4.5.2 — el plugin funciona en cualquier Android).
|
|
51
|
+
- **Eliminado el path de `addProximityAlert`** (decisión de producto: sin geozonas) en ambas rutas; la salida del estado stationary se detecta exclusivamente por polling (FLP `setMaxUpdates(1)` o `LocationManager.requestSingleUpdate`).
|
|
52
|
+
- `DISTANCE_FILTER_PROVIDER` emite `SERVICE_ERROR` cuando ni GPS ni Network están habilitados al `setPace`.
|
|
53
|
+
|
|
54
|
+
### Matriz Play Services (Android)
|
|
55
|
+
| Provider | Play Services | Comportamiento |
|
|
56
|
+
|----------|---------------|----------------|
|
|
57
|
+
| `RAW_PROVIDER` | No requiere | OS LocationManager directo (GPS+Network simultáneo según `desiredAccuracy`). |
|
|
58
|
+
| `DISTANCE_FILTER_PROVIDER` | Opcional | FLP si está disponible, LocationManager si no. Auto. |
|
|
59
|
+
| `ACTIVITY_PROVIDER` | Requerido | Sin fallback (depende de `ActivityRecognitionClient`). En dispositivos sin Play Services usar `DISTANCE_FILTER` o `RAW`. |
|
|
60
|
+
|
|
3
61
|
## [4.5.1](https://github.com/josuelmm/cordova-background-geolocation/tree/4.5.1) (2026-05-09)
|
|
4
62
|
|
|
5
63
|
### Fixed (BLOQUEANTES)
|
package/README.md
CHANGED
|
@@ -179,6 +179,93 @@ BackgroundGeolocation.FOREGROUND_MODE
|
|
|
179
179
|
|
|
180
180
|
Set your preferred provider, accuracy, intervals, and optional server URLs. All options are optional; you can reconfigure later with a subset (options are merged).
|
|
181
181
|
|
|
182
|
+
#### 1.1 `locationProvider` — which engine produces the fixes
|
|
183
|
+
|
|
184
|
+
This is the **most important choice**. It changes how often, how accurately, and how cheaply (battery-wise) the plugin gets locations. Three values, pick **one**:
|
|
185
|
+
|
|
186
|
+
| Value | Constant | Internals | When to use |
|
|
187
|
+
|---|---|---|---|
|
|
188
|
+
| `0` | `BackgroundGeolocation.DISTANCE_FILTER_PROVIDER` (default) | **Hybrid (v4.5.2+)**: `FusedLocationProviderClient` cuando Google Play Services está disponible, fallback automático a `LocationManager` cuando no (Huawei/HMS, AOSP, ChinaROMs). Implementa una **state machine de detección stationary**: mientras se mueve muestrea normal; al detenerse usa **polling lazy** (3 min) y **polling aggressive** (1 min cerca del borde) vía `AlarmManager`. **No usa geofences** (eliminados por decisión de producto); la salida del estado stationary se detecta solo por polling. | **Default para la mayoría de apps.** Tracking personal, couriers de delivery, cualquiera que necesite ubicación sin drenar batería al estar parado. **Funciona con o sin Google Play Services.** |
|
|
189
|
+
| `1` | `BackgroundGeolocation.ACTIVITY_PROVIDER` | Google Play Services `FusedLocationProviderClient` + **Activity Recognition** (walking / driving / still). When `STILL` is detected, the provider stops requesting fixes; when activity resumes, it restarts. Uses `LocationRequest.Builder` + `Priority.PRIORITY_HIGH_ACCURACY` (or balanced, per `desiredAccuracy`). | Apps where the **activity matters** (fitness, fleet, ride-hailing). Best battery profile when the user spends a lot of time still. **Requires Google Play Services** on the device and `ACTIVITY_RECOGNITION` runtime permission on Android 10+. |
|
|
190
|
+
| `2` | `BackgroundGeolocation.RAW_PROVIDER` | Direct `LocationManager` requests with **no stationary detection, no batching, no filtering**. Every fix the OS produces is forwarded. | Vehicle tracking with a **constant interval**, dashcams, anything where you want raw GPS without the plugin trying to be smart. **Highest battery cost.** |
|
|
191
|
+
|
|
192
|
+
```js
|
|
193
|
+
// Recommended for personal apps (Life360-style)
|
|
194
|
+
BackgroundGeolocation.configure({
|
|
195
|
+
locationProvider: BackgroundGeolocation.DISTANCE_FILTER_PROVIDER,
|
|
196
|
+
desiredAccuracy: BackgroundGeolocation.MEDIUM_ACCURACY,
|
|
197
|
+
distanceFilter: 50,
|
|
198
|
+
stationaryRadius: 50
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Recommended for fleet/vehicle tracking
|
|
202
|
+
BackgroundGeolocation.configure({
|
|
203
|
+
locationProvider: BackgroundGeolocation.ACTIVITY_PROVIDER,
|
|
204
|
+
desiredAccuracy: BackgroundGeolocation.HIGH_ACCURACY,
|
|
205
|
+
interval: 15000,
|
|
206
|
+
fastestInterval: 10000,
|
|
207
|
+
activitiesInterval: 30000
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
// Raw — every fix, no smart filtering
|
|
211
|
+
BackgroundGeolocation.configure({
|
|
212
|
+
locationProvider: BackgroundGeolocation.RAW_PROVIDER,
|
|
213
|
+
desiredAccuracy: BackgroundGeolocation.HIGH_ACCURACY,
|
|
214
|
+
interval: 5000
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**iOS note:** all three constants exist for API parity, but iOS internally always uses `CLLocationManager`. The plugin maps `DISTANCE_FILTER_PROVIDER` and `RAW_PROVIDER` to standard location updates, and `ACTIVITY_PROVIDER` enables `CMMotionActivityManager` for activity detection on top.
|
|
219
|
+
|
|
220
|
+
#### 1.2 `startOnBoot` — survive a reboot (Android only)
|
|
221
|
+
|
|
222
|
+
When `true`, the plugin re-arms tracking automatically after the device reboots or after an app update — without the user opening the app.
|
|
223
|
+
|
|
224
|
+
**How it works internally:**
|
|
225
|
+
|
|
226
|
+
1. The plugin registers a `BootCompletedReceiver` that listens for `BOOT_COMPLETED`, `QUICKBOOT_POWERON` (HTC/Xiaomi), `com.htc.intent.action.QUICKBOOT_POWERON`, and `MY_PACKAGE_REPLACED` (Play Store updates).
|
|
227
|
+
2. On boot, the receiver loads the **persisted `Config`** from SQLite (since v4.4.1 / v4.5.0 the full config is stored as `config_json`, so `httpMethod`, `queryParams`, `drivingEvents`, etc. survive).
|
|
228
|
+
3. It checks `ACCESS_FINE_LOCATION` / `ACCESS_COARSE_LOCATION`, and on Android 10+ also `ACCESS_BACKGROUND_LOCATION`. If any is missing, it logs and gives up — it will **NOT** request permissions from a receiver (the OS forbids it).
|
|
229
|
+
4. If permissions are OK, it calls `context.startForegroundService(...)`. The plugin's notification appears and tracking resumes with the same config the app had configured before reboot.
|
|
230
|
+
|
|
231
|
+
**Required runtime permissions** (the app must request them at least once **while it is in foreground**, before relying on `startOnBoot`):
|
|
232
|
+
|
|
233
|
+
```ts
|
|
234
|
+
// Order matters — the OS dialog flow is strict on Android 11+.
|
|
235
|
+
await BackgroundGeolocation.requestNotificationPermission(); // Android 13+
|
|
236
|
+
// ACCESS_FINE_LOCATION via Cordova permission API or @capacitor/geolocation
|
|
237
|
+
await BackgroundGeolocation.requestBackgroundLocationPermission(); // Android 10+, user MUST pick "Allow all the time"
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Without **"Allow all the time"** the receiver runs but the foreground service is killed shortly after, because the OS treats the boot-launched service as "background-started" and a background start without background permission is not allowed.
|
|
241
|
+
|
|
242
|
+
**iOS:** Apple does **not** allow third-party apps to auto-start at boot. `startOnBoot: true` is silently ignored on iOS. The closest equivalent is **`significantLocationChanges`** (already implemented), which wakes the app when the device moves to a new cell tower / region — but only if the app was running at least once after the reboot. Document this expectation to your iOS users.
|
|
243
|
+
|
|
244
|
+
**Common pitfalls:**
|
|
245
|
+
|
|
246
|
+
- **OEM kills (Xiaomi MIUI, Huawei EMUI, Oppo, Vivo, OnePlus, Asus)** disable auto-start by default for non-system apps. The user must enable the app in *"Autostart"* / *"Background activity"* settings of the OEM. Use `BackgroundGeolocation.openAutoStartSettings()` to take the user directly there, and `getManufacturerHelp()` for instructions.
|
|
247
|
+
- **Android 12+ `ForegroundServiceStartNotAllowedException`** — if the device is in *Doze* deep-idle when it reboots, the system may block the foreground service. The plugin catches the exception and logs it; the next user-triggered `start()` (when they open the app) will succeed.
|
|
248
|
+
- **Doze whitelist** — `isIgnoringBatteryOptimizations()` + `requestIgnoreBatteryOptimizations()` reduce the chance of the OS putting the app on the "restricted" list after a reboot.
|
|
249
|
+
|
|
250
|
+
```js
|
|
251
|
+
// Full recommended setup for "track this user across reboots"
|
|
252
|
+
BackgroundGeolocation.configure({
|
|
253
|
+
locationProvider: BackgroundGeolocation.DISTANCE_FILTER_PROVIDER,
|
|
254
|
+
desiredAccuracy: BackgroundGeolocation.MEDIUM_ACCURACY,
|
|
255
|
+
distanceFilter: 50,
|
|
256
|
+
startForeground: true, // mandatory for Android 8+ background tracking
|
|
257
|
+
notificationsEnabled: true,
|
|
258
|
+
notificationTitle: 'Live tracking',
|
|
259
|
+
notificationText: 'Your location is being shared',
|
|
260
|
+
startOnBoot: true, // survive reboots
|
|
261
|
+
stopOnTerminate: false, // keep tracking when user swipes the app away
|
|
262
|
+
url: 'https://my.api/locations',
|
|
263
|
+
syncUrl: 'https://my.api/sync'
|
|
264
|
+
});
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
#### 1.3 Other main options
|
|
268
|
+
|
|
182
269
|
**Main options:**
|
|
183
270
|
|
|
184
271
|
| Option | Description |
|
|
@@ -197,14 +284,76 @@ Set your preferred provider, accuracy, intervals, and optional server URLs. All
|
|
|
197
284
|
| `httpMethod` | **Since 3.3.0.** HTTP method for `url`. `POST` (default) `| GET | PUT | PATCH`. Use `GET` together with URL templating to deliver positions through the query string. |
|
|
198
285
|
| `syncHttpMethod` | **Since 3.3.0.** HTTP method for `syncUrl`. Same values as `httpMethod`. |
|
|
199
286
|
| `httpMode` / `syncMode` | **Since 3.3.0.** `batch` (default) or `single` (one HTTP request per location). `single` is required when the corresponding method is `GET`. |
|
|
200
|
-
| `queryParams` | **Since 3.3.0.** Static placeholder values for URL/body templating (e.g. `{ device_id: 'USER_123' }`). See [HTTP transport](docs/api.md#http-transport-since-330). |
|
|
287
|
+
| `queryParams` | **Since 3.3.0.** Static placeholder values for URL/body templating (e.g. `{ device_id: 'USER_123' }`). See [HTTP transport](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md#http-transport-since-330). |
|
|
201
288
|
| `postTemplate` / `bodyTemplate` | Object or array of properties to send. Supports `@latitude`, `@longitude`, ... and the new `{latitude}`, `{lon}`, `{timestamp_iso}`, ... placeholders on string values. `bodyTemplate` is the alias added in 3.3.0. |
|
|
202
289
|
| `maxLocations` | Max locations kept in DB (default 10000). Should be > `syncThreshold`. |
|
|
203
290
|
|
|
291
|
+
**Diagnostics / sync (3.5+):**
|
|
292
|
+
|
|
293
|
+
| Option | Description |
|
|
294
|
+
|--------|-------------|
|
|
295
|
+
| `heartbeatInterval` | ms between `heartbeat` events. `0` (default) disables. |
|
|
296
|
+
| `mockLocationPolicy` | `'allow'` (default) / `'flag'` / `'drop'` — what to do with mocked locations. |
|
|
297
|
+
|
|
298
|
+
**Driver insights (4.0+):**
|
|
299
|
+
|
|
300
|
+
| Option | Description |
|
|
301
|
+
|--------|-------------|
|
|
302
|
+
| `drivingEvents.enabled` | Master switch. Default `false`. |
|
|
303
|
+
| `drivingEvents.speedLimit` | km/h for `speeding` event. `0` disables. |
|
|
304
|
+
| `drivingEvents.minMovingSpeed` | m/s threshold for "moving" (default 1.0). |
|
|
305
|
+
| `drivingEvents.stoppedDuration` | ms of below-threshold needed for "stopped" (default 60 000). |
|
|
306
|
+
| `drivingEvents.minTripSpeed` | m/s threshold for `tripStart` (default 3.0). |
|
|
307
|
+
| `drivingEvents.minTripDuration` | ms sustained to fire `tripStart` (default 30 000). |
|
|
308
|
+
| `drivingEvents.hardBrakeMps2` | m/s² threshold for `hardBrake` (default 3.5; `0` disables). |
|
|
309
|
+
| `drivingEvents.rapidAccelMps2` | m/s² threshold for `rapidAcceleration` (default 3.5). |
|
|
310
|
+
| `drivingEvents.sharpTurnDegPerSec` | deg/s for `sharpTurn` at speed ≥ 5 m/s (default 30). |
|
|
311
|
+
| `drivingEvents.crashImpactKmh` | km/h drop within window for GPS `possibleCrash` (default 25). |
|
|
312
|
+
| `drivingEvents.crashWindowMs` | window for GPS crash detection (default 2 000). |
|
|
313
|
+
| `drivingEvents.sensorFusion` | **4.2+.** Enable accelerometer + gyroscope. Off by default. |
|
|
314
|
+
| `drivingEvents.crashImpactG` | g threshold for sensor `possibleCrash` (default 3.0). |
|
|
315
|
+
| `drivingEvents.sensorCrashCooldownMs` | ms cooldown between sensor crash detections (default 10 000). |
|
|
316
|
+
| `drivingEvents.phoneUsageWindowMs` | ms of sustained jitter to fire `phoneUsageWhileDriving` (default 4 000). |
|
|
317
|
+
| `drivingEvents.phoneUsageCooldownMs` | ms cooldown between phone-usage events (default 60 000). |
|
|
318
|
+
|
|
319
|
+
**Battery payload (4.4+):**
|
|
320
|
+
|
|
321
|
+
| Option | Description |
|
|
322
|
+
|--------|-------------|
|
|
323
|
+
| `includeBattery` | Stamp `battery` (0-100) and `isCharging` on every fix. Default `true`. |
|
|
324
|
+
|
|
325
|
+
**Battery saving (4.5.1):**
|
|
326
|
+
|
|
327
|
+
| Option | Description |
|
|
328
|
+
|--------|-------------|
|
|
329
|
+
| `wakeLockMode` | `'none' \| 'posting' \| 'always'`. Default `'posting'`. |
|
|
330
|
+
| `stationaryTimeout` | ms of no movement → declare stationary (Android `DISTANCE_FILTER_PROVIDER`). Default 300 000. |
|
|
331
|
+
| `stationaryPollInterval` | Lazy poll interval while stationary (ms). Default 180 000. |
|
|
332
|
+
| `stationaryPollFast` | Aggressive poll near the stationary boundary (ms). Default 60 000. |
|
|
333
|
+
|
|
334
|
+
**Provider hardening (4.5.2):**
|
|
335
|
+
|
|
336
|
+
| Option | Description |
|
|
337
|
+
|--------|-------------|
|
|
338
|
+
| `activityConfidenceThreshold` | 0-100. Ignore STILL/ACTIVE transitions below this confidence (prevents jittery GPS start/stop). iOS normalizes Low/Med/High → 20/40/80. Default 50. Applies to `ACTIVITY_PROVIDER`. |
|
|
339
|
+
| `maxAcceptedAccuracy` | Maximum accepted horizontal accuracy in meters. Fixes worse than this are dropped before persist/POST/JS emission. **Off by default (`null`)** to avoid regressing existing apps. Recommended values: `100` for vehicular tracking, `500` for tolerant scenarios. All providers. |
|
|
340
|
+
|
|
341
|
+
> **Caveats v4.5.2:**
|
|
342
|
+
> - `maxAcceptedAccuracy` está **apagado por defecto**. Si quieres descartar fixes ruidosos (típico en GPS vehicular o indoor), seteá explícito un valor (ej. `100`).
|
|
343
|
+
> - **ACTIVITY_PROVIDER sin `ACTIVITY_RECOGNITION`** (Android 10+): el provider emite `PERMISSION_DENIED_ERROR` pero **degrada a tracking continuo** (no puede detectar STILL/ACTIVE). Si querés ahorro real, pedí el permiso antes de iniciar o cambiá a `DISTANCE_FILTER_PROVIDER`.
|
|
344
|
+
> - **`enableWatchdog`** está **apagado por defecto**. Reinicia el provider si deja de llegar `location` por ~60s (solo si `tripActive`). Útil en apps vehiculares/críticas; aumenta consumo. Recomendado `false` salvo necesidad real.
|
|
345
|
+
> - **`postTemplate` reemplaza el payload completo** — no hay merge con el default. Si lo defines, debes incluir manualmente `@events`, `@battery`, `@isCharging` si los necesitas. Detalle en [docs/api.md](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md#custom-post-template).
|
|
346
|
+
> - **`events` / `battery` / `isCharging` sobreviven la cola de sync** desde v4.5.0 (Android schema v22, iOS schema v7). Si un POST falla, esos campos persisten para `forceSync`/sync automático. Auto-migración desde versiones previas.
|
|
347
|
+
> - **`pendingDrivingEvents` son in-memory**: el detector almacena eventos (hardBrake, speeding, etc.) hasta anexarlos al próximo `location` (cap 20, TTL 60s). Si el proceso muere antes del próximo fix, esos eventos pueden perderse. La cola principal de ubicaciones no se afecta.
|
|
348
|
+
> - **`startOnBoot`** requiere: `stopOnTerminate: false` (o config persistida), `ACCESS_BACKGROUND_LOCATION` concedido (Android 10+), y que el fabricante no bloquee autostart/battery optimization. Xiaomi/Huawei/Oppo/Vivo suelen requerir desactivar manualmente la optimización de batería — usar `openBatterySettings()` / `openAutoStartSettings()` para guiar al usuario.
|
|
349
|
+
> - **Permisos por versión Android**: Android 10+ requiere `ACCESS_BACKGROUND_LOCATION` para tracking real en background. Android 10+ requiere `ACTIVITY_RECOGNITION` para `ACTIVITY_PROVIDER`. Android 13+ requiere `POST_NOTIFICATIONS` para la notificación foreground. Android 14+ requiere `FOREGROUND_SERVICE_LOCATION`. El plugin no fuerza permisos automáticamente; usar los helpers `requestBackgroundLocationPermission()`, `requestActivityRecognitionPermission()` y `requestNotificationPermission()`.
|
|
350
|
+
|
|
204
351
|
**Android-only:** `notificationSyncTitle`, `notificationSyncText`, `notificationSyncCompletedText`, `notificationSyncFailedText` — texts shown in the notification while syncing (defaults in English; set for localization). `startForeground`, `notificationsEnabled`, `startOnBoot`, `stopOnTerminate`, `enableWatchdog`.
|
|
205
352
|
|
|
206
353
|
**iOS-only:** `activityType`, `pauseLocationUpdates`, `saveBatteryOnBackground`, `showsBackgroundLocationIndicator` (since 3.4.0; iOS 11+, shows the blue background indicator).
|
|
207
354
|
|
|
355
|
+
**Full reference** (every option, with types, defaults and platform/provider hints): [`docs/api.md`](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md).
|
|
356
|
+
|
|
208
357
|
Example (default POST + JSON):
|
|
209
358
|
|
|
210
359
|
```js
|
|
@@ -250,7 +399,7 @@ BackgroundGeolocation.configure({
|
|
|
250
399
|
});
|
|
251
400
|
```
|
|
252
401
|
|
|
253
|
-
> **Android runtime permissions.** With `startOnBoot: true`, the app must request `ACCESS_FINE_LOCATION` first, then `POST_NOTIFICATIONS` (Android 13+), and finally `ACCESS_BACKGROUND_LOCATION` (Android 10+, the user must pick **Allow all the time**). Without the background permission the plugin will skip the start on boot. iOS does **not** allow auto-start on device boot (Apple restriction). See [Auto-start on Android boot](docs/api.md#auto-start-on-android-boot-since-330) for the full flow.
|
|
402
|
+
> **Android runtime permissions.** With `startOnBoot: true`, the app must request `ACCESS_FINE_LOCATION` first, then `POST_NOTIFICATIONS` (Android 13+), and finally `ACCESS_BACKGROUND_LOCATION` (Android 10+, the user must pick **Allow all the time**). Without the background permission the plugin will skip the start on boot. iOS does **not** allow auto-start on device boot (Apple restriction). See [Auto-start on Android boot](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md#auto-start-on-android-boot-since-330) for the full flow.
|
|
254
403
|
|
|
255
404
|
### 2. Start tracking
|
|
256
405
|
|
|
@@ -298,7 +447,7 @@ When you use `syncUrl`, locations that fail to post to `url` (or that are only q
|
|
|
298
447
|
| **`application/json`** (default) | **One POST** with a JSON **array** of all locations in the batch. |
|
|
299
448
|
| **`application/x-www-form-urlencoded`** | **One POST per location** (same flat `key=value&...` as real-time to `url`). Same endpoint can handle both. |
|
|
300
449
|
|
|
301
|
-
So: with **JSON** you get one request per batch (e.g. 100 locations in one body). With **form-urlencoded** you get one request per location (one record per POST). For headers, retries, `postTemplate` and full behaviour see [HTTP posting](docs/http_posting.md) and [API](docs/api.md).
|
|
450
|
+
So: with **JSON** you get one request per batch (e.g. 100 locations in one body). With **form-urlencoded** you get one request per location (one record per POST). For headers, retries, `postTemplate` and full behaviour see [HTTP posting](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/http_posting.md) and [API](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md).
|
|
302
451
|
|
|
303
452
|
You can:
|
|
304
453
|
|
|
@@ -325,27 +474,41 @@ BackgroundGeolocation.clearSync().then(function () {
|
|
|
325
474
|
});
|
|
326
475
|
```
|
|
327
476
|
|
|
328
|
-
More on sync (headers, retries, postTemplate): [HTTP posting](docs/http_posting.md). Full options and methods: [API](docs/api.md).
|
|
477
|
+
More on sync (headers, retries, postTemplate): [HTTP posting](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/http_posting.md). Full options and methods: [API](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md).
|
|
329
478
|
|
|
330
479
|
### 6. Other methods (summary)
|
|
331
480
|
|
|
332
|
-
| Method | Description |
|
|
333
|
-
|
|
334
|
-
| `getConfig(success, fail)` | Get current configuration (merged options). |
|
|
335
|
-
| `getLocations(success, fail)` | Get all stored locations. |
|
|
336
|
-
| `getValidLocations(success, fail)` | Get locations not yet posted (valid only). |
|
|
337
|
-
| `deleteLocation(id, success, fail)` | Delete one location by id. |
|
|
338
|
-
| `deleteAllLocations(success, fail)` | Delete all stored locations. |
|
|
339
|
-
| `getCurrentLocation(success, fail, options)` | One-shot location (e.g. timeout, maximumAge). |
|
|
340
|
-
| `getPluginVersion(success, fail)` | Plugin version string (e.g. "
|
|
341
|
-
| `checkStatus(success, fail)` | Service status (isRunning, authorization, etc.). |
|
|
342
|
-
| `showAppSettings()` / `openSettings()` | Open app settings. |
|
|
343
|
-
| `showLocationSettings()` | Open system location settings. |
|
|
344
|
-
| `getLogEntries(limit, fromId, minLevel, success, fail)` | Debug log entries. |
|
|
345
|
-
| `
|
|
346
|
-
| `
|
|
347
|
-
| `
|
|
348
|
-
| `
|
|
481
|
+
| Method | Since | Description |
|
|
482
|
+
|--------|-------|-------------|
|
|
483
|
+
| `getConfig(success, fail)` | 1.0 | Get current configuration (merged options). |
|
|
484
|
+
| `getLocations(success, fail)` | 1.0 | Get all stored locations. |
|
|
485
|
+
| `getValidLocations(success, fail)` | 1.0 | Get locations not yet posted (valid only). |
|
|
486
|
+
| `deleteLocation(id, success, fail)` | 1.0 | Delete one location by id. |
|
|
487
|
+
| `deleteAllLocations(success, fail)` | 1.0 | Delete all stored locations. |
|
|
488
|
+
| `getCurrentLocation(success, fail, options)` | 1.0 | One-shot location (e.g. timeout, maximumAge). |
|
|
489
|
+
| `getPluginVersion(success, fail)` | 1.0 | Plugin version string (e.g. `"4.5.1"`). |
|
|
490
|
+
| `checkStatus(success, fail)` | 1.0 | Service status (isRunning, authorization, etc.). |
|
|
491
|
+
| `showAppSettings()` / `openSettings()` | 1.0 | Open app settings. |
|
|
492
|
+
| `showLocationSettings()` | 1.0 | Open system location settings. |
|
|
493
|
+
| `getLogEntries(limit, fromId, minLevel, success, fail)` | 1.0 | Debug log entries. |
|
|
494
|
+
| `getPendingSyncCount(success, fail)` | 3.1 | Number of locations pending sync. |
|
|
495
|
+
| `forceSync(success, fail)` | 3.1 | Send pending locations immediately (ignores `syncThreshold`). |
|
|
496
|
+
| `clearSync(success, fail)` | 3.1 | Discard pending sync queue without sending. |
|
|
497
|
+
| `startSession(success, fail)` | 3.2 | Start session: clear session table and store new locations until `clearSession()`. |
|
|
498
|
+
| `getSessionLocations(success, fail)` | 3.2 | All locations in current session. |
|
|
499
|
+
| `clearSession(success, fail)` | 3.2 | Clear session table (call when route finished). |
|
|
500
|
+
| `getSessionLocationsCount(success, fail)` | 3.2 | Number of locations in current session. |
|
|
501
|
+
| `getDiagnostics(success, fail)` | 3.5 | Extended diagnostics: permissions, battery optimisation, OEM, last fix age, pending sync, iOS precise location, etc. |
|
|
502
|
+
| `isIgnoringBatteryOptimizations(success, fail)` | 3.6 | Android only. `true` if app is on the Doze whitelist. iOS always `true`. |
|
|
503
|
+
| `requestIgnoreBatteryOptimizations(success, fail)` | 3.6 | Android only. Opens the system dialog to add the app to the whitelist. |
|
|
504
|
+
| `openBatterySettings(success, fail)` | 3.6 | Android only. Opens the battery-related settings screen for this app. |
|
|
505
|
+
| `openAutoStartSettings(success, fail)` | 3.6 | Android only. Opens the OEM-specific auto-start screen (Xiaomi/Huawei/Oppo/Vivo/OnePlus/Asus). |
|
|
506
|
+
| `getManufacturerHelp(success, fail)` | 3.6 | Returns `{ manufacturer, steps[] }` with OEM-specific guidance text. |
|
|
507
|
+
| `triggerSOS(payload?, success, fail)` | 4.0 | Emit a single `sos` event with the latest location plus your payload. Host app handles actual SOS workflow. |
|
|
508
|
+
| `requestBackgroundLocationPermission(success, fail)` | 4.5 | Android 10+. Request `ACCESS_BACKGROUND_LOCATION`. iOS / older Android resolve `{ granted: true, notRequired: true }`. |
|
|
509
|
+
| `requestActivityRecognitionPermission(success, fail)` | 4.5 | Android 10+. Request `ACTIVITY_RECOGNITION`. |
|
|
510
|
+
| `requestNotificationPermission(success, fail)` | 4.5 | Android 13+. Request `POST_NOTIFICATIONS`. |
|
|
511
|
+
| `headlessTask(task)` | 1.0 | **Android only.** Run JS when app is terminated and `stopOnTerminate: false`. iOS no-op. |
|
|
349
512
|
|
|
350
513
|
All methods return a **Promise** if you omit the `success` / `fail` callbacks.
|
|
351
514
|
|
|
@@ -353,6 +516,8 @@ All methods return a **Promise** if you omit the `success` / `fail` callbacks.
|
|
|
353
516
|
|
|
354
517
|
Subscribe with `BackgroundGeolocation.on(eventName, callback)`. Unsubscribe with the returned object’s `remove()` or by calling `removeAllListeners(eventName)`.
|
|
355
518
|
|
|
519
|
+
#### Core (1.0+)
|
|
520
|
+
|
|
356
521
|
| Event | Payload | When |
|
|
357
522
|
|-------|---------|------|
|
|
358
523
|
| `location` | Location object | New location (foreground/background). |
|
|
@@ -366,7 +531,57 @@ Subscribe with `BackgroundGeolocation.on(eventName, callback)`. Unsubscribe with
|
|
|
366
531
|
| `http_authorization` | — | Server returned 401; refresh token and reconfigure headers. |
|
|
367
532
|
| `abort_requested` | — | Server returned 285 (updates not required). |
|
|
368
533
|
|
|
369
|
-
|
|
534
|
+
#### Diagnostics + Sync (3.5+)
|
|
535
|
+
|
|
536
|
+
| Event | Payload | When |
|
|
537
|
+
|-------|---------|------|
|
|
538
|
+
| `heartbeat` | `Location` or `void` | Periodic heartbeat at `heartbeatInterval` ms. Disabled when `heartbeatInterval = 0`. |
|
|
539
|
+
| `syncStart` | — | Background sync POST started. |
|
|
540
|
+
| `syncProgress` | `number` (0-100) | Sync upload progress. |
|
|
541
|
+
| `syncSuccess` | `{ sent: number }` | Sync completed, N locations uploaded. |
|
|
542
|
+
| `syncError` | `{ httpStatus, message }` | Sync failed (network or server). |
|
|
543
|
+
|
|
544
|
+
#### Driver insights (4.0+)
|
|
545
|
+
|
|
546
|
+
| Event | Payload | When |
|
|
547
|
+
|-------|---------|------|
|
|
548
|
+
| `tripStart` | `Location` | Sustained speed ≥ `minTripSpeed` for `minTripDuration` ms. |
|
|
549
|
+
| `tripEnd` | `{ location, distance, durationMs }` | Stationary detected during active trip. |
|
|
550
|
+
| `moving` | `Location` | Speed crossed `minMovingSpeed` upward. |
|
|
551
|
+
| `stopped` | `Location` | `stoppedDuration` ms below `minMovingSpeed`. |
|
|
552
|
+
| `speeding` | `{ location, speedKmh, limitKmh }` | Above `drivingEvents.speedLimit` (rearms on drop). |
|
|
553
|
+
| `providerChange` | `{ provider }` | Location provider changed (gps/network/fused). |
|
|
554
|
+
| `sos` | `{ location, ...payload }` | `BackgroundGeolocation.triggerSOS(payload)` invoked. |
|
|
555
|
+
|
|
556
|
+
#### Driving events — GPS-derived (4.1+) / sensor fusion (4.2+)
|
|
557
|
+
|
|
558
|
+
| Event | Payload | When |
|
|
559
|
+
|-------|---------|------|
|
|
560
|
+
| `hardBrake` | `{ location, value }` | Δspeed/Δt ≤ −`hardBrakeMps2` during active trip. `value` is m/s² (negative). |
|
|
561
|
+
| `rapidAcceleration` | `{ location, value }` | Δspeed/Δt ≥ `rapidAccelMps2`. `value` is m/s² (positive). |
|
|
562
|
+
| `sharpTurn` | `{ location, value }` | Bearing change rate ≥ `sharpTurnDegPerSec` and speed ≥ 5 m/s. `value` is deg/s. |
|
|
563
|
+
| `possibleCrash` | `{ location, value, source }` | GPS heuristic (`source: 'gps'`, `value`: km/h drop) **or** sensor impact (`source: 'sensor'`, `value`: g). Always confirm with user before notifying contacts. |
|
|
564
|
+
| `phoneUsageWhileDriving` | `Location` | Sustained device interaction during active trip with screen on. Requires `drivingEvents.sensorFusion: true`. |
|
|
565
|
+
|
|
566
|
+
Full event payloads and options: [Events](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/events.md). Full API (all options, all methods): [API](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md).
|
|
567
|
+
|
|
568
|
+
### New in 4.5.1
|
|
569
|
+
|
|
570
|
+
Stability + battery optimization release. No new features — only fixes that make the plugin safe for long-term production.
|
|
571
|
+
|
|
572
|
+
- **`wakeLockMode: 'none' | 'posting' | 'always'`** (default `'posting'`). Replaces the previous always-on `PARTIAL_WAKE_LOCK`. `'posting'` acquires a bounded 30 s lock around each fix (SQLite + HTTP POST); `'none'` never acquires; `'always'` is the legacy behaviour for fleet/emergency apps.
|
|
573
|
+
- **Watchdog moving-only** — `enableWatchdog: true` no longer restarts the provider when the device is intentionally stationary. Saves real battery during parking/idle.
|
|
574
|
+
- **Stationary detection configurable** — `stationaryTimeout`, `stationaryPollInterval`, `stationaryPollFast` (Android `DISTANCE_FILTER_PROVIDER`). Defaults: 300 000 / 180 000 / 60 000 ms.
|
|
575
|
+
- **Critical persistence fixes**: `maxLocations` recycle no longer mixes old `events_json`/`battery_level`/`is_charging` into new rows; iOS sync no longer marks rows `Deleted` before the upload finishes (was losing the whole queue on network drop). iOS rescues `SyncPending` rows stale > 15 min after a crash.
|
|
576
|
+
- **iOS race condition fixed**: `MAURLocationMapper._location` was a file-scope global → real-time post + background sync running concurrently produced mixed fixes. Now per-instance ivar.
|
|
577
|
+
- **`locationTransform`**: events / battery / charging now survive transforms that return a new instance (both platforms).
|
|
578
|
+
|
|
579
|
+
### New in 4.5.0
|
|
580
|
+
|
|
581
|
+
- **Driving events, battery and isCharging now survive the sync queue.** Android DB v22 + iOS DB v7 add `events_json` / `battery_level` / `is_charging` columns on `location`. When a real-time POST fails and the location enters SQLite, those fields travel with it to the backend on the next sync.
|
|
582
|
+
- **iOS config persistence parity** — `MAURConfig` now serialises post-3.2 keys (`httpMethod`, `queryParams`, `drivingEvents`, `includeBattery`, etc.) to a `config_json` blob, matching Android v4.4.1.
|
|
583
|
+
- **Runtime permission helpers** (Android): `requestBackgroundLocationPermission()`, `requestActivityRecognitionPermission()`, `requestNotificationPermission()`. iOS / older Android resolve `{ granted: true, notRequired: true }`.
|
|
584
|
+
- **iOS background sync cleanup**: rows that were uploaded successfully are now removed from SQLite (the previous code re-uploaded them every cycle).
|
|
370
585
|
|
|
371
586
|
### New in 4.4.0
|
|
372
587
|
|
|
@@ -444,7 +659,7 @@ BackgroundGeolocation.on('phoneUsageWhileDriving', (location) => {
|
|
|
444
659
|
});
|
|
445
660
|
```
|
|
446
661
|
|
|
447
|
-
Full reference (all thresholds, when to enable, iOS screen-on caveat): [docs/api.md → Driver insights](docs/api.md#driver-insights-since-400).
|
|
662
|
+
Full reference (all thresholds, when to enable, iOS screen-on caveat): [docs/api.md → Driver insights](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md#driver-insights-since-400).
|
|
448
663
|
|
|
449
664
|
### New in 4.1.0
|
|
450
665
|
|
|
@@ -473,7 +688,7 @@ Full reference (all thresholds, when to enable, iOS screen-on caveat): [docs/api
|
|
|
473
688
|
|
|
474
689
|
### New in 3.5.0
|
|
475
690
|
|
|
476
|
-
- **`getDiagnostics()` (Phase 4).** New extended diagnostics method that helps you debug "tracking is not running" in production. Returns permissions (`fineLocationGranted`, `coarseLocationGranted`, `backgroundLocationGranted`, `notificationPermissionGranted`, `activityRecognitionGranted`), battery optimisation state (`batteryOptimizationIgnored`), OEM manufacturer (`manufacturer`), last-fix timestamp, pending sync count, declared `foregroundServiceType` (Android), and `preciseLocationEnabled`, `backgroundRefreshStatus`, `lowPowerModeEnabled`, `motionPermissionStatus` (iOS). Use it to surface actionable hints to users like "Allow all the time" or "Disable battery optimisation". See [getDiagnostics](docs/api.md#getdiagnosticssuccess-fail).
|
|
691
|
+
- **`getDiagnostics()` (Phase 4).** New extended diagnostics method that helps you debug "tracking is not running" in production. Returns permissions (`fineLocationGranted`, `coarseLocationGranted`, `backgroundLocationGranted`, `notificationPermissionGranted`, `activityRecognitionGranted`), battery optimisation state (`batteryOptimizationIgnored`), OEM manufacturer (`manufacturer`), last-fix timestamp, pending sync count, declared `foregroundServiceType` (Android), and `preciseLocationEnabled`, `backgroundRefreshStatus`, `lowPowerModeEnabled`, `motionPermissionStatus` (iOS). Use it to surface actionable hints to users like "Allow all the time" or "Disable battery optimisation". See [getDiagnostics](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md#getdiagnosticssuccess-fail).
|
|
477
692
|
- **`mockLocationPolicy: 'allow' | 'flag' | 'drop'`** — policy for mocked locations. Detection (`isFromMockProvider` Android, `simulated` iOS) was already present; this option controls what to do with those samples. Recommended for anti-fraud: `'flag'` (keep them but tagged) or `'drop'` (discard).
|
|
478
693
|
- **`heartbeatInterval`** option plus events `heartbeat`, `syncStart`, `syncProgress`, `syncSuccess`, `syncError` are all wired end-to-end with native emission on Android and iOS. Subscribe via `BackgroundGeolocation.on('heartbeat', cb)` etc.
|
|
479
694
|
- The Angular service exposes `getDiagnostics()` directly.
|
|
@@ -488,7 +703,7 @@ Full reference (all thresholds, when to enable, iOS screen-on caveat): [docs/api
|
|
|
488
703
|
### New in 3.3.0
|
|
489
704
|
|
|
490
705
|
- **Auto-start Android (Phase 1).** The plugin's boot receiver now also handles `QUICKBOOT_POWERON` (HTC, MIUI / Xiaomi), `com.htc.intent.action.QUICKBOOT_POWERON`, and `MY_PACKAGE_REPLACED` (the service relaunches after a Play Store update). Added `ACCESS_BACKGROUND_LOCATION` to the manifest with runtime validation on Android 10+. `ForegroundServiceStartNotAllowedException` (Android 12+) is caught with clear logging — WorkManager is **not** used as a fallback for tracking. The `foregroundServiceType` is now `"location"` only (dropped `dataSync`); the runtime type is read dynamically from the merged manifest. `<uses-library org.apache.http.legacy>` and `useLibrary 'org.apache.http.legacy'` are removed (the plugin uses `HttpURLConnection`). `jcenter()` → `mavenCentral()`.
|
|
491
|
-
- **Backend-agnostic HTTP transport (Phase 2).** New `httpMethod`, `syncHttpMethod`, `httpMode`, `syncMode`, `queryParams`, `headers` (alias of `httpHeaders`), `bodyTemplate` (alias of `postTemplate`). URL templating with `{latitude}`, `{longitude}`, `{lat}`, `{lon}`, `{time}`, `{timestamp}`, `{timestamp_iso}`, `{speed}`, `{altitude}`, `{bearing}`, `{accuracy}`, `{provider}` and any keys from `queryParams`. The plugin no longer hardcodes `POST` on Android (`HttpPostService`) or iOS (`MAURPostLocationTask`, `MAURBackgroundSync`). Compatibility is fully preserved — apps that only set `url` + `httpHeaders` + `postTemplate` keep working unchanged. See [HTTP transport](docs/api.md#http-transport-since-330) for backend examples (REST, GET single, form-urlencoded, Firebase, n8n).
|
|
706
|
+
- **Backend-agnostic HTTP transport (Phase 2).** New `httpMethod`, `syncHttpMethod`, `httpMode`, `syncMode`, `queryParams`, `headers` (alias of `httpHeaders`), `bodyTemplate` (alias of `postTemplate`). URL templating with `{latitude}`, `{longitude}`, `{lat}`, `{lon}`, `{time}`, `{timestamp}`, `{timestamp_iso}`, `{speed}`, `{altitude}`, `{bearing}`, `{accuracy}`, `{provider}` and any keys from `queryParams`. The plugin no longer hardcodes `POST` on Android (`HttpPostService`) or iOS (`MAURPostLocationTask`, `MAURBackgroundSync`). Compatibility is fully preserved — apps that only set `url` + `httpHeaders` + `postTemplate` keep working unchanged. See [HTTP transport](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md#http-transport-since-330) for backend examples (REST, GET single, form-urlencoded, Firebase, n8n).
|
|
492
707
|
- **Engines:** `cordova-android >= 12.0.0` is now the minimum.
|
|
493
708
|
|
|
494
709
|
### New in 3.2.0
|
|
@@ -502,7 +717,7 @@ Full reference (all thresholds, when to enable, iOS screen-on caveat): [docs/api
|
|
|
502
717
|
|
|
503
718
|
### New in 3.1.1
|
|
504
719
|
|
|
505
|
-
- **Browser / `ng serve` builds** — The plugin can now be bundled by webpack without "Can't resolve 'cordova/exec'" or "Can't resolve 'cordova/channel'". The package ships stub modules and a `browser` field so `ng serve` and browser builds succeed; on device/emulator the stubs delegate to the real Cordova API. See [docs/angular.md](docs/angular.md#build-ng-serve--browser).
|
|
720
|
+
- **Browser / `ng serve` builds** — The plugin can now be bundled by webpack without "Can't resolve 'cordova/exec'" or "Can't resolve 'cordova/channel'". The package ships stub modules and a `browser` field so `ng serve` and browser builds succeed; on device/emulator the stubs delegate to the real Cordova API. See [docs/angular.md](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/angular.md#build-ng-serve--browser).
|
|
506
721
|
|
|
507
722
|
### New in 3.1.0
|
|
508
723
|
|
|
@@ -515,7 +730,7 @@ Full reference (all thresholds, when to enable, iOS screen-on caveat): [docs/api
|
|
|
515
730
|
|
|
516
731
|
---
|
|
517
732
|
|
|
518
|
-
More (stationary, activity, headless task, Angular) is in the [documentation](https://josuelmm.github.io/cordova-background-geolocation/). For **Angular** (service, methods, events), see [docs/angular.md](docs/angular.md).
|
|
733
|
+
More (stationary, activity, headless task, Angular) is in the [documentation](https://josuelmm.github.io/cordova-background-geolocation/). For **Angular** (service, methods, events), see [docs/angular.md](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/angular.md).
|
|
519
734
|
|
|
520
735
|
---
|
|
521
736
|
|
|
@@ -558,13 +773,13 @@ export class MyService {
|
|
|
558
773
|
}
|
|
559
774
|
```
|
|
560
775
|
|
|
561
|
-
**You must import `BackgroundGeolocationModule`** in your `AppModule` (or feature module) so the service is provided and AOT builds work. Then inject `BackgroundGeolocationService` as in the example above. See [docs/angular.md](docs/angular.md) for the full snippet.
|
|
776
|
+
**You must import `BackgroundGeolocationModule`** in your `AppModule` (or feature module) so the service is provided and AOT builds work. Then inject `BackgroundGeolocationService` as in the example above. See [docs/angular.md](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/angular.md) for the full snippet.
|
|
562
777
|
|
|
563
|
-
**`ng serve` / browser:** From 3.1.1 the plugin includes browser stubs so `ng serve` and web builds complete without "Can't resolve 'cordova/exec'" — see [docs/angular.md](docs/angular.md#build-ng-serve--browser).
|
|
778
|
+
**`ng serve` / browser:** From 3.1.1 the plugin includes browser stubs so `ng serve` and web builds complete without "Can't resolve 'cordova/exec'" — see [docs/angular.md](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/angular.md#build-ng-serve--browser).
|
|
564
779
|
|
|
565
|
-
**Lazy-loaded pages:** If you see **NG0202** or *"dependency at index N is invalid"* when opening a page that injects this service, use an app-defined token and inject by that token (the plugin token can be undefined in the lazy chunk). See [docs/angular.md](docs/angular.md) (Lazy-loaded modules).
|
|
780
|
+
**Lazy-loaded pages:** If you see **NG0202** or *"dependency at index N is invalid"* when opening a page that injects this service, use an app-defined token and inject by that token (the plugin token can be undefined in the lazy chunk). See [docs/angular.md](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/angular.md) (Lazy-loaded modules).
|
|
566
781
|
|
|
567
|
-
**Migrating from @awesome-cordova-plugins/background-geolocation:** there you inject a class named `BackgroundGeolocation`. In this package, `BackgroundGeolocation` is the **global plugin object**, not an injectable class. Use `BackgroundGeolocationService` instead (same API). See [docs/angular.md](docs/angular.md) for details.
|
|
782
|
+
**Migrating from @awesome-cordova-plugins/background-geolocation:** there you inject a class named `BackgroundGeolocation`. In this package, `BackgroundGeolocation` is the **global plugin object**, not an injectable class. Use `BackgroundGeolocationService` instead (same API). See [docs/angular.md](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/angular.md) for details.
|
|
568
783
|
|
|
569
784
|
### Summary
|
|
570
785
|
|
|
@@ -590,6 +805,11 @@ No extra wrapper (e.g. Awesome Cordova Plugins) is required.
|
|
|
590
805
|
> 3.3.0+: `cordova-android >= 12` is required for `targetSdk 34+` and the modernised foreground-service handling. The new iOS APIs (`showsBackgroundLocationIndicator` iOS 11+, `locationManagerDidChangeAuthorization:` iOS 14+) are gated by runtime `@available` checks, so older iOS versions still link and run.
|
|
591
806
|
>
|
|
592
807
|
> 4.5.0+: SQLite schemas bumped (Android v22, iOS v7) to persist `events`, `battery`, `isCharging` across the sync queue. Upgrades from any earlier version auto-migrate.
|
|
808
|
+
>
|
|
809
|
+
> 4.5.2+ — **Google Play Services matrix (Android)**:
|
|
810
|
+
> - `RAW_PROVIDER` — no requiere Play Services (usa OS LocationManager). Funciona en Huawei/HMS, AOSP, China ROMs.
|
|
811
|
+
> - `DISTANCE_FILTER_PROVIDER` — **híbrido**: usa `FusedLocationProviderClient` cuando hay Play Services, fallback automático a `LocationManager` cuando no. Funciona en todos los Android.
|
|
812
|
+
> - `ACTIVITY_PROVIDER` — **requiere Play Services** (depende de `ActivityRecognitionClient`, sin equivalente OS). En dispositivos sin Play Services usar `DISTANCE_FILTER_PROVIDER` o `RAW_PROVIDER`.
|
|
593
813
|
|
|
594
814
|
---
|
|
595
815
|
|
|
@@ -599,16 +819,16 @@ This README is the main entry point. For more detail, edge cases and examples us
|
|
|
599
819
|
|
|
600
820
|
| Doc | What you'll find |
|
|
601
821
|
|-----|------------------|
|
|
602
|
-
| **[API reference](docs/api.md)** | Every `configure` option, every method (`configure`, `start`, `stop`, `getPendingSyncCount`, `forceSync`, `clearSync`, `startSession`, `getSessionLocations`, `clearSession`, `getSessionLocationsCount`, `getConfig`, `getLocations`, etc.), TypeScript types. Also covers the **HTTP transport (3.3.0)** and **auto-start on Android boot (3.3.0)**. |
|
|
603
|
-
| **[HTTP transport (3.3.0)](docs/http-transport.md)** | `httpMethod`, `httpMode`, URL templating, `bodyTemplate`, `queryParams`, examples for REST, GET single, form-urlencoded, Firebase, n8n, Traccar. |
|
|
604
|
-
| **[Auto-start on boot (3.3.0)](docs/auto-start.md)** | Android receiver actions, `ACCESS_BACKGROUND_LOCATION` runtime flow, OEM caveats, iOS limitation. |
|
|
605
|
-
| **[Traccar integration example](docs/traccar.md)** | Optional backend: how to deliver positions to Traccar (or Firebase, n8n, custom REST) via the HTTP transport. The plugin is backend-agnostic. |
|
|
606
|
-
| **[Location modernization (3.4.0)](docs/location-modernization.md)** | What was modernised in Phase 3 (LocationRequest.Builder, NSURLSession, iOS 14+ auth callback) and what is still legacy. |
|
|
607
|
-
| **[Roadmap](docs/ROADMAP.md)** | Phases 1–6, what's released, what's next. |
|
|
608
|
-
| **[HTTP posting](docs/http_posting.md)** | `url` vs `syncUrl`, Content-Type (JSON = one POST with array; form-urlencoded = one POST per location), headers, retries, `postTemplate`, sync behaviour. |
|
|
609
|
-
| **[Events](docs/events.md)** | All events (`location`, `error`, `stationary`, `activity`, `http_authorization`, etc.) and payloads. |
|
|
610
|
-
| **[Angular / Ionic](docs/angular.md)** | Injectable service, module, lazy-loaded modules and token "must be defined", `ng serve` / browser build. |
|
|
611
|
-
| **[Example](docs/example.md)** | Full example with events and sync. |
|
|
822
|
+
| **[API reference](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/api.md)** | Every `configure` option, every method (`configure`, `start`, `stop`, `getPendingSyncCount`, `forceSync`, `clearSync`, `startSession`, `getSessionLocations`, `clearSession`, `getSessionLocationsCount`, `getConfig`, `getLocations`, etc.), TypeScript types. Also covers the **HTTP transport (3.3.0)** and **auto-start on Android boot (3.3.0)**. |
|
|
823
|
+
| **[HTTP transport (3.3.0)](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/http-transport.md)** | `httpMethod`, `httpMode`, URL templating, `bodyTemplate`, `queryParams`, examples for REST, GET single, form-urlencoded, Firebase, n8n, Traccar. |
|
|
824
|
+
| **[Auto-start on boot (3.3.0)](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/auto-start.md)** | Android receiver actions, `ACCESS_BACKGROUND_LOCATION` runtime flow, OEM caveats, iOS limitation. |
|
|
825
|
+
| **[Traccar integration example](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/traccar.md)** | Optional backend: how to deliver positions to Traccar (or Firebase, n8n, custom REST) via the HTTP transport. The plugin is backend-agnostic. |
|
|
826
|
+
| **[Location modernization (3.4.0)](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/location-modernization.md)** | What was modernised in Phase 3 (LocationRequest.Builder, NSURLSession, iOS 14+ auth callback) and what is still legacy. |
|
|
827
|
+
| **[Roadmap](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/ROADMAP.md)** | Phases 1–6, what's released, what's next. |
|
|
828
|
+
| **[HTTP posting](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/http_posting.md)** | `url` vs `syncUrl`, Content-Type (JSON = one POST with array; form-urlencoded = one POST per location), headers, retries, `postTemplate`, sync behaviour. |
|
|
829
|
+
| **[Events](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/events.md)** | All events (`location`, `error`, `stationary`, `activity`, `http_authorization`, etc.) and payloads. |
|
|
830
|
+
| **[Angular / Ionic](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/angular.md)** | Injectable service, module, lazy-loaded modules and token "must be defined", `ng serve` / browser build. |
|
|
831
|
+
| **[Example](https://github.com/josuelmm/cordova-background-geolocation/blob/main/docs/example.md)** | Full example with events and sync. |
|
|
612
832
|
| **[CHANGELOG](CHANGELOG.md)** | Version history. |
|
|
613
833
|
|
|
614
834
|
This project is based on [@mauron85/cordova-plugin-background-geolocation](https://github.com/mauron85/cordova-plugin-background-geolocation) and the original by [christocracy](https://github.com/christocracy). Maintained at [josuelmm/cordova-background-geolocation](https://github.com/josuelmm/cordova-background-geolocation). Issues and PRs welcome.
|
|
@@ -198,6 +198,13 @@ public class ConfigMapper {
|
|
|
198
198
|
if (jObject.has("stationaryPollFast") && !jObject.isNull("stationaryPollFast")) {
|
|
199
199
|
config.setStationaryPollFast(jObject.getInt("stationaryPollFast"));
|
|
200
200
|
}
|
|
201
|
+
// v4.5.2: provider hardening
|
|
202
|
+
if (jObject.has("activityConfidenceThreshold") && !jObject.isNull("activityConfidenceThreshold")) {
|
|
203
|
+
config.setActivityConfidenceThreshold(jObject.getInt("activityConfidenceThreshold"));
|
|
204
|
+
}
|
|
205
|
+
if (jObject.has("maxAcceptedAccuracy") && !jObject.isNull("maxAcceptedAccuracy")) {
|
|
206
|
+
config.setMaxAcceptedAccuracy((float) jObject.getDouble("maxAcceptedAccuracy"));
|
|
207
|
+
}
|
|
201
208
|
|
|
202
209
|
return config;
|
|
203
210
|
}
|
|
@@ -288,6 +295,9 @@ public class ConfigMapper {
|
|
|
288
295
|
json.put("stationaryTimeout", config.getStationaryTimeout());
|
|
289
296
|
json.put("stationaryPollInterval", config.getStationaryPollInterval());
|
|
290
297
|
json.put("stationaryPollFast", config.getStationaryPollFast());
|
|
298
|
+
// v4.5.2 provider hardening
|
|
299
|
+
json.put("activityConfidenceThreshold", config.getActivityConfidenceThreshold());
|
|
300
|
+
json.put("maxAcceptedAccuracy", config.getMaxAcceptedAccuracy());
|
|
291
301
|
|
|
292
302
|
return json;
|
|
293
303
|
}
|
|
@@ -96,7 +96,7 @@ public class BackgroundGeolocationPlugin extends CordovaPlugin implements Plugin
|
|
|
96
96
|
public static final String ACTION_REQUEST_NOTIFICATION_PERMISSION = "requestNotificationPermission";
|
|
97
97
|
|
|
98
98
|
/** Plugin version; keep in sync with plugin.xml. */
|
|
99
|
-
public static final String PLUGIN_VERSION = "4.5.
|
|
99
|
+
public static final String PLUGIN_VERSION = "4.5.2";
|
|
100
100
|
|
|
101
101
|
private BackgroundGeolocationFacade facade;
|
|
102
102
|
|
|
@@ -34,6 +34,20 @@ public class BootCompletedReceiver extends BroadcastReceiver {
|
|
|
34
34
|
@Override
|
|
35
35
|
public void onReceive(Context context, Intent intent) {
|
|
36
36
|
String action = intent != null ? intent.getAction() : null;
|
|
37
|
+
|
|
38
|
+
// v4.5.2 — hardening: ignore arbitrary broadcasts directed at this
|
|
39
|
+
// receiver. Without this, any explicit intent (e.g. a malicious app
|
|
40
|
+
// targeting our package) could trigger the service auto-start path.
|
|
41
|
+
// Accept only the canonical boot/package-replaced actions plus the
|
|
42
|
+
// OEM-specific quick-boot variants used by HTC and Samsung.
|
|
43
|
+
if (!Intent.ACTION_BOOT_COMPLETED.equals(action)
|
|
44
|
+
&& !"android.intent.action.QUICKBOOT_POWERON".equals(action)
|
|
45
|
+
&& !"com.htc.intent.action.QUICKBOOT_POWERON".equals(action)
|
|
46
|
+
&& !Intent.ACTION_MY_PACKAGE_REPLACED.equals(action)) {
|
|
47
|
+
Log.w(TAG, "Ignoring unsupported broadcast: " + action);
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
|
|
37
51
|
Log.d(TAG, "Received boot/replace broadcast: " + action);
|
|
38
52
|
ConfigurationDAO dao = DAOFactory.createConfigurationDAO(context);
|
|
39
53
|
Config config = null;
|