@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,699 @@
1
+ package com.marianhello.bgloc;
2
+
3
+ import android.Manifest;
4
+ import android.accounts.Account;
5
+ import android.annotation.TargetApi;
6
+ import android.content.BroadcastReceiver;
7
+ import android.content.Context;
8
+ import android.content.Intent;
9
+ import android.content.IntentFilter;
10
+ import android.content.pm.PackageManager;
11
+ import android.location.Location;
12
+ import android.net.Uri;
13
+ import android.os.Build;
14
+ import android.os.Bundle;
15
+ import android.provider.Settings;
16
+ import android.provider.Settings.SettingNotFoundException;
17
+ import androidx.core.content.ContextCompat;
18
+ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
19
+ import android.text.TextUtils;
20
+
21
+ import com.github.jparkie.promise.Promise;
22
+ import com.intentfilter.androidpermissions.PermissionManager;
23
+ import com.intentfilter.androidpermissions.models.DeniedPermissions;
24
+ import com.marianhello.bgloc.data.BackgroundActivity;
25
+ import com.marianhello.bgloc.data.BackgroundLocation;
26
+ import com.marianhello.bgloc.data.ConfigurationDAO;
27
+ import com.marianhello.bgloc.data.DAOFactory;
28
+ import com.marianhello.bgloc.data.LocationDAO;
29
+ import com.marianhello.bgloc.data.SessionLocationDAO;
30
+ import com.marianhello.bgloc.provider.LocationProvider;
31
+ import com.marianhello.bgloc.service.LocationService;
32
+ import com.marianhello.bgloc.service.LocationServiceImpl;
33
+ import com.marianhello.bgloc.service.LocationServiceProxy;
34
+ import com.marianhello.bgloc.data.LocationTransform;
35
+ import com.marianhello.bgloc.data.sqlite.SQLiteSessionLocationDAO;
36
+ import com.marianhello.bgloc.sync.AccountHelper;
37
+ import com.marianhello.bgloc.sync.NotificationHelper;
38
+ import com.marianhello.bgloc.sync.SyncService;
39
+ import com.marianhello.logging.DBLogReader;
40
+ import com.marianhello.logging.LogEntry;
41
+ import com.marianhello.logging.LoggerManager;
42
+ import com.marianhello.logging.UncaughtExceptionLogger;
43
+
44
+ import org.json.JSONException;
45
+ import org.slf4j.event.Level;
46
+
47
+ import java.util.Arrays;
48
+ import java.util.Collection;
49
+ import java.util.concurrent.TimeoutException;
50
+
51
+ public class BackgroundGeolocationFacade {
52
+
53
+ public static final int SERVICE_STARTED = 1;
54
+ public static final int SERVICE_STOPPED = 0;
55
+ public static final int AUTHORIZATION_AUTHORIZED = 1;
56
+ public static final int AUTHORIZATION_DENIED = 0;
57
+
58
+ public static final String[] PERMISSIONS = {
59
+ Manifest.permission.ACCESS_COARSE_LOCATION,
60
+ Manifest.permission.ACCESS_FINE_LOCATION,
61
+ };
62
+
63
+ private boolean mServiceBroadcastReceiverRegistered = false;
64
+ private boolean mLocationModeChangeReceiverRegistered = false;
65
+ private boolean mIsPaused = false;
66
+
67
+ private Config mConfig;
68
+ private final Context mContext;
69
+ private final PluginDelegate mDelegate;
70
+ private final LocationService mService;
71
+
72
+ private BackgroundLocation mStationaryLocation;
73
+
74
+ private org.slf4j.Logger logger;
75
+
76
+ public BackgroundGeolocationFacade(Context context, PluginDelegate delegate) {
77
+ mContext = context;
78
+ mDelegate = delegate;
79
+ mService = new LocationServiceProxy(context);
80
+
81
+ UncaughtExceptionLogger.register(context.getApplicationContext());
82
+
83
+ logger = LoggerManager.getLogger(BackgroundGeolocationFacade.class);
84
+ LoggerManager.enableDBLogging();
85
+
86
+ logger.info("Initializing plugin");
87
+
88
+ NotificationHelper.registerAllChannels(getApplicationContext());
89
+ }
90
+
91
+ private BroadcastReceiver locationModeChangeReceiver = new BroadcastReceiver() {
92
+ @Override
93
+ public void onReceive(Context context, Intent intent) {
94
+ logger.debug("Authorization has changed");
95
+ mDelegate.onAuthorizationChanged(getAuthorizationStatus());
96
+ }
97
+ };
98
+
99
+ private BroadcastReceiver serviceBroadcastReceiver = new BroadcastReceiver() {
100
+ @Override
101
+ public void onReceive(Context context, Intent intent) {
102
+ Bundle bundle = intent.getExtras();
103
+ int action = bundle.getInt("action");
104
+
105
+ switch (action) {
106
+ case LocationServiceImpl.MSG_ON_LOCATION: {
107
+ logger.debug("Received MSG_ON_LOCATION");
108
+ bundle.setClassLoader(LocationServiceImpl.class.getClassLoader());
109
+ BackgroundLocation location = (BackgroundLocation) bundle.getParcelable("payload");
110
+ mDelegate.onLocationChanged(location);
111
+ return;
112
+ }
113
+
114
+ case LocationServiceImpl.MSG_ON_STATIONARY: {
115
+ logger.debug("Received MSG_ON_STATIONARY");
116
+ bundle.setClassLoader(LocationServiceImpl.class.getClassLoader());
117
+ BackgroundLocation location = (BackgroundLocation) bundle.getParcelable("payload");
118
+ mStationaryLocation = location;
119
+ mDelegate.onStationaryChanged(location);
120
+ return;
121
+ }
122
+
123
+ case LocationServiceImpl.MSG_ON_ACTIVITY: {
124
+ logger.debug("Received MSG_ON_ACTIVITY");
125
+ bundle.setClassLoader(LocationServiceImpl.class.getClassLoader());
126
+ BackgroundActivity activity = (BackgroundActivity) bundle.getParcelable("payload");
127
+ mDelegate.onActivityChanged(activity);
128
+ return;
129
+ }
130
+
131
+ case LocationServiceImpl.MSG_ON_ERROR: {
132
+ logger.debug("Received MSG_ON_ERROR");
133
+ Bundle errorBundle = bundle.getBundle("payload");
134
+ Integer errorCode = errorBundle.getInt("code");
135
+ String errorMessage = errorBundle.getString("message");
136
+ mDelegate.onError(new PluginException(errorMessage, errorCode));
137
+ return;
138
+ }
139
+
140
+ case LocationServiceImpl.MSG_ON_SERVICE_STARTED: {
141
+ logger.debug("Received MSG_ON_SERVICE_STARTED");
142
+ mDelegate.onServiceStatusChanged(SERVICE_STARTED);
143
+ return;
144
+ }
145
+
146
+ case LocationServiceImpl.MSG_ON_SERVICE_STOPPED: {
147
+ logger.debug("Received MSG_ON_SERVICE_STOPPED");
148
+ mDelegate.onServiceStatusChanged(SERVICE_STOPPED);
149
+ return;
150
+ }
151
+
152
+ case LocationServiceImpl.MSG_ON_ABORT_REQUESTED: {
153
+ logger.debug("Received MSG_ON_ABORT_REQUESTED");
154
+
155
+ if (mDelegate != null) {
156
+ // We have a delegate, tell it that there's a request.
157
+ // It will decide whether to stop or not.
158
+ mDelegate.onAbortRequested();
159
+ } else {
160
+ // No delegate, we may be running in the background.
161
+ // Let's just stop.
162
+ stop();
163
+ }
164
+
165
+ return;
166
+ }
167
+
168
+ case LocationServiceImpl.MSG_ON_HTTP_AUTHORIZATION: {
169
+ logger.debug("Received MSG_ON_HTTP_AUTHORIZATION");
170
+
171
+ if (mDelegate != null) {
172
+ mDelegate.onHttpAuthorization();
173
+ }
174
+
175
+ return;
176
+ }
177
+
178
+ case LocationServiceImpl.MSG_ON_SYNC_START: {
179
+ logger.debug("Received MSG_ON_SYNC_START");
180
+ if (mDelegate != null) mDelegate.onSyncStart();
181
+ return;
182
+ }
183
+
184
+ case LocationServiceImpl.MSG_ON_SYNC_SUCCESS: {
185
+ int sent = bundle != null ? bundle.getInt("sent", 0) : 0;
186
+ logger.debug("Received MSG_ON_SYNC_SUCCESS sent={}", sent);
187
+ if (mDelegate != null) mDelegate.onSyncSuccess(sent);
188
+ return;
189
+ }
190
+
191
+ case LocationServiceImpl.MSG_ON_SYNC_ERROR: {
192
+ int status = bundle != null ? bundle.getInt("httpStatus", 0) : 0;
193
+ String msg = bundle != null ? bundle.getString("message", "") : "";
194
+ logger.debug("Received MSG_ON_SYNC_ERROR status={} message={}", status, msg);
195
+ if (mDelegate != null) mDelegate.onSyncError(status, msg);
196
+ return;
197
+ }
198
+
199
+ case LocationServiceImpl.MSG_ON_SYNC_PROGRESS: {
200
+ int progress = bundle != null ? bundle.getInt("progress", 0) : 0;
201
+ if (mDelegate != null) mDelegate.onSyncProgress(progress);
202
+ return;
203
+ }
204
+
205
+ case LocationServiceImpl.MSG_ON_HEARTBEAT: {
206
+ if (bundle != null) {
207
+ bundle.setClassLoader(LocationServiceImpl.class.getClassLoader());
208
+ }
209
+ BackgroundLocation hb = bundle != null ? (BackgroundLocation) bundle.getParcelable("payload") : null;
210
+ if (mDelegate != null) mDelegate.onHeartbeat(hb);
211
+ return;
212
+ }
213
+
214
+ // v4.0 Phase 6: driver-insights events
215
+ case LocationServiceImpl.MSG_ON_TRIP_START:
216
+ case LocationServiceImpl.MSG_ON_TRIP_END:
217
+ case LocationServiceImpl.MSG_ON_MOVING:
218
+ case LocationServiceImpl.MSG_ON_STOPPED:
219
+ case LocationServiceImpl.MSG_ON_SPEEDING:
220
+ case LocationServiceImpl.MSG_ON_SOS: {
221
+ if (bundle != null) bundle.setClassLoader(LocationServiceImpl.class.getClassLoader());
222
+ BackgroundLocation loc = bundle != null ? (BackgroundLocation) bundle.getParcelable("payload") : null;
223
+ if (mDelegate == null) return;
224
+ switch (action) {
225
+ case LocationServiceImpl.MSG_ON_TRIP_START:
226
+ mDelegate.onTripStart(loc); break;
227
+ case LocationServiceImpl.MSG_ON_TRIP_END:
228
+ double dist = bundle != null ? bundle.getDouble("distance", 0.0) : 0.0;
229
+ long durMs = bundle != null ? bundle.getLong("durationMs", 0L) : 0L;
230
+ mDelegate.onTripEnd(loc, dist, durMs); break;
231
+ case LocationServiceImpl.MSG_ON_MOVING:
232
+ mDelegate.onMoving(loc); break;
233
+ case LocationServiceImpl.MSG_ON_STOPPED:
234
+ mDelegate.onStopped(loc); break;
235
+ case LocationServiceImpl.MSG_ON_SPEEDING:
236
+ double sKmh = bundle != null ? bundle.getDouble("speedKmh", 0.0) : 0.0;
237
+ double lKmh = bundle != null ? bundle.getDouble("limitKmh", 0.0) : 0.0;
238
+ mDelegate.onSpeeding(loc, sKmh, lKmh); break;
239
+ case LocationServiceImpl.MSG_ON_SOS:
240
+ org.json.JSONObject sosPayload = null;
241
+ if (bundle != null) {
242
+ String s = bundle.getString("sosPayload");
243
+ if (s != null) {
244
+ try { sosPayload = new org.json.JSONObject(s); }
245
+ catch (org.json.JSONException ignored) { sosPayload = new org.json.JSONObject(); }
246
+ }
247
+ }
248
+ mDelegate.onSOS(loc, sosPayload); break;
249
+ }
250
+ return;
251
+ }
252
+
253
+ case LocationServiceImpl.MSG_ON_PROVIDER_CHANGE: {
254
+ String provider = bundle != null ? bundle.getString("provider", "") : "";
255
+ if (mDelegate != null) mDelegate.onProviderChange(provider);
256
+ return;
257
+ }
258
+
259
+ // v4.1 GPS-derived sensor-like events (and v4.2 sensor-driven possibleCrash)
260
+ case LocationServiceImpl.MSG_ON_HARD_BRAKE:
261
+ case LocationServiceImpl.MSG_ON_RAPID_ACCELERATION:
262
+ case LocationServiceImpl.MSG_ON_SHARP_TURN:
263
+ case LocationServiceImpl.MSG_ON_POSSIBLE_CRASH: {
264
+ if (bundle != null) bundle.setClassLoader(LocationServiceImpl.class.getClassLoader());
265
+ BackgroundLocation drvLoc = bundle != null ? (BackgroundLocation) bundle.getParcelable("payload") : null;
266
+ double drvVal = bundle != null ? bundle.getDouble("value", 0.0) : 0.0;
267
+ String drvSrc = bundle != null ? bundle.getString("source", "gps") : "gps";
268
+ if (mDelegate == null) return;
269
+ switch (action) {
270
+ case LocationServiceImpl.MSG_ON_HARD_BRAKE:
271
+ mDelegate.onHardBrake(drvLoc, drvVal); break;
272
+ case LocationServiceImpl.MSG_ON_RAPID_ACCELERATION:
273
+ mDelegate.onRapidAcceleration(drvLoc, drvVal); break;
274
+ case LocationServiceImpl.MSG_ON_SHARP_TURN:
275
+ mDelegate.onSharpTurn(drvLoc, drvVal); break;
276
+ case LocationServiceImpl.MSG_ON_POSSIBLE_CRASH:
277
+ mDelegate.onPossibleCrash(drvLoc, drvVal, drvSrc); break;
278
+ }
279
+ return;
280
+ }
281
+ // v4.2 sensor fusion: phone usage while driving
282
+ case LocationServiceImpl.MSG_ON_PHONE_USAGE_WHILE_DRIVING: {
283
+ if (bundle != null) bundle.setClassLoader(LocationServiceImpl.class.getClassLoader());
284
+ BackgroundLocation puLoc = bundle != null ? (BackgroundLocation) bundle.getParcelable("payload") : null;
285
+ if (mDelegate != null) mDelegate.onPhoneUsageWhileDriving(puLoc);
286
+ return;
287
+ }
288
+ }
289
+ }
290
+ };
291
+
292
+ @TargetApi(Build.VERSION_CODES.KITKAT)
293
+ private synchronized void registerLocationModeChangeReceiver() {
294
+ if (mLocationModeChangeReceiverRegistered) return;
295
+
296
+ getContext().registerReceiver(locationModeChangeReceiver, new IntentFilter(android.location.LocationManager.MODE_CHANGED_ACTION));
297
+ mLocationModeChangeReceiverRegistered = true;
298
+ }
299
+
300
+ private synchronized void unregisterLocationModeChangeReceiver() {
301
+ if (!mLocationModeChangeReceiverRegistered) return;
302
+
303
+ Context context = getContext();
304
+ if (context != null) {
305
+ context.unregisterReceiver(locationModeChangeReceiver);
306
+ }
307
+ mLocationModeChangeReceiverRegistered = false;
308
+ }
309
+
310
+ private synchronized void registerServiceBroadcast() {
311
+ if (mServiceBroadcastReceiverRegistered) return;
312
+
313
+ LocalBroadcastManager.getInstance(getContext()).registerReceiver(serviceBroadcastReceiver, new IntentFilter(LocationServiceImpl.ACTION_BROADCAST));
314
+ mServiceBroadcastReceiverRegistered = true;
315
+ }
316
+
317
+ private synchronized void unregisterServiceBroadcast() {
318
+ if (!mServiceBroadcastReceiverRegistered) return;
319
+
320
+ Context context = getContext();
321
+ if (context != null) {
322
+ LocalBroadcastManager.getInstance(context).unregisterReceiver(serviceBroadcastReceiver);
323
+ }
324
+
325
+ mServiceBroadcastReceiverRegistered = false;
326
+ }
327
+
328
+ public void start() {
329
+ logger.debug("Starting service");
330
+
331
+ PermissionManager permissionManager = PermissionManager.getInstance(getContext());
332
+ permissionManager.checkPermissions(Arrays.asList(PERMISSIONS), new PermissionManager.PermissionRequestListener() {
333
+ @Override
334
+ public void onPermissionGranted() {
335
+ logger.info("User granted requested permissions");
336
+ // watch location mode changes
337
+ registerLocationModeChangeReceiver();
338
+ registerServiceBroadcast();
339
+ startBackgroundService();
340
+ }
341
+
342
+ @Override
343
+ public void onPermissionDenied(DeniedPermissions deniedPermissions) {
344
+ logger.info("User denied requested permissions");
345
+ if (mDelegate != null) {
346
+ mDelegate.onAuthorizationChanged(BackgroundGeolocationFacade.AUTHORIZATION_DENIED);
347
+ }
348
+ }
349
+ });
350
+ permissionManager.checkPermissions(Arrays.asList(Manifest.permission.POST_NOTIFICATIONS), new PermissionManager.PermissionRequestListener() {
351
+ @Override
352
+ public void onPermissionGranted() {} // noop
353
+
354
+ @Override
355
+ public void onPermissionDenied(DeniedPermissions deniedPermissions) {} // noop
356
+ });
357
+ }
358
+
359
+ public void stop() {
360
+ logger.debug("Stopping service");
361
+ unregisterLocationModeChangeReceiver();
362
+ // Note: we cannot unregistered service broadcast here
363
+ // because no stop notification from service will arrive
364
+ // unregisterServiceBroadcast();
365
+
366
+ stopBackgroundService();
367
+ }
368
+
369
+ public void pause() {
370
+ mIsPaused = true;
371
+ mService.startForeground();
372
+ }
373
+
374
+ public void resume() {
375
+ mIsPaused = false;
376
+ mService.stopHeadlessTask();
377
+ if (!getConfig().getStartForeground()) {
378
+ mService.stopForeground();
379
+ }
380
+ }
381
+
382
+ public void destroy() {
383
+ logger.info("Destroying plugin");
384
+
385
+ unregisterLocationModeChangeReceiver();
386
+ unregisterServiceBroadcast();
387
+
388
+ if (getConfig().getStopOnTerminate()) {
389
+ stopBackgroundService();
390
+ } else {
391
+ mService.startHeadlessTask();
392
+ }
393
+ }
394
+
395
+ public Collection<BackgroundLocation> getLocations() {
396
+ LocationDAO dao = DAOFactory.createLocationDAO(getContext());
397
+ return dao.getAllLocations();
398
+ }
399
+
400
+ public Collection<BackgroundLocation> getValidLocations() {
401
+ LocationDAO dao = DAOFactory.createLocationDAO(getContext());
402
+ return dao.getValidLocations();
403
+ }
404
+
405
+ public Collection<BackgroundLocation> getValidLocationsAndDelete() {
406
+ LocationDAO dao = DAOFactory.createLocationDAO(getContext());
407
+ return dao.getValidLocationsAndDelete();
408
+ }
409
+
410
+ /** Clear session table and start storing all new locations in session. Call when user starts a route. */
411
+ public void startSession() {
412
+ SessionLocationDAO dao = new SQLiteSessionLocationDAO(getContext());
413
+ dao.startSession();
414
+ }
415
+
416
+ /** Return all locations stored in the current session (ordered by time). */
417
+ public Collection<BackgroundLocation> getSessionLocations() {
418
+ SessionLocationDAO dao = new SQLiteSessionLocationDAO(getContext());
419
+ return dao.getSessionLocations();
420
+ }
421
+
422
+ /** Clear session table and stop storing. Call when route is finished and sync OK. */
423
+ public void clearSession() {
424
+ SessionLocationDAO dao = new SQLiteSessionLocationDAO(getContext());
425
+ dao.clearSession();
426
+ }
427
+
428
+ /** Number of locations in the current session. */
429
+ public int getSessionLocationsCount() {
430
+ SessionLocationDAO dao = new SQLiteSessionLocationDAO(getContext());
431
+ return dao.getSessionLocationsCount();
432
+ }
433
+
434
+ public BackgroundLocation getStationaryLocation() {
435
+ return mStationaryLocation;
436
+ }
437
+
438
+ public void deleteLocation(Long locationId) {
439
+ logger.info("Deleting location locationId={}", locationId);
440
+ LocationDAO dao = DAOFactory.createLocationDAO(getContext());
441
+ dao.deleteLocationById(locationId.longValue());
442
+ }
443
+
444
+ public void deleteAllLocations() {
445
+ logger.info("Deleting all locations");
446
+ LocationDAO dao = DAOFactory.createLocationDAO(getContext());
447
+ dao.deleteAllLocations();
448
+ }
449
+
450
+ public BackgroundLocation getCurrentLocation(int timeout, long maximumAge, boolean enableHighAccuracy) throws PluginException {
451
+ logger.info("Getting current location with timeout:{} maximumAge:{} enableHighAccuracy:{}", timeout, maximumAge, enableHighAccuracy);
452
+
453
+ LocationManager locationManager = LocationManager.getInstance(getContext());
454
+ Promise<Location> promise = locationManager.getCurrentLocation(timeout, maximumAge, enableHighAccuracy);
455
+ try {
456
+ promise.await();
457
+ Location location = promise.get();
458
+ if (location != null) {
459
+ return BackgroundLocation.fromLocation(location);
460
+ }
461
+
462
+ Throwable error = promise.getError();
463
+ if (error == null) {
464
+ throw new PluginException("Location not available", 2); // LOCATION_UNAVAILABLE
465
+ }
466
+ if (error instanceof LocationManager.PermissionDeniedException) {
467
+ logger.warn("Getting current location failed due missing permissions");
468
+ throw new PluginException("Permission denied", 1); // PERMISSION_DENIED
469
+ }
470
+ if (error instanceof TimeoutException) {
471
+ throw new PluginException("Location request timed out", 3); // TIME_OUT
472
+ }
473
+
474
+ throw new PluginException(error.getMessage(), 2); // LOCATION_UNAVAILABLE
475
+ } catch (InterruptedException e) {
476
+ logger.error("Interrupted while waiting location", e);
477
+ Thread.currentThread().interrupt();
478
+ throw new RuntimeException("Interrupted while waiting location", e);
479
+ }
480
+ }
481
+
482
+ public void switchMode(final int mode) {
483
+ mService.executeProviderCommand(LocationProvider.CMD_SWITCH_MODE, mode);
484
+ }
485
+
486
+ public void sendCommand(final int commandId) {
487
+ mService.executeProviderCommand(commandId, 0);
488
+ }
489
+
490
+ public synchronized void configure(Config config) throws PluginException {
491
+ try
492
+ {
493
+ Config newConfig = Config.merge(getStoredConfig(), config);
494
+ persistConfiguration(newConfig);
495
+ logger.debug("Service configured with: {}", newConfig.toString());
496
+ mConfig = newConfig;
497
+ mService.configure(newConfig);
498
+ } catch (Exception e) {
499
+ logger.error("Configuration error: {}", e.getMessage());
500
+ throw new PluginException("Configuration error", e, PluginException.CONFIGURE_ERROR);
501
+ }
502
+ }
503
+
504
+ public synchronized Config getConfig() {
505
+ if (mConfig != null) {
506
+ return mConfig;
507
+ }
508
+
509
+ try {
510
+ mConfig = getStoredConfig();
511
+ } catch (PluginException e) {
512
+ logger.error("Error getting stored config will use default", e.getMessage());
513
+ mConfig = Config.getDefault();
514
+ }
515
+
516
+ return mConfig;
517
+ }
518
+
519
+ public synchronized Config getStoredConfig() throws PluginException {
520
+ try {
521
+ ConfigurationDAO dao = DAOFactory.createConfigurationDAO(getContext());
522
+ Config config = dao.retrieveConfiguration();
523
+ if (config == null) {
524
+ config = Config.getDefault();
525
+ }
526
+ return config;
527
+ } catch (JSONException e) {
528
+ logger.error("Error getting stored config: {}", e.getMessage());
529
+ throw new PluginException("Error getting stored config", e, PluginException.JSON_ERROR);
530
+ }
531
+ }
532
+
533
+ public Collection<LogEntry> getLogEntries(int limit) {
534
+ DBLogReader logReader = new DBLogReader();
535
+ return logReader.getEntries(limit, 0, Level.DEBUG);
536
+ }
537
+
538
+ public Collection<LogEntry> getLogEntries(int limit, int offset, String minLevel) {
539
+ DBLogReader logReader = new DBLogReader();
540
+ return logReader.getEntries(limit, offset, Level.valueOf(minLevel));
541
+ }
542
+
543
+ /**
544
+ * Force location sync
545
+ *
546
+ * Method is ignoring syncThreshold and also user sync settings preference
547
+ * and sync locations to defined syncUrl. No-op if sync is disabled in config (sync: false).
548
+ */
549
+ public void forceSync() {
550
+ Config config = getConfig();
551
+ if (!Boolean.TRUE.equals(config.getSyncEnabled())) {
552
+ logger.debug("Sync disabled in config, skipping forceSync");
553
+ return;
554
+ }
555
+ logger.debug("Sync locations forced");
556
+ ResourceResolver resolver = ResourceResolver.newInstance(getContext());
557
+ Account syncAccount = AccountHelper.CreateSyncAccount(getContext(), resolver.getAccountName(),
558
+ resolver.getAccountType());
559
+ SyncService.sync(syncAccount, resolver.getAuthority(), true);
560
+ }
561
+
562
+ /**
563
+ * v4.0 Phase 6 — Trigger an SOS event. The plugin emits a single `sos` JS event
564
+ * carrying the latest known location and the user-supplied JSON payload.
565
+ */
566
+ public void triggerSOS(org.json.JSONObject payload) {
567
+ Bundle b = new Bundle();
568
+ b.putInt("action", LocationServiceImpl.MSG_ON_SOS);
569
+ BackgroundLocation last = LocationServiceImpl.getLastReceivedLocation();
570
+ if (last != null) b.putParcelable("payload", last);
571
+ b.putString("sosPayload", payload != null ? payload.toString() : "{}");
572
+ Intent intent = new Intent(LocationServiceImpl.ACTION_BROADCAST);
573
+ intent.putExtras(b);
574
+ androidx.localbroadcastmanager.content.LocalBroadcastManager
575
+ .getInstance(getContext().getApplicationContext()).sendBroadcast(intent);
576
+ }
577
+
578
+ /**
579
+ * Returns the number of locations pending to be synced (not yet sent to syncUrl).
580
+ */
581
+ public long getPendingSyncCount() {
582
+ LocationDAO dao = DAOFactory.createLocationDAO(getContext());
583
+ return dao.getLocationsForSyncCount(Long.MAX_VALUE);
584
+ }
585
+
586
+ /**
587
+ * Clear the pending sync queue: mark all locations waiting to be synced as deleted.
588
+ * They will not be sent to syncUrl. Use when the user wants to discard pending locations.
589
+ */
590
+ public void clearSync() {
591
+ LocationDAO dao = DAOFactory.createLocationDAO(getContext());
592
+ int count = dao.deletePendingSyncLocations();
593
+ logger.debug("Cleared {} pending sync locations", count);
594
+ }
595
+
596
+ public int getAuthorizationStatus() {
597
+ return hasPermissions() ? AUTHORIZATION_AUTHORIZED : AUTHORIZATION_DENIED;
598
+ }
599
+
600
+ public boolean hasPermissions() {
601
+ return hasPermissions(getContext(), PERMISSIONS);
602
+ }
603
+
604
+ public boolean locationServicesEnabled() throws PluginException {
605
+ Context context = getContext();
606
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
607
+ int locationMode = 0;
608
+ try {
609
+ locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
610
+ return locationMode != Settings.Secure.LOCATION_MODE_OFF;
611
+ } catch (SettingNotFoundException e) {
612
+ logger.error("Location services check failed", e);
613
+ throw new PluginException("Location services check failed", e, PluginException.SETTINGS_ERROR);
614
+ }
615
+ } else {
616
+ String locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
617
+ return !TextUtils.isEmpty(locationProviders);
618
+ }
619
+ }
620
+
621
+ public void registerHeadlessTask(final String taskRunnerClass) {
622
+ logger.info("Registering headless task: {}", taskRunnerClass);
623
+ mService.registerHeadlessTask(taskRunnerClass);
624
+ }
625
+
626
+ private void startBackgroundService() {
627
+ logger.info("Attempt to start bg service");
628
+ if (mIsPaused) {
629
+ mService.startForegroundService();
630
+ } else {
631
+ mService.start();
632
+ }
633
+ }
634
+
635
+ private void stopBackgroundService() {
636
+ logger.info("Attempt to stop bg service");
637
+ mService.stop();
638
+ }
639
+
640
+ public boolean isRunning() {
641
+ return ((LocationServiceProxy) mService).isRunning();
642
+ }
643
+
644
+ private void persistConfiguration(Config config) throws NullPointerException {
645
+ ConfigurationDAO dao = DAOFactory.createConfigurationDAO(getContext());
646
+ dao.persistConfiguration(config);
647
+ }
648
+
649
+ private Context getContext() {
650
+ return mContext;
651
+ }
652
+
653
+ private Context getApplicationContext() {
654
+ return mContext.getApplicationContext();
655
+ }
656
+
657
+ public static void showAppSettings(Context context) {
658
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
659
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
660
+ intent.setData(Uri.parse("package:" + context.getPackageName()));
661
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
662
+ intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
663
+ intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
664
+ context.startActivity(intent);
665
+ }
666
+
667
+ public static void showLocationSettings(Context context) {
668
+ Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
669
+ intent.addCategory(Intent.CATEGORY_DEFAULT);
670
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
671
+ intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
672
+ intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
673
+ context.startActivity(intent);
674
+ }
675
+
676
+ public static boolean hasPermissions(Context context, String[] permissions) {
677
+ for (String perm: permissions) {
678
+ if (ContextCompat.checkSelfPermission(context, perm) != PackageManager.PERMISSION_GRANTED) {
679
+ return false;
680
+ }
681
+ }
682
+ return true;
683
+ }
684
+
685
+ /**
686
+ * Sets a transform for each coordinate about to be committed (sent or saved for later sync).
687
+ * You can use this for modifying the coordinates in any way.
688
+ *
689
+ * If the transform returns <code>null</code>, it will prevent the location from being committed.
690
+ * @param transform - the transform listener
691
+ */
692
+ public static void setLocationTransform(LocationTransform transform) {
693
+ LocationServiceImpl.setLocationTransform(transform);
694
+ }
695
+
696
+ public static LocationTransform getLocationTransform() {
697
+ return LocationServiceImpl.getLocationTransform();
698
+ }
699
+ }