diff --git a/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt b/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt index 8cdb4d2d8..3be7ecf51 100644 --- a/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt +++ b/app/src/main/java/com/geeksville/mesh/service/BluetoothInterface.kt @@ -353,6 +353,8 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String } } catch (ex: CancellationException) { warn("retryDueToException was cancelled") + } finally { + reconnectJob = null } /// We only try to set MTU once, because some buggy implementations fail @@ -417,7 +419,7 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String if (needForceRefresh) { // Our ESP32 code doesn't properly generate "service changed" indications. Therefore we need to force a refresh on initial start //needForceRefresh = false // In fact, because of tearing down BLE in sleep on the ESP32, our handle # assignments are not stable across sleep - so we much refetch every time forceServiceRefresh() // this article says android should not be caching, but it does on some phones: https://punchthrough.com/attribute-caching-in-ble-advantages-and-pitfalls/ - + delay(500) // From looking at the android C code it seems that we need to give some time for the refresh message to reach that worked _before_ we try to set mtu/get services // 200ms was not enough on an Amazon Fire } @@ -447,7 +449,6 @@ class BluetoothInterface(val service: RadioInterfaceService, val address: String override fun close() { reconnectJob?.cancel() // Cancel any queued reconnect attempts - reconnectJob = null if (safe != null) { info("Closing BluetoothInterface") 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 acf156a17..7fd73e7c9 100644 --- a/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/RadioInterfaceService.kt @@ -18,6 +18,7 @@ import com.geeksville.util.toRemoteExceptions import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel class RadioNotConnectedException(message: String = "Not connected to radio") : @@ -121,8 +122,10 @@ class RadioInterfaceService : Service(), Logging { private lateinit var sentPacketsLog: BinaryLogFile // inited in onCreate private lateinit var receivedPacketsLog: BinaryLogFile - private val serviceJob = Job() - val serviceScope = CoroutineScope(Dispatchers.IO + serviceJob) + /** + * We recreate this scope each time we stop an interface + */ + var serviceScope = CoroutineScope(Dispatchers.IO + Job()) private val nopIf = NopInterface() private var radioIf: IRadioInterface = nopIf @@ -198,7 +201,7 @@ class RadioInterfaceService : Service(), Logging { override fun onDestroy() { unregisterReceiver(bluetoothStateReceiver) stopInterface() - serviceJob.cancel() + serviceScope.cancel("Destroying RadioInterface") runningService = null super.onDestroy() } @@ -248,6 +251,10 @@ class RadioInterfaceService : Service(), Logging { radioIf = nopIf r.close() + // cancel any old jobs and get ready for the new ones + serviceScope.cancel("stopping interface") + serviceScope = CoroutineScope(Dispatchers.IO + Job()) + if (logSends) sentPacketsLog.close() if (logReceives)