Julian Steenbakker

ci: update view

1 -include: package:flutter_lints/flutter.yaml  
2 -  
3 -# Additional information about this file can be found at  
4 -# https://dart.dev/guides/language/analysis-options 1 +include: package:flutter_lints/flutter.yaml
@@ -9,8 +9,7 @@ buildscript { @@ -9,8 +9,7 @@ buildscript {
9 } 9 }
10 10
11 dependencies { 11 dependencies {
12 - classpath 'com.android.tools.build:gradle:4.1.3'  
13 - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 12 + classpath 'com.android.tools.build:gradle:7.1.0'
14 } 13 }
15 } 14 }
16 15
@@ -31,10 +31,9 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -31,10 +31,9 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
31 private var camera: Camera? = null 31 private var camera: Camera? = null
32 private var textureEntry: TextureRegistry.SurfaceTextureEntry? = null 32 private var textureEntry: TextureRegistry.SurfaceTextureEntry? = null
33 33
34 -// @AnalyzeMode  
35 -// private var analyzeMode: Int = AnalyzeMode.NONE 34 + @AnalyzeMode
  35 + private var analyzeMode: Int = AnalyzeMode.NONE
36 36
37 - @ExperimentalGetImage  
38 override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: MethodChannel.Result) { 37 override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: MethodChannel.Result) {
39 when (call.method) { 38 when (call.method) {
40 "state" -> stateNative(result) 39 "state" -> stateNative(result)
@@ -101,8 +100,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -101,8 +100,8 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
101 val preview = Preview.Builder().build().apply { setSurfaceProvider(surfaceProvider) } 100 val preview = Preview.Builder().build().apply { setSurfaceProvider(surfaceProvider) }
102 // Analyzer 101 // Analyzer
103 val analyzer = ImageAnalysis.Analyzer { imageProxy -> // YUV_420_888 format 102 val analyzer = ImageAnalysis.Analyzer { imageProxy -> // YUV_420_888 format
104 -// when (analyzeMode) {  
105 -// AnalyzeMode.BARCODE -> { 103 + when (analyzeMode) {
  104 + AnalyzeMode.BARCODE -> {
106 val mediaImage = imageProxy.image ?: return@Analyzer 105 val mediaImage = imageProxy.image ?: return@Analyzer
107 val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) 106 val inputImage = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
108 val scanner = BarcodeScanning.getClient() 107 val scanner = BarcodeScanning.getClient()
@@ -115,9 +114,9 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -115,9 +114,9 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
115 } 114 }
116 .addOnFailureListener { e -> Log.e(TAG, e.message, e) } 115 .addOnFailureListener { e -> Log.e(TAG, e.message, e) }
117 .addOnCompleteListener { imageProxy.close() } 116 .addOnCompleteListener { imageProxy.close() }
118 -// }  
119 -// else -> imageProxy.close()  
120 -// } 117 + }
  118 + else -> imageProxy.close()
  119 + }
121 } 120 }
122 val analysis = ImageAnalysis.Builder() 121 val analysis = ImageAnalysis.Builder()
123 .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) 122 .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
@@ -152,7 +151,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -152,7 +151,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
152 } 151 }
153 152
154 private fun analyzeNative(call: MethodCall, result: MethodChannel.Result) { 153 private fun analyzeNative(call: MethodCall, result: MethodChannel.Result) {
155 -// analyzeMode = call.arguments as Int 154 + analyzeMode = call.arguments as Int
156 result.success(null) 155 result.success(null)
157 } 156 }
158 157
@@ -162,6 +161,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -162,6 +161,7 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
162 cameraProvider!!.unbindAll() 161 cameraProvider!!.unbindAll()
163 textureEntry!!.release() 162 textureEntry!!.release()
164 163
  164 + analyzeMode = AnalyzeMode.NONE
165 camera = null 165 camera = null
166 textureEntry = null 166 textureEntry = null
167 cameraProvider = null 167 cameraProvider = null
@@ -169,14 +169,13 @@ class MobileScanner(private val activity: Activity, private val textureRegistry: @@ -169,14 +169,13 @@ class MobileScanner(private val activity: Activity, private val textureRegistry:
169 result.success(null) 169 result.success(null)
170 } 170 }
171 } 171 }
172 -//  
173 -//  
174 -//@IntDef(AnalyzeMode.NONE, AnalyzeMode.BARCODE)  
175 -//@Target(AnnotationTarget.FIELD)  
176 -//@Retention(AnnotationRetention.SOURCE)  
177 -//annotation class AnalyzeMode {  
178 -// companion object {  
179 -// const val NONE = 0  
180 -// const val BARCODE = 1  
181 -// }  
182 -//}  
  172 +
  173 +@IntDef(AnalyzeMode.NONE, AnalyzeMode.BARCODE)
  174 +@Target(AnnotationTarget.FIELD)
  175 +@Retention(AnnotationRetention.SOURCE)
  176 +annotation class AnalyzeMode {
  177 + companion object {
  178 + const val NONE = 0
  179 + const val BARCODE = 1
  180 + }
  181 +}
