How to get detected barcode/QR automatically

JerabekJakub picture JerabekJakub · Oct 27, 2015 · Viewed 7.8k times · Source

I have tried new Google Play Services feature - Barcode/QR scanner. In sample application is scanning started by taping on button and result is returned also on tap.

Is there a way to change its behavior to return first detected barcode/QR immediately?

I am not the first one curious about this.

Thank you in advance.

Answer

Tsuharesu picture Tsuharesu · Feb 22, 2016

I would advice against creating static variables. They will bite you later.
My recommendation is to create some kind of listener/callback on your TrackerFactory and use it on your Trackers. This is the pattern that Fragments, Adapters and plenty of other Android classes use, so why not copy them?

Step 1: Create an Interface in your BarcodeGraphicTracker (code for parts that changed): Here listener is initialised which sends the final callback response upon first successful detection, back to Tracker Activity (one where camera first opens).

public class BarcodeGraphicTracker extends Tracker<Barcode> {
    private GraphicOverlay<BarcodeGraphic> mOverlay;
    private BarcodeGraphic mGraphic;
    private NewDetectionListener mListener;

[...]
    @Override
    public void onNewItem(int id, Barcode item) {
        mGraphic.setId(id);
        if (mListener != null) mListener.onNewDetection(item);
    }

    public void setListener(NewDetectionListener mListener) {
        this.mListener = mListener;
    }
[...]
    public interface NewDetectionListener {
        void onNewDetection(Barcode barcode);
    }
}

Step 2: Change the Constructor of your BarcodeTrackerFactory to implement the interface. The listener instance is passed on to BarcodeGraphicTracker for initialisation. Code:

public class BarcodeTrackerFactory implements MultiProcessor.Factory<Barcode> {
private BarcodeGraphicTracker.NewDetectionListener newDetectionListener;
private GraphicOverlay<BarcodeGraphic> mGraphicOverlay;

public BarcodeTrackerFactory(GraphicOverlay<BarcodeGraphic> barcodeGraphicOverlay, BarcodeGraphicTracker.NewDetectionListener listener) {
    mGraphicOverlay = barcodeGraphicOverlay;
    newDetectionListener = listener;
}

@Override
public Tracker<Barcode> create(Barcode barcode) {
    BarcodeGraphic graphic = new BarcodeGraphic(mGraphicOverlay);
    BarcodeGraphicTracker tracker = new BarcodeGraphicTracker(mGraphicOverlay, graphic);
    if (newDetectionListener != null) tracker.setListener(newDetectionListener);
    return tracker;
}
}

Final Step: In your Tracker Activity initialise detector instance with the callback. This callback can be used to listen the data from first detected Bar/QR Code.

BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(context).build();
BarcodeTrackerFactory barcodeFactory = new BarcodeTrackerFactory(graphicOverlay,
new BarcodeGraphicTracker.NewDetectionListener() {
    @Override
    public void onNewDetection(Barcode barcode) {
        Log.d("Barcode detected! - " + barcode.displayValue);

        //To send the result back to the Activity which is waiting for the result
        Intent data = new Intent();
        data.putExtra(BarcodeObject, barcode);
        setResult(CommonStatusCodes.SUCCESS, data);
        finish();
    }
 });
barcodeDetector.setProcessor(new MultiProcessor.Builder<>(barcodeFactory).build());