@josuelmm/capacitor-background-geolocation 1.0.0

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.
Files changed (207) hide show
  1. package/JosuelmmCapacitorBackgroundGeolocation.podspec +34 -0
  2. package/LICENSE +17 -0
  3. package/NOTICE.md +32 -0
  4. package/Package.swift +45 -0
  5. package/README.md +402 -0
  6. package/android/build.gradle +79 -0
  7. package/android/proguard-rules.pro +1 -0
  8. package/android/src/main/AndroidManifest.xml +83 -0
  9. package/android/src/main/java/com/evgenii/jsevaluator/HandlerWrapper.java +18 -0
  10. package/android/src/main/java/com/evgenii/jsevaluator/JavaScriptInterface.java +22 -0
  11. package/android/src/main/java/com/evgenii/jsevaluator/JsEvaluator.java +133 -0
  12. package/android/src/main/java/com/evgenii/jsevaluator/JsFunctionCallFormatter.java +37 -0
  13. package/android/src/main/java/com/evgenii/jsevaluator/WebViewWrapper.java +71 -0
  14. package/android/src/main/java/com/evgenii/jsevaluator/interfaces/CallJavaResultInterface.java +8 -0
  15. package/android/src/main/java/com/evgenii/jsevaluator/interfaces/HandlerWrapperInterface.java +5 -0
  16. package/android/src/main/java/com/evgenii/jsevaluator/interfaces/JsCallback.java +10 -0
  17. package/android/src/main/java/com/evgenii/jsevaluator/interfaces/JsEvaluatorInterface.java +18 -0
  18. package/android/src/main/java/com/evgenii/jsevaluator/interfaces/WebViewWrapperInterface.java +14 -0
  19. package/android/src/main/java/com/josuelmm/capacitor/backgroundgeolocation/BackgroundGeolocationPlugin.java +898 -0
  20. package/android/src/main/java/com/josuelmm/capacitor/backgroundgeolocation/ConfigMapper.java +303 -0
  21. package/android/src/main/java/com/josuelmm/capacitor/backgroundgeolocation/HeadlessTaskRegistry.java +34 -0
  22. package/android/src/main/java/com/josuelmm/capacitor/backgroundgeolocation/JsEvaluatorTaskRunner.java +63 -0
  23. package/android/src/main/java/com/marianhello/bgloc/BackgroundGeolocationFacade.java +699 -0
  24. package/android/src/main/java/com/marianhello/bgloc/BootCompletedReceiver.java +103 -0
  25. package/android/src/main/java/com/marianhello/bgloc/Config.java +1155 -0
  26. package/android/src/main/java/com/marianhello/bgloc/ConnectivityListener.java +5 -0
  27. package/android/src/main/java/com/marianhello/bgloc/HttpPostService.java +362 -0
  28. package/android/src/main/java/com/marianhello/bgloc/LocationManager.java +138 -0
  29. package/android/src/main/java/com/marianhello/bgloc/PluginDelegate.java +45 -0
  30. package/android/src/main/java/com/marianhello/bgloc/PluginException.java +38 -0
  31. package/android/src/main/java/com/marianhello/bgloc/PostLocationTask.java +238 -0
  32. package/android/src/main/java/com/marianhello/bgloc/ResourceResolver.java +55 -0
  33. package/android/src/main/java/com/marianhello/bgloc/data/AbstractLocationTemplate.java +69 -0
  34. package/android/src/main/java/com/marianhello/bgloc/data/ArrayListLocationTemplate.java +88 -0
  35. package/android/src/main/java/com/marianhello/bgloc/data/BackgroundActivity.java +108 -0
  36. package/android/src/main/java/com/marianhello/bgloc/data/BackgroundLocation.java +1088 -0
  37. package/android/src/main/java/com/marianhello/bgloc/data/ConfigJsonMapper.java +211 -0
  38. package/android/src/main/java/com/marianhello/bgloc/data/ConfigurationDAO.java +13 -0
  39. package/android/src/main/java/com/marianhello/bgloc/data/DAOFactory.java +17 -0
  40. package/android/src/main/java/com/marianhello/bgloc/data/HashMapLocationTemplate.java +82 -0
  41. package/android/src/main/java/com/marianhello/bgloc/data/LocationDAO.java +27 -0
  42. package/android/src/main/java/com/marianhello/bgloc/data/LocationTemplate.java +12 -0
  43. package/android/src/main/java/com/marianhello/bgloc/data/LocationTemplateFactory.java +71 -0
  44. package/android/src/main/java/com/marianhello/bgloc/data/LocationTransform.java +19 -0
  45. package/android/src/main/java/com/marianhello/bgloc/data/SessionLocationDAO.java +18 -0
  46. package/android/src/main/java/com/marianhello/bgloc/data/provider/ContentProviderLocationDAO.java +406 -0
  47. package/android/src/main/java/com/marianhello/bgloc/data/provider/LocationContentProvider.java +321 -0
  48. package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationContract.java +94 -0
  49. package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteConfigurationDAO.java +227 -0
  50. package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteLocationContract.java +122 -0
  51. package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteLocationDAO.java +550 -0
  52. package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteOpenHelper.java +189 -0
  53. package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteSessionContract.java +74 -0
  54. package/android/src/main/java/com/marianhello/bgloc/data/sqlite/SQLiteSessionLocationDAO.java +169 -0
  55. package/android/src/main/java/com/marianhello/bgloc/driving/DrivingEventsDetector.java +265 -0
  56. package/android/src/main/java/com/marianhello/bgloc/headless/AbstractTaskRunner.java +15 -0
  57. package/android/src/main/java/com/marianhello/bgloc/headless/ActivityTask.java +48 -0
  58. package/android/src/main/java/com/marianhello/bgloc/headless/JsCallback.java +10 -0
  59. package/android/src/main/java/com/marianhello/bgloc/headless/LocationTask.java +60 -0
  60. package/android/src/main/java/com/marianhello/bgloc/headless/StationaryTask.java +25 -0
  61. package/android/src/main/java/com/marianhello/bgloc/headless/Task.java +8 -0
  62. package/android/src/main/java/com/marianhello/bgloc/headless/TaskRunner.java +5 -0
  63. package/android/src/main/java/com/marianhello/bgloc/headless/TaskRunnerFactory.java +8 -0
  64. package/android/src/main/java/com/marianhello/bgloc/http/UrlTemplateResolver.java +115 -0
  65. package/android/src/main/java/com/marianhello/bgloc/oem/BatteryOemHelper.java +214 -0
  66. package/android/src/main/java/com/marianhello/bgloc/provider/AbstractLocationProvider.java +218 -0
  67. package/android/src/main/java/com/marianhello/bgloc/provider/ActivityRecognitionLocationProvider.java +385 -0
  68. package/android/src/main/java/com/marianhello/bgloc/provider/DistanceFilterLocationProvider.java +685 -0
  69. package/android/src/main/java/com/marianhello/bgloc/provider/LocationProvider.java +32 -0
  70. package/android/src/main/java/com/marianhello/bgloc/provider/LocationProviderFactory.java +47 -0
  71. package/android/src/main/java/com/marianhello/bgloc/provider/ProviderDelegate.java +12 -0
  72. package/android/src/main/java/com/marianhello/bgloc/provider/RawLocationProvider.java +175 -0
  73. package/android/src/main/java/com/marianhello/bgloc/sensor/SensorFusionDetector.java +199 -0
  74. package/android/src/main/java/com/marianhello/bgloc/service/LocationService.java +16 -0
  75. package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceImpl.java +1531 -0
  76. package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceInfo.java +6 -0
  77. package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceInfoImpl.java +41 -0
  78. package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceIntentBuilder.java +203 -0
  79. package/android/src/main/java/com/marianhello/bgloc/service/LocationServiceProxy.java +156 -0
  80. package/android/src/main/java/com/marianhello/bgloc/sync/AccountHelper.java +39 -0
  81. package/android/src/main/java/com/marianhello/bgloc/sync/Authenticator.java +68 -0
  82. package/android/src/main/java/com/marianhello/bgloc/sync/AuthenticatorService.java +28 -0
  83. package/android/src/main/java/com/marianhello/bgloc/sync/BatchManager.java +311 -0
  84. package/android/src/main/java/com/marianhello/bgloc/sync/NotificationHelper.java +148 -0
  85. package/android/src/main/java/com/marianhello/bgloc/sync/SyncAdapter.java +301 -0
  86. package/android/src/main/java/com/marianhello/bgloc/sync/SyncService.java +68 -0
  87. package/android/src/main/java/com/marianhello/logging/DBLogReader.java +208 -0
  88. package/android/src/main/java/com/marianhello/logging/LogEntry.java +99 -0
  89. package/android/src/main/java/com/marianhello/logging/LoggerManager.java +70 -0
  90. package/android/src/main/java/com/marianhello/logging/UncaughtExceptionLogger.java +36 -0
  91. package/android/src/main/java/com/marianhello/utils/CloneHelper.java +22 -0
  92. package/android/src/main/java/com/marianhello/utils/Convert.java +56 -0
  93. package/android/src/main/java/com/marianhello/utils/TextUtils.java +72 -0
  94. package/android/src/main/java/com/marianhello/utils/ToneGenerator.java +68 -0
  95. package/android/src/main/java/org/apache/commons/io/Charsets.java +153 -0
  96. package/android/src/main/java/org/apache/commons/io/input/ReversedLinesFileReader.java +344 -0
  97. package/android/src/main/java/org/chromium/content/browser/ThreadUtils.java +134 -0
  98. package/android/src/main/java/ru/andremoniy/sqlbuilder/SqlExpression.java +398 -0
  99. package/android/src/main/java/ru/andremoniy/sqlbuilder/SqlSelectStatement.java +671 -0
  100. package/android/src/main/java/ru/andremoniy/sqlbuilder/SqlStatement.java +29 -0
  101. package/android/src/main/java/ru/andremoniy/utils/TextUtils.java +61 -0
  102. package/android/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  103. package/android/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  104. package/android/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  105. package/android/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  106. package/android/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  107. package/android/src/main/res/values/strings.xml +15 -0
  108. package/android/src/main/res/xml/authenticator.xml +7 -0
  109. package/android/src/main/res/xml/syncadapter.xml +9 -0
  110. package/dist/esm/definitions.d.ts +1052 -0
  111. package/dist/esm/definitions.js +142 -0
  112. package/dist/esm/definitions.js.map +1 -0
  113. package/dist/esm/index.d.ts +8 -0
  114. package/dist/esm/index.js +23 -0
  115. package/dist/esm/index.js.map +1 -0
  116. package/dist/esm/web.d.ts +92 -0
  117. package/dist/esm/web.js +242 -0
  118. package/dist/esm/web.js.map +1 -0
  119. package/dist/plugin.cjs.js +415 -0
  120. package/dist/plugin.cjs.js.map +1 -0
  121. package/dist/plugin.js +418 -0
  122. package/dist/plugin.js.map +1 -0
  123. package/ios/Sources/BackgroundGeolocationPlugin/BackgroundGeolocationPlugin-Bridging-Header.h +18 -0
  124. package/ios/Sources/BackgroundGeolocationPlugin/BackgroundGeolocationPlugin.m +52 -0
  125. package/ios/Sources/BackgroundGeolocationPlugin/BackgroundGeolocationPlugin.swift +750 -0
  126. package/ios/Tests/BackgroundGeolocationPluginTests/BackgroundGeolocationPluginTests.swift +12 -0
  127. package/ios/common/BackgroundGeolocation/CocoaLumberjack.h +1945 -0
  128. package/ios/common/BackgroundGeolocation/CocoaLumberjack.m +5255 -0
  129. package/ios/common/BackgroundGeolocation/FMDB.h +2357 -0
  130. package/ios/common/BackgroundGeolocation/FMDB.m +2672 -0
  131. package/ios/common/BackgroundGeolocation/FMDBLogger.h +42 -0
  132. package/ios/common/BackgroundGeolocation/FMDBLogger.m +264 -0
  133. package/ios/common/BackgroundGeolocation/INTULocationManager/INTUHeadingRequest.h +41 -0
  134. package/ios/common/BackgroundGeolocation/INTULocationManager/INTUHeadingRequest.m +68 -0
  135. package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationManager+Internal.h +33 -0
  136. package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationManager.h +178 -0
  137. package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationManager.m +1025 -0
  138. package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationRequest.h +103 -0
  139. package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationRequest.m +238 -0
  140. package/ios/common/BackgroundGeolocation/INTULocationManager/INTULocationRequestDefines.h +163 -0
  141. package/ios/common/BackgroundGeolocation/INTULocationManager/INTURequestIDGenerator.h +39 -0
  142. package/ios/common/BackgroundGeolocation/INTULocationManager/INTURequestIDGenerator.m +37 -0
  143. package/ios/common/BackgroundGeolocation/MAURAbstractLocationProvider.h +51 -0
  144. package/ios/common/BackgroundGeolocation/MAURAbstractLocationProvider.m +53 -0
  145. package/ios/common/BackgroundGeolocation/MAURActivity.h +23 -0
  146. package/ios/common/BackgroundGeolocation/MAURActivity.m +52 -0
  147. package/ios/common/BackgroundGeolocation/MAURActivityLocationProvider.h +18 -0
  148. package/ios/common/BackgroundGeolocation/MAURActivityLocationProvider.m +340 -0
  149. package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.h +88 -0
  150. package/ios/common/BackgroundGeolocation/MAURBackgroundGeolocationFacade.m +1193 -0
  151. package/ios/common/BackgroundGeolocation/MAURBackgroundSync.h +46 -0
  152. package/ios/common/BackgroundGeolocation/MAURBackgroundSync.m +283 -0
  153. package/ios/common/BackgroundGeolocation/MAURBackgroundTaskManager.h +25 -0
  154. package/ios/common/BackgroundGeolocation/MAURBackgroundTaskManager.m +105 -0
  155. package/ios/common/BackgroundGeolocation/MAURConfig.h +99 -0
  156. package/ios/common/BackgroundGeolocation/MAURConfig.m +636 -0
  157. package/ios/common/BackgroundGeolocation/MAURConfigurationContract.h +53 -0
  158. package/ios/common/BackgroundGeolocation/MAURConfigurationContract.m +54 -0
  159. package/ios/common/BackgroundGeolocation/MAURDistanceFilterLocationProvider.h +20 -0
  160. package/ios/common/BackgroundGeolocation/MAURDistanceFilterLocationProvider.m +550 -0
  161. package/ios/common/BackgroundGeolocation/MAURGeolocationOpenHelper.h +17 -0
  162. package/ios/common/BackgroundGeolocation/MAURGeolocationOpenHelper.m +124 -0
  163. package/ios/common/BackgroundGeolocation/MAURLocation.h +73 -0
  164. package/ios/common/BackgroundGeolocation/MAURLocation.m +392 -0
  165. package/ios/common/BackgroundGeolocation/MAURLocationContract.h +38 -0
  166. package/ios/common/BackgroundGeolocation/MAURLocationContract.m +39 -0
  167. package/ios/common/BackgroundGeolocation/MAURLocationManager.h +53 -0
  168. package/ios/common/BackgroundGeolocation/MAURLocationManager.m +305 -0
  169. package/ios/common/BackgroundGeolocation/MAURLogReader.h +26 -0
  170. package/ios/common/BackgroundGeolocation/MAURLogReader.m +122 -0
  171. package/ios/common/BackgroundGeolocation/MAURLogging.h +19 -0
  172. package/ios/common/BackgroundGeolocation/MAURPostLocationTask.h +53 -0
  173. package/ios/common/BackgroundGeolocation/MAURPostLocationTask.m +367 -0
  174. package/ios/common/BackgroundGeolocation/MAURProviderDelegate.h +52 -0
  175. package/ios/common/BackgroundGeolocation/MAURRawLocationProvider.h +18 -0
  176. package/ios/common/BackgroundGeolocation/MAURRawLocationProvider.m +138 -0
  177. package/ios/common/BackgroundGeolocation/MAURSQLiteConfigurationDAO.h +26 -0
  178. package/ios/common/BackgroundGeolocation/MAURSQLiteConfigurationDAO.m +335 -0
  179. package/ios/common/BackgroundGeolocation/MAURSQLiteHelper.h +57 -0
  180. package/ios/common/BackgroundGeolocation/MAURSQLiteHelper.m +93 -0
  181. package/ios/common/BackgroundGeolocation/MAURSQLiteLocationDAO.h +52 -0
  182. package/ios/common/BackgroundGeolocation/MAURSQLiteLocationDAO.m +520 -0
  183. package/ios/common/BackgroundGeolocation/MAURSQLiteOpenHelper.h +32 -0
  184. package/ios/common/BackgroundGeolocation/MAURSQLiteOpenHelper.m +276 -0
  185. package/ios/common/BackgroundGeolocation/MAURSensorFusionDetector.h +41 -0
  186. package/ios/common/BackgroundGeolocation/MAURSensorFusionDetector.m +137 -0
  187. package/ios/common/BackgroundGeolocation/MAURSessionLocationContract.h +29 -0
  188. package/ios/common/BackgroundGeolocation/MAURSessionLocationContract.m +31 -0
  189. package/ios/common/BackgroundGeolocation/MAURSessionLocationDAO.h +25 -0
  190. package/ios/common/BackgroundGeolocation/MAURSessionLocationDAO.m +153 -0
  191. package/ios/common/BackgroundGeolocation/MAURUncaughtExceptionLogger.h +20 -0
  192. package/ios/common/BackgroundGeolocation/MAURUncaughtExceptionLogger.m +62 -0
  193. package/ios/common/BackgroundGeolocation/MAURUrlTemplateResolver.h +31 -0
  194. package/ios/common/BackgroundGeolocation/MAURUrlTemplateResolver.m +107 -0
  195. package/ios/common/BackgroundGeolocation/Reachability.h +102 -0
  196. package/ios/common/BackgroundGeolocation/Reachability.m +475 -0
  197. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/README.md +170 -0
  198. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/ext/NSString+ZIMString.h +55 -0
  199. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/ext/NSString+ZIMString.m +47 -0
  200. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlDataManipulationCommand.h +27 -0
  201. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlExpression.h +250 -0
  202. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlExpression.m +259 -0
  203. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlSelectStatement.h +360 -0
  204. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlSelectStatement.m +427 -0
  205. package/ios/common/BackgroundGeolocation/SQLQueryBuilder/sql/ZIMSqlStatement.h +37 -0
  206. package/ios/common/BackgroundGeolocation/module.modulemap +16 -0
  207. package/package.json +82 -0
