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.
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 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 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);