有没有办法在Flutter中扫描条形码?

时间:2018-03-27 19:48:41

标签: dart qr-code barcode-scanner flutter android-vision

基本上,我正在创建一个扫描QR码以连接服务器的应用。然后,应用程序将扫描产品的条形码并拍摄该项目的照片并将其发送到服务器。我的问题如下:

是否有Flutter插件可以扫描与image_picker冲突的QR码和条形码?

这是我到目前为止所发现的。

感谢您提供的任何帮助。谢谢!

5 个答案:

答案 0 :(得分:11)

我以前遇到过类似的问题,经过搜索,我找不到很多东西。我决定最好的方法是自己写一个插件......所以我的插件无耻插件= D,而不是我从其他任何人都可以使用它。

你可以看到它here。但是,我没有时间记录它,广泛测试它,或者在Pub上正确发布它。所以你的里程可能不一样。然而它应该适用于android 4.4+(可能在下面),以及支持它的iOS设备。我还没有与Camera插件一起测试它,但我不明白它为什么会出现问题。

它采用与大多数其他qr代码插件不同的方法;而不是制作一个Android或iOS窗口,进行扫描,然后返回颤动,它使用颤振的纹理渲染功能让摄像机直接渲染。

还需要考虑的一点是,它使用谷歌移动视觉SDK以及随之而来的适用许可和功能(并且需要Android上最新版本的Play服务);而且它目前只支持条形码扫描中最基本的信息提取 - 我只需要原始文本,这就是我所做的一切。

要使用它,请将其添加到pubspec.yaml:

dependencies:
  qr_mobile_vision: '^0.0.7'

实施如下:

import 'package:qr_mobile_vision/QrCamera.dart';

...

new Container(
  constraints: new BoxConstraints.loose(
  new Size(cameraSize, cameraSize)),
  child: new QrCamera(
    qrCodeCallback: (code) {
      print(code);
    }
  ),
)

我计划最终完成文档/测试/等,但欢迎您在此期间尝试。如果你决定使用它并且需要一个它不支持的功能,我可以能够帮助实现它......但欢迎并鼓励PR!

更新:现在包含条形码支持。在实例化QrCamera时,您可以传入要支持的QR码/条形码类型。它默认为all,这需要更多的处理,所以如果您在某种类型之后,建议您将其传入。

答案 1 :(得分:2)

根据我的研究,有很好的选择:

  1. flutter_barcode_scanner(阅读器)
  2. barcode_scan(阅读器)
  3. qr_flutter(用于创建QR码)

第一:barcode_scan将用作两个常用的iOS和Android库的包装。 (iOS:https://github.com/mikebuss/MTBBarcodeScanner,Android:https://github.com/dm77/barcodescanner

它们已经在版本3中,并且似乎所有主要错误都已解决。

dependencies:
  barcode_scan: ^3.0.1

功能列表:

[x] Scan 2D barcodes
[x] Scan QR codes
[x] Control the flash while scanning
[x] Permission handling

主要警告是关于https://github.com/dm77/barcodescanner的警告不再存在。

第二个选项是flutter_barcode_scanner,它也适用于android和ios。 https://pub.dev/packages/flutter_barcode_scanner 对于android来说,只需放置pubdev依赖项并进行播放,对于iOS而言,您唯一需要做的就是:1:将最低部署目标设置为11; 2:将Swift版本设置为5; 3:询问使用相机的权限。也许flutter-bardode-scanner是最好的选择,因为它仅取决于pubdev依赖项,而无需第三方项目(不再维护)。

当需要创建QR码时,QR.Flutter也适用于ios和android。 功能:

[x] Built on QR - Dart
[x] Automatic QR code version/type detection or manual entry
[x] Supports QR code versions 1 - 40
[x] Error correction / redundancy
[x] Configurable output size, padding, background and foreground colors
[x] Supports image overlays
[x] Export to image data to save to file or use in memory
[x] No internet connection required

为此,他们两个在pub.dev上都享有最佳声誉。因此,您可能需要尝试一下,并检查其中哪些可以满足您的项目需求。

更新答案:要从图库中读取条形码,还有一个名为qr_code_tools的替代软件包。可以从ImagePicker获取图像,然后通过QrCodeToolsPlugin.decodeFrom

将其解码为数据。

从厨房获取图像:

ImagePicker.pickImage(source: ImageSource.gallery));

将图像解码为数据:

import 'package:qr_code_tools/qr_code_tools.dart';

