Is there a way to scan barcodes in Flutter?
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.
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 :)
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
So take a little bit of time and do it yourself :)