Ionic Angular QR Code Scanner with Cordova

The Ionic framework has shifted its native runtime from Cordova to Capacitor. But we can still create Ionic Angular projects based on Cordova.

In this article, we are going to create an Ionic Angular QR code scanning app based on Cordova using the cordova-plugin-dynamsoft-barcode-reader and the ionic wrapper.

Preview of the final result:

The app will have two pages: a home page and a scanner page. After the user touches the Scan Barcodes button, it will navigate to the scanner page to scan barcodes and QR codes. If it finds a barcode, then return the result to the home page. The user can set the reader to read QR codes only at the home page.

Getting started with Dynamsoft Barcode Reader

DOWNLOAD THE SDK WITH A 30-DAY LICENSE
REQUEST A 30-DAY LICENSE

Writing an Ionic Angular QR Code Scanner

Let’s do this in steps.

New Project

Use the Ionic cli tool to create a new project.

ionic start qr-code-scanner --type=angular --cordova

Add iOS and Android platforms:

ionic cordova platforms add ios
ionic cordova platforms add android

Run the app:

ionic cordova run android
ionic cordova run ios

Add Camera Permission

For iOS, add the following to its Info.plist:

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

Install Dependencies

npm install cordova-plugin-dynamsoft-barcode-reader @awesome-cordova-plugins/core @awesome-cordova-plugins/dynamsoft-barcode-scanner

Create a Scanner Page and Manage Navigation

  1. Generate a page named scanner.

    ionic generate page scanner
    
  2. In home.page.html, add the following template:

    <ion-header [translucent]="true">
      <ion-toolbar>
        <ion-title>
          Home
        </ion-title>
      </ion-toolbar>
    </ion-header>
    <ion-content [fullscreen]="true">
      <ion-button expand="full" (click)="navigate()">Scan Barcodes</ion-button>
      <ion-list>
        <ion-item *ngFor="let entry of scanOptions">
          <ion-label>{{entry.val}}</ion-label>
          <ion-checkbox slot="end" [(ngModel)]="entry.isChecked"></ion-checkbox>
        </ion-item>
        <ion-item *ngFor="let result of barcodeResults">
          <ion-label>{{result.barcodeFormat + ": " + result.barcodeText}}</ion-label>
        </ion-item>
      </ion-list>
    </ion-content>
    
  3. In home.page.ts, add a scanOptions property.

    public scanOptions = [
      { val: 'Scan QR Code Only', isChecked: false }
    ];
    
  4. In home.page.ts, add a navigate function which navigates to the scanner page.

    navigate(){
      let qrcodeonly = this.scanOptions[0].isChecked;
      this.router.navigate(['/scanner'],{
        state: {
          qrcodeonly: qrcodeonly
        }
      });
    }
    
  5. In home.page.ts, add an ionViewWillEnter lifecycle hook to check whether there are barcodes found and update the barcodeResults property. The HTML will be updated if the property is updated.

    ionViewWillEnter(){
      if (history.state.barcodeResults) {
          this.barcodeResults = history.state.barcodeResults;
      }
    }
    
  6. In scanner.page.ts, add the following to ngOnInit to check the navigation with a dummy barcode result.

    ngOnInit() {
      let dummyBarcodeResult:BarcodeResult;
      dummyBarcodeResult = {
        barcodeFormat:"QR_CODE",
        barcodeText:"Dynamsoft",
        barcodeBytesBase64:"base64",
        x1:0,
        x2:0,
        x3:0,
        x4:0,
        y1:0,
        y2:0,
        y3:0,
        y4:0
      }
      this.router.navigate(['/home'],{
        state: {
          barcodeResults:[dummyBarcodeResult]
        }
      });
    }
    

Create a Barcode Scanner Component

