android - 在 Kotlin 中制作函数 block

标签 android kotlin bluetooth-lowenergy

我很高兴这个问题可能已经得到解答,但我无法找到适合我的解决方案。

Tl;dr:如何制作功能 block ?

我有以下用 Kotlin 为 Android API 28 编写的 BLE 相关代码。

override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {

    for (gattService: BluetoothGattService in gatt!!.services) {

        for (gattChar: BluetoothGattCharacteristic in gattService.characteristics) {

                if (gattChar.uuid.toString().contains(ADC_SAMPLESET_0) && !subscribed_0) {

                    subscribed_0 = true

                    gatt.setCharacteristicNotification(gattChar, true)                   

                    val descriptor = gattChar.getDescriptor(
                            UUID.fromString(BleNamesResolver.CLIENT_CHARACTERISTIC_CONFIG)
                    )
                    descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                    gatt.writeDescriptor(descriptor)
                }

上面的if语句会重复多次,以便于订阅多个BLE特性。不幸的是,gatt.writeDescriptor() 函数异步运行。我需要等待它返回,然后再调用 gatt.writeDescriptor() 来获取下一个特征。我该如何实现这一目标?

我尝试在 kotlinx.coroutines.experimental.* 中使用 runBlockingGlobalScope.launch 但我不完全确定他们是正确的。

谢谢, 亚当

最佳答案

onDescriptorWrite() 方法可能会有所帮助。您应该已经覆盖它了。

尝试以下操作:

private var canContinue = false;

override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { //gatt shouldn't be null, so the null-safe ? isn't needed
    loopAsync(gatt);
}

override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
    canContinue = true; //allow the loop to continue once a descriptor is written
}

private fun loopAsync(gatt: BluetoothGatt) {
    async { //Run it async
        gatt.services.forEach { gattService -> //Kotlin has a handy Collections.forEach() extension function
            gattService.characteristics.forEach { gattChar -> //Same for this one
                if (gattChar.uuid.toString().contains(ADC_SAMPLESET_0) && !subscribed_0) {
                    subscribed_0 = true

                    gatt.setCharacteristicNotification(gattChar, true)

                    val descriptor = gattChar.getDescriptor(
                            UUID.fromString(BleNamesResolver.CLIENT_CHARACTERISTIC_CONFIG)
                    }
                    descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
                    gatt.writeDescriptor(descriptor)
                    while(!canContinue); //wait until canContinue becomes true and then continue
                }
            }
        }
    }
}

这有点hacky。可能有一种方法可以通过递归来做到这一点,但是嵌套的 for 循环使这变得很棘手。

关于android - 在 Kotlin 中制作函数 block ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52522448/

相关文章:

android - 在 cordova 3.3 中执行 cordova 平台添加 android 时出错

java - 向安卓应用程序添加日历,标记某些事件

kotlin 在 onNext 或不应为 null 的 BehaviorSubject 中传递 mutableList

inheritance - Kotlin 覆盖成员集并获取

android - lateinit 属性尚未用 dagger2 初始化

react-native - 使用 native react 杀死应用程序后,蓝牙仍然处于事件状态

android - 使用 Gradle 构建库 jar

android - 为什么 TextToSpeech.getLanguage() *有时* 会返回 null?

c - 从 BLE 接收的数据无法从十六进制转换为字符串(北欧)

bluetooth - 我们可以连接多少台设备到蓝牙5