A QR Code Scanner Component for Cordova in ReactJS that works on Android.

Yes, a component that does the job well. Code below, customise for your use case.

Note: It does not use the “cordova-plugin-qrscanner” which is broken at the time of writing.

import React, { Component } from "react";
import jsQR from "jsqr";
import $ from "jquery";

class QrCodeScanner extends Component {
  constructor(props) {
    super(props);
    this.videoRef = React.createRef();
    this.state = {
      qrcode: "",
      videoError: false
    }
  }

  componentDidMount() {
    this.checkCameraPermissions();
  }

  componentWillUnmount() {
    this.stopScanner();
  }

  checkCameraPermissions = async () => {
    var thisController = this;

    cordova.plugins.permissions.requestPermission(
      cordova.plugins.permissions.CAMERA,
      function (status) {
        if (status.hasPermission) {
          console.log("Camera permission granted");
          thisController.startScanner();
        } else {
          console.log("Camera permission denied");
          thisController.state.videoError = true;
          thisController.setState(thisController.state);
        }
      },
      function () {
        console.log("Error requesting camera permission");
        thisController.state.videoError = true;
        thisController.setState(thisController.state);
      }
    );
  };

  startScanner = () => {
    navigator.mediaDevices.getUserMedia({ video: { facingMode: "environment" } })
      .then((stream) => {
        this.videoRef.current.srcObject = stream;
        this.videoRef.current.play();
        this.videoRef.current.addEventListener("loadedmetadata", this.scanFrame);
      })
      .catch((error) => {
        console.error("Error starting scanner: ", error);
        this.state.videoError = true;
      });
  };

  stopScanner = () => {
    const stream = this.videoRef.current.srcObject;
    if (stream) {
      const tracks = stream.getTracks();
      tracks.forEach((track) => {
        track.stop();
      });
    }
    document.getElementById("qrScannerPreview").pause();
  };

  scanFrame = () => {
    var thisController = this;
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("2d");
    const video = this.videoRef.current;

    canvas.width = video.videoWidth;
    canvas.height = video.videoHeight;
    context.drawImage(video, 0, 0, canvas.width, canvas.height);
    const imageData = context.getImageData(0, 0, canvas.width, canvas.height);

    const code = jsQR(imageData.data, imageData.width, imageData.height);
    if (code) {
      console.log("QR code detected: ", code.data);
      //Do something with the extracted code.

        return;
      }

    }

    requestAnimationFrame(this.scanFrame);
  };


  render() {

    return (
      <div style={{ height: "90vh", marginTop: "7vh" }} >

        <div id="view-qrscanner" >
          <div>
            <div className="container-qr">
              <div style={{ paddingTop: "1vh" }} >
                <div align="center">
                  <h3 style={{ fontWeight: 'bold', fontSize: "1.28rem", color: 'white' }}>Scan your onboarding QR code</h3>
                  <label style={{ padding: "10vw", fontSize: "0.92rem", color: 'white' }}>Postion the QR Code a few inches away</label>
                </div>
                <div id="camera" className="pre_capture_frame" style={{ width: '95vw' }} />
                {!this.state.videoError && <video style={{ width: "85vw", height: "85vw", margin: '4.5vw', borderRadius: '12px' }}
                  ref={this.videoRef} id="qrScannerPreview" />}
                {this.state.videoError && <div>Could not start the video source.
                  Please ensure that you have granted camera permissions and that 
                  the camera is not being used by another app.</div>}
                <br />
                <div id="tick" align="center" style={{ display: 'none', color: '#94bde9',
                                                     fontSize: '108px', width: '95vw' }}>
                  &#10004;
                </div>
              </div>

            </div>
          </div>
        </div>

      </div>
    );
  }
}

export default QrCodeScanner;
Kj
Kj [/.] Sreekumar programs computers as a hobby and profession. Into programming from his school days, Sree uses Codemarvels to key in facts and fixes he finds interesting while working on different projects. Some of the articles here give away a few shades of his philosophical leanings too.

Leave a Comment

Your email address will not be published. Required fields are marked *