Skip to content

Barcode and QR Code Scan

SAP BTP SDK for Android supports scanning with the camera, the device built-in scanner, the IPCMobile scanner connected to device via the QWedge app, and a Bluetooth scanner. When scanning with the camera, a screen is provided to open the camera for scanning. When scanning with the device built-in scanner and the IPCMobile scanner, a set of APIs are provided for the client code to trigger a scan and get the scan result. Bluetooth scanners are only supported when they are connected to an Android device in the form of a keyboard. An API is provided to check whether the keyboard input is from a Bluetooth scanner or not, and it will return the scan result to the client code via a callback function.

QR Code View

The QRCode view is based on Google's CameraX and ML Kit barcode scanning libraries. It handles the camera stream and image transformation for barcode detection in real-time. It supports three scan modes: single, multi, and multi-image mode:

  • 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.

In addition, the QRCode view provides extension functions, such as customized view, gesture operation, auto flash, and barcode validation.

  • Customized view allows you to customize QRCode view using XML attributes. See "Custom QR Code View" for additional information.
  • Gesture operation allows the user to zoom in and out on a barcode image. See "Gesture Operations" for additional information.
  • URL link option allows the user to define a keyword and URL in the XML attributes. When the keyword is clicked, the page at that URL is displayed. See "URL Link Option" for additional information.
  • Auto flash allows user to enable flash when the ambient light is insufficient, illuminating the barcode. See "Auto Flash Option" for additional information.
  • Barcode validation ensures the barcode matches certain validation criteria. See "Validation Support" for additional information.

QR Code View QR Code View

Setting up QRCode View

Set up QRCode view using the following procedure.

  • Declare the QRCodeReaderScreen in the layout of your activity or fragment.
<com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen
          android:id="@+id/qr_reader"
          android:layout_width="match_parent"
          android:layout_height="match_parent">
</com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen>
  • Gets the instance of QRCodeReaderScreen.
var qrcodeScreen = findViewById<`QRCodeReaderScreen`>(R.id.qr_reader)
QRCodeReaderScreen qrcodeScreen = findViewById(R.id.qr_reader);
  • Configure the QRCode view using QRCodeConfig.

Note

QRCodeConfig is optional. The QRCode view provides a default value.

// New instance of QRCodeConfig.
var qrCodeConfig = QRCodeConfig.Builder()
    // Set up the barcode format. The default value is Barcode.FORMAT_QR_CODE.
    .setBarCodeFormat(Barcode.FORMAT_ALL_FORMATS)
    // Set up the camera scan interval. The default value is 16 milliseconds.
    .setScanInterval(50)
    // Set up camera auto-focus. The default value is true.
    .setAutoFocus(true)
    .build()
// Set the config to qrcodeScreen.
qrcodeScreen.setQRConfig(qrCodeConfig)
// New instance of QRCodeConfig.
QRCodeConfig qrCodeConfig = new QRCodeConfig.Builder()
    // Set up the barcode format. The default value is Barcode.FORMAT_QR_CODE.
    .setBarCodeFormat(Barcode.FORMAT_ALL_FORMATS)
    // Set up the camera scan interval. The default value is 16 milliseconds.
    .setScanInterval(50)
    // Set up camera auto-focus. The default value is true.
    .setAutoFocus(true)
    .build();
// Set the config to qrcodeScreen.
qrcodeScreen.setQRConfig(qrCodeConfig);
  • Configure the barcode detector listener to get the barcode scan result.
qrcodeScreen.setBarCodeListener(this, object: QRCodeReaderScreen.OnMultiBarCodeDetectorListener {
    override fun onBarcodeDetected(barcode: String?) {
        //handle single barcode scan result
    }

    override fun onMultiBarcodeDetected(barcodes: MutableList<String>?) {
        //handle multi barcodes scan result
    }

    override fun onMultiBarcodeCaptured(barcodesBitMap: Bitmap?, barcodes: MutableList<Barcode>?) {
        //handle the captured image and multi barcodes scan result
    }

})
qrcodeScreen.setBarCodeListener(this, new QRCodeReaderScreen.OnMultiBarCodeDetectorListener() {
    @Override
    public void onBarcodeDetected(String barcode) {
        //handle single barcode scan result
    }

    @Override
    public void onMultiBarcodeDetected(List<String> barcodes) {
        //handle multi barcodes scan result
    }

    @Override
    public void onMultiBarcodeCaptured(Bitmap barcodesBitMap, List<String> barcodes) {
        //handle the captured image and multi barcodes scan result
    }
});

