react-native-move-sdk 2.10.0 → 2.10.2

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.
@@ -1,12 +1,15 @@
1
1
  package `in`.dolph.move.sdk
2
2
 
3
3
  import android.annotation.SuppressLint
4
+ import android.bluetooth.BluetoothManager
4
5
  import android.content.Context
6
+ import android.os.Build
5
7
  import android.util.Log
6
8
  import com.facebook.react.bridge.Promise
7
9
  import com.facebook.react.bridge.ReadableArray
8
10
  import com.facebook.react.bridge.ReadableMap
9
11
  import com.google.gson.Gson
12
+ import `in`.dolph.move.sdk.extentions.PermissionUtils
10
13
  import `in`.dolph.move.sdk.metadata.METADATA_PREF
11
14
  import `in`.dolph.move.sdk.metadata.MetadataStorage
12
15
  import `in`.dolph.move.sdk.metadata.MetadataStorageImpl
@@ -21,6 +24,7 @@ import io.dolphin.move.MoveConfig
21
24
  import io.dolphin.move.MoveConfigurationError
22
25
  import io.dolphin.move.MoveDetectionService
23
26
  import io.dolphin.move.MoveDevice
27
+ import io.dolphin.move.MoveNotification
24
28
  import io.dolphin.move.MoveOptions
25
29
  import io.dolphin.move.MoveScanResult
26
30
  import io.dolphin.move.MoveSdk
@@ -128,14 +132,8 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
128
132
  // Platform config
129
133
  recognitionNotificationTitle: String,
130
134
  recognitionNotificationText: String,
131
- recognitionNotificationChannelId: String,
132
- recognitionNotificationChannelName: String,
133
- recognitionNotificationChannelDescription: String,
134
135
  tripNotificationTitle: String,
135
136
  tripNotificationText: String,
136
- tripNotificationChannelId: String,
137
- tripNotificationChannelName: String,
138
- tripNotificationChannelDescription: String,
139
137
  promise: Promise?
140
138
  ) {
141
139
 
@@ -169,28 +167,6 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
169
167
  )
170
168
  )
171
169
  }
172
- // TODO there was a bug on building local npm, fix it and uncomment
173
- // val recognitionNotificationIcon = getIconIdByName(recognitionIconName)
174
- // val tripNotificationIcon = getIconIdByName(tripIconName)
175
-
176
- val recognitionNotification = MoveNotificationConfig(
177
- recognitionNotificationTitle,
178
- recognitionNotificationText,
179
- null,
180
- recognitionNotificationChannelId,
181
- recognitionNotificationChannelName,
182
- recognitionNotificationChannelDescription,
183
- )
184
- val tripNotification = MoveNotificationConfig(
185
- tripNotificationTitle,
186
- tripNotificationText,
187
- null,
188
- tripNotificationChannelId,
189
- tripNotificationChannelName,
190
- tripNotificationChannelDescription,
191
- )
192
- // TODO - just use recognition notification for now
193
- val walkingNotification = recognitionNotification
194
170
 
195
171
  val featureOptions = options?.toHashMap()
196
172
  val moveOptions = try {
@@ -229,11 +205,16 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
229
205
  refreshToken = refreshToken,
230
206
  projectId = projectId.toLong(),
231
207
  )
232
- MoveSdk.get()?.let {
233
- it.tripNotification(tripNotification.toMoveNotification(context))
234
- it.recognitionNotification(recognitionNotification.toMoveNotification(context))
235
- it.walkingLocationNotification(walkingNotification.toMoveNotification(context))
236
- }
208
+ MoveSdk.get()?.setNotificationText(
209
+ notification = MoveNotification(
210
+ recognitionTitle = recognitionNotificationTitle,
211
+ recognitionText = recognitionNotificationText,
212
+ drivingTitle = tripNotificationTitle,
213
+ drivingText = tripNotificationText,
214
+ walkingTitle = recognitionNotificationTitle,
215
+ walkingText = recognitionNotificationText
216
+ )
217
+ )
237
218
  val moveConfig = MoveConfig(timelineDetectionServicesToUse)
238
219
  MoveSdk.setup(
239
220
  auth = moveAuth,
@@ -241,15 +222,6 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
241
222
  options = moveOptions,
242
223
  )
243
224
 
244
- val moveSdkConfig = MoveSdkConfig(
245
- timelineDetectionServices = timelineDetectionServicesToUse,
246
- auth = moveAuth,
247
- recognitionNotification = recognitionNotification,
248
- tripNotification = tripNotification,
249
- walkingNotification = walkingNotification
250
- )
251
- configRepository.storeConfig(moveSdkConfig)
252
-
253
225
  promise?.resolve(PROMISE_OK)
