Сделать функциональный блок в Котлине - PullRequest
0 голосов
/ 26 сентября 2018

Я ценю, что на это, возможно, уже ответили, но я не могу найти решение, которое работает для меня.

Tl; dr: Как создать функциональный блок?

У меня есть следующий код, связанный с BLE, написанный на Kotlin для Android API 28.

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() для получения следующей характеристики.Как мне этого добиться?

Я пытался использовать runBlocking и GlobalScope.launch в kotlinx.coroutines.experimental.*, но я не совсем уверен, что они правильные.

Спасибо, Адам

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Это не совсем вопрос о Котлине.BluetoothGatt - это Async API с обратными вызовами (как это часто бывает с Bluetooth, из-за его природы), и вы не можете легко использовать языковые функции, чтобы скрыть этот аспект.

Возможно, можно написатьфасад поверх BluetoothGatt, который блокирует, но хорошо поработал бы, это было бы довольно трудоемким делом, и я бы не стал его рекомендовать.

0 голосов
/ 26 сентября 2018

Метод 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
                }
            }
        }
    }
}

Это немного глупо.Вероятно, есть способ сделать это с помощью рекурсии, но вложенные циклы for усложняют задачу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...