Committed by
GitHub
Merge pull request #406 from p-mazhnik/pavel/ios-torch
fix(ios): fix torch
Showing
3 changed files
with
31 additions
and
25 deletions
| @@ -22,10 +22,10 @@ Features: | @@ -22,10 +22,10 @@ Features: | ||
| 22 | * Added a new `placeholderBuilder` function to the `MobileScanner` widget to customize the preview placeholder. | 22 | * Added a new `placeholderBuilder` function to the `MobileScanner` widget to customize the preview placeholder. |
| 23 | * Added `autoStart` parameter to MobileScannerController(). If set to false, controller won't start automatically. | 23 | * Added `autoStart` parameter to MobileScannerController(). If set to false, controller won't start automatically. |
| 24 | * Added `hasTorch` function on MobileScannerController(). After starting the controller, you can check if the device has a torch. | 24 | * Added `hasTorch` function on MobileScannerController(). After starting the controller, you can check if the device has a torch. |
| 25 | +* [iOS] Support `torchEnabled` parameter from MobileScannerController() on iOS | ||
| 25 | * [Web] Added ability to use custom barcode scanning js libraries | 26 | * [Web] Added ability to use custom barcode scanning js libraries |
| 26 | by extending `WebBarcodeReaderBase` class and changing `barCodeReader` property in `MobileScannerWebPlugin` | 27 | by extending `WebBarcodeReaderBase` class and changing `barCodeReader` property in `MobileScannerWebPlugin` |
| 27 | 28 | ||
| 28 | - | ||
| 29 | Fixes: | 29 | Fixes: |
| 30 | * Fixes the missing gradle setup for the Android project, which prevented gradle sync from working. | 30 | * Fixes the missing gradle setup for the Android project, which prevented gradle sync from working. |
| 31 | * Fixes `MobileScannerController.stop()` throwing when already stopped. | 31 | * Fixes `MobileScannerController.stop()` throwing when already stopped. |
| @@ -35,6 +35,7 @@ Fixes: | @@ -35,6 +35,7 @@ Fixes: | ||
| 35 | * Fixes the `MobileScanner` preview depending on all attributes of `MediaQueryData`. | 35 | * Fixes the `MobileScanner` preview depending on all attributes of `MediaQueryData`. |
| 36 | Now it only depends on its layout constraints. | 36 | Now it only depends on its layout constraints. |
| 37 | * Fixed a potential crash when the scanner is restarted due to the app being resumed. | 37 | * Fixed a potential crash when the scanner is restarted due to the app being resumed. |
| 38 | +* [iOS] Fix crash when changing torch state | ||
| 38 | 39 | ||
| 39 | ## 3.0.0-beta.2 | 40 | ## 3.0.0-beta.2 |
| 40 | Breaking changes: | 41 | Breaking changes: |
| @@ -12,6 +12,7 @@ import MLKitVision | @@ -12,6 +12,7 @@ import MLKitVision | ||
| 12 | import MLKitBarcodeScanning | 12 | import MLKitBarcodeScanning |
| 13 | 13 | ||
| 14 | typealias MobileScannerCallback = ((Array<Barcode>?, Error?, UIImage) -> ()) | 14 | typealias MobileScannerCallback = ((Array<Barcode>?, Error?, UIImage) -> ()) |
| 15 | +typealias TorchModeChangeCallback = ((Int?) -> ()) | ||
| 15 | 16 | ||
| 16 | public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, FlutterTexture { | 17 | public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelegate, FlutterTexture { |
| 17 | /// Capture session of the camera | 18 | /// Capture session of the camera |
| @@ -32,6 +33,9 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -32,6 +33,9 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 32 | /// When results are found, this callback will be called | 33 | /// When results are found, this callback will be called |
| 33 | let mobileScannerCallback: MobileScannerCallback | 34 | let mobileScannerCallback: MobileScannerCallback |
| 34 | 35 | ||
| 36 | + /// When torch mode is changes, this callback will be called | ||
| 37 | + let torchModeChangeCallback: TorchModeChangeCallback | ||
| 38 | + | ||
| 35 | /// If provided, the Flutter registry will be used to send the output of the CaptureOutput to a Flutter texture. | 39 | /// If provided, the Flutter registry will be used to send the output of the CaptureOutput to a Flutter texture. |
| 36 | private let registry: FlutterTextureRegistry? | 40 | private let registry: FlutterTextureRegistry? |
| 37 | 41 | ||
| @@ -43,9 +47,10 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -43,9 +47,10 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 43 | 47 | ||
| 44 | var detectionSpeed: DetectionSpeed = DetectionSpeed.noDuplicates | 48 | var detectionSpeed: DetectionSpeed = DetectionSpeed.noDuplicates |
| 45 | 49 | ||
| 46 | - init(registry: FlutterTextureRegistry?, mobileScannerCallback: @escaping MobileScannerCallback) { | 50 | + init(registry: FlutterTextureRegistry?, mobileScannerCallback: @escaping MobileScannerCallback, torchModeChangeCallback: @escaping TorchModeChangeCallback) { |
| 47 | self.registry = registry | 51 | self.registry = registry |
| 48 | self.mobileScannerCallback = mobileScannerCallback | 52 | self.mobileScannerCallback = mobileScannerCallback |
| 53 | + self.torchModeChangeCallback = torchModeChangeCallback | ||
| 49 | super.init() | 54 | super.init() |
| 50 | } | 55 | } |
| 51 | 56 | ||
| @@ -127,17 +132,6 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -127,17 +132,6 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 127 | throw MobileScannerError.noCamera | 132 | throw MobileScannerError.noCamera |
| 128 | } | 133 | } |
| 129 | 134 | ||
| 130 | - // Enable the torch if parameter is set and torch is available | ||
| 131 | - if (device.hasTorch && device.isTorchAvailable) { | ||
| 132 | - do { | ||
| 133 | - try device.lockForConfiguration() | ||
| 134 | - device.torchMode = torch | ||
| 135 | - device.unlockForConfiguration() | ||
| 136 | - } catch { | ||
| 137 | - throw MobileScannerError.torchError(error) | ||
| 138 | - } | ||
| 139 | - } | ||
| 140 | - | ||
| 141 | device.addObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode), options: .new, context: nil) | 135 | device.addObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode), options: .new, context: nil) |
| 142 | captureSession.beginConfiguration() | 136 | captureSession.beginConfiguration() |
| 143 | 137 | ||
| @@ -169,6 +163,13 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -169,6 +163,13 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 169 | } | 163 | } |
| 170 | captureSession.commitConfiguration() | 164 | captureSession.commitConfiguration() |
| 171 | captureSession.startRunning() | 165 | captureSession.startRunning() |
| 166 | + // Enable the torch if parameter is set and torch is available | ||
| 167 | + // torch should be set after 'startRunning' is called | ||
| 168 | + do { | ||
| 169 | + try toggleTorch(torch) | ||
| 170 | + } catch { | ||
| 171 | + print("Failed to set initial torch state.") | ||
| 172 | + } | ||
| 172 | let dimensions = CMVideoFormatDescriptionGetDimensions(device.activeFormat.formatDescription) | 173 | let dimensions = CMVideoFormatDescriptionGetDimensions(device.activeFormat.formatDescription) |
| 173 | 174 | ||
| 174 | return MobileScannerStartParameters(width: Double(dimensions.height), height: Double(dimensions.width), hasTorch: device.hasTorch, textureId: textureId) | 175 | return MobileScannerStartParameters(width: Double(dimensions.height), height: Double(dimensions.width), hasTorch: device.hasTorch, textureId: textureId) |
| @@ -198,6 +199,7 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -198,6 +199,7 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 198 | if (device == nil) { | 199 | if (device == nil) { |
| 199 | throw MobileScannerError.torchWhenStopped | 200 | throw MobileScannerError.torchWhenStopped |
| 200 | } | 201 | } |
| 202 | + if (device.hasTorch && device.isTorchAvailable) { | ||
| 201 | do { | 203 | do { |
| 202 | try device.lockForConfiguration() | 204 | try device.lockForConfiguration() |
| 203 | device.torchMode = torch | 205 | device.torchMode = torch |
| @@ -206,6 +208,19 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | @@ -206,6 +208,19 @@ public class MobileScanner: NSObject, AVCaptureVideoDataOutputSampleBufferDelega | ||
| 206 | throw MobileScannerError.torchError(error) | 208 | throw MobileScannerError.torchError(error) |
| 207 | } | 209 | } |
| 208 | } | 210 | } |
| 211 | + } | ||
| 212 | + | ||
| 213 | + // Observer for torch state | ||
| 214 | + public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { | ||
| 215 | + switch keyPath { | ||
| 216 | + case "torchMode": | ||
| 217 | + // off = 0; on = 1; auto = 2; | ||
| 218 | + let state = change?[.newKey] as? Int | ||
| 219 | + torchModeChangeCallback(state) | ||
| 220 | + default: | ||
| 221 | + break | ||
| 222 | + } | ||
| 223 | + } | ||
| 209 | 224 | ||
| 210 | /// Analyze a single image | 225 | /// Analyze a single image |
| 211 | func analyzeImage(image: UIImage, position: AVCaptureDevice.Position, callback: @escaping BarcodeScanningCallback) { | 226 | func analyzeImage(image: UIImage, position: AVCaptureDevice.Position, callback: @escaping BarcodeScanningCallback) { |
| @@ -55,6 +55,8 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin { | @@ -55,6 +55,8 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin { | ||
| 55 | } else if (error != nil){ | 55 | } else if (error != nil){ |
| 56 | barcodeHandler.publishEvent(["name": "error", "data": error!.localizedDescription]) | 56 | barcodeHandler.publishEvent(["name": "error", "data": error!.localizedDescription]) |
| 57 | } | 57 | } |
| 58 | + }, torchModeChangeCallback: { torchState in | ||
| 59 | + barcodeHandler.publishEvent(["name": "torchState", "data": torchState]) | ||
| 58 | }) | 60 | }) |
| 59 | self.barcodeHandler = barcodeHandler | 61 | self.barcodeHandler = barcodeHandler |
| 60 | super.init() | 62 | super.init() |
| @@ -201,16 +203,4 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin { | @@ -201,16 +203,4 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin { | ||
| 201 | }) | 203 | }) |
| 202 | result(nil) | 204 | result(nil) |
| 203 | } | 205 | } |
| 204 | - | ||
| 205 | - /// Observer for torch state | ||
| 206 | - public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { | ||
| 207 | - switch keyPath { | ||
| 208 | - case "torchMode": | ||
| 209 | - // off = 0; on = 1; auto = 2; | ||
| 210 | - let state = change?[.newKey] as? Int | ||
| 211 | - barcodeHandler.publishEvent(["name": "torchState", "data": state]) | ||
| 212 | - default: | ||
| 213 | - break | ||
| 214 | - } | ||
| 215 | - } | ||
| 216 | } | 206 | } |
-
Please register or login to post a comment