【问题标题】:Is there a way to scan barcodes in Flutter?有没有办法在 Flutter 中扫描条形码?
【发布时间】:2018-03-27 19:48:41
【问题描述】:

基本上,我正在制作一个扫描二维码以连接到服务器的应用程序。然后,该应用程序将扫描产品的条形码并为物品拍照并将其发送到服务器。我的问题如下:

是否有 Flutter 插件可以扫描二维码和不输入与image_picker 冲突的条形码?

这是我目前发现的。

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


更新

barcode_scan 的问题已解决。我最终使用了这个,因为它比公认的答案更快,而且它的问题得到了相当快的解决。请注意,它在 iOS 上的行为是由 Apple 修改的,因此您可能会通过校验和数字或其他东西得到不同的结果。

【问题讨论】:

  • 本文提到的barcode_scan 的问题已关闭。
  • @Lynn 你是对的。 Flutter 生态系统发生了如此巨大的变化,以至于整个线程都已经过时了,而且可能会积极阻碍任何偶然发现这个问题的人。它可能应该被关闭或什么的。
  • 遗憾的是,barcode_scan 依赖项现已停用。

标签: flutter dart qr-code barcode-scanner


【解决方案1】:

我之前也遇到过类似的问题,按照你的方法搜索后,我没有找到很多。我决定最好的方法是自己编写一个插件......在这里为我的插件添加如此无耻的插件 =D,而不是让我从其他人使用它中受益。

你可以看到它here。但是,我还没有时间记录它、广泛地测试它,或者在 Pub 上正确地发布它。所以你的里程可能会有所不同。但是,它应该可以在 android 4.4+(可能更低)和 Flutter 支持的 iOS 设备上运行。我也没有将它与相机插件一起测试,但我不明白为什么它会出现问题。

它采用了与大多数其他二维码插件不同的方法;它不是制作一个 android 或 iOS 窗口,进行扫描,然后返回 Flutter,而是使用 Flutter 的纹理渲染功能让相机直接渲染到 Flutter 中。

还有一些需要考虑的事情是,它使用 Google Mobile Vision SDK 以及随之而来的适用许可和功能(并且需要 Android 上最新版本的 Play Services);并且它目前只支持从条形码扫描中提取最基本的信息——我只需要提取原始文本,这就是我所做的一切。

要使用它,请将其添加到您的 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,这需要更多处理,因此如果您使用某种类型,建议您将其传入。

【讨论】:

  • 糟糕 - 我将静态分支合并到 master,然后忘记更新它以反映这一点。我已经更新了(感谢@NatoBoram 指出)
  • 我更新了依赖项,但 .../QrCamera.dart 包不存在。 @rmtckenzie
  • @SaMiGiMiX 您是否依赖 github url 或 pub?这个答案有点过时了——现在发布的版本是qr_mobile_vision: '^0.0.7',有几个人在使用它,所以它应该可以工作。尝试将其添加到您的 pubspec,然后运行 ​​flutter packages get
  • 正确的包是“qr_mobile_vision/qr_camera.dart”。
  • rmtmckenzie 是的,我在你的包的 GitHub 页面上写了我的问题。
【解决方案2】:

我目前正在开发一些与我的 QR 生成插件 (https://github.com/lukef/qr.flutter) 配套的东西,但很遗憾,我没有具体的时间表。

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

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

【讨论】:

  • 我已经基本实现了你所说的@github.com/rmtmckenzie/flutter_qr_mobile_vision。如果您有时间做出贡献,当然欢迎您将其用作基础,并且欢迎 PR。一旦我记录并清理它,我计划在 Pub 上发布它......
【解决方案3】:

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

我写了一篇文章-Flutter Programming with Android AAR File,分享如何在flutter项目中扫描二维码。 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();
    });
  }

截图

所以花点时间自己做吧:)

【讨论】:

    【解决方案4】:

    我使用了qr_scan。问题是我用目标 c 创造了我的颤动。我不得不删除 iOS 并更改它。

    为此,请从项目中删除 ios 文件夹并使用 swift 创建它。

    创建使用是命令flutter create -i swift . 最后别忘了. 因为我花了几个小时才弄明白

    【讨论】:

      【解决方案5】:

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

      1. flutter_barcode_scanner(读者)
      2. barcode_scan(读者)
      3. qr_flutter(用于创建二维码)

      第一个: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 依赖项,而不需要 3rd 方项目(不再维护)。

      当需要创建二维码时: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;
        });
      }
      

      【讨论】:

      • 我们如何知道从图库中选择的图像是否是有效的二维码图像?
      • @Kamlesh 这不是我上面提到的图书馆的提议。但是您可以使用此包pub.dev/packages/qr_code_tools 从设备库中读取二维码
      猜你喜欢
      • 1970-01-01
      • 2021-02-28
      • 2016-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-16
      • 1970-01-01
      相关资源
      最近更新 更多