@josuelmm/cordova-background-geolocation 4.2.2 → 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 +213 -0
- package/HISTORY.md +73 -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/PostLocationTask.java +1 -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 +36 -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
|
@@ -83,6 +83,17 @@ public class Config implements Parcelable
|
|
|
83
83
|
private String mockLocationPolicy; // allow | flag | drop (default allow)
|
|
84
84
|
// v4.0 (Phase 6): driver insights
|
|
85
85
|
private DrivingEventsOptions drivingEvents;
|
|
86
|
+
// v4.4: include device battery in every location payload (default true).
|
|
87
|
+
private Boolean includeBattery;
|
|
88
|
+
// v4.5.1: battery-saving knobs.
|
|
89
|
+
/** WakeLock policy: 'none' | 'posting' | 'always'. Default 'posting'. */
|
|
90
|
+
private String wakeLockMode;
|
|
91
|
+
/** ms before declaring stationary. DistanceFilterLocationProvider default 5*60_000. */
|
|
92
|
+
private Integer stationaryTimeout;
|
|
93
|
+
/** Lazy poll interval while stationary (ms). Default 3*60_000. */
|
|
94
|
+
private Integer stationaryPollInterval;
|
|
95
|
+
/** Aggressive poll interval while stationary (ms). Default 60_000. */
|
|
96
|
+
private Integer stationaryPollFast;
|
|
86
97
|
|
|
87
98
|
/** v4.0 Phase 6 + v4.1: driver-insights configuration. Plain holder; no Parcelable to keep this class diff small. */
|
|
88
99
|
public static class DrivingEventsOptions {
|
|
@@ -149,6 +160,11 @@ public class Config implements Parcelable
|
|
|
149
160
|
this.queryParams = CloneHelper.deepCopy(config.queryParams);
|
|
150
161
|
this.heartbeatInterval = config.heartbeatInterval;
|
|
151
162
|
this.mockLocationPolicy = config.mockLocationPolicy;
|
|
163
|
+
this.includeBattery = config.includeBattery;
|
|
164
|
+
this.wakeLockMode = config.wakeLockMode;
|
|
165
|
+
this.stationaryTimeout = config.stationaryTimeout;
|
|
166
|
+
this.stationaryPollInterval = config.stationaryPollInterval;
|
|
167
|
+
this.stationaryPollFast = config.stationaryPollFast;
|
|
152
168
|
if (config.drivingEvents != null) {
|
|
153
169
|
DrivingEventsOptions de = new DrivingEventsOptions();
|
|
154
170
|
de.enabled = config.drivingEvents.enabled;
|
|
@@ -251,7 +267,16 @@ public class Config implements Parcelable
|
|
|
251
267
|
de.phoneUsageCooldownMs = dePhoneUsageCooldown;
|
|
252
268
|
this.drivingEvents = de;
|
|
253
269
|
}
|
|
254
|
-
|
|
270
|
+
// v4.4: includeBattery
|
|
271
|
+
setIncludeBattery((Boolean) in.readValue(null));
|
|
272
|
+
// v4.5.1: battery-saving knobs
|
|
273
|
+
setWakeLockMode(in.readString());
|
|
274
|
+
setStationaryTimeout((Integer) in.readValue(null));
|
|
275
|
+
setStationaryPollInterval((Integer) in.readValue(null));
|
|
276
|
+
setStationaryPollFast((Integer) in.readValue(null));
|
|
277
|
+
// v4.5.1 — pass the plugin's classloader so getSerializable() can deserialize
|
|
278
|
+
// LocationTemplate / HashMap subclasses across IPC boundaries (e.g. SyncService :sync process).
|
|
279
|
+
Bundle bundle = in.readBundle(Config.class.getClassLoader());
|
|
255
280
|
setHttpHeaders((HashMap<String, String>) bundle.getSerializable("httpHeaders"));
|
|
256
281
|
setQueryParams((HashMap<String, String>) bundle.getSerializable("queryParams"));
|
|
257
282
|
setTemplate((LocationTemplate) bundle.getSerializable(AbstractLocationTemplate.BUNDLE_KEY));
|
|
@@ -298,6 +323,11 @@ public class Config implements Parcelable
|
|
|
298
323
|
config.queryParams = null;
|
|
299
324
|
config.heartbeatInterval = 0;
|
|
300
325
|
config.mockLocationPolicy = "allow";
|
|
326
|
+
config.includeBattery = true; // v4.4: on by default
|
|
327
|
+
config.wakeLockMode = "posting"; // v4.5.1: hold wake lock only while posting/syncing
|
|
328
|
+
config.stationaryTimeout = 5 * 60 * 1000;
|
|
329
|
+
config.stationaryPollInterval = 3 * 60 * 1000;
|
|
330
|
+
config.stationaryPollFast = 60 * 1000;
|
|
301
331
|
|
|
302
332
|
return config;
|
|
303
333
|
}
|
|
@@ -365,6 +395,13 @@ public class Config implements Parcelable
|
|
|
365
395
|
out.writeLong (de != null ? de.phoneUsageWindowMs : 4_000L);
|
|
366
396
|
out.writeLong (de != null ? de.phoneUsageCooldownMs : 60_000L);
|
|
367
397
|
out.writeInt (de != null ? 1 : 0);
|
|
398
|
+
// v4.4: includeBattery
|
|
399
|
+
out.writeValue(getIncludeBattery());
|
|
400
|
+
// v4.5.1
|
|
401
|
+
out.writeString(getWakeLockMode());
|
|
402
|
+
out.writeValue(getStationaryTimeout());
|
|
403
|
+
out.writeValue(getStationaryPollInterval());
|
|
404
|
+
out.writeValue(getStationaryPollFast());
|
|
368
405
|
Bundle bundle = new Bundle();
|
|
369
406
|
bundle.putSerializable("httpHeaders", getHttpHeaders());
|
|
370
407
|
bundle.putSerializable("queryParams", getQueryParams());
|
|
@@ -762,6 +799,24 @@ public class Config implements Parcelable
|
|
|
762
799
|
this.enableWatchdog = enableWatchdog;
|
|
763
800
|
}
|
|
764
801
|
|
|
802
|
+
@Nullable
|
|
803
|
+
public Boolean getIncludeBattery() {
|
|
804
|
+
return includeBattery;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
public void setIncludeBattery(Boolean includeBattery) {
|
|
808
|
+
this.includeBattery = includeBattery;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
@Nullable public String getWakeLockMode() { return wakeLockMode; }
|
|
812
|
+
public void setWakeLockMode(String mode) { this.wakeLockMode = mode; }
|
|
813
|
+
@Nullable public Integer getStationaryTimeout() { return stationaryTimeout; }
|
|
814
|
+
public void setStationaryTimeout(Integer ms) { this.stationaryTimeout = ms; }
|
|
815
|
+
@Nullable public Integer getStationaryPollInterval() { return stationaryPollInterval; }
|
|
816
|
+
public void setStationaryPollInterval(Integer ms) { this.stationaryPollInterval = ms; }
|
|
817
|
+
@Nullable public Integer getStationaryPollFast() { return stationaryPollFast; }
|
|
818
|
+
public void setStationaryPollFast(Integer ms) { this.stationaryPollFast = ms; }
|
|
819
|
+
|
|
765
820
|
public boolean hasShowTime() {
|
|
766
821
|
return showTime != null;
|
|
767
822
|
}
|
|
@@ -1056,6 +1111,15 @@ public class Config implements Parcelable
|
|
|
1056
1111
|
if (config2.drivingEvents != null) {
|
|
1057
1112
|
merger.setDrivingEvents(config2.drivingEvents);
|
|
1058
1113
|
}
|
|
1114
|
+
// v4.4.1 — was missing: configure({includeBattery: false}) was being ignored.
|
|
1115
|
+
if (config2.includeBattery != null) {
|
|
1116
|
+
merger.setIncludeBattery(config2.getIncludeBattery());
|
|
1117
|
+
}
|
|
1118
|
+
// v4.5.1 — battery-saving knobs.
|
|
1119
|
+
if (config2.wakeLockMode != null) merger.setWakeLockMode(config2.wakeLockMode);
|
|
1120
|
+
if (config2.stationaryTimeout != null) merger.setStationaryTimeout(config2.stationaryTimeout);
|
|
1121
|
+
if (config2.stationaryPollInterval != null) merger.setStationaryPollInterval(config2.stationaryPollInterval);
|
|
1122
|
+
if (config2.stationaryPollFast != null) merger.setStationaryPollFast(config2.stationaryPollFast);
|
|
1059
1123
|
|
|
1060
1124
|
return merger;
|
|
1061
1125
|
}
|
|
@@ -189,7 +189,7 @@ public class PostLocationTask {
|
|
|
189
189
|
String method = mConfig.getHttpMethod();
|
|
190
190
|
String mode = mConfig.getHttpMode();
|
|
191
191
|
logger.debug("Posting to url: {} method: {} mode: {} headers: {}",
|
|
192
|
-
resolvedUrl, method, mConfig.getHttpHeaders());
|
|
192
|
+
resolvedUrl, method, mode, mConfig.getHttpHeaders());
|
|
193
193
|
int responseCode;
|
|
194
194
|
|
|
195
195
|
try {
|
|
@@ -11,6 +11,7 @@ import androidx.core.util.TimeUtils;
|
|
|
11
11
|
|
|
12
12
|
import com.marianhello.bgloc.data.sqlite.SQLiteLocationContract.LocationEntry;
|
|
13
13
|
|
|
14
|
+
import org.json.JSONArray;
|
|
14
15
|
import org.json.JSONException;
|
|
15
16
|
import org.json.JSONObject;
|
|
16
17
|
|
|
@@ -43,6 +44,20 @@ public class BackgroundLocation implements Parcelable {
|
|
|
43
44
|
private int status = POST_PENDING;
|
|
44
45
|
private Bundle extras = null;
|
|
45
46
|
|
|
47
|
+
/**
|
|
48
|
+
* v4.3 — Driving events anexados al fix actual.
|
|
49
|
+
* v4.5: ahora se persiste en SQLite (events_json TEXT) y se propaga vía Parcel para
|
|
50
|
+
* sobrevivir a la cola de sync. Si el POST en real-time falla, los eventos llegan al
|
|
51
|
+
* backend cuando la location se sincroniza más tarde.
|
|
52
|
+
*/
|
|
53
|
+
private JSONArray drivingEvents;
|
|
54
|
+
|
|
55
|
+
/** v4.4 — Device battery percentage (0-100) at the time of this fix, or null if unknown
|
|
56
|
+
* or {@code includeBattery} is disabled. v4.5: persisted in SQLite + Parcel. */
|
|
57
|
+
private Integer batteryLevel;
|
|
58
|
+
/** v4.4 — Whether the device is charging at the time of this fix. v4.5: persisted. */
|
|
59
|
+
private Boolean isCharging;
|
|
60
|
+
|
|
46
61
|
private static final long TWO_MINUTES_IN_NANOS = 1000000000L * 60 * 2;
|
|
47
62
|
|
|
48
63
|
public BackgroundLocation() {}
|
|
@@ -106,6 +121,12 @@ public class BackgroundLocation implements Parcelable {
|
|
|
106
121
|
mockFlags = l.mockFlags;
|
|
107
122
|
status = l.status;
|
|
108
123
|
extras = (l.extras == null) ? null : new Bundle(l.extras);
|
|
124
|
+
// v4.5: copy v4.3+ persisted fields
|
|
125
|
+
if (l.drivingEvents != null) {
|
|
126
|
+
try { drivingEvents = new JSONArray(l.drivingEvents.toString()); } catch (JSONException ignored) {}
|
|
127
|
+
}
|
|
128
|
+
batteryLevel = l.batteryLevel;
|
|
129
|
+
isCharging = l.isCharging;
|
|
109
130
|
}
|
|
110
131
|
|
|
111
132
|
private static BackgroundLocation fromParcel(Parcel in) {
|
|
@@ -134,6 +155,13 @@ public class BackgroundLocation implements Parcelable {
|
|
|
134
155
|
l.mockFlags = in.readInt();
|
|
135
156
|
l.status = in.readInt();
|
|
136
157
|
l.extras = in.readBundle();
|
|
158
|
+
// v4.5: read driving events / battery / charging
|
|
159
|
+
String evJson = in.readString();
|
|
160
|
+
if (evJson != null) {
|
|
161
|
+
try { l.drivingEvents = new JSONArray(evJson); } catch (JSONException ignored) {}
|
|
162
|
+
}
|
|
163
|
+
l.batteryLevel = (Integer) in.readValue(null);
|
|
164
|
+
l.isCharging = (Boolean) in.readValue(null);
|
|
137
165
|
|
|
138
166
|
return l;
|
|
139
167
|
}
|
|
@@ -205,6 +233,18 @@ public class BackgroundLocation implements Parcelable {
|
|
|
205
233
|
l.setStatus(c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_STATUS)));
|
|
206
234
|
l.setLocationId(c.getLong(c.getColumnIndex(LocationEntry._ID)));
|
|
207
235
|
l.setMockFlags(c.getInt((c.getColumnIndex(LocationEntry.COLUMN_NAME_MOCK_FLAGS))));
|
|
236
|
+
// v4.5: events / battery / charging — guarded for DBs that may have NULL after migration.
|
|
237
|
+
int idxEv = c.getColumnIndex(LocationEntry.COLUMN_NAME_EVENTS_JSON);
|
|
238
|
+
if (idxEv >= 0 && !c.isNull(idxEv)) {
|
|
239
|
+
String s = c.getString(idxEv);
|
|
240
|
+
if (s != null && !s.isEmpty()) {
|
|
241
|
+
try { l.drivingEvents = new JSONArray(s); } catch (JSONException ignored) {}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
int idxBat = c.getColumnIndex(LocationEntry.COLUMN_NAME_BATTERY_LEVEL);
|
|
245
|
+
if (idxBat >= 0 && !c.isNull(idxBat)) l.batteryLevel = c.getInt(idxBat);
|
|
246
|
+
int idxChg = c.getColumnIndex(LocationEntry.COLUMN_NAME_IS_CHARGING);
|
|
247
|
+
if (idxChg >= 0 && !c.isNull(idxChg)) l.isCharging = (c.getInt(idxChg) == 1);
|
|
208
248
|
|
|
209
249
|
return l;
|
|
210
250
|
}
|
|
@@ -239,6 +279,10 @@ public class BackgroundLocation implements Parcelable {
|
|
|
239
279
|
dest.writeInt(mockFlags);
|
|
240
280
|
dest.writeInt(status);
|
|
241
281
|
dest.writeBundle(extras);
|
|
282
|
+
// v4.5: persist driving events / battery / charging through Parcel.
|
|
283
|
+
dest.writeString(drivingEvents != null ? drivingEvents.toString() : null);
|
|
284
|
+
dest.writeValue(batteryLevel);
|
|
285
|
+
dest.writeValue(isCharging);
|
|
242
286
|
}
|
|
243
287
|
|
|
244
288
|
public static final Parcelable.Creator<BackgroundLocation> CREATOR
|
|
@@ -899,10 +943,37 @@ public class BackgroundLocation implements Parcelable {
|
|
|
899
943
|
if (hasRadius) json.put("radius", radius);
|
|
900
944
|
if (hasIsFromMockProvider()) json.put("isFromMockProvider", isFromMockProvider());
|
|
901
945
|
if (hasMockLocationsEnabled()) json.put("mockLocationsEnabled", areMockLocationsEnabled());
|
|
946
|
+
// v4.3: driving events anexados a este fix (si los hay).
|
|
947
|
+
if (drivingEvents != null && drivingEvents.length() > 0) {
|
|
948
|
+
json.put("events", drivingEvents);
|
|
949
|
+
}
|
|
950
|
+
// v4.4: device battery snapshot.
|
|
951
|
+
if (batteryLevel != null) json.put("battery", batteryLevel);
|
|
952
|
+
if (isCharging != null) json.put("isCharging", isCharging);
|
|
902
953
|
|
|
903
954
|
return json;
|
|
904
955
|
}
|
|
905
956
|
|
|
957
|
+
// v4.3 — driving event helpers
|
|
958
|
+
/** Append a driving event to this location. The event survives only until the next
|
|
959
|
+
* serialization in real-time POST. NOT persisted in SQLite. */
|
|
960
|
+
public void addDrivingEvent(JSONObject event) {
|
|
961
|
+
if (event == null) return;
|
|
962
|
+
if (drivingEvents == null) drivingEvents = new JSONArray();
|
|
963
|
+
drivingEvents.put(event);
|
|
964
|
+
}
|
|
965
|
+
public JSONArray getDrivingEvents() { return drivingEvents; }
|
|
966
|
+
public boolean hasDrivingEvents() { return drivingEvents != null && drivingEvents.length() > 0; }
|
|
967
|
+
public void clearDrivingEvents() { drivingEvents = null; }
|
|
968
|
+
/** v4.5: bulk setter used by SQLite hydration to restore the persisted events array. */
|
|
969
|
+
public void setDrivingEvents(JSONArray events) { this.drivingEvents = events; }
|
|
970
|
+
|
|
971
|
+
// v4.4 — battery helpers
|
|
972
|
+
public void setBatteryLevel(Integer level) { this.batteryLevel = level; }
|
|
973
|
+
public Integer getBatteryLevel() { return batteryLevel; }
|
|
974
|
+
public void setCharging(Boolean charging) { this.isCharging = charging; }
|
|
975
|
+
public Boolean isCharging() { return isCharging; }
|
|
976
|
+
|
|
906
977
|
/**
|
|
907
978
|
* Returns location as JSON object containing location id
|
|
908
979
|
* Note: Location id is not unique and is usually being recycled when
|
|
@@ -942,6 +1013,18 @@ public class BackgroundLocation implements Parcelable {
|
|
|
942
1013
|
values.put(LocationEntry.COLUMN_NAME_STATUS, status);
|
|
943
1014
|
values.put(LocationEntry.COLUMN_NAME_BATCH_START_MILLIS, batchStartMillis);
|
|
944
1015
|
values.put(LocationEntry.COLUMN_NAME_MOCK_FLAGS, mockFlags);
|
|
1016
|
+
// v4.5.1 — always write these columns (with NULL when absent) so that recycled rows
|
|
1017
|
+
// in ContentProviderLocationDAO's max-rows UPDATE path do not inherit stale events,
|
|
1018
|
+
// battery or charging state from the location previously stored at that _id.
|
|
1019
|
+
if (drivingEvents != null && drivingEvents.length() > 0) {
|
|
1020
|
+
values.put(LocationEntry.COLUMN_NAME_EVENTS_JSON, drivingEvents.toString());
|
|
1021
|
+
} else {
|
|
1022
|
+
values.putNull(LocationEntry.COLUMN_NAME_EVENTS_JSON);
|
|
1023
|
+
}
|
|
1024
|
+
if (batteryLevel != null) values.put(LocationEntry.COLUMN_NAME_BATTERY_LEVEL, batteryLevel);
|
|
1025
|
+
else values.putNull(LocationEntry.COLUMN_NAME_BATTERY_LEVEL);
|
|
1026
|
+
if (isCharging != null) values.put(LocationEntry.COLUMN_NAME_IS_CHARGING, isCharging ? 1 : 0);
|
|
1027
|
+
else values.putNull(LocationEntry.COLUMN_NAME_IS_CHARGING);
|
|
945
1028
|
return values;
|
|
946
1029
|
}
|
|
947
1030
|
|
|
@@ -988,6 +1071,17 @@ public class BackgroundLocation implements Parcelable {
|
|
|
988
1071
|
if ("@mockLocationsEnabled".equals(key)) {
|
|
989
1072
|
return hasMockLocationsEnabled() ? areMockLocationsEnabled() : JSONObject.NULL;
|
|
990
1073
|
}
|
|
1074
|
+
// v4.3 — driving events array (only present if events were attached during this fix).
|
|
1075
|
+
if ("@events".equals(key)) {
|
|
1076
|
+
return drivingEvents != null ? drivingEvents : JSONObject.NULL;
|
|
1077
|
+
}
|
|
1078
|
+
// v4.4 — battery snapshot
|
|
1079
|
+
if ("@battery".equals(key)) {
|
|
1080
|
+
return batteryLevel != null ? batteryLevel : JSONObject.NULL;
|
|
1081
|
+
}
|
|
1082
|
+
if ("@isCharging".equals(key)) {
|
|
1083
|
+
return isCharging != null ? isCharging : JSONObject.NULL;
|
|
1084
|
+
}
|
|
991
1085
|
|
|
992
1086
|
return null;
|
|
993
1087
|
}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
package com.marianhello.bgloc.data;
|
|
2
|
+
|
|
3
|
+
import com.marianhello.bgloc.Config;
|
|
4
|
+
|
|
5
|
+
import org.json.JSONException;
|
|
6
|
+
import org.json.JSONObject;
|
|
7
|
+
|
|
8
|
+
import java.util.HashMap;
|
|
9
|
+
import java.util.Iterator;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* v4.4.1 — JSON serializer/deserializer for the full {@link Config} state.
|
|
13
|
+
*
|
|
14
|
+
* Lives in {@code common} so both the SQLite DAO (also common) and the Cordova
|
|
15
|
+
* {@code ConfigMapper} (cordova) can reuse it without creating a common→cordova
|
|
16
|
+
* dependency. Used to persist a single {@code config_json} TEXT column instead of
|
|
17
|
+
* adding one schema column per new field on every release.
|
|
18
|
+
*
|
|
19
|
+
* Round-trip: every JS-configurable key the plugin understands is preserved.
|
|
20
|
+
* Anything not present in the input JSON keeps the {@link Config} default.
|
|
21
|
+
*/
|
|
22
|
+
public final class ConfigJsonMapper {
|
|
23
|
+
|
|
24
|
+
private ConfigJsonMapper() {}
|
|
25
|
+
|
|
26
|
+
/** Serialize the current Config state to a JSONObject suitable for storage.
|
|
27
|
+
* String fields use {@link JSONObject#NULL} when the user explicitly cleared them
|
|
28
|
+
* (i.e. equals {@link Config#NullString}) so the sentinel survives the round-trip. */
|
|
29
|
+
public static JSONObject toJSONObject(Config c) throws JSONException {
|
|
30
|
+
JSONObject j = new JSONObject();
|
|
31
|
+
if (c == null) return j;
|
|
32
|
+
j.put("stationaryRadius", c.getStationaryRadius());
|
|
33
|
+
j.put("distanceFilter", c.getDistanceFilter());
|
|
34
|
+
j.put("desiredAccuracy", c.getDesiredAccuracy());
|
|
35
|
+
j.put("debug", c.isDebugging());
|
|
36
|
+
j.put("notificationTitle", nullable(c.getNotificationTitle()));
|
|
37
|
+
j.put("notificationText", nullable(c.getNotificationText()));
|
|
38
|
+
j.put("notificationSyncTitle", nullable(c.getNotificationSyncTitle()));
|
|
39
|
+
j.put("notificationSyncText", nullable(c.getNotificationSyncText()));
|
|
40
|
+
j.put("notificationSyncCompletedText", nullable(c.getNotificationSyncCompletedText()));
|
|
41
|
+
j.put("notificationSyncFailedText", nullable(c.getNotificationSyncFailedText()));
|
|
42
|
+
j.put("notificationIconLarge", nullable(c.getLargeNotificationIcon()));
|
|
43
|
+
j.put("notificationIconSmall", nullable(c.getSmallNotificationIcon()));
|
|
44
|
+
j.put("notificationIconColor", nullable(c.getNotificationIconColor()));
|
|
45
|
+
j.put("locationProvider", c.getLocationProvider());
|
|
46
|
+
j.put("interval", c.getInterval());
|
|
47
|
+
j.put("fastestInterval", c.getFastestInterval());
|
|
48
|
+
j.put("activitiesInterval", c.getActivitiesInterval());
|
|
49
|
+
j.put("stopOnTerminate", c.getStopOnTerminate());
|
|
50
|
+
j.put("startOnBoot", c.getStartOnBoot());
|
|
51
|
+
j.put("startForeground", c.getStartForeground());
|
|
52
|
+
j.put("notificationsEnabled", c.getNotificationsEnabled());
|
|
53
|
+
j.put("stopOnStillActivity", c.getStopOnStillActivity());
|
|
54
|
+
j.put("url", nullable(c.getUrl()));
|
|
55
|
+
j.put("syncUrl", nullable(c.getSyncUrl()));
|
|
56
|
+
j.put("syncThreshold", c.getSyncThreshold());
|
|
57
|
+
j.put("syncEnabled", c.getSyncEnabled());
|
|
58
|
+
j.put("maxLocations", c.getMaxLocations());
|
|
59
|
+
j.put("enableWatchdog", c.getEnableWatchdog());
|
|
60
|
+
j.put("showTime", c.getShowTime());
|
|
61
|
+
j.put("showDistance", c.getShowDistance());
|
|
62
|
+
j.put("httpMethod", c.getHttpMethod());
|
|
63
|
+
j.put("syncHttpMethod", c.getSyncHttpMethod());
|
|
64
|
+
j.put("httpMode", c.getHttpMode());
|
|
65
|
+
j.put("syncMode", c.getSyncMode());
|
|
66
|
+
j.put("heartbeatInterval", c.getHeartbeatInterval());
|
|
67
|
+
j.put("mockLocationPolicy", c.getMockLocationPolicy());
|
|
68
|
+
j.put("includeBattery", c.getIncludeBattery());
|
|
69
|
+
// v4.5.1: battery knobs
|
|
70
|
+
j.put("wakeLockMode", c.getWakeLockMode());
|
|
71
|
+
j.put("stationaryTimeout", c.getStationaryTimeout());
|
|
72
|
+
j.put("stationaryPollInterval", c.getStationaryPollInterval());
|
|
73
|
+
j.put("stationaryPollFast", c.getStationaryPollFast());
|
|
74
|
+
|
|
75
|
+
if (c.getHttpHeaders() != null) {
|
|
76
|
+
j.put("httpHeaders", new JSONObject(c.getHttpHeaders()));
|
|
77
|
+
}
|
|
78
|
+
if (c.getQueryParams() != null) {
|
|
79
|
+
j.put("queryParams", new JSONObject(c.getQueryParams()));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
Config.DrivingEventsOptions de = c.getDrivingEvents();
|
|
83
|
+
if (de != null) {
|
|
84
|
+
JSONObject deJson = new JSONObject();
|
|
85
|
+
deJson.put("enabled", de.enabled);
|
|
86
|
+
deJson.put("speedLimit", de.speedLimitKmh);
|
|
87
|
+
deJson.put("minMovingSpeed", de.minMovingSpeedMps);
|
|
88
|
+
deJson.put("stoppedDuration", de.stoppedDurationMs);
|
|
89
|
+
deJson.put("minTripSpeed", de.minTripSpeedMps);
|
|
90
|
+
deJson.put("minTripDuration", de.minTripDurationMs);
|
|
91
|
+
deJson.put("hardBrakeMps2", de.hardBrakeMps2);
|
|
92
|
+
deJson.put("rapidAccelMps2", de.rapidAccelMps2);
|
|
93
|
+
deJson.put("sharpTurnDegPerSec", de.sharpTurnDegPerSec);
|
|
94
|
+
deJson.put("crashImpactKmh", de.crashImpactKmh);
|
|
95
|
+
deJson.put("crashWindowMs", de.crashWindowMs);
|
|
96
|
+
deJson.put("sensorFusion", de.sensorFusion);
|
|
97
|
+
deJson.put("crashImpactG", de.crashImpactG);
|
|
98
|
+
deJson.put("sensorCrashCooldownMs", de.sensorCrashCooldownMs);
|
|
99
|
+
deJson.put("phoneUsageWindowMs", de.phoneUsageWindowMs);
|
|
100
|
+
deJson.put("phoneUsageCooldownMs", de.phoneUsageCooldownMs);
|
|
101
|
+
j.put("drivingEvents", deJson);
|
|
102
|
+
}
|
|
103
|
+
return j;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Deserialize a previously serialized config JSON. Missing keys are skipped (defaults preserved). */
|
|
107
|
+
public static Config fromJSONObject(JSONObject j) throws JSONException {
|
|
108
|
+
Config c = Config.getDefault();
|
|
109
|
+
if (j == null) return c;
|
|
110
|
+
if (j.has("stationaryRadius")) c.setStationaryRadius((float) j.getDouble("stationaryRadius"));
|
|
111
|
+
if (j.has("distanceFilter")) c.setDistanceFilter(j.getInt("distanceFilter"));
|
|
112
|
+
if (j.has("desiredAccuracy")) c.setDesiredAccuracy(j.getInt("desiredAccuracy"));
|
|
113
|
+
if (j.has("debug")) c.setDebugging(j.getBoolean("debug"));
|
|
114
|
+
if (j.has("notificationTitle")) c.setNotificationTitle(readNullable(j, "notificationTitle"));
|
|
115
|
+
if (j.has("notificationText")) c.setNotificationText(readNullable(j, "notificationText"));
|
|
116
|
+
if (j.has("notificationSyncTitle")) c.setNotificationSyncTitle(readNullable(j, "notificationSyncTitle"));
|
|
117
|
+
if (j.has("notificationSyncText")) c.setNotificationSyncText(readNullable(j, "notificationSyncText"));
|
|
118
|
+
if (j.has("notificationSyncCompletedText")) c.setNotificationSyncCompletedText(readNullable(j, "notificationSyncCompletedText"));
|
|
119
|
+
if (j.has("notificationSyncFailedText")) c.setNotificationSyncFailedText(readNullable(j, "notificationSyncFailedText"));
|
|
120
|
+
if (j.has("notificationIconLarge")) c.setLargeNotificationIcon(readNullable(j, "notificationIconLarge"));
|
|
121
|
+
if (j.has("notificationIconSmall")) c.setSmallNotificationIcon(readNullable(j, "notificationIconSmall"));
|
|
122
|
+
if (j.has("notificationIconColor")) c.setNotificationIconColor(readNullable(j, "notificationIconColor"));
|
|
123
|
+
if (j.has("locationProvider")) c.setLocationProvider(j.getInt("locationProvider"));
|
|
124
|
+
if (j.has("interval")) c.setInterval(j.getInt("interval"));
|
|
125
|
+
if (j.has("fastestInterval")) c.setFastestInterval(j.getInt("fastestInterval"));
|
|
126
|
+
if (j.has("activitiesInterval")) c.setActivitiesInterval(j.getInt("activitiesInterval"));
|
|
127
|
+
if (j.has("stopOnTerminate")) c.setStopOnTerminate(j.getBoolean("stopOnTerminate"));
|
|
128
|
+
if (j.has("startOnBoot")) c.setStartOnBoot(j.getBoolean("startOnBoot"));
|
|
129
|
+
if (j.has("startForeground")) c.setStartForeground(j.getBoolean("startForeground"));
|
|
130
|
+
if (j.has("notificationsEnabled")) c.setNotificationsEnabled(j.getBoolean("notificationsEnabled"));
|
|
131
|
+
if (j.has("stopOnStillActivity")) c.setStopOnStillActivity(j.getBoolean("stopOnStillActivity"));
|
|
132
|
+
if (j.has("url")) c.setUrl(readNullable(j, "url"));
|
|
133
|
+
if (j.has("syncUrl")) c.setSyncUrl(readNullable(j, "syncUrl"));
|
|
134
|
+
if (j.has("syncThreshold")) c.setSyncThreshold(j.getInt("syncThreshold"));
|
|
135
|
+
if (j.has("syncEnabled")) c.setSyncEnabled(j.getBoolean("syncEnabled"));
|
|
136
|
+
if (j.has("maxLocations")) c.setMaxLocations(j.getInt("maxLocations"));
|
|
137
|
+
if (j.has("enableWatchdog")) c.setEnableWatchdog(j.getBoolean("enableWatchdog"));
|
|
138
|
+
if (j.has("showTime")) c.setShowTime(j.getBoolean("showTime"));
|
|
139
|
+
if (j.has("showDistance")) c.setShowDistance(j.getBoolean("showDistance"));
|
|
140
|
+
if (has(j, "httpMethod")) c.setHttpMethod(j.getString("httpMethod"));
|
|
141
|
+
if (has(j, "syncHttpMethod")) c.setSyncHttpMethod(j.getString("syncHttpMethod"));
|
|
142
|
+
if (has(j, "httpMode")) c.setHttpMode(j.getString("httpMode"));
|
|
143
|
+
if (has(j, "syncMode")) c.setSyncMode(j.getString("syncMode"));
|
|
144
|
+
if (j.has("heartbeatInterval")) c.setHeartbeatInterval(j.getInt("heartbeatInterval"));
|
|
145
|
+
if (has(j, "mockLocationPolicy")) c.setMockLocationPolicy(j.getString("mockLocationPolicy"));
|
|
146
|
+
if (j.has("includeBattery")) c.setIncludeBattery(j.getBoolean("includeBattery"));
|
|
147
|
+
// v4.5.1: battery knobs
|
|
148
|
+
if (has(j, "wakeLockMode")) c.setWakeLockMode(j.getString("wakeLockMode"));
|
|
149
|
+
if (j.has("stationaryTimeout") && !j.isNull("stationaryTimeout")) c.setStationaryTimeout(j.getInt("stationaryTimeout"));
|
|
150
|
+
if (j.has("stationaryPollInterval") && !j.isNull("stationaryPollInterval")) c.setStationaryPollInterval(j.getInt("stationaryPollInterval"));
|
|
151
|
+
if (j.has("stationaryPollFast") && !j.isNull("stationaryPollFast")) c.setStationaryPollFast(j.getInt("stationaryPollFast"));
|
|
152
|
+
|
|
153
|
+
if (has(j, "httpHeaders")) c.setHttpHeaders(jsonToHashMap(j.getJSONObject("httpHeaders")));
|
|
154
|
+
if (has(j, "queryParams")) c.setQueryParams(jsonToHashMap(j.getJSONObject("queryParams")));
|
|
155
|
+
|
|
156
|
+
if (has(j, "drivingEvents")) {
|
|
157
|
+
JSONObject de = j.getJSONObject("drivingEvents");
|
|
158
|
+
Config.DrivingEventsOptions o = new Config.DrivingEventsOptions();
|
|
159
|
+
if (de.has("enabled")) o.enabled = de.getBoolean("enabled");
|
|
160
|
+
if (de.has("speedLimit")) o.speedLimitKmh = de.getDouble("speedLimit");
|
|
161
|
+
if (de.has("minMovingSpeed")) o.minMovingSpeedMps = de.getDouble("minMovingSpeed");
|
|
162
|
+
if (de.has("stoppedDuration")) o.stoppedDurationMs = de.getLong("stoppedDuration");
|
|
163
|
+
if (de.has("minTripSpeed")) o.minTripSpeedMps = de.getDouble("minTripSpeed");
|
|
164
|
+
if (de.has("minTripDuration")) o.minTripDurationMs = de.getLong("minTripDuration");
|
|
165
|
+
if (de.has("hardBrakeMps2")) o.hardBrakeMps2 = de.getDouble("hardBrakeMps2");
|
|
166
|
+
if (de.has("rapidAccelMps2")) o.rapidAccelMps2 = de.getDouble("rapidAccelMps2");
|
|
167
|
+
if (de.has("sharpTurnDegPerSec")) o.sharpTurnDegPerSec = de.getDouble("sharpTurnDegPerSec");
|
|
168
|
+
if (de.has("crashImpactKmh")) o.crashImpactKmh = de.getDouble("crashImpactKmh");
|
|
169
|
+
if (de.has("crashWindowMs")) o.crashWindowMs = de.getLong("crashWindowMs");
|
|
170
|
+
if (de.has("sensorFusion")) o.sensorFusion = de.getBoolean("sensorFusion");
|
|
171
|
+
if (de.has("crashImpactG")) o.crashImpactG = de.getDouble("crashImpactG");
|
|
172
|
+
if (de.has("sensorCrashCooldownMs")) o.sensorCrashCooldownMs = de.getLong("sensorCrashCooldownMs");
|
|
173
|
+
if (de.has("phoneUsageWindowMs")) o.phoneUsageWindowMs = de.getLong("phoneUsageWindowMs");
|
|
174
|
+
if (de.has("phoneUsageCooldownMs")) o.phoneUsageCooldownMs = de.getLong("phoneUsageCooldownMs");
|
|
175
|
+
c.setDrivingEvents(o);
|
|
176
|
+
}
|
|
177
|
+
return c;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
private static HashMap<String, String> jsonToHashMap(JSONObject obj) throws JSONException {
|
|
181
|
+
HashMap<String, String> map = new HashMap<>();
|
|
182
|
+
Iterator<String> keys = obj.keys();
|
|
183
|
+
while (keys.hasNext()) {
|
|
184
|
+
String k = keys.next();
|
|
185
|
+
map.put(k, String.valueOf(obj.get(k)));
|
|
186
|
+
}
|
|
187
|
+
return map;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private static boolean has(JSONObject j, String key) {
|
|
191
|
+
return j.has(key) && !j.isNull(key);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Map {@link Config#NullString} or null to JSONObject.NULL so the sentinel survives. */
|
|
195
|
+
private static Object nullable(String s) {
|
|
196
|
+
if (s == null || s == Config.NullString) return JSONObject.NULL;
|
|
197
|
+
return s;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** Inverse of {@link #nullable(String)}. JSON null → {@link Config#NullString}. */
|
|
201
|
+
private static String readNullable(JSONObject j, String key) throws JSONException {
|
|
202
|
+
if (j.isNull(key)) return Config.NullString;
|
|
203
|
+
return j.getString(key);
|
|
204
|
+
}
|
|
205
|
+
}
|
package/android/common/src/main/java/com/marianhello/bgloc/data/LocationTemplateFactory.java
CHANGED
|
@@ -60,6 +60,12 @@ public class LocationTemplateFactory {
|
|
|
60
60
|
attrs.put("altitude", "@altitude");
|
|
61
61
|
attrs.put("bearing", "@bearing");
|
|
62
62
|
attrs.put("radius", "@radius");
|
|
63
|
+
// v4.5.1 — README/CHANGELOG promete que el payload default incluye events/battery/isCharging.
|
|
64
|
+
// Como Config.getTemplate() siempre cae a este default si no hay postTemplate custom, hay
|
|
65
|
+
// que añadirlos aquí para que PostLocationTask + BatchManager los serialicen al backend.
|
|
66
|
+
attrs.put("events", "@events");
|
|
67
|
+
attrs.put("battery", "@battery");
|
|
68
|
+
attrs.put("isCharging", "@isCharging");
|
|
63
69
|
return new HashMapLocationTemplate(attrs);
|
|
64
70
|
}
|
|
65
71
|
}
|
|
@@ -47,6 +47,9 @@ public final class SQLiteConfigurationContract {
|
|
|
47
47
|
public static final String COLUMN_NAME_TEMPLATE = "template";
|
|
48
48
|
public static final String COLUMN_NAME_SHOW_TIME = "show_time";
|
|
49
49
|
public static final String COLUMN_NAME_SHOW_DISTANCE = "show_distance";
|
|
50
|
+
// v4.4.1 — single JSON blob holding the full config (replaces per-field columns
|
|
51
|
+
// for new keys). Old columns are kept for backward compat with v20 databases.
|
|
52
|
+
public static final String COLUMN_NAME_CONFIG_JSON = "config_json";
|
|
50
53
|
|
|
51
54
|
public static final String SQL_CREATE_CONFIG_TABLE =
|
|
52
55
|
"CREATE TABLE " + ConfigurationEntry.TABLE_NAME + " (" +
|
|
@@ -81,7 +84,8 @@ public final class SQLiteConfigurationContract {
|
|
|
81
84
|
ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS + INTEGER_TYPE + COMMA_SEP +
|
|
82
85
|
ConfigurationEntry.COLUMN_NAME_TEMPLATE + TEXT_TYPE + COMMA_SEP +
|
|
83
86
|
ConfigurationEntry.COLUMN_NAME_SHOW_TIME + INTEGER_TYPE + COMMA_SEP +
|
|
84
|
-
ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE + INTEGER_TYPE +
|
|
87
|
+
ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE + INTEGER_TYPE + COMMA_SEP +
|
|
88
|
+
ConfigurationEntry.COLUMN_NAME_CONFIG_JSON + TEXT_TYPE +
|
|
85
89
|
" )";
|
|
86
90
|
|
|
87
91
|
public static final String SQL_DROP_CONFIG_TABLE =
|
package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationDAO.java
CHANGED
|
@@ -10,6 +10,7 @@ import org.json.JSONObject;
|
|
|
10
10
|
import org.json.JSONException;
|
|
11
11
|
|
|
12
12
|
import com.marianhello.bgloc.Config;
|
|
13
|
+
import com.marianhello.bgloc.data.ConfigJsonMapper;
|
|
13
14
|
import com.marianhello.bgloc.data.ConfigurationDAO;
|
|
14
15
|
import com.marianhello.bgloc.data.LocationTemplateFactory;
|
|
15
16
|
import com.marianhello.bgloc.data.sqlite.SQLiteConfigurationContract.ConfigurationEntry;
|
|
@@ -63,7 +64,8 @@ public class SQLiteConfigurationDAO implements ConfigurationDAO {
|
|
|
63
64
|
ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS,
|
|
64
65
|
ConfigurationEntry.COLUMN_NAME_TEMPLATE,
|
|
65
66
|
ConfigurationEntry.COLUMN_NAME_SHOW_TIME,
|
|
66
|
-
ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE
|
|
67
|
+
ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE,
|
|
68
|
+
ConfigurationEntry.COLUMN_NAME_CONFIG_JSON
|
|
67
69
|
};
|
|
68
70
|
|
|
69
71
|
String whereClause = null;
|
|
@@ -105,6 +107,26 @@ public class SQLiteConfigurationDAO implements ConfigurationDAO {
|
|
|
105
107
|
}
|
|
106
108
|
|
|
107
109
|
private Config hydrate(Cursor c) throws JSONException {
|
|
110
|
+
// v4.4.1: prefer the full JSON blob if present (covers all keys, including post-3.2 ones).
|
|
111
|
+
// Note: `template` (postTemplate) lives in its dedicated column — restore it after the
|
|
112
|
+
// JSON deserialization so it's not lost when the config arrived via config_json only.
|
|
113
|
+
int idxJson = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_CONFIG_JSON);
|
|
114
|
+
if (idxJson >= 0 && !c.isNull(idxJson)) {
|
|
115
|
+
String json = c.getString(idxJson);
|
|
116
|
+
if (json != null && !json.isEmpty()) {
|
|
117
|
+
try {
|
|
118
|
+
Config restored = ConfigJsonMapper.fromJSONObject(new JSONObject(json));
|
|
119
|
+
int idxTpl = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_TEMPLATE);
|
|
120
|
+
if (idxTpl >= 0 && !c.isNull(idxTpl)) {
|
|
121
|
+
restored.setTemplate(LocationTemplateFactory.fromJSONString(c.getString(idxTpl)));
|
|
122
|
+
}
|
|
123
|
+
return restored;
|
|
124
|
+
} catch (JSONException ex) {
|
|
125
|
+
Log.w(TAG, "config_json parse failed; falling back to legacy columns: " + ex.getMessage());
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Legacy hydration (DBs upgraded from v20 or earlier where config_json is still NULL).
|
|
108
130
|
Config config = Config.getDefault();
|
|
109
131
|
config.setStationaryRadius(c.getFloat(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_RADIUS)));
|
|
110
132
|
config.setDistanceFilter(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_DISTANCE_FILTER)));
|
|
@@ -190,6 +212,15 @@ public class SQLiteConfigurationDAO implements ConfigurationDAO {
|
|
|
190
212
|
values.put(ConfigurationEntry.COLUMN_NAME_TEMPLATE, config.hasTemplate() ? config.getTemplate().toString() : null);
|
|
191
213
|
values.put(ConfigurationEntry.COLUMN_NAME_SHOW_TIME, Boolean.TRUE.equals(config.getShowTime()) ? 1 : 0);
|
|
192
214
|
values.put(ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE, Boolean.TRUE.equals(config.getShowDistance()) ? 1 : 0);
|
|
215
|
+
// v4.4.1: persist the full Config as JSON so post-3.2 fields (httpMethod, queryParams,
|
|
216
|
+
// drivingEvents, includeBattery, mockLocationPolicy, heartbeatInterval, ...) survive
|
|
217
|
+
// a reboot / startOnBoot. Legacy columns are kept populated above for backward compat.
|
|
218
|
+
try {
|
|
219
|
+
values.put(ConfigurationEntry.COLUMN_NAME_CONFIG_JSON,
|
|
220
|
+
ConfigJsonMapper.toJSONObject(config).toString());
|
|
221
|
+
} catch (JSONException e) {
|
|
222
|
+
Log.w(TAG, "config_json serialize failed: " + e.getMessage());
|
|
223
|
+
}
|
|
193
224
|
|
|
194
225
|
return values;
|
|
195
226
|
}
|
package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteLocationContract.java
CHANGED
|
@@ -37,6 +37,10 @@ public final class SQLiteLocationContract {
|
|
|
37
37
|
public static final String COLUMN_NAME_STATUS = "valid";
|
|
38
38
|
public static final String COLUMN_NAME_BATCH_START_MILLIS = "batch_start";
|
|
39
39
|
public static final String COLUMN_NAME_MOCK_FLAGS = "mock_flags";
|
|
40
|
+
// v4.5 — survive sync queue: events JSON, battery percentage and charging state.
|
|
41
|
+
public static final String COLUMN_NAME_EVENTS_JSON = "events_json";
|
|
42
|
+
public static final String COLUMN_NAME_BATTERY_LEVEL = "battery_level";
|
|
43
|
+
public static final String COLUMN_NAME_IS_CHARGING = "is_charging";
|
|
40
44
|
|
|
41
45
|
public static final String SQL_CREATE_LOCATION_TABLE =
|
|
42
46
|
"CREATE TABLE " + LocationEntry.TABLE_NAME + " (" +
|
|
@@ -60,7 +64,10 @@ public final class SQLiteLocationContract {
|
|
|
60
64
|
LocationEntry.COLUMN_NAME_LOCATION_PROVIDER + INTEGER_TYPE + COMMA_SEP +
|
|
61
65
|
LocationEntry.COLUMN_NAME_STATUS + INTEGER_TYPE + COMMA_SEP +
|
|
62
66
|
LocationEntry.COLUMN_NAME_BATCH_START_MILLIS + INTEGER_TYPE + COMMA_SEP +
|
|
63
|
-
LocationEntry.COLUMN_NAME_MOCK_FLAGS + INTEGER_TYPE +
|
|
67
|
+
LocationEntry.COLUMN_NAME_MOCK_FLAGS + INTEGER_TYPE + COMMA_SEP +
|
|
68
|
+
LocationEntry.COLUMN_NAME_EVENTS_JSON + TEXT_TYPE + COMMA_SEP +
|
|
69
|
+
LocationEntry.COLUMN_NAME_BATTERY_LEVEL + INTEGER_TYPE + COMMA_SEP +
|
|
70
|
+
LocationEntry.COLUMN_NAME_IS_CHARGING + INTEGER_TYPE +
|
|
64
71
|
" )";
|
|
65
72
|
|
|
66
73
|
public static final String SQL_DROP_LOCATION_TABLE =
|
|
@@ -106,7 +113,10 @@ public final class SQLiteLocationContract {
|
|
|
106
113
|
COLUMN_NAME_LOCATION_PROVIDER,
|
|
107
114
|
COLUMN_NAME_STATUS,
|
|
108
115
|
COLUMN_NAME_BATCH_START_MILLIS,
|
|
109
|
-
COLUMN_NAME_MOCK_FLAGS
|
|
116
|
+
COLUMN_NAME_MOCK_FLAGS,
|
|
117
|
+
COLUMN_NAME_EVENTS_JSON,
|
|
118
|
+
COLUMN_NAME_BATTERY_LEVEL,
|
|
119
|
+
COLUMN_NAME_IS_CHARGING
|
|
110
120
|
};
|
|
111
121
|
}
|
|
112
122
|
}
|