@@ -0,0 +1,1088 @@
1
+ package com.marianhello.bgloc.data;
2
+
3
+ import android.content.ContentValues;
4
+ import android.database.Cursor;
5
+ import android.location.Location;
6
+ import android.os.Build;
7
+ import android.os.Bundle;
8
+ import android.os.Parcel;
9
+ import android.os.Parcelable;
10
+ import androidx.core.util.TimeUtils;
11
+
12
+ import com.marianhello.bgloc.data.sqlite.SQLiteLocationContract.LocationEntry;
13
+
14
+ import org.json.JSONArray;
15
+ import org.json.JSONException;
16
+ import org.json.JSONObject;
17
+
18
+ public class BackgroundLocation implements Parcelable {
19
+ public static final int DELETED = 0;
20
+ public static final int POST_PENDING = 1;
21
+ public static final int SYNC_PENDING = 2;
22
+
23
+ private Long locationId = null;
24
+ private Integer locationProvider = null;
25
+ private Long batchStartMillis = null;
26
+ private String provider;
27
+ private double latitude = 0.0;
28
+ private double longitude = 0.0;
29
+ private long time = 0;
30
+ private long elapsedRealtimeNanos = 0;
31
+ private float accuracy = 0.0f;
32
+ private float verticalAccuracy = 0.0f;
33
+ private float speed = 0.0f;
34
+ private float bearing = 0.0f;
35
+ private double altitude = 0.0f;
36
+ private float radius = 0.0f;
37
+ private boolean hasAccuracy = false;
38
+ private boolean hasVerticalAccuracy = false;
39
+ private boolean hasAltitude = false;
40
+ private boolean hasSpeed = false;
41
+ private boolean hasBearing = false;
42
+ private boolean hasRadius = false;
43
+ private int mockFlags = 0x0000;
44
+ private int status = POST_PENDING;
45
+ private Bundle extras = null;
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
+
61
+ private static final long TWO_MINUTES_IN_NANOS = 1000000000L * 60 * 2;
62
+
63
+ public BackgroundLocation() {}
64
+
65
+ public BackgroundLocation(String provider) {
66
+ this.provider = provider;
67
+ }
68
+
69
+ /**
70
+ * Construct BackgroundLocation by copying properties from android Location.
71
+ * @param location
72
+ */
73
+ @Deprecated
74
+ public BackgroundLocation(Location location) {
75
+ this(BackgroundLocation.fromLocation(location));
76
+ }
77
+
78
+ @Deprecated
79
+ public BackgroundLocation(Integer locationProvider, Location location) {
80
+ this(location);
81
+ this.locationProvider = locationProvider;
82
+ }
83
+
84
+ /**
85
+ * Construct stationary BackgroundLocation.
86
+ * @param locationProvider
87
+ * @param location
88
+ * @param radius radius of stationary region
89
+ */
90
+ @Deprecated
91
+ public BackgroundLocation(Integer locationProvider, Location location, float radius) {
92
+ this(locationProvider, location);
93
+ setRadius(radius);
94
+ }
95
+
96
+ /**
97
+ * Construct a new Location object that is copied from an existing one.
98
+ * @param location
99
+ */
100
+ public BackgroundLocation(BackgroundLocation l) {
101
+ locationId = l.locationId;
102
+ locationProvider = l.locationProvider;
103
+ batchStartMillis = l.batchStartMillis;
104
+ provider = l.provider;
105
+ latitude = l.latitude;
106
+ longitude = l.longitude;
107
+ time = l.time;
108
+ elapsedRealtimeNanos = l.elapsedRealtimeNanos;
109
+ accuracy = l.accuracy;
110
+ verticalAccuracy = l.verticalAccuracy;
111
+ speed = l.speed;
112
+ bearing = l.bearing;
113
+ altitude = l.altitude;
114
+ radius = l.radius;
115
+ hasAccuracy = l.hasAccuracy;
116
+ hasVerticalAccuracy = l.hasVerticalAccuracy;
117
+ hasAltitude = l.hasAltitude;
118
+ hasSpeed = l.hasSpeed;
119
+ hasBearing = l.hasBearing;
120
+ hasRadius = l.hasRadius;
121
+ mockFlags = l.mockFlags;
122
+ status = l.status;
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;
130
+ }
131
+
132
+ private static BackgroundLocation fromParcel(Parcel in) {
133
+ BackgroundLocation l = new BackgroundLocation();
134
+
135
+ l.locationId = in.readLong();
136
+ l.locationProvider = in.readInt();
137
+ l.batchStartMillis = in.readLong();
138
+ l.provider = in.readString();
139
+ l.latitude = in.readDouble();
140
+ l.longitude = in.readDouble();
141
+ l.time = in.readLong();
142
+ l.elapsedRealtimeNanos = in.readLong();
143
+ l.accuracy = in.readFloat();
144
+ l.verticalAccuracy = in.readFloat();
145
+ l.speed = in.readFloat();
146
+ l.bearing = in.readFloat();
147
+ l.altitude = in.readDouble();
148
+ l.radius = in.readFloat();
149
+ l.hasAccuracy = in.readInt() != 0;
150
+ l.hasVerticalAccuracy = in.readInt() != 0;
151
+ l.hasAltitude = in.readInt() != 0;
152
+ l.hasSpeed = in.readInt() != 0;
153
+ l.hasBearing = in.readInt() != 0;
154
+ l.hasRadius = in.readInt() != 0;
155
+ l.mockFlags = in.readInt();
156
+ l.status = in.readInt();
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);
165
+
166
+ return l;
167
+ }
168
+
169
+ public static BackgroundLocation fromLocation(Location location) {
170
+ BackgroundLocation l = new BackgroundLocation();
171
+
172
+ l.provider = location.getProvider();
173
+ l.latitude = location.getLatitude();
174
+ l.longitude = location.getLongitude();
175
+ l.time = location.getTime();
176
+ l.accuracy = location.getAccuracy();
177
+ l.speed = location.getSpeed();
178
+ l.bearing = location.getBearing();
179
+ l.altitude = location.getAltitude();
180
+ l.hasAccuracy = location.hasAccuracy();
181
+ l.hasAltitude = location.hasAltitude();
182
+ l.hasSpeed = location.hasSpeed();
183
+ l.hasBearing = location.hasBearing();
184
+ l.extras = location.getExtras();
185
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
186
+ l.elapsedRealtimeNanos = location.getElapsedRealtimeNanos();
187
+ }
188
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
189
+ l.setIsFromMockProvider(location.isFromMockProvider());
190
+ }
191
+
192
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
193
+ l.verticalAccuracy = location.getVerticalAccuracyMeters();
194
+ l.hasVerticalAccuracy = location.hasVerticalAccuracy();
195
+ }
196
+
197
+ return l;
198
+ }
199
+
200
+ /**
201
+ * Create a new Location from a cursor
202
+ *
203
+ * @param c the cursor
204
+ * @return the note
205
+ */
206
+ public static BackgroundLocation fromCursor(Cursor c) {
207
+ BackgroundLocation l = new BackgroundLocation();
208
+
209
+ l.setProvider(c.getString(c.getColumnIndex(LocationEntry.COLUMN_NAME_PROVIDER)));
210
+ l.setTime(c.getLong(c.getColumnIndex(LocationEntry.COLUMN_NAME_TIME)));
211
+ if (c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_HAS_ACCURACY)) == 1) {
212
+ l.setAccuracy(c.getFloat(c.getColumnIndex(LocationEntry.COLUMN_NAME_ACCURACY)));
213
+ }
214
+ if (c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_HAS_VERTICAL_ACCURACY)) == 1) {
215
+ l.setVerticalAccuracy(c.getFloat(c.getColumnIndex(LocationEntry.COLUMN_NAME_VERTICAL_ACCURACY)));
216
+ }
217
+ if (c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_HAS_SPEED)) == 1) {
218
+ l.setSpeed(c.getFloat(c.getColumnIndex(LocationEntry.COLUMN_NAME_SPEED)));
219
+ }
220
+ if (c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_HAS_BEARING)) == 1) {
221
+ l.setBearing(c.getFloat(c.getColumnIndex(LocationEntry.COLUMN_NAME_BEARING)));
222
+ }
223
+ if (c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_HAS_ALTITUDE)) == 1) {
224
+ l.setAltitude(c.getDouble(c.getColumnIndex(LocationEntry.COLUMN_NAME_ALTITUDE)));
225
+ }
226
+ if (c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_HAS_RADIUS)) == 1) {
227
+ l.setRadius(c.getFloat(c.getColumnIndex(LocationEntry.COLUMN_NAME_RADIUS)));
228
+ }
229
+ l.setLatitude(c.getDouble(c.getColumnIndex(LocationEntry.COLUMN_NAME_LATITUDE)));
230
+ l.setLongitude(c.getDouble(c.getColumnIndex(LocationEntry.COLUMN_NAME_LONGITUDE)));
231
+ l.setLocationProvider(c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_LOCATION_PROVIDER)));
232
+ l.setBatchStartMillis(c.getLong(c.getColumnIndex(LocationEntry.COLUMN_NAME_BATCH_START_MILLIS)));
233
+ l.setStatus(c.getInt(c.getColumnIndex(LocationEntry.COLUMN_NAME_STATUS)));
234
+ l.setLocationId(c.getLong(c.getColumnIndex(LocationEntry._ID)));
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);
248
+
249
+ return l;
250
+ }
251
+
252
+ @Override
253
+ public int describeContents() {
254
+ return 0;
255
+ }
256
+
257
+ @Override
258
+ public void writeToParcel(Parcel dest, int flags) {
259
+ dest.writeLong(locationId);
260
+ dest.writeInt(locationProvider);
261
+ dest.writeLong(batchStartMillis);
262
+ dest.writeString(provider);
263
+ dest.writeDouble(latitude);
264
+ dest.writeDouble(longitude);
265
+ dest.writeLong(time);
266
+ dest.writeLong(elapsedRealtimeNanos);
267
+ dest.writeFloat(accuracy);
268
+ dest.writeFloat(verticalAccuracy);
269
+ dest.writeFloat(speed);
270
+ dest.writeFloat(bearing);
271
+ dest.writeDouble(altitude);
272
+ dest.writeFloat(radius);
273
+ dest.writeInt(hasAccuracy ? 1 : 0);
274
+ dest.writeInt(hasVerticalAccuracy ? 1 : 0);
275
+ dest.writeInt(hasAltitude ? 1 : 0);
276
+ dest.writeInt(hasSpeed ? 1 : 0);
277
+ dest.writeInt(hasBearing ? 1 : 0);
278
+ dest.writeInt(hasRadius ? 1 : 0);
279
+ dest.writeInt(mockFlags);
280
+ dest.writeInt(status);
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);
286
+ }
287
+
288
+ public static final Parcelable.Creator<BackgroundLocation> CREATOR
289
+ = new Parcelable.Creator<BackgroundLocation>() {
290
+ public BackgroundLocation createFromParcel(Parcel in) {
291
+ return BackgroundLocation.fromParcel(in);
292
+ }
293
+ public BackgroundLocation[] newArray(int size) {
294
+ return new BackgroundLocation[size];
295
+ }
296
+ };
297
+
298
+ public BackgroundLocation makeClone() {
299
+ return new BackgroundLocation(this);
300
+ }
301
+
302
+ /**
303
+ * Returns locationId if location was stored in db.
304
+ * @return locationId or null
305
+ */
306
+ public Long getLocationId() {
307
+ return locationId;
308
+ }
309
+
310
+
311
+ /**
312
+ * Sets locationId
313
+ * used when location was persisted into db and returned db id is used locationId
314
+ * @param locationId
315
+ */
316
+ public void setLocationId(Long locationId) {
317
+ this.locationId = locationId;
318
+ }
319
+
320
+ /**
321
+ * Returns location provider that generated this location.
322
+ * @return location provider id
323
+ */
324
+ public Integer getLocationProvider() {
325
+ return locationProvider;
326
+ }
327
+
328
+ /**
329
+ * Sets the location provider that generated this location.
330
+ * @param locationProvider
331
+ */
332
+ public void setLocationProvider(Integer locationProvider) {
333
+ this.locationProvider = locationProvider;
334
+ }
335
+
336
+ /**
337
+ * Returns batch start time in milliseconds when location is being synced with remote server.
338
+ * @return batch run time or null
339
+ */
340
+ public Long getBatchStartMillis() {
341
+ return batchStartMillis;
342
+ }
343
+
344
+ /**
345
+ * Sets batch start time
346
+ * @param batch run time in milliseconds
347
+ */
348
+ public void setBatchStartMillis(Long batchStartMillis) {
349
+ this.batchStartMillis = batchStartMillis;
350
+ }
351
+
352
+ /**
353
+ * Returns the name of the provider that generated this fix.
354
+ * @return the provider, or null if it has not been set
355
+ */
356
+ public String getProvider() {
357
+ return provider;
358
+ }
359
+
360
+ /**
361
+ * Sets the name of the provider that generated this fix.
362
+ */
363
+ public void setProvider(String provider) {
364
+ this.provider = provider;
365
+ }
366
+
367
+ /**
368
+ * Get the altitude if available, in meters above the WGS 84 reference
369
+ * ellipsoid.
370
+ *
371
+ * <p>If this location does not have an altitude then 0.0 is returned.
372
+ */
373
+ public double getLatitude() {
374
+ return latitude;
375
+ }
376
+
377
+ /**
378
+ * Set the altitude, in meters above the WGS 84 reference ellipsoid.
379
+ *
380
+ * <p>Following this call {@link #hasAltitude} will return true.
381
+ */
382
+ public void setLatitude(double latitude) {
383
+ this.latitude = latitude;
384
+ }
385
+
386
+ /**
387
+ * Get the longitude, in degrees.
388
+ *
389
+ * <p>All locations generated by the {@link LocationManager}
390
+ * will have a valid longitude.
391
+ */
392
+ public double getLongitude() {
393
+ return longitude;
394
+ }
395
+
396
+ /**
397
+ * Set the longitude, in degrees.
398
+ */
399
+ public void setLongitude(double longitude) {
400
+ this.longitude = longitude;
401
+ }
402
+
403
+
404
+ /**
405
+ * Return the UTC time of this fix, in milliseconds since January 1, 1970.
406
+ *
407
+ * <p>Note that the UTC time on a device is not monotonic: it
408
+ * can jump forwards or backwards unpredictably. So always use
409
+ * {@link #getElapsedRealtimeNanos} when calculating time deltas.
410
+ *
411
+ * <p>On the other hand, {@link #getTime} is useful for presenting
412
+ * a human readable time to the user, or for carefully comparing
413
+ * location fixes across reboot or across devices.
414
+ *
415
+ * <p>All locations generated by the {@link LocationManager}
416
+ * are guaranteed to have a valid UTC time, however remember that
417
+ * the system time may have changed since the location was generated.
418
+ *
419
+ * @return time of fix, in milliseconds since January 1, 1970.
420
+ */
421
+ public long getTime() {
422
+ return time;
423
+ }
424
+
425
+ /**
426
+ * Set the UTC time of this fix, in milliseconds since January 1,
427
+ * 1970.
428
+ *
429
+ * @param time UTC time of this fix, in milliseconds since January 1, 1970
430
+ */
431
+ public void setTime(long time) {
432
+ this.time = time;
433
+ }
434
+
435
+ /**
436
+ * Return the time of this fix, in elapsed real-time since system boot.
437
+ *
438
+ * <p>This value can be reliably compared to
439
+ * {@link android.os.SystemClock#elapsedRealtimeNanos},
440
+ * to calculate the age of a fix and to compare Location fixes. This
441
+ * is reliable because elapsed real-time is guaranteed monotonic for
442
+ * each system boot and continues to increment even when the system
443
+ * is in deep sleep (unlike {@link #getTime}.
444
+ *
445
+ * <p>All locations generated by the {@link LocationManager}
446
+ * are guaranteed to have a valid elapsed real-time.
447
+ *
448
+ * @return elapsed real-time of fix, in nanoseconds since system boot.
449
+ */
450
+ public long getElapsedRealtimeNanos() {
451
+ return elapsedRealtimeNanos;
452
+ }
453
+
454
+ /**
455
+ * Set the time of this fix, in elapsed real-time since system boot.
456
+ *
457
+ * @param time elapsed real-time of fix, in nanoseconds since system boot.
458
+ */
459
+ public void setElapsedRealtimeNanos(long elapsedRealtimeNanos) {
460
+ this.elapsedRealtimeNanos = elapsedRealtimeNanos;
461
+ }
462
+
463
+ /**
464
+ * Get the estimated accuracy of this location, in meters.
465
+ *
466
+ * <p>We define accuracy as the radius of 68% confidence. In other
467
+ * words, if you draw a circle centered at this location's
468
+ * latitude and longitude, and with a radius equal to the accuracy,
469
+ * then there is a 68% probability that the true location is inside
470
+ * the circle.
471
+ *
472
+ * <p>In statistical terms, it is assumed that location errors
473
+ * are random with a normal distribution, so the 68% confidence circle
474
+ * represents one standard deviation. Note that in practice, location
475
+ * errors do not always follow such a simple distribution.
476
+ *
477
+ * <p>This accuracy estimation is only concerned with horizontal
478
+ * accuracy, and does not indicate the accuracy of bearing,
479
+ * velocity or altitude if those are included in this Location.
480
+ *
481
+ * <p>If this location does not have an accuracy, then 0.0 is returned.
482
+ * All locations generated by the {@link LocationManager} include
483
+ * an accuracy.
484
+ */
485
+ public float getAccuracy() {
486
+ return accuracy;
487
+ }
488
+
489
+ /**
490
+ * Set the estimated accuracy of this location, meters.
491
+ *
492
+ * <p>See {@link #getAccuracy} for the definition of accuracy.
493
+ *
494
+ * <p>Following this call {@link #hasAccuracy} will return true.
495
+ */
496
+ public void setAccuracy(float accuracy) {
497
+ this.accuracy = accuracy;
498
+ this.hasAccuracy = true;
499
+ }
500
+
501
+ public float getVerticalAccuracy() {
502
+ return verticalAccuracy;
503
+ }
504
+
505
+ public void setVerticalAccuracy(float accuracy) {
506
+ this.verticalAccuracy = accuracy;
507
+ this.hasVerticalAccuracy = true;
508
+ }
509
+
510
+ /**
511
+ * Get the speed if it is available, in meters/second over ground.
512
+ *
513
+ * <p>If this location does not have a speed then 0.0 is returned.
514
+ */
515
+ public float getSpeed() {
516
+ return speed;
517
+ }
518
+
519
+ /**
520
+ * Set the speed, in meters/second over ground.
521
+ *
522
+ * <p>Following this call {@link #hasSpeed} will return true.
523
+ */
524
+ public void setSpeed(float speed) {
525
+ this.speed = speed;
526
+ this.hasSpeed = true;
527
+ }
528
+
529
+ /**
530
+ * Get the bearing, in degrees.
531
+ *
532
+ * <p>Bearing is the horizontal direction of travel of this device,
533
+ * and is not related to the device orientation. It is guaranteed to
534
+ * be in the range (0.0, 360.0] if the device has a bearing.
535
+ *
536
+ * <p>If this location does not have a bearing then 0.0 is returned.
537
+ */
538
+ public float getBearing() {
539
+ return bearing;
540
+ }
541
+
542
+ /**
543
+ * Set the bearing, in degrees.
544
+ *
545
+ * <p>Bearing is the horizontal direction of travel of this device,
546
+ * and is not related to the device orientation.
547
+ *
548
+ * <p>The input will be wrapped into the range (0.0, 360.0].
549
+ */
550
+ public void setBearing(float bearing) {
551
+ this.bearing = bearing;
552
+ this.hasBearing = true;
553
+ }
554
+
555
+ /**
556
+ * Get the altitude if available, in meters above the WGS 84 reference
557
+ * ellipsoid.
558
+ *
559
+ * <p>If this location does not have an altitude then 0.0 is returned.
560
+ */
561
+ public double getAltitude() {
562
+ return altitude;
563
+ }
564
+
565
+ /**
566
+ * Set the altitude, in meters above the WGS 84 reference ellipsoid.
567
+ *
568
+ * <p>Following this call {@link #hasAltitude} will return true.
569
+ */
570
+ public void setAltitude(double altitude) {
571
+ this.altitude = altitude;
572
+ this.hasAltitude = true;
573
+ }
574
+
575
+ /**
576
+ * Return radius of stationary region.
577
+ */
578
+ public float getRadius() {
579
+ return radius;
580
+ }
581
+
582
+ /**
583
+ * Sets radius of stationary region.
584
+ */
585
+ public void setRadius(float radius) {
586
+ this.radius = radius;
587
+ this.hasRadius = true;
588
+ }
589
+
590
+ /**
591
+ * True if this location has an accuracy.
592
+ *
593
+ * <p>All locations generated by the {@link LocationManager} have an
594
+ * accuracy.
595
+ */
596
+ public boolean hasAccuracy() {
597
+ return hasAccuracy;
598
+ }
599
+
600
+ public boolean hasVerticalAccuracy() {
601
+ return hasVerticalAccuracy;
602
+ }
603
+
604
+ /**
605
+ * True if this location has an altitude.
606
+ */
607
+ public boolean hasAltitude() {
608
+ return hasAltitude;
609
+ }
610
+
611
+ /**
612
+ * True if this location has a speed.
613
+ */
614
+ public boolean hasSpeed() {
615
+ return hasSpeed;
616
+ }
617
+
618
+ /**
619
+ * True if this location has a bearing.
620
+ */
621
+ public boolean hasBearing() {
622
+ return hasBearing;
623
+ }
624
+
625
+ /**
626
+ * True if this location has a radius.
627
+ */
628
+ public boolean hasRadius() {
629
+ return hasRadius;
630
+ }
631
+
632
+ /**
633
+ * Mock flags is 4-bit representation of mock status
634
+ *
635
+ * xxx0 - isFromMockProvider is false
636
+ * xxx1 - isFromMockProvider is true
637
+ * xx0x - hasIsFromMockProvider is false
638
+ * xx1x - hasIsFromMockProvider is true
639
+ * x0xx - areMockLocationsEnabled is false
640
+ * x1xx - areMockLocationsEnabled is true
641
+ * 0xxx - hasMockLocationsEnabled is false
642
+ * 1xxx - hasMockLocationsEnabled is true
643
+ *
644
+ * @return mock flags
645
+ */
646
+ public int getMockFlags() {
647
+ return mockFlags;
648
+ }
649
+
650
+ public void setMockFlags(int mockFlags) {
651
+ this.mockFlags = mockFlags;
652
+ }
653
+
654
+ /**
655
+ * Return true if method setIsFromMockProvider was called on location instance
656
+ * @return true indicates that result from isFromMockProvider method is valid
657
+ */
658
+ public boolean hasIsFromMockProvider() {
659
+ return ((mockFlags & 0x0002) >> 1) == 1;
660
+ }
661
+
662
+ /**
663
+ * Returns true if the Location came from a mock provider.
664
+ * Always check hasIsFromMockProvider() before this method
665
+ *
666
+ * @return true if this Location came from a mock provider, false otherwise
667
+ */
668
+ public boolean isFromMockProvider() {
669
+ return (mockFlags & 0x0001) == 1;
670
+ }
671
+
672
+ /**
673
+ * Method should be called to indicate that location was recorded by mock provider
674
+ * If this method was called hasIsFromMockProvider method will always return true
675
+ *
676
+ * @param isFromMockProvider
677
+ */
678
+ public void setIsFromMockProvider(boolean isFromMockProvider) {
679
+ mockFlags |= isFromMockProvider ? 0x0003 : 0x0002;
680
+ }
681
+
682
+ /**
683
+ * Return true if method setMockLocationsEnabled was called on location instance
684
+ * @return true indicates that result from areMockLocationsEnabled method is valid
685
+ */
686
+ public boolean hasMockLocationsEnabled() {
687
+ return ((mockFlags & 0x0008) >> 3) == 1;
688
+ }
689
+
690
+ /**
691
+ * Returns true if mock locations were enabled
692
+ * Always check hasMockLocationsEnabled() before this method
693
+ *
694
+ * @return true if mock locations were enabled
695
+ */
696
+ public boolean areMockLocationsEnabled() {
697
+ return ((mockFlags & 0x0004) >> 2) == 1;
698
+ }
699
+
700
+ /**
701
+ * Method should be called when mock locations were detect in settings
702
+ * If this method was called hasMockLocationsEnabled method will always return true
703
+ *
704
+ * @param mockLocationsEnabled
705
+ */
706
+ public void setMockLocationsEnabled(Boolean mockLocationsEnabled) {
707
+ mockFlags |= mockLocationsEnabled ? 0x000C : 0x0008;
708
+ }
709
+
710
+ /**
711
+ * Returns status of location. Can be one of:
712
+ * <ul>
713
+ * <li>{@value #DELETED}</li>
714
+ * <li>{@value #POST_PENDING}</li>
715
+ * <li>{@value #SYNC_PENDING}</li>
716
+ * </ul>
717
+ * @return status
718
+ */
719
+ public int getStatus() {
720
+ return status;
721
+ }
722
+
723
+ /**
724
+ * Sets status of location. Can be one of:
725
+ * <ul>
726
+ * <li>{@value #DELETED}</li>
727
+ * <li>{@value #POST_PENDING}</li>
728
+ * <li>{@value #SYNC_PENDING}</li>
729
+ * </ul>
730
+ * @param status
731
+ */
732
+ public void setStatus(int status) {
733
+ this.status = status;
734
+ }
735
+
736
+ /**
737
+ * Returns additional provider-specific information about the
738
+ * location fix as a Bundle. The keys and values are determined
739
+ * by the provider. If no additional information is available,
740
+ * null is returned.
741
+ *
742
+ * <p> A number of common key/value pairs are listed
743
+ * below. Providers that use any of the keys on this list must
744
+ * provide the corresponding value as described below.
745
+ *
746
+ * <ul>
747
+ * <li> satellites - the number of satellites used to derive the fix
748
+ * </ul>
749
+ */
750
+ public Bundle getExtras() {
751
+ return extras;
752
+ }
753
+
754
+ /**
755
+ * Sets the extra information associated with this fix to the
756
+ * given Bundle.
757
+ */
758
+ public void setExtras(Bundle extras) {
759
+ this.extras = extras;
760
+ }
761
+
762
+ /**
763
+ * Return android Location instance
764
+ *
765
+ * @return android.location.Location instance
766
+ */
767
+ public Location getLocation() {
768
+ Location l = new Location(provider);
769
+ l.setLatitude(latitude);
770
+ l.setLongitude(longitude);
771
+ l.setTime(time);
772
+ if (hasAccuracy) l.setAccuracy(accuracy);
773
+
774
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
775
+ if (hasVerticalAccuracy)
776
+ l.setVerticalAccuracyMeters(verticalAccuracy);
777
+ }
778
+
779
+ if (hasAltitude) l.setAltitude(altitude);
780
+ if (hasSpeed) l.setSpeed(speed);
781
+ if (hasBearing) l.setBearing(bearing);
782
+ l.setExtras(extras);
783
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
784
+ l.setElapsedRealtimeNanos(elapsedRealtimeNanos);
785
+ }
786
+
787
+ return l;
788
+ }
789
+
790
+ /** Determines whether one Location reading is better than the current Location fix
791
+ *
792
+ * Origin: https://developer.android.com/guide/topics/location/strategies.html
793
+ *
794
+ * @param location The new Location that you want to evaluate
795
+ * @param currentBestLocation The current Location fix, to which you want to compare the new one
796
+ */
797
+ public static boolean isBetterLocation(BackgroundLocation location, BackgroundLocation currentBestLocation) {
798
+ if (location == null) {
799
+ return false;
800
+ }
801
+ if (currentBestLocation == null) {
802
+ // A new location is always better than no location
803
+ return true;
804
+ }
805
+
806
+ long timeDeltaInNanos = 0;
807
+ // Check whether the new location fix is newer or older
808
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
809
+ // because getTime is not monotonic
810
+ timeDeltaInNanos = location.getElapsedRealtimeNanos() - currentBestLocation.getElapsedRealtimeNanos();
811
+ } else {
812
+ // unfortunately there is no other way for pre JELLY_BEAN_MR1 (API Level 17)
813
+ timeDeltaInNanos = (location.getTime() - currentBestLocation.getTime()) * 1000000;
814
+ }
815
+
816
+ boolean isSignificantlyNewer = timeDeltaInNanos > TWO_MINUTES_IN_NANOS;
817
+ boolean isSignificantlyOlder = timeDeltaInNanos < -TWO_MINUTES_IN_NANOS;
818
+ boolean isNewer = timeDeltaInNanos > 0;
819
+
820
+ // If it's been more than two minutes since the current location, use the new location
821
+ // because the user has likely moved
822
+ if (isSignificantlyNewer) {
823
+ return true;
824
+ // If the new location is more than two minutes older, it must be worse
825
+ } else if (isSignificantlyOlder) {
826
+ return false;
827
+ }
828
+
829
+ // Check whether the new location fix is more or less accurate
830
+ int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
831
+ boolean isLessAccurate = accuracyDelta > 0;
832
+ boolean isMoreAccurate = accuracyDelta < 0;
833
+ boolean isSignificantlyLessAccurate = accuracyDelta > 200;
834
+
835
+ // Check if the old and new location are from the same provider
836
+ boolean isFromSameProvider = isSameProvider(location.getProvider(),
837
+ currentBestLocation.getProvider());
838
+
839
+ // Determine location quality using a combination of timeliness and accuracy
840
+ if (isMoreAccurate) {
841
+ return true;
842
+ } else if (isNewer && !isLessAccurate) {
843
+ return true;
844
+ } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
845
+ return true;
846
+ }
847
+ return false;
848
+ }
849
+
850
+ /**
851
+ * Check if given location is better that instance
852
+ * @param location to compare is android Location
853
+ * @return true if location is better and false if not
854
+ */
855
+ public boolean isBetterLocationThan(Location location) {
856
+ if (location == null) {
857
+ return true;
858
+ }
859
+ return !isBetterLocation(new BackgroundLocation(location), this);
860
+ }
861
+
862
+ /**
863
+ * Check if given location is better that instance
864
+ * @param location to compare
865
+ * @return true if location is better and false if not
866
+ */
867
+ public boolean isBetterLocationThan(BackgroundLocation location) {
868
+ if (location == null) {
869
+ return true;
870
+ }
871
+ return !isBetterLocation(location, this);
872
+ }
873
+
874
+ /** Checks whether two providers are the same */
875
+ private static boolean isSameProvider(String provider1, String provider2) {
876
+ if (provider1 == null) {
877
+ return provider2 == null;
878
+ }
879
+ return provider1.equals(provider2);
880
+ }
881
+
882
+ @Override
883
+ public String toString () {
884
+ StringBuilder s = new StringBuilder();
885
+ s.append("BGLocation[").append(provider);
886
+ s.append(String.format(" %.6f,%.6f", latitude, longitude));
887
+ s.append(" id=").append(locationId);
888
+ if (hasAccuracy) {
889
+ s.append(String.format(" acc=%.0f", accuracy));
890
+ } else {
891
+ s.append(" acc=???");
892
+ }
893
+
894
+ if (hasVerticalAccuracy) {
895
+ s.append(String.format(" altAcc=%.0f", verticalAccuracy));
896
+ }
897
+ else {
898
+ s.append(" altAcc=???");
899
+ }
900
+
901
+ if (time == 0) {
902
+ s.append(" t=?!?");
903
+ } else {
904
+ s.append(" t=").append(time);
905
+ }
906
+ if (elapsedRealtimeNanos == 0) {
907
+ s.append(" et=?!?");
908
+ } else {
909
+ s.append(" et=");
910
+ TimeUtils.formatDuration(elapsedRealtimeNanos / 1000000L, s);
911
+ }
912
+ if (hasAltitude) s.append(" alt=").append(altitude);
913
+ if (hasSpeed) s.append(" vel=").append(speed);
914
+ if (hasBearing) s.append(" bear=").append(bearing);
915
+ if (hasRadius) s.append(" radius=").append(radius);
916
+ if (isFromMockProvider()) s.append(" mock");
917
+ if (areMockLocationsEnabled()) s.append(" mocksEnabled");
918
+ if (extras != null) {
919
+ s.append(" {").append(extras).append('}');
920
+ }
921
+ s.append(" locprov=").append(locationProvider);
922
+ s.append("]");
923
+
924
+ return s.toString();
925
+ }
926
+
927
+ /**
928
+ * Returns location as JSON object.
929
+ * @throws JSONException
930
+ */
931
+ public JSONObject toJSONObject() throws JSONException {
932
+ JSONObject json = new JSONObject();
933
+ json.put("provider", provider);
934
+ json.put("locationProvider", locationProvider);
935
+ json.put("time", time);
936
+ json.put("latitude", latitude);
937
+ json.put("longitude", longitude);
938
+ if (hasAccuracy) json.put("accuracy", accuracy);
939
+ if (hasVerticalAccuracy) json.put("altitudeAccuracy", verticalAccuracy);
940
+ if (hasSpeed) json.put("speed", speed);
941
+ if (hasAltitude) json.put("altitude", altitude);
942
+ if (hasBearing) json.put("bearing", bearing);
943
+ if (hasRadius) json.put("radius", radius);
944
+ if (hasIsFromMockProvider()) json.put("isFromMockProvider", isFromMockProvider());
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);
953
+
954
+ return json;
955
+ }
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
+
977
+ /**
978
+ * Returns location as JSON object containing location id
979
+ * Note: Location id is not unique and is usually being recycled when
980
+ * maximum number of locations is stored.
981
+ *
982
+ * @throws JSONException
983
+ */
984
+ public JSONObject toJSONObjectWithId() throws JSONException {
985
+ JSONObject json = toJSONObject();
986
+ json.put("id", locationId);
987
+ return json;
988
+ }
989
+
990
+ /**
991
+ * Return the contentvalues for this record
992
+ */
993
+ public ContentValues toContentValues() {
994
+ ContentValues values = new ContentValues();
995
+ //values.put(LocationEntry._ID, locationId);
996
+ values.put(LocationEntry.COLUMN_NAME_TIME, time);
997
+ values.put(LocationEntry.COLUMN_NAME_ACCURACY, accuracy);
998
+ values.put(LocationEntry.COLUMN_NAME_VERTICAL_ACCURACY, verticalAccuracy);
999
+ values.put(LocationEntry.COLUMN_NAME_SPEED, speed);
1000
+ values.put(LocationEntry.COLUMN_NAME_BEARING, bearing);
1001
+ values.put(LocationEntry.COLUMN_NAME_ALTITUDE, altitude);
1002
+ values.put(LocationEntry.COLUMN_NAME_LATITUDE, latitude);
1003
+ values.put(LocationEntry.COLUMN_NAME_LONGITUDE, longitude);
1004
+ values.put(LocationEntry.COLUMN_NAME_RADIUS, radius);
1005
+ values.put(LocationEntry.COLUMN_NAME_HAS_ACCURACY, hasAccuracy);
1006
+ values.put(LocationEntry.COLUMN_NAME_HAS_VERTICAL_ACCURACY, hasVerticalAccuracy);
1007
+ values.put(LocationEntry.COLUMN_NAME_HAS_SPEED, hasSpeed);
1008
+ values.put(LocationEntry.COLUMN_NAME_HAS_BEARING, hasBearing);
1009
+ values.put(LocationEntry.COLUMN_NAME_HAS_ALTITUDE, hasAltitude);
1010
+ values.put(LocationEntry.COLUMN_NAME_HAS_RADIUS, hasRadius);
1011
+ values.put(LocationEntry.COLUMN_NAME_PROVIDER, provider);
1012
+ values.put(LocationEntry.COLUMN_NAME_LOCATION_PROVIDER, locationProvider);
1013
+ values.put(LocationEntry.COLUMN_NAME_STATUS, status);
1014
+ values.put(LocationEntry.COLUMN_NAME_BATCH_START_MILLIS, batchStartMillis);
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);
1028
+ return values;
1029
+ }
1030
+
1031
+ public Object getValueForKey(String key) {
1032
+ if ("@id".equals(key)) {
1033
+ return locationId;
1034
+ }
1035
+ if ("@provider".equals(key)) {
1036
+ return provider;
1037
+ }
1038
+ if ("@locationProvider".equals(key)) {
1039
+ return locationProvider;
1040
+ }
1041
+ if ("@time".equals(key)) {
1042
+ return time;
1043
+ }
1044
+ if ("@latitude".equals(key)) {
1045
+ return latitude;
1046
+ }
1047
+ if ("@longitude".equals(key)) {
1048
+ return longitude;
1049
+ }
1050
+ if ("@accuracy".equals(key)) {
1051
+ return hasAccuracy ? accuracy : JSONObject.NULL;
1052
+ }
1053
+ if ("@altitudeAccuracy".equals(key)) {
1054
+ return hasVerticalAccuracy ? verticalAccuracy : JSONObject.NULL;
1055
+ }
1056
+ if ("@speed".equals(key)) {
1057
+ return hasSpeed ? speed : JSONObject.NULL;
1058
+ }
1059
+ if ("@altitude".equals(key)) {
1060
+ return hasAltitude ? altitude : JSONObject.NULL;
1061
+ }
1062
+ if ("@bearing".equals(key)) {
1063
+ return hasBearing ? bearing : JSONObject.NULL;
1064
+ }
1065
+ if ("@radius".equals(key)) {
1066
+ return hasRadius ? radius : JSONObject.NULL;
1067
+ }
1068
+ if ("@isFromMockProvider".equals(key)) {
1069
+ return hasIsFromMockProvider() ? isFromMockProvider() : JSONObject.NULL;
1070
+ }
1071
+ if ("@mockLocationsEnabled".equals(key)) {
1072
+ return hasMockLocationsEnabled() ? areMockLocationsEnabled() : JSONObject.NULL;
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
+ }
1085
+
1086
+ return null;
1087
+ }
1088
+ }