hypertrack-sdk-react-native 8.2.1 → 9.0.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 (116) hide show
  1. package/CHANGELOG.md +28 -1
  2. package/CONTRIBUTING.md +32 -110
  3. package/{LICENSE → LICENSE.md} +2 -0
  4. package/README.md +20 -40
  5. package/android/build.gradle +112 -113
  6. package/android/gradle.properties +1 -1
  7. package/android/src/main/java/com/reactnativehypertracksdk/HyperTrackReactNativePlugin.kt +209 -0
  8. package/android/src/main/java/com/reactnativehypertracksdk/HyperTrackSdkPackage.kt +2 -4
  9. package/android/src/main/java/com/reactnativehypertracksdk/ReactNativeSerialization.kt +88 -0
  10. package/android/src/main/java/com/reactnativehypertracksdk/common/Geotag.kt +9 -0
  11. package/android/src/main/java/com/reactnativehypertracksdk/common/HyperTrackError.kt +27 -0
  12. package/android/src/main/java/com/reactnativehypertracksdk/common/HyperTrackSdkWrapper.kt +243 -0
  13. package/android/src/main/java/com/reactnativehypertracksdk/common/LocationError.kt +9 -0
  14. package/android/src/main/java/com/reactnativehypertracksdk/common/Result.kt +48 -0
  15. package/android/src/main/java/com/reactnativehypertracksdk/common/SdkInitParams.kt +46 -0
  16. package/android/src/main/java/com/reactnativehypertracksdk/common/SdkMethod.kt +20 -0
  17. package/android/src/main/java/com/reactnativehypertracksdk/common/Serialization.kt +196 -0
  18. package/hypertrack-sdk-react-native.podspec +2 -2
  19. package/ios/HyperTrackReactNativePlugin.m +54 -0
  20. package/ios/HyperTrackReactNativePlugin.swift +253 -0
  21. package/ios/HyperTrackSdk-Bridging-Header.h +2 -0
  22. package/ios/HyperTrackSdk.xcodeproj/project.pbxproj +8 -11
  23. package/ios/common/DictionaryDecoder.swift +28 -0
  24. package/ios/common/HyperTrackError.swift +20 -0
  25. package/ios/common/HyperTrackSDKWrapper.swift +118 -0
  26. package/ios/common/SDKInitParams.swift +11 -0
  27. package/ios/common/SDKMethod.swift +14 -0
  28. package/ios/common/Serialization.swift +270 -0
  29. package/lib/commonjs/HyperTrack/HyperTrack.js +141 -142
  30. package/lib/commonjs/HyperTrack/HyperTrack.js.map +1 -1
  31. package/lib/commonjs/HyperTrack/data_types/HyperTrackError.js +31 -0
  32. package/lib/commonjs/HyperTrack/data_types/HyperTrackError.js.map +1 -0
  33. package/lib/commonjs/HyperTrack/data_types/Location.js +2 -0
  34. package/lib/commonjs/HyperTrack/data_types/Location.js.map +1 -0
  35. package/lib/commonjs/HyperTrack/data_types/LocationError.js +6 -0
  36. package/lib/commonjs/HyperTrack/data_types/LocationError.js.map +1 -0
  37. package/lib/commonjs/HyperTrack/data_types/SdkInitParams.js +2 -0
  38. package/lib/commonjs/HyperTrack/data_types/SdkInitParams.js.map +1 -0
  39. package/lib/commonjs/HyperTrack/data_types/internal/DeviceId.js +2 -0
  40. package/lib/commonjs/HyperTrack/data_types/internal/DeviceId.js.map +1 -0
  41. package/lib/commonjs/HyperTrack/data_types/internal/DeviceName.js +2 -0
  42. package/lib/commonjs/HyperTrack/data_types/internal/DeviceName.js.map +1 -0
  43. package/lib/commonjs/HyperTrack/data_types/internal/Geotag.js +2 -0
  44. package/lib/commonjs/HyperTrack/data_types/internal/Geotag.js.map +1 -0
  45. package/lib/commonjs/HyperTrack/data_types/internal/HyperTrackErrorInternal.js +2 -0
  46. package/lib/commonjs/HyperTrack/data_types/internal/HyperTrackErrorInternal.js.map +1 -0
  47. package/lib/commonjs/HyperTrack/data_types/internal/IsAvailable.js +2 -0
  48. package/lib/commonjs/HyperTrack/data_types/internal/IsAvailable.js.map +1 -0
  49. package/lib/commonjs/HyperTrack/data_types/internal/IsTracking.js +2 -0
  50. package/lib/commonjs/HyperTrack/data_types/internal/IsTracking.js.map +1 -0
  51. package/lib/commonjs/HyperTrack/data_types/internal/LocationErrorInternal.js +6 -0
  52. package/lib/commonjs/HyperTrack/data_types/internal/LocationErrorInternal.js.map +1 -0
  53. package/lib/commonjs/HyperTrack/data_types/internal/LocationResponse.js +6 -0
  54. package/lib/commonjs/HyperTrack/data_types/internal/LocationResponse.js.map +1 -0
  55. package/lib/commonjs/index.js +28 -17
  56. package/lib/commonjs/index.js.map +1 -1
  57. package/lib/module/HyperTrack/HyperTrack.js +140 -134
  58. package/lib/module/HyperTrack/HyperTrack.js.map +1 -1
  59. package/lib/module/HyperTrack/data_types/HyperTrackError.js +24 -0
  60. package/lib/module/HyperTrack/data_types/HyperTrackError.js.map +1 -0
  61. package/lib/module/HyperTrack/data_types/Location.js +2 -0
  62. package/lib/module/HyperTrack/data_types/Location.js.map +1 -0
  63. package/lib/module/HyperTrack/data_types/LocationError.js +2 -0
  64. package/lib/module/HyperTrack/data_types/LocationError.js.map +1 -0
  65. package/lib/module/HyperTrack/data_types/SdkInitParams.js +2 -0
  66. package/lib/module/HyperTrack/data_types/SdkInitParams.js.map +1 -0
  67. package/lib/module/HyperTrack/data_types/internal/DeviceId.js +2 -0
  68. package/lib/module/HyperTrack/data_types/internal/DeviceId.js.map +1 -0
  69. package/lib/module/HyperTrack/data_types/internal/DeviceName.js +2 -0
  70. package/lib/module/HyperTrack/data_types/internal/DeviceName.js.map +1 -0
  71. package/lib/module/HyperTrack/data_types/internal/Geotag.js +2 -0
  72. package/lib/module/HyperTrack/data_types/internal/Geotag.js.map +1 -0
  73. package/lib/module/HyperTrack/data_types/internal/HyperTrackErrorInternal.js +2 -0
  74. package/lib/module/HyperTrack/data_types/internal/HyperTrackErrorInternal.js.map +1 -0
  75. package/lib/module/HyperTrack/data_types/internal/IsAvailable.js +2 -0
  76. package/lib/module/HyperTrack/data_types/internal/IsAvailable.js.map +1 -0
  77. package/lib/module/HyperTrack/data_types/internal/IsTracking.js +2 -0
  78. package/lib/module/HyperTrack/data_types/internal/IsTracking.js.map +1 -0
  79. package/lib/module/HyperTrack/data_types/internal/LocationErrorInternal.js +2 -0
  80. package/lib/module/HyperTrack/data_types/internal/LocationErrorInternal.js.map +1 -0
  81. package/lib/module/HyperTrack/data_types/internal/LocationResponse.js +2 -0
  82. package/lib/module/HyperTrack/data_types/internal/LocationResponse.js.map +1 -0
  83. package/lib/module/index.js +4 -1
  84. package/lib/module/index.js.map +1 -1
  85. package/lib/typescript/HyperTrack/HyperTrack.d.ts +66 -100
  86. package/lib/typescript/HyperTrack/data_types/HyperTrackError.d.ts +20 -0
  87. package/lib/typescript/HyperTrack/data_types/Location.d.ts +7 -0
  88. package/lib/typescript/HyperTrack/data_types/LocationError.d.ts +8 -0
  89. package/lib/typescript/HyperTrack/data_types/SdkInitParams.d.ts +5 -0
  90. package/lib/typescript/HyperTrack/data_types/internal/DeviceId.d.ts +4 -0
  91. package/lib/typescript/HyperTrack/data_types/internal/DeviceName.d.ts +4 -0
  92. package/lib/typescript/HyperTrack/data_types/internal/Geotag.d.ts +3 -0
  93. package/lib/typescript/HyperTrack/data_types/internal/HyperTrackErrorInternal.d.ts +4 -0
  94. package/lib/typescript/HyperTrack/data_types/internal/IsAvailable.d.ts +4 -0
  95. package/lib/typescript/HyperTrack/data_types/internal/IsTracking.d.ts +4 -0
  96. package/lib/typescript/HyperTrack/data_types/internal/LocationErrorInternal.d.ts +12 -0
  97. package/lib/typescript/HyperTrack/data_types/internal/LocationResponse.d.ts +11 -0
  98. package/lib/typescript/index.d.ts +4 -1
  99. package/package.json +156 -156
  100. package/src/HyperTrack/HyperTrack.ts +163 -163
  101. package/src/HyperTrack/data_types/HyperTrackError.ts +22 -0
  102. package/src/HyperTrack/data_types/Location.ts +7 -0
  103. package/src/HyperTrack/data_types/LocationError.ts +11 -0
  104. package/src/HyperTrack/data_types/SdkInitParams.ts +5 -0
  105. package/src/HyperTrack/data_types/internal/DeviceId.ts +4 -0
  106. package/src/HyperTrack/data_types/internal/DeviceName.ts +4 -0
  107. package/src/HyperTrack/data_types/internal/Geotag.ts +3 -0
  108. package/src/HyperTrack/data_types/internal/HyperTrackErrorInternal.ts +4 -0
  109. package/src/HyperTrack/data_types/internal/IsAvailable.ts +4 -0
  110. package/src/HyperTrack/data_types/internal/IsTracking.ts +4 -0
  111. package/src/HyperTrack/data_types/internal/LocationErrorInternal.ts +14 -0
  112. package/src/HyperTrack/data_types/internal/LocationResponse.ts +14 -0
  113. package/src/index.tsx +4 -7
  114. package/android/src/main/java/com/reactnativehypertracksdk/HyperTrackModule.kt +0 -284
  115. package/ios/HyperTrack.h +0 -7
  116. package/ios/HyperTrack.m +0 -384
