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.
- package/BgGeolocation.podspec +39 -0
- package/LICENSE +20 -0
- package/README.md +366 -0
- package/android/build.gradle +69 -0
- package/android/src/main/AndroidManifest.xml +53 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationActivityRecognitionReceiver.kt +116 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationBootReceiver.kt +44 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationForegroundService.kt +373 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationGeofenceReceiver.kt +55 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationHeadlessTask.kt +138 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationModule.kt +1030 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationMotionStateMachine.kt +159 -0
- package/android/src/main/java/com/bggeolocation/BgGeolocationPackage.kt +31 -0
- package/android/src/main/res/drawable/bg_geo_notification.xml +9 -0
- package/ios/BgGeolocation.h +14 -0
- package/ios/BgGeolocation.mm +709 -0
- package/ios/engine/AtomicBoolean.swift +48 -0
- package/ios/engine/BGActivityChangeEvent.swift +20 -0
- package/ios/engine/BGActivityConfig.swift +71 -0
- package/ios/engine/BGAppConfig.swift +92 -0
- package/ios/engine/BGAppState.swift +147 -0
- package/ios/engine/BGAuthorization.swift +85 -0
- package/ios/engine/BGAuthorizationAlertPresenter.swift +39 -0
- package/ios/engine/BGAuthorizationConfig.swift +50 -0
- package/ios/engine/BGAuthorizationEvent.swift +40 -0
- package/ios/engine/BGBackgroundTaskManager.swift +143 -0
- package/ios/engine/BGCLRouter.swift +101 -0
- package/ios/engine/BGCallback.swift +19 -0
- package/ios/engine/BGConfig.swift +440 -0
- package/ios/engine/BGConfigModuleBase.swift +180 -0
- package/ios/engine/BGConfigOLD.swift +582 -0
- package/ios/engine/BGConnectivityChangeEvent.swift +15 -0
- package/ios/engine/BGCrashDetector.swift +122 -0
- package/ios/engine/BGCurrentPositionRequest.swift +87 -0
- package/ios/engine/BGDataStore.swift +75 -0
- package/ios/engine/BGDatabase.swift +677 -0
- package/ios/engine/BGDatabasePool.swift +220 -0
- package/ios/engine/BGDatabaseQueue.swift +215 -0
- package/ios/engine/BGDateUtils.swift +26 -0
- package/ios/engine/BGDeviceInfo.swift +54 -0
- package/ios/engine/BGDeviceManager.swift +65 -0
- package/ios/engine/BGEnabledChangeEvent.swift +11 -0
- package/ios/engine/BGEnv.swift +17 -0
- package/ios/engine/BGEventBus.swift +83 -0
- package/ios/engine/BGEventManager.swift +169 -0
- package/ios/engine/BGEventNames.swift +51 -0
- package/ios/engine/BGGeofence.swift +233 -0
- package/ios/engine/BGGeofenceDAO.swift +152 -0
- package/ios/engine/BGGeofenceEvent.swift +42 -0
- package/ios/engine/BGGeofenceLocationRequest.swift +94 -0
- package/ios/engine/BGGeofenceManager.swift +315 -0
- package/ios/engine/BGGeofenceTransition.swift +97 -0
- package/ios/engine/BGGeofencesChangeEvent.swift +26 -0
- package/ios/engine/BGGeolocationConfig.swift +136 -0
- package/ios/engine/BGHeartbeatEvent.swift +31 -0
- package/ios/engine/BGHeartbeatService.swift +51 -0
- package/ios/engine/BGHttpConfig.swift +105 -0
- package/ios/engine/BGHttpErrorCodes.swift +63 -0
- package/ios/engine/BGHttpEvent.swift +34 -0
- package/ios/engine/BGHttpRequest.swift +126 -0
- package/ios/engine/BGHttpResponse.swift +93 -0
- package/ios/engine/BGHttpService.swift +428 -0
- package/ios/engine/BGKalmanFilter.swift +105 -0
- package/ios/engine/BGLMActionNames.swift +55 -0
- package/ios/engine/BGLicenseManager.swift +26 -0
- package/ios/engine/BGLiveActivityManager.swift +327 -0
- package/ios/engine/BGLocation.swift +311 -0
- package/ios/engine/BGLocationAuthorization.swift +427 -0
- package/ios/engine/BGLocationDAO.swift +252 -0
- package/ios/engine/BGLocationErrors.swift +28 -0
- package/ios/engine/BGLocationEvent.swift +43 -0
- package/ios/engine/BGLocationFilter.swift +82 -0
- package/ios/engine/BGLocationFilterConfig.swift +57 -0
- package/ios/engine/BGLocationHelper.swift +54 -0
- package/ios/engine/BGLocationManager.swift +662 -0
- package/ios/engine/BGLocationMetricsEngine.swift +116 -0
- package/ios/engine/BGLocationRequestService.swift +459 -0
- package/ios/engine/BGLocationSatisfier.swift +14 -0
- package/ios/engine/BGLocationStreamEvent.swift +27 -0
- package/ios/engine/BGLog.swift +337 -0
- package/ios/engine/BGLogLevel.swift +26 -0
- package/ios/engine/BGLoggerConfig.swift +60 -0
- package/ios/engine/BGMotionActivity.swift +31 -0
- package/ios/engine/BGMotionActivityClassifier.swift +108 -0
- package/ios/engine/BGMotionActivityManagerAdapter.swift +40 -0
- package/ios/engine/BGMotionActivitySource.swift +46 -0
- package/ios/engine/BGMotionDetector.swift +377 -0
- package/ios/engine/BGMotionPermissionManager.swift +50 -0
- package/ios/engine/BGNativeLogger.swift +48 -0
- package/ios/engine/BGNotificaitons.swift +37 -0
- package/ios/engine/BGOdometer.swift +66 -0
- package/ios/engine/BGPersistenceConfig.swift +29 -0
- package/ios/engine/BGPolygonStreamRequest.swift +48 -0
- package/ios/engine/BGPowerSaveChangeEvent.swift +12 -0
- package/ios/engine/BGPropertySpec.swift +29 -0
- package/ios/engine/BGProviderChangeEvent.swift +31 -0
- package/ios/engine/BGQueue.swift +50 -0
- package/ios/engine/BGRPC.swift +194 -0
- package/ios/engine/BGReachability.swift +58 -0
- package/ios/engine/BGResultSet.swift +157 -0
- package/ios/engine/BGSchedule.swift +228 -0
- package/ios/engine/BGScheduleEvent.swift +13 -0
- package/ios/engine/BGScheduler.swift +116 -0
- package/ios/engine/BGSingleLocationRequest.swift +49 -0
- package/ios/engine/BGStreamLocationRequest.swift +42 -0
- package/ios/engine/BGTemplate.swift +54 -0
- package/ios/engine/BGTimerService.swift +46 -0
- package/ios/engine/BGTrackingAudioManager.swift +286 -0
- package/ios/engine/BGTrackingService.swift +879 -0
- package/ios/engine/BGWatchPositionRequest.swift +63 -0
- package/ios/engine/DatabaseQueue.swift +47 -0
- package/ios/engine/LogQuery.swift +10 -0
- package/ios/engine/SQLQuery.swift +65 -0
- package/ios/engine/TransistorAuthorizationToken.swift +182 -0
- package/ios/liveactivity/BGLiveTrackingAttributes.swift +52 -0
- package/ios/locationpush/BGLocationPushDeliverer.swift +260 -0
- package/ios/locationpush/BGLocationPushService.swift +161 -0
- package/ios/locationpush/BGLocationPushShared.swift +98 -0
- package/ios/locationpush/BGLocationPushSocketClient.swift +198 -0
- package/lib/module/NativeBgGeolocation.js +5 -0
- package/lib/module/NativeBgGeolocation.js.map +1 -0
- package/lib/module/events.js +20 -0
- package/lib/module/events.js.map +1 -0
- package/lib/module/index.js +706 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeBgGeolocation.d.ts +57 -0
- package/lib/typescript/src/NativeBgGeolocation.d.ts.map +1 -0
- package/lib/typescript/src/events.d.ts +18 -0
- package/lib/typescript/src/events.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +238 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +229 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +141 -0
- package/src/NativeBgGeolocation.ts +236 -0
- package/src/events.ts +17 -0
- package/src/index.tsx +935 -0
- 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
|
+
}
|