Sander Roest
Committed by GitHub

Merge branch 'juliansteenbakker:master' into master

## NEXT
## 6.0.2
Bugs fixed:
* Fixed a bug that prevented `analyzeImage` from actually accepting the configured formats.
Improvements:
* [iOS] Excluded the `arm64` architecture for Simulators, which is unsupported by MLKit 7.0.0.
## 6.0.1
Bugs fixed:
* Fixed a bug that would cause onDetect to not handle errors.
Improvements:
* [iOS] Excluded the `armv7` architecture, which is unsupported by MLKit 7.0.0.
* Added a new `onDetectError` error handler to the `MobileScanner` widget, for use with `onDetect`.
## 6.0.0
**BREAKING CHANGES:**
* [iOS] iOS 15.5.0 is now the minimum supported iOS version.
* [iOS] Updates MLKit to version 7.0.0.
* [iOS] Updates the minimum supported XCode version to 15.3.0.
Improvements:
* [MacOS] Added the corners and size information to barcode results.
... ...
... ... @@ -60,6 +60,10 @@ dev.steenbakker.mobile_scanner.useUnbundled=true
```
### iOS
_iOS arm64 Simulators are currently not yet supported, until the migration to the Vision API is complete._
_See_ https://github.com/juliansteenbakker/mobile_scanner/issues/1225
**Add the following keys to your Info.plist file, located in <project root>/ios/Runner/Info.plist:**
NSCameraUsageDescription - describe why your app needs access to the camera. This is called Privacy - Camera Usage Description in the visual editor.
... ...
... ... @@ -27,12 +27,12 @@ android {
compileSdk 34
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = '1.8'
jvmTarget = '17'
}
sourceSets {
... ... @@ -42,7 +42,7 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "dev.steenbakker.mobile_scanner_example"
minSdkVersion 21
minSdkVersion 24
targetSdkVersion 34
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
... ...
#Thu May 02 10:24:49 CEST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
... ...
... ... @@ -18,8 +18,8 @@ pluginManagement {
plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
id "org.jetbrains.kotlin.android" version "1.7.22" apply false
id "com.android.application" version "8.3.2" apply false
id "org.jetbrains.kotlin.android" version "2.0.20" apply false
}
include ":app"
\ No newline at end of file
... ...
... ... @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
<string>15.5.0</string>
</dict>
</plist>
... ...
# Uncomment this line to define a global platform for your project
# platform :ios, '12.0'
# platform :ios, '15.5.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
... ... @@ -40,8 +40,8 @@ end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
end
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.5.0'
end
end
end
... ...
... ... @@ -470,7 +470,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.5.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
... ... @@ -601,7 +601,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.5.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
... ... @@ -650,7 +650,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
IPHONEOS_DEPLOYMENT_TARGET = 15.5.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
... ...
... ... @@ -131,15 +131,15 @@ class ScannerOverlay extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// TODO: use `Offset.zero & size` instead of Rect.largest
// we need to pass the size to the custom paint widget
final backgroundPath = Path()..addRect(Rect.largest);
final backgroundPath = Path()
..addRect(Rect.fromLTWH(0, 0, size.width, size.height));
final cutoutPath = Path()..addRect(scanWindow);
final backgroundPaint = Paint()
..color = Colors.black.withOpacity(0.5)
..style = PaintingStyle.fill
..blendMode = BlendMode.dstOut;
..blendMode = BlendMode.dstOver;
final backgroundWithCutout = Path.combine(
PathOperation.difference,
... ...
... ... @@ -102,9 +102,9 @@ class ScannerOverlay extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// TODO: use `Offset.zero & size` instead of Rect.largest
// we need to pass the size to the custom paint widget
final backgroundPath = Path()..addRect(Rect.largest);
final backgroundPath = Path()
..addRect(Rect.fromLTWH(0, 0, size.width, size.height));
final cutoutPath = Path()
..addRRect(
... ... @@ -120,7 +120,7 @@ class ScannerOverlay extends CustomPainter {
final backgroundPaint = Paint()
..color = Colors.black.withOpacity(0.5)
..style = PaintingStyle.fill
..blendMode = BlendMode.dstOut;
..blendMode = BlendMode.dstOver;
final backgroundWithCutout = Path.combine(
PathOperation.difference,
... ...
... ... @@ -4,7 +4,7 @@
#
Pod::Spec.new do |s|
s.name = 'mobile_scanner'
s.version = '5.2.3'
s.version = '6.0.2'
s.summary = 'An universal scanner for Flutter based on MLKit.'
s.description = <<-DESC
An universal scanner for Flutter based on MLKit.
... ... @@ -15,11 +15,16 @@ An universal scanner for Flutter based on MLKit.
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.dependency 'GoogleMLKit/BarcodeScanning', '~> 6.0.0'
s.platform = :ios, '12.0'
s.dependency 'GoogleMLKit/BarcodeScanning', '~> 7.0.0'
s.platform = :ios, '15.5.0'
s.static_framework = true
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
# Flutter.framework does not contain a i386 slice, and MLKit does not support armv7.
s.pod_target_xcconfig = {
'DEFINES_MODULE' => 'YES',
# TODO: add back arm64 (and armv7?) when switching to the Vision API.
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386 armv7 arm64',
'EXCLUDED_ARCHS[sdk=iphoneos*]' => 'armv7',
}
s.swift_version = '5.0'
s.resource_bundles = { 'mobile_scanner_privacy' => ['Resources/PrivacyInfo.xcprivacy'] }
end
... ...
... ... @@ -21,6 +21,7 @@ class MobileScanner extends StatefulWidget {
const MobileScanner({
this.controller,
this.onDetect,
this.onDetectError = _onDetectErrorHandler,
this.fit = BoxFit.cover,
this.errorBuilder,
this.overlayBuilder,
... ... @@ -34,15 +35,17 @@ class MobileScanner extends StatefulWidget {
final MobileScannerController? controller;
/// The function that signals when new codes were detected by the [controller].
/// If null, use the controller.barcodes stream directly to capture barcodes.
///
/// This method does not receive any [MobileScannerBarcodeException]s
/// that are emitted by the scanner.
///
/// To handle both [BarcodeCapture]s and [MobileScannerBarcodeException]s,
/// use the [MobileScannerController.barcodes] stream directly.
/// use the [MobileScannerController.barcodes] stream directly (recommended),
/// or provide a function to [onDetectError].
final void Function(BarcodeCapture barcodes)? onDetect;
/// The error handler equivalent for the [onDetect] function.
///
/// If [onDetect] is not null, and this is null, errors are silently ignored.
final void Function(Object error, StackTrace stackTrace) onDetectError;
/// The error builder for the camera preview.
///
/// If this is null, a black [ColoredBox],
... ... @@ -122,6 +125,11 @@ class MobileScanner extends StatefulWidget {
@override
State<MobileScanner> createState() => _MobileScannerState();
/// This empty function is used as the default error handler for [onDetect].
static void _onDetectErrorHandler(Object error, StackTrace stackTrace) {
// Do nothing.
}
}
class _MobileScannerState extends State<MobileScanner>
... ... @@ -255,7 +263,11 @@ class _MobileScannerState extends State<MobileScanner>
void initState() {
if (widget.onDetect != null) {
WidgetsBinding.instance.addObserver(this);
_subscription = controller.barcodes.listen(widget.onDetect);
_subscription = controller.barcodes.listen(
widget.onDetect,
onError: widget.onDetectError,
cancelOnError: false,
);
}
if (controller.autoStart) {
controller.start();
... ... @@ -297,7 +309,11 @@ class _MobileScannerState extends State<MobileScanner>
case AppLifecycleState.paused:
return;
case AppLifecycleState.resumed:
_subscription = controller.barcodes.listen(widget.onDetect);
_subscription = controller.barcodes.listen(
widget.onDetect,
onError: widget.onDetectError,
cancelOnError: false,
);
unawaited(controller.start());
case AppLifecycleState.inactive:
... ...
... ... @@ -186,6 +186,8 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
/// Analyze an image file.
///
/// The [path] points to a file on the device.
/// The [formats] specify the barcode formats that should be detected in the image.
/// If the [formats] are omitted or empty, all formats are detected.
///
/// This is only supported on Android, iOS and MacOS.
///
... ... @@ -193,8 +195,11 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> {
///
/// If an error occurred during the analysis of the image,
/// a [MobileScannerBarcodeException] error is thrown.
Future<BarcodeCapture?> analyzeImage(String path) {
return MobileScannerPlatform.instance.analyzeImage(path);
Future<BarcodeCapture?> analyzeImage(
String path, {
List<BarcodeFormat> formats = const <BarcodeFormat>[],
}) {
return MobileScannerPlatform.instance.analyzeImage(path, formats: formats);
}
/// Build a camera preview widget.
... ...
... ... @@ -4,7 +4,7 @@
#
Pod::Spec.new do |s|
s.name = 'mobile_scanner'
s.version = '5.2.3'
s.version = '6.0.2'
s.summary = 'An universal scanner for Flutter based on MLKit.'
s.description = <<-DESC
An universal scanner for Flutter based on MLKit.
... ...
name: mobile_scanner
description: A universal barcode and QR code scanner for Flutter based on MLKit. Uses CameraX on Android, AVFoundation on iOS and Apple Vision & AVFoundation on macOS.
version: 5.2.3
version: 6.0.2
repository: https://github.com/juliansteenbakker/mobile_scanner
screenshots:
... ...