254
226
  } catch (t: Throwable) {
255
227
  val message = "SETUP_ERROR: ${t.message}"
@@ -270,14 +242,8 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
270
242
  // Platform config
271
243
  recognitionNotificationTitle: String,
272
244
  recognitionNotificationText: String,
273
- recognitionNotificationChannelId: String,
274
- recognitionNotificationChannelName: String,
275
- recognitionNotificationChannelDescription: String,
276
245
  tripNotificationTitle: String,
277
246
  tripNotificationText: String,
278
- tripNotificationChannelId: String,
279
- tripNotificationChannelName: String,
280
- tripNotificationChannelDescription: String,
281
247
  promise: Promise?
282
248
  ) {
283
249
 
@@ -311,28 +277,6 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
311
277
  )
312
278
  )
313
279
  }
314
- // TODO there was a bug on building local npm, fix it and uncomment
315
- // val recognitionNotificationIcon = getIconIdByName(recognitionIconName)
316
- // val tripNotificationIcon = getIconIdByName(tripIconName)
317
-
318
- val recognitionNotification = MoveNotificationConfig(
319
- recognitionNotificationTitle,
320
- recognitionNotificationText,
321
- null,
322
- recognitionNotificationChannelId,
323
- recognitionNotificationChannelName,
324
- recognitionNotificationChannelDescription,
325
- )
326
- val tripNotification = MoveNotificationConfig(
327
- tripNotificationTitle,
328
- tripNotificationText,
329
- null,
330
- tripNotificationChannelId,
331
- tripNotificationChannelName,
332
- tripNotificationChannelDescription,
333
- )
334
- // TODO - just use recognition notification for now
335
- val walkingNotification = recognitionNotification
336
280
 
337
281
  val featureOptions = options?.toHashMap()
338
282
  val moveOptions = try {
@@ -365,11 +309,16 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
365
309
  try {
366
310
  Log.d(MoveSdkModule.LOG_TAG, "MOVE SDK Version " + MoveSdk.version)
367
311
 
368
- MoveSdk.get()?.let {
369
- it.tripNotification(tripNotification.toMoveNotification(context))
370
- it.recognitionNotification(recognitionNotification.toMoveNotification(context))
371
- it.walkingLocationNotification(walkingNotification.toMoveNotification(context))
372
- }
312
+ MoveSdk.get()?.setNotificationText(
313
+ notification = MoveNotification(
314
+ recognitionTitle = recognitionNotificationTitle,
315
+ recognitionText = recognitionNotificationText,
316
+ drivingTitle = tripNotificationTitle,
317
+ drivingText = tripNotificationText,
318
+ walkingTitle = recognitionNotificationTitle,
319
+ walkingText = recognitionNotificationText
320
+ )
321
+ )
373
322
  val moveConfig = MoveConfig(timelineDetectionServicesToUse)
374
323
  MoveSdk.setup(
375
324
  authCode = code,
@@ -400,12 +349,10 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
400
349
  }
401
350
 
402
351
  fun startAutomaticDetection(): Boolean {
403
- configRepository.storeRunningState(true)
404
352
  return MoveSdk.get()?.startAutomaticDetection() == true
405
353
  }
406
354
 
407
355
  fun stopAutomaticDetection(): Boolean {
408
- configRepository.storeRunningState(false)
409
356
  return MoveSdk.get()?.stopAutomaticDetection() == true
410
357
  }
411
358
 
@@ -521,17 +468,7 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
521
468
  data.putString(ARGUMENT_ERROR_REASON, state.reason.toString())
522
469
  }**/
523
470
  emitDeviceEvent(EVENT_MOVE_STATE, data)
524
-
525
- if (state is MoveSdkState.Ready) {
526
- val isInRunningState = configRepository.loadRunningState()
527
- if (isInRunningState) {
528
- startAutomaticDetection()
529
- }
530
- } else if (state is MoveSdkState.Running) {
531
- Log.d(MoveSdkModule.LOG_TAG, "Move SDK Running")
532
- // Nothing to do here, all good.
533
- // You may call additional features like #keepInForeground(bool)
534
- }
471
+ Log.d(MoveSdkModule.LOG_TAG, "Move SDK $state")
535
472
  }
536
473
 
537
474
  override fun onTripStateChanged(tripState: MoveTripState) {
@@ -557,8 +494,6 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
557
494
  refreshToken = refreshToken,
558
495
  )
559
496
 
