react-native-move-sdk 2.13.0 → 2.14.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 (89) hide show
  1. package/android/build.gradle.kts +42 -0
  2. package/android/gradle.properties +16 -6
  3. package/android/settings.gradle.kts +35 -0
  4. package/android/src/{main/java/in/dolph/move/sdk → legacy}/MoveSdkModule.kt +30 -195
  5. package/android/src/main/AndroidManifest.xml +1 -11
  6. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/DeviceScanner.kt +19 -21
  7. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/Mapper.kt +3 -2
  8. package/android/src/main/java/com/movesdk/MoveExtensions.kt +188 -0
  9. package/android/src/main/java/{in/dolph/move/sdk/MoveSdkRepository.kt → com/movesdk/MoveSdkConfigRepository.kt} +3 -1
  10. package/android/src/main/java/com/movesdk/MoveSdkPackage.kt +32 -0
  11. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/NativeMoveSdkWrapper.kt +201 -61
  12. package/android/src/main/java/com/movesdk/extentions/ConnectionExt.kt +52 -0
  13. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/extentions/PermissionUtils.kt +1 -1
  14. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/extentions/SharedPreferencesExt.kt +1 -1
  15. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/metadata/MetadataStorage.kt +1 -1
  16. package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/metadata/MetadataStorageImpl.kt +2 -2
  17. package/android/src/main/java/com/movesdk/shared/Constants.kt +39 -0
  18. package/android/src/turbo/MoveSdkModule.kt +422 -0
  19. package/ios/MoveSdk.h +13 -0
  20. package/ios/MoveSdk.mm +717 -0
  21. package/ios/MoveSdk.swift +1022 -0
  22. package/ios/{NativeModule/MoveSdkDeviceScanner.swift → MoveSdkDeviceScanner.swift} +1 -1
  23. package/lib/commonjs/NativeMoveSdk.js +21 -0
  24. package/lib/commonjs/NativeMoveSdk.js.map +1 -0
  25. package/lib/commonjs/components/LazyMoveSdk.js +22 -41
  26. package/lib/commonjs/components/LazyMoveSdk.js.map +1 -1
  27. package/lib/commonjs/index.js +331 -25
  28. package/lib/commonjs/index.js.map +1 -1
  29. package/lib/commonjs/package.json +1 -0
  30. package/lib/module/NativeMoveSdk.js +17 -0
  31. package/lib/module/NativeMoveSdk.js.map +1 -0
  32. package/lib/module/components/LazyMoveSdk.js +15 -20
  33. package/lib/module/components/LazyMoveSdk.js.map +1 -1
  34. package/lib/module/index.js +337 -3
  35. package/lib/module/index.js.map +1 -1
  36. package/lib/module/package.json +1 -0
  37. package/lib/typescript/commonjs/example/src/App.d.ts +2 -0
  38. package/lib/typescript/commonjs/example/src/App.d.ts.map +1 -0
  39. package/lib/typescript/commonjs/package.json +1 -0
  40. package/lib/typescript/commonjs/src/NativeMoveSdk.d.ts +138 -0
  41. package/lib/typescript/commonjs/src/NativeMoveSdk.d.ts.map +1 -0
  42. package/lib/typescript/{components → commonjs/src/components}/LazyMoveSdk.d.ts +2 -1
  43. package/lib/typescript/commonjs/src/components/LazyMoveSdk.d.ts.map +1 -0
  44. package/lib/typescript/commonjs/src/index.d.ts +84 -0
  45. package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
  46. package/lib/typescript/module/example/src/App.d.ts +2 -0
  47. package/lib/typescript/module/example/src/App.d.ts.map +1 -0
  48. package/lib/typescript/module/package.json +1 -0
  49. package/lib/typescript/module/src/NativeMoveSdk.d.ts +138 -0
  50. package/lib/typescript/module/src/NativeMoveSdk.d.ts.map +1 -0
  51. package/lib/typescript/module/src/components/LazyMoveSdk.d.ts +8 -0
  52. package/lib/typescript/module/src/components/LazyMoveSdk.d.ts.map +1 -0
  53. package/lib/typescript/module/src/index.d.ts +84 -0
  54. package/lib/typescript/module/src/index.d.ts.map +1 -0
  55. package/package.json +197 -138
  56. package/react-native-move-sdk.podspec +30 -9
  57. package/src/NativeMoveSdk.ts +191 -0
  58. package/src/components/LazyMoveSdk.tsx +2 -2
  59. package/src/{MoveSdk.ts → index.tsx} +131 -199
  60. package/android/.project +0 -17
  61. package/android/build.gradle +0 -153
  62. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  63. package/android/gradle/wrapper/gradle-wrapper.properties +0 -8
  64. package/android/gradlew +0 -183
  65. package/android/gradlew.bat +0 -100
  66. package/android/src/main/java/in/dolph/move/sdk/MoveExtensions.kt +0 -72
  67. package/android/src/main/java/in/dolph/move/sdk/MoveSdkPackage.kt +0 -19
  68. package/android/src/main/java/in/dolph/move/sdk/WrapperBtConnectionsReceiver.kt +0 -99
  69. package/android/src/main/res/drawable-anydpi-v24/ic_notification.xml +0 -13
  70. package/android/src/main/res/drawable-hdpi/ic_notification.png +0 -0
  71. package/android/src/main/res/drawable-mdpi/ic_notification.png +0 -0
  72. package/android/src/main/res/drawable-xhdpi/ic_notification.png +0 -0
  73. package/android/src/main/res/drawable-xxhdpi/ic_notification.png +0 -0
  74. package/android/src/main/res/values/strings.xml +0 -9
  75. package/android/src/main/strings.xml +0 -0
  76. package/android/src/test/java/io/dolphin/move/MoveWrapperTest.kt +0 -190
  77. package/ios/MoveSdk-Bridging-Header.h +0 -3
  78. package/ios/MoveSdk.xcodeproj/project.pbxproj +0 -287
  79. package/ios/MoveSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -4
  80. package/ios/MoveSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  81. package/ios/NativeModule/MoveSdk.h +0 -144
  82. package/ios/NativeModule/MoveSdk.swift +0 -1359
  83. package/lib/commonjs/MoveSdk.js +0 -443
  84. package/lib/commonjs/MoveSdk.js.map +0 -1
  85. package/lib/module/MoveSdk.js +0 -432
  86. package/lib/module/MoveSdk.js.map +0 -1
  87. package/lib/typescript/MoveSdk.d.ts +0 -158
  88. package/lib/typescript/index.d.ts +0 -3
  89. package/src/index.ts +0 -3
