Search code examples
javaandroidfirebasefirebase-mlkitgoogle-mlkit

Firebase ML kit's QR Code Scanner Scans each QR Code Multiple Times


My scanner scans single QR Code multiple times thats why my createDialog method runs multiple time where i get the info regarding QR code and the user who is using it and the agent who posted it and store data into users node in Db and because it run multiple time my Db cant keep track of the no. of times the qr code scanned for each user..

 private void setupCamera() {
    startAgain.setEnabled(isDetected);
    startAgain.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            isDetected = !isDetected;
        }
    });
    cameraView.setLifecycleOwner(this);
    cameraView.addFrameProcessor(new FrameProcessor() {
        @Override
        public void process(@NonNull Frame frame) {
            processorImage((FirebaseVisionImage) getVisionImageFromFrame(frame));
        }
    });
    options = new FirebaseVisionBarcodeDetectorOptions.Builder()
            .setBarcodeFormats(FirebaseVisionBarcode.FORMAT_QR_CODE)
            .build();
    detector = FirebaseVision.getInstance().getVisionBarcodeDetector(options);
}

private Object getVisionImageFromFrame(Frame frame) {
    byte[] data = frame.getData();
    FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
            .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
            .setHeight(frame.getSize().getHeight())
            .setWidth(frame.getSize().getWidth())
            .build();
    return FirebaseVisionImage.fromByteArray(data, metadata);
}

private void processorImage(FirebaseVisionImage image) {
    if (!isDetected) {
        detector.detectInImage(image)
                .addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionBarcode>>() {
                    @Override
                    public void onSuccess(List<FirebaseVisionBarcode> firebaseVisionBarcodes) {
                        processResult(firebaseVisionBarcodes);
                    }
                }).addOnCompleteListener(new OnCompleteListener<List<FirebaseVisionBarcode>>() {
            @Override
            public void onComplete(@NonNull Task<List<FirebaseVisionBarcode>> task) {

            }
        })
                .addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Toast.makeText(StoreScanQR.this, e.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
    }
}

private void processResult(List<FirebaseVisionBarcode> firebaseVisionBarcodes) {
    if (firebaseVisionBarcodes.size() > 0) {
        isDetected = true;
        startAgain.setEnabled(isDetected);
        for (FirebaseVisionBarcode item : firebaseVisionBarcodes) {
                    try {
                        createDialog(item.getRawValue());
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
        }
    }
}

Solution

  • Detection is an asynchronous call, so it may be triggered multiple times with different inputs before you can get the first result. If you only care about the first detected result, you can check your isDetected flag at the result processing side (i.e. in #onSuccess callback) rather than detection triggering side.

    @Override
    public void onSuccess(List<FirebaseVisionBarcode> firebaseVisionBarcodes) {
        if (!isDetected) {
            processResult(firebaseVisionBarcodes);
        }
    }