Replace volatile cancel flag with coroutine Job cancellation in EspFlasher

This commit is contained in:
eddy 2026-07-26 22:58:08 +02:00
commit 71b13c51ee
2 changed files with 13 additions and 24 deletions

View file

@ -24,20 +24,13 @@ class EspFlasher(private val context: Context) {
fun onProgress(percent: Int, message: String)
}
@Volatile
private var cancelled = false
fun cancel() {
cancelled = true
}
suspend fun flashDevice(usbManager: UsbManager, device: UsbDevice, callback: FlashCallback) {
cancelled = false
try {
withContext(kotlinx.coroutines.Dispatchers.IO) {
doFlash(usbManager, device, callback)
}
} catch (e: CancellationException) {
Log.i(TAG, "Flash cancelled")
throw e
} catch (e: Exception) {
Log.e(TAG, "Flash failed", e)
@ -56,7 +49,7 @@ class EspFlasher(private val context: Context) {
private suspend fun doFlash(usbManager: UsbManager, device: UsbDevice, callback: FlashCallback) {
kotlinx.coroutines.delay(500)
checkCancelled()
coroutineContext.ensureActive()
val connection = usbManager.openDevice(device)
?: throw IOException("Kan USB-apparaat niet openen")
@ -77,7 +70,7 @@ class EspFlasher(private val context: Context) {
callback.onProgress(0, "Verbinden met ESP bootloader...")
val transport = UsbSerialTransport(connection, epOut, epIn)
checkCancelled()
coroutineContext.ensureActive()
val assets = context.assets
val bootloader = assets.open("firmware/bootloader.bin").readBytes()
@ -116,7 +109,7 @@ class EspFlasher(private val context: Context) {
stub.eraseFlash()
for (step in steps) {
checkCancelled()
coroutineContext.ensureActive()
val sizeStr = if (step.data.size > 1024) "${step.data.size / 1024}KB" else "${step.data.size} bytes"
callback.onProgress(step.baseProgress, "${step.name} schrijven ($sizeStr)...")
@ -136,9 +129,4 @@ class EspFlasher(private val context: Context) {
}
}
private suspend fun checkCancelled() {
if (cancelled) {
coroutineContext.ensureActive()
}
}
}

View file

@ -22,9 +22,9 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.withContext
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.nio.charset.StandardCharsets
import java.security.SecureRandom
@ -47,7 +47,7 @@ class SettingsActivity : AppCompatActivity() {
private var currentAction = UsbAction.NONE
private var progressDialog: AlertDialog? = null
private var dialog: AlertDialog? = null
private var flasher: EspFlasher? = null
private var flasherJob: Job? = null
private val usbAttachedReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
@ -124,8 +124,8 @@ class SettingsActivity : AppCompatActivity() {
override fun onDestroy() {
super.onDestroy()
currentAction = UsbAction.NONE
flasher?.cancel()
flasher = null
flasherJob?.cancel()
flasherJob = null
try { unregisterReceiver(usbAttachedReceiver) } catch (_: Exception) {}
try { unregisterReceiver(usbPermissionReceiver) } catch (_: Exception) {}
try { unregisterReceiver(usbDetachedReceiver) } catch (_: Exception) {}
@ -211,7 +211,7 @@ class SettingsActivity : AppCompatActivity() {
dialog = null
showProgressDialog("Firmware Flashen", "Initialiseren...", STYLE_HORIZONTAL)
flasher = EspFlasher(this)
val flasher = EspFlasher(this)
val progressCallback = object : EspFlasher.FlashCallback {
override fun onProgress(percent: Int, message: String) {
lifecycleScope.launch(Dispatchers.Main) {
@ -221,9 +221,9 @@ class SettingsActivity : AppCompatActivity() {
}
}
}
lifecycleScope.launch {
flasherJob = lifecycleScope.launch {
try {
flasher?.flashDevice(usbManager, device, progressCallback)
flasher.flashDevice(usbManager, device, progressCallback)
if (isFinishing || isDestroyed) return@launch
currentAction = UsbAction.NONE
progressDialog?.dismiss()
@ -240,6 +240,7 @@ class SettingsActivity : AppCompatActivity() {
.show()
} catch (e: kotlinx.coroutines.CancellationException) {
cleanupAction()
throw e
} catch (e: Exception) {
progressDialog?.dismiss()
progressDialog = null
@ -290,7 +291,7 @@ class SettingsActivity : AppCompatActivity() {
.setTitle(title)
.setView(view)
.setNegativeButton("Annuleren") { _, _ ->
flasher?.cancel()
flasherJob?.cancel()
cleanupAction()
}
.setCancelable(false)