Flutter二维码扫描插件r_scan的使用
Flutter二维码扫描插件r_scan的使用
r_scan

A flutter plugin about qr code or bar code scan, it can scan from file、url、memory and camera qr code or bar code. Welcome to feedback your issue.
Getting Started
Depend on it
Add this to your package’s pubspec.yaml
file:
dependencies:
r_scan: last version
Android Platform
Require <code>read storage permission</code>
and <code>camera permission</code>
, use <code>permission_handler</code>
plugin.
import 'package:permission_handler/permission_handler.dart';
Future<bool> canReadStorage() async {
if (Platform.isIOS) return true;
var status = await PermissionHandler()
.checkPermissionStatus(PermissionGroup.storage);
if (status != PermissionStatus.granted) {
var future = await PermissionHandler()
.requestPermissions([PermissionGroup.storage]);
for (final item in future.entries) {
if (item.value != PermissionStatus.granted) {
return false;
}
}
} else {
return true;
}
return true;
}
Future<bool> canOpenCamera() async {
var status =
await PermissionHandler().checkPermissionStatus(PermissionGroup.camera);
if (status != PermissionStatus.granted) {
var future = await PermissionHandler()
.requestPermissions([PermissionGroup.camera]);
for (final item in future.entries) {
if (item.value != PermissionStatus.granted) {
return false;
}
}
} else {
return true;
}
return true;
}
IOS Platform
Add the permissions in your Info.plist
.
<key>NSCameraUsageDescription</key>
<string>扫描二维码时需要使用您的相机</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>扫描二维码时需要访问您的相册</string>
<key>io.flutter.embedded_views_preview</key>
<true/>
No another.
Usage
1. scan Image File
final result = await RScan.scanImagePath('your file path');
2. scan Image url
final result = await RScan.scanImagePath('your image url');
3. scan Image memory
ByteData data = await rootBundle.load('images/qrCode.png');
final result = await RScan.scanImageMemory(data.buffer.asUint8List());
4. scan camera (new! please upgrade this plugin to v0.14)
Step First: Get available cameras
List<RScanCameraDescription> rScanCameras = await availableRScanCameras();
If you want to get it in main()
method, you can use this code.
List<RScanCameraDescription> rScanCameras;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
rScanCameras = await availableRScanCameras();
runApp(...);
}
Step Second: Use it.
class RScanCameraDialog extends StatefulWidget {
[@override](/user/override)
_RScanCameraDialogState createState() => _RScanCameraDialogState();
}
class _RScanCameraDialogState extends State<RScanCameraDialog> {
RScanCameraController _controller;
bool isFirst = true;
[@override](/user/override)
void initState() {
super.initState();
if (rScanCameras != null && rScanCameras.length > 0) {
_controller = RScanCameraController(
rScanCameras[1], RScanCameraResolutionPreset.max)
..addListener(() {
final result = _controller.result;
if (result != null) {
if (isFirst) {
Navigator.of(context).pop(result);
isFirst = false;
}
}
})
..initialize().then((_) {
if (!mounted) {
return;
}
setState(() {});
});
}
}
[@override](/user/override)
void dispose() {
_controller?.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
if (rScanCameras == null || rScanCameras.length == 0) {
return Scaffold(
body: Container(
alignment: Alignment.center,
child: Text('not have available camera'),
),
);
}
if (!_controller.value.isInitialized) {
return Container();
}
return Scaffold(
backgroundColor: Colors.black,
body: Stack(
children: <Widget>[
ScanImageView(
child: AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: RScanCamera(_controller),
),
),
Align(
alignment: Alignment.bottomCenter,
child: FutureBuilder(
future: getFlashMode(),
builder: _buildFlashBtn,
))
],
),
);
}
Future<bool> getFlashMode() async {
bool isOpen = false;
try {
isOpen = await _controller.getFlashMode();
} catch (_) {}
return isOpen;
}
Widget _buildFlashBtn(BuildContext context, AsyncSnapshot<bool> snapshot) {
return snapshot.hasData
? Padding(
padding: EdgeInsets.only(bottom: 24 + MediaQuery.of(context).padding.bottom),
child: IconButton(
icon: Icon(snapshot.data ? Icons.flash_on : Icons.flash_off),
color: Colors.white,
iconSize: 46,
onPressed: () {
if (snapshot.data) {
_controller.setFlashMode(false);
} else {
_controller.setFlashMode(true);
}
setState(() {});
}),
)
: Container();
}
}
5. scan view (Deprecated)
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:r_scan/r_scan.dart';
class RScanDialog extends StatefulWidget {
[@override](/user/override)
_RScanDialogState createState() => _RScanDialogState();
}
class _RScanDialogState extends State<RScanDialog> {
RScanController _controller;
[@override](/user/override)
void initState() {
super.initState();
initController();
}
bool isFirst = true;
Future<void> initController() async {
_controller = RScanController();
_controller.addListener(() {
final result = _controller.result;
if (result != null) {
if (isFirst) {
Navigator.of(context).pop(result);
isFirst = false;
}
}
});
}
[@override](/user/override)
void dispose() {
_controller.dispose();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.black,
body: FutureBuilder<bool>(
future: canOpenCameraView(),
builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
if (snapshot.hasData && snapshot.data == true) {
return ScanImageView(
child: RScanView(
controller: _controller,
),
);
} else {
return Container();
}
},
),
),
);
}
Future<bool> canOpenCameraView() async {
var status =
await PermissionHandler().checkPermissionStatus(PermissionGroup.camera);
if (status != PermissionStatus.granted) {
var future = await PermissionHandler()
.requestPermissions([PermissionGroup.camera]);
for (final item in future.entries) {
if (item.value != PermissionStatus.granted) {
return false;
}
}
} else {
return true;
}
return true;
}
}
6. open flash lamp / get flash lamp status.
You can use <code>RScanController</code>
class.
// turn off the flash lamp.
await _controller.setFlashMode(false);
// turn on the flash lamp.
await _controller.setFlashMode(true);
// get the flash lamp status.
bool isOpen = await _controller.getFlashMode();
7. RScanResult
When you scan finish, will return the RScanResult
.
class RScanResult {
/// barcode type
final RScanBarType type;
/// barcode message
final String message;
/// barcode points include [x, y]
final List<RScanPoint> points;
}
Complete Example Demo
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:r_scan_example/scan_dialog.dart';
import 'scan_camera_dialog.dart';
import 'package:r_scan/r_scan.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: MyPage(),
);
}
}
class MyPage extends StatefulWidget {
[@override](/user/override)
_MyPageState createState() => _MyPageState();
}
class _MyPageState extends State<MyPage> {
RScanResult result;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('scan example'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Center(
child: Text(result == null
? '点击下方按钮开始扫码'
: '扫码结果${result.toString().split(',').join('\n')}')),
Center(
child: FlatButton(
onPressed: () async {
final result = await Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => RScanCameraDialog()));
setState(() {
this.result = result;
});
},
child: Text('RScanCamera开始扫码'),
),
),
Center(
child: FlatButton(
onPressed: () async {
final result = await Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => RScanDialog()));
setState(() {
this.result = result;
});
},
child: Text('RScanView开始扫码(已弃用)'),
),
),
Center(
child: FlatButton(
onPressed: () async {
if (await canReadStorage()) {
var image =
await ImagePicker.pickImage(source: ImageSource.gallery);
if (image != null) {
final result = await RScan.scanImagePath(image.path);
setState(() {
this.result = result;
});
}
}
},
child: Text('选择图片扫描'),
),
),
Center(
child: FlatButton(
onPressed: () async {
final result = await RScan.scanImageUrl(
"https://s.cn.bing.net/th?id=OJ.5F0gxqWmxskS0Q&w=75&h=75&pid=MSNJVFeeds");
setState(() {
this.result = result;
});
},
child: Text('网络图片解析'),
),
),
Center(
child: FlatButton(
onPressed: () async {
ByteData data = await rootBundle.load('images/qrCode.png');
final result =
await RScan.scanImageMemory(data.buffer.asUint8List());
setState(() {
this.result = result;
});
},
child: Text('内存图片解析'),
),
),
],
),
);
}
Future<bool> canReadStorage() async {
if (Platform.isIOS) return true;
var status = await PermissionHandler()
.checkPermissionStatus(PermissionGroup.storage);
if (status != PermissionStatus.granted) {
var future = await PermissionHandler()
.requestPermissions([PermissionGroup.storage]);
for (final item in future.entries) {
if (item.value != PermissionStatus.granted) {
return false;
}
}
} else {
return true;
}
return true;
}
}
更多关于Flutter二维码扫描插件r_scan的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
r_scan
是一个用于 Flutter 的二维码扫描插件,它基于 ML Kit
和 ZXing
实现,支持在 Android 和 iOS 平台上进行二维码和条形码的扫描。以下是使用 r_scan
插件的基本步骤:
1. 添加依赖
首先,在 pubspec.yaml
文件中添加 r_scan
插件的依赖:
dependencies:
flutter:
sdk: flutter
r_scan: ^0.1.0 # 请使用最新版本
然后运行 flutter pub get
来安装依赖。
2. 配置权限
在 Android 和 iOS 上,你需要配置相应的权限以允许应用访问摄像头。
Android
在 android/app/src/main/AndroidManifest.xml
文件中添加以下权限:
<uses-permission android:name="android.permission.CAMERA" />
iOS
在 ios/Runner/Info.plist
文件中添加以下权限:
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to scan QR codes.</string>
3. 使用 r_scan
插件
在你的 Flutter 应用中,你可以使用 RScan
类来进行二维码扫描。
示例代码
import 'package:flutter/material.dart';
import 'package:r_scan/r_scan.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'QR Code Scanner',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: QRScannerScreen(),
);
}
}
class QRScannerScreen extends StatefulWidget {
[@override](/user/override)
_QRScannerScreenState createState() => _QRScannerScreenState();
}
class _QRScannerScreenState extends State<QRScannerScreen> {
RScanResult? _scanResult;
Future<void> _scanQRCode() async {
try {
final result = await RScan.scan();
setState(() {
_scanResult = result;
});
} catch (e) {
print('Error: $e');
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('QR Code Scanner'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (_scanResult != null)
Text('Scanned Data: ${_scanResult!.message}'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _scanQRCode,
child: Text('Scan QR Code'),
),
],
),
),
);
}
}