Original barcode_scan was discontinued, so barcode_scan2 was borned with sound null safety support🎉
A flutter plugin for scanning 2D barcodes and QR codes.
This provides a simple wrapper for two commonly used iOS and Android libraries:
For Android, you must do the following before you can use the plugin:
Add the camera permission to your AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
This plugin is written in Kotlin. Therefore, you need to add Kotlin support to your project. See installing the Kotlin plugin.
Edit your project-level build.gradle file to look like this:
buildscript {
ext.kotlin_version = '1.3.61'
// ...
dependencies {
// ...
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
// ...
Edit your app-level build.gradle file to look like this:
apply plugin: 'kotlin-android'
// ...
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
// ...
}
Now you can depend on the barcode_scan plugin in your pubspec.yaml file:
dependencies:
# ...
barcode_scan2: any
Click "Packages get" in Android Studio or run flutter packages get
in your project folder.
To use on iOS, you must add the the camera usage description to your Info.plist
<dict>
<!-- ... -->
<key>NSCameraUsageDescription</key>
<string>Camera permission is required for barcode scanning.</string>
<!-- ... -->
</dict>
import 'package:barcode_scan2/barcode_scan2.dart';
void main() async {
var result = await BarcodeScanner.scan();
print(result.type); // The result type (barcode, cancelled, failed)
print(result.rawContent); // The barcode content
print(result.format); // The barcode format (as enum)
print(result.formatNote); // If a unknown format was scanned this field contains a note
}
You can pass options to the scan method:
import 'package:barcode_scan2/barcode_scan2.dart';
void main() async {
var options = ScanOptions(
// set the options
);
var result = await BarcodeScanner.scan(options: options);
// ...
}
Option | Type | Description | Supported by |
---|---|---|---|
strings.cancel | String | The cancel button text on iOS | iOS only |
strings.flash_on | String | The flash on button text | iOS + Android |
strings.flash_off | String | The flash off button text | iOS + Android |
restrictFormat | BarcodeFormat[] | Restrict the formats which are recognized | iOS + Android |
useCamera | int | The index of the camera which is used for scanning (See BarcodeScanner.numberOfCameras ) | iOS + Android |
autoEnableFlash | bool | Enable the flash when start scanning | iOS + Android |
android.aspectTolerance | double | Enable auto focus on Android | Android only |
android.useAutoFocus | bool | Set aspect ratio tolerance level used in calculating the optimal Camera preview size | Android only |
Mac:
$ brew install protobuf
$ brew install swift-protobuf
Windows / Linux: https://github.com/protocolbuffers/protobuf#protocol-compiler-installation
Activate the protobuf dart plugin:
$ flutter pub global activate protoc_plugin
Install theProtobuf Support
plugin for IDEA / Android Studio or vscode-proto3
for VS Code
If you changed the protos.proto you've to execute the ./generate_proto.sh to update the dart / swift sources
Change org.jetbrains.kotlin:kotlin-stdlib-jre
to org.jetbrains.kotlin:kotlin-stdlib-jdk
(StackOverflow)
Run this command:
With Flutter:
$ flutter pub add barcode_scan2
This will add a line like this to your package's pubspec.yaml (and run an implicit flutter pub get
):
dependencies:
barcode_scan2: ^4.3.0
Alternatively, your editor might support flutter pub get
. Check the docs for your editor to learn more.
Now in your Dart code, you can use:
import 'package:barcode_scan2/barcode_scan2.dart';
import 'dart:async';
import 'dart:io' show Platform;
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(const App());
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
ScanResult? scanResult;
final _flashOnController = TextEditingController(text: 'Flash on');
final _flashOffController = TextEditingController(text: 'Flash off');
final _cancelController = TextEditingController(text: 'Cancel');
var _aspectTolerance = 0.00;
var _numberOfCameras = 0;
var _selectedCamera = -1;
var _useAutoFocus = true;
var _autoEnableFlash = false;
static final _possibleFormats = BarcodeFormat.values.toList()
..removeWhere((e) => e == BarcodeFormat.unknown);
List<BarcodeFormat> selectedFormats = [..._possibleFormats];
@override
void initState() {
super.initState();
Future.delayed(Duration.zero, () async {
_numberOfCameras = await BarcodeScanner.numberOfCameras;
setState(() {});
});
}
@override
Widget build(BuildContext context) {
final scanResult = this.scanResult;
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Barcode Scanner Example'),
actions: [
IconButton(
icon: const Icon(Icons.camera),
tooltip: 'Scan',
onPressed: _scan,
),
],
),
body: ListView(
shrinkWrap: true,
children: <Widget>[
if (scanResult != null)
Card(
child: Column(
children: <Widget>[
ListTile(
title: const Text('Result Type'),
subtitle: Text(scanResult.type.toString()),
),
ListTile(
title: const Text('Raw Content'),
subtitle: Text(scanResult.rawContent),
),
ListTile(
title: const Text('Format'),
subtitle: Text(scanResult.format.toString()),
),
ListTile(
title: const Text('Format note'),
subtitle: Text(scanResult.formatNote),
),
],
),
),
const ListTile(
title: Text('Camera selection'),
dense: true,
enabled: false,
),
RadioListTile(
onChanged: (v) => setState(() => _selectedCamera = -1),
value: -1,
title: const Text('Default camera'),
groupValue: _selectedCamera,
),
...List.generate(
_numberOfCameras,
(i) => RadioListTile(
onChanged: (v) => setState(() => _selectedCamera = i),
value: i,
title: Text('Camera ${i + 1}'),
groupValue: _selectedCamera,
),
),
const ListTile(
title: Text('Button Texts'),
dense: true,
enabled: false,
),
ListTile(
title: TextField(
decoration: const InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
labelText: 'Flash On',
),
controller: _flashOnController,
),
),
ListTile(
title: TextField(
decoration: const InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
labelText: 'Flash Off',
),
controller: _flashOffController,
),
),
ListTile(
title: TextField(
decoration: const InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
labelText: 'Cancel',
),
controller: _cancelController,
),
),
if (Platform.isAndroid) ...[
const ListTile(
title: Text('Android specific options'),
dense: true,
enabled: false,
),
ListTile(
title: Text(
'Aspect tolerance (${_aspectTolerance.toStringAsFixed(2)})',
),
subtitle: Slider(
min: -1,
value: _aspectTolerance,
onChanged: (value) {
setState(() {
_aspectTolerance = value;
});
},
),
),
CheckboxListTile(
title: const Text('Use autofocus'),
value: _useAutoFocus,
onChanged: (checked) {
setState(() {
_useAutoFocus = checked!;
});
},
),
],
const ListTile(
title: Text('Other options'),
dense: true,
enabled: false,
),
CheckboxListTile(
title: const Text('Start with flash'),
value: _autoEnableFlash,
onChanged: (checked) {
setState(() {
_autoEnableFlash = checked!;
});
},
),
const ListTile(
title: Text('Barcode formats'),
dense: true,
enabled: false,
),
ListTile(
trailing: Checkbox(
tristate: true,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
value: selectedFormats.length == _possibleFormats.length
? true
: selectedFormats.isEmpty
? false
: null,
onChanged: (checked) {
setState(() {
selectedFormats = [
if (checked ?? false) ..._possibleFormats,
];
});
},
),
dense: true,
enabled: false,
title: const Text('Detect barcode formats'),
subtitle: const Text(
'If all are unselected, all possible '
'platform formats will be used',
),
),
..._possibleFormats.map(
(format) => CheckboxListTile(
value: selectedFormats.contains(format),
onChanged: (i) {
setState(
() => selectedFormats.contains(format)
? selectedFormats.remove(format)
: selectedFormats.add(format),
);
},
title: Text(format.toString()),
),
),
],
),
),
);
}
Future<void> _scan() async {
try {
final result = await BarcodeScanner.scan(
options: ScanOptions(
strings: {
'cancel': _cancelController.text,
'flash_on': _flashOnController.text,
'flash_off': _flashOffController.text,
},
restrictFormat: selectedFormats,
useCamera: _selectedCamera,
autoEnableFlash: _autoEnableFlash,
android: AndroidOptions(
aspectTolerance: _aspectTolerance,
useAutoFocus: _useAutoFocus,
),
),
);
setState(() => scanResult = result);
} on PlatformException catch (e) {
setState(() {
scanResult = ScanResult(
rawContent: e.code == BarcodeScanner.cameraAccessDenied
? 'The user did not grant the camera permission!'
: 'Unknown error: $e',
);
});
}
}
}
Download details:
Author: mono0926.com
Source: https://github.com/mono0926/barcode_scan2