@@ -0,0 +1,188 @@
1
+ package com.movesdk
2
+
3
+ import android.content.Context
4
+ import android.os.PowerManager
5
+ import android.util.Log
6
+ import com.facebook.react.bridge.Arguments
7
+ import com.facebook.react.bridge.ReactApplicationContext
8
+ import com.facebook.react.bridge.WritableArray
9
+ import com.facebook.react.bridge.WritableMap
10
+ import com.facebook.react.modules.core.DeviceEventManagerModule
11
+ import com.google.gson.Gson
12
+ import io.dolphin.move.MoveDetectionService
13
+ import java.util.Locale
14
+ import java.util.regex.Pattern
15
+
16
+ /**
17
+ * https://stackoverflow.com/questions/60010298/how-can-i-convert-a-camel-case-string-to-snake-case-and-back-in-idiomatic-kotlin
18
+ */
19
+
20
+ val camelRegex = "(?<=[a-zA-Z])[A-Z]".toRegex()
21
+ val snakeRegex = "_[a-zA-Z]".toRegex()
22
+
23
+ // String extensions
24
+ fun String.camelToSnakeCase(): String {
25
+ return camelRegex.replace(this) {
26
+ "_${it.value}"
27
+ }.uppercase(Locale.getDefault())
28
+ }
29
+
30
+ fun String.toSnakeCase(): String {
31
+ return if (Pattern.compile(".*[a-z].*").matcher(this).find()) {
32
+ camelRegex.replace(this) {
33
+ "_${it.value}"
34
+ }.uppercase(Locale.getDefault()).replace("-", "_")
35
+ } else {
36
+ uppercase()
37
+ }
38
+ }
39
+
40
+ fun String.snakeToUpperCamelCase(): String {
41
+ val camelCase = StringBuilder()
42
+ var prevChar = '_'
43
+ forEach {
44
+ if (prevChar == '_') {
45
+ camelCase.append(it.uppercase())
46
+ } else if (it != '_') {
47
+ camelCase.append(it.lowercaseChar())
48
+ }
49
+ prevChar = it
50
+ }
51
+ return camelCase.toString()
52
+ }
53
+
54
+ fun String.snakeToUpperCamelCaseParam(): String {
55
+ val camelCase = StringBuilder()
56
+ var prevChar = '_'
57
+ forEachIndexed { index, c ->
58
+ if (index == 0) {
59
+ camelCase.append(c.lowercaseChar())
60
+ }else if (prevChar == '_') {
61
+ camelCase.append(c.uppercase())
62
+ } else if (c != '_') {
63
+ camelCase.append(c.lowercaseChar())
64
+ }
65
+ prevChar = c
66
+ }
67
+ return camelCase.toString()
68
+ }
69
+
70
+ fun String.equalsService(service: MoveDetectionService): Boolean {
71
+ return equals(service.name().camelToSnakeCase(), ignoreCase = true)
72
+ }
73
+
74
+ inline fun <reified T> T.toJsonString(): String {
75
+ return try {
76
+ Gson().toJson(this)
77
+ } catch (e: Exception) {
78
+ ""
79
+ }
80
+ }
81
+
82
+ fun Array<*>.toWritableArray(): WritableArray {
83
+ val data: WritableArray = Arguments.createArray()
84
+ for (value in iterator()) {
85
+ when (value) {
86
+ is String -> {
87
+ data.pushString(value)
88
+ }
89
+
90
+ is Boolean -> {
91
+ data.pushBoolean(value)
92
+ }
93
+
94
+ is Int -> {
95
+ data.pushInt(value)
96
+ }
97
+
98
+ is Array<*> -> {
99
+ data.pushArray(value.toWritableArray())
100
+ }
101
+
102
+ is List<*> -> {
103
+ data.pushArray(value.toTypedArray().toWritableArray())
104
+ }
105
+
106
+ is Map<*, *> -> {
107
+ data.pushMap(value.toWritableMap())
108
+ }
109
+ }
110
+ }
111
+ return data
112
+ }
113
+
114
+ fun Map<*, *>.toWritableMap(): WritableMap {
115
+ val data: WritableMap = Arguments.createMap()
116
+ for (entry in iterator()) {
117
+ val value = entry.value
118
+ print("${entry.key} : $value")
119
+ when (value) {
120
+ is String -> {
121
+ data.putString(entry.key.toString(), value)
122
+ }
123
+
124
+ is Boolean -> {
125
+ data.putBoolean(entry.key.toString(), value)
126
+ }
127
+
128
+ is Int -> {
129
+ data.putInt(entry.key.toString(), value)
130
+ }
131
+
132
+ is Array<*> -> {
133
+ data.putArray(entry.key.toString(), value.toWritableArray())
134
+ }
135
+
136
+ is List<*> -> {
137
+ data.putArray(entry.key.toString(), value.toTypedArray().toWritableArray())
138
+ }
139
+
140
+ is Map<*, *> -> {
141
+ data.putMap(entry.key.toString(), value.toWritableMap())
142
+ }
143
+ }
144
+ }
145
+ return data
146
+ }
147
+
148
+ fun Context.isAppIgnoringBatteryOptimization(): Boolean {
149
+ val packageName = packageName
150
+ val pm: PowerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
151
+ return pm.isIgnoringBatteryOptimizations(packageName)
152
+ }
153
+
154
+
155
+ internal fun ReactApplicationContext.emitDeviceArrayEvent(eventName: String, data: Array<Any>) {
156
+ try {
157
+ val eventData: WritableArray = data.toWritableArray()
158
+ getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
159
+ .emit(eventName.toSnakeCase(), eventData)
160
+ } catch (t: Throwable) {
161
+ Log.e("SDK Module", t.message, t)
162
+ // java.lang.IllegalStateException: Tried to access a JS module before the React instance was fully set up.
163
+ // Calls to ReactContext#getJSModule should only happen once initialize() has been called on your native module.
164
+ }
165
+ }
166
+
167
+ internal fun ReactApplicationContext.emitDeviceMapEvent(eventName: String, data: Map<*, *>) {
168
+ try {
169
+ val eventData: WritableMap = data.toWritableMap()
170
+ getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
171
+ .emit(eventName.toSnakeCase(), eventData)
172
+ } catch (t: Throwable) {
173
+ Log.e("SDK Module", t.message, t)
174
+ // java.lang.IllegalStateException: Tried to access a JS module before the React instance was fully set up.
175
+ // Calls to ReactContext#getJSModule should only happen once initialize() has been called on your native module.
176
+ }
177
+ }
178
+
179
+ internal fun ReactApplicationContext.emitDeviceStringEvent(eventName: String, data: String) {
180
+ try {
181
+ getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
182
+ .emit(eventName.toSnakeCase(), data)
183
+ } catch (t: Throwable) {
184
+ Log.e("SDK Module", t.message, t)
185
+ // java.lang.IllegalStateException: Tried to access a JS module before the React instance was fully set up.
186
+ // Calls to ReactContext#getJSModule should only happen once initialize() has been called on your native module.
187
+ }
188
+ }
@@ -1,4 +1,4 @@
1
- package `in`.dolph.move.sdk
1
+ package com.movesdk
2
2
 
