Skip to content

Barcode Scanner

The FioriBarcodeScannerBox and FioriBarcodeScannerDialog are composable functions implemented based on CameraX and Google's MLKit barcode scanning library. They handle the camera stream and image transformation for barcode detection in real-time. They support three scan modes:

  • Single mode detects one barcode at a time.

  • Multi mode detects multiple barcodes at a time.

  • Multi-image mode returns the captured images to the client code when multiple barcodes are detected and scanned.

Both composable functions provide optional parameters so that developers can leverage the following features

  • Developers can determine whether to use the Region of Interest(ROI) and display detection bounding box in OverlayConfig. With ROI, only the image within the region of interest will be applied to detection. Once the detection bounding box is turned on, the recognized barcode will be marked on camera preview. See "OverlayConfig" for additional information.

  • BarcodeConfig allows users to configure the detection processor itself, including the ability to turn on auto-focus and specify supported barcode formats. See "BarcodeConfig" for additional information.

  • AssociatedHyperlink is a container that allows user to place hints in the preview screen. Developers may bind highlighted keywords to a hyperlink. See "Hyperlink" for additional information.

  • Barcode validation ensures the barcodes match certain validation criteria. See "Validation Support" for additional information.

Setting up FioriBarcodeScanner

Set up FioriBarcodeScannerBox using something similar to the following sample code:

  • Using default configurations for FioriBarcodeScannerBox:

    FioriBarcodeScannerBox(
        detectorListener = object :OnMultiBarCodeDetectorListener {
            override fun onBarcodeDetected(barcode: String) {
            }
        }
    )
    

    onBarcodeDetected(barcode:String) is called back once a barcode has been found within preview (or ROI).

  • Applying configurations and validator to FioriBarcodeScannerBox:

    FioriBarcodeScannerBox(
        overlayConfig = OverlayConfig.Builder().build(), // Set up overlay configuration here.
    
        hyperlink = AssociatedHyperlink.Builder().build(), // Set up customized hint and corresponding hyperlink here.
    
    
        barcodeConfig =BarcodeConfig.Builder().build(), // Set up barcode scanning processor configuration here.
    
        permissionDeniedCallback ={
            // This will be triggered if the user has denied the granting of permission for the camera for barcode scanner.
            // Dismiss the box in the function.
        },
    
        onDismissRequest ={
            // This will be triggered if user has clicked the Cancel button on the top left of FioriBarcodeScanningBox.
            // Dismiss the box in the function.
        }, // If this parameter is set to null, the cancel box will not be rendered on the top left of FioriBarcodeScanningBox.
    
    
        barcodeValidator = object:BarcodeValidator{
            override fun isValid(barcode: String): Boolean {
                return false // write your own rules here to check whether the result string is valid or not.
            }
        },
    
        detectorListener = object :OnMultiBarCodeDetectorListener {
                override fun onBarcodeDetected(barcode: String) {
                    // Handle detection result here
                    // This will only be triggered if single mode is configured in 'barcodeConfig'
                }
    
                override fun onBarcodeNotFound():Boolean{ // This implementation is optional
                    // This callback will be triggered if a barcode is not found by the processor after a user clicks the 'Choose Picture' button.
                    return false // May also return 'true' to intercept further internal processing.
                }
    
    
                override fun onMultiBarcodeDetected(barcodes:List<Barcode>){ // This implementation is optional
                    // This callback will only be triggered when multi mode is turned on in 'barcodeConfig' and one or more barcodes are found in the preview image
                    // Handle detection result here.
                }
    
                override fun onMultiBarcodeCaptured(barcodeBitmap: Bitmap,barcodes:List<Barcode>){ // This implementation is optional
                    // This callback is only triggered when image mode is turned on in 'barcodeConfig' and one or more barcodes are found in preview image or ROI.
                    // Barcodes found in the image along with the preview image processed by the barcode processor will be available in this callback.
                    // Handle the detection result here.
    
                }
            }
        )
    

