@josuelmm/cordova-background-geolocation 4.2.3 → 4.5.1
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/.npmignore +11 -0
- package/CHANGELOG.md +203 -0
- package/HISTORY.md +67 -0
- package/README.md +45 -74
- package/android/CDVBackgroundGeolocation/src/main/java/com/marianhello/bgloc/cordova/ConfigMapper.java +24 -0
- package/android/CDVBackgroundGeolocation/src/main/java/com/tenforwardconsulting/bgloc/cordova/BackgroundGeolocationPlugin.java +61 -1
- package/android/common/src/main/AndroidManifest.xml +1 -1
- package/android/common/src/main/java/com/marianhello/bgloc/BootCompletedReceiver.java +6 -3
- package/android/common/src/main/java/com/marianhello/bgloc/Config.java +65 -1
- package/android/common/src/main/java/com/marianhello/bgloc/data/BackgroundLocation.java +94 -0
- package/android/common/src/main/java/com/marianhello/bgloc/data/ConfigJsonMapper.java +205 -0
- package/android/common/src/main/java/com/marianhello/bgloc/data/LocationTemplateFactory.java +6 -0
- package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationContract.java +5 -1
- package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationDAO.java +32 -1
- package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteLocationContract.java +12 -2
- package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteLocationDAO.java +33 -2
- package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteOpenHelper.java +15 -1
- package/android/common/src/main/java/com/marianhello/bgloc/provider/DistanceFilterLocationProvider.java +23 -8
- package/android/common/src/main/java/com/marianhello/bgloc/service/LocationServiceImpl.java +246 -21
- package/android/common/src/main/java/com/marianhello/bgloc/service/LocationServiceProxy.java +5 -2
- package/android/common/src/main/java/com/marianhello/bgloc/sync/BatchManager.java +46 -13
- package/ios/CDVBackgroundGeolocation/CDVBackgroundGeolocation.m +23 -1
- package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m +111 -5
- package/ios/common/BackgroundGeolocation/MAURBackgroundSync.m +20 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.h +2 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.m +16 -2
- package/ios/common/BackgroundGeolocation/MAURConfigurationContract.h +3 -0
- package/ios/common/BackgroundGeolocation/MAURConfigurationContract.m +3 -1
- package/ios/common/BackgroundGeolocation/MAURGeolocationOpenHelper.m +15 -1
- package/ios/common/BackgroundGeolocation/MAURLocation.h +12 -0
- package/ios/common/BackgroundGeolocation/MAURLocation.m +33 -4
- package/ios/common/BackgroundGeolocation/MAURLocationContract.h +4 -0
- package/ios/common/BackgroundGeolocation/MAURLocationContract.m +5 -1
- package/ios/common/BackgroundGeolocation/MAURPostLocationTask.h +9 -0
- package/ios/common/BackgroundGeolocation/MAURPostLocationTask.m +59 -1
- package/ios/common/BackgroundGeolocation/MAURSQLiteConfigurationDAO.m +54 -4
- package/ios/common/BackgroundGeolocation/MAURSQLiteLocationDAO.h +12 -0
- package/ios/common/BackgroundGeolocation/MAURSQLiteLocationDAO.m +125 -5
- package/package.json +31 -1
- package/plugin.xml +3 -2
- package/www/BackgroundGeolocation.d.ts +114 -3
- package/www/BackgroundGeolocation.js +11 -4
- package/CLAUDE.md +0 -56
- package/android/CDVBackgroundGeolocation/src/test/java/com/marianhello/ConfigMapperTest.java +0 -220
- package/android/common/src/androidTest/java/com/marianhello/bgloc/BackgroundGeolocationFacadeTest.java +0 -45
- package/android/common/src/androidTest/java/com/marianhello/bgloc/BatchManagerTest.java +0 -570
- package/android/common/src/androidTest/java/com/marianhello/bgloc/ConfigTest.java +0 -76
- package/android/common/src/androidTest/java/com/marianhello/bgloc/ContentProviderLocationDAOTest.java +0 -437
- package/android/common/src/androidTest/java/com/marianhello/bgloc/DBLogReaderTest.java +0 -95
- package/android/common/src/androidTest/java/com/marianhello/bgloc/LocationContentProviderTest.java +0 -159
- package/android/common/src/androidTest/java/com/marianhello/bgloc/LocationServiceProxyTest.java +0 -161
- package/android/common/src/androidTest/java/com/marianhello/bgloc/LocationServiceTest.java +0 -247
- package/android/common/src/androidTest/java/com/marianhello/bgloc/SQLiteConfigurationDAOTest.java +0 -200
- package/android/common/src/androidTest/java/com/marianhello/bgloc/SQLiteLocationDAOTest.java +0 -457
- package/android/common/src/androidTest/java/com/marianhello/bgloc/SQLiteLocationDAOThreadTest.java +0 -96
- package/android/common/src/androidTest/java/com/marianhello/bgloc/SQLiteOpenHelperTest.java +0 -225
- package/android/common/src/androidTest/java/com/marianhello/bgloc/TestPluginDelegate.java +0 -46
- package/android/common/src/androidTest/java/com/marianhello/bgloc/TestResourceResolver.java +0 -14
- package/android/common/src/androidTest/java/com/marianhello/bgloc/provider/MockLocationProvider.java +0 -50
- package/android/common/src/androidTest/java/com/marianhello/bgloc/provider/TestLocationProviderFactory.java +0 -17
- package/android/common/src/androidTest/java/com/marianhello/bgloc/sqlite/SQLiteOpenHelper10.java +0 -92
- package/android/common/src/androidTest/java/com/marianhello/bgloc/test/LocationProviderTestCase.java +0 -107
- package/android/common/src/androidTest/java/com/marianhello/bgloc/test/TestConstants.java +0 -5
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/ArrayListLocationTemplateTest.java +0 -82
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/BackgroundLocationTest.java +0 -128
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/ConfigTest.java +0 -191
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/DBLogReaderTest.java +0 -37
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/HashMapLocationTemplateTest.java +0 -216
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/HttpPostServiceTest.java +0 -223
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/LocationTemplateFactoryTest.java +0 -50
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/PostLocationTaskTest.java +0 -180
- package/android/common/src/test/java/com/marianhello/backgroundgeolocation/TestHelper.java +0 -16
- package/ios/common/BackgroundGeolocationTests/Info.plist +0 -24
- package/ios/common/BackgroundGeolocationTests/MAURBackgroundLocationTest.m +0 -185
- package/ios/common/BackgroundGeolocationTests/MAURConfigTest.m +0 -161
- package/ios/common/BackgroundGeolocationTests/MAURGeolocationOpenHelperTest.m +0 -102
- package/ios/common/BackgroundGeolocationTests/MAURLocationTest.m +0 -216
- package/ios/common/BackgroundGeolocationTests/MAURLocationUploaderTest.m +0 -55
- package/ios/common/BackgroundGeolocationTests/MAURLogReaderTest.m +0 -43
- package/ios/common/BackgroundGeolocationTests/MAURSQLiteConfigurationDAOTest.m +0 -102
- package/ios/common/BackgroundGeolocationTests/MAURSQLiteHelperTest.m +0 -41
- package/ios/common/BackgroundGeolocationTests/MAURSQLiteLocationDAOTests.m +0 -240
- package/ios/common/BackgroundGeolocationTests/MAURSQLiteLocationDAOThreadTest.m +0 -84
- package/ios/common/BackgroundGeolocationTests/MAURSQLiteOpenHelperTest.m +0 -144
- package/ios/common/scripts/xcode-refactor.js +0 -184
package/.npmignore
CHANGED
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
/REVIEW_*.md
|
|
9
9
|
/RELEASE.MD
|
|
10
10
|
/NPM_PUBLISH.md
|
|
11
|
+
/CLAUDE.md
|
|
12
|
+
# exclude dev tooling, CI, tarballs, workspace
|
|
13
|
+
/scripts
|
|
14
|
+
/.github
|
|
15
|
+
/josuelmm-cordova-background-geolocation-*.tgz
|
|
16
|
+
/cordova-background-geolocation-plugin.code-workspace
|
|
11
17
|
!/plugin.xml
|
|
12
18
|
!/package.json
|
|
13
19
|
!/www
|
|
@@ -26,11 +32,16 @@
|
|
|
26
32
|
!/android/common
|
|
27
33
|
/android/common/*
|
|
28
34
|
!/android/common/src
|
|
35
|
+
/android/common/src/test
|
|
36
|
+
/android/common/src/androidTest
|
|
29
37
|
!/android/CDVBackgroundGeolocation
|
|
30
38
|
/android/CDVBackgroundGeolocation/*
|
|
31
39
|
!/android/CDVBackgroundGeolocation/src
|
|
40
|
+
/android/CDVBackgroundGeolocation/src/test
|
|
32
41
|
!/ios
|
|
33
42
|
/ios/*
|
|
34
43
|
!/ios/common
|
|
44
|
+
/ios/common/BackgroundGeolocationTests
|
|
45
|
+
/ios/common/scripts
|
|
35
46
|
!/ios/CDVBackgroundGeolocation
|
|
36
47
|
!/LICENSE
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,208 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.5.1](https://github.com/josuelmm/cordova-background-geolocation/tree/4.5.1) (2026-05-09)
|
|
4
|
+
|
|
5
|
+
### Fixed (BLOQUEANTES)
|
|
6
|
+
- **Android no compilaba**: faltaba `import android.os.Build;` en `BackgroundGeolocationPlugin.java` después de los handlers v4.5.0 que usaban `Build.VERSION.SDK_INT`.
|
|
7
|
+
- **Android UPDATE en `maxLocations` mezclaba events/battery viejos**: cuando la cola SQLite alcanzaba `maxLocations`, el row más viejo se reciclaba con UPDATE pero NO actualizaba `events_json`, `battery_level`, `is_charging`. Resultado: un `possibleCrash`/`hardBrake`/batería vieja podía quedarse pegada a una location nueva. `SQLiteLocationDAO` extendido con esas 3 columnas (con `null` cuando la nueva no las tiene, para limpiar valores viejos).
|
|
8
|
+
- **iOS UPDATE en `persistLocation:limitRows:`**: mismo bug que Android. `MAURSQLiteLocationDAO.m` ahora setea `events_json`, `battery_level`, `is_charging` (con `[NSNull null]` cuando faltan).
|
|
9
|
+
|
|
10
|
+
### Added — Optimización de batería
|
|
11
|
+
|
|
12
|
+
- **`wakeLockMode: 'none' | 'posting' | 'always'`** (default `'posting'`). Antes el servicio mantenía un `PARTIAL_WAKE_LOCK` permanente todo el tiempo de tracking → drenaba batería sin necesidad. Ahora:
|
|
13
|
+
- `'posting'` (default): solo 30 s al recibir cada fix (suficiente para SQLite + POST).
|
|
14
|
+
- `'none'`: nunca. Mejor batería; usa solo con `httpMode: 'batch'`.
|
|
15
|
+
- `'always'`: comportamiento legacy. Solo para fleet/emergency apps.
|
|
16
|
+
- **Watchdog moving-only**: `enableWatchdog` ya no reinicia el provider cuando estamos en estacionario. Antes despertaba el GPS cada 60 s aunque el plugin estuviera intencionalmente quieto. Ahora solo reinicia si `tripActive` (driver insights) está marcado.
|
|
17
|
+
- **Stationary params configurables**: `stationaryTimeout` (default 300_000 ms), `stationaryPollInterval` (default 180_000 ms), `stationaryPollFast` (default 60_000 ms). Ya no son constantes hard-coded en `DistanceFilterLocationProvider`.
|
|
18
|
+
|
|
19
|
+
### Fixed (otros)
|
|
20
|
+
- `android/common/src/main/AndroidManifest.xml` interno: `<uses-permission android:name="android.hardware.location" />` → `<uses-feature ... required="false" />` (paridad con `plugin.xml` raíz).
|
|
21
|
+
- `README.md` y `www/BackgroundGeolocation.d.ts`: removido caveat obsoleto que decía "events no sobrevive sync queue" (sí sobrevive desde 4.5.0).
|
|
22
|
+
- `.npmignore`: limpieza para no publicar `CLAUDE.md`, tests internos, scripts, etc.
|
|
23
|
+
|
|
24
|
+
### Fixed (post-auditoría 4 — flujos end-to-end + casos edge)
|
|
25
|
+
- **iOS `MAURLocationMapper._location` declarado a nivel de archivo**: race real entre real-time post + background sync (queues concurrentes). El segundo `+map:` pisaba la referencia del primer mapper → backend recibía fixes con campos mezclados. Migrado a ivar de instancia.
|
|
26
|
+
- **iOS pending events se perdían si `locationTransform` retornaba `nil`**: la facade drenaba `pendingDrivingEventsBuffer` al `location` ANTES de `[postLocationTask add:]`; cuando el transform descartaba el fix, esos eventos no llegaban nunca al backend. Movidos al `MAURPostLocationTask.add:` DESPUÉS del transform (vía property weak `pendingDrivingEventsBuffer` + block `attachBatterySnapshot`).
|
|
27
|
+
- **iOS re-attach con `==` sobrescribía events** del transform en lugar de hacer merge. Paridad con Android: ahora hace `addObjectsFromArray:` cuando la nueva instancia tiene su propio array de events.
|
|
28
|
+
- **Android `wakeLockMode` no hot-reload**: al cambiar `'always' → 'posting'/'none'` el lock permanente se mantenía hasta `stop()`; inverso tampoco lo adquiría. Añadida lógica en `configure()` que compara prev/new y llama `release()` / `acquire()` según corresponda.
|
|
29
|
+
- **`d.ts` `headlessTask`** no marcaba iOS como no soportado. Añadido `Platform: Android` + nota explicando que en iOS es no-op.
|
|
30
|
+
- **README**: bloque corrupto de líneas 638-712 (duplicado de Angular + License) eliminado. Tabla `Compatibility` extendida con `4.2.x – 4.5.x`.
|
|
31
|
+
- **docs/api.md**: tabla `configure` extendida con `drivingEvents`, `includeBattery`, `wakeLockMode`, `stationaryTimeout`, `stationaryPollInterval`, `stationaryPollFast`. Documentados los 3 helpers de permisos runtime.
|
|
32
|
+
|
|
33
|
+
### Fixed (post-auditoría 3 — payload default y serialización)
|
|
34
|
+
- **Payload default no incluía `events` / `battery` / `isCharging`.** `Config.getTemplate()` siempre cae a `LocationTemplateFactory.getDefault()` cuando no hay `postTemplate` custom, y el default omitía los placeholders nuevos. README/CHANGELOG decían "el payload default los incluye" pero **el backend recibía sin esos campos**. Añadidos `@events`, `@battery`, `@isCharging` al default (Android `LocationTemplateFactory.getDefault`, iOS `MAURConfig.getDefaultTemplate`).
|
|
35
|
+
- **iOS default template tenía bug**: `@"provider": @"provider"` enviaba la string literal `"provider"` en lugar del valor real. Corregido a `@"@provider"`.
|
|
36
|
+
- **iOS mapper (`MAURLocation.mapValue`) devolvía el placeholder literal** (`"@events"`, `"@battery"`) cuando la location no tenía valor para esa clave. Ahora retorna `NSNull` para keys que empiezan con `@`; preserva el comportamiento legacy para strings estáticos (ej. `deviceId` literal en postTemplate).
|
|
37
|
+
- **Android `BatchManager.writeValue`** no manejaba `JSONArray` / `JSONObject` — cuando una location de la cola de sync salía con `events` poblado, el array se serializaba como string escapado `"[{\"type\":\"hardBrake\"}]"` en lugar de JSON real. Añadido manejo de tipos JSON + helper `resolveTemplateValue` que devuelve `JSONObject.NULL` para placeholders `@…` sin valor.
|
|
38
|
+
- **`onStationary` Android e iOS** no enriquecían el fix con events/battery — el backend recibía updates stationary sin esos campos aunque las features estuvieran habilitadas. Añadido `flushPendingDrivingEvents` + `attachBatterySnapshot` en ambos.
|
|
39
|
+
- `.npmignore`: añadido `/ios/common/scripts` para no publicar `xcode-refactor.js`.
|
|
40
|
+
|
|
41
|
+
### Fixed (post-auditoría 2)
|
|
42
|
+
- **Android `toContentValues` / `SQLiteLocationDAO.getContentValues` ahora limpian con `putNull`** las columnas `events_json`, `battery_level`, `is_charging` cuando la nueva location no las trae. Sin esto, el flujo `ContentProviderLocationDAO.persistLocation(location, maxRows)` que recicla el row más viejo via UPDATE dejaba pegados los valores del row anterior (ej. un `possibleCrash` viejo aparecía adherido a una location nueva).
|
|
43
|
+
- **`registerReceiver` override**: guard por SDK. `RECEIVER_NOT_EXPORTED` y el 5-arg overload solo se usan en API ≥ 33 / ≥ 26. En APIs viejas se cae al 2-arg estándar.
|
|
44
|
+
- **`checkSelfPermission`** migrado a `ContextCompat.checkSelfPermission` en `BootCompletedReceiver`, `LocationServiceImpl`, `LocationServiceProxy`. Funciona seguro en API < 23 (permisos auto-granted al install).
|
|
45
|
+
- **iOS recovery de `SyncPending` stale**: nuevo `restoreStaleSyncLocationsOlderThan:` que se invoca al inicio de cada `MAURPostLocationTask.sync`. Si la app/proceso murió entre `getLocationsForSync` y el callback success/failure, las locations quedaban atascadas en `SyncPending` y nunca se reintentaban. Ahora se restauran a `PostPending` automáticamente si tienen más de 15 min.
|
|
46
|
+
- **iOS `locationTransform` que retorna nueva instancia**: ahora `MAURPostLocationTask.add` copia `drivingEvents` / `batteryLevel` / `isCharging` de la location original a la transformada si el transform no las propagó. Paridad con el fix Android.
|
|
47
|
+
|
|
48
|
+
### Fixed (post-auditoría — BLOQUEANTE iOS sync)
|
|
49
|
+
- **iOS `getLocationsForSync` borraba TODA la tabla antes del upload.** Bug heredado: `UPDATE location SET valid = Deleted` sin `WHERE`. Si la red caía a mitad del POST, todas las ubicaciones se perdían silenciosamente. Ahora usa transición de estados:
|
|
50
|
+
- `getLocationsForSync` → `PostPending → SyncPending` (in-flight, no se re-incluye en otros sync windows).
|
|
51
|
+
- Success → `deleteSyncedLocationsBefore:cutoff` opera sobre `SyncPending` (no `PostPending` que estarían esperando POST real-time).
|
|
52
|
+
- Failure (network/HTTP) → nuevo `restoreFailedSyncLocations`: `SyncPending → PostPending` para reintento. Sin esto un solo fallo dropeaba todas.
|
|
53
|
+
|
|
54
|
+
### Fixed (post-auditoría)
|
|
55
|
+
- **`LocationServiceImpl.onLocation`** — ahora `attachBatterySnapshot()` y `flushPendingDrivingEvents()` se ejecutan DESPUÉS de `transformLocation()`. Antes, si el usuario configuraba un `LocationTransform` que retornaba una nueva instancia, los `events` y la batería se perdían (se anexaban a la location original que el plugin descartaba). Adicionalmente, los eventos del detector que se anexaron a la location RAW se copian a la transformada via `addDrivingEvent`.
|
|
56
|
+
- **Watchdog smart**: la lógica `mDrivingTripActive` solo aplica cuando `drivingEvents.enabled == true`. Si el usuario tiene `enableWatchdog: true` SIN `drivingEvents`, el watchdog mantiene comportamiento legacy (reinicia el provider tras 60s sin fix). Sin esto, watchdog no se activaría nunca con drivingEvents desactivado.
|
|
57
|
+
- **`Config(Parcel)`** — `in.readBundle(Config.class.getClassLoader())` para que `LocationTemplate`/HashMaps subclase se deserialicen correctamente cuando el Parcel cruza el proceso `:sync`.
|
|
58
|
+
- **iOS race en `deletePendingSyncLocations` tras success** — nuevo método `deleteSyncedLocationsBefore:` que solo borra rows con `recorded_at <= cutoff`, donde `cutoff` se captura ANTES del upload. Las locations persistidas DURANTE el upload (window de race entre POST y delete) se preservan correctamente.
|
|
59
|
+
|
|
60
|
+
## [4.5.0](https://github.com/josuelmm/cordova-background-geolocation/tree/4.5.0) (2026-05-09)
|
|
61
|
+
|
|
62
|
+
### Added — Paridad de persistencia + helpers de permisos
|
|
63
|
+
|
|
64
|
+
#### Persistencia events / battery / charging en cola de sync
|
|
65
|
+
- **Android (DB v22)**: nuevas columnas `events_json TEXT`, `battery_level INTEGER`, `is_charging INTEGER` en tabla `location`. Migración v21→v22 automática. `BackgroundLocation.toContentValues` / `fromCursor` actualizados; campos ya NO transient — sobreviven Parcel y SQLite.
|
|
66
|
+
- **iOS (DB v6)**: mismas 3 columnas en `location`. `MAURSQLiteLocationDAO` `persistLocation` / `convertToLocation` actualizados.
|
|
67
|
+
- **Resultado**: si el POST en real-time falla y la location entra a la cola de sync, los `events`, `battery`, `isCharging` ahora viajan con ella cuando se sincroniza después. Antes se perdían.
|
|
68
|
+
|
|
69
|
+
#### Persistencia config completa iOS (paridad con Android)
|
|
70
|
+
- **DB v7** añade columna `config_json TEXT` en `configuration`. `MAURSQLiteConfigurationDAO.persistConfiguration` ahora serializa todas las keys post-3.2.0 (`httpMethod`, `syncHttpMethod`, `httpMode`, `syncMode`, `queryParams`, `heartbeatInterval`, `mockLocationPolicy`, `drivingEvents`, `includeBattery`) a JSON. `retrieveConfiguration` rehidrata desde el blob.
|
|
71
|
+
|
|
72
|
+
#### Helpers de permisos runtime (Android)
|
|
73
|
+
Tres nuevos métodos JS para que la app pueda controlar el flujo de permisos modernos:
|
|
74
|
+
- `requestBackgroundLocationPermission()` — pide `ACCESS_BACKGROUND_LOCATION` (Android 10+).
|
|
75
|
+
- `requestActivityRecognitionPermission()` — pide `ACTIVITY_RECOGNITION` (Android 10+).
|
|
76
|
+
- `requestNotificationPermission()` — pide `POST_NOTIFICATIONS` (Android 13+).
|
|
77
|
+
|
|
78
|
+
Resuelven con `{ granted: boolean, denied?: string[], notRequired?: boolean }`.
|
|
79
|
+
En iOS y Android < versión mínima resuelven inmediatamente con `notRequired: true`.
|
|
80
|
+
|
|
81
|
+
#### iOS sync cleanup tras success (bug fix)
|
|
82
|
+
- `MAURBackgroundSync` ahora llama `deletePendingSyncLocations` tras un POST batch exitoso (2xx). Antes la cola SQLite no se vaciaba, provocando re-uploads de los mismos rows en cada ciclo.
|
|
83
|
+
|
|
84
|
+
### Migraciones
|
|
85
|
+
- Android DB v21 → v22 (location columns).
|
|
86
|
+
- iOS DB v5 → v7 (location + configuration columns). v5→v6 añade location columns; v6→v7 añade config_json.
|
|
87
|
+
|
|
88
|
+
## [4.4.1](https://github.com/josuelmm/cordova-background-geolocation/tree/4.4.1) (2026-05-09)
|
|
89
|
+
|
|
90
|
+
### Fixed — stability patch
|
|
91
|
+
|
|
92
|
+
#### Crítico
|
|
93
|
+
- **Android: persistencia de configuración**. Tras un reboot + `startOnBoot`, las opciones añadidas desde 3.3.0 (`httpMethod`, `syncHttpMethod`, `httpMode`, `syncMode`, `queryParams`, `heartbeatInterval`, `mockLocationPolicy`, `drivingEvents`, `includeBattery`) volvían a default porque `SQLiteConfigurationDAO` solo persistía las columnas de 3.2.0. Solución: nueva columna `config_json TEXT` (DB v20→v21) que serializa todo el `Config`. Las columnas viejas se mantienen pobladas para retrocompat.
|
|
94
|
+
- **Android: `Config.merge()` ignoraba `includeBattery`**. `configure({includeBattery: false})` se descartaba en el merge interno y el plugin seguía estampando batería en cada location. Arreglado.
|
|
95
|
+
|
|
96
|
+
#### Real
|
|
97
|
+
- **Android: `attachBatterySnapshot` rompía con el override interno de `registerReceiver`**. El servicio sobrescribe `registerReceiver` para forzar `RECEIVER_NOT_EXPORTED` + handler — incompatible con la lectura sticky-only que necesita batería. Ahora la batería se lee con `getApplicationContext().registerReceiver(null, filter)` para bypassear el override.
|
|
98
|
+
- **iOS `MAURPostLocationTask.m:258`**: `*outError == nil` sin guard de `outError == NULL`. Crash defensivo si futuro caller pasa NULL. Añadido `if (outError == NULL || *outError == nil)`.
|
|
99
|
+
- **`pendingDrivingEvents` (Android+iOS)**: ahora capped a 20 entradas (oldest evicted) y al drenar descarta las que tengan `time` > 60s para no anexar eventos cuyo contexto ya no es relevante.
|
|
100
|
+
|
|
101
|
+
#### Menor
|
|
102
|
+
- `plugin.xml`: `<uses-permission android:name="android.hardware.location" />` → `<uses-feature android:name="android.hardware.location" android:required="false" />`. `android.hardware.location` es feature, no permiso.
|
|
103
|
+
- `www/BackgroundGeolocation.js`: removido comentario huérfano "1. new method isLocationEnabled" (no existe método).
|
|
104
|
+
|
|
105
|
+
#### Diseño
|
|
106
|
+
- Para evitar dependencia circular `common → cordova`, la serialización JSON del Config vive en una nueva clase `com.marianhello.bgloc.data.ConfigJsonMapper` (en `common/`). Tanto el SQLite DAO (common) como el `ConfigMapper` Cordova (cordova) pueden reusarla. **Registrada en `plugin.xml` como `<source-file>`** para que llegue al APK.
|
|
107
|
+
- `template` (postTemplate) se mantiene en su columna SQLite dedicada porque tiene serialización propia (`LocationTemplateFactory`). El DAO la rehidrata después de leer el JSON para no perderla.
|
|
108
|
+
- Strings con `Config.NullString` sentinel (cuando el usuario hace `configure({notificationTitle: null})`) sobreviven el round-trip via JSONObject.NULL.
|
|
109
|
+
|
|
110
|
+
#### Decisiones conscientes (no cambiadas en este patch)
|
|
111
|
+
- Eventos/batería NO sobreviven a la cola de sync. Documentado en 4.3.0/4.4.0. Cambiar el schema de `locations` rompería migraciones de apps existentes.
|
|
112
|
+
- Permisos runtime modernos (`ACCESS_BACKGROUND_LOCATION`, `ACTIVITY_RECOGNITION`) NO se piden automáticamente por el plugin — convención: la app controla el flujo. Posibles helpers `requestBackgroundLocationPermission()` / `requestActivityRecognitionPermission()` quedan para una v4.5.
|
|
113
|
+
- **iOS `MAURSQLiteConfigurationDAO`** tiene la misma limitación que tenía Android antes: solo persiste columnas heredadas de 3.2.0. Impacto práctico bajo en iOS porque Apple no permite auto-start al boot — la app siempre llama `configure()` al arrancar. Si más adelante se quiere paridad, se replicará el approach `config_json` de Android.
|
|
114
|
+
|
|
115
|
+
## [4.4.0](https://github.com/josuelmm/cordova-background-geolocation/tree/4.4.0) (2026-05-09)
|
|
116
|
+
|
|
117
|
+
### Added — Battery snapshot in every location payload
|
|
118
|
+
|
|
119
|
+
Cada `location` enviada al backend incluye automáticamente:
|
|
120
|
+
- `battery: number` (0-100, porcentaje)
|
|
121
|
+
- `isCharging: boolean`
|
|
122
|
+
|
|
123
|
+
Ejemplo:
|
|
124
|
+
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"latitude": 40.4168,
|
|
128
|
+
"longitude": -3.7038,
|
|
129
|
+
"time": 1730000000000,
|
|
130
|
+
"speed": 8.2,
|
|
131
|
+
"battery": 78,
|
|
132
|
+
"isCharging": false
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Configuración
|
|
137
|
+
- Default: **ON**.
|
|
138
|
+
- Opt-out: `configure({ includeBattery: false })`.
|
|
139
|
+
|
|
140
|
+
#### Templates custom
|
|
141
|
+
Si usas `postTemplate` / `bodyTemplate`, añade los placeholders `'@battery'` / `'@isCharging'`:
|
|
142
|
+
|
|
143
|
+
```js
|
|
144
|
+
bodyTemplate: {
|
|
145
|
+
deviceId: 'ABC',
|
|
146
|
+
lat: '@latitude',
|
|
147
|
+
lon: '@longitude',
|
|
148
|
+
bat: '@battery',
|
|
149
|
+
charging: '@isCharging'
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
#### Detalles técnicos
|
|
154
|
+
- Android: lectura instantánea via `Intent.ACTION_BATTERY_CHANGED` sticky broadcast (sin permisos extra). Stamp en `LocationServiceImpl.onLocation`.
|
|
155
|
+
- iOS: lectura via `UIDevice.batteryLevel` y `UIDevice.batteryState` (activa `batteryMonitoringEnabled` automáticamente). Stamp en `MAURBackgroundGeolocationFacade.onLocationChanged`.
|
|
156
|
+
- Reemplaza la dependencia de `cordova-plugin-battery-status` para apps que solo querían enviar la batería al backend con cada fix.
|
|
157
|
+
|
|
158
|
+
## [4.3.0](https://github.com/josuelmm/cordova-background-geolocation/tree/4.3.0) (2026-05-09)
|
|
159
|
+
|
|
160
|
+
### Added — Driving events anexados al payload de location
|
|
161
|
+
|
|
162
|
+
Cuando un driving event se dispara, ahora se anexa al location del momento como atributo `events: [...]` y viaja al backend en el mismo POST. La emisión por JS (`on('hardBrake', ...)`) sigue funcionando exactamente igual — esto solo añade el evento al payload.
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
{
|
|
166
|
+
"latitude": 40.4168,
|
|
167
|
+
"longitude": -3.7038,
|
|
168
|
+
"time": 1730000000000,
|
|
169
|
+
"speed": 8.2,
|
|
170
|
+
"events": [
|
|
171
|
+
{ "type": "hardBrake", "value": -4.1, "time": 1730000000000 }
|
|
172
|
+
]
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Tipos posibles: `moving`, `stopped`, `tripStart`, `tripEnd`, `speeding`, `providerChange`, `hardBrake`, `rapidAcceleration`, `sharpTurn`, `possibleCrash`, `phoneUsageWhileDriving`. Cada uno con su payload adicional (`value`, `distance`, `source`, etc.).
|
|
177
|
+
|
|
178
|
+
#### Detalles técnicos
|
|
179
|
+
- Android: nuevo campo `transient JSONArray drivingEvents` en `BackgroundLocation`. Helpers `addDrivingEvent`/`getDrivingEvents`/`clearDrivingEvents`. `toJSONObject()` lo incluye si está populado.
|
|
180
|
+
- iOS: nueva property `NSMutableArray *drivingEvents` en `MAURLocation`. `toDictionary` la incluye. `copyWithZone:` la copia.
|
|
181
|
+
- Buffer de "pending events" para eventos que disparan sin un fix simultáneo (sensor crash, phone usage, providerChange) — se drenan al próximo `onLocation`.
|
|
182
|
+
- Eventos GPS-derived (hardBrake, sharpTurn, etc.) se anexan en el mismo callback del detector, antes del broadcast a JS.
|
|
183
|
+
|
|
184
|
+
#### Caveat
|
|
185
|
+
Si el POST en real-time falla y la location entra a la cola de sync (SQLite/Core Data), el array `events` NO sobrevive — los eventos siguen emitiéndose por JS para que la app pueda postearlos por separado. La cola de sync solo guarda el formato GPS estándar (no se cambió el schema para preservar migraciones existentes).
|
|
186
|
+
|
|
187
|
+
Si usas `postTemplate`/`bodyTemplate` custom, los `events` no se incluyen automáticamente — el template solo serializa los keys que declara. Para incluirlos, añade `events: '@events'` (o el nombre que prefieras) a tu template:
|
|
188
|
+
|
|
189
|
+
```js
|
|
190
|
+
postTemplate: {
|
|
191
|
+
lat: '@latitude',
|
|
192
|
+
lon: '@longitude',
|
|
193
|
+
t: '@time',
|
|
194
|
+
events: '@events' // ← v4.3
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## [4.2.4](https://github.com/josuelmm/cordova-background-geolocation/tree/4.2.4) (2026-05-09)
|
|
199
|
+
|
|
200
|
+
### Fixed (CRÍTICO)
|
|
201
|
+
- **Foreground service no arrancaba en Android 14+** cuando la reflexión sobre `ServiceInfo.foregroundServiceType` fallaba o el manifest merged no incluía el atributo. Síntomas: sin notificación, sin tracking en background, sin envío de ubicaciones al minimizar/cerrar la app.
|
|
202
|
+
- `LocationServiceImpl.startForeground()`: si `getManifestForegroundServiceType()` devuelve `0`, ahora hace fallback a `0x00000008` (`FOREGROUND_SERVICE_TYPE_LOCATION`) con un `logger.warn` visible — antes retornaba silenciosamente y dejaba el servicio en background sin promover.
|
|
203
|
+
- `try/catch` defensivo alrededor de `super.startForeground(...)` con retry sin tipo si la primera llamada falla.
|
|
204
|
+
- El tipo se aplica desde API 30+ (antes solo desde 34); Android 12-13 (API 31-33) lo aceptan opcionalmente y mejora el comportamiento bajo Doze/restricciones.
|
|
205
|
+
|
|
3
206
|
## [4.2.3](https://github.com/josuelmm/cordova-background-geolocation/tree/4.2.3) (2026-05-09)
|
|
4
207
|
|
|
5
208
|
### Fixed
|
package/HISTORY.md
CHANGED
|
@@ -2,6 +2,73 @@
|
|
|
2
2
|
|
|
3
3
|
**for cordova-plugin-background-geolocation**
|
|
4
4
|
|
|
5
|
+
## [4.5.1] - 2026-05-09
|
|
6
|
+
|
|
7
|
+
### Fixed (blockers)
|
|
8
|
+
- Android compile: missing `import android.os.Build;` in BackgroundGeolocationPlugin.
|
|
9
|
+
- Android `SQLiteLocationDAO` UPDATE on `maxLocations` now writes `events_json`, `battery_level`, `is_charging` (with NULL when absent).
|
|
10
|
+
- iOS `MAURSQLiteLocationDAO` UPDATE on `persistLocation:limitRows:` now writes the same 3 columns.
|
|
11
|
+
|
|
12
|
+
### Added (battery optimization)
|
|
13
|
+
- `wakeLockMode: 'none' | 'posting' | 'always'`. Default `'posting'`. Replaces previous always-on wake lock.
|
|
14
|
+
- Watchdog only restarts provider when `tripActive` — no needless GPS wake-ups while stationary.
|
|
15
|
+
- Stationary detection knobs now configurable: `stationaryTimeout`, `stationaryPollInterval`, `stationaryPollFast`.
|
|
16
|
+
|
|
17
|
+
### Fixed (other)
|
|
18
|
+
- Internal Android manifest cleaned (`uses-feature` instead of bogus `uses-permission` for `android.hardware.location`).
|
|
19
|
+
- README and `.d.ts` no longer claim that `events` is lost in sync queue (false since 4.5.0).
|
|
20
|
+
- `.npmignore` no longer ships `CLAUDE.md`, internal tests, scripts.
|
|
21
|
+
|
|
22
|
+
### Plugin version: `4.5.1`.
|
|
23
|
+
|
|
24
|
+
## [4.5.0] - 2026-05-09
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- Persistir `events`, `battery`, `isCharging` en SQLite (Android v22 + iOS v6) — sobreviven cola de sync.
|
|
28
|
+
- iOS `config_json` (DB v7) — paridad con Android, persiste todas las keys post-3.2.0.
|
|
29
|
+
- Helpers JS de permisos runtime: `requestBackgroundLocationPermission`, `requestActivityRecognitionPermission`, `requestNotificationPermission`. iOS/Android viejos resuelven `notRequired: true`.
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
- iOS `MAURBackgroundSync`: borrar SQLite pendientes tras success (antes re-subía los mismos rows).
|
|
33
|
+
- Plugin version: `4.5.0`.
|
|
34
|
+
|
|
35
|
+
## [4.4.1] - 2026-05-09
|
|
36
|
+
|
|
37
|
+
### Fixed (stability)
|
|
38
|
+
- Android: persistencia de config completa via `config_json` TEXT (DB v21 migration). Soluciona pérdida de `httpMethod`, `queryParams`, `drivingEvents`, `includeBattery`, etc. tras reboot + startOnBoot.
|
|
39
|
+
- Android: `Config.merge()` ahora copia `includeBattery` (faltaba — `configure({includeBattery: false})` era ignorado).
|
|
40
|
+
- Android: `attachBatterySnapshot` usa `getApplicationContext().registerReceiver()` para evitar el override interno.
|
|
41
|
+
- Android: `<uses-permission android.hardware.location>` → `<uses-feature ... required="false">`.
|
|
42
|
+
- iOS: `MAURPostLocationTask` guard `outError == NULL`.
|
|
43
|
+
- Android+iOS: `pendingDrivingEvents` capped a 20 entradas, TTL 60s al drenar.
|
|
44
|
+
- JS: removido comentario huérfano `isLocationEnabled` (no existe método).
|
|
45
|
+
- Plugin version: `4.4.1`.
|
|
46
|
+
|
|
47
|
+
### Diseño
|
|
48
|
+
- Nueva `ConfigJsonMapper` en `common/` — serialización JSON reusable por DAO (common) y ConfigMapper (cordova) sin crear dependencia común→cordova.
|
|
49
|
+
|
|
50
|
+
## [4.4.0] - 2026-05-09
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
- Battery snapshot stamped on every location: `battery` (0-100) + `isCharging` (boolean).
|
|
54
|
+
- Default ON. Opt-out: `includeBattery: false`. Placeholders for templates: `'@battery'`, `'@isCharging'`.
|
|
55
|
+
- Android via `BatteryManager` sticky broadcast; iOS via `UIDevice.batteryLevel`. No extra permissions.
|
|
56
|
+
- Plugin version: `4.4.0`.
|
|
57
|
+
|
|
58
|
+
## [4.3.0] - 2026-05-09
|
|
59
|
+
|
|
60
|
+
### Added
|
|
61
|
+
- Driving events anexados al payload de location como `events: [{type, time, ...payload}]`. Se incluyen en el POST real-time al `url` configurado. La emisión vía `on(...)` JS sigue funcionando idéntico.
|
|
62
|
+
- Android: campo `drivingEvents` (transient) en `BackgroundLocation`; iOS: property en `MAURLocation`. Buffer de pending events para los que firan sin fix simultáneo.
|
|
63
|
+
- Caveat: si la location entra a cola de sync (SQLite), `events` no sobrevive. Los eventos siguen llegando por JS.
|
|
64
|
+
- Plugin version: `4.3.0`.
|
|
65
|
+
|
|
66
|
+
## [4.2.4] - 2026-05-09
|
|
67
|
+
|
|
68
|
+
### Fixed (CRITICAL)
|
|
69
|
+
- Foreground service silently aborted on Android 14+ when manifest reflection returned `0`. The plugin now falls back to `FOREGROUND_SERVICE_TYPE_LOCATION` (`0x8`) and retries without type if the typed call throws. Restores notification + background tracking on devices where the manifest merge did not pick up `foregroundServiceType="location"`.
|
|
70
|
+
- Plugin version: `4.2.4`.
|
|
71
|
+
|
|
5
72
|
## [4.2.3] - 2026-05-09
|
|
6
73
|
|
|
7
74
|
### Fixed
|
package/README.md
CHANGED
|
@@ -368,6 +368,48 @@ Subscribe with `BackgroundGeolocation.on(eventName, callback)`. Unsubscribe with
|
|
|
368
368
|
|
|
369
369
|
Full event payloads and options: [Events](docs/events.md). Full API (all options, all methods): [API](docs/api.md).
|
|
370
370
|
|
|
371
|
+
### New in 4.4.0
|
|
372
|
+
|
|
373
|
+
Cada location enviada al backend incluye `battery` (0-100) y `isCharging` automáticamente. Sin dependencias externas (no necesitas `cordova-plugin-battery-status`).
|
|
374
|
+
|
|
375
|
+
```json
|
|
376
|
+
{
|
|
377
|
+
"latitude": 40.4168, "longitude": -3.7038, "speed": 8.2,
|
|
378
|
+
"battery": 78, "isCharging": false
|
|
379
|
+
}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Default ON. Opt-out: `configure({ includeBattery: false })`. Con templates custom usa los placeholders `'@battery'` y `'@isCharging'`.
|
|
383
|
+
|
|
384
|
+
### New in 4.3.0
|
|
385
|
+
|
|
386
|
+
Driving events ahora se **anexan al location** que se envía al backend, en un atributo `events`:
|
|
387
|
+
|
|
388
|
+
```json
|
|
389
|
+
{
|
|
390
|
+
"latitude": 40.4168,
|
|
391
|
+
"longitude": -3.7038,
|
|
392
|
+
"time": 1730000000000,
|
|
393
|
+
"speed": 8.2,
|
|
394
|
+
"events": [
|
|
395
|
+
{ "type": "hardBrake", "value": -4.1, "time": 1730000000000 }
|
|
396
|
+
]
|
|
397
|
+
}
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
Tipos: `moving`, `stopped`, `tripStart`, `tripEnd`, `speeding`, `providerChange`, `hardBrake`, `rapidAcceleration`, `sharpTurn`, `possibleCrash`, `phoneUsageWhileDriving`. La emisión por JS sigue funcionando idéntica (no rompe Opción A).
|
|
401
|
+
|
|
402
|
+
Desde v4.5.0, `events`, `battery` e `isCharging` se persisten en la cola de sync (Android DB v22, iOS DB v7) y sobreviven a POST fallido → SQLite/Core Data → background sync.
|
|
403
|
+
|
|
404
|
+
Si usas `postTemplate`/`bodyTemplate` custom, añade el placeholder `'@events'` para incluirlos:
|
|
405
|
+
|
|
406
|
+
```js
|
|
407
|
+
postTemplate: {
|
|
408
|
+
lat: '@latitude', lon: '@longitude', t: '@time',
|
|
409
|
+
events: '@events'
|
|
410
|
+
}
|
|
411
|
+
```
|
|
412
|
+
|
|
371
413
|
### New in 4.2.2
|
|
372
414
|
|
|
373
415
|
- Build hotfixes — required when consuming the plugin via Capacitor (Gradle 8.x):
|
|
@@ -543,8 +585,11 @@ No extra wrapper (e.g. Awesome Cordova Plugins) is required.
|
|
|
543
585
|
| 2.x | ≥ 10.0.0 | ≥ 10.0.0 | ≥ 6.0.0 |
|
|
544
586
|
| 3.0.x – 3.2.x | ≥ 10.0.0 | ≥ 10.0.0 | ≥ 6.0.0 |
|
|
545
587
|
| 3.3.x – 4.1.x | ≥ 10.0.0 | ≥ 12.0.0 | ≥ 6.2.0 |
|
|
588
|
+
| 4.2.x – 4.5.x | ≥ 10.0.0 | ≥ 12.0.0 | ≥ 6.2.0 |
|
|
546
589
|
|
|
547
590
|
> 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
|
+
>
|
|
592
|
+
> 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.
|
|
548
593
|
|
|
549
594
|
---
|
|
550
595
|
|
|
@@ -586,80 +631,6 @@ furnished to do so, subject to the following conditions:
|
|
|
586
631
|
The above copyright notice and this permission notice shall be included in
|
|
587
632
|
all copies or substantial portions of the Software.
|
|
588
633
|
|
|
589
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
590
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
591
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
592
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
593
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
594
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
595
|
-
THE SOFTWARE.
|
|
596
|
-
return this.bg.on('location', (loc: BackgroundGeolocationResponse) => console.log(loc));
|
|
597
|
-
// subscription.unsubscribe() when done
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
**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.
|
|
603
|
-
|
|
604
|
-
**`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).
|
|
605
|
-
|
|
606
|
-
**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).
|
|
607
|
-
|
|
608
|
-
**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.
|
|
609
|
-
|
|
610
|
-
### Summary
|
|
611
|
-
|
|
612
|
-
| Use case | What to do |
|
|
613
|
-
|-----------------------|------------|
|
|
614
|
-
| **Without Angular** | Use global `BackgroundGeolocation` after `deviceready`. Types: main package or Awesome-style aliases (see [TypeScript imports](#typescript-imports) above). |
|
|
615
|
-
| **With Angular** | Import from `@josuelmm/cordova-background-geolocation/angular`: add `BackgroundGeolocationModule` to your module `imports`, then inject `BackgroundGeolocationService`. Do **not** inject the global `BackgroundGeolocation`. |
|
|
616
|
-
|
|
617
|
-
No extra wrapper (e.g. Awesome Cordova Plugins) is required.
|
|
618
|
-
|
|
619
|
-
---
|
|
620
|
-
|
|
621
|
-
## Compatibility
|
|
622
|
-
|
|
623
|
-
| Plugin version | Cordova CLI | Cordova Android | Cordova iOS |
|
|
624
|
-
|----------------|-------------|-----------------|-------------|
|
|
625
|
-
| 1.x | ≥ 8.0.0 | ≥ 8.0.0 | ≥ 6.0.0 |
|
|
626
|
-
| 2.x | ≥ 10.0.0 | ≥ 10.0.0 | ≥ 6.0.0 |
|
|
627
|
-
|
|
628
|
-
---
|
|
629
|
-
|
|
630
|
-
## Documentation and changelog
|
|
631
|
-
|
|
632
|
-
This README is the main entry point. For more detail, edge cases and examples use the docs below (and the [online documentation](https://josuelmm.github.io/cordova-background-geolocation/)).
|
|
633
|
-
|
|
634
|
-
| Doc | What you’ll find |
|
|
635
|
-
|-----|------------------|
|
|
636
|
-
| **[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. |
|
|
637
|
-
| **[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. |
|
|
638
|
-
| **[Events](docs/events.md)** | All events (`location`, `error`, `stationary`, `activity`, `http_authorization`, etc.) and payloads. |
|
|
639
|
-
| **[Angular / Ionic](docs/angular.md)** | Injectable service, module, lazy-loaded modules and token “must be defined”, `ng serve` / browser build. |
|
|
640
|
-
| **[Example](docs/example.md)** | Full example with events and sync. |
|
|
641
|
-
| **[CHANGELOG](CHANGELOG.md)** | Version history. |
|
|
642
|
-
|
|
643
|
-
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.
|
|
644
|
-
|
|
645
|
-
---
|
|
646
|
-
|
|
647
|
-
## Licence
|
|
648
|
-
|
|
649
|
-
[Apache License](http://www.apache.org/licenses/LICENSE-2.0)
|
|
650
|
-
|
|
651
|
-
Copyright (c) 2013 Christopher Scott, Transistor Software
|
|
652
|
-
|
|
653
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
654
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
655
|
-
in the Software without restriction, including without limitation the rights
|
|
656
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
657
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
658
|
-
furnished to do so, subject to the following conditions:
|
|
659
|
-
|
|
660
|
-
The above copyright notice and this permission notice shall be included in
|
|
661
|
-
all copies or substantial portions of the Software.
|
|
662
|
-
|
|
663
634
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
664
635
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
665
636
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
@@ -181,6 +181,23 @@ public class ConfigMapper {
|
|
|
181
181
|
if (jObject.has("showDistance")) {
|
|
182
182
|
config.setShowDistance(jObject.getBoolean("showDistance"));
|
|
183
183
|
}
|
|
184
|
+
// v4.4: opt-out for battery snapshot in payload.
|
|
185
|
+
if (jObject.has("includeBattery")) {
|
|
186
|
+
config.setIncludeBattery(jObject.getBoolean("includeBattery"));
|
|
187
|
+
}
|
|
188
|
+
// v4.5.1: battery-saving knobs.
|
|
189
|
+
if (jObject.has("wakeLockMode") && !jObject.isNull("wakeLockMode")) {
|
|
190
|
+
config.setWakeLockMode(jObject.getString("wakeLockMode"));
|
|
191
|
+
}
|
|
192
|
+
if (jObject.has("stationaryTimeout") && !jObject.isNull("stationaryTimeout")) {
|
|
193
|
+
config.setStationaryTimeout(jObject.getInt("stationaryTimeout"));
|
|
194
|
+
}
|
|
195
|
+
if (jObject.has("stationaryPollInterval") && !jObject.isNull("stationaryPollInterval")) {
|
|
196
|
+
config.setStationaryPollInterval(jObject.getInt("stationaryPollInterval"));
|
|
197
|
+
}
|
|
198
|
+
if (jObject.has("stationaryPollFast") && !jObject.isNull("stationaryPollFast")) {
|
|
199
|
+
config.setStationaryPollFast(jObject.getInt("stationaryPollFast"));
|
|
200
|
+
}
|
|
184
201
|
|
|
185
202
|
return config;
|
|
186
203
|
}
|
|
@@ -264,6 +281,13 @@ public class ConfigMapper {
|
|
|
264
281
|
deJson.put("phoneUsageCooldownMs", de.phoneUsageCooldownMs);
|
|
265
282
|
json.put("drivingEvents", deJson);
|
|
266
283
|
}
|
|
284
|
+
// v4.4 battery
|
|
285
|
+
json.put("includeBattery", config.getIncludeBattery() != null ? config.getIncludeBattery() : true);
|
|
286
|
+
// v4.5.1 battery-saving knobs
|
|
287
|
+
json.put("wakeLockMode", config.getWakeLockMode() != null ? config.getWakeLockMode() : "posting");
|
|
288
|
+
json.put("stationaryTimeout", config.getStationaryTimeout());
|
|
289
|
+
json.put("stationaryPollInterval", config.getStationaryPollInterval());
|
|
290
|
+
json.put("stationaryPollFast", config.getStationaryPollFast());
|
|
267
291
|
|
|
268
292
|
return json;
|
|
269
293
|
}
|
|
@@ -14,6 +14,7 @@ package com.tenforwardconsulting.bgloc.cordova;
|
|
|
14
14
|
import android.app.Activity;
|
|
15
15
|
import android.app.Application;
|
|
16
16
|
import android.content.Context;
|
|
17
|
+
import android.os.Build;
|
|
17
18
|
|
|
18
19
|
import com.marianhello.bgloc.BackgroundGeolocationFacade;
|
|
19
20
|
import com.marianhello.bgloc.Config;
|
|
@@ -87,9 +88,15 @@ public class BackgroundGeolocationPlugin extends CordovaPlugin implements Plugin
|
|
|
87
88
|
public static final String ACTION_OPEN_AUTOSTART_SETTINGS = "openAutoStartSettings";
|
|
88
89
|
public static final String ACTION_GET_MANUFACTURER_HELP = "getManufacturerHelp";
|
|
89
90
|
public static final String ACTION_TRIGGER_SOS = "triggerSOS";
|
|
91
|
+
// v4.5: runtime permission helpers — opt-in. The app drives the flow; the plugin
|
|
92
|
+
// simply asks the OS dialog (or returns the current state on iOS where Apple does
|
|
93
|
+
// not surface separate runtime gates for background location / activity recognition).
|
|
94
|
+
public static final String ACTION_REQUEST_BACKGROUND_PERMISSION = "requestBackgroundLocationPermission";
|
|
95
|
+
public static final String ACTION_REQUEST_ACTIVITY_PERMISSION = "requestActivityRecognitionPermission";
|
|
96
|
+
public static final String ACTION_REQUEST_NOTIFICATION_PERMISSION = "requestNotificationPermission";
|
|
90
97
|
|
|
91
98
|
/** Plugin version; keep in sync with plugin.xml. */
|
|
92
|
-
public static final String PLUGIN_VERSION = "4.
|
|
99
|
+
public static final String PLUGIN_VERSION = "4.5.1";
|
|
93
100
|
|
|
94
101
|
private BackgroundGeolocationFacade facade;
|
|
95
102
|
|
|
@@ -507,11 +514,64 @@ public class BackgroundGeolocationPlugin extends CordovaPlugin implements Plugin
|
|
|
507
514
|
callbackContext.sendPluginResult(ErrorPluginResult.from("triggerSOS failed", e, PluginException.SERVICE_ERROR));
|
|
508
515
|
}
|
|
509
516
|
return true;
|
|
517
|
+
} else if (ACTION_REQUEST_BACKGROUND_PERMISSION.equals(action)) {
|
|
518
|
+
// Android 10+ (API 29+). Returns {granted: bool}.
|
|
519
|
+
return requestPermissionAction(callbackContext,
|
|
520
|
+
Build.VERSION.SDK_INT >= 29 ? android.Manifest.permission.ACCESS_BACKGROUND_LOCATION : android.Manifest.permission.ACCESS_FINE_LOCATION);
|
|
521
|
+
} else if (ACTION_REQUEST_ACTIVITY_PERMISSION.equals(action)) {
|
|
522
|
+
// Android 10+ (API 29+) needs runtime grant for activity recognition.
|
|
523
|
+
return requestPermissionAction(callbackContext,
|
|
524
|
+
Build.VERSION.SDK_INT >= 29 ? "android.permission.ACTIVITY_RECOGNITION" : null);
|
|
525
|
+
} else if (ACTION_REQUEST_NOTIFICATION_PERMISSION.equals(action)) {
|
|
526
|
+
// Android 13+ (API 33+) requires POST_NOTIFICATIONS at runtime.
|
|
527
|
+
return requestPermissionAction(callbackContext,
|
|
528
|
+
Build.VERSION.SDK_INT >= 33 ? "android.permission.POST_NOTIFICATIONS" : null);
|
|
510
529
|
}
|
|
511
530
|
|
|
512
531
|
return false;
|
|
513
532
|
}
|
|
514
533
|
|
|
534
|
+
/** v4.5: shared helper — request a single runtime permission via PermissionManager.
|
|
535
|
+
* Returns {granted: true} if already granted (or unsupported on this OS version).
|
|
536
|
+
* Returns {granted: false, denied: [name]} if user denies.
|
|
537
|
+
*/
|
|
538
|
+
private boolean requestPermissionAction(final CallbackContext cb, final String permission) {
|
|
539
|
+
if (permission == null) {
|
|
540
|
+
// OS version where this permission does not exist: act as already granted.
|
|
541
|
+
try {
|
|
542
|
+
JSONObject r = new JSONObject();
|
|
543
|
+
r.put("granted", true);
|
|
544
|
+
r.put("notRequired", true);
|
|
545
|
+
cb.success(r);
|
|
546
|
+
} catch (JSONException e) { cb.success(); }
|
|
547
|
+
return true;
|
|
548
|
+
}
|
|
549
|
+
Context ctx = cordova.getActivity().getApplicationContext();
|
|
550
|
+
if (hasPermission(ctx, permission)) {
|
|
551
|
+
try { JSONObject r = new JSONObject(); r.put("granted", true); cb.success(r); }
|
|
552
|
+
catch (JSONException e) { cb.success(); }
|
|
553
|
+
return true;
|
|
554
|
+
}
|
|
555
|
+
com.intentfilter.androidpermissions.PermissionManager pm =
|
|
556
|
+
com.intentfilter.androidpermissions.PermissionManager.getInstance(ctx);
|
|
557
|
+
pm.checkPermissions(java.util.Arrays.asList(permission),
|
|
558
|
+
new com.intentfilter.androidpermissions.PermissionManager.PermissionRequestListener() {
|
|
559
|
+
@Override public void onPermissionGranted() {
|
|
560
|
+
try { JSONObject r = new JSONObject(); r.put("granted", true); cb.success(r); }
|
|
561
|
+
catch (JSONException e) { cb.success(); }
|
|
562
|
+
}
|
|
563
|
+
@Override public void onPermissionDenied(com.intentfilter.androidpermissions.models.DeniedPermissions deniedPermissions) {
|
|
564
|
+
try {
|
|
565
|
+
JSONObject r = new JSONObject();
|
|
566
|
+
r.put("granted", false);
|
|
567
|
+
r.put("denied", new org.json.JSONArray().put(permission));
|
|
568
|
+
cb.success(r);
|
|
569
|
+
} catch (JSONException e) { cb.success(); }
|
|
570
|
+
}
|
|
571
|
+
});
|
|
572
|
+
return true;
|
|
573
|
+
}
|
|
574
|
+
|
|
515
575
|
/** v3.5 Phase 4: extended diagnostics. */
|
|
516
576
|
private JSONObject buildDiagnostics() throws JSONException {
|
|
517
577
|
JSONObject d = new JSONObject();
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
<uses-library android:name="org.apache.http.legacy" android:required="true" />
|
|
59
59
|
</application>
|
|
60
60
|
|
|
61
|
-
<uses-
|
|
61
|
+
<uses-feature android:name="android.hardware.location" android:required="false" />
|
|
62
62
|
<uses-permission android:name="android.permission.INTERNET"/>
|
|
63
63
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
|
64
64
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
|
@@ -17,6 +17,8 @@ import android.content.pm.PackageManager;
|
|
|
17
17
|
import android.os.Build;
|
|
18
18
|
import android.util.Log;
|
|
19
19
|
|
|
20
|
+
import androidx.core.content.ContextCompat;
|
|
21
|
+
|
|
20
22
|
import com.marianhello.bgloc.data.ConfigurationDAO;
|
|
21
23
|
import com.marianhello.bgloc.data.DAOFactory;
|
|
22
24
|
import com.marianhello.bgloc.service.LocationServiceImpl;
|
|
@@ -76,11 +78,12 @@ public class BootCompletedReceiver extends BroadcastReceiver {
|
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
private static boolean hasLocationPermission(Context context) {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
+
// v4.5.1 — ContextCompat handles API < 23 (always granted at install time).
|
|
82
|
+
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|
|
83
|
+
|| ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
private static boolean hasBackgroundLocationPermission(Context context) {
|
|
84
|
-
return
|
|
87
|
+
return ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED;
|
|
85
88
|
}
|
|
86
89
|
}
|