react-native-bg-geolocation 0.2.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 (142) hide show
  1. package/BgGeolocation.podspec +39 -0
  2. package/LICENSE +20 -0
  3. package/README.md +366 -0
  4. package/android/build.gradle +69 -0
  5. package/android/src/main/AndroidManifest.xml +53 -0
  6. package/android/src/main/java/com/bggeolocation/BgGeolocationActivityRecognitionReceiver.kt +116 -0
  7. package/android/src/main/java/com/bggeolocation/BgGeolocationBootReceiver.kt +44 -0
  8. package/android/src/main/java/com/bggeolocation/BgGeolocationForegroundService.kt +373 -0
  9. package/android/src/main/java/com/bggeolocation/BgGeolocationGeofenceReceiver.kt +55 -0
  10. package/android/src/main/java/com/bggeolocation/BgGeolocationHeadlessTask.kt +138 -0
  11. package/android/src/main/java/com/bggeolocation/BgGeolocationModule.kt +1030 -0
  12. package/android/src/main/java/com/bggeolocation/BgGeolocationMotionStateMachine.kt +159 -0
  13. package/android/src/main/java/com/bggeolocation/BgGeolocationPackage.kt +31 -0
  14. package/android/src/main/res/drawable/bg_geo_notification.xml +9 -0
  15. package/ios/BgGeolocation.h +14 -0
  16. package/ios/BgGeolocation.mm +709 -0
  17. package/ios/engine/AtomicBoolean.swift +48 -0
  18. package/ios/engine/BGActivityChangeEvent.swift +20 -0
  19. package/ios/engine/BGActivityConfig.swift +71 -0
  20. package/ios/engine/BGAppConfig.swift +92 -0
  21. package/ios/engine/BGAppState.swift +147 -0
  22. package/ios/engine/BGAuthorization.swift +85 -0
  23. package/ios/engine/BGAuthorizationAlertPresenter.swift +39 -0
  24. package/ios/engine/BGAuthorizationConfig.swift +50 -0
  25. package/ios/engine/BGAuthorizationEvent.swift +40 -0
  26. package/ios/engine/BGBackgroundTaskManager.swift +143 -0
  27. package/ios/engine/BGCLRouter.swift +101 -0
  28. package/ios/engine/BGCallback.swift +19 -0
  29. package/ios/engine/BGConfig.swift +440 -0
  30. package/ios/engine/BGConfigModuleBase.swift +180 -0
  31. package/ios/engine/BGConfigOLD.swift +582 -0
  32. package/ios/engine/BGConnectivityChangeEvent.swift +15 -0
  33. package/ios/engine/BGCrashDetector.swift +122 -0
  34. package/ios/engine/BGCurrentPositionRequest.swift +87 -0
  35. package/ios/engine/BGDataStore.swift +75 -0
  36. package/ios/engine/BGDatabase.swift +677 -0
  37. package/ios/engine/BGDatabasePool.swift +220 -0
  38. package/ios/engine/BGDatabaseQueue.swift +215 -0
  39. package/ios/engine/BGDateUtils.swift +26 -0
  40. package/ios/engine/BGDeviceInfo.swift +54 -0
  41. package/ios/engine/BGDeviceManager.swift +65 -0
  42. package/ios/engine/BGEnabledChangeEvent.swift +11 -0
  43. package/ios/engine/BGEnv.swift +17 -0
  44. package/ios/engine/BGEventBus.swift +83 -0
  45. package/ios/engine/BGEventManager.swift +169 -0
  46. package/ios/engine/BGEventNames.swift +51 -0
  47. package/ios/engine/BGGeofence.swift +233 -0
  48. package/ios/engine/BGGeofenceDAO.swift +152 -0
  49. package/ios/engine/BGGeofenceEvent.swift +42 -0
  50. package/ios/engine/BGGeofenceLocationRequest.swift +94 -0
  51. package/ios/engine/BGGeofenceManager.swift +315 -0
  52. package/ios/engine/BGGeofenceTransition.swift +97 -0
  53. package/ios/engine/BGGeofencesChangeEvent.swift +26 -0
  54. package/ios/engine/BGGeolocationConfig.swift +136 -0
  55. package/ios/engine/BGHeartbeatEvent.swift +31 -0
  56. package/ios/engine/BGHeartbeatService.swift +51 -0
  57. package/ios/engine/BGHttpConfig.swift +105 -0
  58. package/ios/engine/BGHttpErrorCodes.swift +63 -0
  59. package/ios/engine/BGHttpEvent.swift +34 -0
  60. package/ios/engine/BGHttpRequest.swift +126 -0
  61. package/ios/engine/BGHttpResponse.swift +93 -0
  62. package/ios/engine/BGHttpService.swift +428 -0
  63. package/ios/engine/BGKalmanFilter.swift +105 -0
  64. package/ios/engine/BGLMActionNames.swift +55 -0
  65. package/ios/engine/BGLicenseManager.swift +26 -0
  66. package/ios/engine/BGLiveActivityManager.swift +327 -0
  67. package/ios/engine/BGLocation.swift +311 -0
  68. package/ios/engine/BGLocationAuthorization.swift +427 -0
  69. package/ios/engine/BGLocationDAO.swift +252 -0
  70. package/ios/engine/BGLocationErrors.swift +28 -0
  71. package/ios/engine/BGLocationEvent.swift +43 -0
  72. package/ios/engine/BGLocationFilter.swift +82 -0
  73. package/ios/engine/BGLocationFilterConfig.swift +57 -0
  74. package/ios/engine/BGLocationHelper.swift +54 -0
  75. package/ios/engine/BGLocationManager.swift +662 -0
  76. package/ios/engine/BGLocationMetricsEngine.swift +116 -0
  77. package/ios/engine/BGLocationRequestService.swift +459 -0
  78. package/ios/engine/BGLocationSatisfier.swift +14 -0
  79. package/ios/engine/BGLocationStreamEvent.swift +27 -0
  80. package/ios/engine/BGLog.swift +337 -0
  81. package/ios/engine/BGLogLevel.swift +26 -0
  82. package/ios/engine/BGLoggerConfig.swift +60 -0
  83. package/ios/engine/BGMotionActivity.swift +31 -0
  84. package/ios/engine/BGMotionActivityClassifier.swift +108 -0
  85. package/ios/engine/BGMotionActivityManagerAdapter.swift +40 -0
  86. package/ios/engine/BGMotionActivitySource.swift +46 -0
  87. package/ios/engine/BGMotionDetector.swift +377 -0
  88. package/ios/engine/BGMotionPermissionManager.swift +50 -0
  89. package/ios/engine/BGNativeLogger.swift +48 -0
  90. package/ios/engine/BGNotificaitons.swift +37 -0
  91. package/ios/engine/BGOdometer.swift +66 -0
  92. package/ios/engine/BGPersistenceConfig.swift +29 -0
  93. package/ios/engine/BGPolygonStreamRequest.swift +48 -0
  94. package/ios/engine/BGPowerSaveChangeEvent.swift +12 -0
  95. package/ios/engine/BGPropertySpec.swift +29 -0
  96. package/ios/engine/BGProviderChangeEvent.swift +31 -0
  97. package/ios/engine/BGQueue.swift +50 -0
  98. package/ios/engine/BGRPC.swift +194 -0
  99. package/ios/engine/BGReachability.swift +58 -0
  100. package/ios/engine/BGResultSet.swift +157 -0
  101. package/ios/engine/BGSchedule.swift +228 -0
  102. package/ios/engine/BGScheduleEvent.swift +13 -0
  103. package/ios/engine/BGScheduler.swift +116 -0
  104. package/ios/engine/BGSingleLocationRequest.swift +49 -0
  105. package/ios/engine/BGStreamLocationRequest.swift +42 -0
  106. package/ios/engine/BGTemplate.swift +54 -0
  107. package/ios/engine/BGTimerService.swift +46 -0
  108. package/ios/engine/BGTrackingAudioManager.swift +286 -0
  109. package/ios/engine/BGTrackingService.swift +879 -0
  110. package/ios/engine/BGWatchPositionRequest.swift +63 -0
  111. package/ios/engine/DatabaseQueue.swift +47 -0
  112. package/ios/engine/LogQuery.swift +10 -0
  113. package/ios/engine/SQLQuery.swift +65 -0
  114. package/ios/engine/TransistorAuthorizationToken.swift +182 -0
  115. package/ios/liveactivity/BGLiveTrackingAttributes.swift +52 -0
  116. package/ios/locationpush/BGLocationPushDeliverer.swift +260 -0
  117. package/ios/locationpush/BGLocationPushService.swift +161 -0
  118. package/ios/locationpush/BGLocationPushShared.swift +98 -0
  119. package/ios/locationpush/BGLocationPushSocketClient.swift +198 -0
  120. package/lib/module/NativeBgGeolocation.js +5 -0
  121. package/lib/module/NativeBgGeolocation.js.map +1 -0
  122. package/lib/module/events.js +20 -0
  123. package/lib/module/events.js.map +1 -0
  124. package/lib/module/index.js +706 -0
  125. package/lib/module/index.js.map +1 -0
  126. package/lib/module/package.json +1 -0
  127. package/lib/module/types.js +2 -0
  128. package/lib/module/types.js.map +1 -0
  129. package/lib/typescript/package.json +1 -0
  130. package/lib/typescript/src/NativeBgGeolocation.d.ts +57 -0
  131. package/lib/typescript/src/NativeBgGeolocation.d.ts.map +1 -0
  132. package/lib/typescript/src/events.d.ts +18 -0
  133. package/lib/typescript/src/events.d.ts.map +1 -0
  134. package/lib/typescript/src/index.d.ts +238 -0
  135. package/lib/typescript/src/index.d.ts.map +1 -0
  136. package/lib/typescript/src/types.d.ts +229 -0
  137. package/lib/typescript/src/types.d.ts.map +1 -0
  138. package/package.json +141 -0
  139. package/src/NativeBgGeolocation.ts +236 -0
  140. package/src/events.ts +17 -0
  141. package/src/index.tsx +935 -0
  142. package/src/types.ts +254 -0
