Flutter | Building a QR code scanner for Web, Android & iOS

Rob Yeates
4 min readMar 19, 2022

--

Utilising mobile_scanner, jsQR and a custom overlay.

Introduction

In this post, we will create a functioning QR code scanner with just one package from pub.dev. This package makes use of AVFoundation for iOS, CameraX for Android, and jsQR for the web. We will also add a custom overlay over the scanner to make it less like just a camera, and more like an actual scanner.

The package replaces the highly popular qr_code_scanner that has been moved into maintenance mode due to the underlying frameworks no longer being maintained (zxing & MTBBarcodeScanner).

Dependencies

Our project pubspec.yaml file plugin dependencies consist of:

dependencies:
....
mobile_scanner: ^1.0.0
  • mobile_scanner: A universal barcode and QR code scanner for Flutter based on MLKit.

Prerequisites

Android Min SDK

mobile_scanner requires an SDK version of 21 above to work on Android, check that the minSdkVersion is set to 21 or higher at android/app/build.gradle.

defaultConfig {
...
minSdkVersion 21
}

Granting camera permission on Android & iOS

For the scanner to work, the camera must have permission to activate. Make sure these permissions are correctly set in the respective locations:

Android: android/app/src/main/AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA"/>
iOS: ios/Runner/Info.plist
<key>NSCameraUsageDescription</key>
<string>To capture QR Codes</string>

Adding the jsQR library

Scanning the web requires its own JavaScript library to work, luckily there already is one to use instead of creating your own! (Note: Scanning on the web is currently limited and can only do QR codes and not barcodes)

Add the script in the web/index.html file, after the main script for main.dart.js.

 ...
loadMainDartJs();
}
</script>
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.4.0/dist/jsQR.min.js"></script>

Once added, rebuild your Flutter application, a hot restart will not load the new JavaScript.

Scanner Screen

Let's now actually get something on the app; Adding an initial scanner widget is very simple, we will import the package by addingimport 'package:mobile_scanner/mobile_scanner.dart';at the start of the file and then inserting the MobileScanner() widget into our code.

With this, we now get a camera presence on the screen, and if you show a QR code or barcode (Android or iOS) to the camera it will scan it and currently display it within the debug console.

MobileScanner comes with the parameter ‘allowDuplicates’, this is defaulted to false to stop the issue of the scanner scanning multiple scans in a very short time, causing things like pop() to fire lots of times.

Scanner on Web and Android

Adding user controls

This is a great start, lets's now add some controls for the user so they can turn on the flash or switch the camera around. To control the camera, we must provide a controller MobileScannerController cameraController = MobileScannerController();that will be used to change the state of the camera and functionality.

Scanner with user controls

Scanner Overlay

Now, let’s add an overlay on the QR camera’s screen. We make a new file called qr_overlay.dart to hold the overlay. This will be a stateless widget because nothing within it will need to be changed after it has been built. ColorFiltered is used to cut out the centre hole in the overlay, and Paint is used to create the white rounded border lines.

Every build includes a check of the screen’s width and height, allowing us to construct a larger cutout for larger screens and a smaller cutout for smaller devices.

Putting the overlay over the camera

To set the overlay over the camera, we’ll use the stack widget to place it on top. Because the last item in the stack widget list will always be at the front, the overlay widget will be placed after the MobileScanner within the stack.

Final QR scanner with an overlay

--

--