Committed by
GitHub
Merge pull request #826 from navaronbracke/fix_platform_messages_threading
fix: Fix platform messages threading
Showing
7 changed files
with
61 additions
and
47 deletions
| @@ -15,6 +15,7 @@ Bugs fixed: | @@ -15,6 +15,7 @@ Bugs fixed: | ||
| 15 | * Fixed the default values for the `format` and `type` arguments of the Barcode constructor. | 15 | * Fixed the default values for the `format` and `type` arguments of the Barcode constructor. |
| 16 | These now use `BarcodeFormat.unknown` and `BarcodeType.unknown`, rather than `BarcodeFormat.ean13` and `BarcodeType.text`. | 16 | These now use `BarcodeFormat.unknown` and `BarcodeType.unknown`, rather than `BarcodeFormat.ean13` and `BarcodeType.text`. |
| 17 | (thanks @navaronbracke !) | 17 | (thanks @navaronbracke !) |
| 18 | +* Fixed messages not being sent on the main thread for Android, iOS and MacOS. (thanks @navaronbracke !) | ||
| 18 | 19 | ||
| 19 | ## 3.5.0 | 20 | ## 3.5.0 |
| 20 | New Features: | 21 | New Features: |
| @@ -2,6 +2,8 @@ package dev.steenbakker.mobile_scanner | @@ -2,6 +2,8 @@ package dev.steenbakker.mobile_scanner | ||
| 2 | 2 | ||
| 3 | import android.app.Activity | 3 | import android.app.Activity |
| 4 | import android.net.Uri | 4 | import android.net.Uri |
| 5 | +import android.os.Handler | ||
| 6 | +import android.os.Looper | ||
| 5 | import android.util.Size | 7 | import android.util.Size |
| 6 | import androidx.camera.core.CameraSelector | 8 | import androidx.camera.core.CameraSelector |
| 7 | import androidx.camera.core.ExperimentalGetImage | 9 | import androidx.camera.core.ExperimentalGetImage |
| @@ -30,11 +32,12 @@ class MobileScannerHandler( | @@ -30,11 +32,12 @@ class MobileScannerHandler( | ||
| 30 | "name" to "barcode", | 32 | "name" to "barcode", |
| 31 | "data" to barcodes | 33 | "data" to barcodes |
| 32 | )) | 34 | )) |
| 33 | - analyzerResult?.success(true) | ||
| 34 | - } else { | ||
| 35 | - analyzerResult?.success(false) | ||
| 36 | } | 35 | } |
| 37 | - analyzerResult = null | 36 | + |
| 37 | + Handler(Looper.getMainLooper()).post { | ||
| 38 | + analyzerResult?.success(barcodes != null) | ||
| 39 | + analyzerResult = null | ||
| 40 | + } | ||
| 38 | } | 41 | } |
| 39 | 42 | ||
| 40 | private var analyzerResult: MethodChannel.Result? = null | 43 | private var analyzerResult: MethodChannel.Result? = null |
| @@ -92,7 +95,6 @@ class MobileScannerHandler( | @@ -92,7 +95,6 @@ class MobileScannerHandler( | ||
| 92 | if(listener != null) { | 95 | if(listener != null) { |
| 93 | activityPluginBinding.removeRequestPermissionsResultListener(listener) | 96 | activityPluginBinding.removeRequestPermissionsResultListener(listener) |
| 94 | } | 97 | } |
| 95 | - | ||
| 96 | } | 98 | } |
| 97 | 99 | ||
| 98 | @ExperimentalGetImage | 100 | @ExperimentalGetImage |
| @@ -173,11 +175,13 @@ class MobileScannerHandler( | @@ -173,11 +175,13 @@ class MobileScannerHandler( | ||
| 173 | torchStateCallback, | 175 | torchStateCallback, |
| 174 | zoomScaleStateCallback, | 176 | zoomScaleStateCallback, |
| 175 | mobileScannerStartedCallback = { | 177 | mobileScannerStartedCallback = { |
| 176 | - result.success(mapOf( | ||
| 177 | - "textureId" to it.id, | ||
| 178 | - "size" to mapOf("width" to it.width, "height" to it.height), | ||
| 179 | - "torchable" to it.hasFlashUnit | ||
| 180 | - )) | 178 | + Handler(Looper.getMainLooper()).post { |
| 179 | + result.success(mapOf( | ||
| 180 | + "textureId" to it.id, | ||
| 181 | + "size" to mapOf("width" to it.width, "height" to it.height), | ||
| 182 | + "torchable" to it.hasFlashUnit | ||
| 183 | + )) | ||
| 184 | + } | ||
| 181 | }, | 185 | }, |
| 182 | timeout.toLong(), | 186 | timeout.toLong(), |
| 183 | cameraResolution, | 187 | cameraResolution, |
| @@ -9,9 +9,6 @@ import Flutter | @@ -9,9 +9,6 @@ import Flutter | ||
| 9 | import Foundation | 9 | import Foundation |
| 10 | 10 | ||
| 11 | public class BarcodeHandler: NSObject, FlutterStreamHandler { | 11 | public class BarcodeHandler: NSObject, FlutterStreamHandler { |
| 12 | - | ||
| 13 | - var event: [String: Any?] = [:] | ||
| 14 | - | ||
| 15 | private var eventSink: FlutterEventSink? | 12 | private var eventSink: FlutterEventSink? |
| 16 | private let eventChannel: FlutterEventChannel | 13 | private let eventChannel: FlutterEventChannel |
| 17 | 14 | ||
| @@ -23,8 +20,9 @@ public class BarcodeHandler: NSObject, FlutterStreamHandler { | @@ -23,8 +20,9 @@ public class BarcodeHandler: NSObject, FlutterStreamHandler { | ||
| 23 | } | 20 | } |
| 24 | 21 | ||
| 25 | func publishEvent(_ event: [String: Any?]) { | 22 | func publishEvent(_ event: [String: Any?]) { |
| 26 | - self.event = event | ||
| 27 | - eventSink?(event) | 23 | + DispatchQueue.main.async { |
| 24 | + self.eventSink?(event) | ||
| 25 | + } | ||
| 28 | } | 26 | } |
| 29 | 27 | ||
| 30 | public func onListen(withArguments arguments: Any?, | 28 | public func onListen(withArguments arguments: Any?, |
| @@ -232,23 +232,19 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -232,23 +232,19 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 232 | device.activeFormat.formatDescription) | 232 | device.activeFormat.formatDescription) |
| 233 | let hasTorch = device.hasTorch | 233 | let hasTorch = device.hasTorch |
| 234 | 234 | ||
| 235 | - DispatchQueue.main.async { | ||
| 236 | - completion( | ||
| 237 | - MobileScannerStartParameters( | ||
| 238 | - width: Double(dimensions.height), | ||
| 239 | - height: Double(dimensions.width), | ||
| 240 | - hasTorch: hasTorch, | ||
| 241 | - textureId: self.textureId ?? 0 | ||
| 242 | - ) | 235 | + completion( |
| 236 | + MobileScannerStartParameters( | ||
| 237 | + width: Double(dimensions.height), | ||
| 238 | + height: Double(dimensions.width), | ||
| 239 | + hasTorch: hasTorch, | ||
| 240 | + textureId: self.textureId ?? 0 | ||
| 243 | ) | 241 | ) |
| 244 | - } | 242 | + ) |
| 245 | 243 | ||
| 246 | return | 244 | return |
| 247 | } | 245 | } |
| 248 | 246 | ||
| 249 | - DispatchQueue.main.async { | ||
| 250 | - completion(MobileScannerStartParameters()) | ||
| 251 | - } | 247 | + completion(MobileScannerStartParameters()) |
| 252 | } | 248 | } |
| 253 | } | 249 | } |
| 254 | 250 |
| @@ -121,7 +121,12 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | @@ -121,7 +121,12 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | ||
| 121 | 121 | ||
| 122 | do { | 122 | do { |
| 123 | try mobileScanner.start(barcodeScannerOptions: barcodeOptions, returnImage: returnImage, cameraPosition: position, torch: torch ? .on : .off, detectionSpeed: detectionSpeed) { parameters in | 123 | try mobileScanner.start(barcodeScannerOptions: barcodeOptions, returnImage: returnImage, cameraPosition: position, torch: torch ? .on : .off, detectionSpeed: detectionSpeed) { parameters in |
| 124 | - result(["textureId": parameters.textureId, "size": ["width": parameters.width, "height": parameters.height], "torchable": parameters.hasTorch]) | 124 | + DispatchQueue.main.async { |
| 125 | + result([ | ||
| 126 | + "textureId": parameters.textureId, | ||
| 127 | + "size": ["width": parameters.width, "height": parameters.height], | ||
| 128 | + "torchable": parameters.hasTorch]) | ||
| 129 | + } | ||
| 125 | } | 130 | } |
| 126 | } catch MobileScannerError.alreadyStarted { | 131 | } catch MobileScannerError.alreadyStarted { |
| 127 | result(FlutterError(code: "MobileScanner", | 132 | result(FlutterError(code: "MobileScanner", |
| @@ -158,12 +163,12 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | @@ -158,12 +163,12 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | ||
| 158 | private func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | 163 | private func toggleTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { |
| 159 | do { | 164 | do { |
| 160 | try mobileScanner.toggleTorch(call.arguments as? Int == 1 ? .on : .off) | 165 | try mobileScanner.toggleTorch(call.arguments as? Int == 1 ? .on : .off) |
| 166 | + result(nil) | ||
| 161 | } catch { | 167 | } catch { |
| 162 | result(FlutterError(code: "MobileScanner", | 168 | result(FlutterError(code: "MobileScanner", |
| 163 | message: "Called toggleTorch() while stopped!", | 169 | message: "Called toggleTorch() while stopped!", |
| 164 | details: nil)) | 170 | details: nil)) |
| 165 | } | 171 | } |
| 166 | - result(nil) | ||
| 167 | } | 172 | } |
| 168 | 173 | ||
| 169 | /// Toggles the zoomScale | 174 | /// Toggles the zoomScale |
| @@ -177,6 +182,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | @@ -177,6 +182,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | ||
| 177 | } | 182 | } |
| 178 | do { | 183 | do { |
| 179 | try mobileScanner.setScale(scale!) | 184 | try mobileScanner.setScale(scale!) |
| 185 | + result(nil) | ||
| 180 | } catch MobileScannerError.zoomWhenStopped { | 186 | } catch MobileScannerError.zoomWhenStopped { |
| 181 | result(FlutterError(code: "MobileScanner", | 187 | result(FlutterError(code: "MobileScanner", |
| 182 | message: "Called setScale() while stopped!", | 188 | message: "Called setScale() while stopped!", |
| @@ -190,13 +196,13 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | @@ -190,13 +196,13 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | ||
| 190 | message: "Error while zooming.", | 196 | message: "Error while zooming.", |
| 191 | details: nil)) | 197 | details: nil)) |
| 192 | } | 198 | } |
| 193 | - result(nil) | ||
| 194 | } | 199 | } |
| 195 | 200 | ||
| 196 | /// Reset the zoomScale | 201 | /// Reset the zoomScale |
| 197 | private func resetScale(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | 202 | private func resetScale(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { |
| 198 | do { | 203 | do { |
| 199 | try mobileScanner.resetScale() | 204 | try mobileScanner.resetScale() |
| 205 | + result(nil) | ||
| 200 | } catch MobileScannerError.zoomWhenStopped { | 206 | } catch MobileScannerError.zoomWhenStopped { |
| 201 | result(FlutterError(code: "MobileScanner", | 207 | result(FlutterError(code: "MobileScanner", |
| 202 | message: "Called resetScale() while stopped!", | 208 | message: "Called resetScale() while stopped!", |
| @@ -210,7 +216,6 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | @@ -210,7 +216,6 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | ||
| 210 | message: "Error while zooming.", | 216 | message: "Error while zooming.", |
| 211 | details: nil)) | 217 | details: nil)) |
| 212 | } | 218 | } |
| 213 | - result(nil) | ||
| 214 | } | 219 | } |
| 215 | 220 | ||
| 216 | /// Toggles the torch | 221 | /// Toggles the torch |
| @@ -247,16 +252,28 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | @@ -247,16 +252,28 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin { | ||
| 247 | } | 252 | } |
| 248 | 253 | ||
| 249 | mobileScanner.analyzeImage(image: uiImage!, position: AVCaptureDevice.Position.back, callback: { [self] barcodes, error in | 254 | mobileScanner.analyzeImage(image: uiImage!, position: AVCaptureDevice.Position.back, callback: { [self] barcodes, error in |
| 250 | - if error == nil && barcodes != nil && !barcodes!.isEmpty { | 255 | + if error != nil { |
| 256 | + barcodeHandler.publishEvent(["name": "error", "message": error?.localizedDescription]) | ||
| 257 | + | ||
| 258 | + DispatchQueue.main.async { | ||
| 259 | + result(false) | ||
| 260 | + } | ||
| 261 | + | ||
| 262 | + return | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + if (barcodes == nil || barcodes!.isEmpty) { | ||
| 266 | + DispatchQueue.main.async { | ||
| 267 | + result(false) | ||
| 268 | + } | ||
| 269 | + } else { | ||
| 251 | let barcodesMap: [Any?] = barcodes!.compactMap { barcode in barcode.data } | 270 | let barcodesMap: [Any?] = barcodes!.compactMap { barcode in barcode.data } |
| 252 | let event: [String: Any?] = ["name": "barcode", "data": barcodesMap] | 271 | let event: [String: Any?] = ["name": "barcode", "data": barcodesMap] |
| 253 | barcodeHandler.publishEvent(event) | 272 | barcodeHandler.publishEvent(event) |
| 254 | - result(true) | ||
| 255 | - } else { | ||
| 256 | - if error != nil { | ||
| 257 | - barcodeHandler.publishEvent(["name": "error", "message": error?.localizedDescription]) | 273 | + |
| 274 | + DispatchQueue.main.async { | ||
| 275 | + result(true) | ||
| 258 | } | 276 | } |
| 259 | - result(false) | ||
| 260 | } | 277 | } |
| 261 | }) | 278 | }) |
| 262 | } | 279 | } |
| 1 | import AVFoundation | 1 | import AVFoundation |
| 2 | -import Flutter | ||
| 3 | import Foundation | 2 | import Foundation |
| 4 | import MLKitBarcodeScanning | 3 | import MLKitBarcodeScanning |
| 5 | 4 | ||
| 6 | -extension Error { | ||
| 7 | - func throwNative(_ result: FlutterResult) { | ||
| 8 | - let error = FlutterError(code: localizedDescription, message: nil, details: nil) | ||
| 9 | - result(error) | ||
| 10 | - } | ||
| 11 | -} | ||
| 12 | - | ||
| 13 | extension CVBuffer { | 5 | extension CVBuffer { |
| 14 | var image: UIImage { | 6 | var image: UIImage { |
| 15 | let ciImage = CIImage(cvPixelBuffer: self) | 7 | let ciImage = CIImage(cvPixelBuffer: self) |
| @@ -144,7 +144,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | @@ -144,7 +144,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | ||
| 144 | } | 144 | } |
| 145 | } | 145 | } |
| 146 | } else { | 146 | } else { |
| 147 | - self?.sink?(FlutterError(code: "MobileScanner", message: error?.localizedDescription, details: nil)) | 147 | + DispatchQueue.main.async { |
| 148 | + self?.sink?(FlutterError(code: "MobileScanner", message: error?.localizedDescription, details: nil)) | ||
| 149 | + } | ||
| 148 | } | 150 | } |
| 149 | }) | 151 | }) |
| 150 | if(self?.symbologies.isEmpty == false){ | 152 | if(self?.symbologies.isEmpty == false){ |
| @@ -153,7 +155,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | @@ -153,7 +155,9 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | ||
| 153 | } | 155 | } |
| 154 | try imageRequestHandler.perform([barcodeRequest]) | 156 | try imageRequestHandler.perform([barcodeRequest]) |
| 155 | } catch let e { | 157 | } catch let e { |
| 156 | - self?.sink?(FlutterError(code: "MobileScanner", message: e.localizedDescription, details: nil)) | 158 | + DispatchQueue.main.async { |
| 159 | + self?.sink?(FlutterError(code: "MobileScanner", message: e.localizedDescription, details: nil)) | ||
| 160 | + } | ||
| 157 | } | 161 | } |
| 158 | } | 162 | } |
| 159 | } | 163 | } |
| @@ -276,6 +280,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | @@ -276,6 +280,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | ||
| 276 | device.unlockForConfiguration() | 280 | device.unlockForConfiguration() |
| 277 | } catch { | 281 | } catch { |
| 278 | result(FlutterError(code: error.localizedDescription, message: nil, details: nil)) | 282 | result(FlutterError(code: error.localizedDescription, message: nil, details: nil)) |
| 283 | + return | ||
| 279 | } | 284 | } |
| 280 | } | 285 | } |
| 281 | 286 | ||
| @@ -288,6 +293,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | @@ -288,6 +293,7 @@ public class MobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, | ||
| 288 | captureSession.addInput(input) | 293 | captureSession.addInput(input) |
| 289 | } catch { | 294 | } catch { |
| 290 | result(FlutterError(code: error.localizedDescription, message: nil, details: nil)) | 295 | result(FlutterError(code: error.localizedDescription, message: nil, details: nil)) |
| 296 | + return | ||
| 291 | } | 297 | } |
| 292 | captureSession.sessionPreset = AVCaptureSession.Preset.photo | 298 | captureSession.sessionPreset = AVCaptureSession.Preset.photo |
| 293 | // Add video output. | 299 | // Add video output. |
-
Please register or login to post a comment