3
3
  import android.content.Context
4
4
  import android.content.SharedPreferences
@@ -66,6 +66,8 @@ internal fun valueOfMoveDetectionService(
66
66
  MoveDetectionService.AssistanceCall
67
67
  } else if (it.equalsService(MoveDetectionService.AutomaticImpactDetection)) {
68
68
  MoveDetectionService.AutomaticImpactDetection
69
+ } else if (it.equalsService(MoveDetectionService.Health)) {
70
+ MoveDetectionService.Health
69
71
  } else {
70
72
  // default case?
71
73
  throw IllegalArgumentException("$it is not known, use one of " + MoveDetectionService::class.sealedSubclasses.joinToString { kClass ->
@@ -0,0 +1,32 @@
1
+ package com.movesdk
2
+
3
+ import com.movesdk.BuildConfig
4
+ import com.facebook.react.BaseReactPackage
5
+ import com.facebook.react.bridge.NativeModule
6
+ import com.facebook.react.bridge.ReactApplicationContext
7
+ import com.facebook.react.module.model.ReactModuleInfo
8
+ import com.facebook.react.module.model.ReactModuleInfoProvider
9
+
10
+ class MoveSdkPackage : BaseReactPackage() {
11
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
12
+ return if (name == MoveSdkModule.NAME) {
13
+ MoveSdkModule(reactContext)
14
+ } else {
15
+ null
16
+ }
17
+ }
18
+
19
+ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
20
+ mapOf(
21
+ MoveSdkModule.NAME to ReactModuleInfo(
22
+ name = MoveSdkModule.NAME,
23
+ className = MoveSdkModule.NAME,
24
+ canOverrideExistingModule = false,
25
+ needsEagerInit = false,
26
+ isCxxModule = false,
27
+ isTurboModule = BuildConfig.IS_TURBO_MODULE,
28
+ hasConstants = false,
29
+ )
30
+ )
31
+ }
32
+ }
@@ -1,18 +1,55 @@
1
- package `in`.dolph.move.sdk
1
+ package com.movesdk
2
2
 
3
3
  import android.annotation.SuppressLint
4
4
  import android.bluetooth.BluetoothManager
5
+ import android.content.ActivityNotFoundException
5
6
  import android.content.Context
7
+ import android.content.Intent
8
+ import android.net.Uri
6
9
  import android.os.Build
10
+ import android.provider.Settings
7
11
  import android.util.Log
12
+ import android.widget.Toast
13
+ import androidx.activity.result.ActivityResultLauncher
14
+ import androidx.health.connect.client.PermissionController
15
+ import androidx.health.connect.client.permission.HealthPermission
16
+ import androidx.health.connect.client.permission.HealthPermission.Companion.PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND
17
+ import androidx.health.connect.client.records.StepsRecord
18
+ import com.facebook.react.ReactActivity
19
+ import com.facebook.react.bridge.Callback
8
20
  import com.facebook.react.bridge.Promise
21
+ import com.facebook.react.bridge.ReactContext
9
22
  import com.facebook.react.bridge.ReadableArray
10
23
  import com.facebook.react.bridge.ReadableMap
11
24
  import com.google.gson.Gson
12
- import `in`.dolph.move.sdk.extentions.PermissionUtils
13
- import `in`.dolph.move.sdk.metadata.METADATA_PREF
14
- import `in`.dolph.move.sdk.metadata.MetadataStorage
15
- import `in`.dolph.move.sdk.metadata.MetadataStorageImpl
25
+ import com.movesdk.extentions.PermissionUtils
26
+ import com.movesdk.metadata.METADATA_PREF
27
+ import com.movesdk.metadata.MetadataStorage
28
+ import com.movesdk.metadata.MetadataStorageImpl
29
+ import com.movesdk.shared.ARGUMENT_ERROR
30
+ import com.movesdk.shared.ARGUMENT_ERRORS
31
+ import com.movesdk.shared.ARGUMENT_MOVE_HEALTH
32
+ import com.movesdk.shared.ARGUMENT_MOVE_SERVICES
33
+ import com.movesdk.shared.ARGUMENT_STATE
34
+ import com.movesdk.shared.ARGUMENT_WARNINGS
35
+ import com.movesdk.shared.BATTERY_OPTIMIZATION_REQUEST_CODE
36
+ import com.movesdk.shared.EVENT_AUTH_STATE
37
+ import com.movesdk.shared.EVENT_ERRORS
38
+ import com.movesdk.shared.EVENT_INIT_ERROR
39
+ import com.movesdk.shared.EVENT_MOVE_CONFIG_UPDATE
40
+ import com.movesdk.shared.EVENT_MOVE_DEVICES
41
+ import com.movesdk.shared.EVENT_MOVE_SCAN_RESULT
42
+ import com.movesdk.shared.EVENT_MOVE_SDK_APP
43
+ import com.movesdk.shared.EVENT_MOVE_SDK_DEVICE_STATE
44
+ import com.movesdk.shared.EVENT_MOVE_SDK_HEALTH
45
+ import com.movesdk.shared.EVENT_MOVE_SDK_LOG
46
+ import com.movesdk.shared.EVENT_MOVE_SDK_TRIP_START
47
+ import com.movesdk.shared.EVENT_MOVE_STATE
48
+ import com.movesdk.shared.EVENT_TRIP_STATE
49
+ import com.movesdk.shared.EVENT_WARNINGS
50
+ import com.movesdk.shared.LOG_TAG
51
+ import com.movesdk.shared.OVERLAY_REQUEST_CODE
52
+ import com.movesdk.shared.PROMISE_OK
16
53
  import io.dolphin.move.AuthSetupStatus
17
54
  import io.dolphin.move.DeviceDiscovery
18
55
  import io.dolphin.move.DrivingService
@@ -35,12 +72,13 @@ import io.dolphin.move.MoveServiceWarning
35
72
  import io.dolphin.move.MoveShutdownResult
36
73
  import io.dolphin.move.MoveTripState
37
74
  import io.dolphin.move.WalkingService
38
- import java.util.*
39
75
  import kotlinx.coroutines.CoroutineScope
40
76
  import kotlinx.coroutines.Dispatchers
41
77
  import kotlinx.coroutines.launch
42
78
  import kotlinx.coroutines.withContext
43
- import kotlin.collections.ArrayList
79
+ import java.util.Date
80
+ import java.util.Timer
81
+ import java.util.TimerTask
44
82
 
45
83
  @SuppressLint("StaticFieldLeak", "MissingPermission")
46
84
  class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener,
@@ -75,6 +113,15 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
75
113
  ),
