Merge branch 'master' into feature/scan-window
# Conflicts: # lib/src/mobile_scanner.dart
Showing
8 changed files
with
51 additions
and
39 deletions
| 1 | name: code analysis & formatting | 1 | name: code analysis & formatting |
| 2 | 2 | ||
| 3 | -on: [push, pull_request] | 3 | +on: |
| 4 | + push: | ||
| 5 | + branches: | ||
| 6 | + - master | ||
| 7 | + pull_request: | ||
| 8 | + types: [ opened, labeled, unlabeled, synchronize ] | ||
| 4 | 9 | ||
| 5 | jobs: | 10 | jobs: |
| 6 | analysis: | 11 | analysis: |
| 7 | runs-on: ubuntu-latest | 12 | runs-on: ubuntu-latest |
| 8 | steps: | 13 | steps: |
| 9 | - - uses: actions/checkout@v3 | ||
| 10 | - - uses: actions/setup-java@v3 | 14 | + - uses: actions/checkout@v3.0.2 |
| 15 | + - uses: actions/setup-java@v3.4.1 | ||
| 11 | with: | 16 | with: |
| 12 | - distribution: 'temurin' | ||
| 13 | - java-version: '11' | ||
| 14 | - - uses: subosito/flutter-action@v2.4.0 | 17 | + java-version: 11 |
| 18 | + distribution: temurin | ||
| 19 | + - uses: subosito/flutter-action@v2.6.1 | ||
| 20 | + with: | ||
| 21 | + cache: true | ||
| 15 | - name: Version | 22 | - name: Version |
| 16 | run: flutter doctor -v | 23 | run: flutter doctor -v |
| 17 | - name: Install dependencies | 24 | - name: Install dependencies |
| @@ -21,11 +28,13 @@ jobs: | @@ -21,11 +28,13 @@ jobs: | ||
| 21 | formatting: | 28 | formatting: |
| 22 | runs-on: ubuntu-latest | 29 | runs-on: ubuntu-latest |
| 23 | steps: | 30 | steps: |
| 24 | - - uses: actions/checkout@v3 | ||
| 25 | - - uses: actions/setup-java@v3 | 31 | + - uses: actions/checkout@v3.0.2 |
| 32 | + - uses: actions/setup-java@v3.4.1 | ||
| 33 | + with: | ||
| 34 | + java-version: 11 | ||
| 35 | + distribution: temurin | ||
| 36 | + - uses: subosito/flutter-action@v2.6.1 | ||
| 26 | with: | 37 | with: |
| 27 | - distribution: 'temurin' | ||
| 28 | - java-version: '11' | ||
| 29 | - - uses: subosito/flutter-action@v2.4.0 | 38 | + cache: true |
| 30 | - name: Format | 39 | - name: Format |
| 31 | - run: flutter format -n --set-exit-if-changed . | ||
| 40 | + run: flutter format -n --set-exit-if-changed . |
| @@ -2,7 +2,7 @@ group 'dev.steenbakker.mobile_scanner' | @@ -2,7 +2,7 @@ group 'dev.steenbakker.mobile_scanner' | ||
| 2 | version '1.0-SNAPSHOT' | 2 | version '1.0-SNAPSHOT' |
| 3 | 3 | ||
| 4 | buildscript { | 4 | buildscript { |
| 5 | - ext.kotlin_version = '1.6.21' | 5 | + ext.kotlin_version = '1.7.10' |
| 6 | repositories { | 6 | repositories { |
| 7 | google() | 7 | google() |
| 8 | mavenCentral() | 8 | mavenCentral() |
| @@ -52,8 +52,8 @@ dependencies { | @@ -52,8 +52,8 @@ dependencies { | ||
| 52 | // Use this dependency to use the dynamically downloaded model in Google Play Services | 52 | // Use this dependency to use the dynamically downloaded model in Google Play Services |
| 53 | // implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.0.0' | 53 | // implementation 'com.google.android.gms:play-services-mlkit-barcode-scanning:18.0.0' |
| 54 | 54 | ||
| 55 | - implementation "androidx.camera:camera-camera2:1.2.0-alpha01" | ||
| 56 | - implementation 'androidx.camera:camera-lifecycle:1.2.0-alpha01' | 55 | + implementation "androidx.camera:camera-camera2:1.2.0-alpha04" |
| 56 | + implementation 'androidx.camera:camera-lifecycle:1.2.0-alpha04' | ||
| 57 | 57 | ||
| 58 | // // The following line is optional, as the core library is included indirectly by camera-camera2 | 58 | // // The following line is optional, as the core library is included indirectly by camera-camera2 |
| 59 | // implementation "androidx.camera:camera-core:1.1.0-alpha11" | 59 | // implementation "androidx.camera:camera-core:1.1.0-alpha11" |
| @@ -133,9 +133,9 @@ class _BarcodeScannerWithControllerState | @@ -133,9 +133,9 @@ class _BarcodeScannerWithControllerState | ||
| 133 | icon: const Icon(Icons.image), | 133 | icon: const Icon(Icons.image), |
| 134 | iconSize: 32.0, | 134 | iconSize: 32.0, |
| 135 | onPressed: () async { | 135 | onPressed: () async { |
| 136 | - final ImagePicker _picker = ImagePicker(); | 136 | + final ImagePicker picker = ImagePicker(); |
| 137 | // Pick an image | 137 | // Pick an image |
| 138 | - final XFile? image = await _picker.pickImage( | 138 | + final XFile? image = await picker.pickImage( |
| 139 | source: ImageSource.gallery, | 139 | source: ImageSource.gallery, |
| 140 | ); | 140 | ); |
| 141 | if (image != null) { | 141 | if (image != null) { |
| @@ -37,13 +37,12 @@ class MobileScanner extends StatefulWidget { | @@ -37,13 +37,12 @@ class MobileScanner extends StatefulWidget { | ||
| 37 | 37 | ||
| 38 | /// Create a [MobileScanner] with a [controller], the [controller] must has been initialized. | 38 | /// Create a [MobileScanner] with a [controller], the [controller] must has been initialized. |
| 39 | const MobileScanner({ | 39 | const MobileScanner({ |
| 40 | - Key? key, | 40 | + super.key, |
| 41 | required this.onDetect, | 41 | required this.onDetect, |
| 42 | this.controller, | 42 | this.controller, |
| 43 | this.fit = BoxFit.cover, | 43 | this.fit = BoxFit.cover, |
| 44 | this.allowDuplicates = false, | 44 | this.allowDuplicates = false, |
| 45 | - this.scanWindow, | ||
| 46 | - }) : super(key: key); | 45 | + }); |
| 47 | 46 | ||
| 48 | @override | 47 | @override |
| 49 | State<MobileScanner> createState() => _MobileScannerState(); | 48 | State<MobileScanner> createState() => _MobileScannerState(); |
| @@ -58,13 +57,14 @@ class _MobileScannerState extends State<MobileScanner> | @@ -58,13 +57,14 @@ class _MobileScannerState extends State<MobileScanner> | ||
| 58 | super.initState(); | 57 | super.initState(); |
| 59 | WidgetsBinding.instance.addObserver(this); | 58 | WidgetsBinding.instance.addObserver(this); |
| 60 | controller = widget.controller ?? MobileScannerController(); | 59 | controller = widget.controller ?? MobileScannerController(); |
| 60 | + if (!controller.isStarting) controller.start(); | ||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | @override | 63 | @override |
| 64 | void didChangeAppLifecycleState(AppLifecycleState state) { | 64 | void didChangeAppLifecycleState(AppLifecycleState state) { |
| 65 | switch (state) { | 65 | switch (state) { |
| 66 | case AppLifecycleState.resumed: | 66 | case AppLifecycleState.resumed: |
| 67 | - if (!controller.isStarting) controller.start(); | 67 | + if (!controller.isStarting && controller.autoResume) controller.start(); |
| 68 | break; | 68 | break; |
| 69 | case AppLifecycleState.inactive: | 69 | case AppLifecycleState.inactive: |
| 70 | case AppLifecycleState.paused: | 70 | case AppLifecycleState.paused: |
| @@ -134,7 +134,7 @@ class _MobileScannerState extends State<MobileScanner> | @@ -134,7 +134,7 @@ class _MobileScannerState extends State<MobileScanner> | ||
| 134 | builder: (context, value, child) { | 134 | builder: (context, value, child) { |
| 135 | value = value as MobileScannerArguments?; | 135 | value = value as MobileScannerArguments?; |
| 136 | if (value == null) { | 136 | if (value == null) { |
| 137 | - return Container(color: Colors.black); | 137 | + return const ColoredBox(color: Colors.black); |
| 138 | } else { | 138 | } else { |
| 139 | if (widget.scanWindow != null) { | 139 | if (widget.scanWindow != null) { |
| 140 | final window = calculateScanWindowRelativeToTextureInPercentage( | 140 | final window = calculateScanWindowRelativeToTextureInPercentage( |
| @@ -35,7 +35,8 @@ class MobileScannerController { | @@ -35,7 +35,8 @@ class MobileScannerController { | ||
| 35 | EventChannel eventChannel = | 35 | EventChannel eventChannel = |
| 36 | const EventChannel('dev.steenbakker.mobile_scanner/scanner/event'); | 36 | const EventChannel('dev.steenbakker.mobile_scanner/scanner/event'); |
| 37 | 37 | ||
| 38 | - int? _controllerHashcode; | 38 | + //Must be static to keep the same value on new instances |
| 39 | + static int? _controllerHashcode; | ||
| 39 | StreamSubscription? events; | 40 | StreamSubscription? events; |
| 40 | 41 | ||
| 41 | final ValueNotifier<MobileScannerArguments?> args = ValueNotifier(null); | 42 | final ValueNotifier<MobileScannerArguments?> args = ValueNotifier(null); |
| @@ -53,6 +54,9 @@ class MobileScannerController { | @@ -53,6 +54,9 @@ class MobileScannerController { | ||
| 53 | bool hasTorch = false; | 54 | bool hasTorch = false; |
| 54 | late StreamController<Barcode> barcodesController; | 55 | late StreamController<Barcode> barcodesController; |
| 55 | 56 | ||
| 57 | + /// Whether to automatically resume the camera when the application is resumed | ||
| 58 | + bool autoResume; | ||
| 59 | + | ||
| 56 | Stream<Barcode> get barcodes => barcodesController.stream; | 60 | Stream<Barcode> get barcodes => barcodesController.stream; |
| 57 | 61 | ||
| 58 | MobileScannerController({ | 62 | MobileScannerController({ |
| @@ -60,6 +64,7 @@ class MobileScannerController { | @@ -60,6 +64,7 @@ class MobileScannerController { | ||
| 60 | this.ratio, | 64 | this.ratio, |
| 61 | this.torchEnabled, | 65 | this.torchEnabled, |
| 62 | this.formats, | 66 | this.formats, |
| 67 | + this.autoResume = true, | ||
| 63 | }) { | 68 | }) { |
| 64 | // In case a new instance is created before calling dispose() | 69 | // In case a new instance is created before calling dispose() |
| 65 | if (_controllerHashcode != null) { | 70 | if (_controllerHashcode != null) { |
| @@ -75,8 +80,6 @@ class MobileScannerController { | @@ -75,8 +80,6 @@ class MobileScannerController { | ||
| 75 | // onCancel: () => setAnalyzeMode(AnalyzeMode.none.index), | 80 | // onCancel: () => setAnalyzeMode(AnalyzeMode.none.index), |
| 76 | ); | 81 | ); |
| 77 | 82 | ||
| 78 | - start(); | ||
| 79 | - | ||
| 80 | // Listen to events from the platform specific code | 83 | // Listen to events from the platform specific code |
| 81 | events = eventChannel | 84 | events = eventChannel |
| 82 | .receiveBroadcastStream() | 85 | .receiveBroadcastStream() |
| @@ -88,22 +91,22 @@ class MobileScannerController { | @@ -88,22 +91,22 @@ class MobileScannerController { | ||
| 88 | final data = event['data']; | 91 | final data = event['data']; |
| 89 | switch (name) { | 92 | switch (name) { |
| 90 | case 'torchState': | 93 | case 'torchState': |
| 91 | - final state = TorchState.values[data as int]; | 94 | + final state = TorchState.values[data as int? ?? 0]; |
| 92 | torchState.value = state; | 95 | torchState.value = state; |
| 93 | break; | 96 | break; |
| 94 | case 'barcode': | 97 | case 'barcode': |
| 95 | - final barcode = Barcode.fromNative(data as Map); | 98 | + final barcode = Barcode.fromNative(data as Map? ?? {}); |
| 96 | barcodesController.add(barcode); | 99 | barcodesController.add(barcode); |
| 97 | break; | 100 | break; |
| 98 | case 'barcodeMac': | 101 | case 'barcodeMac': |
| 99 | barcodesController.add( | 102 | barcodesController.add( |
| 100 | Barcode( | 103 | Barcode( |
| 101 | - rawValue: (data as Map)['payload'] as String, | 104 | + rawValue: (data as Map)['payload'] as String?, |
| 102 | ), | 105 | ), |
| 103 | ); | 106 | ); |
| 104 | break; | 107 | break; |
| 105 | case 'barcodeWeb': | 108 | case 'barcodeWeb': |
| 106 | - barcodesController.add(Barcode(rawValue: data as String)); | 109 | + barcodesController.add(Barcode(rawValue: data as String?)); |
| 107 | break; | 110 | break; |
| 108 | default: | 111 | default: |
| 109 | throw UnimplementedError(); | 112 | throw UnimplementedError(); |
| @@ -134,11 +137,11 @@ class MobileScannerController { | @@ -134,11 +137,11 @@ class MobileScannerController { | ||
| 134 | // Check authorization status | 137 | // Check authorization status |
| 135 | if (!kIsWeb) { | 138 | if (!kIsWeb) { |
| 136 | MobileScannerState state = MobileScannerState | 139 | MobileScannerState state = MobileScannerState |
| 137 | - .values[await methodChannel.invokeMethod('state') as int]; | 140 | + .values[await methodChannel.invokeMethod('state') as int? ?? 0]; |
| 138 | switch (state) { | 141 | switch (state) { |
| 139 | case MobileScannerState.undetermined: | 142 | case MobileScannerState.undetermined: |
| 140 | final bool result = | 143 | final bool result = |
| 141 | - await methodChannel.invokeMethod('request') as bool; | 144 | + await methodChannel.invokeMethod('request') as bool? ?? false; |
| 142 | state = result | 145 | state = result |
| 143 | ? MobileScannerState.authorized | 146 | ? MobileScannerState.authorized |
| 144 | : MobileScannerState.denied; | 147 | : MobileScannerState.denied; |
| @@ -194,21 +197,21 @@ class MobileScannerController { | @@ -194,21 +197,21 @@ class MobileScannerController { | ||
| 194 | throw PlatformException(code: 'INITIALIZATION ERROR'); | 197 | throw PlatformException(code: 'INITIALIZATION ERROR'); |
| 195 | } | 198 | } |
| 196 | 199 | ||
| 197 | - hasTorch = startResult['torchable'] as bool; | 200 | + hasTorch = startResult['torchable'] as bool? ?? false; |
| 198 | 201 | ||
| 199 | if (kIsWeb) { | 202 | if (kIsWeb) { |
| 200 | args.value = MobileScannerArguments( | 203 | args.value = MobileScannerArguments( |
| 201 | webId: startResult['ViewID'] as String?, | 204 | webId: startResult['ViewID'] as String?, |
| 202 | size: Size( | 205 | size: Size( |
| 203 | - startResult['videoWidth'] as double, | ||
| 204 | - startResult['videoHeight'] as double, | 206 | + startResult['videoWidth'] as double? ?? 0, |
| 207 | + startResult['videoHeight'] as double? ?? 0, | ||
| 205 | ), | 208 | ), |
| 206 | hasTorch: hasTorch, | 209 | hasTorch: hasTorch, |
| 207 | ); | 210 | ); |
| 208 | } else { | 211 | } else { |
| 209 | args.value = MobileScannerArguments( | 212 | args.value = MobileScannerArguments( |
| 210 | - textureId: startResult['textureId'] as int, | ||
| 211 | - size: toSize(startResult['size'] as Map), | 213 | + textureId: startResult['textureId'] as int?, |
| 214 | + size: toSize(startResult['size'] as Map? ?? {}), | ||
| 212 | hasTorch: hasTorch, | 215 | hasTorch: hasTorch, |
| 213 | ); | 216 | ); |
| 214 | } | 217 | } |
-
Please register or login to post a comment