Julian Steenbakker
Committed by GitHub

Merge pull request #470 from juliansteenbakker/bug/parameter-not-resetting

fix: parameter not resetting
... ... @@ -19,23 +19,6 @@ import dev.steenbakker.mobile_scanner.objects.MobileScannerStartParameters
import io.flutter.view.TextureRegistry
import kotlin.math.roundToInt
typealias MobileScannerCallback = (barcodes: List<Map<String, Any?>>, image: ByteArray?, width: Int?, height: Int?) -> Unit
typealias AnalyzerCallback = (barcodes: List<Map<String, Any?>>?) -> Unit
typealias MobileScannerErrorCallback = (error: String) -> Unit
typealias TorchStateCallback = (state: Int) -> Unit
typealias MobileScannerStartedCallback = (parameters: MobileScannerStartParameters) -> Unit
class NoCamera : Exception()
class AlreadyStarted : Exception()
class AlreadyStopped : Exception()
class TorchError : Exception()
class CameraError : Exception()
class TorchWhenStopped : Exception()
class ZoomWhenStopped : Exception()
class ZoomNotInRange : Exception()
class MobileScanner(
private val activity: Activity,
private val textureRegistry: TextureRegistry,
... ... @@ -43,22 +26,21 @@ class MobileScanner(
private val mobileScannerErrorCallback: MobileScannerErrorCallback
) {
/// Internal variables
private var cameraProvider: ProcessCameraProvider? = null
private var camera: Camera? = null
private var preview: Preview? = null
private var textureEntry: TextureRegistry.SurfaceTextureEntry? = null
var scanWindow: List<Float>? = null
private var detectionSpeed: DetectionSpeed = DetectionSpeed.NO_DUPLICATES
private var detectionTimeout: Long = 250
private var scanner = BarcodeScanning.getClient()
private var lastScanned: List<String?>? = null
private var scannerTimeout = false
/// Configurable variables
var scanWindow: List<Float>? = null
private var detectionSpeed: DetectionSpeed = DetectionSpeed.NO_DUPLICATES
private var detectionTimeout: Long = 250
private var returnImage = false
private var scanner = BarcodeScanning.getClient()
/**
* callback for the camera. Every frame is passed through this function.
*/
... ... @@ -87,10 +69,10 @@ class MobileScanner(
val barcodeMap: MutableList<Map<String, Any?>> = mutableListOf()
for ( barcode in barcodes) {
if(scanWindow != null) {
val match = isbarCodeInScanWindow(scanWindow!!, barcode, imageProxy)
if(!match) {
for (barcode in barcodes) {
if (scanWindow != null) {
val match = isBarcodeInScanWindow(scanWindow!!, barcode, imageProxy)
if (!match) {
continue
} else {
barcodeMap.add(barcode.data)
... ... @@ -126,7 +108,11 @@ class MobileScanner(
// scales the scanWindow to the provided inputImage and checks if that scaled
// scanWindow contains the barcode
private fun isbarCodeInScanWindow(scanWindow: List<Float>, barcode: Barcode, inputImage: ImageProxy): Boolean {
private fun isBarcodeInScanWindow(
scanWindow: List<Float>,
barcode: Barcode,
inputImage: ImageProxy
): Boolean {
val barcodeBoundingBox = barcode.boundingBox ?: return false
val imageWidth = inputImage.height
... ...
package dev.steenbakker.mobile_scanner
import dev.steenbakker.mobile_scanner.objects.MobileScannerStartParameters
typealias MobileScannerCallback = (barcodes: List<Map<String, Any?>>, image: ByteArray?, width: Int?, height: Int?) -> Unit
typealias AnalyzerCallback = (barcodes: List<Map<String, Any?>>?) -> Unit
typealias MobileScannerErrorCallback = (error: String) -> Unit
typealias TorchStateCallback = (state: Int) -> Unit
typealias MobileScannerStartedCallback = (parameters: MobileScannerStartParameters) -> Unit
\ No newline at end of file
... ...
package dev.steenbakker.mobile_scanner
class NoCamera : Exception()
class AlreadyStarted : Exception()
class AlreadyStopped : Exception()
class TorchError : Exception()
class CameraError : Exception()
class TorchWhenStopped : Exception()
class ZoomWhenStopped : Exception()
class ZoomNotInRange : Exception()
\ No newline at end of file
... ...
... ... @@ -230,6 +230,6 @@ class MobileScannerHandler(
}
private fun updateScanWindow(call: MethodCall) {
mobileScanner!!.scanWindow = call.argument<List<Float>>("rect")
mobileScanner!!.scanWindow = call.argument<List<Float>?>("rect")
}
}
\ No newline at end of file
... ...
... ... @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
... ... @@ -199,6 +199,7 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
... ... @@ -213,6 +214,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
... ...
... ... @@ -49,5 +49,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
... ...
... ... @@ -197,10 +197,4 @@ class _BarcodeScannerWithControllerState
),
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
}
... ...
import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:mobile_scanner_example/scanner_error_widget.dart';
class BarcodeScannerPageView extends StatefulWidget {
const BarcodeScannerPageView({Key? key}) : super(key: key);
@override
_BarcodeScannerPageViewState createState() => _BarcodeScannerPageViewState();
}
class _BarcodeScannerPageViewState extends State<BarcodeScannerPageView>
with SingleTickerProviderStateMixin {
BarcodeCapture? capture;
Widget cameraView() {
return Builder(
builder: (context) {
return Stack(
children: [
MobileScanner(
startDelay: true,
controller: MobileScannerController(torchEnabled: true),
fit: BoxFit.contain,
errorBuilder: (context, error, child) {
return ScannerErrorWidget(error: error);
},
onDetect: (capture) {
setState(() {
this.capture = capture;
});
},
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
alignment: Alignment.bottomCenter,
height: 100,
color: Colors.black.withOpacity(0.4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Center(
child: SizedBox(
width: MediaQuery.of(context).size.width - 120,
height: 50,
child: FittedBox(
child: Text(
capture?.barcodes.first.rawValue ??
'Scan something!',
overflow: TextOverflow.fade,
style: Theme.of(context)
.textTheme
.headlineMedium!
.copyWith(color: Colors.white),
),
),
),
),
],
),
),
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: PageView(
children: [
cameraView(),
Container(),
cameraView(),
cameraView(),
],
),
);
}
}
... ...
import 'package:flutter/material.dart';
import 'package:mobile_scanner_example/barcode_list_scanner_controller.dart';
import 'package:mobile_scanner_example/barcode_scanner_controller.dart';
import 'package:mobile_scanner_example/barcode_scanner_pageview.dart';
import 'package:mobile_scanner_example/barcode_scanner_returning_image.dart';
import 'package:mobile_scanner_example/barcode_scanner_window.dart';
import 'package:mobile_scanner_example/barcode_scanner_without_controller.dart';
... ... @@ -84,6 +85,16 @@ class MyHome extends StatelessWidget {
},
child: const Text('MobileScanner with zoom slider'),
),
ElevatedButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const BarcodeScannerPageView(),
),
);
},
child: const Text('MobileScanner pageView'),
),
],
),
),
... ...
... ... @@ -36,6 +36,10 @@ class ScannerErrorWidget extends StatelessWidget {
errorMessage,
style: const TextStyle(color: Colors.white),
),
Text(
error.errorDetails?.message ?? '',
style: const TextStyle(color: Colors.white),
),
],
),
),
... ...
platform :osx, '10.13'
platform :osx, '10.14'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
... ...
... ... @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objectVersion = 54;
objects = {
/* Begin PBXAggregateTarget section */
... ... @@ -277,6 +277,7 @@
};
3399D490228B24CF009A79C7 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
... ... @@ -403,7 +404,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
... ... @@ -425,7 +426,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MACOSX_DEPLOYMENT_TARGET = 10.14;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
... ... @@ -483,7 +484,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
... ... @@ -530,7 +531,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
... ... @@ -552,7 +553,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MACOSX_DEPLOYMENT_TARGET = 10.14;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
... ... @@ -573,7 +574,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.13;
MACOSX_DEPLOYMENT_TARGET = 10.14;
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
};
... ...
... ... @@ -56,6 +56,12 @@ class MobileScanner extends StatefulWidget {
/// [BoxFit]
final Rect? scanWindow;
/// Only set this to true if you are starting another instance of mobile_scanner
/// right after disposing the first one, like in a PageView.
///
/// Default: false
final bool startDelay;
/// Create a new [MobileScanner] using the provided [controller]
/// and [onBarcodeDetected] callback.
const MobileScanner({
... ... @@ -67,6 +73,7 @@ class MobileScanner extends StatefulWidget {
this.onScannerStarted,
this.placeholderBuilder,
this.scanWindow,
this.startDelay = false,
super.key,
});
... ... @@ -88,7 +95,7 @@ class _MobileScannerState extends State<MobileScanner>
MobileScannerException? _startException;
Widget __buildPlaceholderOrError(BuildContext context, Widget? child) {
Widget _buildPlaceholderOrError(BuildContext context, Widget? child) {
final error = _startException;
if (error != null) {
... ... @@ -104,18 +111,28 @@ class _MobileScannerState extends State<MobileScanner>
}
/// Start the given [scanner].
void _startScanner(MobileScannerController scanner) {
Future<void> _startScanner() async {
if (widget.startDelay) {
await Future.delayed(const Duration(seconds: 1, milliseconds: 500));
}
if (!_controller.autoStart) {
debugPrint(
'mobile_scanner: not starting automatically because autoStart is set to false in the controller.',
);
return;
}
scanner.start().then((arguments) {
_barcodesSubscription = _controller.barcodes.listen(
widget.onDetect,
);
_controller.start().then((arguments) {
// ignore: deprecated_member_use_from_same_package
widget.onStart?.call(arguments);
widget.onScannerStarted?.call(arguments);
}).catchError((error) {
debugPrint('mobile_scanner: $error');
if (mounted) {
setState(() {
_startException = error as MobileScannerException;
... ... @@ -129,14 +146,7 @@ class _MobileScannerState extends State<MobileScanner>
super.initState();
WidgetsBinding.instance.addObserver(this);
_controller = widget.controller ?? MobileScannerController();
_barcodesSubscription = _controller.barcodes.listen(
widget.onDetect,
);
if (!_controller.isStarting) {
_startScanner(_controller);
}
_startScanner();
}
@override
... ... @@ -149,7 +159,7 @@ class _MobileScannerState extends State<MobileScanner>
switch (state) {
case AppLifecycleState.resumed:
_resumeFromBackground = false;
_startScanner(_controller);
_startScanner();
break;
case AppLifecycleState.paused:
_resumeFromBackground = true;
... ... @@ -228,7 +238,7 @@ class _MobileScannerState extends State<MobileScanner>
valueListenable: _controller.startArguments,
builder: (context, value, child) {
if (value == null) {
return __buildPlaceholderOrError(context, child);
return _buildPlaceholderOrError(context, child);
}
if (widget.scanWindow != null && scanWindow == null) {
... ... @@ -238,7 +248,8 @@ class _MobileScannerState extends State<MobileScanner>
value.size,
Size(constraints.maxWidth, constraints.maxHeight),
);
_controller.updateScanWindow(scanWindow!);
_controller.updateScanWindow(scanWindow);
}
return ClipRect(
... ... @@ -268,8 +279,10 @@ class _MobileScannerState extends State<MobileScanner>
@override
void dispose() {
_controller.updateScanWindow(null);
WidgetsBinding.instance.removeObserver(this);
_barcodesSubscription?.cancel();
_barcodesSubscription = null;
_controller.dispose();
super.dispose();
}
... ...
... ... @@ -20,20 +20,7 @@ class MobileScannerController {
@Deprecated('Instead, use the result of calling `start()` to determine if permissions were granted.')
this.onPermissionSet,
this.autoStart = true,
}) {
// In case a new instance is created before calling dispose()
if (controllerHashcode != null) {
stop();
}
controllerHashcode = hashCode;
events = _eventChannel
.receiveBroadcastStream()
.listen((data) => _handleEvent(data as Map));
}
/// The hashcode of the controller to check if the correct object is mounted.
/// Must be static to keep the same value on new instances
static int? controllerHashcode;
});
/// Select which camera should be used.
///
... ... @@ -84,7 +71,7 @@ class MobileScannerController {
Function(bool permissionGranted)? onPermissionSet;
/// Listen to events from the platform specific code
late StreamSubscription events;
StreamSubscription? events;
/// A notifier that provides several arguments about the MobileScanner
final ValueNotifier<MobileScannerArguments?> startArguments =
... ... @@ -164,6 +151,11 @@ class MobileScannerController {
isStarting = true;
events?.cancel();
events = _eventChannel
.receiveBroadcastStream()
.listen((data) => _handleEvent(data as Map));
// Check authorization status
if (!kIsWeb) {
final MobileScannerState state = MobileScannerState
... ... @@ -327,11 +319,8 @@ class MobileScannerController {
/// If you call this, you cannot use this controller object anymore.
void dispose() {
stop();
events.cancel();
events?.cancel();
_barcodesController.close();
if (hashCode == controllerHashcode) {
controllerHashcode = null;
}
}
/// Handles a returning event from the platform side
... ... @@ -394,9 +383,13 @@ class MobileScannerController {
}
}
/// updates the native scanwindow
Future<void> updateScanWindow(Rect window) async {
final data = [window.left, window.top, window.right, window.bottom];
/// updates the native ScanWindow
Future<void> updateScanWindow(Rect? window) async {
List? data;
if (window != null) {
data = [window.left, window.top, window.right, window.bottom];
}
await _methodChannel.invokeMethod('updateScanWindow', {'rect': data});
}
}
... ...