560
- configRepository.storeAuth(auth)
561
-
562
497
  MoveSdk.get()?.updateAuth(auth) { configurationError ->
563
498
  val data = mutableMapOf<Any, Any>()
564
499
  data[ARGUMENT_ERROR] = configurationError.toString()
@@ -605,10 +540,12 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
605
540
  }
606
541
 
607
542
  override fun onLogReceived(eventName: String, value: String?) {
608
- // TBD
609
543
  val data = mutableMapOf<Any, Any>()
610
- data[ARGUMENT_LOG] = "$eventName ${value ?: ""}".trim()
611
- emitDeviceEvent(EVENT_INIT_ERROR, data)
544
+ data["message"] = eventName.trim()
545
+ value?.let {
546
+ data["value"] = it.trim()
547
+ }
548
+ emitDeviceEvent(EVENT_MOVE_SDK_LOG, data)
612
549
  }
613
550
 
614
551
  override fun onMoveError(serviceFailures: List<MoveServiceFailure>) {
@@ -792,6 +729,31 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
792
729
  map["isConnected"] = device.isConnected
793
730
  emitDeviceEvent(EVENT_MOVE_SDK_DEVICE_STATE, map)
794
731
  }
732
+
733
+ fun isBluetoothEnabled(): Boolean {
734
+ val adapter = context.getSystemService(BluetoothManager::class.java)?.adapter
735
+ if (adapter == null) {
736
+ Log.i(MoveSdkModule.LOG_TAG, "BluetoothManager is missing or BT adapter is null")
737
+ }
738
+ return adapter?.isEnabled == true
739
+ }
740
+ fun hasDiscoveryPermissions(): Boolean {
741
+ var hasPermissions = true
742
+ val hasBluetoothScanPermission = PermissionUtils.hasBluetoothScanPermission(context)
743
+ Log.i(MoveSdkModule.LOG_TAG, "Discovery permission check: BluetoothScanPermission = $hasBluetoothScanPermission")
744
+ hasPermissions = hasPermissions && hasBluetoothScanPermission
745
+ if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
746
+ val hasFineLocationPermission = PermissionUtils.hasFineLocationPermission(context)
747
+ Log.i(MoveSdkModule.LOG_TAG, "Discovery permission check: FineLocationPermission = $hasFineLocationPermission")
748
+ hasPermissions = hasPermissions && hasFineLocationPermission
749
+ }
750
+ if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R || Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
751
+ val hasBackgroundLocationPermission = PermissionUtils.hasBackgroundLocationPermission(context)
752
+ Log.i(MoveSdkModule.LOG_TAG, "Discovery permission check: BackgroundLocationPermission = $hasBackgroundLocationPermission")
753
+ hasPermissions = hasPermissions && hasBackgroundLocationPermission
754
+ }
755
+ return hasPermissions
756
+ }
795
757
  }
796
758
 
797
759
  fun List<MoveServiceFailure>.failuresToArray(): Array<Any> {
@@ -0,0 +1,58 @@
1
+ package `in`.dolph.move.sdk.extentions
2
+
3
+ import android.Manifest
4
+ import android.content.Context
5
+ import android.content.pm.PackageManager
6
+ import android.os.Build
7
+ import androidx.core.content.ContextCompat
8
+
9
+ object PermissionUtils {
10
+
11
+ fun hasFineLocationPermission(context: Context?): Boolean {
12
+ return if (context != null) {
13
+ ContextCompat.checkSelfPermission(
14
+ context,
15
+ Manifest.permission.ACCESS_FINE_LOCATION
16
+ ) == PackageManager.PERMISSION_GRANTED
17
+ } else {
18
+ false
19
+ }
20
+ }
21
+
22
+ fun hasBluetoothScanPermission(context: Context): Boolean {
23
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
24
+ ContextCompat.checkSelfPermission(
25
+ context,
26
+ Manifest.permission.BLUETOOTH_SCAN
27
+ ) == PackageManager.PERMISSION_GRANTED
28
+ } else {
29
+ true
30
+ }
31
+ }
32
+
33
+ fun hasBackgroundLocationPermission(context: Context?): Boolean {
34
+ return if (context != null) {
35
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
36
+ ContextCompat.checkSelfPermission(
37
+ context,
38
+ Manifest.permission.ACCESS_BACKGROUND_LOCATION
39
+ ) == PackageManager.PERMISSION_GRANTED
40
+ } else {
41
+ true
42
+ }
43
+ } else {
44
+ false
45
+ }
46
+ }
47
+
48
+ fun hasBluetoothConnectPermission(context: Context): Boolean {
49
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
50
+ ContextCompat.checkSelfPermission(
51
+ context,
52
+ Manifest.permission.BLUETOOTH_CONNECT
53
+ ) == PackageManager.PERMISSION_GRANTED
54
+ } else {
55
+ true
56
+ }
57
+ }
58
+ }
@@ -134,4 +134,10 @@ RCT_EXTERN_METHOD(requestMotionPermission)
134
134
 