The differences between FioriBarcodeScannerDialog and FioriBarcodeScannerBox are that there is no modifier in the dialog function and there is a Boolean parameter in the dialog function to control whether to display the dialog.

FioriBarcodeScannerDialog is a pop-up that is rendered full-screen, whereas FioriBarcodeScannerBox is a layout composable that contained by a box composable layout and the placement and measurement can be modified using 'modifier' parameter.

This is the scanner box with multi mode enabled. Box


This is the scanner dialog with ROI Dialog

OverlayConfig

Use the OverlayConfig class to configure the UI features of the barcode scanner overlay mask. Developers may build their own configuration using something similar to the following sample codes:

 val overlayConfig = OverlayConfig.Builder()
    .showMask(true) // Determine wheter to turn on the Region of Interest(ROI) in the center of the screen,
    //Use 'true'(the default value) to turn on ROI, 'false' to turn ROI off

    .setFrameRadius(150.dp) // Set the radius of the ROI box. The default value is '150.dp'.

    .showBounds(false) // Determine whether to display the rectangles tracking the barcodes in preview.
    //Use 'true' to display bounds, 'false' (the default value) to turn bounds off.

    .setBoundsStroke(1.dp) //Set the stroke width of the rectangles tracking the barcodes. The default value is '1.dp'.

    .setInvalidBoundColor(Color.Green) // Set the color of the bounds of the rectangles tracking barcodes that do not pass the validation.
    // The default value is 'Color.Green'.

    .setValidBoundColor(Color.Red) // Set the color of the bounds of the rectangles tracking barcodes that pass the validation,
    // The default value is 'Color.Red'.

    .build()

BarcodeConfig

Use BarcodeConfig class to configure different capabilities for the BarcodeScanner internal processor.

val barcodeConfig = BarcodeConfig.Builder()
    .setAutoFocus(true) //Determine whether to turn auto-focus on or not. This does not work if auto-focus is not supported.
    // This is turned on by default.

    .setBarCodeFormat(Barcode.FORMAT_ALL_FORMATS) // Set the barcode formats that can be recognized.
    // Formats can be combined using an 'or' operation

    .setScanInterval(150) // Set scan interval in milliseconds (as detection performance can vary on different devices).
    // To reduce the volume of the detection queue, make sure you are using the proper values under different conditions.

    .isSupportMultiMode(false)
    .isSupportImageMode(false) // If multi mode is turned on, all barcodes within the preview frame will be called back.
    // Furthermore, the image being detected will be called back, along with barcodes found within it, if image mode is turned on
    // If neither mode is turned on, only the first barcode called back in the processor will be called back to the user.
    .setLensFacing(LensFacing.BACK) // By default, the scanner uses the back camera as the input source. You can also set the front camera here, it can be set here. Note that if the specified lens is not available, scanner will choose the first available camera in the device.

    .build()

For information on valid barcode formats, see Scan barcodes with ML Kit on Android.

You can configure Hyperlink in the hint below the ROI. The highlighted hyperlink opens in an external browser.

val hint = AssociatedHyperlink.Builder()
    .appendNormalString("your own string with ") // The string appended here is the normal hint that will be displayed below the ROI.

    .appendKeyword(keyword ="hyperlink", url="https://www.sap.com" )
    // The keyword is appended in the chain and the URL is bounded with the hyperlink.

    .setHyperlinksForKeywords(keyword = "own", url="https://help.sap.com" )
    // The keyword will be scanned in the appended string.
    // The keyword that matches the keyword parameter will be highlighted as a hyperlink bounded with the URL.

Validation Support

FioriBarcodeScannerBox and FioriBarcodeScannerDialog allow the client code to provide a validator for the value of each barcode and display a colored rectangle around the barcode, indicating whether validation was successful or not.

You can customize the colors for successful and failed validations using "Overlayconfig".

val barcodeValidator = object:BarcodeValidator{
    override fun isValid(barcode: String): Boolean {
        // Determine which kind of barcode is valid.
        return false // If 'false' is returned, the barcode is not valid. If 'true', the barcode is valid.
    }
}

Last update: February 20, 2023