Barcode and QR Code Scan¶
SAP BTP SDK for Android supports scanning with the following devices:
- Camera
- Device built-in scanner
- Bluetooth scanner
IPCMobilescanner connected to a device via theQWedgeappProGlovescanner connected to a device via theInsight MobileappKnox Captureapp scanning onSamsung XCoverdevices
When scanning with the camera, a screen is provided to open the camera for scanning.
A set of APIs is provided for client code to trigger scans and retrieve scan results from the device's built-in scanner or third-party scanners, such as IPCMobile, ProGlove, and the Knox Capture app scanner.
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
QRCodeview 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.

Setting up QRCode View¶
Set up QRCode view using the following procedure.
- Declare the
QRCodeReaderScreenin 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
QRCodeview usingQRCodeConfig.
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.
URL Link Option¶
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>

Built-in Scanner, IPCMobile Scanner, ProGlove Scanner Support and Knox Capture App 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 connected via the QWedge app, the ProGlove scanner connected to the device via the Insight Mobile app installed on the device, and the Knox Capture app scanning on SamSung XCover device.
The APIs include the functions to detect the enablement of built-in laser scanner, trigger a scan, and retrieve the scan result. Additionally, for the IPCMobile scanner and ProGlove scanner, there is an extra API to detect if the QWedge app and the Insight Mobile app are installed on the device.
Note
Detecting App info on the device may cause privacy issues. To support IPCMobile scanner and ProGlove scanner, the client code needs to explicitly depend on the module including the app detection API and declare the possible App info detection in privacy notice if necessary.
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 check whether soft scan is enabled on the device by calling the ScannerUtil.isSoftScanSupport(context: Context) API and triggering a scan using the ScannerUtil.startSoftScan(context: Context) API.
Detect Support for Companion Scanners¶
The Companion scanner connects to a device through a third-party application provided by the scanner vendor, which must be installed on the device. The SDK now supports IPCMobile and ProGlove scanners.
To support IPCMobile and ProGlove scanners, the device must install the QWedge app to connect to IPCMobile scanner and the Insight Mobile app to connect to ProGlove scanner.
To avoid potential privacy issues, the SDK has placed the API for detecting app installations in a separate module. If the client needs scanner support, they must explicitly depend on the module com.sap.cloud.android:companion-scanner-detect and invoke the CompanionScannerDetectUtil.requestScannerStatus(context: Context) API before using the scan API.
Set Screen for ProGlove Scanners¶
For ProGlove scanners with a display screen, the client code can set the display screen by calling the ScannerUtil.sendScreenToProGlove(context: Context, id: String, content: String, rightHeaders: String?, separator: String, durationMs: Int = 0, refreshType: String? = null) API.
Multiple Barcodes Scanning Support for Knox Capture App¶
The Knox Capture app supports scanning multiple barcodes. The receiver callback listener returns all scanned barcodes in a string, separated by commas.
Tested Devices¶
The SDK supports all IPCMobile scanners connected via the QWedge app, all ProGlove scanners connected via the Insight Mobile app, all Samsung XCover devices with the Knox Capture apps installed, and all Zebra and Honeywell devices that support intent-based APIs.
The SDK APIs have been tested on the following devices:
IPCMobile Nexus Connect ScannerProGlove MARK 3ProGlove MARK DisplayGalaxy XCover7Galaxy Tab Active5Zebra TC520KHoneywell 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_INTERVALmode, 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_SUFFIXmode, 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);