Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在异步函数中未调用Kotlin回调_Android_Kotlin_Bluetooth Lowenergy - Fatal编程技术网

Android 在异步函数中未调用Kotlin回调

Android 在异步函数中未调用Kotlin回调,android,kotlin,bluetooth-lowenergy,Android,Kotlin,Bluetooth Lowenergy,我正试图订阅Android API 28中可编程外围设备的多个特性 由于BLEAPI的异步特性,我需要使订阅每个特性的函数(gatt.writeDescriptor())块;否则,BLEAPI将尝试一次订阅多个特征,尽管一次只能写入一个描述符:这意味着只能订阅一个特征 阻塞是通过重写onServicesDiscoveryd回调并调用异步函数来循环并订阅特征来实现的。这被一个简单的布尔值(canContinue)阻止不幸的是,从未调用回调函数onDescriptorWrite。 请参阅下面的代码:

我正试图订阅Android API 28中可编程外围设备的多个特性

由于BLEAPI的异步特性,我需要使订阅每个特性的函数(
gatt.writeDescriptor()
)块;否则,BLEAPI将尝试一次订阅多个特征,尽管一次只能写入一个描述符:这意味着只能订阅一个特征

阻塞是通过重写
onServicesDiscoveryd
回调并调用异步函数来循环并订阅特征来实现的。这被一个简单的布尔值(
canContinue
)阻止不幸的是,从未调用回调函数
onDescriptorWrite

请参阅下面的代码:

override fun onDescriptorWrite(gatt: BluetoothGatt, descriptor: BluetoothGattDescriptor, status: Int) {
    canContinue = true 
} 

override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) { 
    runBlocking {
        loopAsync(gatt)
    }
}

private suspend fun loopAsync(gatt: BluetoothGatt) {
    coroutineScope {
        async {
            gatt.services.forEach { gattService ->                      
                gattService.characteristics.forEach { gattChar ->
                    CHAR_LIST.forEach {
                        if (gattChar.uuid.toString().contains(it)) {
                            canContinue = false
                            gatt.setCharacteristicNotification(gattChar, true)

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

                            val write = Runnable {
                                gatt.writeDescriptor(descriptor)
                            }
                            //private val mainHandler = Handler(Looper.getMainLooper())
                            //mainHandler.post(write)
                            //runOnUiThread(write)
                            gatt.writeDescriptor(descriptor)

                        }

                        while (!canContinue)
                    }
                }
            }
        }
    }
}
有人建议我在主线程中运行
gatt.writeDescriptor()
函数。正如您在上面的代码中所看到的,我使用
runOnUiThread()
和根据问题的建议创建一个处理程序对象都尝试了这个方法,但没有效果

如果我从同步函数调用
gatt.writeDescriptor()
,就会调用回调函数,我不知道为什么它不会从异步函数调用

编辑:当(!canContinue)出现时,
循环实际上阻止了回调。如果我注释掉这一行,回调将触发,但我将面临与以前相同的问题。如何阻止此功能

欢迎提出任何建议!请原谅我的无知,但我非常习惯于在嵌入式系统上工作,Android对我来说是一个全新的世界

谢谢,
亚当

所以我实际上自己找到了答案

while(!canContinue)循环实际上阻止了回调,因为它在主线程中运行,并且优先于设置
canContinue
变量所需的回调

只需从主线程中调用
gatt.writeDescriptor()
函数和
while
循环即可解决此问题:

val subscribe = Runnable {
    gatt.writeDescriptor(descriptor)
    while (!canContinue);
    }

runOnUiThread(subscribe)

所以我自己就找到了答案

while(!canContinue)循环实际上阻止了回调,因为它在主线程中运行,并且优先于设置
canContinue
变量所需的回调

只需从主线程中调用
gatt.writeDescriptor()
函数和
while
循环即可解决此问题:

val subscribe = Runnable {
    gatt.writeDescriptor(descriptor)
    while (!canContinue);
    }

runOnUiThread(subscribe)

我在评论中贴了一些注释,但我认为最好将其格式化为答案

即使您已经解决了问题,我还是建议异步运行实际的协同路由,并在其中使用

private-var-channel:channel=channel()
重写脚本编写(gatt:BluetoothGatt,描述符:BluetoothGattDescriptor,状态:Int){
GlobalScope.async{
channel.send(真)
}
} 
覆盖服务发现的乐趣(gatt:BluetoothGatt,状态:Int){
GlobalScope.async{
环异步(gatt)
}
}
私有异步(gatt:BluetoothGatt){
gatt.services.forEach{gattService->
gattService.characteristics.forEach{gattChar->
CHAR_LIST.forEach{
if(gattChar.uuid.toString()包含(它)){
gatt.setCharacteristicNotification(gattChar,真实)
val descriptor=gattChar.getDescriptor(UUID.fromString(BleNamesResolver.CLIENT\u CHARACTERISTIC\u CONFIG))
descriptor.value=bluetoothgattddescriptor.ENABLE\u NOTIFICATION\u值
gatt.writeDescriptor(描述符)
channel.receive()
}
}
}
}
}

我在评论中发布了一些注释,但我认为最好将其格式化为答案

即使您已经解决了问题,我还是建议异步运行实际的协同路由,并在其中使用

private-var-channel:channel=channel()
重写脚本编写(gatt:BluetoothGatt,描述符:BluetoothGattDescriptor,状态:Int){
GlobalScope.async{
channel.send(真)
}
} 
覆盖服务发现的乐趣(gatt:BluetoothGatt,状态:Int){
GlobalScope.async{
环异步(gatt)
}
}
私有异步(gatt:BluetoothGatt){
gatt.services.forEach{gattService->
gattService.characteristics.forEach{gattChar->
CHAR_LIST.forEach{
if(gattChar.uuid.toString()包含(它)){
gatt.setCharacteristicNotification(gattChar,真实)
val descriptor=gattChar.getDescriptor(UUID.fromString(BleNamesResolver.CLIENT\u CHARACTERISTIC\u CONFIG))
descriptor.value=bluetoothgattddescriptor.ENABLE\u NOTIFICATION\u值
gatt.writeDescriptor(描述符)
channel.receive()
}
}
}
}
}

您的while循环不应该在if块中吗?这意味着您只有在编写描述符时才等待。@ErnestZamelczyk您是对的,虽然这对问题本身没有影响,但移动它将有助于缓解未来的问题-谢谢,您的while循环不应该在if块中吗?这意味着您只有在编写描述符时才等待。@ErnestZamelczyk您是对的,虽然这对问题本身没有影响,但移动它将有助于缓解未来的问题-谢谢您,顺便说一句,更好的方法是在后台线程上运行协程并使用它接收通知。因此,您将(!canContinue)
替换为