@josuelmm/cordova-background-geolocation 3.2.0 → 4.2.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 +4 -0
- package/CHANGELOG.md +290 -0
- package/CLAUDE.md +56 -0
- package/HISTORY.md +125 -0
- package/README.md +189 -4
- package/android/CDVBackgroundGeolocation/src/main/java/com/marianhello/bgloc/cordova/ConfigMapper.java +90 -0
- package/android/CDVBackgroundGeolocation/src/main/java/com/tenforwardconsulting/bgloc/cordova/BackgroundGeolocationPlugin.java +310 -1
- package/android/common/src/main/java/com/marianhello/bgloc/BackgroundGeolocationFacade.java +127 -0
- package/android/common/src/main/java/com/marianhello/bgloc/BootCompletedReceiver.java +27 -11
- package/android/common/src/main/java/com/marianhello/bgloc/Config.java +268 -0
- package/android/common/src/main/java/com/marianhello/bgloc/HttpPostService.java +86 -26
- package/android/common/src/main/java/com/marianhello/bgloc/PluginDelegate.java +26 -0
- package/android/common/src/main/java/com/marianhello/bgloc/PostLocationTask.java +42 -5
- package/android/common/src/main/java/com/marianhello/bgloc/driving/DrivingEventsDetector.java +265 -0
- package/android/common/src/main/java/com/marianhello/bgloc/http/UrlTemplateResolver.java +115 -0
- package/android/common/src/main/java/com/marianhello/bgloc/oem/BatteryOemHelper.java +214 -0
- package/android/common/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java +13 -9
- package/android/common/src/main/java/com/marianhello/bgloc/provider/DistanceFilterLocationProvider.java +29 -40
- package/android/common/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java +14 -34
- package/android/common/src/main/java/com/marianhello/bgloc/sensor/SensorFusionDetector.java +199 -0
- package/android/common/src/main/java/com/marianhello/bgloc/service/LocationServiceImpl.java +305 -6
- package/android/common/src/main/java/com/marianhello/bgloc/service/LocationServiceProxy.java +14 -2
- package/android/common/src/main/java/com/marianhello/bgloc/sync/SyncAdapter.java +50 -3
- package/android/dependencies.gradle +0 -3
- package/angular/background-geolocation-events.ts +21 -0
- package/angular/background-geolocation.service.ts +63 -0
- package/angular/dist/background-geolocation-events.d.ts +18 -1
- package/angular/dist/background-geolocation.service.d.ts +36 -0
- package/angular/dist/esm2022/background-geolocation-events.mjs +22 -1
- package/angular/dist/esm2022/background-geolocation.service.mjs +35 -1
- package/angular/dist/fesm2022/josuelmm-cordova-background-geolocation.mjs +55 -0
- package/angular/dist/fesm2022/josuelmm-cordova-background-geolocation.mjs.map +1 -1
- package/ios/CDVBackgroundGeolocation/CDVBackgroundGeolocation.m +312 -1
- package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.h +22 -0
- package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m +400 -15
- package/ios/common/BackgroundGeolocation/MAURBackgroundSync.h +12 -0
- package/ios/common/BackgroundGeolocation/MAURBackgroundSync.m +83 -5
- package/ios/common/BackgroundGeolocation/MAURConfig.h +15 -0
- package/ios/common/BackgroundGeolocation/MAURConfig.m +100 -3
- package/ios/common/BackgroundGeolocation/MAURDistanceFilterLocationProvider.m +29 -2
- package/ios/common/BackgroundGeolocation/MAURPostLocationTask.h +4 -0
- package/ios/common/BackgroundGeolocation/MAURPostLocationTask.m +97 -44
- package/ios/common/BackgroundGeolocation/MAURSensorFusionDetector.h +41 -0
- package/ios/common/BackgroundGeolocation/MAURSensorFusionDetector.m +137 -0
- package/ios/common/BackgroundGeolocation/MAURUrlTemplateResolver.h +31 -0
- package/ios/common/BackgroundGeolocation/MAURUrlTemplateResolver.m +107 -0
- package/package.json +41 -1
- package/plugin.xml +19 -8
- package/www/BackgroundGeolocation.d.ts +517 -3
- package/www/BackgroundGeolocation.js +54 -1
- package/RELEASE.MD +0 -16
|
@@ -6,7 +6,6 @@ import android.content.BroadcastReceiver;
|
|
|
6
6
|
import android.content.Context;
|
|
7
7
|
import android.content.Intent;
|
|
8
8
|
import android.content.IntentFilter;
|
|
9
|
-
import android.location.Criteria;
|
|
10
9
|
import android.location.Location;
|
|
11
10
|
import android.location.LocationListener;
|
|
12
11
|
import android.location.LocationManager;
|
|
@@ -55,8 +54,6 @@ public class DistanceFilterLocationProvider extends AbstractLocationProvider imp
|
|
|
55
54
|
private PendingIntent singleUpdatePI;
|
|
56
55
|
private Integer scaledDistanceFilter;
|
|
57
56
|
|
|
58
|
-
private Criteria criteria;
|
|
59
|
-
|
|
60
57
|
private LocationManager locationManager;
|
|
61
58
|
private AlarmManager alarmManager;
|
|
62
59
|
|
|
@@ -110,12 +107,20 @@ public class DistanceFilterLocationProvider extends AbstractLocationProvider imp
|
|
|
110
107
|
singleUpdatePI = PendingIntent.getBroadcast(mContext, 9003, singleLocationUpdateIntent, cancelCurrentFlag);
|
|
111
108
|
registerReceiver(singleUpdateReceiver, new IntentFilter(SINGLE_LOCATION_UPDATE_ACTION));
|
|
112
109
|
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
// v3.4 Phase 3: Criteria API removed (deprecated since Android 12 / API 31).
|
|
111
|
+
// Provider selection is now explicit (GPS-first / Network-fallback) via pickProvider().
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** v3.4 Phase 3: replaces getBestProvider(criteria, true). */
|
|
115
|
+
private String pickProvider() {
|
|
116
|
+
if (locationManager == null) return null;
|
|
117
|
+
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
|
118
|
+
return LocationManager.GPS_PROVIDER;
|
|
119
|
+
}
|
|
120
|
+
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
|
|
121
|
+
return LocationManager.NETWORK_PROVIDER;
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
119
124
|
}
|
|
120
125
|
|
|
121
126
|
@Override
|
|
@@ -209,9 +214,6 @@ public class DistanceFilterLocationProvider extends AbstractLocationProvider imp
|
|
|
209
214
|
|
|
210
215
|
try {
|
|
211
216
|
locationManager.removeUpdates(this);
|
|
212
|
-
criteria.setAccuracy(Criteria.ACCURACY_FINE);
|
|
213
|
-
criteria.setHorizontalAccuracy(translateDesiredAccuracy(mConfig.getDesiredAccuracy()));
|
|
214
|
-
criteria.setPowerRequirement(Criteria.POWER_HIGH);
|
|
215
217
|
|
|
216
218
|
if (isMoving) {
|
|
217
219
|
// setPace can be called while moving, after distanceFilter has been recalculated. We don't want to re-acquire velocity in this case.
|
|
@@ -228,18 +230,15 @@ public class DistanceFilterLocationProvider extends AbstractLocationProvider imp
|
|
|
228
230
|
// Turn on each provider aggressively for a short period of time
|
|
229
231
|
List<String> matchingProviders = locationManager.getAllProviders();
|
|
230
232
|
for (String provider: matchingProviders) {
|
|
231
|
-
if (
|
|
233
|
+
if (!LocationManager.PASSIVE_PROVIDER.equals(provider)) {
|
|
232
234
|
logger.info("Requesting location updates from provider {}", provider);
|
|
233
235
|
locationManager.requestLocationUpdates(provider, 0, 0, this);
|
|
234
236
|
}
|
|
235
237
|
}
|
|
236
238
|
} else {
|
|
237
|
-
String provider =
|
|
238
|
-
if (Build.VERSION.SDK_INT > 30 && locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
|
239
|
-
provider = LocationManager.GPS_PROVIDER;
|
|
240
|
-
}
|
|
239
|
+
String provider = pickProvider();
|
|
241
240
|
if (provider == null) {
|
|
242
|
-
logger.warn("No
|
|
241
|
+
logger.warn("No location provider available (GPS and Network disabled)");
|
|
243
242
|
return;
|
|
244
243
|
}
|
|
245
244
|
logger.info("Requesting location updates from provider {}", provider);
|
|
@@ -251,23 +250,8 @@ public class DistanceFilterLocationProvider extends AbstractLocationProvider imp
|
|
|
251
250
|
}
|
|
252
251
|
}
|
|
253
252
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
* 0: most aggressive, most accurate, worst battery drain
|
|
257
|
-
* 1000: least aggressive, least accurate, best for battery.
|
|
258
|
-
*/
|
|
259
|
-
private int translateDesiredAccuracy(Integer accuracy) {
|
|
260
|
-
if (accuracy == null) {
|
|
261
|
-
return Criteria.ACCURACY_MEDIUM;
|
|
262
|
-
}
|
|
263
|
-
if (accuracy >= 1000) {
|
|
264
|
-
return Criteria.ACCURACY_LOW;
|
|
265
|
-
}
|
|
266
|
-
if (accuracy >= 100) {
|
|
267
|
-
return Criteria.ACCURACY_MEDIUM;
|
|
268
|
-
}
|
|
269
|
-
return Criteria.ACCURACY_HIGH;
|
|
270
|
-
}
|
|
253
|
+
// v3.4 Phase 3: translateDesiredAccuracy(...) returning Criteria.ACCURACY_* removed.
|
|
254
|
+
// Provider selection no longer depends on Criteria; pickProvider() chooses GPS-first.
|
|
271
255
|
|
|
272
256
|
/**
|
|
273
257
|
* Returns the most accurate and timely previously detected location.
|
|
@@ -533,14 +517,19 @@ public class DistanceFilterLocationProvider extends AbstractLocationProvider imp
|
|
|
533
517
|
logger.info("Stationary location monitor fired");
|
|
534
518
|
playDebugTone(Tone.DIALTONE);
|
|
535
519
|
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
520
|
+
// v3.4 Phase 3: Criteria-based requestSingleUpdate removed (deprecated since API 31).
|
|
521
|
+
// Use the provider-string overload, which is still supported and stable.
|
|
522
|
+
String provider = pickProvider();
|
|
523
|
+
if (provider == null) {
|
|
524
|
+
logger.warn("Stationary monitor: no provider available");
|
|
525
|
+
return;
|
|
526
|
+
}
|
|
540
527
|
try {
|
|
541
|
-
locationManager.requestSingleUpdate(
|
|
528
|
+
locationManager.requestSingleUpdate(provider, singleUpdatePI);
|
|
542
529
|
} catch (SecurityException e) {
|
|
543
530
|
logger.error("Security exception: {}", e.getMessage());
|
|
531
|
+
} catch (IllegalArgumentException e) {
|
|
532
|
+
logger.warn("requestSingleUpdate failed: {}", e.getMessage());
|
|
544
533
|
}
|
|
545
534
|
}
|
|
546
535
|
}
|
package/android/common/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
package com.marianhello.bgloc.provider;
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
|
-
import android.location.Criteria;
|
|
5
4
|
import android.location.Location;
|
|
6
5
|
import android.location.LocationListener;
|
|
7
6
|
import android.location.LocationManager;
|
|
8
7
|
import android.os.Bundle;
|
|
9
8
|
|
|
10
9
|
import com.marianhello.bgloc.Config;
|
|
11
|
-
import com.marianhello.logging.LoggerManager;
|
|
12
10
|
|
|
13
11
|
public class RawLocationProvider extends AbstractLocationProvider implements LocationListener {
|
|
14
12
|
private LocationManager locationManager;
|
|
@@ -39,21 +37,10 @@ public class RawLocationProvider extends AbstractLocationProvider implements Loc
|
|
|
39
37
|
logger.warn("RawLocationProvider started without config");
|
|
40
38
|
return;
|
|
41
39
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (!gpsEnabled) {
|
|
45
|
-
Criteria criteria = new Criteria();
|
|
46
|
-
criteria.setAltitudeRequired(false);
|
|
47
|
-
criteria.setBearingRequired(false);
|
|
48
|
-
criteria.setSpeedRequired(true);
|
|
49
|
-
criteria.setCostAllowed(true);
|
|
50
|
-
criteria.setAccuracy(Criteria.ACCURACY_FINE);
|
|
51
|
-
criteria.setHorizontalAccuracy(translateDesiredAccuracy(mConfig.getDesiredAccuracy()));
|
|
52
|
-
criteria.setPowerRequirement(Criteria.POWER_HIGH);
|
|
53
|
-
provider = locationManager.getBestProvider(criteria, true);
|
|
54
|
-
}
|
|
40
|
+
// v3.4 Phase 3: explicit GPS/Network selection. Drops the deprecated Criteria + getBestProvider.
|
|
41
|
+
String provider = pickProvider();
|
|
55
42
|
if (provider == null) {
|
|
56
|
-
logger.warn("No location provider available (GPS
|
|
43
|
+
logger.warn("No location provider available (GPS and Network disabled)");
|
|
57
44
|
return;
|
|
58
45
|
}
|
|
59
46
|
try {
|
|
@@ -66,6 +53,17 @@ public class RawLocationProvider extends AbstractLocationProvider implements Loc
|
|
|
66
53
|
}
|
|
67
54
|
}
|
|
68
55
|
|
|
56
|
+
/** GPS first, fall back to Network. */
|
|
57
|
+
private String pickProvider() {
|
|
58
|
+
if (locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
|
|
59
|
+
return LocationManager.GPS_PROVIDER;
|
|
60
|
+
}
|
|
61
|
+
if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
|
|
62
|
+
return LocationManager.NETWORK_PROVIDER;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
69
67
|
@Override
|
|
70
68
|
public void onStop() {
|
|
71
69
|
if (!isStarted) {
|
|
@@ -118,24 +116,6 @@ public class RawLocationProvider extends AbstractLocationProvider implements Loc
|
|
|
118
116
|
logger.debug("Provider {} was disabled", provider);
|
|
119
117
|
}
|
|
120
118
|
|
|
121
|
-
/**
|
|
122
|
-
* Translates a number representing desired accuracy of Geolocation system from set [0, 10, 100, 1000].
|
|
123
|
-
* 0: most aggressive, most accurate, worst battery drain
|
|
124
|
-
* 1000: least aggressive, least accurate, best for battery.
|
|
125
|
-
*/
|
|
126
|
-
private int translateDesiredAccuracy(Integer accuracy) {
|
|
127
|
-
if (accuracy == null) {
|
|
128
|
-
return Criteria.ACCURACY_MEDIUM;
|
|
129
|
-
}
|
|
130
|
-
if (accuracy >= 1000) {
|
|
131
|
-
return Criteria.ACCURACY_LOW;
|
|
132
|
-
}
|
|
133
|
-
if (accuracy >= 100) {
|
|
134
|
-
return Criteria.ACCURACY_MEDIUM;
|
|
135
|
-
}
|
|
136
|
-
return Criteria.ACCURACY_HIGH;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
119
|
@Override
|
|
140
120
|
public void onDestroy() {
|
|
141
121
|
logger.debug("Destroying RawLocationProvider");
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
package com.marianhello.bgloc.sensor;
|
|
2
|
+
|
|
3
|
+
import android.content.Context;
|
|
4
|
+
import android.hardware.Sensor;
|
|
5
|
+
import android.hardware.SensorEvent;
|
|
6
|
+
import android.hardware.SensorEventListener;
|
|
7
|
+
import android.hardware.SensorManager;
|
|
8
|
+
import android.os.Handler;
|
|
9
|
+
import android.os.Looper;
|
|
10
|
+
import android.os.PowerManager;
|
|
11
|
+
|
|
12
|
+
import com.marianhello.bgloc.data.BackgroundLocation;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* v4.2 Phase 8 — Real sensor fusion detector.
|
|
16
|
+
*
|
|
17
|
+
* Samples linear acceleration (TYPE_LINEAR_ACCELERATION, gravity removed) and
|
|
18
|
+
* gyroscope (TYPE_GYROSCOPE) at SENSOR_DELAY_GAME (~50 Hz). Used to refine
|
|
19
|
+
* possibleCrash and to detect phoneUsageWhileDriving. Pure-Android, no JNI.
|
|
20
|
+
*
|
|
21
|
+
* Crash detection: |a| (m/s²) above {@code crashImpactG} g during a tripActive
|
|
22
|
+
* window emits {@link Listener#onPossibleCrash}. Combined with the GPS-derived
|
|
23
|
+
* heuristic in {@link com.marianhello.bgloc.driving.DrivingEventsDetector},
|
|
24
|
+
* this gives a far higher-confidence signal at low speeds (parking-lot impact)
|
|
25
|
+
* where GPS alone misses.
|
|
26
|
+
*
|
|
27
|
+
* phoneUsageWhileDriving: while {@code tripActive} is true, if the screen turns
|
|
28
|
+
* on and the user produces touch-shaped jitter on the device for a sustained
|
|
29
|
+
* window, fires {@link Listener#onPhoneUsageWhileDriving}. Conservative — designed
|
|
30
|
+
* to avoid false-positives from passenger usage by tying to {@code tripActive}.
|
|
31
|
+
*/
|
|
32
|
+
public class SensorFusionDetector implements SensorEventListener {
|
|
33
|
+
|
|
34
|
+
public interface Listener {
|
|
35
|
+
/** Triggered when |a| exceeds crashImpactG while tripActive. */
|
|
36
|
+
void onSensorCrash(BackgroundLocation lastLocation, double impactG);
|
|
37
|
+
/** Screen on + sustained device interaction during tripActive. */
|
|
38
|
+
void onPhoneUsageWhileDriving(BackgroundLocation lastLocation);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public static class Config {
|
|
42
|
+
public boolean enabled = false;
|
|
43
|
+
/** Crash threshold in g. 1g = 9.81 m/s². Default 3g. */
|
|
44
|
+
public double crashImpactG = 3.0;
|
|
45
|
+
/** Cooldown between repeated crash detections. */
|
|
46
|
+
public long crashCooldownMs = 10_000;
|
|
47
|
+
/** Min sustained gyro+accel jitter window for phoneUsage. */
|
|
48
|
+
public long phoneUsageWindowMs = 4_000;
|
|
49
|
+
/** Cooldown between repeated phone-usage events. */
|
|
50
|
+
public long phoneUsageCooldownMs = 60_000;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private static final float G = 9.80665f;
|
|
54
|
+
|
|
55
|
+
private final Context appContext;
|
|
56
|
+
private final Listener listener;
|
|
57
|
+
private final SensorManager sensorManager;
|
|
58
|
+
private final Sensor linearAccel;
|
|
59
|
+
private final Sensor gyroscope;
|
|
60
|
+
private final PowerManager powerManager;
|
|
61
|
+
private final Handler handler;
|
|
62
|
+
|
|
63
|
+
private Config cfg = new Config();
|
|
64
|
+
private boolean started = false;
|
|
65
|
+
private boolean tripActive = false;
|
|
66
|
+
private BackgroundLocation lastLocation;
|
|
67
|
+
|
|
68
|
+
private long lastCrashAt = 0L;
|
|
69
|
+
private long lastPhoneUsageAt = 0L;
|
|
70
|
+
|
|
71
|
+
// phoneUsage state
|
|
72
|
+
private long jitterAboveSince = 0L;
|
|
73
|
+
private static final double JITTER_GYRO_RAD_S = 0.7; // ~40 deg/s
|
|
74
|
+
private static final double JITTER_ACCEL_MPS2 = 0.5; // small accel, hand movement
|
|
75
|
+
|
|
76
|
+
public SensorFusionDetector(Context context, Listener listener) {
|
|
77
|
+
this.appContext = context.getApplicationContext();
|
|
78
|
+
this.listener = listener;
|
|
79
|
+
this.sensorManager = (SensorManager) appContext.getSystemService(Context.SENSOR_SERVICE);
|
|
80
|
+
this.linearAccel = sensorManager != null ? sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION) : null;
|
|
81
|
+
this.gyroscope = sensorManager != null ? sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) : null;
|
|
82
|
+
this.powerManager = (PowerManager) appContext.getSystemService(Context.POWER_SERVICE);
|
|
83
|
+
this.handler = new Handler(Looper.getMainLooper());
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public synchronized void setConfig(Config c) {
|
|
87
|
+
if (c != null) this.cfg = c;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
public synchronized boolean isAvailable() {
|
|
91
|
+
return sensorManager != null && linearAccel != null;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Start sampling sensors. Idempotent. */
|
|
95
|
+
public synchronized void start() {
|
|
96
|
+
if (started || !cfg.enabled || sensorManager == null) return;
|
|
97
|
+
if (linearAccel != null) {
|
|
98
|
+
sensorManager.registerListener(this, linearAccel, SensorManager.SENSOR_DELAY_GAME, handler);
|
|
99
|
+
}
|
|
100
|
+
if (gyroscope != null) {
|
|
101
|
+
sensorManager.registerListener(this, gyroscope, SensorManager.SENSOR_DELAY_GAME, handler);
|
|
102
|
+
}
|
|
103
|
+
started = true;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Stop sampling. Idempotent. */
|
|
107
|
+
public synchronized void stop() {
|
|
108
|
+
if (!started) return;
|
|
109
|
+
if (sensorManager != null) sensorManager.unregisterListener(this);
|
|
110
|
+
started = false;
|
|
111
|
+
jitterAboveSince = 0L;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Called by detector host whenever the GPS layer marks tripActive on/off. */
|
|
115
|
+
public synchronized void setTripActive(boolean active) {
|
|
116
|
+
this.tripActive = active;
|
|
117
|
+
if (!active) jitterAboveSince = 0L;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Last known location for event payload. Updated by host. */
|
|
121
|
+
public synchronized void setLastLocation(BackgroundLocation loc) {
|
|
122
|
+
this.lastLocation = loc;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@Override public void onAccuracyChanged(Sensor sensor, int accuracy) { /* ignore */ }
|
|
126
|
+
|
|
127
|
+
@Override
|
|
128
|
+
public void onSensorChanged(SensorEvent event) {
|
|
129
|
+
Listener l;
|
|
130
|
+
Config c;
|
|
131
|
+
boolean tripActiveNow;
|
|
132
|
+
BackgroundLocation loc;
|
|
133
|
+
synchronized (this) {
|
|
134
|
+
l = this.listener;
|
|
135
|
+
c = this.cfg;
|
|
136
|
+
tripActiveNow = this.tripActive;
|
|
137
|
+
loc = this.lastLocation;
|
|
138
|
+
}
|
|
139
|
+
if (l == null || c == null || !c.enabled) return;
|
|
140
|
+
|
|
141
|
+
long now = System.currentTimeMillis();
|
|
142
|
+
|
|
143
|
+
if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
|
|
144
|
+
float ax = event.values[0], ay = event.values[1], az = event.values[2];
|
|
145
|
+
double mag = Math.sqrt(ax * ax + ay * ay + az * az);
|
|
146
|
+
double gMag = mag / G;
|
|
147
|
+
|
|
148
|
+
// Crash: high impact during a trip.
|
|
149
|
+
if (tripActiveNow && c.crashImpactG > 0 && gMag >= c.crashImpactG
|
|
150
|
+
&& (now - lastCrashAt) >= c.crashCooldownMs) {
|
|
151
|
+
lastCrashAt = now;
|
|
152
|
+
l.onSensorCrash(loc, gMag);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Phone usage signal: small accel jitter during trip + screen on.
|
|
156
|
+
evaluatePhoneUsage(now, mag, /*gyroMag*/ -1, c, l, tripActiveNow, loc);
|
|
157
|
+
} else if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
|
|
158
|
+
float gx = event.values[0], gy = event.values[1], gz = event.values[2];
|
|
159
|
+
double gyroMag = Math.sqrt(gx * gx + gy * gy + gz * gz);
|
|
160
|
+
evaluatePhoneUsage(now, /*accelMag*/ -1, gyroMag, c, l, tripActiveNow, loc);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
private void evaluatePhoneUsage(long now,
|
|
165
|
+
double accelMag,
|
|
166
|
+
double gyroMag,
|
|
167
|
+
Config c,
|
|
168
|
+
Listener l,
|
|
169
|
+
boolean tripActiveNow,
|
|
170
|
+
BackgroundLocation loc) {
|
|
171
|
+
if (!tripActiveNow) { jitterAboveSince = 0L; return; }
|
|
172
|
+
if (powerManager == null || !isScreenOn()) { jitterAboveSince = 0L; return; }
|
|
173
|
+
|
|
174
|
+
boolean above = (accelMag >= 0 && accelMag >= JITTER_ACCEL_MPS2)
|
|
175
|
+
|| (gyroMag >= 0 && gyroMag >= JITTER_GYRO_RAD_S);
|
|
176
|
+
if (above) {
|
|
177
|
+
if (jitterAboveSince == 0L) jitterAboveSince = now;
|
|
178
|
+
if ((now - jitterAboveSince) >= c.phoneUsageWindowMs
|
|
179
|
+
&& (now - lastPhoneUsageAt) >= c.phoneUsageCooldownMs) {
|
|
180
|
+
lastPhoneUsageAt = now;
|
|
181
|
+
jitterAboveSince = 0L;
|
|
182
|
+
l.onPhoneUsageWhileDriving(loc);
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
jitterAboveSince = 0L;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@SuppressWarnings("deprecation")
|
|
190
|
+
private boolean isScreenOn() {
|
|
191
|
+
if (powerManager == null) return false;
|
|
192
|
+
try {
|
|
193
|
+
// isInteractive added API 20; we target >= 21 elsewhere, but guard anyway.
|
|
194
|
+
return powerManager.isInteractive();
|
|
195
|
+
} catch (Throwable t) {
|
|
196
|
+
return powerManager.isScreenOn();
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|