76
114
  gson,
77
115
  )
116
+ private val timersHolder = mutableMapOf<String, Timer?>()
117
+ private var healthPermissionPromise: Promise? = null
118
+ private val permissions =
119
+ setOf(
120
+ HealthPermission.getReadPermission(StepsRecord::class),
121
+ PERMISSION_READ_HEALTH_DATA_IN_BACKGROUND,
122
+ )
123
+ private var requestPermissionsLauncher: ActivityResultLauncher<Set<String>>? = null
124
+
78
125
  fun init(context: Context) {
79
126
  val moveSdk = MoveSdk.init(context.applicationContext)
80
127
 
@@ -94,25 +141,6 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
94
141
 
95
142
  moveSdk.setDeviceStateListener(this)
96
143
  moveSdk.setMoveHealthScoreListener(this)
97
-
98
- // Initialize notifications by default (might be overwritten by setup)
99
- // TODO remove notification setup in init when VIG1-1620 will be fixed
100
- /* val config: MoveSdkConfig = configRepository.loadConfig()
101
- try {
102
- moveSdk.recognitionNotification(config.recognitionNotification.toAndroidNotification(context))
103
- moveSdk.tripNotification(config.tripNotification.toAndroidNotification(context))
104
- } catch (t: Throwable) {
105
- *//**
106
- * TODO Find cause, maybe channelID 0?
107
- * Caused by: java.lang.IllegalArgumentException
108
- at android.os.Parcel.createExceptionOrNull(Parcel.java:2429)
109
- at android.os.Parcel.createException(Parcel.java:2409)
110
- at android.os.Parcel.readException(Parcel.java:2392)
111
- at android.os.Parcel.readException(Parcel.java:2334)
112
- at android.app.INotificationManager$Stub$Proxy.createNotificationChannels(INotificationManager.java:3933)
113
- *//*
114
- }
115
- */
116
144
  }