@@ -0,0 +1,169 @@
1
+ import Foundation
2
+
3
+ @objc public class BGLocationListener: NSObject {
4
+ @objc public var success: ((Any?) -> Void)?
5
+ @objc public var failure: ((Any?) -> Void)?
6
+
7
+ @objc public override func isEqual(_ object: Any?) -> Bool {
8
+ guard let other = object as? BGLocationListener else { return false }
9
+ return self === other
10
+ }
11
+
12
+ @objc public override var hash: Int { return ObjectIdentifier(self).hashValue }
13
+ }
14
+
15
+ @objc public class BGEventManager: NSObject {
16
+
17
+ private static var _sharedInstance: BGEventManager?
18
+ private static let lock = NSLock()
19
+
20
+ @objc public var listeners: NSMutableDictionary = NSMutableDictionary()
21
+ @objc public var locationListeners: NSMutableArray = NSMutableArray()
22
+ @objc public var bufferedEvents: NSMutableDictionary = NSMutableDictionary()
23
+ @objc public var bufferingEnabled: Bool = true
24
+ @objc public var locked: Bool = false
25
+ @objc public var maxBufferedPerEvent: Int = 1
26
+
27
+ @objc public class func sharedInstance() -> BGEventManager {
28
+ lock.lock()
29
+ defer { lock.unlock() }
30
+ if _sharedInstance == nil {
31
+ _sharedInstance = BGEventManager()
32
+ }
33
+ return _sharedInstance!
34
+ }
35
+
36
+ @objc public override init() {
37
+ super.init()
38
+ listeners = NSMutableDictionary()
39
+ locationListeners = NSMutableArray()
40
+ bufferedEvents = NSMutableDictionary()
41
+ bufferingEnabled = true
42
+ maxBufferedPerEvent = 1
43
+ }
44
+
45
+ @objc public func isLocked() -> Bool { return locked }
46
+ @objc public func isBuffering() -> Bool { return bufferingEnabled }
47
+
48
+ @objc public func lock() { locked = true }
49
+
50
+ @objc public func ready() {
51
+ bufferingEnabled = false
52
+ flushBufferedEvents()
53
+ }
54
+
55
+ @objc public func addListener(_ event: String, callback: @escaping (Any?) -> Void) -> String {
56
+ let token = UUID().uuidString
57
+ objc_sync_enter(self)
58
+ var eventListeners = listeners[event] as? [[String: Any]] ?? []
59
+ eventListeners.append(["token": token, "callback": callback])
60
+ listeners[event] = eventListeners
61
+ objc_sync_exit(self)
62
+ return token
63
+ }
64
+
65
+ @objc public func addLocationListener(success: @escaping (Any?) -> Void,
66
+ failure: @escaping (Any?) -> Void) -> BGLocationListener {
67
+ let listener = BGLocationListener()
68
+ listener.success = success
69
+ listener.failure = failure
70
+ objc_sync_enter(self)
71
+ locationListeners.add(listener)
72
+ objc_sync_exit(self)
73
+ return listener
74
+ }
75
+
76
+ @objc public func removeListener(_ event: String, callback: AnyObject) {
77
+ objc_sync_enter(self)
78
+ if var eventListeners = listeners[event] as? [[String: Any]] {
79
+ eventListeners.removeAll { ($0["callback"] as AnyObject) === callback }
80
+ listeners[event] = eventListeners
81
+ }
82
+ objc_sync_exit(self)
83
+ }
84
+
85
+ @objc public func removeListener(_ event: String, token: String) {
86
+ objc_sync_enter(self)
87
+ if var eventListeners = listeners[event] as? [[String: Any]] {
88
+ eventListeners.removeAll { ($0["token"] as? String) == token }
89
+ listeners[event] = eventListeners
90
+ }
91
+ objc_sync_exit(self)
92
+ }
93
+
94
+ @objc public func removeListeners(_ event: String) {
95
+ objc_sync_enter(self)
96
+ listeners.removeObject(forKey: event)
97
+ objc_sync_exit(self)
98
+ }
99
+
100
+ @objc public func removeListeners() {
101
+ objc_sync_enter(self)
102
+ listeners.removeAllObjects()
103
+ locationListeners.removeAllObjects()
104
+ objc_sync_exit(self)
105
+ }
106
+
107
+ @objc public func trigger(_ event: String, payload: Any?) {
108
+ if bufferingEnabled {
109
+ bufferEvent(event, payload: payload)
110
+ return
111
+ }
112
+ objc_sync_enter(self)
113
+ let eventListeners = listeners[event] as? [[String: Any]] ?? []
114
+ objc_sync_exit(self)
115
+ for entry in eventListeners {
116
+ if let callback = entry["callback"] as? (Any?) -> Void {
117
+ callback(payload)
118
+ }
119
+ }
120
+ }
121
+
122
+ @objc public func triggerLocationSuccess(_ location: Any?) {
123
+ objc_sync_enter(self)
124
+ let lst = locationListeners.copy() as! NSArray
125
+ objc_sync_exit(self)
126
+ for listener in lst {
127
+ (listener as? BGLocationListener)?.success?(location)
128
+ }
129
+ }
130
+
131
+ @objc public func triggerLocationError(_ error: Any?) {
132
+ objc_sync_enter(self)
133
+ let lst = locationListeners.copy() as! NSArray
134
+ objc_sync_exit(self)
135
+ for listener in lst {
136
+ (listener as? BGLocationListener)?.failure?(error)
137
+ }
138
+ }
139
+
140
+ @objc public func bufferEvent(_ event: String, payload: Any?) {
141
+ objc_sync_enter(self)
142
+ var buf = bufferedEvents[event] as? [Any] ?? []
143
+ buf.append(payload as Any)
144
+ if buf.count > maxBufferedPerEvent {
145
+ buf.removeFirst()
146
+ }
147
+ bufferedEvents[event] = buf
148
+ objc_sync_exit(self)
149
+ }
150
+
151
+ @objc public func drainBuffer(forEvent event: String) {
152
+ objc_sync_enter(self)
153
+ let buf = bufferedEvents[event] as? [Any] ?? []
154
+ bufferedEvents.removeObject(forKey: event)
155
+ objc_sync_exit(self)
156
+ for payload in buf {
157
+ trigger(event, payload: payload)
158
+ }
159
+ }
160
+
161
+ @objc public func flushBufferedEvents() {
162
+ objc_sync_enter(self)
163
+ let events = (bufferedEvents.allKeys as? [String]) ?? []
164
+ objc_sync_exit(self)
165
+ for event in events {
166
+ drainBuffer(forEvent: event)
167
+ }
168
+ }
169
+ }
@@ -0,0 +1,51 @@
1
+ import Foundation
2
+
3
+ // Global NSString event-name constants (extern NSString * const BGEventName…).
4
+
5
+ public let BGEventNameLocation = "location"
6
+ public let BGEventNameLocationError = "locationerror"
7
+ public let BGEventNameHttp = "http"
8
+ public let BGEventNameGeofence = "geofence"
9
+ public let BGEventNameHeartbeat = "heartbeat"
10
+ public let BGEventNameMotionChange = "motionchange"
11
+ public let BGEventNameActivityChange = "activitychange"
12
+ public let BGEventNameProviderChange = "providerchange"
13
+ public let BGEventNameGeofencesChange = "geofenceschange"
14
+ public let BGEventNameSchedule = "schedule"
15
+ public let BGEventNamePowerSaveChange = "powersavechange"
16
+ public let BGEventNameConnectivityChange = "connectivitychange"
17
+ public let BGEventNameEnabledChange = "enabledchange"
18
+ public let BGEventNameAuthorization = "authorization"
19
+ public let BGEventNameCLLocation = "CLLocation"
20
+ public let BGEventNameWatchPosition = "watchposition"
21
+ public let BGEventNameRPCError = "RPCError"
22
+ public let BGEventNameStopMonitoringSignificantLocationChanges = "stopMonitoringSignificantLocationChanges"
23
+
24
+ public let BGEventBusNameAppResume = "BGAppState.resume"
25
+ public let BGEventBusNameAppSuspend = "BGAppState.suspend"
26
+ public let BGEventBusNamePersist = "BGLocation.persist"
27
+
28
+ // Convenience namespace for dot-syntax access to event name constants.
29
+ public struct BGEventNames {
30
+ public static let location = BGEventNameLocation
31
+ public static let locationError = BGEventNameLocationError
32
+ public static let http = BGEventNameHttp
33
+ public static let geofence = BGEventNameGeofence
34
+ public static let heartbeat = BGEventNameHeartbeat
35
+ public static let motionChange = BGEventNameMotionChange
36
+ public static let activityChange = BGEventNameActivityChange
37
+ public static let providerChange = BGEventNameProviderChange
38
+ public static let geofencesChange = BGEventNameGeofencesChange
39
+ public static let schedule = BGEventNameSchedule
40
+ public static let powerSaveChange = BGEventNamePowerSaveChange
41
+ public static let connectivityChange = BGEventNameConnectivityChange
42
+ public static let enabledChange = BGEventNameEnabledChange
43
+ public static let authorization = BGEventNameAuthorization
44
+ public static let watchPosition = BGEventNameWatchPosition
45
+ // Composite names used by BGLog and other components
46
+ public static let locationComplete = "locationComplete"
47
+ public static let locationSample = "locationSample"
48
+ public static let geofenceComplete = "geofenceComplete"
49
+ public static let motionChangeComplete = "motionChangeComplete"
50
+ public static let motionChangeError = "motionChangeError"
51
+ }
@@ -0,0 +1,233 @@
1
+ import Foundation
2
+ import CoreLocation
3
+
4
+ @objc public class BGGeofence: NSObject {
5
+
6
+ @objc public var identifier: String = ""
7
+ @objc public var latitude: CLLocationDegrees = 0
8
+ @objc public var longitude: CLLocationDegrees = 0
9
+ @objc public var radius: CLLocationDistance = 200
10
+ @objc public var notifyOnEntry: Bool = true
11
+ @objc public var notifyOnExit: Bool = true
12
+ @objc public var notifyOnDwell: Bool = false
13
+ @objc public var loiteringDelay: Double = 0
14
+ @objc public var extras: [String: Any]?
15
+ @objc public var vertices: [[Double]] = []
16
+
17
+ @objc public var entryState: String = "UNKNOWN"
18
+ @objc public var stateUpdatedAt: Date?
19
+ @objc public var hits: Int = 0
20
+ @objc public var isLoitering: Bool = false
21
+ @objc public var isMonitoring: Bool = false
22
+ @objc public var loiteringRegion: CLCircularRegion?
23
+ @objc public var loiteringTransition: String?
24
+ @objc public var request: Any?
25
+ @objc public var cancelRequest: (() -> Void)?
26
+ @objc public var currentPolygonHits: Int = 0
27
+ @objc public var desiredPolygonHits: Int = 0
28
+
29
+ @objc public class func circle(
30
+ withIdentifier identifier: String,
31
+ radius: CLLocationDistance,
32
+ latitude: CLLocationDegrees,
33
+ longitude: CLLocationDegrees,
34
+ notifyOnEntry: Bool,
35
+ notifyOnExit: Bool,
36
+ notifyOnDwell: Bool,
37
+ loiteringDelay: Double,
38
+ extras: [String: Any]?
39
+ ) -> BGGeofence {
40
+ let g = BGGeofence()
41
+ g.identifier = identifier
42
+ g.radius = radius
43
+ g.latitude = latitude
44
+ g.longitude = longitude
45
+ g.notifyOnEntry = notifyOnEntry
46
+ g.notifyOnExit = notifyOnExit
47
+ g.notifyOnDwell = notifyOnDwell
48
+ g.loiteringDelay = loiteringDelay
49
+ g.extras = extras
50
+ return g
51
+ }
52
+
53
+ @objc public class func polygon(
54
+ withIdentifier identifier: String,
55
+ vertices: [[Double]],
56
+ notifyOnEntry: Bool,
57
+ notifyOnExit: Bool,
58
+ notifyOnDwell: Bool,
59
+ loiteringDelay: Double,
60
+ extras: [String: Any]?
61
+ ) -> BGGeofence {
62
+ let g = BGGeofence()
63
+ g.identifier = identifier
64
+ g.vertices = vertices
65
+ g.notifyOnEntry = notifyOnEntry
66
+ g.notifyOnExit = notifyOnExit
67
+ g.notifyOnDwell = notifyOnDwell
68
+ g.loiteringDelay = loiteringDelay
69
+ g.extras = extras
70
+ return g
71
+ }
72
+
73
+ @objc public init(
74
+ identifier: String,
75
+ radius: CLLocationDistance,
76
+ latitude: CLLocationDegrees,
77
+ longitude: CLLocationDegrees,
78
+ notifyOnEntry: Bool,
79
+ notifyOnExit: Bool,
80
+ notifyOnDwell: Bool,
81
+ loiteringDelay: Double
82
+ ) {
83
+ self.identifier = identifier
84
+ self.radius = radius
85
+ self.latitude = latitude
86
+ self.longitude = longitude
87
+ self.notifyOnEntry = notifyOnEntry
88
+ self.notifyOnExit = notifyOnExit
89
+ self.notifyOnDwell = notifyOnDwell
90
+ self.loiteringDelay = loiteringDelay
91
+ super.init()
92
+ }
93
+
94
+ @objc public init(
95
+ identifier: String,
96
+ radius: CLLocationDistance,
97
+ latitude: CLLocationDegrees,
98
+ longitude: CLLocationDegrees,
99
+ notifyOnEntry: Bool,
100
+ notifyOnExit: Bool,
101
+ notifyOnDwell: Bool,
102
+ loiteringDelay: Double,
103
+ extras: [String: Any]?,
104
+ vertices: [[Double]]
105
+ ) {
106
+ self.identifier = identifier
107
+ self.radius = radius
108
+ self.latitude = latitude
109
+ self.longitude = longitude
110
+ self.notifyOnEntry = notifyOnEntry
111
+ self.notifyOnExit = notifyOnExit
112
+ self.notifyOnDwell = notifyOnDwell
113
+ self.loiteringDelay = loiteringDelay
114
+ self.extras = extras
115
+ self.vertices = vertices
116
+ super.init()
117
+ }
118
+
119
+ @objc public init(
120
+ identifier: String,
121
+ radius: CLLocationDistance,
122
+ latitude: CLLocationDegrees,
123
+ longitude: CLLocationDegrees,
124
+ notifyOnEntry: Bool,
125
+ notifyOnExit: Bool,
126
+ notifyOnDwell: Bool,
127
+ loiteringDelay: Double,
128
+ extras: [String: Any]?,
129
+ vertices: [[Double]],
130
+ entryState: String,
131
+ stateUpdatedAt: Date?,
132
+ hits: Int
133
+ ) {
134
+ self.identifier = identifier
135
+ self.radius = radius
136
+ self.latitude = latitude
137
+ self.longitude = longitude
138
+ self.notifyOnEntry = notifyOnEntry
139
+ self.notifyOnExit = notifyOnExit
140
+ self.notifyOnDwell = notifyOnDwell
141
+ self.loiteringDelay = loiteringDelay
142
+ self.extras = extras
143
+ self.vertices = vertices
144
+ self.entryState = entryState
145
+ self.stateUpdatedAt = stateUpdatedAt
146
+ self.hits = hits
147
+ super.init()
148
+ }
149
+
150
+ @objc public override init() {
151
+ super.init()
152
+ }
153
+
154
+ @objc public var isPolygon: Bool {
155
+ return !vertices.isEmpty
156
+ }
157
+
158
+ @objc public var exitMEC: CLCircularRegion? {
159
+ guard !isPolygon else { return nil }
160
+ let center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
161
+ return CLCircularRegion(center: center, radius: radius, identifier: identifier)
162
+ }
163
+
164
+ @objc public func startMonitoring(withLocationManager manager: CLLocationManager, prefix: String) {
165
+ guard !isPolygon else {
166
+ startMonitoringPolygon()
167
+ return
168
+ }
169
+ let center = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
170
+ let region = CLCircularRegion(center: center, radius: radius, identifier: "\(prefix)\(identifier)")
171
+ region.notifyOnEntry = notifyOnEntry
172
+ region.notifyOnExit = notifyOnExit
173
+ manager.startMonitoring(for: region)
174
+ isMonitoring = true
175
+ }
176
+
177
+ @objc public func startMonitoringPolygon() {
178
+ isMonitoring = true
179
+ }
180
+
181
+ @objc public func stopMonitoringPolygon() {
182
+ isMonitoring = false
183
+ }
184
+
185
+ @objc public func startLoitering() {
186
+ isLoitering = true
187
+ }
188
+
189
+ @objc public func cancelLoitering() {
190
+ isLoitering = false
191
+ }
192
+
193
+ @objc public func cancelLocationRequest() {
194
+ cancelRequest?()
195
+ cancelRequest = nil
196
+ }
197
+
198
+ @objc public func cancel() {
199
+ cancelLocationRequest()
200
+ isMonitoring = false
201
+ }
202
+
203
+ @objc public func fireEvent(_ action: String, location: CLLocation?) {
204
+ NotificationCenter.default.post(
205
+ name: NSNotification.Name("BGGeofenceEvent"),
206
+ object: self,
207
+ userInfo: ["action": action, "location": location as Any]
208
+ )
209
+ }
210
+
211
+ @objc public func persistState() {
212
+ }
213
+
214
+ @objc public func toDictionary() -> [String: Any] {
215
+ var dict: [String: Any] = [
216
+ "identifier": identifier,
217
+ "latitude": latitude,
218
+ "longitude": longitude,
219
+ "radius": radius,
220
+ "notifyOnEntry": notifyOnEntry,
221
+ "notifyOnExit": notifyOnExit,
222
+ "notifyOnDwell": notifyOnDwell,
223
+ "loiteringDelay": loiteringDelay
224
+ ]
225
+ if let extras = extras { dict["extras"] = extras }
226
+ if !vertices.isEmpty { dict["vertices"] = vertices }
227
+ return dict
228
+ }
229
+
230
+ @objc public override var description: String {
231
+ return "<BGGeofence id=\(identifier) lat=\(latitude) lon=\(longitude) radius=\(radius)>"
232
+ }
233
+ }
@@ -0,0 +1,152 @@
1
+ import Foundation
2
+ import CoreLocation
3
+
4
+ @objc public class BGGeofenceDAO: NSObject {
5
+
6
+ private static var _sharedInstance: BGGeofenceDAO?
7
+ private static let lock = NSLock()
8
+ private var geofences: [String: BGGeofence] = [:]
9
+ private let daLock = NSLock()
10
+
11
+ @objc public class func sharedInstance() -> BGGeofenceDAO {
12
+ lock.lock()
13
+ defer { lock.unlock() }
14
+ if _sharedInstance == nil {
15
+ _sharedInstance = BGGeofenceDAO()
16
+ }
17
+ return _sharedInstance!
18
+ }
19
+
20
+ @objc public override init() {
21
+ super.init()
22
+ }
23
+
24
+ @objc public func all() -> [BGGeofence] {
25
+ daLock.lock()
26
+ defer { daLock.unlock() }
27
+ return Array(geofences.values)
28
+ }
29
+
30
+ @objc public func all(withLocking lock: Bool) -> [BGGeofence] {
31
+ return all()
32
+ }
33
+
34
+ @objc public func count() -> Int {
35
+ daLock.lock()
36
+ defer { daLock.unlock() }
37
+ return geofences.count
38
+ }
39
+
40
+ @objc public func maxRadius() -> CLLocationDistance {
41
+ daLock.lock()
42
+ defer { daLock.unlock() }
43
+ return geofences.values.map { $0.radius }.max() ?? 0
44
+ }
45
+
46
+ @objc public func find(_ identifier: String) -> BGGeofence? {
47
+ daLock.lock()
48
+ defer { daLock.unlock() }
49
+ return geofences[identifier]
50
+ }
51
+
52
+ @objc public func exists(_ identifier: String) -> Bool {
53
+ daLock.lock()
54
+ defer { daLock.unlock() }
55
+ return geofences[identifier] != nil
56
+ }
57
+
58
+ @objc public func exists(_ db: Any?, identifier: String) -> Bool {
59
+ return exists(identifier)
60
+ }
61
+
62
+ @objc public func create(_ geofence: BGGeofence) -> Bool {
63
+ daLock.lock()
64
+ geofences[geofence.identifier] = geofence
65
+ daLock.unlock()
66
+ return true
67
+ }
68
+
69
+ @objc public func createAll(_ fences: [BGGeofence]) {
70
+ daLock.lock()
71
+ for g in fences { geofences[g.identifier] = g }
72
+ daLock.unlock()
73
+ }
74
+
75
+ @objc public func destroy(_ identifier: String) -> Bool {
76
+ daLock.lock()
77
+ let existed = geofences.removeValue(forKey: identifier) != nil
78
+ daLock.unlock()
79
+ return existed
80
+ }
81
+
82
+ @objc public func destroyAll() {
83
+ daLock.lock()
84
+ geofences.removeAll()
85
+ daLock.unlock()
86
+ }
87
+
88
+ @objc public func doInsert(_ db: Any?, geofence: BGGeofence) -> Bool {
89
+ return create(geofence)
90
+ }
91
+
92
+ @objc public func hydrate(_ row: [String: Any]) -> BGGeofence? {
93
+ guard let id = row["identifier"] as? String else { return nil }
94
+ let g = BGGeofence()
95
+ g.identifier = id
96
+ g.latitude = row["latitude"] as? CLLocationDegrees ?? 0
97
+ g.longitude = row["longitude"] as? CLLocationDegrees ?? 0
98
+ g.radius = row["radius"] as? CLLocationDistance ?? 200
99
+ g.notifyOnEntry = row["notify_on_entry"] as? Bool ?? true
100
+ g.notifyOnExit = row["notify_on_exit"] as? Bool ?? true
101
+ g.notifyOnDwell = row["notify_on_dwell"] as? Bool ?? false
102
+ g.loiteringDelay = row["loitering_delay"] as? Double ?? 0
103
+ g.entryState = row["entry_state"] as? String ?? "UNKNOWN"
104
+ g.hits = row["hits"] as? Int ?? 0
105
+ if let extrasStr = row["extras"] as? String {
106
+ g.extras = decodeExtras(extrasStr)
107
+ }
108
+ if let vertStr = row["vertices"] as? String {
109
+ g.vertices = decodeVertices(vertStr)
110
+ }
111
+ return g
112
+ }
113
+
114
+ @objc public func decodeExtras(_ json: String) -> [String: Any]? {
115
+ guard let data = json.data(using: .utf8) else { return nil }
116
+ return try? JSONSerialization.jsonObject(with: data) as? [String: Any]
117
+ }
118
+
119
+ @objc public func decodeVertices(_ json: String) -> [[Double]] {
120
+ guard let data = json.data(using: .utf8),
121
+ let arr = try? JSONSerialization.jsonObject(with: data) as? [[Double]] else { return [] }
122
+ return arr
123
+ }
124
+
125
+ @objc public func allWithinRadius(
126
+ _ radius: CLLocationDistance,
127
+ latitude: CLLocationDegrees,
128
+ longitude: CLLocationDegrees,
129
+ limit: Int
130
+ ) -> [BGGeofence] {
131
+ let center = CLLocation(latitude: latitude, longitude: longitude)
132
+ daLock.lock()
133
+ var results = geofences.values.filter {
134
+ let loc = CLLocation(latitude: $0.latitude, longitude: $0.longitude)
135
+ return center.distance(from: loc) <= radius
136
+ }
137
+ daLock.unlock()
138
+ if limit > 0 { results = Array(results.prefix(limit)) }
139
+ return results
140
+ }
141
+
142
+ @objc public func updateState(
143
+ forIdentifier identifier: String,
144
+ entryState: String,
145
+ hits: Int
146
+ ) {
147
+ daLock.lock()
148
+ geofences[identifier]?.entryState = entryState
149
+ geofences[identifier]?.hits = hits
150
+ daLock.unlock()
151
+ }
152
+ }
@@ -0,0 +1,42 @@
1
+ import Foundation
2
+ import CoreLocation
3
+
4
+ @objc public final class BGGeofenceEvent: NSObject {
5
+
6
+ @objc public private(set) var identifier: String
7
+ @objc public private(set) var action: String
8
+ @objc public private(set) var timestamp: Date?
9
+ @objc public private(set) var geofence: BGGeofence?
10
+ @objc public private(set) var location: Any?
11
+ @objc public private(set) var extras: [AnyHashable: Any]?
12
+
13
+ @objc public init(identifier: String?,
14
+ action: String?,
15
+ timestamp: Date?,
16
+ geofence: BGGeofence?,
17
+ location: Any?,
18
+ extras: [AnyHashable: Any]?) {
19
+ self.identifier = identifier ?? ""
20
+ self.action = action ?? ""
21
+ self.timestamp = timestamp
22
+ self.geofence = geofence
23
+ self.location = location ?? [AnyHashable: Any]()
24
+ self.extras = extras
25
+ super.init()
26
+ }
27
+
28
+ @objc public func toDictionary() -> [String: Any] {
29
+ var dict: [String: Any] = [:]
30
+ dict["identifier"] = identifier
31
+ dict["action"] = action
32
+ if let timestamp = timestamp {
33
+ dict["timestamp"] = BGDateUtils.iso8601String(from: timestamp)
34
+ }
35
+ dict["geofence"] = geofence?.toDictionary()
36
+ dict["location"] = location
37
+ if let extras = extras {
38
+ dict["extras"] = extras
39
+ }
40
+ return dict
41
+ }
42
+ }