0

I am using google vision in my application to read barcodes and qr-codes. This is working great, but it crashes when the scanned surface has 2 codes next to each other, like in the picture below.

enter image description here

This happens, even though the codes are scanned properly if they are scanned seperately. Does anyone know how to stop this from happening?

Here is the code that manages the code scanning activity:

public class ScanningActivity extends AppCompatActivity {

    SurfaceView cameraPreview;
    BarcodeDetector barcodeDetector;
    CameraSource cameraSource;
    final Integer requestCameraPermissionID = 1001;

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

        final int height = getSurfaceViewHeight();
        final int width = getSurfaceViewWidth();

        cameraPreview = findViewById(R.id.surfaceview_scanner);

        barcodeDetector = new BarcodeDetector.Builder(AddScanningActivity.this)
                .setBarcodeFormats(Barcode.ALL_FORMATS)
                .build();
        cameraSource = new CameraSource.Builder(AddScanningActivity.this, barcodeDetector)
                .setAutoFocusEnabled(true)
                .setRequestedPreviewSize(width, height)
                .build();
        barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
            @Override
            public void release() {

            }

            @Override
            public void receiveDetections(Detector.Detections<Barcode> detections) {
                final SparseArray<Barcode> barcodes = detections.getDetectedItems();
                if (barcodes.size() != 0) {
                    Vibrator vibrator = (Vibrator) getApplicationContext().getSystemService(VIBRATOR_SERVICE);
                    vibrator.vibrate(100);

                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        @Override
                        public void run() {
                            cameraSource.release();
                        }
                    });
                }
            }
        });
        cameraPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                            ActivityCompat.requestPermissions(AddScanningActivity.this,
                                    new String[]{Manifest.permission.CAMERA}, requestCameraPermissionID);
                            return;
                        }
                        try {
                            cameraSource.start(cameraPreview.getHolder());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }, 100);
            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

            }

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

    private Integer getSurfaceViewHeight() {
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        Integer screenHeight = size.y;

        Rect rectangle = new Rect();
        Window window = getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
        final int statusBarHeight = rectangle.top;

        int[] attrs = new int[]{R.attr.actionBarSize};
        TypedArray ta = this.obtainStyledAttributes(attrs);
        final int actionBarHeight = ta.getDimensionPixelSize(0, -1);
        ta.recycle();
        return screenHeight - statusBarHeight - actionBarHeight;
    }

    private Integer getSurfaceViewWidth() {
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        return size.x;
    }
}
BramH
  • 221
  • 5
  • 24

1 Answers1

0

The problem was that the receiveDetections method was called a second time before the cameraSource was released. Then the second time it was called, the method tried to release the cameraSource again, but it was not available anymore, resulting in an error. Below is the working code, which only has a minor simple change, namely the use of the Boolean 'codeDetected':

public class AddScanningActivity extends AppCompatActivity {

    SurfaceView cameraPreview;
    BarcodeDetector barcodeDetector;
    CameraSource cameraSource;
    final Integer requestCameraPermissionID = 1001;
    Boolean codeDetected = false;

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

        final int height = getSurfaceViewHeight();
        final int width = getSurfaceViewWidth();

        cameraPreview = findViewById(R.id.surfaceview_scanner);

        barcodeDetector = new BarcodeDetector.Builder(AddScanningActivity.this)
                .setBarcodeFormats(Barcode.ALL_FORMATS)
                .build();
        cameraSource = new CameraSource.Builder(AddScanningActivity.this, barcodeDetector)
                .setAutoFocusEnabled(true)
                .setRequestedPreviewSize(width, height)
                .build();
        barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
            @Override
            public void release() {

            }

            @Override
            public void receiveDetections(Detector.Detections<Barcode> detections) {
                    final SparseArray<Barcode> barcodes = detections.getDetectedItems();
                    if (barcodes.size() != 0 && !codeDetected) {
                        codeDetected = true;
                        Vibrator vibrator = (Vibrator) getApplicationContext().getSystemService(VIBRATOR_SERVICE);
                        vibrator.vibrate(100);

                        Handler handler = new Handler(Looper.getMainLooper());
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                cameraSource.release();
                            }
                        });
                    }
            }
        });
        cameraPreview.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder surfaceHolder) {
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                            ActivityCompat.requestPermissions(AddScanningActivity.this,
                                    new String[]{Manifest.permission.CAMERA}, requestCameraPermissionID);
                            return;
                        }
                        try {
                            cameraSource.start(cameraPreview.getHolder());
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }, 100);
            }

            @Override
            public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

            }

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

    private Integer getSurfaceViewHeight() {
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        Integer screenHeight = size.y;

        Rect rectangle = new Rect();
        Window window = getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
        final int statusBarHeight = rectangle.top;

        int[] attrs = new int[] {R.attr.actionBarSize};
        TypedArray ta = this.obtainStyledAttributes(attrs);
        final int actionBarHeight = ta.getDimensionPixelSize(0, -1);
        ta.recycle();
        return screenHeight - statusBarHeight - actionBarHeight;
    }

    private Integer getSurfaceViewWidth() {
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        return size.x;
    }
}
BramH
  • 221
  • 5
  • 24