@@ -0,0 +1,209 @@
1
+ package com.reactnativehypertracksdk
2
+
3
+ import com.facebook.react.bridge.*
4
+ import com.facebook.react.module.annotations.ReactModule
5
+ import com.facebook.react.modules.core.DeviceEventManagerModule
6
+ import com.hypertrack.sdk.*
7
+ import com.hypertrack.sdk.TrackingStateObserver.OnTrackingStateChangeListener
8
+ import com.hypertrack.sdk.AvailabilityStateObserver.OnAvailabilityStateChangeListener
9
+ import com.reactnativehypertracksdk.common.*
10
+ import com.reactnativehypertracksdk.common.Serialization.serializeIsAvailable
11
+ import com.reactnativehypertracksdk.common.Serialization.serializeIsTracking
12
+
13
+ @Suppress("ComplexRedundantLet")
14
+ @ReactModule(name = HyperTrackReactNativePlugin.NAME)
15
+ class HyperTrackReactNativePlugin(reactContext: ReactApplicationContext?) :
16
+ ReactContextBaseJavaModule(reactContext) {
17
+
18
+ var trackingStateListener: OnTrackingStateChangeListener? = null
19
+ var availabilityListener: OnAvailabilityStateChangeListener? = null
20
+
21
+ override fun getName(): String {
22
+ return NAME
23
+ }
24
+
25
+ @ReactMethod
26
+ fun addListener(type: String?) {
27
+ when(type) {
28
+ EVENT_TRACKING -> {
29
+ HyperTrackSdkWrapper.isTracking().let {
30
+ when(it) {
31
+ is Success -> {
32
+ emitIsTracking(it.success)
33
+ }
34
+ is Failure -> {
35
+ throw Exception("isTracking failed: ${it.failure}", it.failure)
36
+ }
37
+ }
38
+ }
39
+ }
40
+ EVENT_AVAILABILITY -> {
41
+ HyperTrackSdkWrapper.isAvailable().let {
42
+ when(it) {
43
+ is Success -> {
44
+ emitIsAvailable(it.success)
45
+ }
46
+ is Failure -> {
47
+ throw Exception("isAvailable failed: ${it.failure}", it.failure)
48
+ }
49
+ }
50
+ }
51
+ }
52
+ EVENT_ERRORS -> {
53
+ HyperTrackSdkWrapper.getInitialErrors().let {
54
+ emitErrors(it)
55
+ }
56
+ }
57
+ else -> Unit
58
+ }
59
+ // Keep: Required for RN built in Event Emitter Calls.
60
+ }
61
+
62
+ @ReactMethod
63
+ fun removeListeners(type: Int?) {
64
+ // Keep: Required for RN built in Event Emitter Calls.
65
+ }
66
+
67
+ @ReactMethod
68
+ fun initializeSdk(
69
+ initParams: ReadableMap,
70
+ promise: Promise
71
+ ) {
72
+ HyperTrackSdkWrapper
73
+ .initialize(initParams.toHashMap())
74
+ .mapSuccess { sdk ->
75
+ initListeners(sdk)
76
+ }
77
+ .toPromise(promise)
78
+ }
79
+
80
+ private fun initListeners(sdkInstance: HyperTrack) {
81
+ if (trackingStateListener != null) {
82
+ sdkInstance.removeTrackingListener(trackingStateListener)
83
+ trackingStateListener = null
84
+ }
85
+ trackingStateListener = object : OnTrackingStateChangeListener {
86
+ override fun onError(trackingError: TrackingError) {
87
+ emitErrors(HyperTrackSdkWrapper.getErrors(trackingError))
88
+ }
89
+
90
+ override fun onTrackingStart() {
91
+ emitIsTracking(serializeIsTracking(true))
92
+ }
93
+
94
+ override fun onTrackingStop() {
95
+ emitIsTracking(serializeIsTracking(false))
96
+ }
97
+ }.also {
98
+ sdkInstance.addTrackingListener(it)
99
+ }
100
+
101
+ if (availabilityListener != null) {
102
+ sdkInstance.removeAvailabilityListener(availabilityListener)
103
+ availabilityListener = null
104
+ }
105
+ availabilityListener =
106
+ object : AvailabilityStateObserver.OnAvailabilityStateChangeListener {
107
+ override fun onError(p0: AvailabilityError) {
108
+ // ignored, errors are handled by trackingStateListener
109
+ }
110
+
111
+ override fun onAvailable() {
112
+ emitIsAvailable(serializeIsAvailable(true))
113
+ }
114
+
115
+ override fun onUnavailable() {
116
+ emitIsAvailable(serializeIsAvailable(false))
117
+ }
118
+ }.also {
119
+ sdkInstance.addAvailabilityListener(it)
120
+ }
121
+ }
122
+
123
+ @ReactMethod
124
+ fun getDeviceId(promise: Promise) {
125
+ HyperTrackSdkWrapper.getDeviceID().toPromise(promise)
126
+ }
127
+
128
+ @ReactMethod
129
+ fun isTracking(promise: Promise) {
130
+ HyperTrackSdkWrapper.isTracking().toPromise(promise)
131
+ }
132
+
133
+ @ReactMethod
134
+ fun startTracking() {
135
+ HyperTrackSdkWrapper.startTracking()
136
+ }
137
+
138
+ @ReactMethod
139
+ fun stopTracking() {
140
+ HyperTrackSdkWrapper.stopTracking()
141
+ }
142
+
143
+ @ReactMethod
144
+ fun sync() {
145
+ HyperTrackSdkWrapper.sync()
146
+ }
147
+
148
+ @ReactMethod
149
+ fun addGeotag(args: ReadableMap, promise: Promise) {
150
+ HyperTrackSdkWrapper.addGeotag(args.toHashMap()).toPromise(promise)
151
+ }
152
+
153
+ @ReactMethod
154
+ fun isAvailable(promise: Promise) {
155
+ HyperTrackSdkWrapper.isAvailable().toPromise(promise)
156
+ }
157
+
158
+ @ReactMethod
159
+ fun setAvailability(args: ReadableMap) {
160
+ HyperTrackSdkWrapper.setAvailability(args.toHashMap())
161
+ }
162
+
163
+ @ReactMethod
164
+ fun setName(args: ReadableMap) {
165
+ HyperTrackSdkWrapper.setName(args.toHashMap())
166
+ }
167
+
168
+ @ReactMethod
169
+ fun setMetadata(args: ReadableMap) {
170
+ HyperTrackSdkWrapper.setMetadata(args.toHashMap())
171
+ }
172
+
173
+ @ReactMethod
174
+ fun getLocation(promise: Promise) {
175
+ HyperTrackSdkWrapper.getLocation().toPromise(promise)
176
+ }
177
+
178
+ private fun emitIsTracking(isTracking: Map<String, Any?>) {
179
+ emitEvent(EVENT_TRACKING, isTracking.toWritableMap())
180
+ }
181
+
182
+ private fun emitIsAvailable(isAvailable: Map<String, Any?>) {
183
+ emitEvent(EVENT_AVAILABILITY, isAvailable.toWritableMap())
184
+ }
185
+
186
+ private fun emitErrors(errors: List<Map<String, Any?>>) {
187
+ emitEvent(EVENT_ERRORS, errors.toWriteableArray())
188
+ }
189
+
190
+ private fun emitEvent(event: String, data: WritableMap) {
191
+ reactApplicationContext
192
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
193
+ .emit(event, data)
194
+ }
195
+
196
+ private fun emitEvent(event: String, data: WritableArray) {
197
+ reactApplicationContext
198
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
199
+ .emit(event, data)
200
+ }
201
+
202
+ companion object {
203
+ private const val EVENT_TRACKING = "onTrackingChanged"
204
+ private const val EVENT_AVAILABILITY = "onAvailabilityChanged"
205
+ private const val EVENT_ERRORS = "onError"
206
+
207
+ const val NAME = "HyperTrackReactNativePlugin"
208
+ }
209
+ }
@@ -3,12 +3,10 @@ import com.facebook.react.ReactPackage
3
3
  import com.facebook.react.bridge.NativeModule