String _data;
Future decode(String file) async {
  String data = await QrCodeToolsPlugin.decodeFrom(file);
  setState(() {
    _data = data;
  });
}

答案 2 :(得分:1)

我正在处理目前作为我的QR生成插件(https://github.com/lukef/qr.flutter)的伴侣,但不幸的是我没有特定的时间表。

我的计划是使用Texture对象并连接相机(或分叉/使用相机插件),然后使用Google Vision API(https://developers.google.com/vision/android/barcodes-overview)。

它应该是体面的微不足道的,我只需要找时间。无论哪种方式,如果您想这样做,那就是计划:)

答案 3 :(得分:0)

您可以在Flutter项目中使用开源SDK(例如 ZXing )或商业SDK(例如 Dynamsoft条码阅读器SDK )。实现条形码扫描功能很容易。

我写了一篇文章 - Flutter Programming with Android AAR File,分享了如何在一个颤动的项目中扫描二维码。 source code也可以在GitHub上找到。

Java代码

private String onGetBarcode(String json) {
        String filename;
        try {
            JSONObject message = new JSONObject(json);
            filename = message.getString("filename");
        } catch (JSONException e) {
            Log.e(TAG, "JSON exception", e);
            return null;
        }

        String locationProvider;
        String barcodeResult = "No barcode detected";
        File file = new File(filename);
        if (!file.exists()) {
            barcodeResult = "No file exists: " + file.toString();
            Toast.makeText(BarcodeReaderActivity.this, barcodeResult, Toast.LENGTH_LONG).show();

            return null;
        }
        else {
            Bitmap bitmap = BitmapFactory.decodeFile(file.toString());
            BarcodeReader reader = new BarcodeReader("license");
            ReadResult result = reader.readSingle(bitmap, Barcode.QR_CODE);
            Barcode[] all = result.barcodes;
            if (all != null && all.length == 1) {
                barcodeResult = all[0].displayValue;
            }
            else {
                barcodeResult = "no barcode found: " + file.toString();
            }

            bitmap.recycle();

        }

        JSONObject reply = new JSONObject();
        try {
            if (barcodeResult != null) {
              reply.put("result", barcodeResult);
            } else {
              reply.put("result", "No barcode detected");
            }
        } catch (JSONException e) {
            Log.e(TAG, "JSON exception", e);
            return null;
        }

        return reply.toString();
    }

飞镖代码

@override
  Widget build(BuildContext context) {
    if (_isExisted) {
      return new Material(
          child: new Center(
              child: new Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    new Text('Barcode Reader'),
                    new Input(
                      labelText: 'Please input the image path',
                      value: new InputValue(text: _filename),
                      onChanged: onTextChanged,
                      autofocus: true,
                    ),
                    new Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: <Widget>[
                          new RaisedButton(
                              child: new Text('Read'),
                              onPressed: _getBarcode
                          ),
                          new RaisedButton(
                              child: new Text('Reset'),
                              onPressed: _resetResult
                          ),
                        ]
                    ),
                    new Image.file(new File(_filename)),
                    new Text('$_result'),
                  ]
              )
          )
      );
    }
    else {
      return new Material(
          child: new Center(
              child: new Column(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: <Widget>[
                    new Text('Barcode Reader'),
                    new Input(
                      labelText: 'Please input the image path',
                      onChanged: onTextChanged,
                      autofocus: true,
                    ),
                    new Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: <Widget>[
                          new RaisedButton(
                              child: new Text('Read'),
                              onPressed: _getBarcode
                          ),
                          new RaisedButton(
                              child: new Text('Reset'),
                              onPressed: _resetResult
                          ),
                        ]
                    ),
                    new Text('$_result'),
                  ]
              )
          )
      );
    }
  }

  Future<Null> _readBarcode() async {
    final Map<String, String> message = <String, String>{'filename':_filename};
    final Map<String, dynamic> reply = await HostMessages.sendJSON('getBarcode', message);
    // If the widget was removed from the tree while the message was in flight,
    // we want to discard the reply rather than calling setState to update our
    // non-existent appearance.
    if (!mounted)
    return;
    setState(() {
    _result = reply['result'].toString();
    });
  }

<强>截图

enter image description here

所以请花一点时间自己动手:)

答案 4 :(得分:0)

我使用了qr_scan。问题是我用目标c造成了扑打。我必须删除iOS并进行更改。

为此,请从项目中删除ios文件夹,并快速创建它。

要创建使用命令,flutter create -i swift .不要忘记.,因为花了我几个小时才弄清这一点