diff --git a/CHANGELOG.md b/CHANGELOG.md index 41cc7d819..757b9ffce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ ## 0.0.1 +Initial release! +Things working on Android: +* Scanning barcodes using the latest version of MLKit and CameraX! +* Switching camera's +* Toggling of the torch (flash) -* TODO: Describe initial release. +Things working on iOS: +* Scanning barcodes using the latest version of MLKit and AVFoundation! diff --git a/LICENSE b/LICENSE index ba75c69f7..8e665deca 100644 --- a/LICENSE +++ b/LICENSE @@ -1 +1,29 @@ -TODO: Add your license here. +BSD 3-Clause License + +Copyright (c) 2022, Julian Steenbakker +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/example/android/build.gradle b/example/android/build.gradle index 2778fe6fe..cba6c84b6 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.1.0' + classpath 'com.android.tools.build:gradle:7.1.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 37d37cb3b..5e7d0f120 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Feb 08 10:35:11 CET 2022 +#Tue Feb 15 22:11:04 CET 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/example/lib/main.dart b/example/lib/main.dart index 03d092b06..3ba4deb1a 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,5 +1,3 @@ -import 'dart:ui'; - import 'package:flutter/material.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; @@ -18,8 +16,10 @@ class _AnalyzeViewState extends State with SingleTickerProviderStateMixin { String? barcode; - MobileScannerController controller = MobileScannerController(torchEnabled: true, - facing: CameraFacing.front,); + MobileScannerController controller = MobileScannerController( + torchEnabled: true, + facing: CameraFacing.front, + ); @override Widget build(BuildContext context) { @@ -30,7 +30,7 @@ class _AnalyzeViewState extends State return Stack( children: [ MobileScanner( - controller: controller, + controller: controller, fit: BoxFit.contain, // controller: MobileScannerController( // torchEnabled: true, @@ -55,20 +55,22 @@ class _AnalyzeViewState extends State children: [ IconButton( color: Colors.white, - icon: ValueListenableBuilder( - valueListenable: controller.torchState, - builder: (context, state, child) { - switch (state as TorchState) { - case TorchState.off: - return const Icon(Icons.flash_off, color: Colors.grey); - case TorchState.on: - return const Icon(Icons.flash_on, color: Colors.yellow); - } - }, - ), - iconSize: 32.0, - onPressed: () => controller.toggleTorch(), + icon: ValueListenableBuilder( + valueListenable: controller.torchState, + builder: (context, state, child) { + switch (state as TorchState) { + case TorchState.off: + return const Icon(Icons.flash_off, + color: Colors.grey); + case TorchState.on: + return const Icon(Icons.flash_on, + color: Colors.yellow); + } + }, ), + iconSize: 32.0, + onPressed: () => controller.toggleTorch(), + ), Center( child: SizedBox( width: MediaQuery.of(context).size.width - 120, diff --git a/example/lib/mobile_scanner_overlay.dart b/example/lib/mobile_scanner_overlay.dart index ec267d5a2..44238c5ef 100644 --- a/example/lib/mobile_scanner_overlay.dart +++ b/example/lib/mobile_scanner_overlay.dart @@ -20,7 +20,7 @@ class _AnalyzeViewState extends State // CameraController cameraController = CameraController(context, width: 320, height: 150); - String? barcode = null; + String? barcode; @override Widget build(BuildContext context) { @@ -30,40 +30,41 @@ class _AnalyzeViewState extends State return Stack( children: [ MobileScanner( - // fitScreen: false, + // fitScreen: false, // controller: cameraController, onDetect: (barcode, args) { - if (this.barcode != barcode.rawValue) { - this.barcode = barcode.rawValue; - if (barcode.corners != null) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text('${barcode.rawValue}'), - duration: const Duration(milliseconds: 200), - animation: null, - )); - setState(() { - final List points = []; - double factorWidth = args.size.width / 520; - // double factorHeight = wanted / args.size.height; - final size = MediaQuery.of(context).devicePixelRatio; - debugPrint('Size: ${barcode.corners}'); - for (var point in barcode.corners!) { - final adjustedWith = point.dx ; - final adjustedHeight= point.dy ; - points.add(Offset(adjustedWith / size, adjustedHeight / size)); - // points.add(Offset((point.dx ) / size, - // (point.dy) / size)); - // final differenceWidth = (args.wantedSize!.width - args.size.width) / 2; - // final differenceHeight = (args.wantedSize!.height - args.size.height) / 2; - // points.add(Offset((point.dx + differenceWidth) / size, - // (point.dy + differenceHeight) / size)); - } - this.points = points; - }); + if (this.barcode != barcode.rawValue) { + this.barcode = barcode.rawValue; + if (barcode.corners != null) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(barcode.rawValue), + duration: const Duration(milliseconds: 200), + animation: null, + )); + setState(() { + final List points = []; + // double factorWidth = args.size.width / 520; + // double factorHeight = wanted / args.size.height; + final size = MediaQuery.of(context).devicePixelRatio; + debugPrint('Size: ${barcode.corners}'); + for (var point in barcode.corners!) { + final adjustedWith = point.dx; + final adjustedHeight = point.dy; + points.add( + Offset(adjustedWith / size, adjustedHeight / size)); + // points.add(Offset((point.dx ) / size, + // (point.dy) / size)); + // final differenceWidth = (args.wantedSize!.width - args.size.width) / 2; + // final differenceHeight = (args.wantedSize!.height - args.size.height) / 2; + // points.add(Offset((point.dx + differenceWidth) / size, + // (point.dy + differenceHeight) / size)); } - } - // Default 640 x480 - }), + this.points = points; + }); + } + } + // Default 640 x480 + }), CustomPaint( painter: OpenPainter(points), ), @@ -108,7 +109,7 @@ class OpenPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { var paint1 = Paint() - ..color = Color(0xff63aa65) + ..color = const Color(0xff63aa65) ..strokeWidth = 10; //draw points on canvas canvas.drawPoints(PointMode.points, points, paint1); diff --git a/example/test/widget_test.dart b/example/test/widget_test.dart index 971d6db5a..7fdea585b 100644 --- a/example/test/widget_test.dart +++ b/example/test/widget_test.dart @@ -5,11 +5,8 @@ // gestures. You can also use WidgetTester to find child widgets in the widget // tree, read text, and verify that the values of widget properties are correct. -import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:mobile_scanner_example/main.dart'; - void main() { testWidgets('Verify Platform version', (WidgetTester tester) async { // Build our app and trigger a frame. diff --git a/ios/Classes/SwiftMobileScanner.swift b/ios/Classes/SwiftMobileScanner.swift new file mode 100644 index 000000000..82d78ed64 --- /dev/null +++ b/ios/Classes/SwiftMobileScanner.swift @@ -0,0 +1,8 @@ +// +// SwiftMobileScanner.swift +// mobile_scanner +// +// Created by Julian Steenbakker on 15/02/2022. +// + +import Foundation diff --git a/ios/Classes/SwiftMobileScannerPlugin.swift b/ios/Classes/SwiftMobileScannerPlugin.swift index 79050a212..899b049cd 100644 --- a/ios/Classes/SwiftMobileScannerPlugin.swift +++ b/ios/Classes/SwiftMobileScannerPlugin.swift @@ -5,61 +5,77 @@ import MLKitBarcodeScanning public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHandler, FlutterTexture, AVCaptureVideoDataOutputSampleBufferDelegate { - public static func register(with registrar: FlutterPluginRegistrar) { - let instance = SwiftMobileScannerPlugin(registrar.textures()) - - let method = FlutterMethodChannel(name: "dev.steenbakker.mobile_scanner/scanner/method", binaryMessenger: registrar.messenger()) - registrar.addMethodCallDelegate(instance, channel: method) - - let event = FlutterEventChannel(name: "dev.steenbakker.mobile_scanner/scanner/event", binaryMessenger: registrar.messenger()) - event.setStreamHandler(instance) - } - let registry: FlutterTextureRegistry + + // Sink for publishing event changes var sink: FlutterEventSink! + + // Texture id of the camera preview var textureId: Int64! + + // Capture session of the camera var captureSession: AVCaptureSession! + + // The selected camera var device: AVCaptureDevice! + + // Image to be sent to the texture var latestBuffer: CVImageBuffer! - var analyzeMode: Int - var analyzing: Bool + + + var analyzeMode: Int = 0 + var analyzing: Bool = false + var position = AVCaptureDevice.Position.back + + public static func register(with registrar: FlutterPluginRegistrar) { + let instance = SwiftMobileScannerPlugin(registrar.textures()) + + let method = FlutterMethodChannel(name: + "dev.steenbakker.mobile_scanner/scanner/method", binaryMessenger: registrar.messenger()) + let event = FlutterEventChannel(name: + "dev.steenbakker.mobile_scanner/scanner/event", binaryMessenger: registrar.messenger()) + registrar.addMethodCallDelegate(instance, channel: method) + event.setStreamHandler(instance) + } init(_ registry: FlutterTextureRegistry) { self.registry = registry - analyzeMode = 0 - analyzing = false super.init() } + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "state": - stateNative(call, result) + checkPermission(call, result) case "request": - requestNative(call, result) + requestPermission(call, result) case "start": - startNative(call, result) + start(call, result) case "torch": - torchNative(call, result) + switchTorch(call, result) case "analyze": - analyzeNative(call, result) + switchAnalyzeMode(call, result) case "stop": - stopNative(result) + stop(result) default: result(FlutterMethodNotImplemented) } } + // FlutterStreamHandler public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? { sink = events return nil } + // FlutterStreamHandler public func onCancel(withArguments arguments: Any?) -> FlutterError? { sink = nil return nil } + // FlutterTexture public func copyPixelBuffer() -> Unmanaged? { if latestBuffer == nil { return nil @@ -67,11 +83,12 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan return Unmanaged.passRetained(latestBuffer) } + // Gets called when a new image is added to the buffer public func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) { - + latestBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) registry.textureFrameAvailable(textureId) - + switch analyzeMode { case 1: // barcode if analyzing { @@ -84,7 +101,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan deviceOrientation: UIDevice.current.orientation, defaultOrientation: .portrait ) - + let scanner = BarcodeScanner.barcodeScanner() scanner.process(image) { [self] barcodes, error in if error == nil && barcodes != nil { @@ -120,7 +137,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan } } - func stateNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + func checkPermission(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { let status = AVCaptureDevice.authorizationStatus(for: .video) switch status { case .notDetermined: @@ -132,34 +149,45 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan } } - func requestNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + func requestPermission(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { AVCaptureDevice.requestAccess(for: .video, completionHandler: { result($0) }) } - - var position = AVCaptureDevice.Position.back - - func startNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + + func start(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { textureId = registry.register(self) captureSession = AVCaptureSession() let argReader = MapArgumentReader(call.arguments as? [String: Any]) - guard let targetWidth = argReader.int(key: "targetWidth"), - let targetHeight = argReader.int(key: "targetHeight"), - let facing = argReader.int(key: "facing") else { - result(FlutterError(code: "INVALID_ARGUMENT", message: "Missing a required argument", details: "Expecting targetWidth, targetHeight, formats, and optionally heartbeatTimeout")) - return - } - +// let ratio: Int = argReader.int(key: "ratio") + let torch: Bool = argReader.bool(key: "torch") ?? false + let facing: Int = argReader.int(key: "facing") ?? 1 + + // Set the camera to use position = facing == 0 ? AVCaptureDevice.Position.front : .back + + // Open the camera device if #available(iOS 10.0, *) { device = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: .video, position: position).devices.first } else { device = AVCaptureDevice.devices(for: .video).filter({$0.position == position}).first } + + // Enable the torch if parameter is set and torch is available + if (device.hasTorch && device.isTorchAvailable) { + do { + try device.lockForConfiguration() + device.torchMode = torch ? .on : .off + device.unlockForConfiguration() + } catch { + error.throwNative(result) + } + } + device.addObserver(self, forKeyPath: #keyPath(AVCaptureDevice.torchMode), options: .new, context: nil) captureSession.beginConfiguration() - // Add device input. + + // Add device input do { let input = try AVCaptureDeviceInput(device: device) captureSession.addInput(input) @@ -191,7 +219,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan result(answer) } - func torchNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + func switchTorch(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { do { try device.lockForConfiguration() device.torchMode = call.arguments as! Int == 1 ? .on : .off @@ -202,12 +230,12 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan } } - func analyzeNative(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { + func switchAnalyzeMode(_ call: FlutterMethodCall, _ result: @escaping FlutterResult) { analyzeMode = call.arguments as! Int result(nil) } - func stopNative(_ result: FlutterResult) { + func stop(_ result: FlutterResult) { captureSession.stopRunning() for input in captureSession.inputs { captureSession.removeInput(input) @@ -227,6 +255,7 @@ public class SwiftMobileScannerPlugin: NSObject, FlutterPlugin, FlutterStreamHan result(nil) } + // Observer for torch state public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { switch keyPath { case "torchMode": @@ -255,6 +284,10 @@ class MapArgumentReader { func int(key: String) -> Int? { return (args?[key] as? NSNumber)?.intValue } + + func bool(key: String) -> Bool? { + return (args?[key] as? NSNumber)?.boolValue + } func stringArray(key: String) -> [String]? { return args?[key] as? [String] diff --git a/lib/mobile_scanner.dart b/lib/mobile_scanner.dart index c04766e63..bdbdf5d51 100644 --- a/lib/mobile_scanner.dart +++ b/lib/mobile_scanner.dart @@ -2,4 +2,4 @@ library mobile_scanner; export 'src/mobile_scanner.dart'; export 'src/mobile_scanner_controller.dart'; -export 'src/objects/barcode.dart'; \ No newline at end of file +export 'src/objects/barcode.dart'; diff --git a/lib/src/mobile_scanner.dart b/lib/src/mobile_scanner.dart index 1e5bcba63..aa6fc13d8 100644 --- a/lib/src/mobile_scanner.dart +++ b/lib/src/mobile_scanner.dart @@ -3,10 +3,7 @@ import 'package:mobile_scanner/mobile_scanner.dart'; import 'mobile_scanner_arguments.dart'; -enum Ratio { - ratio_4_3, - ratio_16_9 -} +enum Ratio { ratio_4_3, ratio_16_9 } /// A widget showing a live camera preview. class MobileScanner extends StatefulWidget { @@ -18,7 +15,8 @@ class MobileScanner extends StatefulWidget { /// Create a [MobileScanner] with a [controller], the [controller] must has been initialized. const MobileScanner( {Key? key, this.onDetect, this.controller, this.fit = BoxFit.cover}) - : assert((controller != null )), super(key: key); + : assert((controller != null)), + super(key: key); @override State createState() => _MobileScannerState(); @@ -91,4 +89,4 @@ class _MobileScannerState extends State controller.dispose(); super.dispose(); } -} \ No newline at end of file +} diff --git a/lib/src/mobile_scanner_arguments.dart b/lib/src/mobile_scanner_arguments.dart index 6cdda9508..3fb6dcda7 100644 --- a/lib/src/mobile_scanner_arguments.dart +++ b/lib/src/mobile_scanner_arguments.dart @@ -11,5 +11,6 @@ class MobileScannerArguments { final bool hasTorch; /// Create a [MobileScannerArguments]. - MobileScannerArguments({required this.textureId,required this.size, required this.hasTorch}); + MobileScannerArguments( + {required this.textureId, required this.size, required this.hasTorch}); } diff --git a/lib/src/mobile_scanner_controller.dart b/lib/src/mobile_scanner_controller.dart index cdaabd06b..01ba23a18 100644 --- a/lib/src/mobile_scanner_controller.dart +++ b/lib/src/mobile_scanner_controller.dart @@ -38,7 +38,6 @@ class MobileScannerController { int? _controllerHashcode; StreamSubscription? events; - final ValueNotifier args = ValueNotifier(null); final ValueNotifier torchState = ValueNotifier(TorchState.off); late final ValueNotifier cameraFacingState; @@ -107,7 +106,8 @@ class MobileScannerController { setAnalyzeMode(AnalyzeMode.barcode.index); // Check authorization status - MobileScannerState state = MobileScannerState.values[await methodChannel.invokeMethod('state')]; + MobileScannerState state = + MobileScannerState.values[await methodChannel.invokeMethod('state')]; switch (state) { case MobileScannerState.undetermined: final bool result = await methodChannel.invokeMethod('request'); @@ -129,13 +129,18 @@ class MobileScannerController { if (torchEnabled != null) arguments['torch'] = torchEnabled; // Start the camera with arguments - final Map? startResult = await methodChannel.invokeMapMethod( - 'start', arguments); + final Map? startResult = await methodChannel + .invokeMapMethod('start', arguments); - if (startResult == null) throw PlatformException(code: 'INITIALIZATION ERROR'); + if (startResult == null) { + throw PlatformException(code: 'INITIALIZATION ERROR'); + } hasTorch = startResult['torchable']; - args.value = MobileScannerArguments(textureId: startResult['textureId'], size: toSize(startResult['size']), hasTorch: hasTorch); + args.value = MobileScannerArguments( + textureId: startResult['textureId'], + size: toSize(startResult['size']), + hasTorch: hasTorch); } Future stop() async => await methodChannel.invokeMethod('stop'); @@ -157,7 +162,8 @@ class MobileScannerController { Future switchCamera() async { ensure('switchCamera'); await stop(); - facing = facing == CameraFacing.back ? CameraFacing.front : CameraFacing.back; + facing = + facing == CameraFacing.back ? CameraFacing.front : CameraFacing.back; start(); } diff --git a/lib/src/objects/barcode.dart b/lib/src/objects/barcode.dart index eca90f12f..8b9430084 100644 --- a/lib/src/objects/barcode.dart +++ b/lib/src/objects/barcode.dart @@ -490,7 +490,7 @@ enum BarcodeFormat { /// Barcode format constant for Data Matrix. /// /// Constant Value: 16 - data_matrix, + dataMatrix, /// Barcode format constant for EAN-13. /// @@ -510,17 +510,17 @@ enum BarcodeFormat { /// Barcode format constant for QR Code. /// /// Constant Value: 256 - qr_code, + qrCode, /// Barcode format constant for UPC-A. /// /// Constant Value: 512 - upc_a, + upcA, /// Barcode format constant for UPC-E. /// /// Constant Value: 1024 - upc_e, + upcE, /// Barcode format constant for PDF-417. /// diff --git a/lib/src/objects/barcode_utility.dart b/lib/src/objects/barcode_utility.dart index 9b122fff3..bc03d00b5 100644 --- a/lib/src/objects/barcode_utility.dart +++ b/lib/src/objects/barcode_utility.dart @@ -29,7 +29,7 @@ BarcodeFormat toFormat(int value) { case 8: return BarcodeFormat.codebar; case 16: - return BarcodeFormat.data_matrix; + return BarcodeFormat.dataMatrix; case 32: return BarcodeFormat.ean13; case 64: @@ -37,11 +37,11 @@ BarcodeFormat toFormat(int value) { case 128: return BarcodeFormat.itf; case 256: - return BarcodeFormat.qr_code; + return BarcodeFormat.qrCode; case 512: - return BarcodeFormat.upc_a; + return BarcodeFormat.upcA; case 1024: - return BarcodeFormat.upc_e; + return BarcodeFormat.upcE; case 2048: return BarcodeFormat.pdf417; case 4096: diff --git a/pubspec.yaml b/pubspec.yaml index 8f42f8045..648d696d5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -23,6 +23,4 @@ flutter: package: dev.steenbakker.mobile_scanner pluginClass: MobileScannerPlugin ios: - pluginClass: MobileScannerPlugin - macos: - pluginClass: MobileScannerPlugin + pluginClass: MobileScannerPlugin \ No newline at end of file diff --git a/test/mobile_scanner_test.dart b/test/mobile_scanner_test.dart index 64a664d9a..aa3608f52 100644 --- a/test/mobile_scanner_test.dart +++ b/test/mobile_scanner_test.dart @@ -1,6 +1,5 @@ import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:mobile_scanner/src/mobile_scanner.dart'; void main() { const MethodChannel channel = MethodChannel('mobile_scanner'); @@ -16,5 +15,4 @@ void main() { tearDown(() { channel.setMockMethodCallHandler(null); }); - }