117
145
 
118
146
  fun allowMockLocations(allowMockLocations: Boolean) {
@@ -145,7 +173,11 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
145
173
  walkingServices.toArrayList().forEach {
146
174
  val serviceName = if (it == "WALKING_LOCATION") "LOCATION" else it
147
175
  try {
148
- walkingServicesToUse.add(WalkingService.valueOf(serviceName.toString().snakeToUpperCamelCase()))
176
+ walkingServicesToUse.add(
177
+ WalkingService.valueOf(
178
+ serviceName.toString().snakeToUpperCamelCase()
179
+ )
180
+ )
149
181
  } catch (t: Throwable) {
150
182
  t.printStackTrace()
151
183
  }
@@ -172,7 +204,7 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
172
204
  val moveOptions = options?.let(::extractMoveOptions)
173
205
 
174
206
  try {
175
- Log.d(MoveSdkModule.LOG_TAG, "MOVE SDK Version " + MoveSdk.version)
207
+ Log.d(LOG_TAG, "MOVE SDK Version " + MoveSdk.version)
176
208
 
177
209
  val moveAuth = MoveAuth(
178
210
  userId = userId,
@@ -200,7 +232,7 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
200
232
  promise?.resolve(PROMISE_OK)
201
233
  } catch (t: Throwable) {
202
234
  val message = "SETUP_ERROR: ${t.message}"
203
- Log.e(MoveSdkModule.LOG_TAG, message, t)
235
+ Log.e(LOG_TAG, message, t)
204
236
  emitDeviceEvent(EVENT_MOVE_SDK_APP, message)
205
237
  promise?.reject(Exception(message))
206
238
  }
@@ -229,7 +261,11 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
229
261
  walkingServices.toArrayList().forEach {
230
262
  val serviceName = if (it == "WALKING_LOCATION") "LOCATION" else it
231
263
  try {
232
- walkingServicesToUse.add(WalkingService.valueOf(serviceName.toString().snakeToUpperCamelCase()))
264
+ walkingServicesToUse.add(
265
+ WalkingService.valueOf(
266
+ serviceName.toString().snakeToUpperCamelCase()
267
+ )
268
+ )
233
269
  } catch (t: Throwable) {
234
270
  t.printStackTrace()
235
271
  }
@@ -257,7 +293,8 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
257
293
  val moveOptions = try {
258
294
  val motionPermissionMandatory = featureOptions?.get("motionPermissionMandatory") as? Boolean
259
295
  val useBackendConfig = featureOptions?.get("useBackendConfig") as? Boolean
260
- val backgroundLocationPermissionMandatory = featureOptions?.get("backgroundLocationPermissionMandatory") as? Boolean
296
+ val backgroundLocationPermissionMandatory =
297
+ featureOptions?.get("backgroundLocationPermissionMandatory") as? Boolean
261
298
  val overlayPermissionMandatory = featureOptions?.get("overlayPermissionMandatory") as? Boolean
262
299
  val deviceDiscovery = featureOptions?.get("deviceDiscovery") as? Map<String, Any>
263
300
  val startDelay = deviceDiscovery?.get("startDelay") as? Double
@@ -277,12 +314,12 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
277
314
  ),
278
315
  )
279
316
  } catch (e: Exception) {
280
- Log.e(MoveSdkModule.LOG_TAG, "setup: ${e.message}", e)
317
+ Log.e(LOG_TAG, "setup: ${e.message}", e)
281
318
  null
282
319
  }
283
320
 
284
321
  try {
285
- Log.d(MoveSdkModule.LOG_TAG, "MOVE SDK Version " + MoveSdk.version)
322
+ Log.d(LOG_TAG, "MOVE SDK Version " + MoveSdk.version)
286
323
 
287
324
  MoveSdk.get()?.setNotificationText(
288
325
  notification = MoveNotification(
@@ -305,6 +342,7 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
305
342
  AuthSetupStatus.SUCCESS -> {
306
343
  promise?.resolve(PROMISE_OK)
307
344
  }
345
+
308
346
  AuthSetupStatus.INVALID_CODE,
309
347
  AuthSetupStatus.NETWORK_ERROR -> promise?.reject(Exception(result.status.name))
310
348
  }
@@ -313,7 +351,7 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
313
351
  )
314
352
  } catch (t: Throwable) {
315
353
  val message = "SETUP_ERROR: ${t.message}"
316
- Log.e(MoveSdkModule.LOG_TAG, message, t)
354
+ Log.e(LOG_TAG, message, t)
317
355
  emitDeviceEvent(EVENT_MOVE_SDK_APP, message)
318
356
  promise?.reject(Exception(message))
319
357
  }
@@ -352,8 +390,14 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
352
390
  }
353
391
  }
