react-native-nitro-geolocation 1.2.6 → 1.3.1

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 (223) hide show
  1. package/README.md +61 -272
  2. package/android/build.gradle +1 -0
  3. package/android/src/main/AndroidManifest.xml +39 -0
  4. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidFusedLocationProvider.kt +310 -0
  5. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidFusedRequestFactory.kt +31 -0
  6. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationConversions.kt +71 -0
  7. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationErrors.kt +85 -0
  8. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidGeolocationOptions.kt +92 -0
  9. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidLocationSettings.kt +3 -0
  10. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/AndroidProviderRoute.kt +74 -0
  11. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroBackgroundLocation.kt +132 -0
  12. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/NitroGeolocation.kt +219 -476
  13. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundHttpSync.kt +134 -0
  14. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundPermissions.kt +196 -0
  15. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/AndroidBackgroundSerialization.kt +266 -0
  16. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroActivityRecognitionReceiver.kt +13 -0
  17. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundEventHub.kt +65 -0
  18. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundHeadlessTaskService.kt +58 -0
  19. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundLocationController.kt +711 -0
  20. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundLocationService.kt +48 -0
  21. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundNotificationFactory.kt +37 -0
  22. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBackgroundStore.kt +655 -0
  23. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroBootReceiver.kt +26 -0
  24. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroGeofenceReceiver.kt +14 -0
  25. package/android/src/main/java/com/margelo/nitro/nitrogeolocation/background/NitroLocationUpdateReceiver.kt +37 -0
  26. package/android/src/test/java/com/margelo/nitro/nitrogeolocation/AndroidFusedLocationProviderTest.kt +64 -0
  27. package/android/src/test/java/com/margelo/nitro/nitrogeolocation/AndroidProviderRouteTest.kt +116 -0
  28. package/ios/IOSBackgroundHttpSync.swift +126 -0
  29. package/ios/IOSBackgroundLocationDelegate.swift +36 -0
  30. package/ios/IOSBackgroundMotion.swift +55 -0
  31. package/ios/IOSBackgroundSerialization.swift +539 -0
  32. package/ios/IOSGeolocationConversions.swift +131 -0
  33. package/ios/IOSGeolocationDelegate.swift +31 -0
  34. package/ios/IOSGeolocationErrors.swift +39 -0
  35. package/ios/IOSGeolocationOptions.swift +135 -0
  36. package/ios/NitroBackgroundLocation.swift +849 -0
  37. package/ios/NitroGeolocation.swift +14 -347
  38. package/nitrogen/generated/android/c++/JActivityRecognitionOptions.hpp +69 -0
  39. package/nitrogen/generated/android/c++/JAndroidBackgroundLocationOptions.hpp +74 -0
  40. package/nitrogen/generated/android/c++/JAndroidBackgroundLocationStatus.hpp +67 -0
  41. package/nitrogen/generated/android/c++/JAndroidBackgroundProvider.hpp +61 -0
  42. package/nitrogen/generated/android/c++/JAndroidForegroundServiceOptions.hpp +90 -0
  43. package/nitrogen/generated/android/c++/JBackgroundEventEnvelope.hpp +129 -0
  44. package/nitrogen/generated/android/c++/JBackgroundEventType.hpp +70 -0
  45. package/nitrogen/generated/android/c++/JBackgroundHttpMethod.hpp +61 -0
  46. package/nitrogen/generated/android/c++/JBackgroundHttpSyncOptions.hpp +131 -0
  47. package/nitrogen/generated/android/c++/JBackgroundHttpSyncResult.hpp +111 -0
  48. package/nitrogen/generated/android/c++/JBackgroundLocation.hpp +110 -0
  49. package/nitrogen/generated/android/c++/JBackgroundLocationOptions.hpp +162 -0
  50. package/nitrogen/generated/android/c++/JBackgroundLocationSource.hpp +73 -0
  51. package/nitrogen/generated/android/c++/JBackgroundLocationState.hpp +70 -0
  52. package/nitrogen/generated/android/c++/JBackgroundLocationStatus.hpp +126 -0
  53. package/nitrogen/generated/android/c++/JBackgroundPermissionResult.hpp +79 -0
  54. package/nitrogen/generated/android/c++/JBackgroundPermissionStatus.hpp +64 -0
  55. package/nitrogen/generated/android/c++/JBackgroundTrackingMode.hpp +61 -0
  56. package/nitrogen/generated/android/c++/JBatterySnapshot.hpp +61 -0
  57. package/nitrogen/generated/android/c++/JDetectedActivity.hpp +66 -0
  58. package/nitrogen/generated/android/c++/JDetectedActivityType.hpp +76 -0
  59. package/nitrogen/generated/android/c++/JFunc_void_BackgroundEventEnvelope.hpp +114 -0
  60. package/nitrogen/generated/android/c++/JFunc_void_BackgroundLocation.hpp +95 -0
  61. package/nitrogen/generated/android/c++/JGeofenceEvent.hpp +94 -0
  62. package/nitrogen/generated/android/c++/JGeofenceRegion.hpp +112 -0
  63. package/nitrogen/generated/android/c++/JGeofenceTransition.hpp +61 -0
  64. package/nitrogen/generated/android/c++/JGeofencingOptions.hpp +82 -0
  65. package/nitrogen/generated/android/c++/JGetStoredBackgroundEventsOptions.hpp +90 -0
  66. package/nitrogen/generated/android/c++/JGetStoredBackgroundLocationsOptions.hpp +69 -0
  67. package/nitrogen/generated/android/c++/JHybridNitroBackgroundLocationSpec.cpp +662 -0
  68. package/nitrogen/generated/android/c++/JHybridNitroBackgroundLocationSpec.hpp +89 -0
  69. package/nitrogen/generated/android/c++/JIOSBackgroundActivityType.hpp +67 -0
  70. package/nitrogen/generated/android/c++/JIOSBackgroundLocationOptions.hpp +79 -0
  71. package/nitrogen/generated/android/c++/JIOSBackgroundLocationStatus.hpp +61 -0
  72. package/nitrogen/generated/android/c++/JLocationProviderStatus.hpp +5 -1
  73. package/nitrogen/generated/android/c++/JStoredBackgroundEventEnvelope.hpp +115 -0
  74. package/nitrogen/generated/android/c++/JStoredBackgroundLocation.hpp +122 -0
  75. package/nitrogen/generated/android/c++/JVariant_NullType_Boolean_String_Double.cpp +34 -0
  76. package/nitrogen/generated/android/c++/JVariant_NullType_Boolean_String_Double.hpp +100 -0
  77. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/ActivityRecognitionOptions.kt +66 -0
  78. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundLocationOptions.kt +66 -0
  79. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundLocationStatus.kt +61 -0
  80. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidBackgroundProvider.kt +24 -0
  81. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/AndroidForegroundServiceOptions.kt +91 -0
  82. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundEventEnvelope.kt +96 -0
  83. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundEventType.kt +27 -0
  84. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpMethod.kt +24 -0
  85. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpSyncOptions.kt +101 -0
  86. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundHttpSyncResult.kt +71 -0
  87. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocation.kt +96 -0
  88. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationOptions.kt +136 -0
  89. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationSource.kt +28 -0
  90. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationState.kt +27 -0
  91. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundLocationStatus.kt +116 -0
  92. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundPermissionResult.kt +71 -0
  93. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundPermissionStatus.kt +25 -0
  94. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BackgroundTrackingMode.kt +24 -0
  95. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/BatterySnapshot.kt +56 -0
  96. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/DetectedActivity.kt +61 -0
  97. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/DetectedActivityType.kt +29 -0
  98. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_BackgroundEventEnvelope.kt +80 -0
  99. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Func_void_BackgroundLocation.kt +80 -0
  100. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceEvent.kt +66 -0
  101. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceRegion.kt +96 -0
  102. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofenceTransition.kt +24 -0
  103. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GeofencingOptions.kt +56 -0
  104. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GetStoredBackgroundEventsOptions.kt +66 -0
  105. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/GetStoredBackgroundLocationsOptions.kt +66 -0
  106. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/HybridNitroBackgroundLocationSpec.kt +174 -0
  107. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundActivityType.kt +26 -0
  108. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundLocationOptions.kt +76 -0
  109. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/IOSBackgroundLocationStatus.kt +56 -0
  110. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/LocationProviderStatus.kt +7 -2
  111. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/StoredBackgroundEventEnvelope.kt +76 -0
  112. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/StoredBackgroundLocation.kt +111 -0
  113. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrogeolocation/Variant_NullType_Boolean_String_Double.kt +88 -0
  114. package/nitrogen/generated/android/nitrogeolocation+autolinking.cmake +3 -0
  115. package/nitrogen/generated/android/nitrogeolocationOnLoad.cpp +20 -0
  116. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.cpp +104 -15
  117. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Bridge.hpp +1107 -50
  118. package/nitrogen/generated/ios/NitroGeolocation-Swift-Cxx-Umbrella.hpp +102 -0
  119. package/nitrogen/generated/ios/NitroGeolocationAutolinking.mm +8 -0
  120. package/nitrogen/generated/ios/NitroGeolocationAutolinking.swift +15 -3
  121. package/nitrogen/generated/ios/c++/HybridNitroBackgroundLocationSpecSwift.cpp +11 -0
  122. package/nitrogen/generated/ios/c++/HybridNitroBackgroundLocationSpecSwift.hpp +416 -0
  123. package/nitrogen/generated/ios/swift/ActivityRecognitionOptions.swift +96 -0
  124. package/nitrogen/generated/ios/swift/AndroidBackgroundLocationOptions.swift +76 -0
  125. package/nitrogen/generated/ios/swift/AndroidBackgroundLocationStatus.swift +58 -0
  126. package/nitrogen/generated/ios/swift/AndroidBackgroundProvider.swift +44 -0
  127. package/nitrogen/generated/ios/swift/AndroidForegroundServiceOptions.swift +160 -0
  128. package/nitrogen/generated/ios/swift/BackgroundEventEnvelope.swift +110 -0
  129. package/nitrogen/generated/ios/swift/BackgroundEventType.swift +56 -0
  130. package/nitrogen/generated/ios/swift/BackgroundHttpMethod.swift +44 -0
  131. package/nitrogen/generated/ios/swift/BackgroundHttpSyncOptions.swift +259 -0
  132. package/nitrogen/generated/ios/swift/BackgroundHttpSyncResult.swift +87 -0
  133. package/nitrogen/generated/ios/swift/BackgroundLocation.swift +118 -0
  134. package/nitrogen/generated/ios/swift/BackgroundLocationOptions.swift +292 -0
  135. package/nitrogen/generated/ios/swift/BackgroundLocationSource.swift +60 -0
  136. package/nitrogen/generated/ios/swift/BackgroundLocationState.swift +56 -0
  137. package/nitrogen/generated/ios/swift/BackgroundLocationStatus.swift +124 -0
  138. package/nitrogen/generated/ios/swift/BackgroundPermissionResult.swift +81 -0
  139. package/nitrogen/generated/ios/swift/BackgroundPermissionStatus.swift +48 -0
  140. package/nitrogen/generated/ios/swift/BackgroundTrackingMode.swift +44 -0
  141. package/nitrogen/generated/ios/swift/BatterySnapshot.swift +60 -0
  142. package/nitrogen/generated/ios/swift/DetectedActivity.swift +39 -0
  143. package/nitrogen/generated/ios/swift/DetectedActivityType.swift +64 -0
  144. package/nitrogen/generated/ios/swift/Func_void_BackgroundEventEnvelope.swift +46 -0
  145. package/nitrogen/generated/ios/swift/Func_void_BackgroundHttpSyncResult.swift +46 -0
  146. package/nitrogen/generated/ios/swift/Func_void_BackgroundLocation.swift +46 -0
  147. package/nitrogen/generated/ios/swift/Func_void_BackgroundLocationStatus.swift +46 -0
  148. package/nitrogen/generated/ios/swift/Func_void_BackgroundPermissionResult.swift +46 -0
  149. package/nitrogen/generated/ios/swift/Func_void_std__optional_BackgroundLocationOptions_.swift +46 -0
  150. package/nitrogen/generated/ios/swift/Func_void_std__vector_GeofenceRegion_.swift +46 -0
  151. package/nitrogen/generated/ios/swift/Func_void_std__vector_StoredBackgroundEventEnvelope_.swift +46 -0
  152. package/nitrogen/generated/ios/swift/Func_void_std__vector_StoredBackgroundLocation_.swift +46 -0
  153. package/nitrogen/generated/ios/swift/GeofenceEvent.swift +50 -0
  154. package/nitrogen/generated/ios/swift/GeofenceRegion.swift +195 -0
  155. package/nitrogen/generated/ios/swift/GeofenceTransition.swift +44 -0
  156. package/nitrogen/generated/ios/swift/GeofencingOptions.swift +66 -0
  157. package/nitrogen/generated/ios/swift/GetStoredBackgroundEventsOptions.swift +102 -0
  158. package/nitrogen/generated/ios/swift/GetStoredBackgroundLocationsOptions.swift +96 -0
  159. package/nitrogen/generated/ios/swift/HybridNitroBackgroundLocationSpec.swift +81 -0
  160. package/nitrogen/generated/ios/swift/HybridNitroBackgroundLocationSpec_cxx.swift +654 -0
  161. package/nitrogen/generated/ios/swift/IOSBackgroundActivityType.swift +52 -0
  162. package/nitrogen/generated/ios/swift/IOSBackgroundLocationOptions.swift +125 -0
  163. package/nitrogen/generated/ios/swift/IOSBackgroundLocationStatus.swift +34 -0
  164. package/nitrogen/generated/ios/swift/LocationProviderStatus.swift +19 -1
  165. package/nitrogen/generated/ios/swift/StoredBackgroundEventEnvelope.swift +54 -0
  166. package/nitrogen/generated/ios/swift/StoredBackgroundLocation.swift +120 -0
  167. package/nitrogen/generated/ios/swift/Variant_NullType_Bool_String_Double.swift +34 -0
  168. package/nitrogen/generated/shared/c++/ActivityRecognitionOptions.hpp +95 -0
  169. package/nitrogen/generated/shared/c++/AndroidBackgroundLocationOptions.hpp +100 -0
  170. package/nitrogen/generated/shared/c++/AndroidBackgroundLocationStatus.hpp +93 -0
  171. package/nitrogen/generated/shared/c++/AndroidBackgroundProvider.hpp +80 -0
  172. package/nitrogen/generated/shared/c++/AndroidForegroundServiceOptions.hpp +116 -0
  173. package/nitrogen/generated/shared/c++/BackgroundEventEnvelope.hpp +140 -0
  174. package/nitrogen/generated/shared/c++/BackgroundEventType.hpp +92 -0
  175. package/nitrogen/generated/shared/c++/BackgroundHttpMethod.hpp +80 -0
  176. package/nitrogen/generated/shared/c++/BackgroundHttpSyncOptions.hpp +129 -0
  177. package/nitrogen/generated/shared/c++/BackgroundHttpSyncResult.hpp +101 -0
  178. package/nitrogen/generated/shared/c++/BackgroundLocation.hpp +134 -0
  179. package/nitrogen/generated/shared/c++/BackgroundLocationOptions.hpp +174 -0
  180. package/nitrogen/generated/shared/c++/BackgroundLocationSource.hpp +96 -0
  181. package/nitrogen/generated/shared/c++/BackgroundLocationState.hpp +92 -0
  182. package/nitrogen/generated/shared/c++/BackgroundLocationStatus.hpp +158 -0
  183. package/nitrogen/generated/shared/c++/BackgroundPermissionResult.hpp +107 -0
  184. package/nitrogen/generated/shared/c++/BackgroundPermissionStatus.hpp +84 -0
  185. package/nitrogen/generated/shared/c++/BackgroundTrackingMode.hpp +80 -0
  186. package/nitrogen/generated/shared/c++/BatterySnapshot.hpp +87 -0
  187. package/nitrogen/generated/shared/c++/DetectedActivity.hpp +92 -0
  188. package/nitrogen/generated/shared/c++/DetectedActivityType.hpp +100 -0
  189. package/nitrogen/generated/shared/c++/GeofenceEvent.hpp +103 -0
  190. package/nitrogen/generated/shared/c++/GeofenceRegion.hpp +123 -0
  191. package/nitrogen/generated/shared/c++/GeofenceTransition.hpp +80 -0
  192. package/nitrogen/generated/shared/c++/GeofencingOptions.hpp +90 -0
  193. package/nitrogen/generated/shared/c++/GetStoredBackgroundEventsOptions.hpp +98 -0
  194. package/nitrogen/generated/shared/c++/GetStoredBackgroundLocationsOptions.hpp +95 -0
  195. package/nitrogen/generated/shared/c++/HybridNitroBackgroundLocationSpec.cpp +47 -0
  196. package/nitrogen/generated/shared/c++/HybridNitroBackgroundLocationSpec.hpp +133 -0
  197. package/nitrogen/generated/shared/c++/IOSBackgroundActivityType.hpp +88 -0
  198. package/nitrogen/generated/shared/c++/IOSBackgroundLocationOptions.hpp +105 -0
  199. package/nitrogen/generated/shared/c++/IOSBackgroundLocationStatus.hpp +87 -0
  200. package/nitrogen/generated/shared/c++/LocationProviderStatus.hpp +5 -1
  201. package/nitrogen/generated/shared/c++/StoredBackgroundEventEnvelope.hpp +108 -0
  202. package/nitrogen/generated/shared/c++/StoredBackgroundLocation.hpp +146 -0
  203. package/package.json +17 -6
  204. package/src/NitroGeolocation.nitro.ts +4 -4
  205. package/src/api/getCurrentPosition.ts +1 -1
  206. package/src/api/requestLocationSettings.ts +3 -2
  207. package/src/background/NitroBackgroundLocation.nitro.ts +83 -0
  208. package/src/background/index.ts +200 -0
  209. package/src/background/index.web.ts +120 -0
  210. package/src/background/task.ts +13 -0
  211. package/src/background/types.ts +328 -0
  212. package/src/compat/index.web.ts +141 -0
  213. package/src/index.tsx +3 -0
  214. package/src/index.web.tsx +41 -0
  215. package/src/publicTypes.ts +6 -5
  216. package/src/types.ts +3 -0
  217. package/src/web/browser.ts +171 -0
  218. package/src/web/index.ts +167 -0
  219. package/src/web/useWatchPosition.ts +76 -0
  220. package/src/web/watch.ts +81 -0
  221. package/src/devtools/index.test.ts +0 -54
  222. package/src/utils/errors.test.ts +0 -65
  223. package/src/utils/provider.test.ts +0 -303
