@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,276 @@
1
+ //
2
+ // MAURSQLiteOpenHelper.m
3
+ //
4
+ // Created by Marian Hello on 22/06/16.
5
+ //
6
+
7
+ #import <Foundation/Foundation.h>
8
+ #import <sqlite3.h>
9
+ #import "MAURSQLiteHelper.h"
10
+ #import "MAURSQLiteOpenHelper.h"
11
+
12
+ @implementation MAURSQLiteOpenHelper {
13
+ FMDatabaseQueue *mQueue;
14
+ BOOL mIsInitializing;
15
+ BOOL mIsReadOnly;
16
+ NSInteger mNewVersion; // REMARK: never use mNewVersion < 1 in your subclasses
17
+ NSString* mName;
18
+ }
19
+
20
+ static NSString *const metaTableName = @"__META";
21
+ static int const OPEN_READONLY = SQLITE_OPEN_READONLY|SQLITE_OPEN_FULLMUTEX;
22
+ static int const OPEN_READWRITE = SQLITE_OPEN_CREATE|SQLITE_OPEN_READWRITE|SQLITE_OPEN_FULLMUTEX;
23
+
24
+ - (instancetype)init:(NSString*)name version:(NSInteger)version
25
+ {
26
+ self = [super init];
27
+ if (self) {
28
+ self->mName = name;
29
+ self->mNewVersion = version;
30
+ }
31
+ return self;
32
+ }
33
+
34
+ - (FMDatabaseQueue*) getReadableDatabase
35
+ {
36
+
37
+ @synchronized(self) {
38
+ return [self getDatabaseLocked: NO];
39
+ }
40
+ }
41
+
42
+ - (FMDatabaseQueue*) getWritableDatabase
43
+ {
44
+ @synchronized(self) {
45
+ return [self getDatabaseLocked: YES];
46
+ }
47
+ }
48
+
49
+ - (FMDatabaseQueue*) getDatabaseLocked:(BOOL)writable
50
+ {
51
+ if (mQueue != nil) {
52
+ // TODO: add check if db was closed by user
53
+ return mQueue;
54
+ }
55
+
56
+ if (mIsInitializing) {
57
+ @throw [NSException exceptionWithName:NSInternalInconsistencyException
58
+ reason:[NSString stringWithFormat:@"getDatabaseLocked called recursively"]
59
+ userInfo:nil];
60
+ }
61
+
62
+ FMDatabaseQueue* queue = mQueue;
63
+ mIsInitializing = true;
64
+
65
+ if (queue != nil) {
66
+ if (writable && mIsReadOnly) {
67
+ // TODO reopen as writable
68
+ }
69
+ } else if (mName == nil) {
70
+ @throw [NSException exceptionWithName:NSInternalInconsistencyException
71
+ reason:[NSString stringWithFormat:@"in memory database is not supported"]
72
+ userInfo:nil];
73
+ } else {
74
+ if (writable) {
75
+ queue = [self openOrCreateDatabase:mName];
76
+ } else {
77
+ queue = [self openDatabase:[self getDatabasePath] flags: OPEN_READONLY];
78
+ }
79
+ }
80
+
81
+ [self onConfigure:queue];
82
+
83
+ NSInteger version = [self getVersion:queue];
84
+ NSLog(@"Current db version: %ld", (long)version);
85
+
86
+ if (version != mNewVersion) {
87
+ if (version == 0) {
88
+ [self onCreate:queue];
89
+ } else {
90
+ if (version < mNewVersion) {
91
+ [self onUpgrade:queue fromVersion:version toVersion:mNewVersion];
92
+ } else if (version > mNewVersion) {
93
+ [self onDowngrade:queue fromVersion:version toVersion:mNewVersion];
94
+ }
95
+ }
96
+ [self setVersion:queue version:mNewVersion];
97
+ }
98
+
99
+ [self onOpen:queue];
100
+
101
+ mQueue = queue;
102
+ mIsInitializing = false;
103
+ mIsReadOnly = !writable;
104
+ return queue;
105
+ }
106
+
107
+ - (FMDatabaseQueue*) openDatabase:(NSString*)path flags:(int)flags
108
+ {
109
+ return [FMDatabaseQueue databaseQueueWithPath:path flags:flags];
110
+ }
111
+
112
+ - (FMDatabaseQueue*) openOrCreateDatabase:(NSString*)name
113
+ {
114
+ __block BOOL isOpen;
115
+ FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:[self getDatabasePath:name]];
116
+
117
+ [queue inDatabase:^(FMDatabase *database) {
118
+ isOpen = [database open];
119
+ }];
120
+
121
+ if (!isOpen) {
122
+ return nil;
123
+ }
124
+
125
+ if ([self getVersion:queue] == -1) {
126
+ NSArray *columns = @[
127
+ @{ @"name": @"id", @"type": [SQLPrimaryKeyColumnType sqlColumnWithType: kInteger]},
128
+ @{ @"name": @"db_version", @"type": [SQLColumnType sqlColumnWithType: kInteger]},
129
+ @{ @"name": @"created", @"type": [SQLColumnType sqlColumnWithType: kInteger]},
130
+ @{ @"name": @"last_updated", @"type": [SQLColumnType sqlColumnWithType: kInteger]}
131
+ ];
132
+
133
+ [queue inDatabase:^(FMDatabase *database) {
134
+ if ([database executeStatements:[MAURSQLiteHelper createTableSqlStatement:metaTableName columns:columns]]) {
135
+ NSString *sql = [NSString stringWithFormat: @"INSERT INTO %@ (id,db_version,created,last_updated) VALUES (1,%d,datetime(),null)", metaTableName, 0];
136
+ if (![database executeUpdate:sql]) {
137
+ NSLog(@"%@ failed code: %d: message: %@", sql, [database lastErrorCode], [database lastErrorMessage]);
138
+ }
139
+ } else {
140
+ NSLog(@"Creating meta table %@ failed code: %d: message: %@", metaTableName, [database lastErrorCode], [database lastErrorMessage]);
141
+ }
142
+ }];
143
+ }
144
+
145
+ return queue;
146
+ }
147
+
148
+ - (void) close
149
+ {
150
+ @synchronized(self) {
151
+ if (mQueue != nil) {
152
+ [mQueue close];
153
+ mQueue = nil;
154
+ }
155
+ }
156
+ }
157
+
158
+ - (NSDictionary*) getDatabaseMetadata
159
+ {
160
+ FMDatabaseQueue *queue = [self getReadableDatabase];
161
+ NSMutableDictionary *metadata = [[NSMutableDictionary alloc] init];
162
+ [metadata setObject:[NSNumber numberWithInt:-1] forKey:@"dbVersion"];
163
+
164
+ NSString *sql =[NSString stringWithFormat: @"SELECT db_version, created, last_updated FROM %@ LIMIT 1", metaTableName];
165
+ [queue inDatabase:^(FMDatabase *database) {
166
+ FMResultSet *rs = [database executeQuery:sql];
167
+ while ([rs next]) {
168
+ NSNumber *dbVersion = [NSNumber numberWithInt:[rs intForColumnIndex:0]];
169
+ NSString *created = [rs stringForColumnIndex:1] ?: @"";
170
+ NSString *lastUpdated = [rs stringForColumnIndex:2] ?: @"";
171
+
172
+ [metadata setObject:dbVersion forKey:@"dbVersion"];
173
+ [metadata setObject:created forKey:@"created"];
174
+ [metadata setObject:lastUpdated forKey:@"last_updated"];
175
+ }
176
+
177
+ // TODO error handling
178
+ // NSLog(@"Retrieving meta data failed code: %d: message: %s", sqlite3_errcode(database), sqlite3_errmsg(database));
179
+ [rs close];
180
+
181
+ }];
182
+
183
+ [queue close];
184
+
185
+ return metadata;
186
+ }
187
+
188
+ - (NSString*) getDatabaseName
189
+ {
190
+ return mName;
191
+ }
192
+
193
+ - (NSString*) getDatabasePath:(NSString*)name
194
+ {
195
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
196
+ NSString *libraryDirectory = [paths objectAtIndex:0];
197
+ NSString *databasePath = [[NSString alloc]initWithString:[libraryDirectory stringByAppendingPathComponent:name]];
198
+
199
+ return databasePath;
200
+ }
201
+
202
+ - (NSString*) getDatabasePath
203
+ {
204
+ return [self getDatabasePath:mName];
205
+ }
206
+
207
+ - (FMDatabaseQueue*) getDatabaseQueue
208
+ {
209
+ @synchronized(self) {
210
+ if (mQueue == nil) {
211
+ mQueue = [FMDatabaseQueue databaseQueueWithPath:[self getDatabasePath]];
212
+ }
213
+
214
+ return mQueue;
215
+ }
216
+ }
217
+
218
+ - (NSInteger) getVersion:(FMDatabaseQueue*)queue
219
+ {
220
+ __block NSInteger dbVersion = -1;
221
+ NSString *sql =[NSString stringWithFormat: @"SELECT db_version FROM %@", metaTableName];
222
+ [queue inDatabase:^(FMDatabase *database) {
223
+ database.logsErrors = NO;
224
+ NSError *lastError;
225
+ FMResultSet *rs = [database executeQuery:sql values:nil error:&lastError];
226
+ if (rs != nil) {
227
+ while ([rs next]) {
228
+ dbVersion = [rs intForColumnIndex:0];
229
+ }
230
+ [rs close];
231
+ } else {
232
+ NSLog(@"Determining db version returned error (ok for first run): %@", [lastError localizedDescription]);
233
+ }
234
+ database.logsErrors = YES;
235
+ }];
236
+
237
+ return dbVersion;
238
+ }
239
+
240
+ - (void) setVersion:(FMDatabaseQueue*)queue version:(NSInteger)version
241
+ {
242
+ NSString *sql = [NSString stringWithFormat: @"UPDATE %@ SET db_version = %ld, last_updated = datetime()", metaTableName, (long)version];
243
+ [queue inDatabase:^(FMDatabase *database) {
244
+ if (![database executeUpdate:sql]) {
245
+ NSLog(@"%@ failed code: %d: message: %@", sql, [database lastErrorCode], [database lastErrorMessage]);
246
+ }
247
+ }];
248
+ }
249
+
250
+ - (void) onOpen:(FMDatabaseQueue*)database
251
+ {
252
+ // ment to be implemented in subclass
253
+ }
254
+
255
+ - (void) onConfigure:(FMDatabaseQueue*)database;
256
+ {
257
+ // ment to be implemented in subclass
258
+ }
259
+
260
+ - (void) onCreate:(FMDatabaseQueue*)database
261
+ {
262
+ // has to be implemented in subclass
263
+ }
264
+
265
+ - (void) onUpgrade:(FMDatabaseQueue*)database fromVersion:(NSInteger)oldVersion toVersion:(NSInteger)newVersion
266
+ {
267
+ // upgrade policy has to be implemented in subclass
268
+ }
269
+
270
+ - (void) onDowngrade:(FMDatabaseQueue*)database fromVersion:(NSInteger)oldVersion toVersion:(NSInteger)newVersion
271
+ {
272
+ // upgrade policy has to be implemented in subclass
273
+ }
274
+
275
+
276
+ @end
@@ -0,0 +1,41 @@
1
+ //
2
+ // MAURSensorFusionDetector.h
3
+ // BackgroundGeolocation
4
+ //
5
+ // v4.2 Phase 8 — Real sensor fusion detector for iOS.
6
+ // Uses CMMotionManager to sample userAcceleration (gravity removed) and rotationRate.
7
+ // Refines possibleCrash via accelerometer impact and detects phoneUsageWhileDriving.
8
+ //
9
+
10
+ #ifndef MAURSensorFusionDetector_h
11
+ #define MAURSensorFusionDetector_h
12
+
13
+ #import <Foundation/Foundation.h>
14
+
15
+ @class MAURLocation;
16
+
17
+ @protocol MAURSensorFusionListener <NSObject>
18
+ - (void)onSensorCrashWithImpactG:(double)impactG location:(MAURLocation *)location;
19
+ - (void)onPhoneUsageWhileDriving:(MAURLocation *)location;
20
+ @end
21
+
22
+ @interface MAURSensorFusionDetector : NSObject
23
+
24
+ @property (nonatomic, weak) id<MAURSensorFusionListener> listener;
25
+ @property (nonatomic, assign) BOOL enabled;
26
+ @property (nonatomic, assign) double crashImpactG; // default 3.0
27
+ @property (nonatomic, assign) NSTimeInterval crashCooldownMs; // default 10000
28
+ @property (nonatomic, assign) NSTimeInterval phoneUsageWindowMs; // default 4000
29
+ @property (nonatomic, assign) NSTimeInterval phoneUsageCooldownMs; // default 60000
30
+
31
+ @property (nonatomic, assign) BOOL tripActive;
32
+ @property (nonatomic, strong) MAURLocation *lastLocation;
33
+
34
+ - (instancetype)init;
35
+ - (BOOL)isAvailable;
36
+ - (void)start;
37
+ - (void)stop;
38
+
39
+ @end
40
+
41
+ #endif /* MAURSensorFusionDetector_h */
@@ -0,0 +1,137 @@
1
+ //
2
+ // MAURSensorFusionDetector.m
3
+ // BackgroundGeolocation
4
+ //
5
+ // v4.2 Phase 8 — sensor fusion detector implementation.
6
+ //
7
+
8
+ #import "MAURSensorFusionDetector.h"
9
+ #import <CoreMotion/CoreMotion.h>
10
+ #import <UIKit/UIKit.h>
11
+
12
+ static const double kJitterGyroRadS = 0.7; // ~40 deg/s
13
+ static const double kJitterAccelMps2 = 0.5;
14
+
15
+ @interface MAURSensorFusionDetector ()
16
+ @property (nonatomic, strong) CMMotionManager *motion;
17
+ @property (nonatomic, strong) NSOperationQueue *queue;
18
+ @property (nonatomic, assign) BOOL started;
19
+ @property (nonatomic, assign) NSTimeInterval lastCrashAt;
20
+ @property (nonatomic, assign) NSTimeInterval lastPhoneUsageAt;
21
+ @property (nonatomic, assign) NSTimeInterval jitterAboveSince;
22
+ @end
23
+
24
+ @implementation MAURSensorFusionDetector
25
+
26
+ - (instancetype)init {
27
+ if ((self = [super init])) {
28
+ _motion = [[CMMotionManager alloc] init];
29
+ _motion.deviceMotionUpdateInterval = 1.0 / 50.0; // 50 Hz
30
+ _queue = [[NSOperationQueue alloc] init];
31
+ _queue.name = @"MAURSensorFusionQueue";
32
+ _queue.maxConcurrentOperationCount = 1;
33
+ _enabled = NO;
34
+ _crashImpactG = 3.0;
35
+ _crashCooldownMs = 10000;
36
+ _phoneUsageWindowMs = 4000;
37
+ _phoneUsageCooldownMs = 60000;
38
+ _started = NO;
39
+ _lastCrashAt = 0;
40
+ _lastPhoneUsageAt = 0;
41
+ _jitterAboveSince = 0;
42
+ }
43
+ return self;
44
+ }
45
+
46
+ - (BOOL)isAvailable {
47
+ return self.motion.isDeviceMotionAvailable;
48
+ }
49
+
50
+ - (void)start {
51
+ @synchronized (self) {
52
+ if (self.started || !self.enabled) return;
53
+ if (![self.motion isDeviceMotionAvailable]) return;
54
+ __weak typeof(self) weakSelf = self;
55
+ [self.motion startDeviceMotionUpdatesToQueue:self.queue
56
+ withHandler:^(CMDeviceMotion * _Nullable motion, NSError * _Nullable error) {
57
+ if (!motion || error) return;
58
+ [weakSelf processMotion:motion];
59
+ }];
60
+ self.started = YES;
61
+ }
62
+ }
63
+
64
+ - (void)stop {
65
+ @synchronized (self) {
66
+ if (!self.started) return;
67
+ [self.motion stopDeviceMotionUpdates];
68
+ self.started = NO;
69
+ self.jitterAboveSince = 0;
70
+ }
71
+ }
72
+
73
+ - (void)processMotion:(CMDeviceMotion *)motion {
74
+ if (!self.enabled) return;
75
+ NSTimeInterval nowMs = [[NSDate date] timeIntervalSince1970] * 1000.0;
76
+
77
+ // userAcceleration is in g (gravity removed); convert magnitude to g and to m/s².
78
+ double ax = motion.userAcceleration.x;
79
+ double ay = motion.userAcceleration.y;
80
+ double az = motion.userAcceleration.z;
81
+ double accelMagG = sqrt(ax*ax + ay*ay + az*az); // g
82
+ double accelMagMs = accelMagG * 9.80665; // m/s²
83
+
84
+ double gx = motion.rotationRate.x;
85
+ double gy = motion.rotationRate.y;
86
+ double gz = motion.rotationRate.z;
87
+ double gyroMag = sqrt(gx*gx + gy*gy + gz*gz); // rad/s
88
+
89
+ BOOL tripActiveNow = self.tripActive;
90
+ MAURLocation *loc = self.lastLocation;
91
+ id<MAURSensorFusionListener> l = self.listener;
92
+
93
+ // Crash detection
94
+ if (tripActiveNow && self.crashImpactG > 0 && accelMagG >= self.crashImpactG
95
+ && (nowMs - self.lastCrashAt) >= self.crashCooldownMs) {
96
+ self.lastCrashAt = nowMs;
97
+ if ([l respondsToSelector:@selector(onSensorCrashWithImpactG:location:)]) {
98
+ [l onSensorCrashWithImpactG:accelMagG location:loc];
99
+ }
100
+ }
101
+
102
+ // phoneUsageWhileDriving
103
+ if (!tripActiveNow) { self.jitterAboveSince = 0; return; }
104
+ BOOL screenOn = [self isScreenOnApprox];
105
+ if (!screenOn) { self.jitterAboveSince = 0; return; }
106
+
107
+ BOOL above = (accelMagMs >= kJitterAccelMps2) || (gyroMag >= kJitterGyroRadS);
108
+ if (above) {
109
+ if (self.jitterAboveSince == 0) self.jitterAboveSince = nowMs;
110
+ if ((nowMs - self.jitterAboveSince) >= self.phoneUsageWindowMs
111
+ && (nowMs - self.lastPhoneUsageAt) >= self.phoneUsageCooldownMs) {
112
+ self.lastPhoneUsageAt = nowMs;
113
+ self.jitterAboveSince = 0;
114
+ if ([l respondsToSelector:@selector(onPhoneUsageWhileDriving:)]) {
115
+ [l onPhoneUsageWhileDriving:loc];
116
+ }
117
+ }
118
+ } else {
119
+ self.jitterAboveSince = 0;
120
+ }
121
+ }
122
+
123
+ - (BOOL)isScreenOnApprox {
124
+ // Heuristic: app is foreground active => screen is on. Background sampling does
125
+ // not constitute phone usage while driving (passenger may have screen off too).
126
+ __block UIApplicationState state = UIApplicationStateBackground;
127
+ if ([NSThread isMainThread]) {
128
+ state = [UIApplication sharedApplication].applicationState;
129
+ } else {
130
+ dispatch_sync(dispatch_get_main_queue(), ^{
131
+ state = [UIApplication sharedApplication].applicationState;
132
+ });
133
+ }
134
+ return state == UIApplicationStateActive;
135
+ }
136
+
137
+ @end
@@ -0,0 +1,29 @@
1
+ //
2
+ // MAURSessionLocationContract.h
3
+ // BackgroundGeolocation
4
+ //
5
+ // Session table for current recording route. Independent of sync; cleared on startSession/clearSession.
6
+ //
7
+
8
+ #ifndef MAURSessionLocationContract_h
9
+ #define MAURSessionLocationContract_h
10
+
11
+ #define LSC_TABLE_NAME "location_session"
12
+ #define LSC_COLUMN_NAME_ID "id"
13
+ #define LSC_COLUMN_NAME_TIME "time"
14
+ #define LSC_COLUMN_NAME_ACCURACY "accuracy"
15
+ #define LSC_COLUMN_NAME_SPEED "speed"
16
+ #define LSC_COLUMN_NAME_BEARING "bearing"
17
+ #define LSC_COLUMN_NAME_ALTITUDE "altitude"
18
+ #define LSC_COLUMN_NAME_LATITUDE "latitude"
19
+ #define LSC_COLUMN_NAME_LONGITUDE "longitude"
20
+ #define LSC_COLUMN_NAME_PROVIDER "provider"
21
+ #define LSC_COLUMN_NAME_LOCATION_PROVIDER "service_provider"
22
+ #define LSC_COLUMN_NAME_STATUS "valid"
23
+ #define LSC_COLUMN_NAME_RECORDED_AT "recorded_at"
24
+
25
+ @interface MAURSessionLocationContract : NSObject
26
+ + (NSString*) createTableSQL;
27
+ @end
28
+
29
+ #endif /* MAURSessionLocationContract_h */
@@ -0,0 +1,31 @@
1
+ //
2
+ // MAURSessionLocationContract.m
3
+ // BackgroundGeolocation
4
+ //
5
+
6
+ #import <Foundation/Foundation.h>
7
+ #import "MAURSQLiteHelper.h"
8
+ #import "MAURSessionLocationContract.h"
9
+
10
+ @implementation MAURSessionLocationContract
11
+
12
+ + (NSString*) createTableSQL
13
+ {
14
+ NSArray *columns = @[
15
+ @{ @"name": @LSC_COLUMN_NAME_ID, @"type": [SQLPrimaryKeyAutoIncColumnType sqlColumnWithType: kInteger]},
16
+ @{ @"name": @LSC_COLUMN_NAME_TIME, @"type": [SQLColumnType sqlColumnWithType: kReal]},
17
+ @{ @"name": @LSC_COLUMN_NAME_ACCURACY, @"type": [SQLColumnType sqlColumnWithType: kReal]},
18
+ @{ @"name": @LSC_COLUMN_NAME_SPEED, @"type": [SQLColumnType sqlColumnWithType: kReal]},
19
+ @{ @"name": @LSC_COLUMN_NAME_BEARING, @"type": [SQLColumnType sqlColumnWithType: kReal]},
20
+ @{ @"name": @LSC_COLUMN_NAME_ALTITUDE, @"type": [SQLColumnType sqlColumnWithType: kReal]},
21
+ @{ @"name": @LSC_COLUMN_NAME_LATITUDE, @"type": [SQLColumnType sqlColumnWithType: kReal]},
22
+ @{ @"name": @LSC_COLUMN_NAME_LONGITUDE, @"type": [SQLColumnType sqlColumnWithType: kReal]},
23
+ @{ @"name": @LSC_COLUMN_NAME_PROVIDER, @"type": [SQLColumnType sqlColumnWithType: kText]},
24
+ @{ @"name": @LSC_COLUMN_NAME_LOCATION_PROVIDER, @"type": [SQLColumnType sqlColumnWithType: kText]},
25
+ @{ @"name": @LSC_COLUMN_NAME_STATUS, @"type": [SQLColumnType sqlColumnWithType: kInteger]},
26
+ @{ @"name": @LSC_COLUMN_NAME_RECORDED_AT, @"type": [SQLColumnType sqlColumnWithType: kInteger]}
27
+ ];
28
+ return [MAURSQLiteHelper createTableSqlStatement:@LSC_TABLE_NAME columns:columns];
29
+ }
30
+
31
+ @end
@@ -0,0 +1,25 @@
1
+ //
2
+ // MAURSessionLocationDAO.h
3
+ // BackgroundGeolocation
4
+ //
5
+ // Session storage for current route. Cleared on startSession/clearSession; not cleared by sync.
6
+ //
7
+
8
+ #ifndef MAURSessionLocationDAO_h
9
+ #define MAURSessionLocationDAO_h
10
+
11
+ #import <Foundation/Foundation.h>
12
+ #import "MAURLocation.h"
13
+
14
+ @interface MAURSessionLocationDAO : NSObject
15
+ + (instancetype) sharedInstance;
16
+ - (id) init NS_UNAVAILABLE;
17
+ - (void) startSession;
18
+ - (void) clearSession;
19
+ - (BOOL) isSessionActive;
20
+ - (void) persistSessionLocation:(MAURLocation*)location;
21
+ - (NSArray<MAURLocation*>*) getSessionLocations;
22
+ - (NSInteger) getSessionLocationsCount;
23
+ @end
24
+
25
+ #endif /* MAURSessionLocationDAO_h */
@@ -0,0 +1,153 @@
1
+ //
2
+ // MAURSessionLocationDAO.m
3
+ // BackgroundGeolocation
4
+ //
5
+
6
+ #import <Foundation/Foundation.h>
7
+ #import "MAURGeolocationOpenHelper.h"
8
+ #import "MAURSessionLocationContract.h"
9
+ #import "MAURSessionLocationDAO.h"
10
+ #import "MAURLocation.h"
11
+ #import "FMDB.h"
12
+
13
+ static NSString *const kSessionActiveKey = @"bgloc_session_active";
14
+
15
+ @interface MAURSessionLocationDAO ()
16
+ - (instancetype)initPrivate;
17
+ @end
18
+
19
+ @implementation MAURSessionLocationDAO {
20
+ FMDatabaseQueue* queue;
21
+ MAURGeolocationOpenHelper *helper;
22
+ }
23
+
24
+ + (instancetype) sharedInstance
25
+ {
26
+ static MAURSessionLocationDAO *instance = nil;
27
+ static dispatch_once_t onceToken;
28
+ dispatch_once(&onceToken, ^{
29
+ instance = [[self alloc] initPrivate];
30
+ });
31
+ return instance;
32
+ }
33
+
34
+ - (instancetype) initPrivate
35
+ {
36
+ if (self = [super init]) {
37
+ helper = [[MAURGeolocationOpenHelper alloc] init];
38
+ queue = [helper getWritableDatabase];
39
+ }
40
+ return self;
41
+ }
42
+
43
+ - (void) startSession
44
+ {
45
+ [queue inDatabase:^(FMDatabase *database) {
46
+ NSString *sql = [NSString stringWithFormat:@"DELETE FROM %@", @LSC_TABLE_NAME];
47
+ [database executeUpdate:sql];
48
+ }];
49
+ [[NSUserDefaults standardUserDefaults] setBool:YES forKey:kSessionActiveKey];
50
+ [[NSUserDefaults standardUserDefaults] synchronize];
51
+ }
52
+
53
+ - (void) clearSession
54
+ {
55
+ [queue inDatabase:^(FMDatabase *database) {
56
+ NSString *sql = [NSString stringWithFormat:@"DELETE FROM %@", @LSC_TABLE_NAME];
57
+ [database executeUpdate:sql];
58
+ }];
59
+ [[NSUserDefaults standardUserDefaults] setBool:NO forKey:kSessionActiveKey];
60
+ [[NSUserDefaults standardUserDefaults] synchronize];
61
+ }
62
+
63
+ - (BOOL) isSessionActive
64
+ {
65
+ return [[NSUserDefaults standardUserDefaults] boolForKey:kSessionActiveKey];
66
+ }
67
+
68
+ - (void) persistSessionLocation:(MAURLocation*)location
69
+ {
70
+ if (![self isSessionActive]) return;
71
+ if (!location || !location.time) return;
72
+ NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970];
73
+ NSNumber *recordedAt = [NSNumber numberWithDouble:timestamp];
74
+
75
+ NSString *sql = @"INSERT INTO " @LSC_TABLE_NAME @" ("
76
+ @LSC_COLUMN_NAME_TIME @"," @LSC_COLUMN_NAME_ACCURACY @"," @LSC_COLUMN_NAME_SPEED @","
77
+ @LSC_COLUMN_NAME_BEARING @"," @LSC_COLUMN_NAME_ALTITUDE @"," @LSC_COLUMN_NAME_LATITUDE @","
78
+ @LSC_COLUMN_NAME_LONGITUDE @"," @LSC_COLUMN_NAME_PROVIDER @"," @LSC_COLUMN_NAME_LOCATION_PROVIDER @","
79
+ @LSC_COLUMN_NAME_STATUS @"," @LSC_COLUMN_NAME_RECORDED_AT
80
+ @") VALUES (?,?,?,?,?,?,?,?,?,?,?)";
81
+
82
+ [queue inDatabase:^(FMDatabase *database) {
83
+ [database executeUpdate:sql,
84
+ [NSNumber numberWithDouble:[location.time timeIntervalSince1970]],
85
+ location.accuracy ?: @0,
86
+ location.speed ?: @0,
87
+ location.heading ?: @0,
88
+ location.altitude ?: @0,
89
+ location.latitude ?: @0,
90
+ location.longitude ?: @0,
91
+ location.provider ?: [NSNull null],
92
+ location.locationProvider ? [NSString stringWithFormat:@"%@", location.locationProvider] : [NSNull null],
93
+ @(1),
94
+ recordedAt
95
+ ];
96
+ }];
97
+ }
98
+
99
+ - (NSArray<MAURLocation*>*) getSessionLocations
100
+ {
101
+ __block NSMutableArray* locations = [[NSMutableArray alloc] init];
102
+ NSString *sql = @"SELECT " @LSC_COLUMN_NAME_ID @"," @LSC_COLUMN_NAME_TIME @"," @LSC_COLUMN_NAME_ACCURACY @","
103
+ @LSC_COLUMN_NAME_SPEED @"," @LSC_COLUMN_NAME_BEARING @"," @LSC_COLUMN_NAME_ALTITUDE @","
104
+ @LSC_COLUMN_NAME_LATITUDE @"," @LSC_COLUMN_NAME_LONGITUDE @"," @LSC_COLUMN_NAME_PROVIDER @","
105
+ @LSC_COLUMN_NAME_LOCATION_PROVIDER @"," @LSC_COLUMN_NAME_STATUS @"," @LSC_COLUMN_NAME_RECORDED_AT
106
+ @" FROM " @LSC_TABLE_NAME @" ORDER BY " @LSC_COLUMN_NAME_RECORDED_AT;
107
+
108
+ [queue inDatabase:^(FMDatabase *database) {
109
+ FMResultSet *rs = [database executeQuery:sql];
110
+ while ([rs next]) {
111
+ MAURLocation *loc = [self convertToLocation:rs];
112
+ [locations addObject:loc];
113
+ }
114
+ [rs close];
115
+ }];
116
+ return locations;
117
+ }
118
+
119
+ - (NSInteger) getSessionLocationsCount
120
+ {
121
+ __block NSInteger count = 0;
122
+ NSString *sql = [NSString stringWithFormat:@"SELECT COUNT(*) FROM %@", @LSC_TABLE_NAME];
123
+ [queue inDatabase:^(FMDatabase *database) {
124
+ FMResultSet *rs = [database executeQuery:sql];
125
+ if ([rs next]) {
126
+ count = [rs intForColumnIndex:0];
127
+ }
128
+ [rs close];
129
+ }];
130
+ return count;
131
+ }
132
+
133
+ - (MAURLocation*) convertToLocation:(FMResultSet*)rs
134
+ {
135
+ MAURLocation *location = [[MAURLocation alloc] init];
136
+ location.locationId = [NSNumber numberWithLongLong:[rs longLongIntForColumnIndex:0]];
137
+ NSTimeInterval timestamp = [rs doubleForColumnIndex:1];
138
+ location.time = [NSDate dateWithTimeIntervalSince1970:timestamp];
139
+ location.accuracy = [NSNumber numberWithDouble:[rs doubleForColumnIndex:2]];
140
+ location.speed = [NSNumber numberWithDouble:[rs doubleForColumnIndex:3]];
141
+ location.heading = [NSNumber numberWithDouble:[rs doubleForColumnIndex:4]];
142
+ location.altitude = [NSNumber numberWithDouble:[rs doubleForColumnIndex:5]];
143
+ location.latitude = [NSNumber numberWithDouble:[rs doubleForColumnIndex:6]];
144
+ location.longitude = [NSNumber numberWithDouble:[rs doubleForColumnIndex:7]];
145
+ location.provider = [rs stringForColumnIndex:8];
146
+ location.locationProvider = [NSNumber numberWithInt:[rs intForColumnIndex:9]];
147
+ location.isValid = [rs intForColumnIndex:10] == 1 ? YES : NO;
148
+ NSTimeInterval recordedAt = [rs longForColumnIndex:11];
149
+ location.recordedAt = [NSDate dateWithTimeIntervalSince1970:recordedAt];
150
+ return location;
151
+ }
152
+
153
+ @end