如何设置 Google Vision QR Scanner 只检测一个值?

How to set Google Vision QR Scanner to detect only one value?

我已经使用 Google Vision API 实现了 QR 扫描仪 (QRScanner class)。一旦检测到一个值,它就会使用 Intents 传递给另一个 activity(Info class)。问题是,一旦二维码被扫描,Info class 就会打开几个 times.I 想要限制 QRScanner class 只获取一个 QR 值和 Info classed只能打开一次。

QRScanner Class

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qr_scanner);

cameraPreview = (SurfaceView) findViewById(R.id.camera_surface);
qrResult = (TextView) findViewById(R.id.scannerResult);
setupCamera();
}

private void setupCamera() {

BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(this).setBarcodeFormats(Barcode.QR_CODE).build();
final CameraSource cameraSource = new CameraSource.Builder(this, barcodeDetector)
        .setAutoFocusEnabled(true)
        .setRequestedPreviewSize(1600, 1024)
        .build();

cameraPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        if (ActivityCompat.checkSelfPermission(QrScanner.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        try {
            cameraSource.start(cameraPreview.getHolder());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        cameraSource.stop();
    }
});


barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
    @Override
    public void release() {

    }

    @Override
    public void receiveDetections(Detector.Detections<Barcode> detections) {

        final SparseArray<Barcode> qrCodes = detections.getDetectedItems();

        if(qrCodes.size()>0)
        {
            qrResult.post(new Runnable() {
                @Override
                public void run() {

                    qrResult.setText(qrCodes.valueAt(0).displayValue);
                    Intent intent = new Intent(QrScanner.this,Info.class);
                    intent.putExtra(QR_CODE,qrCodes.valueAt(0).displayValue);
                    startActivity(intent);
                }
            });
        }
    }
});
}

信息Class

Intent intent = getIntent();
QRCODE = (String) intent.getStringExtra(QrScanner.QR_CODE);

DB = FirebaseDatabase.getInstance();
ref = DB.getReference().child("Animals").child(QRCODE);
ref.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

        String DBAnimalClass = dataSnapshot.child("class").getValue().toString();
        String DBAnimalFamily = dataSnapshot.child("family").getValue().toString();
        String DBAnimalOrder = dataSnapshot.child("order").getValue().toString();

    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {

    }
});

目前,一旦检测到二维码,就会多次调用信息 class。我希望 QRScanner 只获得一个值,而 Info class 只被调用一次。

您的摄像头正在连续检测 QR 码,那是您 activity 打开了多次。所以当你成功检测到任何东西时,你需要停止相机。

 if(qrCodes.size()>0)
        {

            cameraSource.stop(); // ADD THIS. THIS WILL STOP CAMERA
            qrResult.post(new Runnable() {
                @Override
                public void run() {

                    qrResult.setText(qrCodes.valueAt(0).displayValue);
                    Intent intent = new Intent(QrScanner.this,Info.class);
                    intent.putExtra(QR_CODE,qrCodes.valueAt(0).displayValue);
                    startActivity(intent);
                }
            });
        }

我认为您需要收集数据并将其传递到内部 class 之外。

示例:

@Override
public void receiveDetections(Detector.Detections<Barcode> detections) {
    final SparseArray<Barcode> qrCodes = detections.getDetectedItems();
    final String qrData = "";
    if(qrCodes.size()>0){
        qrResult.post(new Runnable() {
            @Override
            public void run() {
                qrData = qrCodes.valueAt(0).displayValue;
            }
        });
    }
    qrResult.setText(qrData);
    goToPage(qrData);
}


private void goToPage (String qrData) {
    Intent intent = new Intent(QrScanner.this,IDNA.Info.class);
    intent.putExtra(QR_CODE,qrData);
    startActivity(intent);
}

使用这个库MobileVisionBarcodeScanner

您可以启用和禁用多重扫描 .setSupportMultipleScan(true/false)

并使用

停止扫描
barcodeCapture.stopScanning();

还有很多功能。

经过一些研究,我发现了如何解决这个问题。然而,在通过 Intent 加载的 activity 按下后退按钮返回到此 activity 后,扫描仪将不再工作,因此应重新加载 onCreate() 方法。

工作代码

if(qrCodes.size()>0)
    {

        barcodeDetector.release(); //stops the scanner from reading multiple values
        qrResult.post(new Runnable() {
            @Override
            public void run() {

                qrResult.setText(qrCodes.valueAt(0).displayValue);
                Intent intent = new Intent(QrScanner.this,Info.class);
                intent.putExtra(QR_CODE,qrCodes.valueAt(0).displayValue);
                startActivity(intent);
            }
        });
    }

cameraSource.stop() 不起作用的原因在 link 中有解释;

希望对您有所帮助!!