354
392
 
355
- fun getErrors(): List<MoveServiceFailure>? {
356
- return MoveSdk.get()?.getServiceErrors()
393
+ fun getErrors(promise: Promise?) {
394
+ mainScope.launch {
395
+ val errors: List<MoveServiceFailure>
396
+ withContext(ioContext) {
397
+ errors = MoveSdk.get()?.getServiceErrors() ?: emptyList()
398
+ }
399
+ promise?.resolve(errors.failuresToArray().toWritableArray())
400
+ }
357
401
  }
358
402
 
359
403
  fun getWarnings(): List<MoveServiceWarning>? {
@@ -443,7 +487,7 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
443
487
  data.putString(ARGUMENT_ERROR_REASON, state.reason.toString())
444
488
  }**/
445
489
  emitDeviceEvent(EVENT_MOVE_STATE, data)
446
- Log.d(MoveSdkModule.LOG_TAG, "Move SDK $state")
490
+ Log.d(LOG_TAG, "Move SDK $state")
447
491
  }
448
492
 
449
493
  override fun onTripStateChanged(tripState: MoveTripState) {
@@ -630,18 +674,18 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
630
674
  }
631
675
 
632
676
  // TODO uncomment when will be fixed VIG1-1620
633
- /* private fun getIconIdByName(name: String?): Int? {
634
- Log.i("MissingNotifications", "getIconIdByName name = $name")
635
- name ?: return null
636
- val packageName = context.packageName
637
- return try {
638
- val resource = context.resources.getIdentifier(name, "drawable", packageName).takeIf { it != 0 }
639
- Log.i("MissingNotifications", "getIdentifier resource = $resource")
640
- resource
641
- } catch (e: Exception) {
642
- null
643
- }
644
- }*/
677
+ /* private fun getIconIdByName(name: String?): Int? {
678
+ Log.i("MissingNotifications", "getIconIdByName name = $name")
679
+ name ?: return null
680
+ val packageName = context.packageName
681
+ return try {
682
+ val resource = context.resources.getIdentifier(name, "drawable", packageName).takeIf { it != 0 }
683
+ Log.i("MissingNotifications", "getIdentifier resource = $resource")
684
+ resource
685
+ } catch (e: Exception) {
686
+ null
687
+ }
688
+ }*/
645
689
 