135
135
  RCT_EXTERN_METHOD(requestBluetoothAlwaysUsagePermission)
136
136
 
137
+ RCT_EXTERN_METHOD(getBluetoothPermission: (RCTPromiseResolveBlock)resolve
138
+ rejecter: (RCTPromiseRejectBlock)reject)
139
+
140
+ RCT_EXTERN_METHOD(getBluetoothState: (RCTPromiseResolveBlock)resolve
141
+ rejecter: (RCTPromiseRejectBlock)reject)
142
+
137
143
  @end
@@ -96,7 +96,7 @@ class RCTMoveSdk: RCTEventEmitter {
96
96
  /// Audio/iBeacon device scanner.
97
97
  private var scanner: MoveSdkDeviceScanner?
98
98
  /// Bluetooth manager for permission.
99
- private var bleManager: CBCentralManager?
99
+ lazy var bluetoothManager = MoveSdkBluetoothManager()
100
100
 
101
101
  override func startObserving() {
102
102
  MoveSDKLauncher.shared.delegate = self
@@ -469,7 +469,7 @@ class RCTMoveSdk: RCTEventEmitter {
469
469
  if MoveSDK.shared.startAutomaticDetection() {
470
470
  resolve(true)
471
471
  } else {
472
- reject("false", nil, nil)
472
+ resolve(false)
473
473
  }
474
474
  }
475
475
 
@@ -482,7 +482,7 @@ class RCTMoveSdk: RCTEventEmitter {
482
482
  if MoveSDK.shared.setLiveLocationTag(tag) {
483
483
  resolve(true)
484
484
  } else {
485
- reject("false", nil, nil)
485
+ resolve(false)
486
486
  }
487
487
  }
488
488
 
@@ -495,7 +495,7 @@ class RCTMoveSdk: RCTEventEmitter {
495
495
  if MoveSDK.shared.startTrip(metadata: data) {
496
496
  resolve(true)
497
497
  } else {
498
- reject("false", nil, nil)
498
+ resolve(false)
499
499
  }
500
500
  }
501
501
 
@@ -516,7 +516,7 @@ class RCTMoveSdk: RCTEventEmitter {
516
516
  if MoveSDK.shared.stopAutomaticDetection() {
517
517
  resolve(true)
518
518
  } else {
519
- reject("false", nil, nil)
519
+ resolve(false)
520
520
  }
521
521
  }
522
522
 
@@ -665,7 +665,53 @@ class RCTMoveSdk: RCTEventEmitter {
665
665
  /// Requests user bluetooth permission.
666
666
  @objc
667
667
  func requestBluetoothAlwaysUsagePermission() {
668
- bleManager = CBCentralManager()
668
+ bluetoothManager.getBluetoothState() { _ in }
669
+ }
670
+
671
+ @objc
672
+ func getBluetoothPermission(_ resolve: @escaping RCTPromiseResolveBlock,
673
+ rejecter _: @escaping RCTPromiseRejectBlock) {
674
+ bluetoothManager.getBluetoothState() { state in
675
+ switch state {
676
+ case .unknown:
677
+ resolve(false)
678
+ case .resetting:
679
+ resolve(false)
680
+ case .unsupported:
681
+ resolve(false)
682
+ case .unauthorized:
683
+ resolve(false)
684
+ case .poweredOff:
685
+ resolve(true)
686
+ case .poweredOn:
687
+ resolve(true)
688
+ @unknown default:
689
+ resolve(false)
690
+ }
691
+ }
692
+ }
693
+
694
+ @objc
695
+ func getBluetoothState(_ resolve: @escaping RCTPromiseResolveBlock,
696
+ rejecter reject: @escaping RCTPromiseRejectBlock) {
697
+ bluetoothManager.getBluetoothState() { state in
698
+ switch state {
699
+ case .unknown:
700
+ resolve(false)
701
+ case .resetting:
702
+ resolve(false)
703
+ case .unsupported:
704
+ resolve(false)
705
+ case .unauthorized:
706
+ resolve(false)
707
+ case .poweredOff:
708
+ resolve(false)
709
+ case .poweredOn:
710
+ resolve(true)
711
+ @unknown default:
712
+ resolve(false)
713
+ }
714
+ }
669
715
  }
670
716
 
671
717
  /// Delegates initialize with launch options to the launcher.
@@ -735,6 +781,8 @@ internal class MoveSDKLauncher {
735
781
  case configUpdate = "MOVE_SDK_CONFIG_UPDATE"
736
782
  /// SDK trip start event.
737
783
  case tripStart = "MOVE_SDK_TRIP_START"
784
+ /// Log event.
785
+ case logEvent = "MOVE_SDK_LOG"
738
786
  }
739
787
 
740
788
  /// User defaults kets.
@@ -828,8 +876,20 @@ internal class MoveSDKLauncher {
828
876
  self.tripMetaData = [:]
829
877
  return metadata
830
878
  }
879
+
880
+ sdk.setLogListener { (event, value) in
881
+ DispatchQueue.main.async {
882
+ var data: [String: Any] = ["message": event]
883
+
884
+ if let value = value {
885
+ data["value"] = value
886
+ }
887
+
888
+ self.send(event: .logEvent, data: data)
889
+ }
890
+ }
831
891
  }
832
-
892
+
833
893
  /// Send event to observer.
834
894
  /// - Parameters:
835
895
  /// - event: Event key.
@@ -1,4 +1,5 @@
1
1
  import AVFoundation
2
+ import CoreBluetooth
2
3
  import CoreLocation
3
4
  import Foundation
4
5
  import DolphinMoveSDK
@@ -119,3 +120,19 @@ extension MoveSdkDeviceScanner: CLLocationManagerDelegate {
119
120
  print("didDetermineState: \(region) : \(state)")
120
121
  }
121
122
  }
123
+
124
+ internal class MoveSdkBluetoothManager: NSObject, CBCentralManagerDelegate {
125
+
126
+ private var stateCallback: ((CBManagerState) -> Void)?
127
+ private var manager: CBCentralManager?
128
+
129
+ func getBluetoothState(_ callback: @escaping(CBManagerState) -> Void) {
130
+ stateCallback = callback
131
+ manager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: false])
132
+ }
133
+
134
+ func centralManagerDidUpdateState(_ central: CBCentralManager) {
135
+ stateCallback?(central.state)
136
+ stateCallback = nil
137
+ }
138
+ }
@@ -66,7 +66,7 @@ class MoveSdk {
66
66
  throw new Error('MOVE SDK needs notification configuration for Android');
67
67
  }
