26

Basically, I'm making an app that scans a QR code to connect to a server. Then, the app will scan the barcode of products and take pictures of the item and send them to the server. My question is the following :

Is there a Flutter plugin to scan QR codes and barcodes that doesn't enter in conflict with image_picker?

Here's what I found so far.

I appreciate any help you can provide. Thanks!


Update

The issue with barcode_scan was resolved. I ended up using this one since it's faster than the accepted answer and its issues got resolved rather quickly. Be aware that its behaviour on iOS is modified by Apple, so you might get different results with checksum numbers or something.

Nato Boram
  • 4,083
  • 6
  • 28
  • 58

5 Answers5

16

I've previously had a similar problem, and after searching as you did I didn't find a whole lot. I decided that the best approach would be to write a plugin myself... so shameless plug for my plugin here =D, not that I benefit from anyone else using it at all.

You can see it here. However, I haven't had time to document it, test it all that extensively, or publish it properly on Pub. So your mileage may vary. It should however work on android 4.4+ (and maybe below), and iOS devices that flutter supports. I also haven't tested it in conjunction with the Camera plugin but I don't see why it would have a problem with it.

It takes a different approach than most of the other qr code plugins; instead of making an android or iOS window, doing the scan, then returning to flutter, it uses flutter's texture rendering capabilities to have the camera render directly into flutter.

A few more things to consider are that it uses the Google Mobile Vision SDK with the applicable licensing and capabilities that comes along with that (and requires a recent version of Play Services on Android); and that it currently only supports the most basic extraction of information from barcode scans - I only needed the raw text out so that's all I did.

To use it, add this to your pubspec.yaml:

dependencies:
  qr_mobile_vision: '^0.0.7'

And implement as follows:

import 'package:qr_mobile_vision/QrCamera.dart';

...

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

I do plan on finishing documentation/testing/etc eventually, but you're welcome to try it out in the meantime. If you decide to use it and need a feature it doesn't support I may be able to help implement it... but PRs are welcome and encouraged!

UPDATE: this does include Barcode support now. You can pass in which types of QR code / Barcode you want to support when you instantiate QrCamera. It defaults to all, which takes more processing so if you're after a certain type it's recommended that you pass it in.

rmtmckenzie
  • 37,718
  • 9
  • 112
  • 99
  • Oops - I merged the static branch to master and then forgot to update this to reflect that. I've updated it (and thanks @NatoBoram for pointing that out) – rmtmckenzie Mar 28 '18 at 17:19
  • I updated dependencies but the .../QrCamera.dart package is not existing. @rmtckenzie – Saman Aug 07 '18 at 08:41
  • @SaMiGiMiX did you depend on it with the github url or pub? This answer is a bit out of date - the released version is at `qr_mobile_vision: '^0.0.7'` now and a few people are using it so it should work. Try adding it to your pubspec then running `flutter packages get`. – rmtmckenzie Aug 07 '18 at 16:09
  • the correct package is "qr_mobile_vision/qr_camera.dart". – Saman Aug 09 '18 at 14:07
  • thanks for creating this package, but is there a way to insert delay for each scan and then callback ? – Saman Aug 12 '18 at 08:16
  • @samigimix I'm not sure exactly what you mean - can you elaborate and maybe provide an example? And the GitHub project would probably be a better place for that than here. – rmtmckenzie Aug 12 '18 at 12:50
  • 1
    rmtmckenzie yes I wroted my question in your package's GitHub page. – Saman Aug 12 '18 at 12:52
  • Great package! Of course needs some work, but it does what it says. I do recommend adding more comment documentation in the code. – mauriii May 28 '19 at 06:40
  • Why is the camera so dark compared to barcode_scan? – user2233706 Mar 14 '20 at 04:56
  • I'm getting this Firebase error, even I'm not using anywhere. PlatformException(error, Default FirebaseApp is not initialized in this process com.mateen.restpool. Make sure to call FirebaseApp.initializeApp(Context) first., null) – Mateen May 03 '20 at 04:31
1

I'm working on something currently as a companion to my QR generation plugin (https://github.com/lukef/qr.flutter) but I don't have a specific timeline, unfortunately.

My plan is to use the Texture object and hookup a camera (or fork / use the camera plugin) and then use the Google Vision API (https://developers.google.com/vision/android/barcodes-overview).

It should be decently trivial, I just need to find the time. Either way, that was the plan if you want to do it :)

Luke
  • 6,388
  • 3
  • 26
  • 35
  • 1
    I've implemented basically what you're talking about @ https://github.com/rmtmckenzie/flutter_qr_mobile_vision. If you have time to contribute, you're welcome to use that as a base of course, and PRs are welcome. Once I document it & clean it up a bit more I'm planning on releasing it on Pub... – rmtmckenzie Mar 28 '18 at 14:25
0

You can use an open source SDK (e.g., ZXing) or a commercial SDK (e.g., Dynamsoft Barcode Reader SDK) in your Flutter project. Implementing the barcode scanning function is easy.

I have written an article - Flutter Programming with Android AAR File, sharing how to scan QR code in a flutter project. The source code is also available on GitHub.

Java code

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();
    }

Dart code

@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();
    });
  }

Screenshot

enter image description here

So take a little bit of time and do it yourself :)

yushulx
  • 11,695
  • 8
  • 37
  • 64
0

According with my researchs there are good options for that:

  1. flutter_barcode_scanner (reader)
  2. barcode_scan (reader)
  3. qr_flutter (thats is for create QR codes)

1st: barcode_scan will works as a wrapper for two commonly used iOS and Android libraries. (iOS: https://github.com/mikebuss/MTBBarcodeScanner, Android: https://github.com/dm77/barcodescanner)

They are in version 3 already and seems like the all the major bugs were resolved.

dependencies:
  barcode_scan: ^3.0.1

Here the feature list:

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

The main warn is about https://github.com/dm77/barcodescanner that's no longer maintained.

The 2nd option is flutter_barcode_scanner thats also works for both android and ios. https://pub.dev/packages/flutter_barcode_scanner For android is just put the pubdev dependency and play, for iOS the only things you need to do is: 1: set minimum deployment target to 11, 2: set Swift version to 5 and 3: ask the permission to use the camera. May the flutter-bardode-scanner is best option since it will depends on just a pubdev dependency without the need of 3rd party project (no longer maintained).

When it's needed to create QR code there is: QR.Flutter also works for ios and android. Features:

[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

Both of them have the best reputation on pub.dev for this propose. So may you need to give a try and check which of them will fill your project needs.

Updating the answer: To read barcode from image gallery there is an alternative package called qr_code_tools. The image could be get from ImagePicker and then decoded to data through QrCodeToolsPlugin.decodeFrom

Getting the image from galley:

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

Decoding the image to data:

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;
  });
}
Cassio Seffrin
  • 7,293
  • 1
  • 54
  • 54
  • how can we know that selected image from gallery is a valid QR code image or not? – Kamlesh Oct 11 '20 at 10:55
  • 2
    @Kamlesh this is not the proposal of the libraries I mentioned above. But you can read QR code from device gallery using this package https://pub.dev/packages/qr_code_tools – Cassio Seffrin Oct 11 '20 at 14:52
0

I used qr_scan. The issue was I created my flutter with objective c. I had to delete iOS and change it.

To do that delete the ios folder from the project and create it with swift.

To create use is command flutter create -i swift . dont forget the . in the end cause it took me a couple of hours to figure that out

zizutg
  • 1,070
  • 14
  • 20