Switch Scan Modes

The user can switch among single-, multi-scan and multi-image mode using QRCodeConfig.

Enable multi-scan mode.

QRCodeConfig codeConfig = new QRCodeConfig.Builder()
    .setBarCodeFormat(Barcode.FORMAT_ALL_FORMATS)
    .isSupportMultiMode(true).build();
// refresh the config to qrcodeScreen.
qrcodeScreen.setQRConfig(qrCodeConfig);
val codeConfig = QRCodeConfig.Builder()
    .setBarCodeFormat(Barcode.FORMAT_ALL_FORMATS)
    .isSupportMultiMode(true).build();
// refresh the config to qrcodeScreen.
qrcodeScreen.setQRConfig(qrCodeConfig);

Enable multi-image mode.

QRCodeConfig codeConfig = new QRCodeConfig.Builder()
    .setBarCodeFormat(Barcode.FORMAT_ALL_FORMATS)
    .isSupportImageMode(true).build();
// refresh the config to qrcodeScreen.
qrcodeScreen.setQRConfig(qrCodeConfig);
val codeConfig = QRCodeConfig.Builder()
    .setBarCodeFormat(Barcode.FORMAT_ALL_FORMATS)
    .isSupportImageMode(true).build();
// refresh the config to qrcodeScreen.
qrcodeScreen.setQRConfig(qrCodeConfig);

Custom QRCode View

Note

All the XML attributes have default values.

<com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen
          android:id="@+id/qr_reader"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:isShowFrameContainer="true"
          app:isDrawMask="true"
          app:isShowScanAnimation="true"
          app:frameCornerLineColor="@color/onboarding_blue_50"
          app:frameContainerRatio="0.5"
          app:isShowHintText="true"
          app:hintText="Position QR code or barcode in this frame"
          app:frameCornerLength="30dp"
          app:frameCornerLineWidth="4dp"
          app:isAutoShowFlash="true"
          app:isDrawKeywordUnderLine="true"
          app:urlKeyword="this"
          app:urlLink="http://www.sap.com" />
</com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen>

The following table shows all the available XML attributes of custom QRCode and their explanations.

XML attributes
app:isDrawMask Draw the mask outside of the frame container
app:maskColor The mask color
app:isAutoShowFlash Auto show flash icon according to ambient light
app:isShowScanAnimation Whether to show scan animation
app:scanLineHeight Scan line height
app:isShowFrameContainer Whether to show the frame container
app:frameCornerLineColor Frame container corner line color
app:frameContainerRatio The ratio of frame container width in screen width
app:frameCornerLength Frame container corner line length
app:frameCornerLineWidth Frame container corner line width
app:frameContainerCornerRadius Frame container corner radius
app:frameContainerLineColor Frame container line color
app:frameContainerWidth Frame container width, if set, the frameContainerRatio will be ignored
app:frameContainerHeight Frame container height, if set, the frameContainerRatio will be ignored
app:isShowHintText Whether to show the hint text under the frame container
app:hintText Hint text under the frame container
app:hintTextColor Hint text color
app:hintTextSize Hint text size
app:urlKeyword URL keyword in hint text
app:urlLink Keyword URL link
app:keywordColor Keyword color
app:isDrawKeywordUnderLine Draw the line under the keyword
app:keywordUnderLineColor Keyword under line color
app:multiBarcodeOverlayStrokeWidth Barcode rectangle line width in multi mode
app:multiBarcodeOverlayColor Barcode rectangle color when no validator is provided
app:multiBarcodeValidColor Barcode rectangle color when validation passes
app:multiBarcodeInvalidColor Barcode rectangle color when validation fails

Close the QRCode View

To close the QRCode view, set up a click listener for the Close Image button.

qrcodeScreen.setCloseReaderButtonOnClickListener{
    finish()
}
qrcodeScreen.setCloseReaderButtonOnClickListener((view)->{
    finish();
});

Detecting a Barcode by Scanning a Saved Barcode Image

The QRCode view scans the barcode from a saved image by default. Click the photo library of QRCodeReaderScreen and select the barcode image. The result will be passed in OnMultiBarCodeDetectorListener. The developer does not need handle this part of the code.

