Search code examples
javaandroidfirebasebarcode-scannerfirebase-mlkit

How to create a modular class for barcode scanning using Firebase ML Kit


I want to create a modular class that I can use anytime I want to scan a barcode. Is this possible using Firebase ML Kit?

This is what I've got so far:

public List<FirebaseVisionBarcode> ScanBarcode(int... barcodeFormats)
{
    //region Init, config and execution of the barcode scanning
    final FirebaseVisionBarcodeDetectorOptions.Builder BUILDER =
            new FirebaseVisionBarcodeDetectorOptions.Builder();

    //Set barcode formats based on arguments
    for (int formats : barcodeFormats)
    {
        BUILDER.setBarcodeFormats(formats);
    }

    final FirebaseVisionBarcodeDetectorOptions OPTIONS = BUILDER.build();

    final FirebaseVisionImage IMAGE = FirebaseVisionImage.fromBitmap(bitmap);

    final FirebaseVisionBarcodeDetector DETECTOR = FirebaseVision.getInstance()
            .getVisionBarcodeDetector(OPTIONS);

    DETECTOR.detectInImage(IMAGE)
            .addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionBarcode>>()
            {
                @Override
                public void onSuccess(List<FirebaseVisionBarcode> _barcodes)
                {
                    barcodes = _barcodes;
                }
            })

            .addOnFailureListener(new OnFailureListener()
            {
                @Override
                public void onFailure(@NonNull Exception e)
                {
                    barcodes = new ArrayList<>();
                }
            });

    //endregion

    return barcodes;

Mostly taken from https://firebase.google.com/docs/ml-kit/

The problem here is that the listener, for the DETECTOR, is some kind of async call. Which means that it will return before onSuccess is called.

The barcode scanning part works, but I'm having a hard time wrapping it in a class of it's own.

Thanks.


Solution

  • I figured it out. Not sure if it's the best approach class structure wise, but it works quite nice.

    public Task<List<FirebaseVisionBarcode>> ScanBarcode(int... barcodeFormats)
    {
        //region Init, config and execution of the barcode scanning. Mostly taken from https://firebase.google.com/docs/ml-kit/
        final FirebaseVisionBarcodeDetectorOptions.Builder BUILDER =
                new FirebaseVisionBarcodeDetectorOptions.Builder();
    
        //Set barcode formats based on arguments
        for (int formats : barcodeFormats)
        {
            BUILDER.setBarcodeFormats(formats);
        }
    
        final FirebaseVisionBarcodeDetectorOptions OPTIONS = BUILDER.build();
    
        final FirebaseVisionImage IMAGE = FirebaseVisionImage.fromBitmap(bitmap);
    
        final FirebaseVisionBarcodeDetector DETECTOR = FirebaseVision.getInstance()
                .getVisionBarcodeDetector(OPTIONS);
    
        final Task<List<FirebaseVisionBarcode>> DETECT_IMG_TASK = DETECTOR.detectInImage(IMAGE)
                .addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionBarcode>>()
                {
                    @Override
                    public void onSuccess(List<FirebaseVisionBarcode> _barcodes)
                    {
                        barcodes = _barcodes;
                    }
                })
    
                .addOnFailureListener(new OnFailureListener()
                {
                    @Override
                    public void onFailure(@NonNull Exception e)
                    {
                        barcodes = new ArrayList<>();
                    }
                });
    
        return DETECT_IMG_TASK;
        //endregion
    
    }
    
    public List<FirebaseVisionBarcode> GetBarcodes()
    {
        return barcodes;
    }
    

    detectInImage returns a Task. What I did was return this task. Once this task completes, you can call GetBarcodes to obtain the parsed data. I hate to force calling additional methods to get the final results, but it was the only way I could get it to work.