react-native-move-sdk 2.13.0 → 2.14.0-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/android/build.gradle.kts +42 -0
- package/android/gradle.properties +16 -6
- package/android/settings.gradle.kts +35 -0
- package/android/src/{main/java/in/dolph/move/sdk → legacy}/MoveSdkModule.kt +30 -195
- package/android/src/main/AndroidManifest.xml +1 -11
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/DeviceScanner.kt +19 -21
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/Mapper.kt +3 -2
- package/android/src/main/java/com/movesdk/MoveExtensions.kt +188 -0
- package/android/src/main/java/{in/dolph/move/sdk/MoveSdkRepository.kt → com/movesdk/MoveSdkConfigRepository.kt} +3 -1
- package/android/src/main/java/com/movesdk/MoveSdkPackage.kt +32 -0
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/NativeMoveSdkWrapper.kt +201 -61
- package/android/src/main/java/com/movesdk/extentions/ConnectionExt.kt +52 -0
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/extentions/PermissionUtils.kt +1 -1
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/extentions/SharedPreferencesExt.kt +1 -1
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/metadata/MetadataStorage.kt +1 -1
- package/android/src/main/java/{in/dolph/move/sdk → com/movesdk}/metadata/MetadataStorageImpl.kt +2 -2
- package/android/src/main/java/com/movesdk/shared/Constants.kt +39 -0
- package/android/src/turbo/MoveSdkModule.kt +422 -0
- package/ios/MoveSdk.h +13 -0
- package/ios/MoveSdk.mm +717 -0
- package/ios/MoveSdk.swift +1022 -0
- package/ios/{NativeModule/MoveSdkDeviceScanner.swift → MoveSdkDeviceScanner.swift} +1 -1
- package/lib/commonjs/NativeMoveSdk.js +21 -0
- package/lib/commonjs/NativeMoveSdk.js.map +1 -0
- package/lib/commonjs/components/LazyMoveSdk.js +22 -41
- package/lib/commonjs/components/LazyMoveSdk.js.map +1 -1
- package/lib/commonjs/index.js +331 -25
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/package.json +1 -0
- package/lib/module/NativeMoveSdk.js +17 -0
- package/lib/module/NativeMoveSdk.js.map +1 -0
- package/lib/module/components/LazyMoveSdk.js +15 -20
- package/lib/module/components/LazyMoveSdk.js.map +1 -1
- package/lib/module/index.js +337 -3
- package/lib/module/index.js.map +1 -1
- package/lib/module/package.json +1 -0
- package/lib/typescript/commonjs/example/src/App.d.ts +2 -0
- package/lib/typescript/commonjs/example/src/App.d.ts.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/NativeMoveSdk.d.ts +133 -0
- package/lib/typescript/commonjs/src/NativeMoveSdk.d.ts.map +1 -0
- package/lib/typescript/{components → commonjs/src/components}/LazyMoveSdk.d.ts +2 -1
- package/lib/typescript/commonjs/src/components/LazyMoveSdk.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +84 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/module/example/src/App.d.ts +2 -0
- package/lib/typescript/module/example/src/App.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/NativeMoveSdk.d.ts +133 -0
- package/lib/typescript/module/src/NativeMoveSdk.d.ts.map +1 -0
- package/lib/typescript/module/src/components/LazyMoveSdk.d.ts +8 -0
- package/lib/typescript/module/src/components/LazyMoveSdk.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +84 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/package.json +197 -138
- package/react-native-move-sdk.podspec +30 -9
- package/src/NativeMoveSdk.ts +227 -0
- package/src/components/LazyMoveSdk.tsx +2 -2
- package/src/{MoveSdk.ts → index.tsx} +131 -199
- package/android/.project +0 -17
- package/android/build.gradle +0 -153
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -8
- package/android/gradlew +0 -183
- package/android/gradlew.bat +0 -100
- package/android/src/main/java/in/dolph/move/sdk/MoveExtensions.kt +0 -72
- package/android/src/main/java/in/dolph/move/sdk/MoveSdkPackage.kt +0 -19
- package/android/src/main/java/in/dolph/move/sdk/WrapperBtConnectionsReceiver.kt +0 -99
- package/android/src/main/res/drawable-anydpi-v24/ic_notification.xml +0 -13
- package/android/src/main/res/drawable-hdpi/ic_notification.png +0 -0
- package/android/src/main/res/drawable-mdpi/ic_notification.png +0 -0
- package/android/src/main/res/drawable-xhdpi/ic_notification.png +0 -0
- package/android/src/main/res/drawable-xxhdpi/ic_notification.png +0 -0
- package/android/src/main/res/values/strings.xml +0 -9
- package/android/src/main/strings.xml +0 -0
- package/android/src/test/java/io/dolphin/move/MoveWrapperTest.kt +0 -190
- package/ios/MoveSdk-Bridging-Header.h +0 -3
- package/ios/MoveSdk.xcodeproj/project.pbxproj +0 -287
- package/ios/MoveSdk.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -4
- package/ios/MoveSdk.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/ios/NativeModule/MoveSdk.h +0 -144
- package/ios/NativeModule/MoveSdk.swift +0 -1359
- package/lib/commonjs/MoveSdk.js +0 -443
- package/lib/commonjs/MoveSdk.js.map +0 -1
- package/lib/module/MoveSdk.js +0 -432
- package/lib/module/MoveSdk.js.map +0 -1
- package/lib/typescript/MoveSdk.d.ts +0 -158
- package/lib/typescript/index.d.ts +0 -3
- 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
|
|
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
|
|
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
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
317
|
+
Log.e(LOG_TAG, "setup: ${e.message}", e)
|
|
281
318
|
null
|
|
282
319
|
}
|
|
283
320
|
|
|
284
321
|
try {
|
|
285
|
-
Log.d(
|
|
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(
|
|
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(
|
|
356
|
-
|
|
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(
|
|
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
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
811
|
+
Log.d(LOG_TAG, "onMoveHealthScoreChanged $data")
|
|
754
812
|
}
|
|
755
813
|
} catch (e: Exception) {
|
|
756
|
-
Log.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()
|
|
768
|
-
|
|
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()
|
|
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
|
+
|