646
690
  override fun onTripStarted(startDate: Date) {
647
691
  emitDeviceEvent(EVENT_MOVE_SDK_TRIP_START, startDate.time.toString())
@@ -660,7 +704,11 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
660
704
  walkingServices.toArrayList().forEach {
661
705
  val serviceName = if (it == "WALKING_LOCATION") "LOCATION" else it
662
706
  try {
663
- walkingServicesToUse.add(WalkingService.valueOf(serviceName.toString().snakeToUpperCamelCase()))
707
+ walkingServicesToUse.add(
708
+ WalkingService.valueOf(
709
+ serviceName.toString().snakeToUpperCamelCase()
710
+ )
711
+ )
664
712
  } catch (t: Throwable) {
665
713
  t.printStackTrace()
666
714
  }
@@ -713,23 +761,33 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
713
761
  fun isBluetoothEnabled(): Boolean {
714
762
  val adapter = context.getSystemService(BluetoothManager::class.java)?.adapter
715
763
  if (adapter == null) {
716
- Log.i(MoveSdkModule.LOG_TAG, "BluetoothManager is missing or BT adapter is null")
764
+ Log.i(LOG_TAG, "BluetoothManager is missing or BT adapter is null")
717
765
  }
718
766
  return adapter?.isEnabled == true
719
767
  }
768
+
720
769
  fun hasDiscoveryPermissions(): Boolean {
721
770
  var hasPermissions = true
722
771
  val hasBluetoothScanPermission = PermissionUtils.hasBluetoothScanPermission(context)
723
- Log.i(MoveSdkModule.LOG_TAG, "Discovery permission check: BluetoothScanPermission = $hasBluetoothScanPermission")
772
+ Log.i(
773
+ LOG_TAG,
774
+ "Discovery permission check: BluetoothScanPermission = $hasBluetoothScanPermission"
775
+ )
724
776
  hasPermissions = hasPermissions && hasBluetoothScanPermission
725
777
  if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) {
726
778
  val hasFineLocationPermission = PermissionUtils.hasFineLocationPermission(context)
727
- Log.i(MoveSdkModule.LOG_TAG, "Discovery permission check: FineLocationPermission = $hasFineLocationPermission")
779
+ Log.i(
780
+ LOG_TAG,
781
+ "Discovery permission check: FineLocationPermission = $hasFineLocationPermission"
782
+ )
728
783
  hasPermissions = hasPermissions && hasFineLocationPermission
729
784
  }
730
785
  if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R || Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
731
786
  val hasBackgroundLocationPermission = PermissionUtils.hasBackgroundLocationPermission(context)
732
- Log.i(MoveSdkModule.LOG_TAG, "Discovery permission check: BackgroundLocationPermission = $hasBackgroundLocationPermission")
787
+ Log.i(
788
+ LOG_TAG,
789
+ "Discovery permission check: BackgroundLocationPermission = $hasBackgroundLocationPermission"
790
+ )
733
791
  hasPermissions = hasPermissions && hasBackgroundLocationPermission
734
792
  }
735
793
  return hasPermissions
@@ -750,10 +808,85 @@ class NativeMoveSdkWrapper(private val context: Context) : MoveSdk.StateListener
750
808
  health.add(healthItem)
751
809
  data[ARGUMENT_MOVE_HEALTH] = health
752
810
  emitDeviceEvent(EVENT_MOVE_SDK_HEALTH, data)
753
- Log.d(MoveSdkModule.LOG_TAG, "onMoveHealthScoreChanged $data")
811
+ Log.d(LOG_TAG, "onMoveHealthScoreChanged $data")
754
812
  }
