@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,321 @@
1
+ package com.marianhello.bgloc.data.provider;
2
+
3
+ import android.content.ContentProvider;
4
+ import android.content.ContentResolver;
5
+ import android.content.ContentUris;
6
+ import android.content.ContentValues;
7
+ import android.content.Context;
8
+ import android.content.UriMatcher;
9
+ import android.database.Cursor;
10
+ import android.database.SQLException;
11
+ import android.database.sqlite.SQLiteDatabase;
12
+ import android.database.sqlite.SQLiteQueryBuilder;
13
+ import android.net.Uri;
14
+ import android.text.TextUtils;
15
+
16
+ import com.marianhello.bgloc.ResourceResolver;
17
+ import com.marianhello.bgloc.data.sqlite.SQLiteLocationContract.LocationEntry;
18
+ import com.marianhello.bgloc.data.sqlite.SQLiteOpenHelper;
19
+
20
+ /**
21
+ * Content provider implementation based on
22
+ * https://shellmonger.com/2017/06/28/android-notes-app-content-providers/
23
+ */
24
+ public class LocationContentProvider extends ContentProvider {
25
+
26
+ /**
27
+ * Creates a UriMatcher for matching the path elements for this content provider
28
+ */
29
+ private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
30
+
31
+ /**
32
+ * The code for the UriMatch matching all notes
33
+ */
34
+ private static final int ALL_ITEMS = 10;
35
+
36
+ /**
37
+ * The code for the UriMatch matching a single note
38
+ */
39
+ private static final int ONE_ITEM = 20;
40
+
41
+ /**
42
+ * The database helper for this content provider
43
+ */
44
+ private SQLiteOpenHelper mDatabaseHelper;
45
+
46
+ /*
47
+ * Initialize the UriMatcher with the URIs that this content provider handles
48
+ *
49
+ * All paths added to the UriMatcher have a corresponding code to return when a match is
50
+ * found. The code passed into the constructor of UriMatcher here represents the code to
51
+ * return for the root URI. It's common to use NO_MATCH as the code for this case.
52
+ */
53
+ private static void initialize(String authority) {
54
+
55
+ /* This URI is content://com.example.location/location/ */
56
+ sUriMatcher.addURI(
57
+ authority,
58
+ LocationEntry.TABLE_NAME,
59
+ ALL_ITEMS);
60
+
61
+
62
+ /*
63
+ * This URI would look something like content://com.example.location/location/1
64
+ * The "/#" signifies to the UriMatcher that if TABLE_NAME is followed by ANY number,
65
+ * that it should return the ONE_ITEM code
66
+ */
67
+ sUriMatcher.addURI(
68
+ authority,
69
+ LocationEntry.TABLE_NAME + "/#",
70
+ ONE_ITEM);
71
+ }
72
+
73
+ /**
74
+ * Part of the Content Provider interface. The system calls onCreate() when it starts up
75
+ * the provider. You should only perform fast-running initialization tasks in this method.
76
+ * Defer database creation and data loading until the provider actually receives a request
77
+ * for the data. This runs on the UI thread.
78
+ *
79
+ * @return true if the provider was successfully loaded; false otherwise
80
+ */
81
+ @Override
82
+ public boolean onCreate() {
83
+ Context context = getContext();
84
+ ResourceResolver resourceResolver = ResourceResolver.newInstance(getContext());
85
+ initialize(resourceResolver.getAuthority());
86
+ mDatabaseHelper = new SQLiteOpenHelper(context);
87
+ return true;
88
+ }
89
+
90
+ /**
91
+ * The content provider must return the content type for its supported URIs. The supported
92
+ * URIs are defined in the UriMatcher
93
+ *
94
+ * As we don't export this content provider, we return null here.
95
+ *
96
+ * @param uri the URI for typing
97
+ * @return the type of the URI
98
+ */
99
+ @Override
100
+ public String getType(Uri uri) {
101
+ return null;
102
+ }
103
+
104
+ /**
105
+ * Handles query requests from clients. We will use this method to query for all
106
+ * of our location data as well as to query for the specific location record.
107
+ *
108
+ * @param uri The URI to query
109
+ * @param projection The list of columns to put into the cursor. If null, all columns are
110
+ * included.
111
+ * @param selection A selection criteria to apply when filtering rows. If null, then all
112
+ * rows are included.
113
+ * @param selectionArgs You may include ?s in selection, which will be replaced by
114
+ * the values from selectionArgs, in order that they appear in the
115
+ * selection.
116
+ * @param sortOrder How the rows in the cursor should be sorted.
117
+ * @return A Cursor containing the results of the query. In our implementation,
118
+ */
119
+ @Override
120
+ public Cursor query(
121
+ Uri uri,
122
+ String[] projection,
123
+ String selection,
124
+ String[] selectionArgs,
125
+ String sortOrder) {
126
+
127
+ int uriType = sUriMatcher.match(uri);
128
+ SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
129
+ SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
130
+
131
+ switch (uriType) {
132
+ /*
133
+ * When sUriMatcher's match method is called with a URI that looks EXACTLY like this
134
+ *
135
+ * content://com.example.location/location
136
+ *
137
+ * sUriMatcher's match method will return the code that indicates to us that we need
138
+ * to return all of the records in our location table.
139
+ *
140
+ * In this case, we want to return a cursor that contains every record
141
+ * in our location table.
142
+ */
143
+ case ALL_ITEMS:
144
+ queryBuilder.setTables(LocationEntry.TABLE_NAME);
145
+ if (TextUtils.isEmpty(sortOrder)) {
146
+ sortOrder = LocationEntry.COLUMN_NAME_TIME + " ASC";
147
+ }
148
+ break;
149
+
150
+
151
+ /*
152
+ * When sUriMatcher's match method is called with a URI that looks something like this
153
+ *
154
+ * content://com.example.location/location/2
155
+ *
156
+ * sUriMatcher's match method will return the code that indicates to us that we need
157
+ * to return the location for a particular id. The id in this code is encoded in
158
+ * int and is at the very end of the URI (2) and can be accessed
159
+ * programmatically using Uri's getLastPathSegment method.
160
+ *
161
+ * In this case, we want to return a cursor that contains one row of location data for
162
+ * a particular date.
163
+ */
164
+ case ONE_ITEM:
165
+ queryBuilder.setTables(LocationEntry.TABLE_NAME);
166
+ queryBuilder.appendWhere(LocationEntry._ID + " = " + uri.getLastPathSegment());
167
+ break;
168
+
169
+ default:
170
+ throw new IllegalArgumentException("Unsupported URI: " + uri);
171
+ }
172
+
173
+ Cursor cursor = queryBuilder.query(db, projection, selection, selectionArgs, null, null, sortOrder);
174
+ cursor.setNotificationUri(getContext().getContentResolver(), uri);
175
+ return cursor;
176
+ }
177
+
178
+ /**
179
+ * Insert a new record into the database.
180
+ *
181
+ * @param uri the base URI to insert at (must be a directory-based URI)
182
+ * @param values the values to be inserted
183
+ * @return the URI of the inserted item
184
+ */
185
+ @Override
186
+ public Uri insert(Uri uri, ContentValues values) {
187
+ int uriType = sUriMatcher.match(uri);
188
+ switch (uriType) {
189
+ case ALL_ITEMS:
190
+ SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
191
+ long id = db.insert(
192
+ LocationEntry.TABLE_NAME,
193
+ null,
194
+ values);
195
+ if (id > 0) {
196
+ Uri item = ContentUris.withAppendedId(uri, id);
197
+ notifyAllListeners(item);
198
+ return item;
199
+ }
200
+
201
+ throw new SQLException("Error inserting for URI " + uri + " result:" + id);
202
+ default:
203
+ throw new IllegalArgumentException("Unsupported URI: " + uri);
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Delete one or more records from the SQLite database.
209
+ *
210
+ * @param uri the URI of the record(s) to delete
211
+ * @param selection A WHERE clause to use for the deletion
212
+ * @param selectionArgs Any arguments to replace the ? in the selection
213
+ * @return the number of rows deleted.
214
+ */
215
+ @Override
216
+ public int delete(Uri uri, String selection, String[] selectionArgs) {
217
+ int uriType = sUriMatcher.match(uri);
218
+ int rows;
219
+ SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
220
+ switch (uriType) {
221
+ case ALL_ITEMS:
222
+ rows = db.delete(
223
+ LocationEntry.TABLE_NAME, // The table name
224
+ selection, selectionArgs); // The WHERE clause
225
+ break;
226
+ case ONE_ITEM:
227
+ String where = LocationEntry._ID + " = " + uri.getLastPathSegment();
228
+ if (!TextUtils.isEmpty(selection)) {
229
+ where += " AND " + selection;
230
+ }
231
+ rows = db.delete(
232
+ LocationEntry.TABLE_NAME, // The table name
233
+ where, selectionArgs); // The WHERE clause
234
+ break;
235
+ default:
236
+ throw new IllegalArgumentException("Unsupported URI: " + uri);
237
+ }
238
+ if (rows > 0) {
239
+ notifyAllListeners(uri);
240
+ }
241
+ return rows;
242
+ }
243
+
244
+ @Override
245
+ public int update(
246
+ Uri uri,
247
+ ContentValues values,
248
+ String selection,
249
+ String[] selectionArgs) {
250
+ int uriType = sUriMatcher.match(uri);
251
+ int rows;
252
+ SQLiteDatabase db = mDatabaseHelper.getWritableDatabase();
253
+ switch (uriType) {
254
+ case ALL_ITEMS:
255
+ rows = db.update(
256
+ LocationEntry.TABLE_NAME, // The table name
257
+ values, // The values to replace
258
+ selection, selectionArgs); // The WHERE clause
259
+ break;
260
+ case ONE_ITEM:
261
+ String where = LocationEntry._ID + " = " + uri.getLastPathSegment();
262
+ if (!TextUtils.isEmpty(selection)) {
263
+ where += " AND " + selection;
264
+ }
265
+ rows = db.update(
266
+ LocationEntry.TABLE_NAME, // The table name
267
+ values, // The values to replace
268
+ where, selectionArgs); // The WHERE clause
269
+ break;
270
+ default:
271
+ throw new IllegalArgumentException("Unsupported URI: " + uri);
272
+ }
273
+ if (rows > 0) {
274
+ notifyAllListeners(uri);
275
+ }
276
+ return rows;
277
+ }
278
+
279
+ /**
280
+ * Notify all listeners that the specified URI has changed
281
+ * @param uri the URI that changed
282
+ */
283
+ private void notifyAllListeners(Uri uri) {
284
+ ContentResolver resolver = getContext().getContentResolver();
285
+ if (resolver != null) {
286
+ resolver.notifyChange(uri, null);
287
+ }
288
+ }
289
+
290
+ /**
291
+ * The base CONTENT_URI used to query the Location table from the content provider
292
+ */
293
+ public static Uri getBaseContentUri(String authority) {
294
+ return Uri.parse("content://" + authority);
295
+ }
296
+
297
+ /**
298
+ * The content URI for this table
299
+ */
300
+ public static Uri getContentUri(String authority) {
301
+ return getBaseContentUri(authority).buildUpon()
302
+ .appendPath(LocationEntry.TABLE_NAME)
303
+ .build();
304
+ }
305
+
306
+ /**
307
+ * Builds a URI that adds the task _ID to the end of the location content URI path.
308
+ * This is used to query details about a single location entry by _ID. This is what we
309
+ * use for the detail view query.
310
+ *
311
+ * @param authority The authority of the locations content provider
312
+ * @param id Unique id pointing to that row
313
+ * @return Uri to query details about a single location entry
314
+ */
315
+ public static Uri buildUriWithId(String authority, long id) {
316
+ return getContentUri(authority).buildUpon()
317
+ .appendPath(Long.toString(id))
318
+ .build();
319
+ }
320
+ }
321
+
@@ -0,0 +1,94 @@
1
+ package com.marianhello.bgloc.data.sqlite;
2
+
3
+ import android.provider.BaseColumns;
4
+
5
+ import static com.marianhello.bgloc.data.sqlite.SQLiteOpenHelper.COMMA_SEP;
6
+ import static com.marianhello.bgloc.data.sqlite.SQLiteOpenHelper.INTEGER_TYPE;
7
+ import static com.marianhello.bgloc.data.sqlite.SQLiteOpenHelper.REAL_TYPE;
8
+ import static com.marianhello.bgloc.data.sqlite.SQLiteOpenHelper.TEXT_TYPE;
9
+
10
+ public final class SQLiteConfigurationContract {
11
+ // To prevent someone from accidentally instantiating the contract class,
12
+ // give it an empty constructor.
13
+ public SQLiteConfigurationContract() {}
14
+
15
+ /* Inner class that defines the table contents */
16
+ public static abstract class ConfigurationEntry implements BaseColumns {
17
+ public static final String TABLE_NAME = "configuration";
18
+ public static final String COLUMN_NAME_NULLABLE = "NULLHACK";
19
+ public static final String COLUMN_NAME_RADIUS = "stationary_radius";
20
+ public static final String COLUMN_NAME_DISTANCE_FILTER = "distance_filter";
21
+ public static final String COLUMN_NAME_DESIRED_ACCURACY = "desired_accuracy";
22
+ public static final String COLUMN_NAME_DEBUG = "debugging";
23
+ public static final String COLUMN_NAME_NOTIF_TITLE = "notification_title";
24
+ public static final String COLUMN_NAME_NOTIF_TEXT = "notification_text";
25
+ public static final String COLUMN_NAME_NOTIF_SYNC_TITLE = "notification_sync_title";
26
+ public static final String COLUMN_NAME_NOTIF_SYNC_TEXT = "notification_sync_text";
27
+ public static final String COLUMN_NAME_NOTIF_SYNC_COMPLETED = "notification_sync_completed_text";
28
+ public static final String COLUMN_NAME_NOTIF_SYNC_FAILED = "notification_sync_failed_text";
29
+ public static final String COLUMN_NAME_NOTIF_ICON_LARGE = "notification_icon_large";
30
+ public static final String COLUMN_NAME_NOTIF_ICON_SMALL = "notification_icon_small";
31
+ public static final String COLUMN_NAME_NOTIF_COLOR = "notification_icon_color";
32
+ public static final String COLUMN_NAME_STOP_TERMINATE = "stop_terminate";
33
+ public static final String COLUMN_NAME_START_BOOT = "start_boot";
34
+ public static final String COLUMN_NAME_START_FOREGROUND = "start_foreground";
35
+ public static final String COLUMN_NAME_NOTIFICATIONS_ENABLED = "notifications_enabled";
36
+ public static final String COLUMN_NAME_STOP_ON_STILL = "stop_still";
37
+ public static final String COLUMN_NAME_LOCATION_PROVIDER = "service_provider";
38
+ public static final String COLUMN_NAME_INTERVAL = "interval";
39
+ public static final String COLUMN_NAME_FASTEST_INTERVAL = "fastest_interval";
40
+ public static final String COLUMN_NAME_ACTIVITIES_INTERVAL = "activities_interval";
41
+ public static final String COLUMN_NAME_URL = "url";
42
+ public static final String COLUMN_NAME_SYNC_URL = "sync_url";
43
+ public static final String COLUMN_NAME_SYNC_THRESHOLD = "sync_threshold";
44
+ public static final String COLUMN_NAME_SYNC_ENABLED = "sync_enabled";
45
+ public static final String COLUMN_NAME_HEADERS = "http_headers";
46
+ public static final String COLUMN_NAME_MAX_LOCATIONS = "max_locations";
47
+ public static final String COLUMN_NAME_TEMPLATE = "template";
48
+ public static final String COLUMN_NAME_SHOW_TIME = "show_time";
49
+ public static final String COLUMN_NAME_SHOW_DISTANCE = "show_distance";
50
+ // v4.4.1 — single JSON blob holding the full config (replaces per-field columns
51
+ // for new keys). Old columns are kept for backward compat with v20 databases.
52
+ public static final String COLUMN_NAME_CONFIG_JSON = "config_json";
53
+
54
+ public static final String SQL_CREATE_CONFIG_TABLE =
55
+ "CREATE TABLE " + ConfigurationEntry.TABLE_NAME + " (" +
56
+ ConfigurationEntry._ID + " INTEGER PRIMARY KEY," +
57
+ ConfigurationEntry.COLUMN_NAME_RADIUS + REAL_TYPE + COMMA_SEP +
58
+ ConfigurationEntry.COLUMN_NAME_DISTANCE_FILTER + INTEGER_TYPE + COMMA_SEP +
59
+ ConfigurationEntry.COLUMN_NAME_DESIRED_ACCURACY + INTEGER_TYPE + COMMA_SEP +
60
+ ConfigurationEntry.COLUMN_NAME_DEBUG + INTEGER_TYPE + COMMA_SEP +
61
+ ConfigurationEntry.COLUMN_NAME_NOTIF_TITLE + TEXT_TYPE + COMMA_SEP +
62
+ ConfigurationEntry.COLUMN_NAME_NOTIF_TEXT + TEXT_TYPE + COMMA_SEP +
63
+ ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_TITLE + TEXT_TYPE + COMMA_SEP +
64
+ ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_TEXT + TEXT_TYPE + COMMA_SEP +
65
+ ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_COMPLETED + TEXT_TYPE + COMMA_SEP +
66
+ ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_FAILED + TEXT_TYPE + COMMA_SEP +
67
+ ConfigurationEntry.COLUMN_NAME_NOTIF_ICON_SMALL + TEXT_TYPE + COMMA_SEP +
68
+ ConfigurationEntry.COLUMN_NAME_NOTIF_ICON_LARGE + TEXT_TYPE + COMMA_SEP +
69
+ ConfigurationEntry.COLUMN_NAME_NOTIF_COLOR + TEXT_TYPE + COMMA_SEP +
70
+ ConfigurationEntry.COLUMN_NAME_STOP_TERMINATE + INTEGER_TYPE + COMMA_SEP +
71
+ ConfigurationEntry.COLUMN_NAME_STOP_ON_STILL + INTEGER_TYPE + COMMA_SEP +
72
+ ConfigurationEntry.COLUMN_NAME_START_BOOT + INTEGER_TYPE + COMMA_SEP +
73
+ ConfigurationEntry.COLUMN_NAME_START_FOREGROUND + INTEGER_TYPE + COMMA_SEP +
74
+ ConfigurationEntry.COLUMN_NAME_NOTIFICATIONS_ENABLED + INTEGER_TYPE + COMMA_SEP +
75
+ ConfigurationEntry.COLUMN_NAME_LOCATION_PROVIDER + TEXT_TYPE + COMMA_SEP +
76
+ ConfigurationEntry.COLUMN_NAME_INTERVAL + INTEGER_TYPE + COMMA_SEP +
77
+ ConfigurationEntry.COLUMN_NAME_FASTEST_INTERVAL + INTEGER_TYPE + COMMA_SEP +
78
+ ConfigurationEntry.COLUMN_NAME_ACTIVITIES_INTERVAL + INTEGER_TYPE + COMMA_SEP +
79
+ ConfigurationEntry.COLUMN_NAME_URL + TEXT_TYPE + COMMA_SEP +
80
+ ConfigurationEntry.COLUMN_NAME_SYNC_URL + TEXT_TYPE + COMMA_SEP +
81
+ ConfigurationEntry.COLUMN_NAME_SYNC_THRESHOLD + INTEGER_TYPE + COMMA_SEP +
82
+ ConfigurationEntry.COLUMN_NAME_SYNC_ENABLED + INTEGER_TYPE + COMMA_SEP +
83
+ ConfigurationEntry.COLUMN_NAME_HEADERS + TEXT_TYPE + COMMA_SEP +
84
+ ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS + INTEGER_TYPE + COMMA_SEP +
85
+ ConfigurationEntry.COLUMN_NAME_TEMPLATE + TEXT_TYPE + COMMA_SEP +
86
+ ConfigurationEntry.COLUMN_NAME_SHOW_TIME + INTEGER_TYPE + COMMA_SEP +
87
+ ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE + INTEGER_TYPE + COMMA_SEP +
88
+ ConfigurationEntry.COLUMN_NAME_CONFIG_JSON + TEXT_TYPE +
89
+ " )";
90
+
91
+ public static final String SQL_DROP_CONFIG_TABLE =
92
+ "DROP TABLE IF EXISTS " + ConfigurationEntry.TABLE_NAME;
93
+ }
94
+ }
@@ -0,0 +1,227 @@
1
+ package com.marianhello.bgloc.data.sqlite;
2
+
3
+ import android.content.ContentValues;
4
+ import android.content.Context;
5
+ import android.database.Cursor;
6
+ import android.database.sqlite.SQLiteDatabase;
7
+ import android.util.Log;
8
+
9
+ import org.json.JSONObject;
10
+ import org.json.JSONException;
11
+
12
+ import com.marianhello.bgloc.Config;
13
+ import com.marianhello.bgloc.data.ConfigJsonMapper;
14
+ import com.marianhello.bgloc.data.ConfigurationDAO;
15
+ import com.marianhello.bgloc.data.LocationTemplateFactory;
16
+ import com.marianhello.bgloc.data.sqlite.SQLiteConfigurationContract.ConfigurationEntry;
17
+
18
+ public class SQLiteConfigurationDAO implements ConfigurationDAO {
19
+ private static final String TAG = SQLiteConfigurationDAO.class.getName();
20
+
21
+ private SQLiteDatabase db;
22
+
23
+ public SQLiteConfigurationDAO(Context context) {
24
+ SQLiteOpenHelper helper = SQLiteOpenHelper.getHelper(context);
25
+ this.db = helper.getWritableDatabase();
26
+ }
27
+
28
+ public SQLiteConfigurationDAO(SQLiteDatabase db) {
29
+ this.db = db;
30
+ }
31
+
32
+ public Config retrieveConfiguration() throws JSONException {
33
+ Cursor cursor = null;
34
+
35
+ String[] columns = {
36
+ ConfigurationEntry._ID,
37
+ ConfigurationEntry.COLUMN_NAME_RADIUS,
38
+ ConfigurationEntry.COLUMN_NAME_DISTANCE_FILTER,
39
+ ConfigurationEntry.COLUMN_NAME_DESIRED_ACCURACY,
40
+ ConfigurationEntry.COLUMN_NAME_DEBUG,
41
+ ConfigurationEntry.COLUMN_NAME_NOTIF_TITLE,
42
+ ConfigurationEntry.COLUMN_NAME_NOTIF_TEXT,
43
+ ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_TITLE,
44
+ ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_TEXT,
45
+ ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_COMPLETED,
46
+ ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_FAILED,
47
+ ConfigurationEntry.COLUMN_NAME_NOTIF_ICON_LARGE,
48
+ ConfigurationEntry.COLUMN_NAME_NOTIF_ICON_SMALL,
49
+ ConfigurationEntry.COLUMN_NAME_NOTIF_COLOR,
50
+ ConfigurationEntry.COLUMN_NAME_STOP_TERMINATE,
51
+ ConfigurationEntry.COLUMN_NAME_STOP_ON_STILL,
52
+ ConfigurationEntry.COLUMN_NAME_START_BOOT,
53
+ ConfigurationEntry.COLUMN_NAME_START_FOREGROUND,
54
+ ConfigurationEntry.COLUMN_NAME_NOTIFICATIONS_ENABLED,
55
+ ConfigurationEntry.COLUMN_NAME_LOCATION_PROVIDER,
56
+ ConfigurationEntry.COLUMN_NAME_INTERVAL,
57
+ ConfigurationEntry.COLUMN_NAME_FASTEST_INTERVAL,
58
+ ConfigurationEntry.COLUMN_NAME_ACTIVITIES_INTERVAL,
59
+ ConfigurationEntry.COLUMN_NAME_URL,
60
+ ConfigurationEntry.COLUMN_NAME_SYNC_URL,
61
+ ConfigurationEntry.COLUMN_NAME_SYNC_THRESHOLD,
62
+ ConfigurationEntry.COLUMN_NAME_SYNC_ENABLED,
63
+ ConfigurationEntry.COLUMN_NAME_HEADERS,
64
+ ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS,
65
+ ConfigurationEntry.COLUMN_NAME_TEMPLATE,
66
+ ConfigurationEntry.COLUMN_NAME_SHOW_TIME,
67
+ ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE,
68
+ ConfigurationEntry.COLUMN_NAME_CONFIG_JSON
69
+ };
70
+
71
+ String whereClause = null;
72
+ String[] whereArgs = null;
73
+ String groupBy = null;
74
+ String having = null;
75
+ String orderBy = null;
76
+
77
+ Config config = null;
78
+ try {
79
+ cursor = db.query(
80
+ ConfigurationEntry.TABLE_NAME, // The table to query
81
+ columns, // The columns to return
82
+ whereClause, // The columns for the WHERE clause
83
+ whereArgs, // The values for the WHERE clause
84
+ groupBy, // don't group the rows
85
+ having, // don't filter by row groups
86
+ orderBy // The sort order
87
+ );
88
+ if (cursor.moveToFirst()) {
89
+ config = hydrate(cursor);
90
+ }
91
+ } finally {
92
+ if (cursor != null) {
93
+ cursor.close();
94
+ }
95
+ }
96
+ return config;
97
+ }
98
+
99
+ public boolean persistConfiguration(Config config) throws NullPointerException {
100
+ long rowId = db.replace(ConfigurationEntry.TABLE_NAME, ConfigurationEntry.COLUMN_NAME_NULLABLE, getContentValues(config));
101
+ Log.d(TAG, "Configuration persisted with rowId = " + rowId);
102
+ if (rowId > -1) {
103
+ return true;
104
+ } else {
105
+ return false;
106
+ }
107
+ }
108
+
109
+ private Config hydrate(Cursor c) throws JSONException {
110
+ // v4.4.1: prefer the full JSON blob if present (covers all keys, including post-3.2 ones).
111
+ // Note: `template` (postTemplate) lives in its dedicated column — restore it after the
112
+ // JSON deserialization so it's not lost when the config arrived via config_json only.
113
+ int idxJson = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_CONFIG_JSON);
114
+ if (idxJson >= 0 && !c.isNull(idxJson)) {
115
+ String json = c.getString(idxJson);
116
+ if (json != null && !json.isEmpty()) {
117
+ try {
118
+ Config restored = ConfigJsonMapper.fromJSONObject(new JSONObject(json));
119
+ int idxTpl = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_TEMPLATE);
120
+ if (idxTpl >= 0 && !c.isNull(idxTpl)) {
121
+ restored.setTemplate(LocationTemplateFactory.fromJSONString(c.getString(idxTpl)));
122
+ }
123
+ return restored;
124
+ } catch (JSONException ex) {
125
+ Log.w(TAG, "config_json parse failed; falling back to legacy columns: " + ex.getMessage());
126
+ }
127
+ }
128
+ }
129
+ // Legacy hydration (DBs upgraded from v20 or earlier where config_json is still NULL).
130
+ Config config = Config.getDefault();
131
+ config.setStationaryRadius(c.getFloat(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_RADIUS)));
132
+ config.setDistanceFilter(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_DISTANCE_FILTER)));
133
+ config.setDesiredAccuracy(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_DESIRED_ACCURACY)));
134
+ config.setDebugging( (c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_DEBUG)) == 1) ? true : false );
135
+ config.setNotificationTitle(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_TITLE)));
136
+ config.setNotificationText(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_TEXT)));
137
+ int idxSyncTitle = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_TITLE);
138
+ if (idxSyncTitle >= 0) {
139
+ if (!c.isNull(idxSyncTitle)) config.setNotificationSyncTitle(c.getString(idxSyncTitle));
140
+ int idxSyncText = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_TEXT);
141
+ if (idxSyncText >= 0 && !c.isNull(idxSyncText)) config.setNotificationSyncText(c.getString(idxSyncText));
142
+ int idxSyncCompleted = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_COMPLETED);
143
+ if (idxSyncCompleted >= 0 && !c.isNull(idxSyncCompleted)) config.setNotificationSyncCompletedText(c.getString(idxSyncCompleted));
144
+ int idxSyncFailed = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_FAILED);
145
+ if (idxSyncFailed >= 0 && !c.isNull(idxSyncFailed)) config.setNotificationSyncFailedText(c.getString(idxSyncFailed));
146
+ }
147
+ config.setSmallNotificationIcon(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_ICON_SMALL)));
148
+ config.setLargeNotificationIcon(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_ICON_LARGE)));
149
+ config.setNotificationIconColor(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIF_COLOR)));
150
+ config.setStopOnTerminate( (c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_STOP_TERMINATE)) == 1) ? true : false );
151
+ config.setStopOnStillActivity( (c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_STOP_ON_STILL)) == 1) ? true : false );
152
+ config.setStartOnBoot( (c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_START_BOOT)) == 1) ? true : false );
153
+ config.setStartForeground( (c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_START_FOREGROUND)) == 1) ? true : false );
154
+ config.setNotificationsEnabled( (c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_NOTIFICATIONS_ENABLED)) == 1) ? true : false );
155
+ config.setLocationProvider(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_LOCATION_PROVIDER)));
156
+ config.setInterval(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_INTERVAL)));
157
+ config.setFastestInterval(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_FASTEST_INTERVAL)));
158
+ config.setActivitiesInterval(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_ACTIVITIES_INTERVAL)));
159
+ config.setUrl(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_URL)));
160
+ config.setSyncUrl(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_SYNC_URL)));
161
+ config.setSyncThreshold(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_SYNC_THRESHOLD)));
162
+ int idxSyncEnabled = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_SYNC_ENABLED);
163
+ if (idxSyncEnabled >= 0 && !c.isNull(idxSyncEnabled)) {
164
+ config.setSyncEnabled(c.getInt(idxSyncEnabled) == 1);
165
+ }
166
+ config.setHttpHeaders(new JSONObject(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_HEADERS))));
167
+ config.setMaxLocations(c.getInt(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS)));
168
+ config.setTemplate(LocationTemplateFactory.fromJSONString(c.getString(c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_TEMPLATE))));
169
+ int idxShowTime = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_SHOW_TIME);
170
+ if (idxShowTime >= 0 && !c.isNull(idxShowTime)) {
171
+ config.setShowTime(c.getInt(idxShowTime) == 1);
172
+ }
173
+ int idxShowDistance = c.getColumnIndex(ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE);
174
+ if (idxShowDistance >= 0 && !c.isNull(idxShowDistance)) {
175
+ config.setShowDistance(c.getInt(idxShowDistance) == 1);
176
+ }
177
+
178
+ return config;
179
+ }
180
+
181
+ private ContentValues getContentValues(Config config) throws NullPointerException {
182
+ ContentValues values = new ContentValues();
183
+ values.put(ConfigurationEntry._ID, 1);
184
+ values.put(ConfigurationEntry.COLUMN_NAME_RADIUS, config.getStationaryRadius());
185
+ values.put(ConfigurationEntry.COLUMN_NAME_DISTANCE_FILTER, config.getDistanceFilter());
186
+ values.put(ConfigurationEntry.COLUMN_NAME_DESIRED_ACCURACY, config.getDesiredAccuracy());
187
+ values.put(ConfigurationEntry.COLUMN_NAME_DEBUG, (config.isDebugging() == true) ? 1 : 0);
188
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_TITLE, config.getNotificationTitle());
189
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_TEXT, config.getNotificationText());
190
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_TITLE, config.getNotificationSyncTitle());
191
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_TEXT, config.getNotificationSyncText());
192
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_COMPLETED, config.getNotificationSyncCompletedText());
193
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_SYNC_FAILED, config.getNotificationSyncFailedText());
194
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_ICON_SMALL, config.getSmallNotificationIcon());
195
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_ICON_LARGE, config.getLargeNotificationIcon());
196
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIF_COLOR, config.getNotificationIconColor());
197
+ values.put(ConfigurationEntry.COLUMN_NAME_STOP_TERMINATE, (config.getStopOnTerminate() == true) ? 1 : 0);
198
+ values.put(ConfigurationEntry.COLUMN_NAME_STOP_ON_STILL, (config.getStopOnStillActivity() == true) ? 1 : 0);
199
+ values.put(ConfigurationEntry.COLUMN_NAME_START_BOOT, (config.getStartOnBoot() == true) ? 1 : 0);
200
+ values.put(ConfigurationEntry.COLUMN_NAME_START_FOREGROUND, (config.getStartForeground() == true) ? 1 : 0);
201
+ values.put(ConfigurationEntry.COLUMN_NAME_NOTIFICATIONS_ENABLED, (config.getNotificationsEnabled() == true) ? 1 : 0);
202
+ values.put(ConfigurationEntry.COLUMN_NAME_LOCATION_PROVIDER, config.getLocationProvider());
203
+ values.put(ConfigurationEntry.COLUMN_NAME_INTERVAL, config.getInterval());
204
+ values.put(ConfigurationEntry.COLUMN_NAME_FASTEST_INTERVAL, config.getFastestInterval());
205
+ values.put(ConfigurationEntry.COLUMN_NAME_ACTIVITIES_INTERVAL, config.getActivitiesInterval());
206
+ values.put(ConfigurationEntry.COLUMN_NAME_URL, config.getUrl());
207
+ values.put(ConfigurationEntry.COLUMN_NAME_SYNC_URL, config.getSyncUrl());
208
+ values.put(ConfigurationEntry.COLUMN_NAME_SYNC_THRESHOLD, config.getSyncThreshold());
209
+ values.put(ConfigurationEntry.COLUMN_NAME_SYNC_ENABLED, Boolean.TRUE.equals(config.getSyncEnabled()) ? 1 : 0);
210
+ values.put(ConfigurationEntry.COLUMN_NAME_HEADERS, new JSONObject(config.getHttpHeaders()).toString());
211
+ values.put(ConfigurationEntry.COLUMN_NAME_MAX_LOCATIONS, config.getMaxLocations());
212
+ values.put(ConfigurationEntry.COLUMN_NAME_TEMPLATE, config.hasTemplate() ? config.getTemplate().toString() : null);
213
+ values.put(ConfigurationEntry.COLUMN_NAME_SHOW_TIME, Boolean.TRUE.equals(config.getShowTime()) ? 1 : 0);
214
+ values.put(ConfigurationEntry.COLUMN_NAME_SHOW_DISTANCE, Boolean.TRUE.equals(config.getShowDistance()) ? 1 : 0);
215
+ // v4.4.1: persist the full Config as JSON so post-3.2 fields (httpMethod, queryParams,
216
+ // drivingEvents, includeBattery, mockLocationPolicy, heartbeatInterval, ...) survive
217
+ // a reboot / startOnBoot. Legacy columns are kept populated above for backward compat.
218
+ try {
219
+ values.put(ConfigurationEntry.COLUMN_NAME_CONFIG_JSON,
220
+ ConfigJsonMapper.toJSONObject(config).toString());
221
+ } catch (JSONException e) {
222
+ Log.w(TAG, "config_json serialize failed: " + e.getMessage());
223
+ }
224
+
225
+ return values;
226
+ }
227
+ }