Closed cren90 closed 1 year ago
Hmmm, seems like the 'long read' is not working properly. Odd...
Need to see if I can reproduce this...
I have same problem, after read first part of bytearray (with 20 bytes), don't read remnant. first part is : E9 00 13 01 01 00 00 31 13 01 01 00 01 09 00 00 15 5E 5B 5C and I expect another bytearray with E9 Header, but don't get it
@weliem any updates on this?
I did a quick test with a peripheral to set a long value and read it. Seems to work fine:
D/BluetoothPeripheral: reading characteristic <00002a29-0000-1000-8000-00805f9b34fb> I/BluetoothHandler$handlePeripheral: Received: This is quite a long text that should result in a long read D/BluetoothPeripheral: reading characteristic <00002a24-0000-1000-8000-00805f9b34fb> I/BluetoothHandler$handlePeripheral: Received: Pixel 5
So the central side is working fine which is to be expected because this library doesn't do anything special when reading a long characteristic. It is all handled by Android under the hood.
The problem could be with the peripheral side. But then I don't understand why it would work with nRF Connect...
Can you share some code and logs so I can see what is happening?
Yeah I'll put together a minimal reproduction and link here.
@weliem Here's the repo: https://github.com/cren90/blessed-long-scan Log lines when attempting to read the characteristic:
onConnectionUpdated() - Device=565D94_F interval=35 latency=0 timeout=500 status=0
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D Characteristic read
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D data:{
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D "className": "BlePeripheral",
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D "Characteristic": {
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D "Value": "{\"uuid\":\"8d302192-ced6"
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D },
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D "severity": "DEBUG"
2023-04-10 13:20:20.802 6743-6868 BlePeripheral.read com...ssed.long_read D }
2023-04-10 13:20:20.805 6743-6868 BlePeripheral.read com...ssed.long_read D Characteristic read
2023-04-10 13:20:20.806 6743-6868 BlePeripheral.read com...ssed.long_read D data:{
2023-04-10 13:20:20.806 6743-6868 BlePeripheral.read com...ssed.long_read D "className": "BlePeripheral",
2023-04-10 13:20:20.806 6743-6868 BlePeripheral.read com...ssed.long_read D "Characteristic": {
2023-04-10 13:20:20.806 6743-6868 BlePeripheral.read com...ssed.long_read D "Uuid": "0000e8a2-0000-1000-8000-00805f9b34fb",
2023-04-10 13:20:20.806 6743-6868 BlePeripheral.read com...ssed.long_read D "Value": "{\"uuid\":\"8d302192-ced6"
2023-04-10 13:20:20.806 6743-6868 BlePeripheral.read com...ssed.long_read D },
2023-04-10 13:20:20.806 6743-6868 BlePeripheral.read com...ssed.long_read D "severity": "DEBUG"
2023-04-10 13:20:20.806 6743-6868 BlePeripheral.read com...ssed.long_read D }
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E Failed to parse device info
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E data:{
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "className": "BlePeripheral",
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "exception": {
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "message": "Unexpected JSON token at offset 8: Expected quotation mark \u0027\"\u0027, but had \u0027\"\u0027 instead at path: $.uuid\nJSON input: {\"uuid\":\"8d302192-ced6",
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "stacktrace": "kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 8: Expected quotation mark \u0027\"\u0027, but had \u0027\"\u0027 instead at path: $.uuid\nJSON input: {\"uuid\":\"8d302192-ced6\n\tat kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)\n\tat kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:584)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:582)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail$kotlinx_serialization_json(AbstractJsonLexer.kt:223)\n\tat kotlinx.serialization.json.internal.StringJsonLexer.consumeKeyString(StringJsonLexer.kt:88)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.consumeString(AbstractJsonLexer.kt:369)\n\tat kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeString(StreamingJsonDecoder.kt:342)\n\tat kotlinx.serialization.encoding.AbstractDecoder.decodeStringElement(AbstractDecoder.kt:58)\n\tat com.cren90.blessed.long_read.ble.BleData$$serializer.deserialize(BleData.kt:5)\n\tat com.cren90.blessed.long_read.ble.BleData$$serializer.deserialize(BleData.kt:5)\n\tat kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:70)\n\tat kotlinx.serialization.json.Json.decodeFromString(Json.kt:97)\n\tat com.cren90.blessed.long_read.ble.BlePeripheral.getDeviceInfo(BlePeripheral.kt:85)\n\tat com.cren90.blessed.long_read.ble.BlePeripheral$getDeviceInfo$1.invokeSuspend(Unknown Source:14)\n\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)\n\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)\n\tat kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:54)\n\tat kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:100)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:780)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:684)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:671)\n"
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E },
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "severity": "ERROR"
2023-04-10 13:20:20.811 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E }
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E Failed to parse device info
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E data:{
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "className": "BlePeripheral",
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "exception": {
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "message": "Unexpected JSON token at offset 8: Expected quotation mark \u0027\"\u0027, but had \u0027\"\u0027 instead at path: $.uuid\nJSON input: {\"uuid\":\"8d302192-ced6",
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "stacktrace": "kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 8: Expected quotation mark \u0027\"\u0027, but had \u0027\"\u0027 instead at path: $.uuid\nJSON input: {\"uuid\":\"8d302192-ced6\n\tat kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)\n\tat kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:584)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:582)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.fail$kotlinx_serialization_json(AbstractJsonLexer.kt:223)\n\tat kotlinx.serialization.json.internal.StringJsonLexer.consumeKeyString(StringJsonLexer.kt:88)\n\tat kotlinx.serialization.json.internal.AbstractJsonLexer.consumeString(AbstractJsonLexer.kt:369)\n\tat kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeString(StreamingJsonDecoder.kt:342)\n\tat kotlinx.serialization.encoding.AbstractDecoder.decodeStringElement(AbstractDecoder.kt:58)\n\tat com.cren90.blessed.long_read.ble.BleData$$serializer.deserialize(BleData.kt:5)\n\tat com.cren90.blessed.long_read.ble.BleData$$serializer.deserialize(BleData.kt:5)\n\tat kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:70)\n\tat kotlinx.serialization.json.Json.decodeFromString(Json.kt:97)\n\tat com.cren90.blessed.long_read.ble.BlePeripheral.getDeviceInfo(BlePeripheral.kt:85)\n\tat com.cren90.blessed.long_read.ble.BlePeripheral$getDeviceInfo$1.invokeSuspend(Unknown Source:14)\n\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)\n\tat kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)\n\tat kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:54)\n\tat kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:100)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:780)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:684)\n\tat kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:671)\n"
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E },
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E "severity": "ERROR"
2023-04-10 13:20:20.815 6743-6868 BlePeripher...tDeviceInfo com...ssed.long_read E }
2023-04-10 13:20:20.816 6743-6868 BluetoothGatt com...ssed.long_read D cancelOpen() - device: 565D94_F
@weliem Any updates?
I am currently on holidays so I will have a look when I get back. Thanks for preparing the demo app!
I am a bit puzzled.....I tried your app and judging by the logs everything is fine...
Connected to the target VM, address: 'localhost:57300', transport: 'socket'
Capturing and displaying logcat messages from application. This behavior can be disabled in the "Logcat output" section of the "Debugger" settings page.
I/essed.long_read: Late-enabling -Xcheck:jni
I/essed.long_read: Using CollectorTypeCC GC.
D/CompatibilityChangeReporter: Compat change id reported: 171979766; UID 10127; state: ENABLED
W/ActivityThread: Application com.cren90.blessed.long_read is waiting for the debugger on port 8100...
I/System.out: Sending WAIT chunk
I/System.out: Debugger has connected
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: waiting for debugger to settle...
I/System.out: debugger has settled (1409)
W/ziparchive: Unable to open '/data/app/~~6sfQJYpplx1dpUJYmb4zEQ==/com.cren90.blessed.long_read-uPeH6rrYfw6QzfHyOYpCIQ==/base.dm': No such file or directory
W/ziparchive: Unable to open '/data/app/~~6sfQJYpplx1dpUJYmb4zEQ==/com.cren90.blessed.long_read-uPeH6rrYfw6QzfHyOYpCIQ==/base.dm': No such file or directory
D/nativeloader: Configuring classloader-namespace for other apk /data/app/6sfQJYpplx1dpUJYmb4zEQ==/com.cren90.blessed.long_read-uPeH6rrYfw6QzfHyOYpCIQ==/base.apk. target_sdk_version=33, uses_libraries=, library_path=/data/app/6sfQJYpplx1dpUJYmb4zEQ==/com.cren90.blessed.long_read-uPeH6rrYfw6QzfHyOYpCIQ==/lib/arm64, permitted_path=/data:/mnt/expand:/data/user/0/com.cren90.blessed.long_read
V/GraphicsEnvironment: ANGLE Developer option for 'com.cren90.blessed.long_read' set to: 'default'
V/GraphicsEnvironment: ANGLE GameManagerService for com.cren90.blessed.long_read: false
V/GraphicsEnvironment: Updatable production driver is not supported on the device.
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
D/NetworkSecurityConfig: No Network Security Config specified, using platform default
W/essed.long_read: Verification of com.cren90.blessed.long_read.ble.BleAdvertiser com.cren90.blessed.long_read.MainActivity.getAdvertiser() took 116.055ms (25.85 bytecodes/s) (1408B approximate peak alloc)
W/essed.long_read: Method java.lang.Object androidx.compose.runtime.snapshots.SnapshotStateMap.mutate(kotlin.jvm.functions.Function1) failed lock verification and will run slower.
Common causes for lock verification issues are non-optimized dex code
and incorrect proguard optimizations.
W/essed.long_read: Method void androidx.compose.runtime.snapshots.SnapshotStateMap.update(kotlin.jvm.functions.Function1) failed lock verification and will run slower.
W/essed.long_read: Method boolean androidx.compose.runtime.snapshots.SnapshotStateMap.removeIf$runtime_release(kotlin.jvm.functions.Function1) failed lock verification and will run slower.
I/AdrenoGLES-0: QUALCOMM build : 4783c89, I46ff5fc46f
Build Date : 11/30/20
OpenGL ES Shader Compiler Version: EV031.31.04.01
Local Branch : QPR2
Remote Branch :
Remote Branch :
Reconstruct Branch :
I/AdrenoGLES-0: Build Config : S P 10.0.4 AArch64
I/AdrenoGLES-0: Driver Path : /vendor/lib64/egl/libGLESv2_adreno.so
I/AdrenoGLES-0: PFP: 0x016dd093, ME: 0x00000000
W/AdrenoUtils:
Is there a specific way to trigger the issue?
Perhaps it is phone related or Android version related....what are you testing on? I used a Samsung S22 and a Pixel 5 both running Android 13
I've been testing between my Galaxy S9+ running Android 10 and my Note 20 Ultra running Android 13. Others at my company are seeing the same behavior between multiple Pixel 6 devices running Android 13
Looks like it was the translation from byte[] to string that was causing the issue. When I used either ByteArray.asString()
or ByteArray.toString()
I got a 20 char string, switching to ByteArray.decodeToString()
resolved. I'm going to mark as closed.
@SaeedBahari this might resolve for you as well.
I'm using the library both for advertising from device1 and scanning from device2.
When attempting to read a characteristic on device1, I get the callback in device1 for
BluetoothPeripheralManagerCallback.onCharacteristicRead
and then performcharacteristic.setValue(data)
which is ~200 characters. I get the first 22 chars returned to device2peripheral.readCharacteristic(uuid, uuid)
.If I scan using the nRF app, on device2 I see the full data payload. I've also tried
requestMtu(MAX_MTU)
and that hasn't helped.It appears as though the
suspendCoroutine
inBluetoothPeripheral.readCharacteristic
line 790 is resuming early on the first value being read.