68
68
 
69
- platformParams = [recognitionNotification.title, recognitionNotification.text, recognitionNotification.channel.id, recognitionNotification.channel.name, recognitionNotification.channel.description, tripNotification.title, tripNotification.text, tripNotification.channel.id, tripNotification.channel.name, tripNotification.channel.description];
69
+ platformParams = [recognitionNotification.title, recognitionNotification.text, tripNotification.title, tripNotification.text];
70
70
  }
71
71
 
72
72
  return await NativeMoveSdk.setup(userId, accessToken, refreshToken, projectId, // Config
@@ -95,7 +95,7 @@ class MoveSdk {
95
95
  throw new Error('MOVE SDK needs notification configuration for Android');
96
96
  }
97
97
 
98
- platformParams = [recognitionNotification.title, recognitionNotification.text, recognitionNotification.channel.id, recognitionNotification.channel.name, recognitionNotification.channel.description, tripNotification.title, tripNotification.text, tripNotification.channel.id, tripNotification.channel.name, tripNotification.channel.description];
98
+ platformParams = [recognitionNotification.title, recognitionNotification.text, tripNotification.title, tripNotification.text];
99
99
  }
100
100
 
101
101
  return await NativeMoveSdk.setupWithCode(code, // Config
@@ -232,6 +232,12 @@ class MoveSdk {
232
232
  });
233
233
  }
234
234
 
235
+ static addLogListener(logReceived) {
236
+ return eventEmitter.addListener('MOVE_SDK_LOG', event => {
237
+ logReceived(event);
238
+ });
239
+ }
240
+
235
241
  static addRemoteConfigChangeListener(configChangeReceived) {
236
242
  return eventEmitter.addListener('MOVE_SDK_CONFIG_UPDATE', config => {
237
243
  configChangeReceived(config);
@@ -258,6 +264,14 @@ class MoveSdk {
258
264
  }
259
265
  }
260
266
 
267
+ static async getBluetoothPermission() {
268
+ return await NativeMoveSdk.getBluetoothPermission();
269
+ }
270
+
271
+ static async getBluetoothState() {
272
+ return await NativeMoveSdk.getBluetoothState();
273
+ }
274
+
261
275
  static async shutdown() {
262
276
  let force = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
263
277
  return await NativeMoveSdk.shutdown(force);