diff --git a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt index b5f66757a..00b3709e5 100644 --- a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt @@ -16,6 +16,10 @@ import com.geeksville.concurrent.DeferredExecution import com.geeksville.mesh.IRadioInterfaceService import com.geeksville.util.exceptionReporter import com.geeksville.util.toRemoteExceptions +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.delay import java.lang.reflect.Method import java.util.* @@ -215,6 +219,9 @@ class RadioInterfaceService : Service(), Logging { private var isConnected = false + private val serviceJob = Job() + private val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob) + /// Work that users of our service want done, which might get deferred until after /// we have completed our initial connection private val clientOperations = DeferredExecution() @@ -317,24 +324,27 @@ class RadioInterfaceService : Service(), Logging { // we begin by setting our MTU size as high as it can go safe!!.asyncRequestMtu(512) { mtuRes -> - debug("requested MTU result=$mtuRes") - mtuRes.getOrThrow() // FIXME - why sometimes is the result Unit!?! + serviceScope.handledLaunch { + debug("requested MTU result=$mtuRes") + mtuRes.getOrThrow() // FIXME - why sometimes is the result Unit!?! + delay(500) // android BLE is buggy and needs a 500ms sleep before calling getChracteristic, or you might get back null - fromNum = service.getCharacteristic(BTM_FROMNUM_CHARACTER)!! + fromNum = service.getCharacteristic(BTM_FROMNUM_CHARACTER)!! - // We must set this to true before broadcasting connectionChanged - isConnected = true + // We must set this to true before broadcasting connectionChanged + isConnected = true - safe!!.setNotify(fromNum, true) { - debug("fromNum changed, so we are reading new messages") + safe!!.setNotify(fromNum, true) { + debug("fromNum changed, so we are reading new messages") + doReadFromRadio() + } + + // Now tell clients they can (finally use the api) + broadcastConnectionChanged(true) + + // Immediately broadcast any queued packets sitting on the device doReadFromRadio() } - - // Now tell clients they can (finally use the api) - broadcastConnectionChanged(true) - - // Immediately broadcast any queued packets sitting on the device - doReadFromRadio() } } } @@ -347,6 +357,7 @@ class RadioInterfaceService : Service(), Logging { override fun onDestroy() { setEnabled(false) + serviceJob.cancel() runningService = null super.onDestroy() } diff --git a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt index d0bc86e60..059a8ec95 100644 --- a/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt +++ b/app/src/main/java/com/geeksville/mesh/service/SafeBluetooth.kt @@ -501,6 +501,29 @@ class SafeBluetooth(private val context: Context, private val device: BluetoothD // c.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT gatt!!.setCharacteristicNotification(c, enable) + /* + c is null sometimes +2020-04-13 15:59:38.222 2111-2182/com.geeksville.mesh D/BluetoothGatt: setCharacteristicNotification() - uuid: ed9da18c-a800-4f66-a670-aa7547e34453 enable: true +2020-04-13 15:59:38.225 2111-2182/com.geeksville.mesh E/com.geeksville.util.Exceptions: exceptionReporter Uncaught Exception + kotlin.KotlinNullPointerException + at com.geeksville.mesh.service.SafeBluetooth.setNotify(SafeBluetooth.kt:505) + at com.geeksville.mesh.service.RadioInterfaceService$onConnect$1$1.invoke(RadioInterfaceService.kt:328) + at com.geeksville.mesh.service.RadioInterfaceService$onConnect$1$1.invoke(RadioInterfaceService.kt:90) + at com.geeksville.concurrent.CallbackContinuation.resume(SyncContinuation.kt:20) + at com.geeksville.mesh.service.SafeBluetooth$completeWork$1.invoke(SafeBluetooth.kt:329) + at com.geeksville.mesh.service.SafeBluetooth$completeWork$1.invoke(SafeBluetooth.kt:33) + at com.geeksville.util.ExceptionsKt.exceptionReporter(Exceptions.kt:34) + at com.geeksville.mesh.service.SafeBluetooth.completeWork(SafeBluetooth.kt:312) + at com.geeksville.mesh.service.SafeBluetooth.access$completeWork(SafeBluetooth.kt:33) + at com.geeksville.mesh.service.SafeBluetooth$gattCallback$1.onMtuChanged(SafeBluetooth.kt:221) + at android.bluetooth.BluetoothGatt$1$13.run(BluetoothGatt.java:658) + at android.bluetooth.BluetoothGatt.runOrQueueCallback(BluetoothGatt.java:780) + at android.bluetooth.BluetoothGatt.access$200(BluetoothGatt.java:41) + at android.bluetooth.BluetoothGatt$1.onConfigureMTU(BluetoothGatt.java:653) + at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:330) + at android.os.Binder.execTransactInternal(Binder.java:1021) + at android.os.Binder.execTransact(Binder.java:994) + */ // per https://stackoverflow.com/questions/27068673/subscribe-to-a-ble-gatt-notification-android val descriptor: BluetoothGattDescriptor = c.getDescriptor(configurationDescriptorUUID)!! descriptor.value =