How to Build a Cross-Platform QR Code Scanner with Capacitor

Capacitor is an open source native runtime created by the Ionic team for building Web Native apps. We can use it to create cross-platform iOS, Android, and Progressive Web Apps with JavaScript, HTML, and CSS.1 As an alternative to Cordova, Capacitor delivers the same cross-platform benefits, but with a more modern approach to app development, taking advantage of the latest Web APIs and native platform capabilities.2

In this article, we are going to talk about how to use the capacitor barcode reader plugin to build a QR code scanner using Dynamsoft Barcode Reader (DBR) along with Dynamsoft Camera Enhancer (DCE).

Getting started with Dynamsoft Barcode Reader

Build a QR Code Scanner using Capacitor

Integrate Capacitor with an Existing Web App

Capacitor can be integrated with existing web apps to add native functionality.

Here, we create a webpack app with a template first.

git clone https://github.com/wbkd/webpack-starter

Then, drop Capacitor into the project.

cd webpack-starter
npm install @capacitor/cli @capacitor/core
npx cap init

Then, we can create projects for Android and iOS.

npm install @capacitor/ios @capacitor/android
npx cap add ios
npx cap add android

Use the following commands to update files after the app is changed:

npm run build
npx cap sync

Use the following commands to start the app:

npm run start // run in browsers
npx cap run android // run on Android devices
npx cap run ios // run on iOS devices

Use Plugins to Bring QR Code Scanning Functionality to the App

Plugins in Capacitor enable JavaScript to interface directly with Native APIs.3 A plugin has been created to make it easy to use Dynamsoft Barcode Reader and Dynamsoft Camera Enhancer in a Capacitor app to scan QR codes. Since Dynamsoft Barcode Reader has Android, iOS and JavaScript editions, the plugin also supports Android, iOS and Web. We can test the app on the web browsers first and then make modifications to make it compatible with native platforms.

  1. Install the plugin to the web app we just create.

    npm install capacitor-plugin-dynamsoft-barcode-reader
    
  2. Add a start scanning button, a camera select and a result container in a controls container. In addition, a status span is added as well to show whether Dynamsoft Barcode Reader has been initialized.

    <span id="status">Initializing...</span>
    <div id="controls" style="display:none;">
      <select id="cameraSelect" style="max-width:200px;"></select>
      <button id="controlButton">Start Scanning</button>
      <div id="result"></div>
    </div>
    
  3. Initialize the plugin when the page is loaded. You may need to apply for a trial license to use DBR from here.

    import { DBR } from 'capacitor-plugin-dynamsoft-barcode-reader';
       
    initDBR();
       
    async function initDBR(){
      let options = {license:"DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ=="};
      let result = await DBR.initialize(options);
      if (result) {
        if (result.success == true) {
          await loadCameras();
          document.getElementById("status").remove();
          document.getElementById("controls").style.display = "";
          DBR.addListener('onFrameRead', (retObj) => {
            onFrameRead(retObj);
          });
        }
      }
    }
    

    If the initialization is successful, it will load cameras to the camera select, hide the initializing span, reveal the controls and add a listener to get the barcode results.

    The loadCameras function:

    async function loadCameras(){
      let cameraSelect = document.getElementById("cameraSelect");
      let result = await DBR.getAllCameras();
      result.cameras.forEach(camera => {
        let option = document.createElement("option");
        option.value = camera;
        option.label = camera;
        cameraSelect.appendChild(option);
      });
    }
    
  4. Add the onclick event for the start scanning button.

    function toggleScan(){
      if (document.getElementById("controlButton").innerText == "Stop Scanning") {
        stopScan();
      }else{
        startScan();
      }
    }
    

    If the scanner is opened, then stop scan, otherwise, start scan.

    The startScan and the stopScan functions:

    async function startScan(){
      scanned = false;
      document.getElementById("result").innerHTML = "";
      await onCameraSelectionChanged();
      await DBR.startScan();
      document.body.style.background = "transparent";
      document.getElementById("controls").className = "fullscreen";
      document.getElementById("controlButton").innerText = "Stop Scanning";
    }
       
    async function stopScan(){
      document.getElementById("controls").className = "";
      await DBR.stopScan();
      document.body.style.background = "white";
      document.getElementById("controlButton").innerText = "Start Scanning";
    }
    

    Please note that the plugin puts the camera preview under the webview on Android and iOS. We need to set the background to transparent to reveal the camera.

  5. When barcodes are found, stop scanning and display the results.

    function onFrameRead(retObj){
      let results = retObj["results"];
      if (results.length>0 && scanned == false) {
        scanned = true;
        let ol = document.createElement("ol");
    
        for (let index = 0; index < results.length; index++) {
          let li = document.createElement("li");
          const result = results[index];
          li.innerText = result["barcodeFormat"]+": "+result["barcodeText"];
          ol.appendChild(li);
        }
        stopScan();
        document.getElementById("result").innerHTML = ol.outerHTML;
      }
    }
    

Add Camera Permissions for iOS

We have to configure the camera permission for iOS in order to use the camera.

Add the following to Info.plist:

<key>NSCameraUsageDescription</key>
<string>For barcode scanning</string>

Ionic React Example

You can learn about how to use the plugin in React in a declarative way by checking out this article: Ionic React QR Code Scanner with Capacitor.

Source Code

https://github.com/xulihang/capacitor-qr-code-scanner

References