react-native-move-sdk 0.1.5 → 0.2.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.
- package/README.md +21 -22
- package/android/build.gradle +45 -39
- package/android/gradle/wrapper/gradle-wrapper.properties +4 -1
- package/android/gradle.properties +8 -4
- package/android/src/main/java/in/dolph/move/sdk/MoveExtensions.kt +44 -0
- package/android/src/main/java/in/dolph/move/sdk/MoveNotificationConfig.kt +26 -26
- package/android/src/main/java/in/dolph/move/sdk/MoveSdkConfig.kt +8 -13
- package/android/src/main/java/in/dolph/move/sdk/MoveSdkModule.kt +137 -27
- package/android/src/main/java/in/dolph/move/sdk/MoveSdkPackage.kt +1 -1
- package/android/src/main/java/in/dolph/move/sdk/MoveSdkRepository.kt +171 -162
- package/android/src/main/java/in/dolph/move/sdk/NativeMoveSdkWrapper.kt +184 -84
- package/android/src/test/java/io/dolphin/move/MoveWrapperTest.kt +157 -0
- package/ios/MoveSdk-Bridging-Header.h +1 -0
- package/ios/MoveSdk.xcodeproj/project.pbxproj +6 -8
- package/ios/NativeModule/{DolphinSdk.h → MoveSdk.h} +21 -7
- package/ios/NativeModule/MoveSdk.swift +607 -0
- package/lib/commonjs/index.js +105 -111
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +105 -111
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +38 -39
- package/package.json +1 -1
- package/react-native-move-sdk.podspec +3 -1
- package/src/index.ts +163 -191
- package/ios/NativeModule/DolphinSdk.swift +0 -357
- package/ios/NativeModule/DolphinSdkDemoReactNative-Bridging-Header.h +0 -8
|
@@ -0,0 +1,607 @@
|
|
|
1
|
+
import CoreMotion
|
|
2
|
+
import Foundation
|
|
3
|
+
import DolphinMoveSDK
|
|
4
|
+
|
|
5
|
+
internal protocol MoveSDKLauncherDelegate: AnyObject {
|
|
6
|
+
func send(event: MoveSDKLauncher.Event, data: [String: Any])
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
typealias MoveSDKErrorListItem = [String:Any]
|
|
10
|
+
|
|
11
|
+
@objc(RCTMoveSdk)
|
|
12
|
+
class RCTMoveSdk: RCTEventEmitter {
|
|
13
|
+
private enum CError: String, Error {
|
|
14
|
+
case transformedServices = "Unknown driving service identifier in init parameters"
|
|
15
|
+
case transformedTimelineDetectionServices = "Unknown timeline service identifier in init parameters"
|
|
16
|
+
case transformedWalkingServices = "Unknown walking service identifier in init parameters"
|
|
17
|
+
case transformedOtherServices = "Unknown other service identifier in init parameters"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private enum ErrorCode: String {
|
|
21
|
+
case setupError = "SETUP_ERROR"
|
|
22
|
+
case resolveFailed = "RESOLVE_FAILED"
|
|
23
|
+
case serviceUnavailable = "SERVICE_UNAVAILABLE"
|
|
24
|
+
case thresholdReached = "THRESHOLD_REACHED"
|
|
25
|
+
case geocodeError = "GEOCODE_ERROR"
|
|
26
|
+
case authInvalid = "AUTH_INVALID"
|
|
27
|
+
case initializationError = "INITIALIZATION_ERROR"
|
|
28
|
+
case locationError = "LOCATION_ERROR"
|
|
29
|
+
case networkError = "NETWORK_ERROR"
|
|
30
|
+
case assistanceCallError = "ASSISTANCE_CALL_ERROR"
|
|
31
|
+
case configurationError = "CONFIGURATION_ERROR"
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let motionManager = CMMotionActivityManager()
|
|
36
|
+
|
|
37
|
+
override func startObserving() {
|
|
38
|
+
MoveSDKLauncher.shared.delegate = self
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@objc
|
|
42
|
+
func setup(_ contractId: String,
|
|
43
|
+
accessToken: String,
|
|
44
|
+
refreshToken: String,
|
|
45
|
+
productId: Int64,
|
|
46
|
+
timelineDetectionServices: Array<String>,
|
|
47
|
+
drivingServices: Array<String>,
|
|
48
|
+
walkingServices: Array<String>,
|
|
49
|
+
resolve: @escaping RCTPromiseResolveBlock,
|
|
50
|
+
reject: @escaping RCTPromiseRejectBlock) {
|
|
51
|
+
|
|
52
|
+
do {
|
|
53
|
+
|
|
54
|
+
let transformedServices: [MoveConfig.DrivingService] = try drivingServices.map {
|
|
55
|
+
switch $0 {
|
|
56
|
+
case "DISTRACTION_FREE_DRIVING":
|
|
57
|
+
return .distractionFreeDriving
|
|
58
|
+
case "DRIVING_BEHAVIOUR":
|
|
59
|
+
return .drivingBehavior
|
|
60
|
+
default:
|
|
61
|
+
throw CError.transformedServices
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let transformedWalkingServices: [MoveConfig.WalkingService] = try walkingServices.map {
|
|
66
|
+
if $0 == "LOCATION" {
|
|
67
|
+
return .location
|
|
68
|
+
}
|
|
69
|
+
throw CError.transformedWalkingServices
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
let transformedDetectionServices: [MoveConfig.DetectionService] = try! timelineDetectionServices.map {
|
|
73
|
+
switch $0 {
|
|
74
|
+
case "DRIVING":
|
|
75
|
+
return .driving(transformedServices)
|
|
76
|
+
case "WALKING":
|
|
77
|
+
return .walking(transformedWalkingServices)
|
|
78
|
+
case "CYCLING":
|
|
79
|
+
return .cycling
|
|
80
|
+
case "PUBLIC_TRANSPORT":
|
|
81
|
+
return .publicTransport
|
|
82
|
+
case "ASSISTANCE_CALL":
|
|
83
|
+
return .assistanceCall
|
|
84
|
+
case "POINTS_OF_INTEREST":
|
|
85
|
+
return .pointsOfInterest
|
|
86
|
+
case "AUTOMATIC_IMPACT_DETECTION":
|
|
87
|
+
return .automaticImpactDetection
|
|
88
|
+
default:
|
|
89
|
+
throw CError.transformedTimelineDetectionServices
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// TODO: Fix wrapper and add config option from RN for walking services (actually only 1 now)
|
|
94
|
+
let sdkConfig = MoveConfig(detectionService: transformedDetectionServices)
|
|
95
|
+
let auth = MoveAuth(userToken: accessToken, refreshToken: refreshToken, userID: contractId, projectID: productId)
|
|
96
|
+
|
|
97
|
+
DispatchQueue.main.async {
|
|
98
|
+
MoveSDKLauncher.shared.setup(auth: auth, config: sdkConfig)
|
|
99
|
+
}
|
|
100
|
+
resolve("OK")
|
|
101
|
+
} catch {
|
|
102
|
+
reject(ErrorCode.setupError.rawValue, "\(error)", nil)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@objc
|
|
107
|
+
func getState(
|
|
108
|
+
_ resolve: RCTPromiseResolveBlock,
|
|
109
|
+
rejecter reject: RCTPromiseRejectBlock
|
|
110
|
+
) {
|
|
111
|
+
let value = "\(MoveSDK.shared.getSDKState())".uppercased()
|
|
112
|
+
resolve(value)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@objc
|
|
116
|
+
func getAuthState(
|
|
117
|
+
_ resolve: RCTPromiseResolveBlock,
|
|
118
|
+
rejecter reject: RCTPromiseRejectBlock
|
|
119
|
+
) {
|
|
120
|
+
let value = "\(MoveSDK.shared.getAuthState())".uppercased()
|
|
121
|
+
resolve(value)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
@objc
|
|
125
|
+
func setAssistanceMetaData(_ data: String) {
|
|
126
|
+
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@objc
|
|
130
|
+
func geocode(_ latitude: Double, _ longitude: Double,
|
|
131
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
132
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
133
|
+
) {
|
|
134
|
+
MoveSDK.shared.geocode(latitude: latitude, longitude: longitude) { result in
|
|
135
|
+
switch result {
|
|
136
|
+
case let .success(value):
|
|
137
|
+
resolve(value)
|
|
138
|
+
case let .failure(err):
|
|
139
|
+
switch err {
|
|
140
|
+
case .resolveFailed:
|
|
141
|
+
reject(ErrorCode.resolveFailed.rawValue, nil, nil)
|
|
142
|
+
case .serviceUnreachable:
|
|
143
|
+
reject(ErrorCode.serviceUnavailable.rawValue, nil, nil)
|
|
144
|
+
case .thresholdReached:
|
|
145
|
+
reject(ErrorCode.thresholdReached.rawValue, nil, nil)
|
|
146
|
+
@unknown default:
|
|
147
|
+
reject(ErrorCode.geocodeError.rawValue, nil, nil)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@objc
|
|
154
|
+
func updateAuth(
|
|
155
|
+
_ contractId: String,
|
|
156
|
+
accessToken: String,
|
|
157
|
+
refreshToken: String,
|
|
158
|
+
productId: Int64,
|
|
159
|
+
resolver resolve: @escaping RCTPromiseResolveBlock,
|
|
160
|
+
rejecter reject: @escaping RCTPromiseRejectBlock
|
|
161
|
+
) {
|
|
162
|
+
let auth = MoveAuth(userToken: accessToken, refreshToken: refreshToken, userID: contractId, projectID: productId)
|
|
163
|
+
|
|
164
|
+
MoveSDKLauncher.shared.sdk.update(auth: auth) { configurationError in
|
|
165
|
+
if let configurationError = configurationError {
|
|
166
|
+
switch configurationError {
|
|
167
|
+
case .authInvalid:
|
|
168
|
+
reject(ErrorCode.authInvalid.rawValue, nil, nil)
|
|
169
|
+
@unknown default:
|
|
170
|
+
reject(ErrorCode.configurationError.rawValue, nil, nil)
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
resolve("OK")
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@objc
|
|
179
|
+
func getTripState(
|
|
180
|
+
_ resolve: RCTPromiseResolveBlock,
|
|
181
|
+
rejecter reject: RCTPromiseRejectBlock
|
|
182
|
+
) {
|
|
183
|
+
let value = "\(MoveSDK.shared.getTripState())".uppercased()
|
|
184
|
+
resolve(value)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
@objc
|
|
188
|
+
func getWarnings(
|
|
189
|
+
_ resolve: RCTPromiseResolveBlock,
|
|
190
|
+
rejecter reject: RCTPromiseRejectBlock
|
|
191
|
+
) {
|
|
192
|
+
resolve(MoveSDKLauncher.shared.getServiceWarnings())
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
@objc
|
|
196
|
+
func getErrors(
|
|
197
|
+
_ resolve: RCTPromiseResolveBlock,
|
|
198
|
+
rejecter reject: RCTPromiseRejectBlock
|
|
199
|
+
) {
|
|
200
|
+
resolve(MoveSDKLauncher.shared.getServiceFailures())
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@objc
|
|
204
|
+
func startAutomaticDetection() {
|
|
205
|
+
MoveSDK.shared.startAutomaticDetection()
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
@objc
|
|
209
|
+
func stopAutomaticDetection() {
|
|
210
|
+
MoveSDK.shared.stopAutomaticDetection()
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
@objc
|
|
214
|
+
func shutdown() {
|
|
215
|
+
MoveSDKLauncher.shared.shutdown()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
@objc
|
|
219
|
+
func forceTripRecognition() {
|
|
220
|
+
MoveSDKLauncher.shared.sdk.forceTripRecognition()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@objc
|
|
224
|
+
func synchronizeUserData(
|
|
225
|
+
_ resolve: @escaping RCTPromiseResolveBlock,
|
|
226
|
+
rejecter reject: @escaping RCTPromiseRejectBlock) {
|
|
227
|
+
MoveSDKLauncher.shared.sdk.synchronizeUserData() { success in
|
|
228
|
+
resolve(success)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@objc
|
|
233
|
+
func initiateAssistanceCall(
|
|
234
|
+
_ resolve: @escaping(RCTPromiseResolveBlock),
|
|
235
|
+
rejecter reject: @escaping(RCTPromiseRejectBlock)
|
|
236
|
+
) {
|
|
237
|
+
MoveSDKLauncher.shared.sdk.initiateAssistanceCall { status in
|
|
238
|
+
switch status {
|
|
239
|
+
case .success:
|
|
240
|
+
resolve(true)
|
|
241
|
+
case .initializationError:
|
|
242
|
+
reject(ErrorCode.initializationError.rawValue, nil, nil)
|
|
243
|
+
case .locationError:
|
|
244
|
+
reject(ErrorCode.locationError.rawValue, nil, nil)
|
|
245
|
+
case .networkError:
|
|
246
|
+
reject(ErrorCode.networkError.rawValue, nil, nil)
|
|
247
|
+
@unknown default:
|
|
248
|
+
reject(ErrorCode.assistanceCallError.rawValue, nil, nil)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
@objc
|
|
254
|
+
func ignoreCurrentTrip() {
|
|
255
|
+
MoveSDKLauncher.shared.sdk.ignoreCurrentTrip()
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
@objc
|
|
259
|
+
func finishCurrentTrip() {
|
|
260
|
+
MoveSDKLauncher.shared.sdk.finishCurrentTrip()
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
@objc
|
|
264
|
+
func resolveError() {
|
|
265
|
+
MoveSDKLauncher.shared.sdk.resolveSDKStateError()
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
@objc
|
|
269
|
+
func sendAppEvent(_ eventInfo: NSString) {
|
|
270
|
+
send(event: .appEvent, data: ["eventInfo": "\(eventInfo)"])
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
@objc
|
|
274
|
+
func requestMotionPermission() {
|
|
275
|
+
motionManager.queryActivityStarting(from: Date(), to: Date(), to: OperationQueue.main) { _, error in
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@objc public static func initIfPossible(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
|
|
280
|
+
MoveSDKLauncher.shared.initIfPossibleWith(launchOptions: launchOptions)
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
@objc public static func performBackgroundFetch(_ completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
|
284
|
+
MoveSDKLauncher.shared.performBackgroundFetch(completionHandler)
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
override func supportedEvents() -> [String]! {
|
|
288
|
+
MoveSDKLauncher.Event.allCases.map { $0.rawValue }
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
static override func moduleName() -> String! {
|
|
292
|
+
return "MoveSdk"
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
static override func requiresMainQueueSetup() -> Bool {
|
|
296
|
+
// To let React Native know if your module needs to be initialized on the main thread, before any JavaScript code executes.
|
|
297
|
+
// Otherwise you will see a warning that in the future your module may be initialized on a background thread unless you explicitly opt out
|
|
298
|
+
return true
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
extension RCTMoveSdk: MoveSDKLauncherDelegate {
|
|
303
|
+
func send(event: MoveSDKLauncher.Event, data: [String: Any]) {
|
|
304
|
+
sendEvent(withName: event.rawValue, body: data)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
internal class MoveSDKLauncher {
|
|
309
|
+
internal enum Event: String, CaseIterable {
|
|
310
|
+
case appEvent = "MOVE_SDK_APP_EVENT"
|
|
311
|
+
case sdkState = "MOVE_SDK_STATE"
|
|
312
|
+
case tripState = "MOVE_SDK_TRIP_STATE"
|
|
313
|
+
case authState = "MOVE_SDK_AUTH_STATE"
|
|
314
|
+
case warning = "MOVE_SDK_WARNINGS"
|
|
315
|
+
case failure = "MOVE_SDK_ERRORS"
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
private enum DefaultsKey: String {
|
|
319
|
+
case auth = "MOVE.WRAPPER.AUTH"
|
|
320
|
+
case config = "MOVE.WRAPPER.CONFIG"
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
weak var delegate: MoveSDKLauncherDelegate?
|
|
324
|
+
|
|
325
|
+
static let shared = MoveSDKLauncher()
|
|
326
|
+
|
|
327
|
+
let sdk = MoveSDK.shared
|
|
328
|
+
var launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
|
329
|
+
|
|
330
|
+
init() {
|
|
331
|
+
sdk.setSDKStateListener { state in
|
|
332
|
+
let value = "\(state)".uppercased()
|
|
333
|
+
self.delegate?.send(event: .sdkState, data: ["state": "\(value)"])
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
sdk.setTripStateListener { state in
|
|
337
|
+
let value = "\(state)".uppercased()
|
|
338
|
+
self.delegate?.send(event: .tripState, data: ["state": "\(value)"])
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
sdk.setAuthStateUpdateListener { state in
|
|
342
|
+
let value = "\(state)".uppercased()
|
|
343
|
+
self.delegate?.send(event: .authState, data: ["state": "\(value)"])
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
sdk.setServiceFailureListener { failures in
|
|
347
|
+
let data: [String: Any] = ["errors": self.convert(failures: failures)]
|
|
348
|
+
self.delegate?.send(event: .failure, data: data)
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
sdk.setServiceWarningListener { warnings in
|
|
352
|
+
let data: [String: Any] = ["warnings": self.convert(warnings: warnings)]
|
|
353
|
+
self.delegate?.send(event: .warning, data: data)
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
func getServiceWarnings() -> [MoveSDKErrorListItem] {
|
|
358
|
+
return convert(warnings: sdk.getServiceWarnings())
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
func getServiceFailures() -> [MoveSDKErrorListItem] {
|
|
362
|
+
return convert(failures: sdk.getServiceFailures())
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
func convert(service: DolphinMoveSDK.MoveConfig.DetectionService) -> String {
|
|
366
|
+
return service.debugDescription
|
|
367
|
+
// switch service {
|
|
368
|
+
// case let .driving(sub):
|
|
369
|
+
// if sub.isEmpty {
|
|
370
|
+
// return "DRIVING"
|
|
371
|
+
// } else {
|
|
372
|
+
// return service.debugDescription
|
|
373
|
+
// }
|
|
374
|
+
// case .cycling:
|
|
375
|
+
// return "CYCLING"
|
|
376
|
+
// case let .walking(sub):
|
|
377
|
+
// if sub.isEmpty {
|
|
378
|
+
// return "WALKING"
|
|
379
|
+
// } else {
|
|
380
|
+
// return service.debugDescription
|
|
381
|
+
// }
|
|
382
|
+
// case .places:
|
|
383
|
+
// return "PLACES"
|
|
384
|
+
// case .publicTransport:
|
|
385
|
+
// return "PUBLIC_TRANSPORT"
|
|
386
|
+
// case .pointsOfInterest:
|
|
387
|
+
// return "POINTS_OF_INTEREST"
|
|
388
|
+
// case .automaticImpactDetection:
|
|
389
|
+
// return "AUTOMATIC_IMPACT_DETECTION"
|
|
390
|
+
// case .assistanceCall:
|
|
391
|
+
// return "ASSISTANCE_CALL"
|
|
392
|
+
// @unknown default:
|
|
393
|
+
// return service.debugDescription
|
|
394
|
+
// }
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
func convert(failures: [DolphinMoveSDK.MoveServiceFailure]) -> [MoveSDKErrorListItem] {
|
|
398
|
+
var converted: [MoveSDKErrorListItem] = []
|
|
399
|
+
|
|
400
|
+
for failure in failures {
|
|
401
|
+
var reasons: [String] = []
|
|
402
|
+
switch failure.reason {
|
|
403
|
+
case let .missingPermission(permissions):
|
|
404
|
+
let content: [String] = permissions.map { self.permissionString($0) }
|
|
405
|
+
reasons = content
|
|
406
|
+
case .unauthorized:
|
|
407
|
+
reasons = ["Unauthorized"]
|
|
408
|
+
@unknown default:
|
|
409
|
+
break
|
|
410
|
+
}
|
|
411
|
+
converted.append(["service": convert(service: failure.service), "reasons": reasons])
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
return converted
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
func convert(warnings: [DolphinMoveSDK.MoveServiceWarning]) -> [MoveSDKErrorListItem] {
|
|
418
|
+
var converted: [MoveSDKErrorListItem] = []
|
|
419
|
+
|
|
420
|
+
for warning in warnings {
|
|
421
|
+
var reasons: [String] = []
|
|
422
|
+
switch warning.reason {
|
|
423
|
+
case let .missingPermission(permissions):
|
|
424
|
+
let content: [String] = permissions.map { self.permissionString($0) }
|
|
425
|
+
reasons = content
|
|
426
|
+
@unknown default:
|
|
427
|
+
break
|
|
428
|
+
}
|
|
429
|
+
converted.append(["service": convert(service: warning.service), "reasons": reasons])
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
return converted
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
func permissionString(_ permission: DolphinMoveSDK.MovePermission) -> String {
|
|
436
|
+
switch permission {
|
|
437
|
+
case .location:
|
|
438
|
+
return "LOCATION_PERMISSION_MISSING"
|
|
439
|
+
case .backgroundLocation:
|
|
440
|
+
return "BACKGROUND_PERMISSION_MISSING"
|
|
441
|
+
case .preciseLocation:
|
|
442
|
+
return "PRECISE_LOCATION_PERMISSION_MISSING"
|
|
443
|
+
case .motionActivity:
|
|
444
|
+
return "MOTION_PERMISSION_MISSING"
|
|
445
|
+
case .gyroscope:
|
|
446
|
+
return "GYROSCOPE_BROKEN"
|
|
447
|
+
case .accelerometer:
|
|
448
|
+
return "ACCELEROMETER_BROKEN"
|
|
449
|
+
@unknown default:
|
|
450
|
+
return "UNKNOWN"
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
internal func initIfPossibleWith(launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
|
|
455
|
+
self.launchOptions = launchOptions
|
|
456
|
+
MoveSDK.shared.initialize(launchOptions: launchOptions)
|
|
457
|
+
|
|
458
|
+
let oldConfig: OldConfig? = MoveSDKLauncher.decode(.config)
|
|
459
|
+
let oldAuth: OldAuth? = MoveSDKLauncher.decode(.auth)
|
|
460
|
+
|
|
461
|
+
/// migrate
|
|
462
|
+
if let oldAuth = oldAuth, let oldConfig = oldConfig {
|
|
463
|
+
let auth = DolphinMoveSDK.MoveAuth(userToken: oldAuth.userToken, refreshToken: oldAuth.refreshToken, userID: oldAuth.contractID, projectID: oldAuth.productID)
|
|
464
|
+
|
|
465
|
+
MoveSDK.shared.setup(auth: auth, config: oldConfig.convert())
|
|
466
|
+
MoveSDKLauncher.encode(nil as OldAuth?, forKey: .auth)
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
let isInRunningState = UserDefaults.standard.bool(forKey: "MOVE.WRAPPER.RUNNING")
|
|
470
|
+
if isInRunningState {
|
|
471
|
+
sdk.startAutomaticDetection()
|
|
472
|
+
UserDefaults.standard.removeObject(forKey: "MOVE.WRAPPER.RUNNING")
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
internal func performBackgroundFetch(_ completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
|
477
|
+
MoveSDK.shared.performBackgroundFetch(completionHandler)
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
internal func setup(auth: DolphinMoveSDK.MoveAuth, config: DolphinMoveSDK.MoveConfig) {
|
|
481
|
+
MoveSDK.shared.setup(auth: auth, config: config)
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
func shutdown() {
|
|
485
|
+
sdk.shutDown()
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
private static func decode<T>(_ key: DefaultsKey) -> T? where T: Decodable {
|
|
489
|
+
let decoder = PropertyListDecoder()
|
|
490
|
+
|
|
491
|
+
if let data = UserDefaults.standard.object(forKey: key.rawValue) as? Data {
|
|
492
|
+
return try? decoder.decode(T.self, from: data)
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return nil
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
private static func encode<T>(_ encodable: T?, forKey key: DefaultsKey) where T: Encodable {
|
|
499
|
+
if let encodable = encodable {
|
|
500
|
+
let encoder = PropertyListEncoder()
|
|
501
|
+
if let data = try? encoder.encode(encodable) {
|
|
502
|
+
UserDefaults.standard.set(data, forKey: key.rawValue)
|
|
503
|
+
}
|
|
504
|
+
} else {
|
|
505
|
+
UserDefaults.standard.removeObject(forKey: key.rawValue)
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
struct OldAuth: Codable {
|
|
511
|
+
var userToken: String
|
|
512
|
+
var refreshToken: String
|
|
513
|
+
var contractID: String
|
|
514
|
+
var productID: Int64
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
struct OldConfig: Codable {
|
|
518
|
+
/// Expresses modes of transport to be detected
|
|
519
|
+
enum TimelineDetectionService: Int, Codable {
|
|
520
|
+
/// Detect driving behaviour
|
|
521
|
+
case driving = 1
|
|
522
|
+
|
|
523
|
+
/// Detect cycling behaviour
|
|
524
|
+
case bicycle = 2
|
|
525
|
+
|
|
526
|
+
/// Detect walking behaviour
|
|
527
|
+
case walking = 3
|
|
528
|
+
|
|
529
|
+
/// Detect visits
|
|
530
|
+
case places = 4
|
|
531
|
+
|
|
532
|
+
case publicTransport = 5
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/// Expresses driving services to be detected
|
|
536
|
+
enum DrivingService: Int, Codable {
|
|
537
|
+
/// Detect distraction free driving
|
|
538
|
+
case dfd = 101
|
|
539
|
+
|
|
540
|
+
/// Detect driving behaviour
|
|
541
|
+
case behaviour = 102
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/// Expresses walking services to be detected
|
|
545
|
+
enum WalkingService: Int, Codable {
|
|
546
|
+
/// Detects GPS location for collected walking events
|
|
547
|
+
case location = 301
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/// Expresses other services to be detected
|
|
551
|
+
enum OtherService: Int, Codable {
|
|
552
|
+
/// Monitor points of intrest
|
|
553
|
+
case poi = 401
|
|
554
|
+
case impact = 402
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
var timelineDetectionService: [TimelineDetectionService]
|
|
558
|
+
var drivingServices: [DrivingService]
|
|
559
|
+
var walkingServices: [WalkingService]
|
|
560
|
+
var otherServices: [OtherService]
|
|
561
|
+
var tripStatusUpdateFrequency: Double = -1
|
|
562
|
+
|
|
563
|
+
func convert() -> DolphinMoveSDK.MoveConfig {
|
|
564
|
+
let driving: [DolphinMoveSDK.MoveConfig.DrivingService] = drivingServices.map {
|
|
565
|
+
switch $0 {
|
|
566
|
+
case .behaviour:
|
|
567
|
+
return .drivingBehavior
|
|
568
|
+
case .dfd:
|
|
569
|
+
return .distractionFreeDriving
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
let walking: [DolphinMoveSDK.MoveConfig.WalkingService] = walkingServices.map {
|
|
574
|
+
switch $0 {
|
|
575
|
+
case .location:
|
|
576
|
+
return .location
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
let services: [DolphinMoveSDK.MoveConfig.DetectionService] = timelineDetectionService.map {
|
|
581
|
+
switch $0 {
|
|
582
|
+
|
|
583
|
+
case .driving:
|
|
584
|
+
return .driving(driving)
|
|
585
|
+
case .bicycle:
|
|
586
|
+
return .cycling
|
|
587
|
+
case .walking:
|
|
588
|
+
return .walking(walking)
|
|
589
|
+
case .places:
|
|
590
|
+
return .places
|
|
591
|
+
case .publicTransport:
|
|
592
|
+
return .publicTransport
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
let otherServices: [DolphinMoveSDK.MoveConfig.DetectionService] = otherServices.map {
|
|
597
|
+
switch $0 {
|
|
598
|
+
case .poi:
|
|
599
|
+
return .pointsOfInterest
|
|
600
|
+
case .impact:
|
|
601
|
+
return .automaticImpactDetection
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
return DolphinMoveSDK.MoveConfig(detectionService: services + otherServices)
|
|
606
|
+
}
|
|
607
|
+
}
|