We need to create a barcode scanner component to use in the scanner page.

  1. Run the following command to create the component:

    ionic generate component BarcodeScanner
    
  2. Initialize Dynamsoft Barcode Reader with a license in the ngOnInit hook.

    import { BarcodeScanner as DBR, FrameResult } from '@awesome-cordova-plugins/dynamsoft-barcode-scanner/';
       
    @Input() license?:string
    async ngOnInit():Promise<void> {
      if (!this.license) {
        this.license = "DLS2eyJoYW5kc2hha2VDb2RlIjoiMjAwMDAxLTE2NDk4Mjk3OTI2MzUiLCJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSIsInNlc3Npb25QYXNzd29yZCI6IndTcGR6Vm05WDJrcEQ5YUoifQ==";
      }
      let result = await DBR.init(this.license);
    }
    

    You can apply for a trial license here.

  3. Update the runtime settings in the ngOnInit hook as well:

    @Input() runtimeSettings:string;
    async ngOnInit():Promise<void> {
      if (this.runtimeSettings) {
        DBR.initRuntimeSettingsWithString(this.runtimeSettings);
      }
    }
    

    We can modify the runtime settings of Dynamsoft Barcode Reader with a JSON template. For example, the following template specifies the barcode format to QR code:

    {"ImageParameter":{"BarcodeFormatIds":["BF_QR_CODE"],"Description":"","Name":"Settings"},"Version":"3.0"}
    

    You can learn about the runtime settings by checkout the docs.

  4. Add an isActive property. When it is set to true, start scanning. Otherwise, stop scanning.

    private _isActive: boolean;
    onFrameRead = new EventEmitter<FrameResult>();
       
    @Input()
    set isActive(isActive: boolean) {
      this._isActive= isActive;
      if (isActive === true) {
        DBR.startScanning({dceLicense:this.license}).subscribe((result:FrameResult) => {
          if (this.onFrameRead) {
            this.onFrameRead.emit(result);
          }
        });
      }else{
        console.log("stop scanning");
        DBR.stopScanning();
      }
    }
    get isActive(): boolean{ return this._isActive; }
    

    The barcode results will be sent to the component’s parent through an EventEmitter.

  5. Add a torchOn property. When it is set to true, turn on torch. Otherwise, turn off torch.

    @Input()
    set torchOn(torchOn: boolean) {
      this._torchOn= torchOn;
      if (torchOn === true) {
        DBR.switchTorch("on");
      }else{
        DBR.switchTorch("off");
      }
    }
    
    get torchOn(): boolean{ return this._torchOn; }
    

Add the Barcode Scanner Component to the Scanner Page

  1. In scanner.page.html, add the following template:

    <app-barcode-scanner
      [isActive] = "isActive"
      [runtimeSettings] = "runtimeSettings"
      [torchOn] = "torchOn"
      (onFrameRead)="onFrameRead($event)">
    </app-barcode-scanner>
    
  2. In scanner.module.ts, add the component declaration:

    @NgModule({
      imports: [
        CommonModule,
        FormsModule,
        IonicModule,
        ScannerPageRoutingModule
      ],
      declarations: [
        ScannerPage, 
    +   BarcodeScannerComponent
      ]
    })
    
  3. Switch to scanner.page.ts, in the constructor, update the runtime settings based on the user’s selection of whether to scan QR codes only in the home page.

    isActive: boolean;
    qrcodeonly: boolean;
    torchOn: boolean;
    runtimeSettings: string;
    constructor(private router: Router) {
      if (this.router.getCurrentNavigation().extras.state) {
        const routeState = this.router.getCurrentNavigation().extras.state;
        if (routeState) {
          this.qrcodeonly = routeState.qrcodeonly;
        }
      }
      if (this.qrcodeonly === true) {
        this.runtimeSettings = "{\"ImageParameter\":{\"BarcodeFormatIds\":[\"BF_QR_CODE\"],\"Description\":\"\",\"Name\":\"Settings\"},\"Version\":\"3.0\"}";
      }else{
        this.runtimeSettings = "{\"ImageParameter\":{\"BarcodeFormatIds\":[\"BF_ALL\"],\"Description\":\"\",\"Name\":\"Settings\"},\"Version\":\"3.0\"}";
      }
      this.isActive = true; //set initial values
      this.torchOn = false; 
    }
    
  4. Add an onFrameRead function to receive the barcode reading result.

    onFrameRead(frameResult:FrameResult) {
      if (frameResult.results.length>0) {
        this.isActive = false;
        this.torchOn = false;
        this.router.navigate(['/home'],{
          state: {
            barcodeResults:frameResult.results
          }
        });
      }
    }
    

    If there are barcodes found, stop scanning and return to the home page.

Add a Floating Action Button to the Scanner Page

In order to let the user turn on/off the torch and close the scanner page, we can add a floating action button.

  1. In scanner.page.html, add the following template:

    <ion-fab vertical="bottom" horizontal="start" slot="fixed">
      <ion-fab-button>
        <ion-icon name="ellipsis-horizontal-outline"></ion-icon>
      </ion-fab-button>
      <ion-fab-list side="top">
        <ion-fab-button (click)="toggleTorch()">
          <ion-icon name="flashlight-outline"></ion-icon>
        </ion-fab-button>
        <ion-fab-button (click)="close()">
          <ion-icon name="close-outline"></ion-icon>
        </ion-fab-button>
      </ion-fab-list>
    </ion-fab>
    
  2. Add equivalent functions:

    close(){
      this.isActive = false;
      this.torchOn = false;
      this.router.navigate(['/home'],{
        state: {
          barcodeResults:[]
        }
      });
    }
    
    toggleTorch(){
      this.torchOn = !this.torchOn;
    }
    

All right, we have now completed the Ionic angular QR code scanner.

Source Code

Check out the source code to have a try.

https://github.com/xulihang/Ionic-Angular-Cordova-Barcode-Scanner