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;

Comments

Leave a Reply

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