Re-Scan Option

The QRCode view provides a re-scan option, where you can decide to stop or restart the barcode scanning process.

// Stop the barcode scan.
qrcodeScreen.stopScan()
// Restart the barcode scan.
qrcodeScreen.reStartScan()
// Stop the barcode scan.
qrcodeScreen.stopScan();
// Restart the barcode scan.
qrcodeScreen.reStartScan();

Gesture Operation

The QRCode view supports gesture operation, meaning that the user can zoom in or out to adjust the barcode distance. The user double-clicks to zoom in or out.

The QRCode view supports a URL link option, allowing the user to define a keyword and URL in the XML attributes. The user can then click the keyword and the page at that URL is displayed.

Note

The URL link can only be specified if the hint text is set up and also contains the keyword.

<com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen
          android:id="@+id/qr_reader"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:isShowHintText="true"
          app:hintText="Position QR code or barcode in this frame"
          app:isDrawKeywordUnderLine="true"
          app:urlKeyword="this"
          app:urlLink="http://www.sap.com" />
</com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen>

Auto Flash Option

The QRCode view supports an auto flash option, where the flash icon will be displayed when the ambient light is insufficient to illuminate the barcode properly. The user can then enable or disable the flash using the icon.

<com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen
          android:id="@+id/qr_reader"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:isAutoShowFlash="true" />
</com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen>

Validation Support

The QRCode view allows 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. The colors for successful and failed validations can be customized when the QRCode view is defined.

// Add validation for barcode value.
qrcodeScreen.setBarCodeValidator(
    object : QRCodeReaderScreen.BarCodeValidator {
        override fun isValid(barcode: String?): Boolean {
            //add validation logic
        }
    }
)
// Add validation for barcode value.
qrcodeScreen.setBarCodeValidator(new QRCodeReaderScreen.BarCodeValidator() {
    @Override
    public Boolean isValid(String barcode) {
        // add validation logic
    }
});
<com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen
          android:id="@+id/qr_reader"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          app:multiBarcodeValidColor="@color/maps_default_stroke_color"
          app:multiBarcodeInvalidColor="@color/onboarding_red_200" />
</com.sap.cloud.mobile.fiori.qrcode.QRCodeReaderScreen>

QR Code View

Built-in Scanner and IPCMobile Scanner Support

In addition to supporting scanning with a camera, SAP BTP SDK for Android provides APIs to integrate the device built-in laser scanner into your app. Currently only Zebra and Honeywell devices are supported and the API is based on the DataWedge intent-based API.

The same intent-based API is supported for the IPCMobile scanner that is connected via the QWedge app installed on the device.

The APIs include the functions to detect the enablement of built-in laser scanner, trigger a scan, and get the scan result.

Register Receiver

The ScannerUtil.registerReceivers(context: Context, listener: ScannerReceiver.OnResultReceivedListener, intentOutputAction: String) API allows client code to register a broadcast receiver for receiving data and provide its own logic when data is received. The logic is provided by implementing the ScannerReceiver.OnResultReceivedListener callback listener.

When the scan is completed, the client code should call the ScannerUtil.unRegisterReceivers(context: Context) API to unregister the broadcast receiver.

ScannerReceiver.OnResultReceivedListener listener = new ScannerReceiver.OnResultReceivedListener() {
        @Override
        public void onScannerDetected(boolean enabled) {
            //notify received barcode
            textView.setText(barcode);
        }

        @Override
        public void onBarcodeDetected(@Nullable String barcode) {
            //notify if laser scanner is enabled
            laserEnabled = enabled
        }
    };
ScannerUtil scannerUtil = new ScannerUtil();
scannerUtil.registerReceivers(this, listener, "com.fioriscan.ACTION");
val listener = object : ScannerReceiver.OnResultReceivedListener {
        //notify received barcode
        override fun onBarcodeDetected(barcode: String?) {
            textView.setText(barcode)
        }

        //notify if laser scanner is enabled
        override fun onScannerDetected(enabled: Boolean) {
            laserEnabled = enabled
        }
    }
val scannerUtil = ScannerUtil()
scannerUtil.registerReceivers(this, listener, "com.fioriscan.ACTION")

Trigger a Scan

If a built-in laser scanner is enabled on the device, the client code can trigger a scan using the ScannerUtil.startSoftScan(context: Context) API.

Tested Devices

