Android - observer.collect throws NoSuchElementException
See original GitHub issueI’m trying to read some data of a UART Service that provides a “write without response” and a “notify” characteristic. I can write to it fine using cable but Kable but get the following error when using observer.collect { ... } to subscribe to notifications.
java.util.NoSuchElementException: Collection contains no element matching the predicate.
The characteristic works fine to read using other apps and sends out data about once a second. As probably will be apparent from my sample code below I’m fairly new to Kotlin but as far as I understand after reading up and digging through the source code I can’t see why this error is produced.
I looked at issue 38 but since I go through the steps to get the characteristic I get this error even if it is discovered. Or did i misunderstand the cause of that issue?
The characteristic and observer objects looks fine to me, what I can notice is that the
Sample code
bluetoothScope.launch {
val peripheral: Peripheral? = getPeripheral() // Get Peripheral using Scanner()
if (peripheral != null) {
peripheral.connect()
val characteristic = peripheral.services
?.first { service -> service.serviceUuid == UUID.fromString(UART_SERVICE)}
?.characteristics?.first { characteristic ->
characteristic.characteristicUuid == UUID.fromString(RX_CHARACTERISTIC_UUID)
}
if (characteristic != null ) {
val observer = peripheral.observe(characteristic)
try {
observer.collect { data ->
Log.d(TAG, data)
}
} catch (e: NoSuchElementException) {
Log.d(TAG, "Error: $e")
}
}
peripheral.state?.collect { state ->
when (state) {
State.Connected -> {
Log.d(TAG, "Connected")
}
else -> Log.d(TAG, "Not Connected")
}
}
}
}
}
Scan result
DiscoveredService(serviceUuid=6e400001-b5a3-f393-e0a9-e50e24dcca9e,
characteristics=[
DiscoveredCharacteristic(
serviceUuid=6e400001-b5a3-f393-e0a9-e50e24dcca9e,
characteristicUuid=6e400003-b5a3-f393-e0a9-e50e24dcca9e,
descriptors=[]),
DiscoveredCharacteristic(
serviceUuid=6e400001-b5a3-f393-e0a9-e50e24dcca9e,
characteristicUuid=6e400002-b5a3-f393-e0a9-e50e24dcca9e,
descriptors=[])]
)]
Issue Analytics
- State:
- Created 3 years ago
- Comments:15 (9 by maintainers)

Top Related StackOverflow Question
Your issue is actually closely related to #38, in that I believe you’re still being hit by the internal characteristic lookup failure within
writeorread, despite having retrieved the characteristic object from the discoveredservices.Definitely a shortcoming in how the
writeandreadfunctions retrieve the platform characteristic object: Theservicesproperty converts the list of services toList<DiscoveredService>, whereasDiscoveredServiceonly holds UUID details about the service (the reference to the actual platform service object is not held, to ensure that library consumers don’t hold on to/leak the platform’s service/characteristic objects).Unfortunately this means that a lookup (in
Peripheral’s internal service cache) is still performed even when manually finding the service/characteristic yourself (as you have done).For Android, in the future, we may consider holding a weak reference in the services/characteristics provided by
servicesproperty, making the lookup only necessary if the weak reference is lost.In the mean time, I’ll be sure and get #38 closed out soon and push a
SNAPSHOTor get another version published. It will at least give you a clearer picture of what is going wrong. Additionally, I’ll brainstorm other possible causes of the failure you’re seeing.I suspect it is actually here (as described above):
https://github.com/JuulLabs/kable/blob/c750de57fa6b0ea3dbd148dee3807b95e4ec1719/core/src/jsMain/kotlin/Peripheral.kt#L207-L212
Thanks for the help and issue report. I’ll keep you posted.
I have reproduced similar crash with SensorTag example when disconnect peripheral in during of connecting. You can reproduce this with my peripheral app attached here peripheral.apk.zip
java.util.NoSuchElementException: Collection contains no element matching the predicate. at com.juul.kable.PeripheralKt.bluetoothGattCharacteristicFrom(Peripheral.kt:269) at com.juul.kable.PeripheralKt.access$bluetoothGattCharacteristicFrom(Peripheral.kt:1) at com.juul.kable.AndroidPeripheral.startNotifications$core_debug(Peripheral.kt:193) at com.juul.kable.Observers$acquire$1.invokeSuspend(Observers.kt:45) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:342) at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith$default(DispatchedContinuation.kt:263) at kotlinx.coroutines.internal.ScopeCoroutine.afterCompletion(Scopes.kt:27) at kotlinx.coroutines.JobSupport.continueCompleting(JobSupport.kt:933) at kotlinx.coroutines.JobSupport.access$continueCompleting(JobSupport.kt:28) at kotlinx.coroutines.JobSupport$ChildCompletion.invoke(JobSupport.kt:1152) at kotlinx.coroutines.JobSupport.notifyCompletion(JobSupport.kt:1520) at kotlinx.coroutines.JobSupport.completeStateFinalization(JobSupport.kt:323) at kotlinx.coroutines.JobSupport.finalizeFinishingState(JobSupport.kt:240) at kotlinx.coroutines.JobSupport.tryMakeCompletingSlowPath(JobSupport.kt:903) at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:860) at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:825) at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:111) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:226) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7156) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)