Barcodescanner, Camera cannot be turned off

asked 2019-06-21 20:50:28 +0800

OSDaniel gravatar image OSDaniel
3 1

About the Barcodescanner Component.

If I set setEnable() to false or remove the component, after the first onDetect event, the Phones Camera will not turn off.

Another problem I have is I can't scan another Barcode after the first one until I refresh the page. I tried to set setEnable() and setContinuous() to true but it didn't work either.

Thanks in advance.

delete flag offensive retag edit

4 Answers

Sort by ยป oldest newest most voted

answered 2019-07-08 18:51:13 +0800

MDuchemin gravatar image MDuchemin
2310 1 6
ZK Team

updated 2019-07-08 18:55:44 +0800

hawk gravatar image hawk
3135 1 5
http://hawkphoenix.blogsp... ZK Team

Hi OSDaniel,

thanks for the code sample. I could reproduce the use case and have a look at the cause Found a few issues with the current implementation and posted some tracker tickets:

I found a workaround for both, so you could try adding those to your application with the following override script:

zk.afterLoad('zkmax.barscanner', function() {
    var xBarcodescannerStatic = {};
    zk.override(zkmax.barscanner.Barcodescanner, xBarcodescannerStatic ,{
        _quaggaInit: function (wgt, video, canvas, target) {
            var readerType = [],
                reader = wgt._QUAGGAReader;
            wgt.debug = false;
            reader._ready = false;
            readerType = zkmax.barscanner.Barcodescanner._quaggaTypeFilter(wgt);

            //Before quagga.init, the video status should be 4, so it has videoWidth and videoHeight attribute to set the
            //size of canvas
            new Promise(function (resolve, reject) {
                var waitVideo = setInterval(function () {
                    if (video.readyState == 4) {
                }, 50, wgt);
            }).then(function () {
                    locate: true,
                    inputStream: {
                        name: 'Live',
                        type: 'LiveStream',
                        target: target, // Or '#yourElement' (optional)
                        area: { // defines rectangle of the detection/localization area
                            top: '0%',    // top offset
                            right: '0%',  // right offset
                            left: '0%',   // left offset
                            bottom: '0%'  // bottom offset
                        size: zkmax.barscanner.Barcodescanner._quaggaCanvasDim(wgt).width
                    frequency: 1000,
                    decoder: {
                        readers: readerType, // List of active readers
                        debug: {
                            drawBoundingBox: false,
                            showFrequency: false,
                            drawScanline: false,
                            showPattern: false
                        multiple: false
                    locator: {
                        halfSample: false,
                        patchSize: 'medium', // x-small, small, medium, large, x-large
                        debug: {
                            showCanvas: wgt.debug,
                            showPatches: wgt.debug,
                            showFoundPatches: wgt.debug,
                            showSkeleton: wgt.debug,
                            showLabels: wgt.debug,
                            showPatchLabels: wgt.debug,
                            showRemainingPatchLabels: wgt.debug,
                            boxFromPatches: {
                                showTransformed: wgt.debug,
                                showTransformedBox: wgt.debug,
                                showBB: wgt.debug
                    debug: wgt.debug
                }, function (err) {
                    if (err) {
                    reader.canvas = jq.extend(true, {}, zkmax.barscanner.quagga.canvas);
                    reader._ready = true;
                    reader._reset = true;
                    reader._consistencyBuffer = [];
            var onProcessedCallback = function (result) {
                if(wgt.$n() == null){
                var q = zkmax.barscanner.quagga,
                        drawingCanvas = wgt.$n('canvas'),
                        drawingCtx = drawingCanvas.getContext('2d');
                    if (result) {
                        if (result.boxes) {
                            drawingCtx.clearRect(0, 0, parseInt(drawingCanvas.getAttribute('width')), parseInt(drawingCanvas.getAttribute('height')));
                                .filter(function (box) { return box !== result.box; })
                                .forEach(function (box) {
                                    q.ImageDebug.drawPath(box, {x: 0, y: 1}, drawingCtx, {color: 'green', lineWidth: 2});
                        if (result.box)
                            q.ImageDebug.drawPath(result.box, {x: 0, y: 1}, drawingCtx, {color: 'blue', lineWidth: 2});
                        if (result.codeResult && result.codeResult.code)
                            q.ImageDebug.drawPath(result.line, {x: 'x', y: 'y'}, drawingCtx, {color: 'red', lineWidth: 3});
            reader.onDetected(function (result) {
                if (result[0] != undefined) {
                    result = result[0];
                var errors = result.codeResult.decodedCodes
                        .filter(function (i) { return i.error !== undefined; })
                        .map(function (i) { return i.error; }),
                    errorSum = errors.reduce(function (prev, next) { return prev + next; }),
                    errorFactor = errorSum / errors.length;
                if (errorFactor <= wgt._errorAcceptance) {
                    var format = result.codeResult.format.replace('_', ''),
                        value = result.codeResult.code,
                        buf = reader._consistencyBuffer;
                    if (buf.length > wgt._consistencyBufferSize) buf.shift();
                    if (buf.filter(function (v) { return v === value; }).length >= wgt._consistencyThreshold) {
                        reader._consistencyBuffer = [];
                        wgt._doDetect(format, value);
                        reader.processing = false;
zk.afterLoad('zkmax.barscanner', function() {
    var xBarcodescanner = {};
    zk.override(zkmax.barscanner.Barcodescanner.prototype, xBarcodescanner ,{
        _setReaders: function () {
            var libs = this.$class._checkLibs(this),
                wgt = this;
            var wgtLibsName = [];
            this.libs.forEach(function (lib) {
            for (var i = 0; i < libs.length; i++) {
                wgt.$n('canvas').width = wgt.$n('canvas').width;
                wgt.$n('canvas').height = wgt.$n('canvas').height;
                var barReader = wgt.$class._readerConstruct(wgt, libs[i].constructor);
                if (barReader['zinit']) {
                    barReader.zinit(wgt, wgt.$n('video'), wgt.$n('canvas'), wgt.$n());
link publish delete flag offensive edit

answered 2019-06-24 19:13:04 +0800

MDuchemin gravatar image MDuchemin
2310 1 6
ZK Team

Hi OSDaniel,

The enable flag on barcodescanner doesn't release the camera API on the web browser by design. It is used to activate / deactivate capture events for this scanner instance.

I agree that the API not being released if the component is removed is a problem, so I've added a bug ticket to tracker regarding that behavior: https://tracker.zkoss.org/browse/ZK-4327

Regarding the multiple scan problem, I don't see that issue on my local test. I've run the following code locally (require localhost or https), and I get multiple scans while the scanner is in enable=true mode. Can you share a code sample that reproduce the issue from your side? http://zkfiddle.org/sample/2uale3u/1-barcode-scanner-not-unloading

link publish delete flag offensive edit

answered 2019-07-04 21:01:48 +0800

OSDaniel gravatar image OSDaniel
3 1

Hi MDuchemin,

Sorry that it took so long. I've provided a code sample for you. I've also tried to disable the barcodescanner when I'm closing the window but I got the same result: I can only scan once, after that I have to refresh the page to scan again.

package system.view.article;

import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zkmax.zul.Barcode;
import org.zkoss.zkmax.zul.Barcodescanner;
import org.zkoss.zkmax.zul.event.DetectEvent;
import org.zkoss.zul.Label;
import org.zkoss.zul.Window;

import system.view.ContentComposer;

public class MyView {

    private ContentComposer composer;

    private Label lbOutput;
    private Window bcScanWindow;
    private Barcode bcQrCode;

    // event listener
    private EventListener<Event> onQrClick = new EventListener<Event>() {

        public void onEvent(Event event) throws Exception {

            bcScanWindow = new Window();
            bcScanWindow.setTitle("Barcode Scanner");

            Barcodescanner bScan = new Barcodescanner();
            bScan.addEventListener("onDetect", onBarcodeDetect);



    private EventListener<DetectEvent> onBarcodeDetect = new EventListener<DetectEvent>() {

        public void onEvent(DetectEvent event) throws Exception {
            Events.postEvent(Events.ON_OK, lbOutput, null); // Updates other UI elements

            if (bcScanWindow != null) {

    private void initializeUIElements(){

        bcQrCode = new Barcode();
        bcQrCode.addEventListener(Events.ON_CLICK, onQrClick);

link publish delete flag offensive edit

answered 2023-02-16 17:21:41 +0800

ypaz gravatar image ypaz


Thank you for the solution. I had the same issue with the <barcodescanner> component (error repetitively of the getContext()). For this, I inserted the javascript in the zul file. But this is a temporal solution for the problem ?

Do you have analyze the issue to create a patch for the next release the ZK ?

Thanks, ypaz

link publish delete flag offensive edit


when we put bugs into our https://tracker.zkoss.org/, we will fix them in our plan. We watch the bug with the tracker link.

hawk ( 2023-02-20 11:25:57 +0800 )edit
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools




Asked: 2019-06-21 20:50:28 +0800

Seen: 36 times

Last updated: Feb 16

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More