The SDK supports all IPCMobile scanners connected via the QWedge app and all Zebra and Honeywell devices that support intent-based APIs. The SDK APIs have been tested on the IPCMobile Nexus Connect Scanner, Zebra TC520K, and Honeywell EDA51K.

Bluetooth Scanner Support

In addition to supporting scanning with a camera and built-in scanner, the SDK provides an API to integrate the Bluetooth scanner into your app. Currently, only Bluetooth scanners connected as a keyboard are supported. The API can detect whether the keyboard input is from a Bluetooth scanner or a real keyboard, and will return the scan result to the client code via a callback function.

The API supports two scanning detection modes: TIME_INTERVAL mode and PREFIX_SUFFIX mode.

  • For TIME_INTERVAL mode, the client code can specify an interval in milliseconds. If the time between two consecutive keyboard inputs is shorter than the interval, the API will treat the input as a Bluetooth scan.
  • For PREFIX_SUFFIX mode, the client code can specify a prefix and a suffix for a barcode, and an interval between the prefix and suffix. If the API detects the prefix and suffix from the keyboard input, and the time between the prefix and suffix is shorter than the specified interval, the API will treat the input as a Bluetooth scan.

Setting up BluetoothScanner Configuration

When using the BluetoothScanner class to do a Bluetooth scan, the client code can configure the scan mode and the detailed properties for each scan mode using the BluetoothConfig class.

// New instance of BluetoothConfig.
val config1 = BluetoothConfig.Builder()
    // Set up the scan mode
    .setScanMode(ScanMode.TIME_INTERVAL)
    // Set up the scan interval for each keyboard input
    .setDetectionInterval(100)
    .build()
// Set the config to BluetoothScanner.
val scanner = BluetoothScanner()
scanner.setScanProperties(config1)

val config2 = BluetoothConfig.Builder()
    // Set up the scan mode
    .setScanMode(ScanMode.PREFIX_SUFFIX)
    // Set the prefix
    .setPrefix("$")
    // Set the suffix
    .setSuffix("#")
    // Set the interval between the input of the prefix and suffix
    .setMaxPrefixSuffixInterval(5000)
    .build()
// Set the config to BluetoothScanner.
val scanner = BluetoothScanner()
scanner.setScanProperties(config2)
// New instance of BluetoothConfig.
BluetoothConfig config1 = new BluetoothConfig.Builder()
    // Set up the scan mode
    .setScanMode(ScanMode.TIME_INTERVAL)
    // Set up the scan interval for each keyboard input
    .setDetectionInterval(100)
    .build();

// Set the config to BluetoothScanner.
BluetoothScanner scanner = new BluetoothScanner();
scanner.setScanProperties(config1);

// New instance of BluetoothConfig.
BluetoothConfig config2 = new BluetoothConfig.Builder()
    // Set up the scan mode
    .setScanMode(ScanMode.PREFIX_SUFFIX)
    // Set the prefix
    .setPrefix("$")
    // Set the suffix
    .setSuffix("#")
    // Set the interval between the input of the prefix and suffix
    .setMaxPrefixSuffixInterval(5000)
    .build();

// Set the config to BluetoothScanner.
BluetoothScanner scanner = new BluetoothScanner();
scanner.setScanProperties(config2);

Note

BluetoothConfig is optional. The BluetoothScanner provides a default configuration.

Start a Bluetooth Scan

The BluetoothScanner.startScan(event: KeyEvent, bluetoothScanListener: OnBluetoothScanDetectedListener) API allows client code to receive a Bluetooth scan result and provide its own logic when data is received. The logic is provided by implementing the BluetoothScanner.OnBluetoothScanDetectedListener callback listener.

val listener = object : BluetoothScanner.OnBluetoothScanDetectedListener {
            override fun onBluetoothScanDetected(barcode: String?, keyboardInput: String?) {
                textView.setText(barcode)
            }
        }

val scanner = BluetoothScanner()
scanner.startScan(event, listener)
BluetoothScanner.OnBluetoothScanDetectedListener listener = new BluetoothScanner.OnBluetoothScanDetectedListener() {
        @Override
        public void onBluetoothScanDetected(@Nullable String barcode, @Nullable String keyboardInput) {
            textView.setText(barcode);
        }
    };

BluetoothScanner scanner = new BluetoothScanner();
scanner.startScan(event, listener);

Last update: February 29, 2024