4
4
  import com.facebook.react.bridge.ReactApplicationContext
5
5
  import com.facebook.react.uimanager.ViewManager
6
- import com.hypertrack.reactnative.androidsdk.HTSDKModule
7
-
8
6
 
9
7
  class HyperTrackSdkPackage : ReactPackage {
10
- override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11
- return listOf(HTSDKModule(reactContext))
8
+ override fun createNativeModules(reactContext: ReactApplicationContext): MutableList<NativeModule> {
9
+ return listOf(HyperTrackReactNativePlugin(reactContext)).toMutableList()
12
10
  }
13
11
 
14
12
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
@@ -0,0 +1,88 @@
1
+ package com.reactnativehypertracksdk
2
+
3
+ import android.util.Log
4
+ import com.facebook.react.bridge.Arguments
5
+ import com.facebook.react.bridge.Promise
6
+ import com.facebook.react.bridge.WritableArray
7
+ import com.facebook.react.bridge.WritableMap
8
+ import com.reactnativehypertracksdk.common.Failure
9
+ import com.reactnativehypertracksdk.common.Result
10
+ import com.reactnativehypertracksdk.common.Success
11
+
12
+ @Suppress("UNCHECKED_CAST")
13
+ internal fun <T> Result<T>.toPromise(promise: Promise) {
14
+ when(this) {
15
+ is Success -> {
16
+ when(this.success) {
17
+ is Map<*, *> -> {
18
+ promise.resolve((this.success as Map<String, Any>).toWritableMap())
19
+ }
20
+ is Unit -> {
21
+ promise.resolve(null)
22
+ }
23
+ else -> {
24
+ // using nested exception to correctly display error in RN logs
25
+ promise.reject(Exception(IllegalArgumentException(this.success.toString())))
26
+ }
27
+ }
28
+ }
29
+ is Failure -> {
30
+ promise.reject(Exception(this.failure))
31
+ }
32
+ }
33
+ }
34
+
35
+ @Suppress("UNCHECKED_CAST")
36
+ internal fun List<Any>.toWriteableArray(): WritableArray {
37
+ return Arguments.createArray().also { writableArray ->
38
+ forEach {
39
+ when (it) {
40
+ is String -> {
41
+ writableArray.pushString(it)
42
+ }
43
+ is Map<*, *> -> {
44
+ writableArray.pushMap((it as Map<String, Any>).toWritableMap())
45
+ }
46
+ else -> {
47
+ throw Exception(IllegalArgumentException(it.javaClass.toString()))
48
+ }
49
+ }
50
+ }
51
+ }
52
+ }
53
+
54
+ @Suppress("UNCHECKED_CAST")
55
+ internal fun Map<String, Any?>.toWritableMap(): WritableMap {
56
+ val map = this
57
+ return Arguments.createMap().apply {
58
+ map.forEach { entry ->
59
+ val key = entry.key
60
+ when (val value = entry.value) {
61
+ is String -> {
62
+ putString(key, value)
63
+ }
64
+ is Int -> {
65
+ putInt(key, value)
66
+ }
67
+ is Double -> {
68
+ putDouble(key, value)
69
+ }
70
+ is Boolean -> {
71
+ putBoolean(key, value)
72
+ }
73
+ is List<*> -> {
74
+ putArray(key, (value as List<String>).toWriteableArray())
75
+ }
76
+ is Map<*, *> -> {
77
+ putMap(key, (value as Map<String, Any>).toWritableMap())
78
+ }
79
+ null -> {
80
+ putNull(key)
81
+ }
82
+ else -> {
83
+ throw Exception(IllegalArgumentException(entry.value?.javaClass.toString()))
84
+ }
85
+ }
86
+ }
87
+ }
88
+ }
@@ -0,0 +1,9 @@
1
+ package com.reactnativehypertracksdk.common
2
+
3
+ /**
4
+ * The data that represents geotag to create. Now it contains only payload data but
5
+ * can have other params like expectedLocation in future
6
+ *
7
+ * @param data Geotag payload
8
+ */
9
+ internal data class Geotag(val data: Map<String, Any?>)
@@ -0,0 +1,27 @@
1
+ package com.reactnativehypertracksdk.common
2
+
3
+ /**
4
+ * Check HyperTrack SDK docs for HyperTrackError
5
+ * Enum naming convention is ignored to make datatype sync across platforms easier
6
+ */
7
+ @Suppress("EnumEntryName")
8
+ internal enum class HyperTrackError {
9
+ gpsSignalLost,
10
+ locationMocked,
11
+ locationPermissionsDenied,
12
+ locationPermissionsInsufficientForBackground,
13
+ locationPermissionsNotDetermined,
14
+ locationPermissionsReducedAccuracy,
15
+ locationPermissionsProvisional,
16
+ locationPermissionsRestricted,
17
+ locationServicesDisabled,
18
+ locationServicesUnavailable,
19
+ motionActivityPermissionsNotDetermined,
20
+ motionActivityPermissionsDenied,
21
+ motionActivityServicesDisabled,
22
+ motionActivityServicesUnavailable,
23
+ motionActivityPermissionsRestricted,
24
+ networkConnectionUnavailable,
25
+ invalidPublishableKey,
26
+ blockedFromRunning
27
+ }
@@ -0,0 +1,243 @@
1
+ package com.reactnativehypertracksdk.common
2
+
3
+ import com.hypertrack.sdk.*
4
+ import com.reactnativehypertracksdk.common.Serialization.deserializeAvailability
5
+ import com.reactnativehypertracksdk.common.Serialization.deserializeGeotagData
6
+ import com.reactnativehypertracksdk.common.Serialization.serializeFailure
7
+ import com.reactnativehypertracksdk.common.Serialization.serializeErrors
8
+ import com.reactnativehypertracksdk.common.Serialization.serializeIsAvailable
9
+ import com.reactnativehypertracksdk.common.Serialization.serializeIsTracking
10
+ import com.reactnativehypertracksdk.common.Serialization.serializeSuccess
11
+ import com.reactnativehypertracksdk.common.Serialization.serializeDeviceId
12
+ import com.reactnativehypertracksdk.common.Serialization.deserializeDeviceName
13
+ import com.reactnativehypertracksdk.common.Serialization.parse
14
+ import java.lang.IllegalStateException
15
+ import java.lang.RuntimeException
16
+ import android.util.Log
17
+
18
+
19
+ /**
20
+ * This class stores SDK instance, calls HyperTrack SDK methods and serializes responses.
21
+ * It receives serialized params.
22
+ */
23
+ internal object HyperTrackSdkWrapper {
24
+
25
+ // initialize method is guaranteed to be called (by non-native side)
26
+ // prior to any access to the SDK instance
27
+ private lateinit var _sdkInstance: HyperTrack
28
+ val sdkInstance: HyperTrack
29
+ get() = _sdkInstance
30
+
31
+ fun initialize(
32
+ args: Map<String, Any?>
33
+ ): Result<HyperTrack> {
34
+ return try {
35
+ SdkInitParams.fromMap(args).flatMapSuccess { initParams ->
36
+ _sdkInstance = HyperTrack.getInstance(initParams.publishableKey)
37
+ if (initParams.loggingEnabled) {
38
+ HyperTrack.enableDebugLogging()
39
+ }
40
+ if (initParams.allowMockLocations) {
41
+ sdkInstance.allowMockLocations()
42
+ }
43
+ this.sdkInstance.backgroundTrackingRequirement(
44
+ initParams.requireBackgroundTrackingPermission
45
+ )
46
+ Success(sdkInstance)
47
+ }
48
+ } catch (exception: Exception) {
49
+ Failure(Exception("Hypertrack SDK initialization failed.", exception))
50
+ }
51
+ }
52
+
53
+ fun getDeviceID(): Result<Map<String, Any?>> {
54
+ return Success(serializeDeviceId(sdkInstance.deviceID))
55
+ }
56
+
57
+ fun startTracking(): Result<Unit> {
58
+ sdkInstance.start()
59
+ return Success(Unit)
60
+ }
61
+
62
+ fun stopTracking(): Result<Unit> {
63
+ sdkInstance.stop()
64
+ return Success(Unit)
65
+ }
66
+
67
+ fun sync(): Result<Unit> {
68
+ sdkInstance.syncDeviceSettings()
69
+ return Success(Unit)
70
+ }
71
+
72
+ fun addGeotag(args: Map<String, Any?>): Result<Map<String, Any?>> {
73
+ return deserializeGeotagData(args).flatMapSuccess { geotag ->
74
+ sdkInstance.addGeotag(geotag.data).let { result ->
75
+ when (result) {
76
+ is GeotagResult.SuccessWithDeviation -> {
77
+ serializeSuccess(result.deviceLocation)
78
+ }
79
+ is GeotagResult.Success -> {
80
+ serializeSuccess(result.deviceLocation)
81
+ }
82
+ is GeotagResult.Error -> {
83
+ serializeFailure(getLocationError(result.reason))
84
+ }
85
+ else -> {
86
+ throw IllegalArgumentException()
87
+ }
88
+ }
89
+ }.let {
90
+ Success(it)
91
+ }
92
+ }
93
+ }
94
+
95
+ fun isTracking(): Result<Map<String, Any?>> {
96
+ return Success(serializeIsTracking(sdkInstance.isTracking))
97
+ }
98
+
99
+ fun isAvailable(): Result<Map<String, Any?>> {
100
+ return Success(
101
+ serializeIsAvailable(sdkInstance.availability.equals(Availability.AVAILABLE))
102
+ )
103
+ }
104
+
105
+ fun setAvailability(args: Map<String, Any?>): Result<Unit> {
106
+ return deserializeAvailability(args).mapSuccess { isAvailable ->
107
+ if (isAvailable) {
108
+ sdkInstance.availability = Availability.AVAILABLE
109
+ } else {
110
+ sdkInstance.availability = Availability.UNAVAILABLE
111
+ }
112
+ }
113
+ }
114
+
115
+ fun setName(args: Map<String, Any?>): Result<Unit> {
116
+ return deserializeDeviceName(args).mapSuccess { name ->
117
+ sdkInstance.setDeviceName(name)
118
+ }
119
+ }
120
+
121
+ fun setMetadata(metadata: Map<String, Any?>): Result<Unit> {
122
+ return Result.tryAsResult {
123
+ sdkInstance.setDeviceMetadata(metadata)
124
+ Unit
125
+ }
126
+ }
127
+
128
+ fun getLocation(): Result<Map<String, Any?>> {
129
+ return sdkInstance.latestLocation.let { result ->
130
+ if (result.isSuccess) {
131
+ serializeSuccess(result.value)
132
+ } else {
133
+ serializeFailure(getLocationError(result.error))
134
+ }
135
+ }.let { Success(it) }
136
+ }
137
+
138
+ fun getInitialErrors(): List<Map<String, String>> {
139
+ return serializeErrors(getHyperTrackErrorsFromBlockers())
140
+ }
141
+
142
+ fun getErrors(error: TrackingError): List<Map<String, String>> {
143
+ return serializeErrors(getTrackingErrors((error)))
144
+ }
145
+
146
+ private fun getTrackingErrors(error: TrackingError): Set<HyperTrackError> {
147
+ return when (error.code) {
148
+ TrackingError.INVALID_PUBLISHABLE_KEY_ERROR -> {
149
+ HyperTrackError.invalidPublishableKey
150
+ }
151
+ TrackingError.PERMISSION_DENIED_ERROR -> {
152
+ null
153
+ }
154
+ TrackingError.AUTHORIZATION_ERROR -> {
155
+ HyperTrackError.blockedFromRunning
156
+ }
157
+ TrackingError.GPS_PROVIDER_DISABLED_ERROR -> {
158
+ HyperTrackError.locationServicesDisabled
159
+ }
160
+ TrackingError.UNKNOWN_NETWORK_ERROR -> {
161
+ HyperTrackError.blockedFromRunning
162
+ }
163
+ else -> {
164
+ throw RuntimeException("Unknown tracking error")
165
+ }
166
+ }.let { hyperTrackError ->
167
+ (hyperTrackError?.let { setOf(it) } ?: setOf()) + getHyperTrackErrorsFromBlockers()
168
+ }
169
+ }
170
+
171
+ private fun getLocationError(error: OutageReason): LocationError {
172
+ val blockersErrors = getHyperTrackErrorsFromBlockers()
173
+ return when (error) {
174
+ OutageReason.NO_GPS_SIGNAL -> {
175
+ Errors(setOf(HyperTrackError.gpsSignalLost) + blockersErrors)
176
+ }
177
+ OutageReason.MISSING_LOCATION_PERMISSION -> {
178
+ Errors(setOf(HyperTrackError.locationPermissionsDenied) + blockersErrors)
179
+ }
180
+ OutageReason.LOCATION_SERVICE_DISABLED -> {
181
+ Errors(setOf(HyperTrackError.locationServicesDisabled) + blockersErrors)
182
+ }
183
+ OutageReason.MISSING_ACTIVITY_PERMISSION -> {
184
+ Errors(setOf(HyperTrackError.motionActivityPermissionsDenied) + blockersErrors)
185
+ }
186
+ OutageReason.NOT_TRACKING -> {
187
+ NotRunning
188
+ }
189
+ OutageReason.START_HAS_NOT_FINISHED -> {
190
+ Starting
191
+ }
192
+ OutageReason.RESTART_REQUIRED -> {
193
+ throw IllegalStateException("RESTART_REQUIRED must not be returned")
194
+ }
195
+ }
196
+ }
197
+
198
+ private fun getLocationError(error: GeotagResult.Error.Reason): LocationError {
199
+ val blockersErrors = getHyperTrackErrorsFromBlockers()
200
+ return when (error) {
201
+ GeotagResult.Error.Reason.NO_GPS_SIGNAL -> {
202
+ Errors(setOf(HyperTrackError.gpsSignalLost) + blockersErrors)
203
+ }
204
+ GeotagResult.Error.Reason.MISSING_LOCATION_PERMISSION -> {
205
+ Errors(setOf(HyperTrackError.locationPermissionsDenied) + blockersErrors)
206
+ }
207
+ GeotagResult.Error.Reason.LOCATION_SERVICE_DISABLED -> {
208
+ Errors(setOf(HyperTrackError.locationServicesDisabled) + blockersErrors)
209
+ }
210
+ GeotagResult.Error.Reason.MISSING_ACTIVITY_PERMISSION -> {
211
+ Errors(setOf(HyperTrackError.motionActivityPermissionsDenied) + blockersErrors)
212
+ }
213
+ GeotagResult.Error.Reason.NOT_TRACKING -> {
214
+ NotRunning
215
+ }
216
+ GeotagResult.Error.Reason.START_HAS_NOT_FINISHED -> {
217
+ Starting
218
+ }
219
+ }
220
+ }
221
+
222
+ private fun getHyperTrackErrorsFromBlockers(): Set<HyperTrackError> {
223
+ return HyperTrack.getBlockers()
224
+ .map {
225
+ when (it) {
226
+ Blocker.LOCATION_PERMISSION_DENIED -> {
227
+ HyperTrackError.locationPermissionsDenied
228
+ }
229
+ Blocker.LOCATION_SERVICE_DISABLED -> {
230
+ HyperTrackError.locationServicesDisabled
231
+ }
232
+ Blocker.ACTIVITY_PERMISSION_DENIED -> {
233
+ HyperTrackError.motionActivityPermissionsDenied
234
+ }
235
+ Blocker.BACKGROUND_LOCATION_DENIED -> {
236
+ HyperTrackError.locationPermissionsInsufficientForBackground
237
+ }
238
+ }
239
+ }
240
+ .toSet()
241
+ }
242
+
243
+ }
@@ -0,0 +1,9 @@
1
+ package com.reactnativehypertracksdk.common
2
+
3
+ /**
4
+ * Check HyperTrack SDK docs for LocationError
5
+ */
6
+ internal sealed class LocationError
7
+ internal object NotRunning : LocationError()
8
+ internal object Starting : LocationError()
9
+ internal data class Errors(val errors: Set<HyperTrackError>) : LocationError()
@@ -0,0 +1,48 @@
1
+ package com.reactnativehypertracksdk.common
2
+
3
+ internal sealed class Result<S> {
4
+ fun <T> flatMapSuccess(onSuccess: (S) -> Result<T>): Result<T> {
5
+ return when (this) {
6
+ is Success -> {
7
+ onSuccess.invoke(this.success)
8
+ }
9
+ is Failure -> {
10
+ Failure<T>(this.failure)
11
+ }
12
+ }
13
+ }
14
+
15
+ fun <T> mapSuccess(onSuccess: (S) -> T): Result<T> {
16
+ return when (this) {
17
+ is Success -> {
18
+ Success(onSuccess.invoke(this.success))
19
+ }
20
+ is Failure -> {
21
+ Failure<T>(this.failure)
22
+ }
23
+ }
24
+ }
25
+
26
+ fun getOrThrow(): S {
27
+ return when (this) {
28
+ is Success -> this.success
29
+ is Failure -> throw Exception(
30
+ "Result unwrapping failed: ${this.failure}",
31
+ this.failure
32
+ )
33
+ }
34
+ }
35
+
36
+ companion object {
37
+ fun <T> tryAsResult(block: () -> T): Result<T> {
38
+ return try {
39
+ Success(block.invoke())
40
+ } catch (e: Exception) {
41
+ Failure(e)
42
+ }
43
+ }
44
+ }
45
+ }
46
+
47
+ internal data class Success<S>(val success: S) : Result<S>()
48
+ internal data class Failure<S>(val failure: Throwable) : Result<S>()
@@ -0,0 +1,46 @@
1
+ package com.reactnativehypertracksdk.common
2
+
3
+ import com.reactnativehypertracksdk.common.Serialization.parse
4
+ import android.util.Log
5
+
6
+ /**
7
+ * SDK config params
8
+ */
9
+ internal data class SdkInitParams(
10
+ val publishableKey: String,
11
+ val requireBackgroundTrackingPermission: Boolean,
12
+ val loggingEnabled: Boolean,
13
+ val allowMockLocations: Boolean,
14
+ ) {
15
+
16
+ companion object {
17
+ fun fromMap(map: Map<String, Any?>): Result<SdkInitParams> {
18
+ Log.v(javaClass.simpleName, "fromMap 1")
19
+ return parse(map) {
20
+ Log.v(javaClass.simpleName, "parse 1")
21
+ SdkInitParams(
22
+ publishableKey = it.get<String>(KEY_PUBLISHABLE_KEY).getOrThrow(),
23
+ requireBackgroundTrackingPermission = it.get<Boolean>(
24
+ KEY_REQUIRE_BACKGROUND_TRACKING_PERMISSION
25
+ ).getOrThrow(),
26
+ loggingEnabled = it.get<Boolean>(KEY_LOGGING_ENABLED).getOrThrow(),
27
+ allowMockLocations = it.get<Boolean>(KEY_ALLOW_MOCK_LOCATIONS).getOrThrow()
28
+ )
29
+ }.also {
30
+ Log.v(javaClass.simpleName, "fromMap $it")
31
+ }
32
+ }
33
+
34
+ private const val KEY_PUBLISHABLE_KEY =
35
+ "publishableKey"
36
+ private const val KEY_REQUIRE_BACKGROUND_TRACKING_PERMISSION =
37
+ "requireBackgroundTrackingPermission"
38
+ private const val KEY_LOGGING_ENABLED =
39
+ "loggingEnabled"
40
+ private const val KEY_ALLOW_MOCK_LOCATIONS =
41
+ "allowMockLocations"
42
+ }
43
+
44
+ }
45
+
46
+