0

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

3 Answers

Sort by ยป oldest newest most voted
0

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

MDuchemin gravatar image MDuchemin
1376 1 4
ZK Team

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

hawk gravatar image hawk
2400 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:

<script><![CDATA[ 
zk.afterLoad('zkmax.barscanner', function() {
    var xBarcodescannerStatic = {};
    zk.override(zkmax.barscanner.Barcodescanner, xBarcodescannerStatic ,{
        _quaggaInit: function (wgt, video, canvas, target) {
            //zkmax.barscanner.Barcodescanner.quaggaApp.init(wgt);
            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) {
                        clearInterval(waitVideo);
                        resolve();
                    }
                }, 50, wgt);
            }).then(function () {
                reader.init({
                    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) {
                        zk.error(err);
                        return;
                    }
                    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){
                    reader.offProcessed(onProcessedCallback);
                    return;
                }
                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')));
                            result.boxes
                                .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.onProcessed(onProcessedCallback);
            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;
                    buf.push(value);
                    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;
                        reader.pause();
                    }
                }
            });
        }
    });
    zkmax.barscanner.Barcodescanner._initLibrary();
});
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) {
                wgtLibsName.push(lib.libname);
            });
            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());
                    barReader.zexecute(wgt);
                }
                wgt.readers.push(barReader);
                wgt.libs.push(libs[i]);
            }
        }
    });//zk.override
});//zk.afterLoad
]]></script>
link publish delete flag offensive edit
0

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

MDuchemin gravatar image MDuchemin
1376 1 4
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
0

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>() {

        @Override
        public void onEvent(Event event) throws Exception {

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

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

            bcScanWindow.appendChild(bScan);
            bScan.setEnable(true);
            composer.getContent().appendChild(bcScanWindow);

            bcScanWindow.doModal();
        }
    };

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

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

            if (bcScanWindow != null) {
                bcScanWindow.onClose();
            }
        }
    };


    private void initializeUIElements(){

        bcQrCode = new Barcode();
        bcQrCode.setType("qr");
        bcQrCode.addEventListener(Events.ON_CLICK, onQrClick);
        bcQrCode.setId("bc_qrCode");
        composer.getContent().appendChild(bcQrCode);
    }

}
link publish delete flag offensive 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

Follow
2 followers

RSS

Stats

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

Seen: 22 times

Last updated: Jul 08

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