From b3e52ce036ba4a1369aa47a64a747e0efbb957b1 Mon Sep 17 00:00:00 2001 From: Shreyash Gupta <79988299+ghostshreyash@users.noreply.github.com> Date: Mon, 12 Oct 2026 19:02:41 +0530 Subject: [PATCH] fix(barcode-scanner): settle the pending scan() promise on cancel (fix #3560) (#3571) On Android, cancel() called destroy() first, and destroy() sets savedInvoke to null, so the savedInvoke?.reject("cancelled") that follows was a no-op. The pending scan() promise was never settled and callers awaiting it were stranded, which is especially bad in windowed mode where the page background stays transparent. Reject the pending invoke before tearing the camera down, matching the order the iOS implementation already uses. --- .changes/barcode-scanner-cancel-settles-scan.md | 6 ++++++ .../android/src/main/java/BarcodeScannerPlugin.kt | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 .changes/barcode-scanner-cancel-settles-scan.md diff --git a/.changes/barcode-scanner-cancel-settles-scan.md b/.changes/barcode-scanner-cancel-settles-scan.md new file mode 100644 index 000000000..8d51ff25f --- /dev/null +++ b/.changes/barcode-scanner-cancel-settles-scan.md @@ -0,0 +1,6 @@ +--- +"barcode-scanner": patch +"barcode-scanner-js": patch +--- + +Fix `cancel()` on Android leaving the pending `scan()` promise unsettled: `destroy()` cleared the saved invoke before it was rejected, so the `"cancelled"` rejection never reached the caller. The pending scan is now rejected before the camera is torn down, matching iOS. diff --git a/plugins/barcode-scanner/android/src/main/java/BarcodeScannerPlugin.kt b/plugins/barcode-scanner/android/src/main/java/BarcodeScannerPlugin.kt index 957240d50..4ac921943 100644 --- a/plugins/barcode-scanner/android/src/main/java/BarcodeScannerPlugin.kt +++ b/plugins/barcode-scanner/android/src/main/java/BarcodeScannerPlugin.kt @@ -332,8 +332,10 @@ class BarcodeScannerPlugin(private val activity: Activity) : Plugin(activity), @Command fun cancel(invoke: Invoke) { - destroy() + // Reject the pending scan before destroy() clears savedInvoke, otherwise the + // scan() promise is never settled. Mirrors the iOS implementation. savedInvoke?.reject("cancelled") + destroy() invoke.resolve() }