@@ -0,0 +1,655 @@
1
+ package com.margelo.nitro.nitrogeolocation.background
2
+
3
+ import android.content.ContentValues
4
+ import android.content.Context
5
+ import android.database.sqlite.SQLiteDatabase
6
+ import android.database.sqlite.SQLiteOpenHelper
7
+ import com.margelo.nitro.nitrogeolocation.BackgroundEventEnvelope
8
+ import com.margelo.nitro.nitrogeolocation.BackgroundEventType
9
+ import com.margelo.nitro.nitrogeolocation.BackgroundHttpSyncResult
10
+ import com.margelo.nitro.nitrogeolocation.BackgroundLocation
11
+ import com.margelo.nitro.nitrogeolocation.BackgroundLocationSource
12
+ import com.margelo.nitro.nitrogeolocation.DetectedActivity
13
+ import com.margelo.nitro.nitrogeolocation.DetectedActivityType
14
+ import com.margelo.nitro.nitrogeolocation.GeofenceEvent
15
+ import com.margelo.nitro.nitrogeolocation.GeofenceRegion
16
+ import com.margelo.nitro.nitrogeolocation.GeofenceTransition
17
+ import com.margelo.nitro.nitrogeolocation.GeolocationCoordinates
18
+ import com.margelo.nitro.nitrogeolocation.GetStoredBackgroundEventsOptions
19
+ import com.margelo.nitro.nitrogeolocation.GetStoredBackgroundLocationsOptions
20
+ import com.margelo.nitro.nitrogeolocation.LocationProviderUsed
21
+ import com.margelo.nitro.nitrogeolocation.NullableDouble
22
+ import com.margelo.nitro.nitrogeolocation.StoredBackgroundEventEnvelope
23
+ import com.margelo.nitro.nitrogeolocation.StoredBackgroundLocation
24
+ import com.margelo.nitro.nitrogeolocation.Variant_NullType_Boolean_String_Double
25
+ import com.margelo.nitro.core.NullType
26
+ import org.json.JSONArray
27
+ import org.json.JSONObject
28
+
29
+ class NitroBackgroundStore(context: Context) :
30
+ SQLiteOpenHelper(context, "nitro_background_location.db", null, 3) {
31
+
32
+ override fun onCreate(db: SQLiteDatabase) {
33
+ db.execSQL(
34
+ """
35
+ CREATE TABLE IF NOT EXISTS background_locations (
36
+ id TEXT PRIMARY KEY,
37
+ latitude REAL NOT NULL,
38
+ longitude REAL NOT NULL,
39
+ altitude REAL,
40
+ accuracy REAL NOT NULL,
41
+ altitude_accuracy REAL,
42
+ heading REAL,
43
+ speed REAL,
44
+ timestamp REAL NOT NULL,
45
+ provider TEXT,
46
+ mocked INTEGER,
47
+ source TEXT NOT NULL,
48
+ recorded_at REAL NOT NULL,
49
+ delivered_to_js INTEGER NOT NULL DEFAULT 0,
50
+ synced INTEGER NOT NULL DEFAULT 0,
51
+ created_at REAL NOT NULL
52
+ )
53
+ """.trimIndent()
54
+ )
55
+ db.execSQL(
56
+ """
57
+ CREATE TABLE IF NOT EXISTS background_events (
58
+ id TEXT PRIMARY KEY,
59
+ type TEXT NOT NULL,
60
+ location_id TEXT,
61
+ payload TEXT,
62
+ timestamp REAL NOT NULL,
63
+ delivered_to_js INTEGER NOT NULL DEFAULT 0,
64
+ created_at REAL NOT NULL
65
+ )
66
+ """.trimIndent()
67
+ )
68
+ db.execSQL(
69
+ """
70
+ CREATE TABLE IF NOT EXISTS geofences (
71
+ identifier TEXT PRIMARY KEY,
72
+ latitude REAL NOT NULL,
73
+ longitude REAL NOT NULL,
74
+ radius REAL NOT NULL,
75
+ notify_on_entry INTEGER NOT NULL,
76
+ notify_on_exit INTEGER NOT NULL,
77
+ notify_on_dwell INTEGER NOT NULL,
78
+ loitering_delay REAL,
79
+ expiration_duration REAL,
80
+ metadata TEXT,
81
+ created_at REAL NOT NULL
82
+ )
83
+ """.trimIndent()
84
+ )
85
+ }
86
+
87
+ override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
88
+ if (oldVersion < 2) {
89
+ runCatching { db.execSQL("ALTER TABLE background_events ADD COLUMN payload TEXT") }
90
+ }
91
+ if (oldVersion < 3) {
92
+ runCatching { db.execSQL("ALTER TABLE geofences ADD COLUMN metadata TEXT") }
93
+ }
94
+ }
95
+
96
+ fun insertLocation(location: BackgroundLocation): StoredBackgroundLocation {
97
+ val id = location.id ?: java.util.UUID.randomUUID().toString()
98
+ val createdAt = System.currentTimeMillis().toDouble()
99
+ writableDatabase.insertWithOnConflict(
100
+ "background_locations",
101
+ null,
102
+ ContentValues().apply {
103
+ put("id", id)
104
+ put("latitude", location.coords.latitude)
105
+ put("longitude", location.coords.longitude)
106
+ put("altitude", location.coords.altitude?.asSecondOrNull())
107
+ put("accuracy", location.coords.accuracy)
108
+ put("altitude_accuracy", location.coords.altitudeAccuracy?.asSecondOrNull())
109
+ put("heading", location.coords.heading?.asSecondOrNull())
110
+ put("speed", location.coords.speed?.asSecondOrNull())
111
+ put("timestamp", location.timestamp)
112
+ put("provider", location.provider?.name)
113
+ put("mocked", if (location.mocked == true) 1 else 0)
114
+ put("source", location.source.name)
115
+ put("recorded_at", location.recordedAt)
116
+ put("created_at", createdAt)
117
+ },
118
+ SQLiteDatabase.CONFLICT_REPLACE
119
+ )
120
+
121
+ return StoredBackgroundLocation(
122
+ id,
123
+ false,
124
+ false,
125
+ createdAt,
126
+ location.source,
127
+ location.isFromBackground,
128
+ location.provider,
129
+ location.mocked,
130
+ location.recordedAt,
131
+ location.activity,
132
+ location.battery,
133
+ location.coords,
134
+ location.timestamp
135
+ )
136
+ }
137
+
138
+ fun insertEvent(event: BackgroundEventEnvelope) {
139
+ writableDatabase.insertWithOnConflict(
140
+ "background_events",
141
+ null,
142
+ ContentValues().apply {
143
+ put("id", event.id)
144
+ put("type", event.type.name)
145
+ put("location_id", event.location?.id)
146
+ put(
147
+ "payload",
148
+ event.location?.let(::locationPayload)
149
+ ?: event.geofence?.let(::geofencePayload)
150
+ ?: event.activity?.let(::activityPayload)
151
+ ?: event.result?.let(::httpSyncPayload)
152
+ )
153
+ put("timestamp", event.timestamp)
154
+ put("delivered_to_js", if (event.deliveredToJS) 1 else 0)
155
+ put("created_at", System.currentTimeMillis().toDouble())
156
+ },
157
+ SQLiteDatabase.CONFLICT_REPLACE
158
+ )
159
+ }
160
+
161
+ fun getLocations(options: GetStoredBackgroundLocationsOptions?): Array<StoredBackgroundLocation> {
162
+ val where = mutableListOf<String>()
163
+ val args = mutableListOf<String>()
164
+ if (options?.includeDelivered != true) {
165
+ where += "delivered_to_js = 0"
166
+ }
167
+ if (options?.includeSynced != true) {
168
+ where += "synced = 0"
169
+ }
170
+ options?.since?.let {
171
+ where += "created_at >= ?"
172
+ args += it.toString()
173
+ }
174
+ val limit = options?.limit?.toInt()?.takeIf { it > 0 } ?: 100
175
+ val cursor = readableDatabase.query(
176
+ "background_locations",
177
+ null,
178
+ where.takeIf { it.isNotEmpty() }?.joinToString(" AND "),
179
+ args.toTypedArray(),
180
+ null,
181
+ null,
182
+ "created_at DESC",
183
+ limit.toString()
184
+ )
185
+ return cursor.use {
186
+ val rows = mutableListOf<StoredBackgroundLocation>()
187
+ while (it.moveToNext()) {
188
+ rows += cursorToStoredLocation(it)
189
+ }
190
+ rows.toTypedArray()
191
+ }
192
+ }
193
+
194
+ fun getEvents(options: GetStoredBackgroundEventsOptions?): Array<StoredBackgroundEventEnvelope> {
195
+ val where = mutableListOf<String>()
196
+ val args = mutableListOf<String>()
197
+ if (options?.includeDelivered != true) {
198
+ where += "delivered_to_js = 0"
199
+ }
200
+ options?.since?.let {
201
+ where += "created_at >= ?"
202
+ args += it.toString()
203
+ }
204
+ options?.types?.takeIf { it.isNotEmpty() }?.let { types ->
205
+ where += "type IN (${types.joinToString(",") { "?" }})"
206
+ args += types.map { it.name }
207
+ }
208
+ val limit = options?.limit?.toInt()?.takeIf { it > 0 } ?: 100
209
+ val cursor = readableDatabase.query(
210
+ "background_events",
211
+ null,
212
+ where.takeIf { it.isNotEmpty() }?.joinToString(" AND "),
213
+ args.toTypedArray(),
214
+ null,
215
+ null,
216
+ "created_at DESC",
217
+ limit.toString()
218
+ )
219
+ return cursor.use {
220
+ val rows = mutableListOf<StoredBackgroundEventEnvelope>()
221
+ while (it.moveToNext()) {
222
+ val id = it.getString(it.getColumnIndexOrThrow("id"))
223
+ val type = enumValueOf<BackgroundEventType>(
224
+ it.getString(it.getColumnIndexOrThrow("type"))
225
+ )
226
+ val locationId = it.getString(it.getColumnIndexOrThrow("location_id"))
227
+ val payload = nullableStringColumn(it, "payload")
228
+ val geofence = if (type == BackgroundEventType.GEOFENCE) {
229
+ payload?.let(::payloadToGeofence)
230
+ } else {
231
+ null
232
+ }
233
+ val activity = if (type == BackgroundEventType.ACTIVITY) {
234
+ payload?.let(::payloadToActivity)
235
+ } else {
236
+ null
237
+ }
238
+ val result = if (type == BackgroundEventType.HTTPSYNC) {
239
+ payload?.let(::payloadToHttpSync)
240
+ } else {
241
+ null
242
+ }
243
+ val location = if (type == BackgroundEventType.LOCATION) {
244
+ payload?.let(::payloadToLocation)
245
+ ?: locationId?.let(::getLocationById)?.toBackgroundLocation()
246
+ } else {
247
+ locationId?.let(::getLocationById)?.toBackgroundLocation()
248
+ }
249
+ val event = BackgroundEventEnvelope(
250
+ location,
251
+ geofence,
252
+ activity,
253
+ null,
254
+ result,
255
+ null,
256
+ id,
257
+ type,
258
+ it.getDouble(it.getColumnIndexOrThrow("timestamp")),
259
+ it.getInt(it.getColumnIndexOrThrow("delivered_to_js")) == 1
260
+ )
261
+ rows += StoredBackgroundEventEnvelope(
262
+ event,
263
+ it.getDouble(it.getColumnIndexOrThrow("created_at")),
264
+ id,
265
+ type,
266
+ event.timestamp,
267
+ event.deliveredToJS
268
+ )
269
+ }
270
+ rows.toTypedArray()
271
+ }
272
+ }
273
+
274
+ fun markLocationsDelivered(ids: Array<String>) = markRows("background_locations", ids)
275
+ fun markEventsDelivered(ids: Array<String>) = markRows("background_events", ids)
276
+ fun clearLocations(ids: Array<String>?) = deleteRows("background_locations", ids)
277
+ fun clearEvents(ids: Array<String>?) = deleteRows("background_events", ids)
278
+
279
+ fun saveGeofences(regions: Array<GeofenceRegion>) {
280
+ writableDatabase.beginTransaction()
281
+ try {
282
+ for (region in regions) {
283
+ writableDatabase.insertWithOnConflict(
284
+ "geofences",
285
+ null,
286
+ ContentValues().apply {
287
+ put("identifier", region.identifier)
288
+ put("latitude", region.latitude)
289
+ put("longitude", region.longitude)
290
+ put("radius", region.radius)
291
+ put("notify_on_entry", if (region.notifyOnEntry != false) 1 else 0)
292
+ put("notify_on_exit", if (region.notifyOnExit != false) 1 else 0)
293
+ put("notify_on_dwell", if (region.notifyOnDwell == true) 1 else 0)
294
+ put("loitering_delay", region.loiteringDelay)
295
+ put("expiration_duration", region.expirationDuration)
296
+ put("metadata", metadataToJson(region.metadata))
297
+ put("created_at", System.currentTimeMillis().toDouble())
298
+ },
299
+ SQLiteDatabase.CONFLICT_REPLACE
300
+ )
301
+ }
302
+ writableDatabase.setTransactionSuccessful()
303
+ } finally {
304
+ writableDatabase.endTransaction()
305
+ }
306
+ }
307
+
308
+ fun removeGeofences(ids: Array<String>?) = deleteRows("geofences", ids, "identifier")
309
+
310
+ fun getGeofences(): Array<GeofenceRegion> {
311
+ val cursor = readableDatabase.query("geofences", null, null, null, null, null, "created_at DESC")
312
+ return cursor.use {
313
+ val rows = mutableListOf<GeofenceRegion>()
314
+ while (it.moveToNext()) {
315
+ rows += GeofenceRegion(
316
+ it.getString(it.getColumnIndexOrThrow("identifier")),
317
+ it.getDouble(it.getColumnIndexOrThrow("latitude")),
318
+ it.getDouble(it.getColumnIndexOrThrow("longitude")),
319
+ it.getDouble(it.getColumnIndexOrThrow("radius")),
320
+ it.getInt(it.getColumnIndexOrThrow("notify_on_entry")) == 1,
321
+ it.getInt(it.getColumnIndexOrThrow("notify_on_exit")) == 1,
322
+ it.getInt(it.getColumnIndexOrThrow("notify_on_dwell")) == 1,
323
+ nullableDoubleColumn(it, "loitering_delay"),
324
+ nullableDoubleColumn(it, "expiration_duration"),
325
+ nullableStringColumn(it, "metadata")?.let(::jsonToMetadata)
326
+ )
327
+ }
328
+ rows.toTypedArray()
329
+ }
330
+ }
331
+
332
+ fun count(table: String): Double {
333
+ val cursor = readableDatabase.rawQuery("SELECT COUNT(*) FROM $table", null)
334
+ return cursor.use {
335
+ if (it.moveToFirst()) it.getLong(0).toDouble() else 0.0
336
+ }
337
+ }
338
+
339
+ fun markSynced(ids: List<String>) {
340
+ if (ids.isEmpty()) return
341
+ val placeholders = ids.joinToString(",") { "?" }
342
+ writableDatabase.execSQL(
343
+ "UPDATE background_locations SET synced = 1 WHERE id IN ($placeholders)",
344
+ ids.toTypedArray()
345
+ )
346
+ }
347
+
348
+ fun pruneLocations(maxRows: Int?) = pruneRows("background_locations", maxRows)
349
+ fun pruneEvents(maxRows: Int?) = pruneRows("background_events", maxRows)
350
+
351
+ private fun pruneRows(table: String, maxRows: Int?) {
352
+ val limit = maxRows?.takeIf { it > 0 } ?: return
353
+ writableDatabase.execSQL(
354
+ """
355
+ DELETE FROM $table
356
+ WHERE id NOT IN (
357
+ SELECT id FROM $table ORDER BY created_at DESC LIMIT ?
358
+ )
359
+ """.trimIndent(),
360
+ arrayOf(limit.toString())
361
+ )
362
+ }
363
+
364
+ private fun getLocationById(id: String): StoredBackgroundLocation? {
365
+ val cursor = readableDatabase.query(
366
+ "background_locations",
367
+ null,
368
+ "id = ?",
369
+ arrayOf(id),
370
+ null,
371
+ null,
372
+ null,
373
+ "1"
374
+ )
375
+ return cursor.use {
376
+ if (it.moveToFirst()) cursorToStoredLocation(it) else null
377
+ }
378
+ }
379
+
380
+ private fun markRows(table: String, ids: Array<String>) {
381
+ if (ids.isEmpty()) return
382
+ val placeholders = ids.joinToString(",") { "?" }
383
+ writableDatabase.execSQL(
384
+ "UPDATE $table SET delivered_to_js = 1 WHERE id IN ($placeholders)",
385
+ ids
386
+ )
387
+ }
388
+
389
+ private fun deleteRows(table: String, ids: Array<String>?, idColumn: String = "id") {
390
+ if (ids == null) {
391
+ writableDatabase.delete(table, null, null)
392
+ return
393
+ }
394
+ if (ids.isEmpty()) return
395
+ writableDatabase.delete(table, "$idColumn IN (${ids.joinToString(",") { "?" }})", ids)
396
+ }
397
+
398
+ private fun StoredBackgroundLocation.toBackgroundLocation(): BackgroundLocation {
399
+ return BackgroundLocation(
400
+ id,
401
+ source,
402
+ isFromBackground,
403
+ provider,
404
+ mocked,
405
+ recordedAt,
406
+ activity,
407
+ battery,
408
+ coords,
409
+ timestamp
410
+ )
411
+ }
412
+
413
+ private fun cursorToStoredLocation(cursor: android.database.Cursor): StoredBackgroundLocation {
414
+ val id = cursor.getString(cursor.getColumnIndexOrThrow("id"))
415
+ val coords = GeolocationCoordinates(
416
+ cursor.getDouble(cursor.getColumnIndexOrThrow("latitude")),
417
+ cursor.getDouble(cursor.getColumnIndexOrThrow("longitude")),
418
+ nullableDoubleVariant(cursor, "altitude"),
419
+ cursor.getDouble(cursor.getColumnIndexOrThrow("accuracy")),
420
+ nullableDoubleVariant(cursor, "altitude_accuracy"),
421
+ nullableDoubleVariant(cursor, "heading"),
422
+ nullableDoubleVariant(cursor, "speed")
423
+ )
424
+ return StoredBackgroundLocation(
425
+ id,
426
+ cursor.getInt(cursor.getColumnIndexOrThrow("delivered_to_js")) == 1,
427
+ cursor.getInt(cursor.getColumnIndexOrThrow("synced")) == 1,
428
+ cursor.getDouble(cursor.getColumnIndexOrThrow("created_at")),
429
+ runCatching {
430
+ enumValueOf<BackgroundLocationSource>(
431
+ cursor.getString(cursor.getColumnIndexOrThrow("source"))
432
+ )
433
+ }.getOrDefault(BackgroundLocationSource.UNKNOWN),
434
+ true,
435
+ cursor.getString(cursor.getColumnIndexOrThrow("provider"))?.let {
436
+ runCatching { enumValueOf<LocationProviderUsed>(it) }.getOrNull()
437
+ },
438
+ cursor.getInt(cursor.getColumnIndexOrThrow("mocked")) == 1,
439
+ cursor.getDouble(cursor.getColumnIndexOrThrow("recorded_at")),
440
+ null,
441
+ null,
442
+ coords,
443
+ cursor.getDouble(cursor.getColumnIndexOrThrow("timestamp"))
444
+ )
445
+ }
446
+
447
+ private fun nullableDoubleColumn(cursor: android.database.Cursor, column: String): Double? {
448
+ val index = cursor.getColumnIndexOrThrow(column)
449
+ return if (cursor.isNull(index)) null else cursor.getDouble(index)
450
+ }
451
+
452
+ private fun nullableStringColumn(cursor: android.database.Cursor, column: String): String? {
453
+ val index = cursor.getColumnIndex(column)
454
+ return if (index < 0 || cursor.isNull(index)) null else cursor.getString(index)
455
+ }
456
+
457
+ private fun nullableDoubleVariant(cursor: android.database.Cursor, column: String): NullableDouble? {
458
+ return nullableDoubleColumn(cursor, column)?.let { NullableDouble.create(it) }
459
+ }
460
+
461
+ private fun locationPayload(location: BackgroundLocation): String {
462
+ return JSONObject()
463
+ .put("id", location.id)
464
+ .put("source", location.source.name)
465
+ .put("isFromBackground", location.isFromBackground)
466
+ .put("provider", location.provider?.name)
467
+ .put("mocked", location.mocked)
468
+ .put("recordedAt", location.recordedAt)
469
+ .put(
470
+ "coords",
471
+ JSONObject()
472
+ .put("latitude", location.coords.latitude)
473
+ .put("longitude", location.coords.longitude)
474
+ .put("altitude", location.coords.altitude?.asSecondOrNull())
475
+ .put("accuracy", location.coords.accuracy)
476
+ .put("altitudeAccuracy", location.coords.altitudeAccuracy?.asSecondOrNull())
477
+ .put("heading", location.coords.heading?.asSecondOrNull())
478
+ .put("speed", location.coords.speed?.asSecondOrNull())
479
+ )
480
+ .put("timestamp", location.timestamp)
481
+ .toString()
482
+ }
483
+
484
+ private fun payloadToLocation(payload: String): BackgroundLocation? {
485
+ return runCatching {
486
+ val json = JSONObject(payload)
487
+ val coordsJson = json.getJSONObject("coords")
488
+ BackgroundLocation(
489
+ if (json.has("id") && !json.isNull("id")) json.getString("id") else null,
490
+ runCatching {
491
+ enumValueOf<BackgroundLocationSource>(json.getString("source"))
492
+ }.getOrDefault(BackgroundLocationSource.UNKNOWN),
493
+ json.optBoolean("isFromBackground", true),
494
+ if (json.has("provider") && !json.isNull("provider")) {
495
+ runCatching { enumValueOf<LocationProviderUsed>(json.getString("provider")) }.getOrNull()
496
+ } else {
497
+ null
498
+ },
499
+ if (json.has("mocked") && !json.isNull("mocked")) json.getBoolean("mocked") else null,
500
+ json.getDouble("recordedAt"),
501
+ null,
502
+ null,
503
+ GeolocationCoordinates(
504
+ coordsJson.getDouble("latitude"),
505
+ coordsJson.getDouble("longitude"),
506
+ coordsJson.optDoubleOrNull("altitude")?.let { NullableDouble.create(it) },
507
+ coordsJson.getDouble("accuracy"),
508
+ coordsJson.optDoubleOrNull("altitudeAccuracy")?.let { NullableDouble.create(it) },
509
+ coordsJson.optDoubleOrNull("heading")?.let { NullableDouble.create(it) },
510
+ coordsJson.optDoubleOrNull("speed")?.let { NullableDouble.create(it) }
511
+ ),
512
+ json.getDouble("timestamp")
513
+ )
514
+ }.getOrNull()
515
+ }
516
+
517
+ private fun geofencePayload(event: GeofenceEvent): String {
518
+ val region = event.region
519
+ return JSONObject()
520
+ .put("transition", event.transition.name)
521
+ .put("timestamp", event.timestamp)
522
+ .put(
523
+ "region",
524
+ JSONObject()
525
+ .put("identifier", region.identifier)
526
+ .put("latitude", region.latitude)
527
+ .put("longitude", region.longitude)
528
+ .put("radius", region.radius)
529
+ .put("notifyOnEntry", region.notifyOnEntry)
530
+ .put("notifyOnExit", region.notifyOnExit)
531
+ .put("notifyOnDwell", region.notifyOnDwell)
532
+ .put("loiteringDelay", region.loiteringDelay)
533
+ .put("expirationDuration", region.expirationDuration)
534
+ .put("metadata", metadataToJsonObject(region.metadata))
535
+ )
536
+ .toString()
537
+ }
538
+
539
+ private fun payloadToGeofence(payload: String): GeofenceEvent? {
540
+ return runCatching {
541
+ val json = JSONObject(payload)
542
+ val regionJson = json.getJSONObject("region")
543
+ GeofenceEvent(
544
+ GeofenceRegion(
545
+ regionJson.getString("identifier"),
546
+ regionJson.getDouble("latitude"),
547
+ regionJson.getDouble("longitude"),
548
+ regionJson.getDouble("radius"),
549
+ regionJson.optBoolean("notifyOnEntry", true),
550
+ regionJson.optBoolean("notifyOnExit", true),
551
+ regionJson.optBoolean("notifyOnDwell", false),
552
+ regionJson.optDoubleOrNull("loiteringDelay"),
553
+ regionJson.optDoubleOrNull("expirationDuration"),
554
+ regionJson.optJSONObject("metadata")?.let(::jsonToMetadata)
555
+ ),
556
+ enumValueOf<GeofenceTransition>(json.getString("transition")),
557
+ null,
558
+ json.getDouble("timestamp")
559
+ )
560
+ }.getOrNull()
561
+ }
562
+
563
+ private fun activityPayload(activity: DetectedActivity): String {
564
+ return JSONObject()
565
+ .put("type", activity.type.name)
566
+ .put("confidence", activity.confidence)
567
+ .put("timestamp", activity.timestamp)
568
+ .toString()
569
+ }
570
+
571
+ private fun payloadToActivity(payload: String): DetectedActivity? {
572
+ return runCatching {
573
+ val json = JSONObject(payload)
574
+ DetectedActivity(
575
+ enumValueOf<DetectedActivityType>(json.getString("type")),
576
+ json.getDouble("confidence"),
577
+ json.getDouble("timestamp")
578
+ )
579
+ }.getOrNull()
580
+ }
581
+
582
+ private fun httpSyncPayload(result: BackgroundHttpSyncResult): String {
583
+ return JSONObject()
584
+ .put("success", result.success)
585
+ .put("statusCode", result.statusCode)
586
+ .put("syncedLocationIds", JSONArray(result.syncedLocationIds.toList()))
587
+ .put("failedLocationIds", JSONArray(result.failedLocationIds.toList()))
588
+ .put("error", result.error)
589
+ .toString()
590
+ }
591
+
592
+ private fun payloadToHttpSync(payload: String): BackgroundHttpSyncResult? {
593
+ return runCatching {
594
+ val json = JSONObject(payload)
595
+ BackgroundHttpSyncResult(
596
+ json.getBoolean("success"),
597
+ json.optDoubleOrNull("statusCode"),
598
+ json.optJSONArray("syncedLocationIds").toStringArray(),
599
+ json.optJSONArray("failedLocationIds").toStringArray(),
600
+ if (json.has("error") && !json.isNull("error")) json.getString("error") else null
601
+ )
602
+ }.getOrNull()
603
+ }
604
+
605
+ private fun JSONArray?.toStringArray(): Array<String> {
606
+ if (this == null) return emptyArray()
607
+ return Array(length()) { index -> getString(index) }
608
+ }
609
+
610
+ private fun JSONObject.optDoubleOrNull(key: String): Double? {
611
+ return if (has(key) && !isNull(key)) optDouble(key) else null
612
+ }
613
+
614
+ private fun metadataToJson(metadata: Map<String, Variant_NullType_Boolean_String_Double>?): String? {
615
+ return metadata?.let(::metadataToJsonObject)?.toString()
616
+ }
617
+
618
+ private fun metadataToJsonObject(
619
+ metadata: Map<String, Variant_NullType_Boolean_String_Double>?
620
+ ): JSONObject? {
621
+ metadata ?: return null
622
+ val json = JSONObject()
623
+ metadata.forEach { (key, value) ->
624
+ when (value) {
625
+ is Variant_NullType_Boolean_String_Double.First -> json.put(key, JSONObject.NULL)
626
+ is Variant_NullType_Boolean_String_Double.Second -> json.put(key, value.value)
627
+ is Variant_NullType_Boolean_String_Double.Third -> json.put(key, value.value)
628
+ is Variant_NullType_Boolean_String_Double.Fourth -> json.put(key, value.value)
629
+ }
630
+ }
631
+ return json
632
+ }
633
+
634
+ private fun jsonToMetadata(json: JSONObject): Map<String, Variant_NullType_Boolean_String_Double> {
635
+ val metadata = mutableMapOf<String, Variant_NullType_Boolean_String_Double>()
636
+ val keys = json.keys()
637
+ while (keys.hasNext()) {
638
+ val key = keys.next()
639
+ metadata[key] = when (val value = json.get(key)) {
640
+ JSONObject.NULL -> Variant_NullType_Boolean_String_Double.create(NullType.NULL)
641
+ is Boolean -> Variant_NullType_Boolean_String_Double.create(value)
642
+ is String -> Variant_NullType_Boolean_String_Double.create(value)
643
+ is Number -> Variant_NullType_Boolean_String_Double.create(value.toDouble())
644
+ is JSONArray -> Variant_NullType_Boolean_String_Double.create(value.toString())
645
+ is JSONObject -> Variant_NullType_Boolean_String_Double.create(value.toString())
646
+ else -> Variant_NullType_Boolean_String_Double.create(value.toString())
647
+ }
648
+ }
649
+ return metadata
650
+ }
651
+
652
+ private fun jsonToMetadata(payload: String): Map<String, Variant_NullType_Boolean_String_Double> {
653
+ return jsonToMetadata(JSONObject(payload))
654
+ }
655
+ }
@@ -0,0 +1,26 @@
1
+ package com.margelo.nitro.nitrogeolocation.background
2
+
3
+ import android.content.BroadcastReceiver
4
+ import android.content.Context
5
+ import android.content.Intent
6
+
7
+ class NitroBootReceiver : BroadcastReceiver() {
8
+ override fun onReceive(context: Context, intent: Intent) {
9
+ if (
10
+ intent.action != Intent.ACTION_BOOT_COMPLETED &&
11
+ intent.action != Intent.ACTION_LOCKED_BOOT_COMPLETED
12
+ ) {
13
+ return
14
+ }
15
+
16
+ val prefs = context.applicationContext.getSharedPreferences(
17
+ "nitro_background_location",
18
+ Context.MODE_PRIVATE
19
+ )
20
+ val controller = NitroBackgroundLocationController.getInstance(context)
21
+ runCatching { controller.registerPersistedGeofencesIfNeeded() }
22
+ if (prefs.getBoolean("startOnBoot", false)) {
23
+ runCatching { controller.start(null) }
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,14 @@
1
+ package com.margelo.nitro.nitrogeolocation.background
2
+
3
+ import android.content.BroadcastReceiver
4
+ import android.content.Context
5
+ import android.content.Intent
6
+ import com.google.android.gms.location.GeofencingEvent
7
+
8
+ class NitroGeofenceReceiver : BroadcastReceiver() {
9
+ override fun onReceive(context: Context, intent: Intent) {
10
+ val event = GeofencingEvent.fromIntent(intent) ?: return
11
+ if (event.hasError()) return
12
+ NitroBackgroundLocationController.getInstance(context).handleGeofenceEvent(event)
13
+ }
14
+ }