flutter中 对含有二维码图片进行扫描

1 阅读3分钟

最近开发中遇到了一个需求,就是实现一个类似于微信中 打开图片(预览), 针对有二维码的图片,展示识别图中二维码的选项, 对于没有二维码的图片,不展示.

一开始接到这样的需求,我 直接去pub.dev/ 市场里面搜 有关二维码扫描的 库, 但大多库都是 打开相机然后调取摄像头 进行扫描的, 不太满足我的场景. 我希望能够 直接从 图片的在线链接 或者 图片文件信息 读取图中的二维码.

一开始我找到了qrcode , github.com/wu9007/qrco…, 这个库支持从相册选择图片, 或者从图片的路径 进行读取二维码数据. 这是官方下的使用

import 'package:qrscan/qrscan.dart' as scanner;

// Select Bar-Code or QR-Code photos for analysis
String photoScanResult = await scanner.scanPhoto();

// Generating QR-Code
Uint8List result = await scanner.generateBarCode('https://github.com/leyan95/qrcode_scanner');

// Scanning the image of the specified path
String barcode = await scanner.scanPath(path);

// Parse to code string with uint8list
File file = await ImagePicker.pickImage(source: ImageSource.camera);
Uint8List bytes = file.readAsBytesSync();
String barcode = await scanner.scanBytes(uint8list);

但是无奈的是,这个库发布较早, 包规范不符合目前的标准,导致无法安装下来, 索性就放弃了.

再后来找到了mobile_scanner , 我把该库的例子下载到本地, 试跑了一下, 功能很强大, 也包含上方我的需求, 提供路径,然后获取该文件中的二维码. 但是奈何 体积较大, 老板不让用. 无奈之下,我只好继续找了.

再后来,我在pub get 市场找到了这个小众. 该库的特征正好迎合了我的需求.

  • ✅ 从相机扫描(支持 Android、IOS、Web
  • ✅ 从图像文件扫描

体积小, 且使用简单.

从相机扫描

ScanView(
    onResult: (List<Result> results),
),

从图像文件扫描

List<Result> results = await scanImage(await file.readAsBytes());

image.png

// 扫描网络图片中的二维码
Future<void> scanQRCodeFromUrl(String imageUrl) async {
  final Uint8List bytes = await getCachedImageBytes(imageUrl);
  final List<Result>? results = await scanImage(bytes,maxSize: 800);
  if (results != null && results.isNotEmpty) {
    _scannedData = results.first.text;
    if (_scannedData!.isNotEmpty) {
      NavigatorUtil.openUrl(_scannedData!);
      Navigator.pop(context);
    } else {
      setState(() {
        _scannedData = '扫描到的文本不是有效的 URL: $_scannedData';
      });
    }
  }else{
    ToastUtils.showToast("无内容");
  }
}

解析:

  1. 传入图片 url
  2. 根据url 获取缓存中的图片的 字节
  3. 通过scanImage方法 根据图片的字节 获取图片的中二维码
  4. 有数据(读取二维码的内容), 进行跳转
  5. 无数据进行提示

下面我再说一下吧, 因为我们的app的图片都是缓存本地的. 然后如何根据图片的url 获取对应缓存的本地地址吧.

cached_network_image 提供了根据图片url 获取图片文件的.

var file = await CachedNetworkImageProvider.defaultCacheManager.getSingleFile(imageUrl);

对于getSingleFile 方法的介绍

abstract class BaseCacheManager {
  /// Get the file from the cache and/or online, depending on availability and age.
  /// Downloaded form [url], [headers] can be used for example for authentication.
  /// When a file is cached it is return directly, when it is too old the file is
  /// downloaded in the background. When a cached file is not available the
  /// newly downloaded file is returned.

  /// 从缓存和/或在线获取文件,具体取决于可用性和期限。
  /// 下载的表单 [url]、[headers] 可用于身份验证等。
  /// 当文件被缓存时直接返回,当文件太旧时则返回
  /// 在后台下载。当缓存文件不可用时
  /// 返回新下载的文件。

  
  Future<File> getSingleFile(
    String url, {
    String key,
    Map<String, String> headers,
  });
  ...
}

我们拿到该文件之后, 直接使用readAsBytes获取文件的字节码即可.