Flutter移动扫描插件mobile_scanner的使用

发布于 1周前 作者 itying888 来自 Flutter

Flutter移动扫描插件mobile_scanner的使用

插件简介

mobile_scanner 是一个基于MLKit的通用Flutter扫描插件。它在Android上使用CameraX,在iOS上使用AVFoundation。该插件支持多种平台,包括Android、iOS、macOS和Web,并且具有丰富的特性。

pub package style: lint mobile_scanner GitHub Sponsors

版本变更(v5.0.0)

版本5.0.0引入了一些破坏性变更,但在5.1.0中部分被恢复。主要变更如下:

  • autoStart 属性已从 MobileScannerController 中移除,但已在5.1.0中恢复。
  • onDetect 方法已从 MobileScanner widget中移除,但已在5.1.0中恢复。
  • 其他一些属性和方法的名称和行为有所调整,具体请参阅Changelog.md

功能支持

Features Android iOS macOS Web
analyzeImage (Gallery) ✔️ ✔️ ✔️
returnImage ✔️ ✔️ ✔️
scanWindow ✔️ ✔️ ✔️

平台支持

Platform Support
Android
iOS
macOS
Web
Linux
Windows

平台特定设置

Android

默认情况下,插件使用捆绑版本的MLKit Barcode-scanning。若要使用非捆绑版本,请在 /android/gradle.properties 文件中添加以下行:

dev.steenbakker.mobile_scanner.useUnbundled=true

iOS

确保在Info.plist文件中添加以下键:

<key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan QR codes</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photos access to get QR code from photo library</string>

macOS

确保在XCode中授予相机权限。

Web

无需手动添加脚本,插件会自动加载。

使用示例

完整示例代码

main.dart

import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';

void main() {
  runApp(
    const MaterialApp(
      title: 'Mobile Scanner Example',
      home: MyHome(),
    ),
  );
}

class MyHome extends StatelessWidget {
  const MyHome({super.key});

  Widget _buildItem(BuildContext context, String label, Widget page) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.of(context).push(
              MaterialPageRoute(
                builder: (context) => page,
              ),
            );
          },
          child: Text(label),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Mobile Scanner Example')),
      body: Center(
        child: ListView(
          children: [
            _buildItem(
              context,
              'MobileScanner Simple',
              const BarcodeScannerSimple(),
            ),
            // Add more items as needed
          ],
        ),
      ),
    );
  }
}

class BarcodeScannerSimple extends StatefulWidget {
  const BarcodeScannerSimple({super.key});

  @override
  State<BarcodeScannerSimple> createState() => _BarcodeScannerSimpleState();
}

class _BarcodeScannerSimpleState extends State<BarcodeScannerSimple> with WidgetsBindingObserver {
  final MobileScannerController controller = MobileScannerController();
  StreamSubscription<Object?>? _subscription;

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    if (!controller.value.hasCameraPermission) {
      return;
    }

    switch (state) {
      case AppLifecycleState.resumed:
        _subscription = controller.barcodes.listen(_handleBarcode);
        unawaited(controller.start());
        break;
      case AppLifecycleState.paused:
      case AppLifecycleState.inactive:
      case AppLifecycleState.detached:
        unawaited(_subscription?.cancel());
        _subscription = null;
        unawaited(controller.stop());
        break;
    }
  }

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _subscription = controller.barcodes.listen(_handleBarcode);
    unawaited(controller.start());
  }

  @override
  Future<void> dispose() async {
    WidgetsBinding.instance.removeObserver(this);
    unawaited(_subscription?.cancel());
    _subscription = null;
    await controller.dispose();
    super.dispose();
  }

  void _handleBarcode(Object? barcode) {
    if (barcode != null) {
      // Handle the scanned barcode here
      print('Scanned barcode: $barcode');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Simple Barcode Scanner')),
      body: MobileScanner(
        controller: controller,
        onDetect: (barcode) {
          _handleBarcode(barcode);
        },
      ),
    );
  }
}

此示例展示了如何使用 mobile_scanner 插件创建一个简单的二维码扫描器。您可以根据需要扩展此示例,例如添加扫描窗口、缩放功能等。更多详细用法可以参考 官方示例


更多关于Flutter移动扫描插件mobile_scanner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter移动扫描插件mobile_scanner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter应用中使用mobile_scanner插件来进行移动扫描的示例代码。这个插件允许你通过设备的摄像头扫描二维码或条形码。

首先,确保你已经在pubspec.yaml文件中添加了mobile_scanner依赖:

dependencies:
  flutter:
    sdk: flutter
  mobile_scanner: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来安装依赖。

接下来,你可以按照以下步骤在你的Flutter应用中使用mobile_scanner插件:

  1. 导入必要的包
import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
  1. 创建一个扫描页面
class ScanPage extends StatefulWidget {
  @override
  _ScanPageState createState() => _ScanPageState();
}

class _ScanPageState extends State<ScanPage> {
  final MobileScannerController scannerController = MobileScannerController();
  String result = "";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Scan QR/Barcode"),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Expanded(
            child: MobileScanner(
              controller: scannerController,
              onCapture: (result) {
                // 扫描成功后的回调
                setState(() {
                  this.result = result;
                });
                scannerController.stopScanning(); // 停止扫描
                Navigator.pop(context, result); // 返回到之前的页面并传递结果
              },
              onError: (e) {
                print("Error: $e");
              },
            ),
          ),
          Text(
            "Scan Result: $result",
            style: TextStyle(fontSize: 20),
          ),
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          bool hasPermission = await scannerController.checkPermission();
          if (hasPermission) {
            await scannerController.startScanning();
          } else {
            // 请求权限
            bool requestPermission = await scannerController.requestPermission();
            if (requestPermission) {
              await scannerController.startScanning();
            } else {
              // 权限被拒绝
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text("Permission Denied")),
              );
            }
          }
        },
        tooltip: 'Start Scanning',
        child: Icon(Icons.camera_alt),
      ),
    );
  }
}
  1. 在你的应用中使用这个页面
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ScanPage(),
    );
  }
}

这个示例代码展示了如何在一个Flutter应用中集成并使用mobile_scanner插件。当你运行这个应用时,它会显示一个扫描界面,你可以通过点击浮动操作按钮(FAB)来开始扫描。扫描成功后,结果会显示在屏幕上,并且可以通过Navigator.pop方法将结果传递回之前的页面。

注意:确保在真机或模拟器上运行此代码,因为摄像头访问需要设备支持。

回到顶部