@bota.dev/react-native-app-sdk 2.0.0-beta.7 → 2.0.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -5
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidDevices.kt +18 -0
- package/android/src/main/java/dev/bota/sdk/reactnative/BotaDeviceSDKModule.kt +3 -0
- package/android/src/test/java/dev/bota/sdk/reactnative/BotaDeviceSDKAndroidDevicesTest.kt +34 -0
- package/generated/codegen-contract.json +2 -2
- package/lib/commonjs/sdkIdentity.js +1 -1
- package/lib/module/sdkIdentity.js +1 -1
- package/lib/typescript/sdkIdentity.d.ts +1 -1
- package/package.json +1 -1
- package/src/sdkIdentity.ts +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ into the native Apple and Android SDKs.
|
|
|
7
7
|
|
|
8
8
|
## Requirements
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
App SDK beta.6 and later expose `BotaDeviceSDK.clientPresence.nextReport(deviceId)`.
|
|
11
11
|
It returns `BotaClientPresenceContext | null` from the native verified connection,
|
|
12
12
|
preserving native session/sequence while identifying this React Native package
|
|
13
13
|
and its generated version. It makes no HTTP call or device command. Destroy
|
|
@@ -23,13 +23,18 @@ adopting this source API; published-package availability is a separate gate.
|
|
|
23
23
|
|
|
24
24
|
## Install
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
Published beta.8 remains available. Install this beta.9 source candidate with
|
|
27
|
+
the exact pin below only after its publication is verified. Beta.9 closes stale
|
|
28
|
+
Android GATT clients and clears connection state on adapter-off even without a
|
|
29
|
+
disconnect callback. Reconnect explicitly after restoring Bluetooth. The
|
|
30
|
+
[preflight](../../release/evidence/2.0.0-beta.9-preflight.md) separates candidate
|
|
31
|
+
phone evidence from publication and final package acceptance.
|
|
28
32
|
Remove `@bota.dev/react-native-sdk` before adding the replacement; do not
|
|
29
|
-
co-install both.
|
|
33
|
+
co-install both. Standalone maintenance ended September 29, 2026; follow the
|
|
34
|
+
[retirement and migration notice](../../docs/migrations/react-native-sdk-sunset.md).
|
|
30
35
|
|
|
31
36
|
```bash
|
|
32
|
-
npm install --save-exact @bota.dev/react-native-app-sdk@2.0.0-beta.
|
|
37
|
+
npm install --save-exact @bota.dev/react-native-app-sdk@2.0.0-beta.9
|
|
33
38
|
npx pod-install
|
|
34
39
|
```
|
|
35
40
|
|
|
@@ -31,6 +31,7 @@ internal interface BotaDeviceSDKAndroidDeviceClient {
|
|
|
31
31
|
suspend fun nextClientPresence(deviceId: String): dev.bota.sdk.SDKClientContext?
|
|
32
32
|
|
|
33
33
|
suspend fun statusUpdates(): Flow<DeviceStatus>
|
|
34
|
+
fun connectionUpdates(): Flow<ConnectedDevice?>
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
internal class BotaDeviceSDKSharedAndroidDeviceClient(
|
|
@@ -61,6 +62,7 @@ internal class BotaDeviceSDKSharedAndroidDeviceClient(
|
|
|
61
62
|
client.clientPresence.nextReport(deviceId)
|
|
62
63
|
|
|
63
64
|
override suspend fun statusUpdates(): Flow<DeviceStatus> = client.devices.statusUpdates()
|
|
65
|
+
override fun connectionUpdates(): Flow<ConnectedDevice?> = client.devices.connectionUpdates()
|
|
64
66
|
}
|
|
65
67
|
|
|
66
68
|
internal class BotaDeviceSDKAndroidDevices(
|
|
@@ -73,6 +75,20 @@ internal class BotaDeviceSDKAndroidDevices(
|
|
|
73
75
|
private val statusLock = Any()
|
|
74
76
|
private var activeScan: Job? = null
|
|
75
77
|
private var activeStatusUpdates: Job? = null
|
|
78
|
+
private var activeConnectionUpdates: Job? = null
|
|
79
|
+
|
|
80
|
+
suspend fun startConnectionUpdates(onDisconnected: () -> Unit) = operations.withLock {
|
|
81
|
+
activeConnectionUpdates?.cancelAndJoin()
|
|
82
|
+
val stream = client.connectionUpdates()
|
|
83
|
+
activeConnectionUpdates = scope.launch(start = CoroutineStart.UNDISPATCHED) {
|
|
84
|
+
var connected = false
|
|
85
|
+
stream.collect { device ->
|
|
86
|
+
val lost = connected && device == null
|
|
87
|
+
connected = device != null
|
|
88
|
+
if (lost) onDisconnected()
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
76
92
|
|
|
77
93
|
suspend fun startScan(
|
|
78
94
|
timeoutMilliseconds: ULong,
|
|
@@ -155,6 +171,8 @@ internal class BotaDeviceSDKAndroidDevices(
|
|
|
155
171
|
}
|
|
156
172
|
|
|
157
173
|
suspend fun stopAll() = operations.withLock {
|
|
174
|
+
activeConnectionUpdates?.cancelAndJoin()
|
|
175
|
+
activeConnectionUpdates = null
|
|
158
176
|
stopScanOwned()
|
|
159
177
|
stopStatusUpdatesOwned()
|
|
160
178
|
}
|
|
@@ -22,6 +22,38 @@ import org.junit.Assert.assertEquals
|
|
|
22
22
|
import org.junit.Test
|
|
23
23
|
|
|
24
24
|
class BotaDeviceSDKAndroidDevicesTest {
|
|
25
|
+
@Test
|
|
26
|
+
fun transportLossIsForwardedWithoutAStatusSubscription() = runTest {
|
|
27
|
+
val verified = ConnectedDevice(
|
|
28
|
+
id = "selected", serialNumber = "EVFXXW67KP", deviceType = DeviceType.BotaPin,
|
|
29
|
+
firmwareVersion = "1.0.19", isProvisioned = false,
|
|
30
|
+
connectionState = ConnectionState.Connected, mtu = 247,
|
|
31
|
+
)
|
|
32
|
+
val stopped = CompletableDeferred<Unit>()
|
|
33
|
+
val client = FakeDeviceClient(
|
|
34
|
+
DiscoveredDevice("selected", rssi = -30), verified,
|
|
35
|
+
connections = flow {
|
|
36
|
+
try {
|
|
37
|
+
emit(null)
|
|
38
|
+
emit(verified)
|
|
39
|
+
emit(null)
|
|
40
|
+
emit(null)
|
|
41
|
+
awaitCancellation()
|
|
42
|
+
} finally {
|
|
43
|
+
stopped.complete(Unit)
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
)
|
|
47
|
+
val devices = BotaDeviceSDKAndroidDevices(client, backgroundScope)
|
|
48
|
+
var losses = 0
|
|
49
|
+
devices.startConnectionUpdates { losses += 1 }
|
|
50
|
+
assertEquals(1, losses)
|
|
51
|
+
assertEquals(0, client.statusReadCount)
|
|
52
|
+
devices.stopAll()
|
|
53
|
+
stopped.await()
|
|
54
|
+
assertEquals(1, losses)
|
|
55
|
+
}
|
|
56
|
+
|
|
25
57
|
@Test
|
|
26
58
|
fun unknownPairingStateUsesTheFrozenUnpairedFallback() {
|
|
27
59
|
assertEquals("unpaired", PairingState.Unknown(0xFFu).toBridgeValue())
|
|
@@ -134,7 +166,9 @@ class BotaDeviceSDKAndroidDevicesTest {
|
|
|
134
166
|
private val connected: ConnectedDevice,
|
|
135
167
|
private val scanFailure: Throwable? = null,
|
|
136
168
|
private val status: DeviceStatus = testDeviceStatus(),
|
|
169
|
+
private val connections: Flow<ConnectedDevice?> = kotlinx.coroutines.flow.emptyFlow(),
|
|
137
170
|
) : BotaDeviceSDKAndroidDeviceClient {
|
|
171
|
+
override fun connectionUpdates(): Flow<ConnectedDevice?> = connections
|
|
138
172
|
override suspend fun nextClientPresence(deviceId: String): dev.bota.sdk.SDKClientContext? = null
|
|
139
173
|
val scanOptions = mutableListOf<Pair<ULong, Boolean>>()
|
|
140
174
|
val selectedIds = mutableListOf<String>()
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"package": "@bota.dev/react-native-app-sdk",
|
|
4
|
-
"packageVersion": "2.0.0-beta.
|
|
4
|
+
"packageVersion": "2.0.0-beta.9",
|
|
5
5
|
"reactNativeVersion": "0.86.3",
|
|
6
6
|
"codegenLibrary": "BotaDeviceSDKSpec",
|
|
7
7
|
"nativeModule": "BotaDeviceSDK",
|
|
@@ -4149,5 +4149,5 @@
|
|
|
4149
4149
|
}
|
|
4150
4150
|
]
|
|
4151
4151
|
},
|
|
4152
|
-
"contractDigest": "
|
|
4152
|
+
"contractDigest": "4d34ba215afd0469042660c26d544d99a764d15b73372979f50c915351c6b8ab"
|
|
4153
4153
|
}
|
|
@@ -6,5 +6,5 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.SDK_VERSION = exports.SDK_PACKAGE = void 0;
|
|
7
7
|
// Generated by cargo xtask client-identity generate. Do not edit.
|
|
8
8
|
const SDK_PACKAGE = exports.SDK_PACKAGE = '@bota.dev/react-native-app-sdk';
|
|
9
|
-
const SDK_VERSION = exports.SDK_VERSION = '2.0.0-beta.
|
|
9
|
+
const SDK_VERSION = exports.SDK_VERSION = '2.0.0-beta.9';
|
|
10
10
|
//# sourceMappingURL=sdkIdentity.js.map
|
package/package.json
CHANGED
package/src/sdkIdentity.ts
CHANGED