755
813
  } catch (e: Exception) {
756
- Log.e(MoveSdkModule.LOG_TAG, "Exception in Health listener", e)
814
+ Log.e(LOG_TAG, "Exception in Health listener", e)
815
+ }
816
+ }
817
+
818
+ fun setTimer(delay: Int? = 0, key: String, callback: Callback) {
819
+ try {
820
+ val timer = timersHolder[key]
821
+ timer?.cancel()
822
+ Timer().also {
823
+ timersHolder[key] = it
824
+ it.schedule(
825
+ object : TimerTask() {
826
+ override fun run() {
827
+ callback.invoke()
828
+ }
829
+ },
830
+ delay?.toLong() ?: 0L,
831
+ )
832
+ }
833
+ } catch (e: Exception) {
834
+ // Do nothing
835
+ }
836
+ }
837
+
838
+ fun cancelTimer(key: String?) {
839
+ key ?: return
840
+ try {
841
+ timersHolder[key]?.cancel()
842
+ } catch (e: Exception) {
843
+ Log.i("cancelTimer", "error: ${e.message}")
844
+ }
845
+ }
846
+
847
+ fun requestDrawOverlaysPermission(context: ReactContext) {
848
+ val intent = Intent(
849
+ Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
850
+ Uri.parse("package:${context.packageName}")
851
+ )
852
+ context.currentActivity!!.startActivityForResult(intent, OVERLAY_REQUEST_CODE)
853
+ }
854
+
855
+ fun requestAppIgnoringBatteryOptimization(context: ReactContext) {
856
+ val intent = Intent(
857
+ Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS,
858
+ Uri.parse("package:" + context.packageName)
859
+ )
860
+ context.currentActivity?.startActivityForResult(intent, BATTERY_OPTIMIZATION_REQUEST_CODE)
861
+ }
862
+
863
+ fun registerRequestPermissionLauncher(activity: ReactActivity) {
864
+ val requestPermissionActivityContract =
865
+ PermissionController.createRequestPermissionResultContract()
866
+ requestPermissionsLauncher =
867
+ activity.registerForActivityResult(requestPermissionActivityContract) { granted ->
868
+ if (granted.containsAll(permissions)) {
869
+ Log.d(LOG_TAG, "Health connect permission has been granted")
870
+ MoveSdk.get()?.resolveError()
871
+ healthPermissionPromise?.resolve(true)
872
+ } else {
873
+ Log.d(LOG_TAG, "Health connect permission NOT granted")
874
+ healthPermissionPromise?.reject(Throwable("Granted: $granted"))
875
+ }
876
+ healthPermissionPromise = null
877
+ }
878
+ }
879
+
880
+ fun requestHealthPermissions(promise: Promise?) {
881
+ healthPermissionPromise = promise
882
+ try {
883
+ requestPermissionsLauncher?.launch(permissions)
884
+ } catch (e: ActivityNotFoundException) {
885
+ Log.w(LOG_TAG, "No Activity found to handle Intent.\n Install Health connect")
886
+ promise?.reject(Throwable("Install Health connect!"))
887
+ } catch (e: Exception) {
888
+ Log.w(LOG_TAG, e.message, e)
889
+ promise?.reject(e)
757
890
  }
758
891
  }
759
892
  }
@@ -762,16 +895,19 @@ fun List<MoveServiceFailure>.failuresToArray(): Array<Any> {
762
895
  val data = mutableListOf<Any>()
763
896
  forEach {
764
897
  val map = mutableMapOf<String, Any>()
765
- val serviceName = when(val nativeService = it.service) {
898
+ val serviceName = when (val nativeService = it.service) {
766
899
  is MoveDetectionService.Driving ->
767
- nativeService.drivingServices?.firstOrNull()?.name?.toSnakeCase() ?: nativeService.name().toSnakeCase()
768
- is MoveDetectionService.Walking ->{
900
+ nativeService.drivingServices?.firstOrNull()?.name?.toSnakeCase() ?: nativeService.name()
901
+ .toSnakeCase()
902
+
903
+ is MoveDetectionService.Walking -> {
769
904
  if (nativeService.walkingServices?.isNotEmpty() == true) {
770
905
  "WALKING_LOCATION"
771
906
  } else {
772
907
  nativeService.name().toSnakeCase()
773
908
  }
774
909
  }
910
+
775
911
  else -> nativeService.name().toSnakeCase()
776
912
  }
777
913
  map["service"] = serviceName
@@ -786,9 +922,11 @@ fun List<MoveServiceWarning>.warningsToArray(): Array<Any> {
786
922
  val data = mutableListOf<Any>()
787
923
  forEach {
788
924
  val map = mutableMapOf<String, Any?>()
789
- val serviceName = when(val nativeService = it.service) {
925
+ val serviceName = when (val nativeService = it.service) {
790
926
  is MoveDetectionService.Driving ->
791
- nativeService.drivingServices?.firstOrNull()?.name?.toSnakeCase() ?: nativeService.name().toSnakeCase()
927
+ nativeService.drivingServices?.firstOrNull()?.name?.toSnakeCase() ?: nativeService.name()
928
+ .toSnakeCase()
929
+
792
930
  is MoveDetectionService.Walking -> {
793
931
  if (nativeService.walkingServices?.isNotEmpty() == true) {
794
932
  "WALKING_LOCATION"
@@ -796,6 +934,7 @@ fun List<MoveServiceWarning>.warningsToArray(): Array<Any> {
796
934
  nativeService.name().toSnakeCase()
797
935
  }
798
936
  }
937
+
799
938
  else -> nativeService?.name()?.toSnakeCase()
800
939
  }
801
940
  map["service"] = serviceName
@@ -805,3 +944,4 @@ fun List<MoveServiceWarning>.warningsToArray(): Array<Any> {
805
944
  }
806
945
  return data.toTypedArray()
807
946
  }
947
+