Merge branch 'master' into dependabot/github_actions/subosito/flutter-action-2.3.0
Showing
17 changed files
with
157 additions
and
81 deletions
| 1 | ## 0.0.1 | 1 | ## 0.0.1 |
| 2 | +Initial release! | ||
| 3 | +Things working on Android: | ||
| 4 | +* Scanning barcodes using the latest version of MLKit and CameraX! | ||
| 5 | +* Switching camera's | ||
| 6 | +* Toggling of the torch (flash) | ||
| 2 | 7 | ||
| 3 | -* TODO: Describe initial release. | 8 | +Things working on iOS: |
| 9 | +* Scanning barcodes using the latest version of MLKit and AVFoundation! |
| 1 | -TODO: Add your license here. | 1 | +BSD 3-Clause License |
| 2 | + | ||
| 3 | +Copyright (c) 2022, Julian Steenbakker | ||
| 4 | +All rights reserved. | ||
| 5 | + | ||
| 6 | +Redistribution and use in source and binary forms, with or without | ||
| 7 | +modification, are permitted provided that the following conditions are met: | ||
| 8 | + | ||
| 9 | +1. Redistributions of source code must retain the above copyright notice, this | ||
| 10 | + list of conditions and the following disclaimer. | ||
| 11 | + | ||
| 12 | +2. Redistributions in binary form must reproduce the above copyright notice, | ||
| 13 | + this list of conditions and the following disclaimer in the documentation | ||
| 14 | + and/or other materials provided with the distribution. | ||
| 15 | + | ||
| 16 | +3. Neither the name of the copyright holder nor the names of its | ||
| 17 | + contributors may be used to endorse or promote products derived from | ||
| 18 | + this software without specific prior written permission. | ||
| 19 | + | ||
| 20 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 21 | +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 22 | +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
| 23 | +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||
| 24 | +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 25 | +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||
| 26 | +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||
| 27 | +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||
| 28 | +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| 29 | +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| @@ -6,7 +6,7 @@ buildscript { | @@ -6,7 +6,7 @@ buildscript { | ||
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | dependencies { | 8 | dependencies { |
| 9 | - classpath 'com.android.tools.build:gradle:7.1.0' | 9 | + classpath 'com.android.tools.build:gradle:7.1.1' |
| 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" |
| 11 | } | 11 | } |
| 12 | } | 12 | } |
| 1 | -#Tue Feb 08 10:35:11 CET 2022 | 1 | +#Tue Feb 15 22:11:04 CET 2022 |
| 2 | distributionBase=GRADLE_USER_HOME | 2 | distributionBase=GRADLE_USER_HOME |
| 3 | -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip | 3 | +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip |
| 4 | distributionPath=wrapper/dists | 4 | distributionPath=wrapper/dists |
| 5 | zipStorePath=wrapper/dists | 5 | zipStorePath=wrapper/dists |
| 6 | zipStoreBase=GRADLE_USER_HOME | 6 | zipStoreBase=GRADLE_USER_HOME |
| 1 | -import 'dart:ui'; | ||
| 2 | - | ||
| 3 | import 'package:flutter/material.dart'; | 1 | import 'package:flutter/material.dart'; |
| 4 | import 'package:mobile_scanner/mobile_scanner.dart'; | 2 | import 'package:mobile_scanner/mobile_scanner.dart'; |
| 5 | 3 | ||
| @@ -18,8 +16,10 @@ class _AnalyzeViewState extends State<AnalyzeView> | @@ -18,8 +16,10 @@ class _AnalyzeViewState extends State<AnalyzeView> | ||
| 18 | with SingleTickerProviderStateMixin { | 16 | with SingleTickerProviderStateMixin { |
| 19 | String? barcode; | 17 | String? barcode; |
| 20 | 18 | ||
| 21 | - MobileScannerController controller = MobileScannerController(torchEnabled: true, | ||
| 22 | - facing: CameraFacing.front,); | 19 | + MobileScannerController controller = MobileScannerController( |
| 20 | + torchEnabled: true, | ||
| 21 | + facing: CameraFacing.front, | ||
| 22 | + ); | ||
| 23 | 23 | ||
| 24 | @override | 24 | @override |
| 25 | Widget build(BuildContext context) { | 25 | Widget build(BuildContext context) { |
| @@ -60,9 +60,11 @@ class _AnalyzeViewState extends State<AnalyzeView> | @@ -60,9 +60,11 @@ class _AnalyzeViewState extends State<AnalyzeView> | ||
| 60 | builder: (context, state, child) { | 60 | builder: (context, state, child) { |
| 61 | switch (state as TorchState) { | 61 | switch (state as TorchState) { |
| 62 | case TorchState.off: | 62 | case TorchState.off: |
| 63 | - return const Icon(Icons.flash_off, color: Colors.grey); | 63 | + return const Icon(Icons.flash_off, |
| 64 | + color: Colors.grey); | ||
| 64 | case TorchState.on: | 65 | case TorchState.on: |
| 65 | - return const Icon(Icons.flash_on, color: Colors.yellow); | 66 | + return const Icon(Icons.flash_on, |
| 67 | + color: Colors.yellow); | ||
| 66 | } | 68 | } |
| 67 | }, | 69 | }, |
| 68 | ), | 70 | ), |
| @@ -20,7 +20,7 @@ class _AnalyzeViewState extends State<AnalyzeView> | @@ -20,7 +20,7 @@ class _AnalyzeViewState extends State<AnalyzeView> | ||
| 20 | 20 | ||
| 21 | // CameraController cameraController = CameraController(context, width: 320, height: 150); | 21 | // CameraController cameraController = CameraController(context, width: 320, height: 150); |
| 22 | 22 | ||
| 23 | - String? barcode = null; | 23 | + String? barcode; |
| 24 | 24 | ||
| 25 | @override | 25 | @override |
| 26 | Widget build(BuildContext context) { | 26 | Widget build(BuildContext context) { |
| @@ -37,20 +37,21 @@ class _AnalyzeViewState extends State<AnalyzeView> | @@ -37,20 +37,21 @@ class _AnalyzeViewState extends State<AnalyzeView> | ||
| 37 | this.barcode = barcode.rawValue; | 37 | this.barcode = barcode.rawValue; |
| 38 | if (barcode.corners != null) { | 38 | if (barcode.corners != null) { |
| 39 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( | 39 | ScaffoldMessenger.of(context).showSnackBar(SnackBar( |
| 40 | - content: Text('${barcode.rawValue}'), | 40 | + content: Text(barcode.rawValue), |
| 41 | duration: const Duration(milliseconds: 200), | 41 | duration: const Duration(milliseconds: 200), |
| 42 | animation: null, | 42 | animation: null, |
| 43 | )); | 43 | )); |
| 44 | setState(() { | 44 | setState(() { |
| 45 | final List<Offset> points = []; | 45 | final List<Offset> points = []; |
| 46 | - double factorWidth = args.size.width / 520; | 46 | + // double factorWidth = args.size.width / 520; |
| 47 | // double factorHeight = wanted / args.size.height; | 47 | // double factorHeight = wanted / args.size.height; |
| 48 | final size = MediaQuery.of(context).devicePixelRatio; | 48 | final size = MediaQuery.of(context).devicePixelRatio; |
| 49 | debugPrint('Size: ${barcode.corners}'); | 49 | debugPrint('Size: ${barcode.corners}'); |
| 50 | for (var point in barcode.corners!) { | 50 | for (var point in barcode.corners!) { |
| 51 | - final adjustedWith = point.dx ; | ||
| 52 | - final adjustedHeight= point.dy ; | ||
| 53 | - points.add(Offset(adjustedWith / size, adjustedHeight / size)); | 51 | + final adjustedWith = point.dx; |
| 52 | + final adjustedHeight = point.dy; | ||
| 53 | + points.add( | ||
| 54 | + Offset(adjustedWith / size, adjustedHeight / size)); | ||
| 54 | // points.add(Offset((point.dx ) / size, | 55 | // points.add(Offset((point.dx ) / size, |
| 55 | // (point.dy) / size)); | 56 | // (point.dy) / size)); |
| 56 | // final differenceWidth = (args.wantedSize!.width - args.size.width) / 2; | 57 | // final differenceWidth = (args.wantedSize!.width - args.size.width) / 2; |
| @@ -108,7 +109,7 @@ class OpenPainter extends CustomPainter { | @@ -108,7 +109,7 @@ class OpenPainter extends CustomPainter { | ||
| 108 | @override | 109 | @override |
| 109 | void paint(Canvas canvas, Size size) { | 110 | void paint(Canvas canvas, Size size) { |
| 110 | var paint1 = Paint() | 111 | var paint1 = Paint() |
| 111 | - ..color = Color(0xff63aa65) | 112 | + ..color = const Color(0xff63aa65) |
| 112 | ..strokeWidth = 10; | 113 | ..strokeWidth = 10; |
| 113 | //draw points on canvas | 114 | //draw points on canvas |
| 114 | canvas.drawPoints(PointMode.points, points, paint1); | 115 | canvas.drawPoints(PointMode.points, points, paint1); |
| @@ -5,11 +5,8 @@ | @@ -5,11 +5,8 @@ | ||
| 5 | // gestures. You can also use WidgetTester to find child widgets in the widget | 5 | // gestures. You can also use WidgetTester to find child widgets in the widget |
| 6 | // tree, read text, and verify that the values of widget properties are correct. | 6 | // tree, read text, and verify that the values of widget properties are correct. |
| 7 | 7 | ||
| 8 | -import 'package:flutter/material.dart'; | ||
| 9 | import 'package:flutter_test/flutter_test.dart'; | 8 | import 'package:flutter_test/flutter_test.dart'; |
| 10 | 9 | ||
| 11 | -import 'package:mobile_scanner_example/main.dart'; | ||
| 12 | - | ||
| 13 | void main() { | 10 | void main() { |
| 14 | testWidgets('Verify Platform version', (WidgetTester tester) async { | 11 | testWidgets('Verify Platform version', (WidgetTester tester) async { |
| 15 | // Build our app and trigger a frame. | 12 | // Build our app and trigger a frame. |
ios/Classes/SwiftMobileScanner.swift
0 → 100644
| @@ -5,61 +5,77 @@ import MLKitBarcodeScanning | @@ -5,61 +5,77 @@ import MLKitBarcodeScanning | ||
| 5 | 5 | ||
| 6 | public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, FlutterTexture, AVCaptureVideoDataOutputSampleBufferDelegate { | 6 | public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, FlutterTexture, AVCaptureVideoDataOutputSampleBufferDelegate { |
| 7 | 7 | ||
| 8 | - public static func register(with registrar: FlutterPluginRegistrar) { | ||
| 9 | - let instance = SwiftMobileScannerPlugin(registrar.textures()) | ||
| 10 | - | ||
| 11 | - let method = FlutterMethodChannel(name: "dev.steenbakker.mobile_scanner/scanner/method", binaryMessenger: registrar.messenger()) | ||
| 12 | - registrar.addMethodCallDelegate(instance, channel: method) | ||
| 13 | - | ||
| 14 | - let event = FlutterEventChannel(name: "dev.steenbakker.mobile_scanner/scanner/event", binaryMessenger: registrar.messenger()) | ||
| 15 | - event.setStreamHandler(instance) | ||
| 16 | - } | ||
| 17 | - | ||
| 18 | let registry: FlutterTextureRegistry | 8 | let registry: FlutterTextureRegistry |
| 9 | + | ||
| 10 | + // Sink for publishing event changes | ||
| 19 | var sink: FlutterEventSink! | 11 | var sink: FlutterEventSink! |
| 12 | + | ||
| 13 | + // Texture id of the camera preview | ||
| 20 | var textureId: Int64! | 14 | var textureId: Int64! |
| 15 | + | ||
| 16 | + // Capture session of the camera | ||
| 21 | var captureSession: AVCaptureSession! | 17 | var captureSession: AVCaptureSession! |
| 18 | + | ||
| 19 | + // The selected camera | ||
| 22 | var device: AVCaptureDevice! | 20 | var device: AVCaptureDevice! |
| 21 | + | ||
| 22 | + // Image to be sent to the texture | ||
| 23 | var latestBuffer: CVImageBuffer! | 23 | var latestBuffer: CVImageBuffer! |
| 24 | - var analyzeMode: Int | ||
| 25 | - var analyzing: Bool | 24 | + |
| 25 | + | ||
| 26 | + var analyzeMode: Int = 0 | ||
| 27 | + var analyzing: Bool = false | ||
| 28 | + var position = AVCaptureDevice.Position.back | ||
| 29 | + | ||
| 30 | + public static func register(with registrar: FlutterPluginRegistrar) { | ||
| 31 | + let instance = SwiftMobileScannerPlugin(registrar.textures()) | ||
| 32 | + | ||
| 33 | + let method = FlutterMethodChannel(name: | ||
| 34 | + "dev.steenbakker.mobile_scanner/scanner/method", binaryMessenger: registrar.messenger()) | ||
| 35 | + let event = FlutterEventChannel(name: | ||
| 36 | + "dev.steenbakker.mobile_scanner/scanner/event", binaryMessenger: registrar.messenger()) | ||
| 37 | + registrar.addMethodCallDelegate(instance, channel: method) | ||
| 38 | + event.setStreamHandler(instance) | ||
| 39 | + } | ||
| 26 | 40 | ||
| 27 | init(_ registry: FlutterTextureRegistry) { | 41 | init(_ registry: FlutterTextureRegistry) { |
| 28 | self.registry = registry | 42 | self.registry = registry |
| 29 | - analyzeMode = 0 | ||
| 30 | - analyzing = false | ||
| 31 | super.init() | 43 | super.init() |
| 32 | } | 44 | } |
| 33 | 45 | ||
| 46 | + | ||
| 34 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { | 47 | public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { |
| 35 | switch call.method { | 48 | switch call.method { |
| 36 | case "state": | 49 | case "state": |
| 37 | - stateNative(call, result) | 50 | + checkPermission(call, result) |
| 38 | case "request": | 51 | case "request": |
| 39 | - requestNative(call, result) | 52 | + requestPermission(call, result) |
| 40 | case "start": | 53 | case "start": |
| 41 | - startNative(call, result) | 54 | + start(call, result) |
| 42 | case "torch": | 55 | case "torch": |
| 43 | - torchNative(call, result) | 56 | + switchTorch(call, result) |
| 44 | case "analyze": | 57 | case "analyze": |
| 45 | - analyzeNative(call, result) | 58 | + switchAnalyzeMode(call, result) |
| 46 | case "stop": | 59 | case "stop": |
| 47 | - stopNative(result) | 60 | + stop(result) |
| 48 | default: | 61 | default: |
| 49 | result(FlutterMethodNotImplemented) | 62 | result(FlutterMethodNotImplemented) |
| 50 | } | 63 | } |
| 51 | } | 64 | } |
| 52 | 65 | ||
| 66 | + // FlutterStreamHandler | ||
| 53 | public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { | 67 | public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { |
| 54 | sink = events | 68 | sink = events |
| 55 | return nil | 69 | return nil |
| 56 | } | 70 | } |
| 57 | 71 | ||
| 72 | + // FlutterStreamHandler | ||
| 58 | public func onCancel(withArguments arguments: Any?) -> FlutterError? { | 73 | public func onCancel(withArguments arguments: Any?) -> FlutterError? { |
| 59 | sink = nil | 74 | sink = nil |
| 60 | return nil | 75 | return nil |
| 61 | } | 76 | } |
| 62 | 77 | ||
| 78 | + // FlutterTexture | ||
| 63 | public func copyPixelBuffer() -> Unmanaged<CVPixelBuffer>? { | 79 | public func copyPixelBuffer() -> Unmanaged<CVPixelBuffer>? { |
| 64 | if latestBuffer == nil { | 80 | if latestBuffer == nil { |
| 65 | return nil | 81 | return nil |
| @@ -67,6 +83,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -67,6 +83,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 67 | return Unmanaged<CVPixelBuffer>.passRetained(latestBuffer) | 83 | return Unmanaged<CVPixelBuffer>.passRetained(latestBuffer) |
| 68 | } | 84 | } |
| 69 | 85 | ||
| 86 | + // Gets called when a new image is added to the buffer | ||
| 70 | public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { | 87 | public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { |
| 71 | 88 | ||
| 72 | latestBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) | 89 | latestBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) |
| @@ -120,7 +137,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -120,7 +137,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 120 | } | 137 | } |
| 121 | } | 138 | } |
| 122 | 139 | ||
| 123 | - func stateNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | 140 | + func checkPermission(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { |
| 124 | let status = AVCaptureDevice.authorizationStatus(for: .video) | 141 | let status = AVCaptureDevice.authorizationStatus(for: .video) |
| 125 | switch status { | 142 | switch status { |
| 126 | case .notDetermined: | 143 | case .notDetermined: |
| @@ -132,34 +149,45 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -132,34 +149,45 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 132 | } | 149 | } |
| 133 | } | 150 | } |
| 134 | 151 | ||
| 135 | - func requestNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | 152 | + func requestPermission(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { |
| 136 | AVCaptureDevice.requestAccess(for: .video, completionHandler: { result($0) }) | 153 | AVCaptureDevice.requestAccess(for: .video, completionHandler: { result($0) }) |
| 137 | } | 154 | } |
| 138 | 155 | ||
| 139 | - var position = AVCaptureDevice.Position.back | ||
| 140 | - | ||
| 141 | - func startNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | 156 | + func start(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { |
| 142 | textureId = registry.register(self) | 157 | textureId = registry.register(self) |
| 143 | captureSession = AVCaptureSession() | 158 | captureSession = AVCaptureSession() |
| 144 | 159 | ||
| 145 | let argReader = MapArgumentReader(call.arguments as? [String: Any]) | 160 | let argReader = MapArgumentReader(call.arguments as? [String: Any]) |
| 146 | 161 | ||
| 147 | - guard let targetWidth = argReader.int(key: "targetWidth"), | ||
| 148 | - let targetHeight = argReader.int(key: "targetHeight"), | ||
| 149 | - let facing = argReader.int(key: "facing") else { | ||
| 150 | - result(FlutterError(code: "INVALID_ARGUMENT", message: "Missing a required argument", details: "Expecting targetWidth, targetHeight, formats, and optionally heartbeatTimeout")) | ||
| 151 | - return | ||
| 152 | - } | 162 | +// let ratio: Int = argReader.int(key: "ratio") |
| 163 | + let torch: Bool = argReader.bool(key: "torch") ?? false | ||
| 164 | + let facing: Int = argReader.int(key: "facing") ?? 1 | ||
| 153 | 165 | ||
| 166 | + // Set the camera to use | ||
| 154 | position = facing == 0 ? AVCaptureDevice.Position.front : .back | 167 | position = facing == 0 ? AVCaptureDevice.Position.front : .back |
| 168 | + | ||
| 169 | + // Open the camera device | ||
| 155 | if #available(iOS 10.0, *) { | 170 | if #available(iOS 10.0, *) { |
| 156 | device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: position).devices.first | 171 | device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: position).devices.first |
| 157 | } else { | 172 | } else { |
| 158 | device = AVCaptureDevice.devices(for: .video).filter({$0.position == position}).first | 173 | device = AVCaptureDevice.devices(for: .video).filter({$0.position == position}).first |
| 159 | } | 174 | } |
| 175 | + | ||
| 176 | + // Enable the torch if parameter is set and torch is available | ||
| 177 | + if (device.hasTorch && device.isTorchAvailable) { | ||
| 178 | + do { | ||
| 179 | + try device.lockForConfiguration() | ||
| 180 | + device.torchMode = torch ? .on : .off | ||
| 181 | + device.unlockForConfiguration() | ||
| 182 | + } catch { | ||
| 183 | + error.throwNative(result) | ||
| 184 | + } | ||
| 185 | + } | ||
| 186 | + | ||
| 160 | device.addObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode), options: .new, context: nil) | 187 | device.addObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode), options: .new, context: nil) |
| 161 | captureSession.beginConfiguration() | 188 | captureSession.beginConfiguration() |
| 162 | - // Add device input. | 189 | + |
| 190 | + // Add device input | ||
| 163 | do { | 191 | do { |
| 164 | let input = try AVCaptureDeviceInput(device: device) | 192 | let input = try AVCaptureDeviceInput(device: device) |
| 165 | captureSession.addInput(input) | 193 | captureSession.addInput(input) |
| @@ -191,7 +219,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -191,7 +219,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 191 | result(answer) | 219 | result(answer) |
| 192 | } | 220 | } |
| 193 | 221 | ||
| 194 | - func torchNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | 222 | + func switchTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { |
| 195 | do { | 223 | do { |
| 196 | try device.lockForConfiguration() | 224 | try device.lockForConfiguration() |
| 197 | device.torchMode = call.arguments as! Int == 1 ? .on : .off | 225 | device.torchMode = call.arguments as! Int == 1 ? .on : .off |
| @@ -202,12 +230,12 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -202,12 +230,12 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 202 | } | 230 | } |
| 203 | } | 231 | } |
| 204 | 232 | ||
| 205 | - func analyzeNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { | 233 | + func switchAnalyzeMode(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { |
| 206 | analyzeMode = call.arguments as! Int | 234 | analyzeMode = call.arguments as! Int |
| 207 | result(nil) | 235 | result(nil) |
| 208 | } | 236 | } |
| 209 | 237 | ||
| 210 | - func stopNative(_ result: FlutterResult) { | 238 | + func stop(_ result: FlutterResult) { |
| 211 | captureSession.stopRunning() | 239 | captureSession.stopRunning() |
| 212 | for input in captureSession.inputs { | 240 | for input in captureSession.inputs { |
| 213 | captureSession.removeInput(input) | 241 | captureSession.removeInput(input) |
| @@ -227,6 +255,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | @@ -227,6 +255,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan | ||
| 227 | result(nil) | 255 | result(nil) |
| 228 | } | 256 | } |
| 229 | 257 | ||
| 258 | + // Observer for torch state | ||
| 230 | public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { | 259 | public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { |
| 231 | switch keyPath { | 260 | switch keyPath { |
| 232 | case "torchMode": | 261 | case "torchMode": |
| @@ -256,6 +285,10 @@ class MapArgumentReader { | @@ -256,6 +285,10 @@ class MapArgumentReader { | ||
| 256 | return (args?[key] as? NSNumber)?.intValue | 285 | return (args?[key] as? NSNumber)?.intValue |
| 257 | } | 286 | } |
| 258 | 287 | ||
| 288 | + func bool(key: String) -> Bool? { | ||
| 289 | + return (args?[key] as? NSNumber)?.boolValue | ||
| 290 | + } | ||
| 291 | + | ||
| 259 | func stringArray(key: String) -> [String]? { | 292 | func stringArray(key: String) -> [String]? { |
| 260 | return args?[key] as? [String] | 293 | return args?[key] as? [String] |
| 261 | } | 294 | } |
| @@ -3,10 +3,7 @@ import 'package:mobile_scanner/mobile_scanner.dart'; | @@ -3,10 +3,7 @@ import 'package:mobile_scanner/mobile_scanner.dart'; | ||
| 3 | 3 | ||
| 4 | import 'mobile_scanner_arguments.dart'; | 4 | import 'mobile_scanner_arguments.dart'; |
| 5 | 5 | ||
| 6 | -enum Ratio { | ||
| 7 | - ratio_4_3, | ||
| 8 | - ratio_16_9 | ||
| 9 | -} | 6 | +enum Ratio { ratio_4_3, ratio_16_9 } |
| 10 | 7 | ||
| 11 | /// A widget showing a live camera preview. | 8 | /// A widget showing a live camera preview. |
| 12 | class MobileScanner extends StatefulWidget { | 9 | class MobileScanner extends StatefulWidget { |
| @@ -18,7 +15,8 @@ class MobileScanner extends StatefulWidget { | @@ -18,7 +15,8 @@ class MobileScanner extends StatefulWidget { | ||
| 18 | /// Create a [MobileScanner] with a [controller], the [controller] must has been initialized. | 15 | /// Create a [MobileScanner] with a [controller], the [controller] must has been initialized. |
| 19 | const MobileScanner( | 16 | const MobileScanner( |
| 20 | {Key? key, this.onDetect, this.controller, this.fit = BoxFit.cover}) | 17 | {Key? key, this.onDetect, this.controller, this.fit = BoxFit.cover}) |
| 21 | - : assert((controller != null )), super(key: key); | 18 | + : assert((controller != null)), |
| 19 | + super(key: key); | ||
| 22 | 20 | ||
| 23 | @override | 21 | @override |
| 24 | State<MobileScanner> createState() => _MobileScannerState(); | 22 | State<MobileScanner> createState() => _MobileScannerState(); |
| @@ -11,5 +11,6 @@ class MobileScannerArguments { | @@ -11,5 +11,6 @@ class MobileScannerArguments { | ||
| 11 | final bool hasTorch; | 11 | final bool hasTorch; |
| 12 | 12 | ||
| 13 | /// Create a [MobileScannerArguments]. | 13 | /// Create a [MobileScannerArguments]. |
| 14 | - MobileScannerArguments({required this.textureId,required this.size, required this.hasTorch}); | 14 | + MobileScannerArguments( |
| 15 | + {required this.textureId, required this.size, required this.hasTorch}); | ||
| 15 | } | 16 | } |
| @@ -38,7 +38,6 @@ class MobileScannerController { | @@ -38,7 +38,6 @@ class MobileScannerController { | ||
| 38 | int? _controllerHashcode; | 38 | int? _controllerHashcode; |
| 39 | StreamSubscription? events; | 39 | StreamSubscription? events; |
| 40 | 40 | ||
| 41 | - | ||
| 42 | final ValueNotifier<MobileScannerArguments?> args = ValueNotifier(null); | 41 | final ValueNotifier<MobileScannerArguments?> args = ValueNotifier(null); |
| 43 | final ValueNotifier<TorchState> torchState = ValueNotifier(TorchState.off); | 42 | final ValueNotifier<TorchState> torchState = ValueNotifier(TorchState.off); |
| 44 | late final ValueNotifier<CameraFacing> cameraFacingState; | 43 | late final ValueNotifier<CameraFacing> cameraFacingState; |
| @@ -107,7 +106,8 @@ class MobileScannerController { | @@ -107,7 +106,8 @@ class MobileScannerController { | ||
| 107 | 106 | ||
| 108 | setAnalyzeMode(AnalyzeMode.barcode.index); | 107 | setAnalyzeMode(AnalyzeMode.barcode.index); |
| 109 | // Check authorization status | 108 | // Check authorization status |
| 110 | - MobileScannerState state = MobileScannerState.values[await methodChannel.invokeMethod('state')]; | 109 | + MobileScannerState state = |
| 110 | + MobileScannerState.values[await methodChannel.invokeMethod('state')]; | ||
| 111 | switch (state) { | 111 | switch (state) { |
| 112 | case MobileScannerState.undetermined: | 112 | case MobileScannerState.undetermined: |
| 113 | final bool result = await methodChannel.invokeMethod('request'); | 113 | final bool result = await methodChannel.invokeMethod('request'); |
| @@ -129,13 +129,18 @@ class MobileScannerController { | @@ -129,13 +129,18 @@ class MobileScannerController { | ||
| 129 | if (torchEnabled != null) arguments['torch'] = torchEnabled; | 129 | if (torchEnabled != null) arguments['torch'] = torchEnabled; |
| 130 | 130 | ||
| 131 | // Start the camera with arguments | 131 | // Start the camera with arguments |
| 132 | - final Map<String, dynamic>? startResult = await methodChannel.invokeMapMethod<String, dynamic>( | ||
| 133 | - 'start', arguments); | 132 | + final Map<String, dynamic>? startResult = await methodChannel |
| 133 | + .invokeMapMethod<String, dynamic>('start', arguments); | ||
| 134 | 134 | ||
| 135 | - if (startResult == null) throw PlatformException(code: 'INITIALIZATION ERROR'); | 135 | + if (startResult == null) { |
| 136 | + throw PlatformException(code: 'INITIALIZATION ERROR'); | ||
| 137 | + } | ||
| 136 | 138 | ||
| 137 | hasTorch = startResult['torchable']; | 139 | hasTorch = startResult['torchable']; |
| 138 | - args.value = MobileScannerArguments(textureId: startResult['textureId'], size: toSize(startResult['size']), hasTorch: hasTorch); | 140 | + args.value = MobileScannerArguments( |
| 141 | + textureId: startResult['textureId'], | ||
| 142 | + size: toSize(startResult['size']), | ||
| 143 | + hasTorch: hasTorch); | ||
| 139 | } | 144 | } |
| 140 | 145 | ||
| 141 | Future<void> stop() async => await methodChannel.invokeMethod('stop'); | 146 | Future<void> stop() async => await methodChannel.invokeMethod('stop'); |
| @@ -157,7 +162,8 @@ class MobileScannerController { | @@ -157,7 +162,8 @@ class MobileScannerController { | ||
| 157 | Future<void> switchCamera() async { | 162 | Future<void> switchCamera() async { |
| 158 | ensure('switchCamera'); | 163 | ensure('switchCamera'); |
| 159 | await stop(); | 164 | await stop(); |
| 160 | - facing = facing == CameraFacing.back ? CameraFacing.front : CameraFacing.back; | 165 | + facing = |
| 166 | + facing == CameraFacing.back ? CameraFacing.front : CameraFacing.back; | ||
| 161 | start(); | 167 | start(); |
| 162 | } | 168 | } |
| 163 | 169 |
| @@ -490,7 +490,7 @@ enum BarcodeFormat { | @@ -490,7 +490,7 @@ enum BarcodeFormat { | ||
| 490 | /// Barcode format constant for Data Matrix. | 490 | /// Barcode format constant for Data Matrix. |
| 491 | /// | 491 | /// |
| 492 | /// Constant Value: 16 | 492 | /// Constant Value: 16 |
| 493 | - data_matrix, | 493 | + dataMatrix, |
| 494 | 494 | ||
| 495 | /// Barcode format constant for EAN-13. | 495 | /// Barcode format constant for EAN-13. |
| 496 | /// | 496 | /// |
| @@ -510,17 +510,17 @@ enum BarcodeFormat { | @@ -510,17 +510,17 @@ enum BarcodeFormat { | ||
| 510 | /// Barcode format constant for QR Code. | 510 | /// Barcode format constant for QR Code. |
| 511 | /// | 511 | /// |
| 512 | /// Constant Value: 256 | 512 | /// Constant Value: 256 |
| 513 | - qr_code, | 513 | + qrCode, |
| 514 | 514 | ||
| 515 | /// Barcode format constant for UPC-A. | 515 | /// Barcode format constant for UPC-A. |
| 516 | /// | 516 | /// |
| 517 | /// Constant Value: 512 | 517 | /// Constant Value: 512 |
| 518 | - upc_a, | 518 | + upcA, |
| 519 | 519 | ||
| 520 | /// Barcode format constant for UPC-E. | 520 | /// Barcode format constant for UPC-E. |
| 521 | /// | 521 | /// |
| 522 | /// Constant Value: 1024 | 522 | /// Constant Value: 1024 |
| 523 | - upc_e, | 523 | + upcE, |
| 524 | 524 | ||
| 525 | /// Barcode format constant for PDF-417. | 525 | /// Barcode format constant for PDF-417. |
| 526 | /// | 526 | /// |
| @@ -29,7 +29,7 @@ BarcodeFormat toFormat(int value) { | @@ -29,7 +29,7 @@ BarcodeFormat toFormat(int value) { | ||
| 29 | case 8: | 29 | case 8: |
| 30 | return BarcodeFormat.codebar; | 30 | return BarcodeFormat.codebar; |
| 31 | case 16: | 31 | case 16: |
| 32 | - return BarcodeFormat.data_matrix; | 32 | + return BarcodeFormat.dataMatrix; |
| 33 | case 32: | 33 | case 32: |
| 34 | return BarcodeFormat.ean13; | 34 | return BarcodeFormat.ean13; |
| 35 | case 64: | 35 | case 64: |
| @@ -37,11 +37,11 @@ BarcodeFormat toFormat(int value) { | @@ -37,11 +37,11 @@ BarcodeFormat toFormat(int value) { | ||
| 37 | case 128: | 37 | case 128: |
| 38 | return BarcodeFormat.itf; | 38 | return BarcodeFormat.itf; |
| 39 | case 256: | 39 | case 256: |
| 40 | - return BarcodeFormat.qr_code; | 40 | + return BarcodeFormat.qrCode; |
| 41 | case 512: | 41 | case 512: |
| 42 | - return BarcodeFormat.upc_a; | 42 | + return BarcodeFormat.upcA; |
| 43 | case 1024: | 43 | case 1024: |
| 44 | - return BarcodeFormat.upc_e; | 44 | + return BarcodeFormat.upcE; |
| 45 | case 2048: | 45 | case 2048: |
| 46 | return BarcodeFormat.pdf417; | 46 | return BarcodeFormat.pdf417; |
| 47 | case 4096: | 47 | case 4096: |
| 1 | import 'package:flutter/services.dart'; | 1 | import 'package:flutter/services.dart'; |
| 2 | import 'package:flutter_test/flutter_test.dart'; | 2 | import 'package:flutter_test/flutter_test.dart'; |
| 3 | -import 'package:mobile_scanner/src/mobile_scanner.dart'; | ||
| 4 | 3 | ||
| 5 | void main() { | 4 | void main() { |
| 6 | const MethodChannel channel = MethodChannel('mobile_scanner'); | 5 | const MethodChannel channel = MethodChannel('mobile_scanner'); |
| @@ -16,5 +15,4 @@ void main() { | @@ -16,5 +15,4 @@ void main() { | ||
| 16 | tearDown(() { | 15 | tearDown(() { |
| 17 | channel.setMockMethodCallHandler(null); | 16 | channel.setMockMethodCallHandler(null); |
| 18 | }); | 17 | }); |
| 19 | - | ||
| 20 | } | 18 | } |
-
Please register or login to post a comment