@@ -24,8 +24,6 @@ if (flutterVersionName == null) { @@ -24,8 +24,6 @@ if (flutterVersionName == null) {
24 apply plugin: 'com.android.application' 24 apply plugin: 'com.android.application'
25 apply plugin: 'kotlin-android' 25 apply plugin: 'kotlin-android'
26 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 26 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 -// Apply the Performance Monitoring plugin  
28 -apply plugin: 'com.google.firebase.firebase-perf'  
29 27
30 android { 28 android {
31 compileSdkVersion flutter.compileSdkVersion 29 compileSdkVersion flutter.compileSdkVersion
@@ -59,6 +57,7 @@ android { @@ -59,6 +57,7 @@ android {
59 signingConfig signingConfigs.debug 57 signingConfig signingConfigs.debug
60 } 58 }
61 } 59 }
  60 + namespace 'dev.steenbakker.mobile_scanner_example'
62 } 61 }
63 62
64 flutter { 63 flutter {
1 -<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
2 - package="dev.steenbakker.mobile_scanner_example"> 1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3 <!-- Flutter needs it to communicate with the running application 2 <!-- Flutter needs it to communicate with the running application
4 to allow setting breakpoints, to provide hot reload, etc. 3 to allow setting breakpoints, to provide hot reload, etc.
5 --> 4 -->
1 <manifest xmlns:android="http://schemas.android.com/apk/res/android" 1 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 - package="dev.steenbakker.mobile_scanner_example"> 2 + package="dev.steenbakker.mobile_scanner.example">
  3 +
3 <application 4 <application
4 android:label="mobile_scanner_example" 5 android:label="mobile_scanner_example"
5 - android:name="${applicationName}"  
6 android:icon="@mipmap/ic_launcher"> 6 android:icon="@mipmap/ic_launcher">
7 <activity 7 <activity
8 - android:name=".MainActivity" 8 + android:name="io.flutter.embedding.android.FlutterActivity"
9 android:exported="true" 9 android:exported="true"
10 android:launchMode="singleTop" 10 android:launchMode="singleTop"
11 android:theme="@style/LaunchTheme" 11 android:theme="@style/LaunchTheme"
1 -<manifest xmlns:android="http://schemas.android.com/apk/res/android"  
2 - package="dev.steenbakker.mobile_scanner_example"> 1 +<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3 <!-- Flutter needs it to communicate with the running application 2 <!-- Flutter needs it to communicate with the running application
4 to allow setting breakpoints, to provide hot reload, etc. 3 to allow setting breakpoints, to provide hot reload, etc.
5 --> 4 -->
@@ -6,8 +6,7 @@ buildscript { @@ -6,8 +6,7 @@ buildscript {
6 } 6 }
7 7
8 dependencies { 8 dependencies {
9 - classpath 'com.google.firebase:perf-plugin:1.4.0' // Performanc  
10 - classpath 'com.android.tools.build:gradle:7.0.4' 9 + classpath 'com.android.tools.build:gradle:7.1.0'
11 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 10 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
12 } 11 }
13 } 12 }
1 -  
2 import 'dart:ui'; 1 import 'dart:ui';
3 2
4 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
@@ -17,76 +16,75 @@ class AnalyzeView extends StatefulWidget { @@ -17,76 +16,75 @@ class AnalyzeView extends StatefulWidget {
17 16
18 class _AnalyzeViewState extends State<AnalyzeView> 17 class _AnalyzeViewState extends State<AnalyzeView>
19 with SingleTickerProviderStateMixin { 18 with SingleTickerProviderStateMixin {
20 -  
21 List<Offset> points = []; 19 List<Offset> points = [];
22 20
23 CameraController cameraController = CameraController(); 21 CameraController cameraController = CameraController();
24 22
25 String? barcode = null; 23 String? barcode = null;
26 24
27 -  
28 @override 25 @override
29 Widget build(BuildContext context) { 26 Widget build(BuildContext context) {
30 return MaterialApp( 27 return MaterialApp(
31 home: Scaffold( 28 home: Scaffold(
32 - body: Builder(  
33 - builder: (context) {  
34 - return Stack(  
35 - children: [  
36 - CameraView(cameraController,  
37 - onDetect: (barcode, args) {  
38 - if (this.barcode != barcode.rawValue) {  
39 - this.barcode = barcode.rawValue;  
40 - if ( barcode.corners != null) {  
41 - debugPrint('Size: ${MediaQuery.of(context).size}');  
42 - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('${barcode.rawValue}'), duration: Duration(milliseconds: 200), animation: null,));  
43 - setState(() {  
44 - final List<Offset> points = [];  
45 - double factorWidth = args.size.width / 520;  
46 - double factorHeight = args.size.height / 640;  
47 - for (var point in barcode.corners!) {  
48 - points.add(Offset(point.dx * factorWidth, point.dy * factorHeight));  
49 - }  
50 - this.points = points;  
51 - }); 29 + body: Builder(builder: (context) {
  30 + return Stack(
  31 + children: [
  32 + CameraView(
  33 + controller: cameraController,
  34 + onDetect: (barcode, args) {
  35 + if (this.barcode != barcode.rawValue) {
  36 + this.barcode = barcode.rawValue;
  37 + if (barcode.corners != null) {
  38 + debugPrint('Size: ${MediaQuery.of(context).size}');
  39 + ScaffoldMessenger.of(context).showSnackBar(SnackBar(
  40 + content: Text('${barcode.rawValue}'),
  41 + duration: Duration(milliseconds: 200),
  42 + animation: null,
  43 + ));
  44 + setState(() {
  45 + final List<Offset> points = [];
  46 + double factorWidth = args.size.width / 520;
  47 + double factorHeight = args.size.height / 640;
  48 + for (var point in barcode.corners!) {
  49 + points.add(Offset(point.dx * factorWidth,
  50 + point.dy * factorHeight));
  51 + }
  52 + this.points = points;
  53 + });
  54 + }
52 } 55 }
53 - }  
54 - // Default 640 x480  
55 -  
56 - }),  
57 - Container(  
58 - // width: 400,  
59 - // height: 400,  
60 - child: CustomPaint(  
61 - painter: OpenPainter(points),  
62 - ), 56 + // Default 640 x480
  57 + }),
  58 + Container(
  59 + // width: 400,
  60 + // height: 400,
  61 + child: CustomPaint(
  62 + painter: OpenPainter(points),
63 ), 63 ),
64 - Container(  
65 - alignment: Alignment.bottomCenter,  
66 - margin: EdgeInsets.only(bottom: 80.0),  
67 - child: IconButton(  
68 - icon: ValueListenableBuilder(  
69 - valueListenable: cameraController.torchState,  
70 - builder: (context, state, child) {  
71 - final color =  
72 - state == TorchState.off ? Colors.grey : Colors.white;  
73 - return Icon(Icons.bolt, color: color);  
74 - },  
75 - ),  
76 - iconSize: 32.0,  
77 - onPressed: () => cameraController.torch(), 64 + ),
  65 + Container(
  66 + alignment: Alignment.bottomCenter,
  67 + margin: EdgeInsets.only(bottom: 80.0),
  68 + child: IconButton(
  69 + icon: ValueListenableBuilder(
  70 + valueListenable: cameraController.torchState,
  71 + builder: (context, state, child) {
  72 + final color =
  73 + state == TorchState.off ? Colors.grey : Colors.white;
  74 + return Icon(Icons.bolt, color: color);
  75 + },
78 ), 76 ),
  77 + iconSize: 32.0,
  78 + onPressed: () => cameraController.torch(),
79 ), 79 ),
80 - ],  
81 - );  
82 - }  
83 - ), 80 + ),
  81 + ],
  82 + );
  83 + }),
84 ), 84 ),
85 ); 85 );
86 } 86 }
87 87
88 -  
89 -  
90 @override 88 @override
91 void dispose() { 89 void dispose() {
92 cameraController.dispose(); 90 cameraController.dispose();
@@ -4,11 +4,20 @@ import 'package:flutter/cupertino.dart'; @@ -4,11 +4,20 @@ import 'package:flutter/cupertino.dart';
4 import 'package:flutter/services.dart'; 4 import 'package:flutter/services.dart';
5 5
6 import 'camera_args.dart'; 6 import 'camera_args.dart';
7 -import 'camera_facing.dart';  
8 import 'objects/barcode.dart'; 7 import 'objects/barcode.dart';
9 import 'torch_state.dart'; 8 import 'torch_state.dart';
10 import 'util.dart'; 9 import 'util.dart';
11 10
  11 +/// The facing of a camera.
  12 +enum CameraFacing {
  13 + /// Front facing camera.
  14 + front,
  15 +
  16 + /// Back facing camera.
  17 + back,
  18 +}
  19 +
  20 +
12 /// A camera controller. 21 /// A camera controller.
13 abstract class CameraController { 22 abstract class CameraController {
14 /// Arguments for [CameraView]. 23 /// Arguments for [CameraView].
1 -/// The facing of a camera.  
2 -enum CameraFacing {  
3 - /// Front facing camera.  
4 - front,  
5 -  
6 - /// Back facing camera.  
7 - back,  
8 -}  
@@ -2,44 +2,60 @@ import 'package:flutter/material.dart'; @@ -2,44 +2,60 @@ import 'package:flutter/material.dart';
2 import 'package:mobile_scanner/mobile_scanner.dart'; 2 import 'package:mobile_scanner/mobile_scanner.dart';
3 3
4 import 'camera_args.dart'; 4 import 'camera_args.dart';
5 -import 'camera_controller.dart';  
6 5
7 /// A widget showing a live camera preview. 6 /// A widget showing a live camera preview.
8 -class CameraView extends StatelessWidget { 7 +class CameraView extends StatefulWidget {
9 /// The controller of the camera. 8 /// The controller of the camera.
10 - final CameraController controller; 9 + final CameraController? controller;
11 final Function(Barcode barcode, CameraArgs args)? onDetect; 10 final Function(Barcode barcode, CameraArgs args)? onDetect;
12 11
13 /// Create a [CameraView] with a [controller], the [controller] must has been initialized. 12 /// Create a [CameraView] with a [controller], the [controller] must has been initialized.
14 - CameraView(this.controller, {this.onDetect}); 13 + const CameraView({Key? key, this.onDetect, this.controller}) : super(key: key);
  14 +
  15 + @override
  16 + State<CameraView> createState() => _CameraViewState();
  17 +}
  18 +
  19 +class _CameraViewState extends State<CameraView> {
  20 +
  21 + late CameraController controller;
  22 + @override
  23 + initState() {
  24 + super.initState();
  25 + controller = widget.controller ?? CameraController();
  26 + }
15 27
16 @override 28 @override
17 Widget build(BuildContext context) { 29 Widget build(BuildContext context) {
18 return ValueListenableBuilder( 30 return ValueListenableBuilder(
19 - valueListenable: controller.args,  
20 - builder: (context, value, child) => _build(context, value as CameraArgs?),  
21 - );  
22 - } 31 + valueListenable: controller.args,
  32 + builder: (context, value, child) {
  33 + value = value as CameraArgs?;
  34 + if (value == null) {
  35 + return Container(color: Colors.black);
  36 + } else {
  37 + controller.barcodes
  38 + .listen((a) => widget.onDetect!(a, value as CameraArgs));
23 39
24 - Widget _build(BuildContext context, CameraArgs? value) {  
25 - if (value == null) {  
26 - return Container(color: Colors.black);  
27 - } else { 40 + return ClipRect(
  41 + child: Transform.scale(
  42 + scale: value.size.fill(MediaQuery.of(context).size),
  43 + child: Center(
  44 + child: AspectRatio(
  45 + aspectRatio: value.size.aspectRatio,
  46 + child: Texture(textureId: value.textureId),
  47 + ),
  48 + ),
  49 + ),
  50 + );
  51 + }
  52 + });
  53 + }
28 54
29 - controller.barcodes.listen((a) => onDetect!(a, value));  
30 -  
31 - return ClipRect(  
32 - child: Transform.scale(  
33 - scale: value.size.fill(MediaQuery.of(context) .size),  
34 - child: Center(  
35 - child: AspectRatio(  
36 - aspectRatio: value.size.aspectRatio,  
37 - child: Texture(textureId: value.textureId),  
38 - ),  
39 - ),  
40 - ),  
41 - );  
42 - } 55 + @override
  56 + void dispose() {
  57 + controller.dispose();
  58 + super.dispose();
43 } 59 }
44 } 60 }
45 61
1 -import 'dart:async';  
2 -import 'package:flutter/material.dart';  
3 -import 'package:mobile_scanner/src/mobile_scanner_handler.dart';  
4 -import 'package:mobile_scanner/src/objects/preview_details.dart';  
5 -  
6 -import 'mobile_scanner_preview.dart';  
7 -import 'objects/barcode_formats.dart';  
8 -  
9 -typedef ErrorCallback = Widget Function(BuildContext context, Object? error);  
10 -  
11 -Text _defaultNotStartedBuilder(context) => const Text("Camera Loading ...");  
12 -Text _defaultOffscreenBuilder(context) => const Text("Camera Paused.");  
13 -Text _defaultOnError(BuildContext context, Object? error) {  
14 - debugPrint("Error reading from camera: $error");  
15 - return const Text("Error reading from camera...");  
16 -}  
17 -  
18 -class MobileScanner extends StatefulWidget {  
19 - const MobileScanner(  
20 - {Key? key,  
21 - required this.qrCodeCallback,  
22 - this.child,  
23 - this.fit = BoxFit.cover,  
24 - WidgetBuilder? notStartedBuilder,  
25 - WidgetBuilder? offscreenBuilder,  
26 - ErrorCallback? onError,  
27 - this.formats,  
28 - this.rearLens = true,  
29 - this.manualFocus = false})  
30 - : notStartedBuilder = notStartedBuilder ?? _defaultNotStartedBuilder,  
31 - offscreenBuilder =  
32 - offscreenBuilder ?? notStartedBuilder ?? _defaultOffscreenBuilder,  
33 - onError = onError ?? _defaultOnError,  
34 - super(key: key);  
35 -  
36 - final BoxFit fit;  
37 - final ValueChanged<String?> qrCodeCallback;  
38 - final Widget? child;  
39 - final WidgetBuilder notStartedBuilder;  
40 - final WidgetBuilder offscreenBuilder;  
41 - final ErrorCallback onError;  
42 - final List<BarcodeFormats>? formats;  
43 - final bool rearLens;  
44 - final bool manualFocus;  
45 -  
46 - static void toggleFlash() {  
47 - MobileScannerHandler.toggleFlash();  
48 - }  
49 -  
50 - static void flipCamera() {  
51 - MobileScannerHandler.switchCamera();  
52 - }  
53 -  
54 - @override  
55 - _MobileScannerState createState() => _MobileScannerState();  
56 -}  
57 -  
58 -class _MobileScannerState extends State<MobileScanner>  
59 - with WidgetsBindingObserver {  
60 -  
61 - bool onScreen = true;  
62 - Future<PreviewDetails>? _previewDetails;  
63 -  
64 - @override  
65 - void initState() {  
66 - super.initState();  
67 - WidgetsBinding.instance!.addObserver(this);  
68 - }  
69 -  
70 - @override  
71 - void dispose() {  
72 - WidgetsBinding.instance!.removeObserver(this);  
73 - super.dispose();  
74 - }  
75 -  
76 - @override  
77 - void didChangeAppLifecycleState(AppLifecycleState state) {  
78 - if (state == AppLifecycleState.resumed) {  
79 - setState(() => onScreen = true);  
80 - } else {  
81 - if (_previewDetails != null && onScreen) {  
82 - MobileScannerHandler.stop();  
83 - }  
84 - setState(() {  
85 - onScreen = false;  
86 - _previewDetails = null;  
87 - });  
88 - }  
89 - }  
90 -  
91 - Future<PreviewDetails> _initPreview(num width, num height) async {  
92 - final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;  
93 - return await MobileScannerHandler.start(  
94 - width: (devicePixelRatio * width.toInt()).ceil(),  
95 - height: (devicePixelRatio * height.toInt()).ceil(),  
96 - qrCodeHandler: widget.qrCodeCallback,  
97 - formats: widget.formats,  
98 - );  
99 - }  
100 -  
101 - void switchCamera() {  
102 - MobileScannerHandler.rearLens = !MobileScannerHandler.rearLens;  
103 - restart();  
104 - }  
105 -  
106 -  
107 - void switchFocus() {  
108 - MobileScannerHandler.manualFocus = !MobileScannerHandler.manualFocus;  
109 - restart();  
110 - }  
111 -  
112 - /// This method can be used to restart scanning  
113 - /// the event that it was paused.  
114 - Future<void> restart() async {  
115 - await MobileScannerHandler.stop();  
116 - setState(() {  
117 - _previewDetails = null;  
118 - });  
119 - }  
120 -  
121 - /// This method can be used to manually stop the  
122 - /// camera.  
123 - Future<void> stop() async {  
124 - await MobileScannerHandler.stop();  
125 - }  
126 -  
127 - @override  
128 - deactivate() {  
129 - super.deactivate();  
130 - MobileScannerHandler.stop();  
131 - }  
132 -  
133 - @override  
134 - Widget build(BuildContext context) {  
135 - return LayoutBuilder(  
136 - builder: (BuildContext context, BoxConstraints constraints) {  
137 - if (_previewDetails == null && onScreen) {  
138 - _previewDetails =  
139 - _initPreview(constraints.maxWidth, constraints.maxHeight);  
140 - } else if (!onScreen) {  
141 - return widget.offscreenBuilder(context);  
142 - }  
143 -  
144 - return FutureBuilder(  
145 - future: _previewDetails,  
146 - builder: (BuildContext context, AsyncSnapshot<PreviewDetails> details) {  
147 - switch (details.connectionState) {  
148 - case ConnectionState.none:  
149 - case ConnectionState.waiting:  
150 - return widget.notStartedBuilder(context);  
151 - case ConnectionState.done:  
152 - if (details.hasError) {  
153 - debugPrint(details.error.toString());  
154 - return widget.onError(context, details.error);  
155 - }  
156 - Widget preview = SizedBox(  
157 - width: constraints.maxWidth,  
158 - height: constraints.maxHeight,  
159 - child: Preview(  
160 - previewDetails: details.data!,  
161 - targetWidth: constraints.maxWidth,  
162 - targetHeight: constraints.maxHeight,  
163 - fit: widget.fit,  
164 - ),  
165 - );  
166 -  
167 - if (widget.child != null) {  
168 - return Stack(  
169 - children: [  
170 - preview,  
171 - widget.child!,  
172 - ],  
173 - );  
174 - }  
175 - return preview;  
176 -  
177 - default:  
178 - throw AssertionError("${details.connectionState} not supported.");  
179 - }  
180 - },  
181 - );  
182 - });  
183 - }  
184 -} 1 +// import 'dart:async';
  2 +// import 'package:flutter/material.dart';
  3 +// import 'package:mobile_scanner/src/mobile_scanner_handler.dart';
  4 +// import 'package:mobile_scanner/src/objects/preview_details.dart';
  5 +//
  6 +// import 'mobile_scanner_preview.dart';
  7 +// import 'objects/barcode_formats.dart';
  8 +//
  9 +// typedef ErrorCallback = Widget Function(BuildContext context, Object? error);
  10 +//
  11 +// Text _defaultNotStartedBuilder(context) => const Text("Camera Loading ...");
  12 +// Text _defaultOffscreenBuilder(context) => const Text("Camera Paused.");
  13 +// Text _defaultOnError(BuildContext context, Object? error) {
  14 +// debugPrint("Error reading from camera: $error");
  15 +// return const Text("Error reading from camera...");
  16 +// }
  17 +//
  18 +// class MobileScanner extends StatefulWidget {
  19 +// const MobileScanner(
  20 +// {Key? key,
  21 +// required this.qrCodeCallback,
  22 +// this.child,
  23 +// this.fit = BoxFit.cover,
  24 +// WidgetBuilder? notStartedBuilder,
  25 +// WidgetBuilder? offscreenBuilder,
  26 +// ErrorCallback? onError,
  27 +// this.formats,
  28 +// this.rearLens = true,
  29 +// this.manualFocus = false})
  30 +// : notStartedBuilder = notStartedBuilder ?? _defaultNotStartedBuilder,
  31 +// offscreenBuilder =
  32 +// offscreenBuilder ?? notStartedBuilder ?? _defaultOffscreenBuilder,
  33 +// onError = onError ?? _defaultOnError,
  34 +// super(key: key);
  35 +//
  36 +// final BoxFit fit;
  37 +// final ValueChanged<String?> qrCodeCallback;
  38 +// final Widget? child;
  39 +// final WidgetBuilder notStartedBuilder;
  40 +// final WidgetBuilder offscreenBuilder;
  41 +// final ErrorCallback onError;
  42 +// final List<BarcodeFormats>? formats;
  43 +// final bool rearLens;
  44 +// final bool manualFocus;
  45 +//
  46 +// static void toggleFlash() {
  47 +// MobileScannerHandler.toggleFlash();
  48 +// }
  49 +//
  50 +// static void flipCamera() {
  51 +// MobileScannerHandler.switchCamera();
  52 +// }
  53 +//
  54 +// @override
  55 +// _MobileScannerState createState() => _MobileScannerState();
  56 +// }
  57 +//
  58 +// class _MobileScannerState extends State<MobileScanner>
  59 +// with WidgetsBindingObserver {
  60 +//
  61 +// bool onScreen = true;
  62 +// Future<PreviewDetails>? _previewDetails;
  63 +//
  64 +// @override
  65 +// void initState() {
  66 +// super.initState();
  67 +// WidgetsBinding.instance!.addObserver(this);
  68 +// }
  69 +//
  70 +// @override
  71 +// void dispose() {
  72 +// WidgetsBinding.instance!.removeObserver(this);
  73 +// super.dispose();
  74 +// }
  75 +//
  76 +// @override
  77 +// void didChangeAppLifecycleState(AppLifecycleState state) {
  78 +// if (state == AppLifecycleState.resumed) {
  79 +// setState(() => onScreen = true);
  80 +// } else {
  81 +// if (_previewDetails != null && onScreen) {
  82 +// MobileScannerHandler.stop();
  83 +// }
  84 +// setState(() {
  85 +// onScreen = false;
  86 +// _previewDetails = null;
  87 +// });
  88 +// }
  89 +// }
  90 +//
  91 +// Future<PreviewDetails> _initPreview(num width, num height) async {
  92 +// final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
  93 +// return await MobileScannerHandler.start(
  94 +// width: (devicePixelRatio * width.toInt()).ceil(),
  95 +// height: (devicePixelRatio * height.toInt()).ceil(),
  96 +// qrCodeHandler: widget.qrCodeCallback,
  97 +// formats: widget.formats,
  98 +// );
  99 +// }
  100 +//
  101 +// void switchCamera() {
  102 +// MobileScannerHandler.rearLens = !MobileScannerHandler.rearLens;
  103 +// restart();
  104 +// }
  105 +//
  106 +//
  107 +// void switchFocus() {
  108 +// MobileScannerHandler.manualFocus = !MobileScannerHandler.manualFocus;
  109 +// restart();
  110 +// }
  111 +//
  112 +// /// This method can be used to restart scanning
  113 +// /// the event that it was paused.
  114 +// Future<void> restart() async {
  115 +// await MobileScannerHandler.stop();
  116 +// setState(() {
  117 +// _previewDetails = null;
  118 +// });
  119 +// }
  120 +//
  121 +// /// This method can be used to manually stop the
  122 +// /// camera.
  123 +// Future<void> stop() async {
  124 +// await MobileScannerHandler.stop();
  125 +// }
  126 +//
  127 +// @override
  128 +// deactivate() {
  129 +// super.deactivate();
  130 +// MobileScannerHandler.stop();
  131 +// }
  132 +//
  133 +// @override
  134 +// Widget build(BuildContext context) {
  135 +// return LayoutBuilder(
  136 +// builder: (BuildContext context, BoxConstraints constraints) {
  137 +// if (_previewDetails == null && onScreen) {
  138 +// _previewDetails =
  139 +// _initPreview(constraints.maxWidth, constraints.maxHeight);
  140 +// } else if (!onScreen) {
  141 +// return widget.offscreenBuilder(context);
  142 +// }
  143 +//
  144 +// return FutureBuilder(
  145 +// future: _previewDetails,
  146 +// builder: (BuildContext context, AsyncSnapshot<PreviewDetails> details) {
  147 +// switch (details.connectionState) {
  148 +// case ConnectionState.none:
  149 +// case ConnectionState.waiting:
  150 +// return widget.notStartedBuilder(context);
  151 +// case ConnectionState.done:
  152 +// if (details.hasError) {
  153 +// debugPrint(details.error.toString());
  154 +// return widget.onError(context, details.error);
  155 +// }
  156 +// Widget preview = SizedBox(
  157 +// width: constraints.maxWidth,
  158 +// height: constraints.maxHeight,
  159 +// child: Preview(
  160 +// previewDetails: details.data!,
  161 +// targetWidth: constraints.maxWidth,
  162 +// targetHeight: constraints.maxHeight,
  163 +// fit: widget.fit,
  164 +// ),
  165 +// );
  166 +//
  167 +// if (widget.child != null) {
  168 +// return Stack(
  169 +// children: [
  170 +// preview,
  171 +// widget.child!,
  172 +// ],
  173 +// );
  174 +// }
  175 +// return preview;
  176 +//
  177 +// default:
  178 +// throw AssertionError("${details.connectionState} not supported.");
  179 +// }
  180 +// },
  181 +// );
  182 +// });
  183 +// }
  184 +// }
1 -import 'dart:async';  
2 -  
3 -import 'package:flutter/material.dart';  
4 -import 'package:mobile_scanner/src/objects/preview_details.dart';  
5 -import 'package:native_device_orientation/native_device_orientation.dart';  
6 -import 'package:sensors_plus/sensors_plus.dart';  
7 -  
8 -class Preview extends StatefulWidget {  
9 - final double width, height;  
10 - final double targetWidth, targetHeight;  
11 - final int? textureId;  
12 - final int? sensorOrientation;  
13 - final BoxFit fit;  
14 -  
15 - Preview({  
16 - Key? key,  
17 - required PreviewDetails previewDetails,  
18 - required this.targetWidth,  
19 - required this.targetHeight,  
20 - required this.fit,  
21 - }) : textureId = previewDetails.textureId,  
22 - width = previewDetails.width!.toDouble(),  
23 - height = previewDetails.height!.toDouble(),  
24 - sensorOrientation = previewDetails.sensorOrientation as int?,  
25 - super(key: key);  
26 -  
27 - @override  
28 - State<Preview> createState() => _PreviewState();  
29 -}  
30 -  
31 -class _PreviewState extends State<Preview> {  
32 -  
33 - final _streamSubscriptions = <StreamSubscription<dynamic>>[];  
34 - bool landscapeLeft = false;  
35 -  
36 - @override  
37 - void initState() {  
38 - super.initState();  
39 - _streamSubscriptions.add(  
40 - magnetometerEvents.listen(  
41 - (MagnetometerEvent event) {  
42 - if (event.x <= 0) {  
43 - landscapeLeft = true;  
44 - } else {  
45 - landscapeLeft = false;  
46 - }  
47 - },  
48 - ),  
49 - );  
50 - }  
51 -  
52 - @override  
53 - void dispose() {  
54 - super.dispose();  
55 - for (final subscription in _streamSubscriptions) {  
56 - subscription.cancel();  
57 - }  
58 - }  
59 -  
60 -  
61 - int _getRotationCompensation(NativeDeviceOrientation nativeOrientation) {  
62 - int nativeRotation = 0;  
63 - switch (nativeOrientation) {  
64 - case NativeDeviceOrientation.portraitUp:  
65 - nativeRotation = 0;  
66 - break;  
67 - case NativeDeviceOrientation.landscapeRight:  
68 - nativeRotation = 90;  
69 - break;  
70 - case NativeDeviceOrientation.portraitDown:  
71 - nativeRotation = 180;  
72 - break;  
73 - case NativeDeviceOrientation.landscapeLeft:  
74 - nativeRotation = 270;  
75 - break;  
76 - case NativeDeviceOrientation.unknown:  
77 - default:  
78 - break;  
79 - }  
80 -  
81 - return ((nativeRotation - widget.sensorOrientation! + 450) % 360) ~/ 90;  
82 - }  
83 -  
84 - @override  
85 - Widget build(BuildContext context) {  
86 - final orientation = MediaQuery.of(context).orientation;  
87 - double frameHeight = widget.width;  
88 - double frameWidth = widget.height;  
89 -  
90 - return ClipRect(  
91 - child: FittedBox(  
92 - fit: widget.fit,  
93 - child: RotatedBox(  
94 - quarterTurns: orientation == Orientation.landscape ? landscapeLeft ? 1 : 3 : 0,  
95 - child: SizedBox(  
96 - width: frameWidth,  
97 - height: frameHeight,  
98 - child: Texture(textureId: widget.textureId!),  
99 - ),  
100 - ),  
101 - ),  
102 - );  
103 -  
104 - return NativeDeviceOrientationReader(  
105 - builder: (context) {  
106 - var nativeOrientation =  
107 - NativeDeviceOrientationReader.orientation(context);  
108 -  
109 - double frameHeight = widget.width;  
110 - double frameWidth = widget.height;  
111 -  
112 - return ClipRect(  
113 - child: FittedBox(  
114 - fit: widget.fit,  
115 - child: RotatedBox(  
116 - quarterTurns: _getRotationCompensation(nativeOrientation),  
117 - child: SizedBox(  
118 - width: frameWidth,  
119 - height: frameHeight,  
120 - child: Texture(textureId: widget.textureId!),  
121 - ),  
122 - ),  
123 - ),  
124 - );  
125 - },  
126 - );  
127 - }  
128 -} 1 +// import 'dart:async';
  2 +//
  3 +// import 'package:flutter/material.dart';
  4 +// import 'package:mobile_scanner/src/objects/preview_details.dart';
  5 +//
  6 +// class Preview extends StatefulWidget {
  7 +// final double width, height;
  8 +// final double targetWidth, targetHeight;
  9 +// final int? textureId;
  10 +// final int? sensorOrientation;
  11 +// final BoxFit fit;
  12 +//
  13 +// Preview({
  14 +// Key? key,
  15 +// required PreviewDetails previewDetails,
  16 +// required this.targetWidth,
  17 +// required this.targetHeight,
  18 +// required this.fit,
  19 +// }) : textureId = previewDetails.textureId,
  20 +// width = previewDetails.width!.toDouble(),
  21 +// height = previewDetails.height!.toDouble(),
  22 +// sensorOrientation = previewDetails.sensorOrientation as int?,
  23 +// super(key: key);
  24 +//
  25 +// @override
  26 +// State<Preview> createState() => _PreviewState();
  27 +// }
  28 +//
  29 +// class _PreviewState extends State<Preview> {
  30 +//
  31 +// final _streamSubscriptions = <StreamSubscription<dynamic>>[];
  32 +// bool landscapeLeft = false;
  33 +//
  34 +// @override
  35 +// void initState() {
  36 +// super.initState();
  37 +// _streamSubscriptions.add(
  38 +// magnetometerEvents.listen(
  39 +// (MagnetometerEvent event) {
  40 +// if (event.x <= 0) {
  41 +// landscapeLeft = true;
  42 +// } else {
  43 +// landscapeLeft = false;
  44 +// }
  45 +// },
  46 +// ),
  47 +// );
  48 +// }
  49 +//
  50 +// @override
  51 +// void dispose() {
  52 +// super.dispose();
  53 +// for (final subscription in _streamSubscriptions) {
  54 +// subscription.cancel();
  55 +// }
  56 +// }
  57 +//
  58 +//
  59 +// int _getRotationCompensation(NativeDeviceOrientation nativeOrientation) {
  60 +// int nativeRotation = 0;
  61 +// switch (nativeOrientation) {
  62 +// case NativeDeviceOrientation.portraitUp:
  63 +// nativeRotation = 0;
  64 +// break;
  65 +// case NativeDeviceOrientation.landscapeRight:
  66 +// nativeRotation = 90;
  67 +// break;
  68 +// case NativeDeviceOrientation.portraitDown:
  69 +// nativeRotation = 180;
  70 +// break;
  71 +// case NativeDeviceOrientation.landscapeLeft:
  72 +// nativeRotation = 270;
  73 +// break;
  74 +// case NativeDeviceOrientation.unknown:
  75 +// default:
  76 +// break;
  77 +// }
  78 +//
  79 +// return ((nativeRotation - widget.sensorOrientation! + 450) % 360) ~/ 90;
  80 +// }
  81 +//
  82 +// @override
  83 +// Widget build(BuildContext context) {
  84 +// final orientation = MediaQuery.of(context).orientation;
  85 +// double frameHeight = widget.width;
  86 +// double frameWidth = widget.height;
  87 +//
  88 +// return ClipRect(
  89 +// child: FittedBox(
  90 +// fit: widget.fit,
  91 +// child: RotatedBox(
  92 +// quarterTurns: orientation == Orientation.landscape ? landscapeLeft ? 1 : 3 : 0,
  93 +// child: SizedBox(
  94 +// width: frameWidth,
  95 +// height: frameHeight,
  96 +// child: Texture(textureId: widget.textureId!),
  97 +// ),
  98 +// ),
  99 +// ),
  100 +// );
  101 +//
  102 +// return NativeDeviceOrientationReader(
  103 +// builder: (context) {
  104 +// var nativeOrientation =
  105 +// NativeDeviceOrientationReader.orientation(context);
  106 +//
  107 +// double frameHeight = widget.width;
  108 +// double frameWidth = widget.height;
  109 +//
  110 +// return ClipRect(
  111 +// child: FittedBox(
  112 +// fit: widget.fit,
  113 +// child: RotatedBox(
  114 +// quarterTurns: _getRotationCompensation(nativeOrientation),
  115 +// child: SizedBox(
  116 +// width: frameWidth,
  117 +// height: frameHeight,
  118 +// child: Texture(textureId: widget.textureId!),
  119 +// ),
  120 +// ),
  121 +// ),
  122 +// );
  123 +// },
  124 +// );
  125 +// }
  126 +// }
@@ -8,25 +8,15 @@ environment: @@ -8,25 +8,15 @@ environment:
8 flutter: ">=2.5.0" 8 flutter: ">=2.5.0"
9 9
10 dependencies: 10 dependencies:
11 - native_device_orientation: ^1.0.0  
12 - sensors_plus: ^1.2.1  
13 flutter: 11 flutter:
14 sdk: flutter 12 sdk: flutter
15 13
16 dev_dependencies: 14 dev_dependencies:
17 flutter_test: 15 flutter_test:
18 sdk: flutter 16 sdk: flutter
19 - flutter_lints: ^1.0.0 17 + flutter_lints: ^1.0.4
20 18
21 -# For information on the generic Dart part of this file, see the  
22 -# following page: https://dart.dev/tools/pub/pubspec  
23 -  
24 -# The following section is specific to Flutter.  
25 flutter: 19 flutter:
26 - # This section identifies this Flutter project as a plugin project.  
27 - # The 'pluginClass' and Android 'package' identifiers should not ordinarily  
28 - # be modified. They are used by the tooling to maintain consistency when  
29 - # adding or updating assets for this project.  
30 plugin: 20 plugin:
31 platforms: 21 platforms:
32 android: 22 android:
@@ -36,34 +26,3 @@ flutter: @@ -36,34 +26,3 @@ flutter:
36 pluginClass: MobileScannerPlugin 26 pluginClass: MobileScannerPlugin
37 macos: 27 macos:
38 pluginClass: MobileScannerPlugin 28 pluginClass: MobileScannerPlugin
39 -  
40 - # To add assets to your plugin package, add an assets section, like this:  
41 - # assets:  
42 - # - images/a_dot_burr.jpeg  
43 - # - images/a_dot_ham.jpeg  
44 - #  
45 - # For details regarding assets in packages, see  
46 - # https://flutter.dev/assets-and-images/#from-packages  
47 - #  
48 - # An image asset can refer to one or more resolution-specific "variants", see  
49 - # https://flutter.dev/assets-and-images/#resolution-aware.  
50 -  
51 - # To add custom fonts to your plugin package, add a fonts section here,  
52 - # in this "flutter" section. Each entry in this list should have a  
53 - # "family" key with the font family name, and a "fonts" key with a  
54 - # list giving the asset and other descriptors for the font. For  
55 - # example:  
56 - # fonts:  
57 - # - family: Schyler  
58 - # fonts:  
59 - # - asset: fonts/Schyler-Regular.ttf  
60 - # - asset: fonts/Schyler-Italic.ttf  
61 - # style: italic  
62 - # - family: Trajan Pro  
63 - # fonts:  
64 - # - asset: fonts/TrajanPro.ttf  
65 - # - asset: fonts/TrajanPro_Bold.ttf  
66 - # weight: 700  
67 - #  
68 - # For details regarding fonts in packages, see  
69 - # https://flutter.dev/custom-fonts/#from-packages