@josuelmm/cordova-background-geolocation 4.2.3 → 4.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.npmignore +11 -0
- package/CHANGELOG.md +261 -0
- package/README.md +306 -115
- package/android/CDVBackgroundGeolocation/src/main/java/com/marianhello/bgloc/cordova/ConfigMapper.java +34 -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 +20 -3
- package/android/common/src/main/java/com/marianhello/bgloc/Config.java +87 -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 +211 -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/AbstractLocationProvider.java +48 -1
- package/android/common/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java +105 -6
- package/android/common/src/main/java/com/marianhello/bgloc/provider/DistanceFilterLocationProvider.java +336 -250
- package/android/common/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java +69 -19
- 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/MAURActivityLocationProvider.m +208 -70
- package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m +132 -5
- package/ios/common/BackgroundGeolocation/MAURBackgroundSync.m +20 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.h +7 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.m +37 -2
- package/ios/common/BackgroundGeolocation/MAURConfigurationContract.h +3 -0
- package/ios/common/BackgroundGeolocation/MAURConfigurationContract.m +3 -1
- package/ios/common/BackgroundGeolocation/MAURDistanceFilterLocationProvider.m +10 -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/MAURLocationManager.m +19 -1
- package/ios/common/BackgroundGeolocation/MAURPostLocationTask.h +9 -0
- package/ios/common/BackgroundGeolocation/MAURPostLocationTask.m +59 -1
- package/ios/common/BackgroundGeolocation/MAURRawLocationProvider.m +10 -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 -10
- package/www/BackgroundGeolocation.d.ts +143 -3
- package/www/BackgroundGeolocation.js +11 -4
- package/CLAUDE.md +0 -56
- package/HISTORY.md +0 -871
- 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/BackgroundGeolocation/SOMotionDetector/CHANGELOG.md +0 -2
- package/ios/common/BackgroundGeolocation/SOMotionDetector/LICENSE +0 -21
- package/ios/common/BackgroundGeolocation/SOMotionDetector/README.md +0 -135
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOLocationManager.h +0 -80
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOLocationManager.m +0 -147
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOMotionActivity.h +0 -30
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOMotionActivity.m +0 -42
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOMotionDetector.h +0 -99
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOMotionDetector.m +0 -327
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOStepDetector.h +0 -44
- package/ios/common/BackgroundGeolocation/SOMotionDetector/SOStepDetector.m +0 -94
- package/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/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
|
}
|
package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteLocationDAO.java
CHANGED
|
@@ -300,7 +300,10 @@ public class SQLiteLocationDAO implements LocationDAO {
|
|
|
300
300
|
.append(LocationEntry.COLUMN_NAME_LOCATION_PROVIDER).append("= ?,")
|
|
301
301
|
.append(LocationEntry.COLUMN_NAME_BATCH_START_MILLIS).append("= ?,")
|
|
302
302
|
.append(LocationEntry.COLUMN_NAME_STATUS).append("= ?,")
|
|
303
|
-
.append(LocationEntry.COLUMN_NAME_MOCK_FLAGS).append("=
|
|
303
|
+
.append(LocationEntry.COLUMN_NAME_MOCK_FLAGS).append("= ?,")
|
|
304
|
+
.append(LocationEntry.COLUMN_NAME_EVENTS_JSON).append("= ?,")
|
|
305
|
+
.append(LocationEntry.COLUMN_NAME_BATTERY_LEVEL).append("= ?,")
|
|
306
|
+
.append(LocationEntry.COLUMN_NAME_IS_CHARGING).append("= ?")
|
|
304
307
|
.append(" WHERE ").append(LocationEntry._ID)
|
|
305
308
|
.append("= ?")
|
|
306
309
|
.toString();
|
|
@@ -325,6 +328,9 @@ public class SQLiteLocationDAO implements LocationDAO {
|
|
|
325
328
|
location.getBatchStartMillis(),
|
|
326
329
|
location.getStatus(),
|
|
327
330
|
location.getMockFlags(),
|
|
331
|
+
location.hasDrivingEvents() ? location.getDrivingEvents().toString() : null,
|
|
332
|
+
location.getBatteryLevel(),
|
|
333
|
+
location.isCharging() != null ? (location.isCharging() ? 1 : 0) : null,
|
|
328
334
|
locationId
|
|
329
335
|
});
|
|
330
336
|
|
|
@@ -459,6 +465,18 @@ public class SQLiteLocationDAO implements LocationDAO {
|
|
|
459
465
|
l.setStatus(c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_STATUS)));
|
|
460
466
|
l.setLocationId(c.getLong(c.getColumnIndex(LocationEntry._ID)));
|
|
461
467
|
l.setMockFlags(c.getInt((c.getColumnIndex(LocationEntry.COLUMN_NAME_MOCK_FLAGS))));
|
|
468
|
+
// v4.5: events / battery / charging
|
|
469
|
+
int idxEv = c.getColumnIndex(LocationEntry.COLUMN_NAME_EVENTS_JSON);
|
|
470
|
+
if (idxEv >= 0 && !c.isNull(idxEv)) {
|
|
471
|
+
String s = c.getString(idxEv);
|
|
472
|
+
if (s != null && !s.isEmpty()) {
|
|
473
|
+
try { l.setDrivingEvents(new org.json.JSONArray(s)); } catch (org.json.JSONException ignored) {}
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
int idxBat = c.getColumnIndex(LocationEntry.COLUMN_NAME_BATTERY_LEVEL);
|
|
477
|
+
if (idxBat >= 0 && !c.isNull(idxBat)) l.setBatteryLevel(c.getInt(idxBat));
|
|
478
|
+
int idxChg = c.getColumnIndex(LocationEntry.COLUMN_NAME_IS_CHARGING);
|
|
479
|
+
if (idxChg >= 0 && !c.isNull(idxChg)) l.setCharging(c.getInt(idxChg) == 1);
|
|
462
480
|
|
|
463
481
|
return l;
|
|
464
482
|
}
|
|
@@ -485,6 +503,16 @@ public class SQLiteLocationDAO implements LocationDAO {
|
|
|
485
503
|
values.put(LocationEntry.COLUMN_NAME_STATUS, l.getStatus());
|
|
486
504
|
values.put(LocationEntry.COLUMN_NAME_BATCH_START_MILLIS, l.getBatchStartMillis());
|
|
487
505
|
values.put(LocationEntry.COLUMN_NAME_MOCK_FLAGS, l.getMockFlags());
|
|
506
|
+
// v4.5.1: always write — NULL when absent — to clear stale values on maxRows recycle.
|
|
507
|
+
if (l.hasDrivingEvents()) {
|
|
508
|
+
values.put(LocationEntry.COLUMN_NAME_EVENTS_JSON, l.getDrivingEvents().toString());
|
|
509
|
+
} else {
|
|
510
|
+
values.putNull(LocationEntry.COLUMN_NAME_EVENTS_JSON);
|
|
511
|
+
}
|
|
512
|
+
if (l.getBatteryLevel() != null) values.put(LocationEntry.COLUMN_NAME_BATTERY_LEVEL, l.getBatteryLevel());
|
|
513
|
+
else values.putNull(LocationEntry.COLUMN_NAME_BATTERY_LEVEL);
|
|
514
|
+
if (l.isCharging() != null) values.put(LocationEntry.COLUMN_NAME_IS_CHARGING, l.isCharging() ? 1 : 0);
|
|
515
|
+
else values.putNull(LocationEntry.COLUMN_NAME_IS_CHARGING);
|
|
488
516
|
|
|
489
517
|
return values;
|
|
490
518
|
}
|
|
@@ -511,7 +539,10 @@ public class SQLiteLocationDAO implements LocationDAO {
|
|
|
511
539
|
LocationEntry.COLUMN_NAME_LOCATION_PROVIDER,
|
|
512
540
|
LocationEntry.COLUMN_NAME_STATUS,
|
|
513
541
|
LocationEntry.COLUMN_NAME_BATCH_START_MILLIS,
|
|
514
|
-
LocationEntry.COLUMN_NAME_MOCK_FLAGS
|
|
542
|
+
LocationEntry.COLUMN_NAME_MOCK_FLAGS,
|
|
543
|
+
LocationEntry.COLUMN_NAME_EVENTS_JSON,
|
|
544
|
+
LocationEntry.COLUMN_NAME_BATTERY_LEVEL,
|
|
545
|
+
LocationEntry.COLUMN_NAME_IS_CHARGING
|
|
515
546
|
};
|
|
516
547
|
|
|
517
548
|
return columns;
|
package/android/common/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteOpenHelper.java
CHANGED
|
@@ -22,7 +22,7 @@ import static com.marianhello.bgloc.data.sqlite.SQLiteLocationContract.LocationE
|
|
|
22
22
|
public class SQLiteOpenHelper extends android.database.sqlite.SQLiteOpenHelper {
|
|
23
23
|
private static final String TAG = SQLiteOpenHelper.class.getName();
|
|
24
24
|
public static final String SQLITE_DATABASE_NAME = "cordova_bg_geolocation.db";
|
|
25
|
-
public static final int DATABASE_VERSION =
|
|
25
|
+
public static final int DATABASE_VERSION = 22;
|
|
26
26
|
|
|
27
27
|
public static final String TEXT_TYPE = " TEXT";
|
|
28
28
|
public static final String INTEGER_TYPE = " INTEGER";
|
|
@@ -143,6 +143,20 @@ public class SQLiteOpenHelper extends android.database.sqlite.SQLiteOpenHelper {
|
|
|
143
143
|
case 19:
|
|
144
144
|
alterSql.add(SessionEntry.SQL_CREATE_SESSION_TABLE);
|
|
145
145
|
alterSql.add(SessionEntry.SQL_CREATE_SESSION_TABLE_TIME_IDX);
|
|
146
|
+
case 20:
|
|
147
|
+
// v4.4.1: store the full Config as a single JSON blob so future-added fields
|
|
148
|
+
// do not require a per-field schema bump.
|
|
149
|
+
alterSql.add("ALTER TABLE " + ConfigurationEntry.TABLE_NAME +
|
|
150
|
+
" ADD COLUMN " + ConfigurationEntry.COLUMN_NAME_CONFIG_JSON + TEXT_TYPE);
|
|
151
|
+
case 21:
|
|
152
|
+
// v4.5.0: persist driving events / battery / isCharging on each location so
|
|
153
|
+
// they survive the sync queue (POST failure → SQLite → background sync).
|
|
154
|
+
alterSql.add("ALTER TABLE " + LocationEntry.TABLE_NAME +
|
|
155
|
+
" ADD COLUMN " + LocationEntry.COLUMN_NAME_EVENTS_JSON + TEXT_TYPE);
|
|
156
|
+
alterSql.add("ALTER TABLE " + LocationEntry.TABLE_NAME +
|
|
157
|
+
" ADD COLUMN " + LocationEntry.COLUMN_NAME_BATTERY_LEVEL + INTEGER_TYPE);
|
|
158
|
+
alterSql.add("ALTER TABLE " + LocationEntry.TABLE_NAME +
|
|
159
|
+
" ADD COLUMN " + LocationEntry.COLUMN_NAME_IS_CHARGING + INTEGER_TYPE);
|
|
146
160
|
|
|
147
161
|
break; // DO NOT FORGET TO MOVE DOWN BREAK ON DB UPGRADE!!!
|
|
148
162
|
default:
|
package/android/common/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java
CHANGED
|
@@ -88,11 +88,29 @@ public abstract class AbstractLocationProvider implements LocationProvider {
|
|
|
88
88
|
mContext.unregisterReceiver(receiver);
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/**
|
|
92
|
+
* v4.5.2: drop fixes whose horizontal accuracy is worse than the configured
|
|
93
|
+
* maxAcceptedAccuracy threshold. Returns true when the location must be
|
|
94
|
+
* discarded.
|
|
95
|
+
*/
|
|
96
|
+
private boolean exceedsMaxAcceptedAccuracy(Location location) {
|
|
97
|
+
if (location == null || mConfig == null) return false;
|
|
98
|
+
Float max = mConfig.getMaxAcceptedAccuracy();
|
|
99
|
+
if (max == null || max <= 0) return false;
|
|
100
|
+
if (!location.hasAccuracy()) return false;
|
|
101
|
+
if (location.getAccuracy() > max) {
|
|
102
|
+
logger.debug("Dropping fix: accuracy={} exceeds maxAcceptedAccuracy={}", location.getAccuracy(), max);
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
|
|
91
108
|
/**
|
|
92
109
|
* Handle location as recorder by provider
|
|
93
110
|
* @param location
|
|
94
111
|
*/
|
|
95
112
|
protected void handleLocation (Location location) {
|
|
113
|
+
if (exceedsMaxAcceptedAccuracy(location)) return;
|
|
96
114
|
playDebugTone(Tone.BEEP);
|
|
97
115
|
if (mDelegate != null) {
|
|
98
116
|
BackgroundLocation bgLocation = new BackgroundLocation(PROVIDER_ID, location);
|
|
@@ -108,6 +126,7 @@ public abstract class AbstractLocationProvider implements LocationProvider {
|
|
|
108
126
|
* @param radius radius of stationary region
|
|
109
127
|
*/
|
|
110
128
|
protected void handleStationary (Location location, float radius) {
|
|
129
|
+
if (exceedsMaxAcceptedAccuracy(location)) return;
|
|
111
130
|
playDebugTone(Tone.LONG_BEEP);
|
|
112
131
|
if (mDelegate != null) {
|
|
113
132
|
BackgroundLocation bgLocation = new BackgroundLocation(PROVIDER_ID, location);
|
|
@@ -123,6 +142,7 @@ public abstract class AbstractLocationProvider implements LocationProvider {
|
|
|
123
142
|
* @param location
|
|
124
143
|
*/
|
|
125
144
|
protected void handleStationary (Location location) {
|
|
145
|
+
if (exceedsMaxAcceptedAccuracy(location)) return;
|
|
126
146
|
playDebugTone(Tone.LONG_BEEP);
|
|
127
147
|
if (mDelegate != null) {
|
|
128
148
|
BackgroundLocation bgLocation = new BackgroundLocation(PROVIDER_ID, location);
|
|
@@ -148,6 +168,26 @@ public abstract class AbstractLocationProvider implements LocationProvider {
|
|
|
148
168
|
}
|
|
149
169
|
}
|
|
150
170
|
|
|
171
|
+
/**
|
|
172
|
+
* v4.5.2: emit a permission-denied error to the delegate (used when a runtime
|
|
173
|
+
* permission such as ACTIVITY_RECOGNITION is missing on Android 10+).
|
|
174
|
+
*/
|
|
175
|
+
protected void handlePermissionDenied(String message) {
|
|
176
|
+
if (mDelegate != null) {
|
|
177
|
+
mDelegate.onError(new PluginException(message, PluginException.PERMISSION_DENIED_ERROR));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* v4.5.2: emit a service-level error to the delegate (used when Google Play
|
|
183
|
+
* Services is missing/outdated or the OS location service is disabled).
|
|
184
|
+
*/
|
|
185
|
+
protected void handleServiceError(String message) {
|
|
186
|
+
if (mDelegate != null) {
|
|
187
|
+
mDelegate.onError(new PluginException(message, PluginException.SERVICE_ERROR));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
151
191
|
protected void showDebugToast (String text) {
|
|
152
192
|
if (mConfig.isDebugging()) {
|
|
153
193
|
Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
|
|
@@ -155,7 +195,14 @@ public abstract class AbstractLocationProvider implements LocationProvider {
|
|
|
155
195
|
}
|
|
156
196
|
|
|
157
197
|
public Boolean hasMockLocationsEnabled() {
|
|
158
|
-
|
|
198
|
+
// v4.5.2: Settings.Secure.getString may return null (key absent on the
|
|
199
|
+
// device's settings provider). The previous code crashed with NPE because
|
|
200
|
+
// it called .equals("1") on the returned value. Invert the comparison so
|
|
201
|
+
// null safely yields false.
|
|
202
|
+
String value = Settings.Secure.getString(
|
|
203
|
+
mContext.getContentResolver(),
|
|
204
|
+
android.provider.Settings.Secure.ALLOW_MOCK_LOCATION);
|
|
205
|
+
return "1".equals(value);
|
|
159
206
|
}
|
|
160
207
|
|
|
161
208
|
/**
|
|
@@ -12,6 +12,8 @@ import android.os.Build;
|
|
|
12
12
|
import android.os.Looper;
|
|
13
13
|
import androidx.core.app.ActivityCompat;
|
|
14
14
|
|
|
15
|
+
import com.google.android.gms.common.ConnectionResult;
|
|
16
|
+
import com.google.android.gms.common.GoogleApiAvailability;
|
|
15
17
|
import com.google.android.gms.location.ActivityRecognition;
|
|
16
18
|
import com.google.android.gms.location.ActivityRecognitionClient;
|
|
17
19
|
import com.google.android.gms.location.ActivityRecognitionResult;
|
|
@@ -41,8 +43,19 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide
|
|
|
41
43
|
private boolean isStarted = false;
|
|
42
44
|
private boolean isTracking = false;
|
|
43
45
|
private boolean isWatchingActivity = false;
|
|
46
|
+
private boolean playServicesAvailable = false;
|
|
47
|
+
private boolean activityPermissionErrorEmitted = false;
|
|
48
|
+
private boolean stopOnStillWarningEmitted = false;
|
|
44
49
|
private DetectedActivity lastActivity = new DetectedActivity(DetectedActivity.UNKNOWN, 100);
|
|
45
50
|
|
|
51
|
+
// v4.5.2: snapshot of fields that require restarting tracking when they change.
|
|
52
|
+
private Integer prevDesiredAccuracy;
|
|
53
|
+
private Integer prevInterval;
|
|
54
|
+
private Integer prevFastestInterval;
|
|
55
|
+
private Integer prevDistanceFilter;
|
|
56
|
+
private Integer prevActivitiesInterval;
|
|
57
|
+
private Boolean prevStopOnStillActivity;
|
|
58
|
+
|
|
46
59
|
private final LocationCallback locationCallback = new LocationCallback() {
|
|
47
60
|
@Override
|
|
48
61
|
public void onLocationResult(LocationResult result) {
|
|
@@ -63,6 +76,20 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide
|
|
|
63
76
|
@Override
|
|
64
77
|
public void onCreate() {
|
|
65
78
|
super.onCreate();
|
|
79
|
+
|
|
80
|
+
// v4.5.2: ACTIVITY_PROVIDER strictly depends on Google Play Services
|
|
81
|
+
// (FusedLocationProviderClient + ActivityRecognitionClient). If GPS is
|
|
82
|
+
// missing/outdated we cannot operate — surface a clear error instead of
|
|
83
|
+
// silently failing.
|
|
84
|
+
int gps = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(mContext);
|
|
85
|
+
playServicesAvailable = (gps == ConnectionResult.SUCCESS);
|
|
86
|
+
if (!playServicesAvailable) {
|
|
87
|
+
String msg = "Google Play Services unavailable for ACTIVITY_PROVIDER (code=" + gps + "); provider will be inert.";
|
|
88
|
+
logger.error(msg);
|
|
89
|
+
handleServiceError(msg);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
66
93
|
fusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext);
|
|
67
94
|
activityRecognitionClient = ActivityRecognition.getClient(mContext);
|
|
68
95
|
|
|
@@ -80,6 +107,15 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide
|
|
|
80
107
|
public void onStart() {
|
|
81
108
|
logger.info("Start recording");
|
|
82
109
|
this.isStarted = true;
|
|
110
|
+
|
|
111
|
+
// v4.5.2: ACTIVITY_PROVIDER hinges on the STILL/ACTIVE state machine.
|
|
112
|
+
// If the host turned that off, the provider degenerates into a tracker
|
|
113
|
+
// that never pauses — warn so it shows up in logcat for the integrator.
|
|
114
|
+
if (mConfig != null && Boolean.FALSE.equals(mConfig.getStopOnStillActivity()) && !stopOnStillWarningEmitted) {
|
|
115
|
+
logger.warn("ACTIVITY_PROVIDER with stopOnStillActivity=false will track continuously; consider DISTANCE_FILTER_PROVIDER or RAW_PROVIDER for that use case.");
|
|
116
|
+
stopOnStillWarningEmitted = true;
|
|
117
|
+
}
|
|
118
|
+
|
|
83
119
|
attachRecorder();
|
|
84
120
|
}
|
|
85
121
|
|
|
@@ -93,11 +129,40 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide
|
|
|
93
129
|
|
|
94
130
|
@Override
|
|
95
131
|
public void onConfigure(Config config) {
|
|
96
|
-
|
|
132
|
+
// v4.5.2: only restart tracking if a field that actually affects the
|
|
133
|
+
// LocationRequest / activity-updates subscription has changed. A no-op
|
|
134
|
+
// reconfigure used to drop+re-add the location callback and momentarily
|
|
135
|
+
// leave the service without updates.
|
|
136
|
+
boolean restart = false;
|
|
97
137
|
if (isStarted) {
|
|
138
|
+
restart = !sameValue(prevDesiredAccuracy, config != null ? config.getDesiredAccuracy() : null)
|
|
139
|
+
|| !sameValue(prevInterval, config != null ? config.getInterval() : null)
|
|
140
|
+
|| !sameValue(prevFastestInterval, config != null ? config.getFastestInterval() : null)
|
|
141
|
+
|| !sameValue(prevDistanceFilter, config != null ? config.getDistanceFilter() : null)
|
|
142
|
+
|| !sameValue(prevActivitiesInterval, config != null ? config.getActivitiesInterval() : null)
|
|
143
|
+
|| !sameValue(prevStopOnStillActivity, config != null ? config.getStopOnStillActivity() : null);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
super.onConfigure(config);
|
|
147
|
+
|
|
148
|
+
if (restart) {
|
|
149
|
+
logger.debug("Restarting ACTIVITY_PROVIDER tracking after relevant config change.");
|
|
98
150
|
onStop();
|
|
99
151
|
onStart();
|
|
100
152
|
}
|
|
153
|
+
|
|
154
|
+
if (config != null) {
|
|
155
|
+
prevDesiredAccuracy = config.getDesiredAccuracy();
|
|
156
|
+
prevInterval = config.getInterval();
|
|
157
|
+
prevFastestInterval = config.getFastestInterval();
|
|
158
|
+
prevDistanceFilter = config.getDistanceFilter();
|
|
159
|
+
prevActivitiesInterval = config.getActivitiesInterval();
|
|
160
|
+
prevStopOnStillActivity = config.getStopOnStillActivity();
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private static boolean sameValue(Object a, Object b) {
|
|
165
|
+
return a == null ? b == null : a.equals(b);
|
|
101
166
|
}
|
|
102
167
|
|
|
103
168
|
@Override
|
|
@@ -139,10 +204,16 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide
|
|
|
139
204
|
int priority = translateDesiredAccuracy(mConfig.getDesiredAccuracy());
|
|
140
205
|
// v3.4: LocationRequest.Builder (play-services-location 21.0.0+) replaces deprecated
|
|
141
206
|
// LocationRequest.create() + setPriority/setInterval/setFastestInterval.
|
|
142
|
-
|
|
207
|
+
// v4.5.2: also honor distanceFilter (was ignored on ACTIVITY_PROVIDER), so the
|
|
208
|
+
// FusedLocationProvider can throttle by distance and not just by interval.
|
|
209
|
+
LocationRequest.Builder builder = new LocationRequest.Builder(priority, mConfig.getInterval())
|
|
143
210
|
.setMinUpdateIntervalMillis(mConfig.getFastestInterval())
|
|
144
|
-
.setWaitForAccurateLocation(false)
|
|
145
|
-
|
|
211
|
+
.setWaitForAccurateLocation(false);
|
|
212
|
+
Integer distanceFilter = mConfig.getDistanceFilter();
|
|
213
|
+
if (distanceFilter != null && distanceFilter > 0) {
|
|
214
|
+
builder.setMinUpdateDistanceMeters(distanceFilter.floatValue());
|
|
215
|
+
}
|
|
216
|
+
LocationRequest locationRequest = builder.build();
|
|
146
217
|
|
|
147
218
|
try {
|
|
148
219
|
fusedLocationClient.requestLocationUpdates(
|
|
@@ -185,7 +256,20 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide
|
|
|
185
256
|
|
|
186
257
|
startTracking();
|
|
187
258
|
|
|
188
|
-
if (!isWatchingActivity && mConfig.getStopOnStillActivity()
|
|
259
|
+
if (!isWatchingActivity && mConfig.getStopOnStillActivity()) {
|
|
260
|
+
// v4.5.2: on Android 10+ ACTIVITY_RECOGNITION is a runtime permission.
|
|
261
|
+
// Without it, requestActivityUpdates() silently returns no broadcasts and
|
|
262
|
+
// STILL/ACTIVE never flips — the provider then runs as a continuous tracker
|
|
263
|
+
// by accident. Emit a one-shot error so the host app knows to request it.
|
|
264
|
+
if (!activityRecognitionPermitted()) {
|
|
265
|
+
if (!activityPermissionErrorEmitted) {
|
|
266
|
+
String msg = "ACTIVITY_RECOGNITION permission denied; ACTIVITY_PROVIDER cannot detect STILL/ACTIVE transitions.";
|
|
267
|
+
logger.warn(msg);
|
|
268
|
+
handlePermissionDenied(msg);
|
|
269
|
+
activityPermissionErrorEmitted = true;
|
|
270
|
+
}
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
189
273
|
activityRecognitionClient.requestActivityUpdates(
|
|
190
274
|
mConfig.getActivitiesInterval(),
|
|
191
275
|
detectedActivitiesPI
|
|
@@ -255,7 +339,22 @@ public class ActivityRecognitionLocationProvider extends AbstractLocationProvide
|
|
|
255
339
|
List<DetectedActivity> detectedActivities = result.getProbableActivities();
|
|
256
340
|
if (detectedActivities == null || detectedActivities.isEmpty()) return;
|
|
257
341
|
|
|
258
|
-
|
|
342
|
+
DetectedActivity candidate = getProbableActivity(detectedActivities);
|
|
343
|
+
|
|
344
|
+
// v4.5.2: skip transitions whose confidence is below the configured
|
|
345
|
+
// threshold (default 50). Prevents jittery STILL/ACTIVE flips when the
|
|
346
|
+
// motion classifier is unsure — which translated into spurious GPS
|
|
347
|
+
// start/stop bursts in earlier versions.
|
|
348
|
+
Integer threshold = mConfig != null ? mConfig.getActivityConfidenceThreshold() : null;
|
|
349
|
+
if (threshold != null && candidate.getConfidence() < threshold) {
|
|
350
|
+
logger.debug("Ignoring low-confidence activity={} confidence={} threshold={}",
|
|
351
|
+
BackgroundActivity.getActivityString(candidate.getType()),
|
|
352
|
+
candidate.getConfidence(),
|
|
353
|
+
threshold);
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
lastActivity = candidate;
|
|
259
358
|
|
|
260
359
|
logger.debug("Detected activity={} confidence={}", BackgroundActivity.getActivityString(lastActivity.getType()), lastActivity.getConfidence());
|
|
261
360
|
|