Zebra Android Scanner SDK
Zebra Android Scanner SDK
1. What is Zebra Android Scanner SDK?
Zebra Android Scanner SDK is used to connect an Android app with Zebra barcode scanners.
Simple meaning:
Android App
|
Zebra Scanner SDK
|
Zebra Barcode ScannerIt helps Android apps:
- Pair scanner
- Connect scanner
- Receive barcode data
- Enable/disable scanner
- Beep scanner
- Control LED
- Handle scanner events
- Update firmwareZebra’s official guide says the SDK helps developers integrate barcode scanner functionality into Android Studio projects and provides APIs for scanner features like LED, beeper, and firmware updates.
---
2. Real Use Cases
| Use Case | Example |
|---|---|
| Warehouse | Scan product barcode |
| Retail | Scan item at billing counter |
| Logistics | Scan package/tracking ID |
| Manufacturing | Scan component serial number |
| Healthcare | Scan patient wristband |
| Inventory | Scan stock item and update quantity |
| Field service | Scan asset tag |
Example:
Worker scans product barcode
|
Zebra scanner sends barcode to Android app
|
App validates product
|
App updates inventory/server---
3. High-Level Flow
Android App
|
Add Zebra Scanner SDK AAR
|
Request Bluetooth permissions
|
Initialize SDKHandler
|
Set operation mode
|
Subscribe scanner events
|
Show Scan-To-Connect barcode
|
Scanner scans pairing barcode
|
Scanner connects to app
|
App receives barcode event
|
Process barcode data---
4. Important Classes / Concepts
| Concept | Meaning |
| --------------------------------------- | ------------------------------------- |
| `SDKHandler` | Main SDK object |
| `DCSScannerInfo` | Scanner information |
| `scannerId` | Unique scanner ID assigned by SDK |
| `IDcsSdkApiDelegate` | Callback interface for scanner events |
| `dcssdkSetOperationalMode()` | Set connection mode |
| `dcssdkSubsribeForEvents()` | Subscribe to scanner events |
| `dcssdkEstablishCommunicationSession()` | Connect scanner |
| `dcssdkTerminateCommunicationSession()` | Disconnect scanner |
| `dcssdkEventBarcode()` | Barcode received callback |Zebra docs show SDKHandler initialization, delegate setup, scanner detection, operation modes, event subscription, and barcode event callbacks through IDcsSdkApiDelegate.
---
5. Connection Types
Zebra scanner can connect mainly using:
1. Bluetooth Classic
2. Bluetooth Low Energy / BLE
3. SNAPI / Wired mode
4. Scan-To-Connect barcodeZebra docs explain that the scanner can connect using SSI BT Classic discoverable barcode or Scan-To-Connect barcode. Scan-To-Connect is easier because one scan can establish connection with both the Android device and the app.
---
6. Scan-To-Connect Meaning
What is Scan-To-Connect?
Scan-To-Connect means your Android app displays a pairing barcode. The Zebra scanner scans that barcode and connects to the app.
Simple meaning:
App shows pairing barcode
|
Scanner scans barcode
|
Scanner connects to Android appDiagram:
Android App Screen
|
Shows Scan-To-Connect Barcode
|
Zebra Scanner scans it
|
Pairing + App Connection Done---
7. Implementation Steps
Step 1: Add SDK AAR
Add Zebra Scanner SDK AAR file into your app module libs folder.
Example:
app/
libs/
barcode_scanner_library_v2.x.x.x.aarThen add it as an implementation dependency.
Zebra docs show adding barcode_scanner_library_vx.x.x.x.aar into the app module libs directory and adding it as a Jar/AAR dependency.
---
Step 2: Add Permissions
<uses-permission
android:name="android.permission.BLUETOOTH"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
android:maxSdkVersion="30" />
<uses-permission
android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />Zebra docs list Bluetooth permissions including legacy Bluetooth permissions, Android 12+ Bluetooth permissions, and location permission, and also note that BLUETOOTH_SCAN, BLUETOOTH_CONNECT, and BLUETOOTH_ADVERTISE are runtime permissions.
---
Step 3: Request Runtime Permissions
Simple flow:
App starts
|
Check Android version
|
Request Bluetooth permissions
|
If granted
|
Initialize Zebra SDKInterview point:
Do not initialize scanner connection flow before required Bluetooth permissions are granted.---
Step 4: Initialize SDK
Java-style pseudocode:
// Pseudocode: actual SDK classes are Java-based
class ZebraScannerManager(
private val context: Context
) {
private var sdkHandler: SDKHandler? = null
fun initialize() {
if (sdkHandler == null) {
sdkHandler = SDKHandler(context, true)
}
sdkHandler?.dcssdkSetDelegate(scannerDelegate)
sdkHandler?.dcssdkEnableAvailableScannersDetection(true)
sdkHandler?.dcssdkSetOperationalMode(
DCSSDKDefs.DCSSDK_MODE.DCSSDK_OPMODE_BT_NORMAL
)
subscribeEvents()
}
private fun subscribeEvents() {
var mask = 0
mask = mask or DCSSDKDefs.DCSSDK_EVENT
.DCSSDK_EVENT_SCANNER_APPEARANCE.value
mask = mask or DCSSDKDefs.DCSSDK_EVENT
.DCSSDK_EVENT_SCANNER_DISAPPEARANCE.value
mask = mask or DCSSDKDefs.DCSSDK_EVENT
.DCSSDK_EVENT_SESSION_ESTABLISHMENT.value
mask = mask or DCSSDKDefs.DCSSDK_EVENT
.DCSSDK_EVENT_SESSION_TERMINATION.value
mask = mask or DCSSDKDefs.DCSSDK_EVENT
.DCSSDK_EVENT_BARCODE.value
sdkHandler?.dcssdkSubsribeForEvents(mask)
}
}Zebra docs show initialization through SDKHandler, setting the delegate, enabling scanner detection, setting operational modes such as BT LE, BT Normal, and SNAPI, and subscribing to scanner appearance, session, and barcode events.
---
8. Operation Modes
| Mode | Meaning |
|---|---|
DCSSDK_OPMODE_BT_NORMAL | Bluetooth Classic mode |
DCSSDK_OPMODE_BT_LE | Bluetooth Low Energy mode |
DCSSDK_OPMODE_SNAPI | Wired/SNAPI scanner mode |
Simple memory:
BT_NORMAL = Bluetooth Classic
BT_LE = Bluetooth Low Energy
SNAPI = Wired scanner mode---
9. Connect Scanner
Basic flow:
Get available scanner list
|
Pick scanner
|
Get scannerId
|
Call establish communication session
|
Receive session established callbackPseudocode:
fun connectScanner() {
val scanners = ArrayList<DCSScannerInfo>()
sdkHandler?.dcssdkGetAvailableScannersList(scanners)
if (scanners.isNotEmpty()) {
val scannerId = scanners[0].scannerID
// Run on background thread/coroutine
sdkHandler?.dcssdkEstablishCommunicationSession(scannerId)
}
}Zebra docs use dcssdkGetAvailableScannersList() to fill scanner information and dcssdkEstablishCommunicationSession(scannerId) to make the scanner connection.
---
10. Disconnect Scanner
fun disconnectScanner() {
val activeScanners = ArrayList<DCSScannerInfo>()
sdkHandler?.dcssdkGetActiveScannersList(activeScanners)
if (activeScanners.isNotEmpty()) {
val scannerId = activeScanners[0].scannerID
sdkHandler?.dcssdkTerminateCommunicationSession(scannerId)
}
}Zebra docs recommend using dcssdkTerminateCommunicationSession(scannerId) to disconnect the scanner instead of closing the entire SDK handler, so the same SDKHandler can be reused.
---
11. Receive Barcode Data
When barcode is scanned, SDK callback is triggered.
private val scannerDelegate = object : IDcsSdkApiDelegate {
override fun dcssdkEventBarcode(
barcodeData: ByteArray,
barcodeType: Int,
fromScannerID: Int
) {
val scannedValue = String(barcodeData)
Log.d("ZEBRA", "Barcode: $scannedValue")
// Send to ViewModel / Repository Flow
}
override fun dcssdkEventCommunicationSessionEstablished(
activeScanner: DCSScannerInfo
) {
Log.d("ZEBRA", "Scanner connected")
}
override fun dcssdkEventCommunicationSessionTerminated(
scannerID: Int
) {
Log.d("ZEBRA", "Scanner disconnected")
}
}Zebra docs define dcssdkEventBarcode(byte[] barcodeData, int barcodeType, int fromScannerID) as the barcode event notification that provides scanned barcode data, barcode type, and scanner ID.
---
12. Enable / Disable Scanner
Use this when you want to control scanning from the app.
Enable scanner = scanner can scan barcode
Disable scanner = scanner cannot scan barcodePseudocode:
fun enableScanner(scannerId: Int) {
val inXml = """
<inArgs>
<scannerID>$scannerId</scannerID>
</inArgs>
""".trimIndent()
val outXml = StringBuilder()
sdkHandler?.dcssdkExecuteCommandOpCodeInXMLForScanner(
DCSSDKDefs.DCSSDK_COMMAND_OPCODE.DCSSDK_DEVICE_SCAN_ENABLE,
inXml,
outXml
)
}Zebra docs show enabling the scanner using the DCSSDK_DEVICE_SCAN_ENABLE opcode and disabling barcode scanning using the corresponding scanner command.
---
13. SDK Close vs Scanner Disconnect
| Action | Meaning | When to Use |
| ------------------------------------------------ | ------------------------------------------- | ----------------------------------- |
| `dcssdkTerminateCommunicationSession(scannerId)` | Disconnect scanner session | Normal disconnect |
| `dcssdkClose()` | Close SDK handler and cleanup SDK resources | App shutdown / SDK no longer needed |Important:
For normal scanner disconnect, use terminate communication session.
For complete cleanup, use dcssdkClose().Zebra docs state that `dcssdkClose()` unsubscribes SDK events, cleans resources, and closes the SDK instance; after calling it, SDK reinitialization is required for future events.---
14. Recommended Android Architecture
For 11+ years interview, do not keep SDK code directly inside Activity.Use this:
UI / Compose / Activity
|
ViewModel
|
Use Case
|
Repository Interface
|
Repository Implementation
|
Zebra Scanner Data Source
|
Zebra Scanner SDK
|
Scanner Device---
Package Structure
feature_scanner/
presentation/
ScannerScreen.kt
ScannerViewModel.kt
ScannerUiState.kt
domain/
repository/
ScannerRepository.kt
usecase/
InitializeScannerSdkUseCase.kt
ConnectScannerUseCase.kt
DisconnectScannerUseCase.kt
EnableScannerUseCase.kt
DisableScannerUseCase.kt
ObserveBarcodeUseCase.kt
data/
ZebraScannerRepositoryImpl.kt
ZebraScannerDataSource.kt
MockScannerDataSource.kt---
15. UI State Example
sealed interface ScannerUiState {
data object Idle : ScannerUiState
data object PermissionRequired : ScannerUiState
data object SdkInitializing : ScannerUiState
data object WaitingForScanner : ScannerUiState
data object Connecting : ScannerUiState
data object Connected : ScannerUiState
data object Disconnected : ScannerUiState
data class BarcodeScanned(
val value: String,
val barcodeType: Int
) : ScannerUiState
data class Error(val message: String) : ScannerUiState
}---
16. Repository Interface
interface ScannerRepository {
fun observeScannerState(): Flow<ScannerConnectionState>
fun observeBarcodeData(): Flow<ScannedBarcode>
suspend fun initializeSdk()
suspend fun connectScanner()
suspend fun disconnectScanner()
suspend fun enableScanner()
suspend fun disableScanner()
suspend fun closeSdk()
}---
17. Data Model
data class ScannedBarcode(
val value: String,
val barcodeType: Int,
val scannerId: Int,
val scannedAt: Long = System.currentTimeMillis()
)---
18. ViewModel Example
class ScannerViewModel(
private val scannerRepository: ScannerRepository
) : ViewModel() {
private val _uiState =
MutableStateFlow<ScannerUiState>(ScannerUiState.Idle)
val uiState: StateFlow<ScannerUiState> = _uiState
init {
observeBarcode()
observeScannerState()
}
fun initialize() {
viewModelScope.launch {
try {
_uiState.value = ScannerUiState.SdkInitializing
scannerRepository.initializeSdk()
_uiState.value = ScannerUiState.WaitingForScanner
} catch (e: Exception) {
_uiState.value =
ScannerUiState.Error(e.message ?: "SDK initialization failed")
}
}
}
fun connect() {
viewModelScope.launch {
_uiState.value = ScannerUiState.Connecting
scannerRepository.connectScanner()
}
}
private fun observeBarcode() {
viewModelScope.launch {
scannerRepository.observeBarcodeData().collect { barcode ->
_uiState.value = ScannerUiState.BarcodeScanned(
value = barcode.value,
barcodeType = barcode.barcodeType
)
}
}
}
private fun observeScannerState() {
viewModelScope.launch {
scannerRepository.observeScannerState().collect { state ->
_uiState.value = when (state) {
ScannerConnectionState.Connected -> ScannerUiState.Connected
ScannerConnectionState.Disconnected -> ScannerUiState.Disconnected
ScannerConnectionState.Waiting -> ScannerUiState.WaitingForScanner
}
}
}
}
}---
19. Zebra Scanner SDK vs DataWedge
This is important for interviews.
DataWedge
DataWedge is available out-of-the-box on Zebra Android devices and can send captured barcode data to apps without directly using scanner APIs. It can output scanned data as keystrokes or intents and can be configured with profiles.
Scanner SDK
Scanner SDK is useful when you need direct control of an external Zebra scanner from your Android app.
| Topic | Zebra Scanner SDK | Zebra DataWedge |
|---|---|---|
| Best for | Direct scanner integration/control | Quick scan data capture |
| Coding required | Yes | Less or no code |
| Works with | Zebra barcode scanners | Zebra Android mobile computers and peripherals |
| Control scanner | Yes, more control | Limited/configuration based |
| Events | SDK callbacks | Intents/keystrokes |
| Features | Connect, disconnect, barcode, beeper, LED, firmware | Capture and route data |
| Architecture | SDK wrapper/repository | Broadcast receiver/profile |
| Interview keyword | SDKHandler, IDcsSdkApiDelegate | Profiles, Intent Output |
Simple memory:
DataWedge = easiest way to get scan data on Zebra Android devices
Scanner SDK = more control over scanner connection and scanner features---
20. Pros and Cons
Pros
| Pros | Explanation |
|---|---|
| Direct scanner control | Connect, disconnect, enable, disable |
| Barcode event callbacks | App receives barcode data directly |
| Supports scanner features | Beeper, LED, firmware update |
| Good for enterprise apps | Warehouse, retail, logistics |
| Supports external scanners | Useful beyond built-in scanner flow |
Cons
| Cons | Explanation |
|---|---|
| More implementation effort | Need SDK setup and lifecycle handling |
| Bluetooth permission complexity | Android 12+ runtime permissions |
| Hardware dependency | Need Zebra scanner for full testing |
| SDK-specific knowledge | Need Zebra APIs and XML commands |
| More error handling | Pairing, disconnect, reconnect, scanner unavailable |
---
21. Common Mistakes
1. Calling Zebra SDK directly from Activity.
2. Not requesting Android 12+ Bluetooth permissions.
3. Not handling scanner disconnect.
4. Not unsubscribing/closing SDK resources.
5. Confusing DataWedge with Scanner SDK.
6. Not using background thread for connection/commands.
7. Assuming only one scanner is always connected.
8. Not validating scanned barcode before using it.
9. Logging sensitive barcode data.
10. Not testing scan failure and reconnect cases.---
22. Interview Questions and Answers
Q1. What is Zebra Android Scanner SDK?
> Zebra Android Scanner SDK is used to connect and control Zebra barcode scanners from an Android app. It provides APIs for pairing, connecting, receiving barcode events, enabling/disabling scanning, beeper/LED operations, and firmware-related operations.
Q2. How do you connect a Zebra scanner?
> First I add the SDK AAR and required Bluetooth permissions. After runtime permission approval, I initialize SDKHandler, set the operation mode such as BT Classic or BLE, subscribe to scanner events, get available scanners, and call dcssdkEstablishCommunicationSession(scannerId).
Q3. How do you receive barcode data?
> I implement IDcsSdkApiDelegate and handle dcssdkEventBarcode(). This callback gives barcode bytes, barcode type, and scanner ID. I convert the byte array to a string, validate it, then pass it to ViewModel/domain layer.
Q4. What is Scan-To-Connect?
> Scan-To-Connect is a Zebra pairing approach where the Android app displays a pairing barcode. The scanner scans that barcode and connects to the Android device and app.
Q5. Difference between DataWedge and Scanner SDK?
> DataWedge is easier and usually requires less code because it routes captured data to apps through profiles, keystrokes, or intents. Scanner SDK is better when the app needs direct scanner control, scanner events, connection management, beeper/LED, or firmware operations.
Q6. How would you design this in Clean Architecture?
> I would keep Zebra SDK calls inside a data source. The repository would expose scanner state and barcode data as Flow. Use cases would handle connect, disconnect, enable, disable, and observe barcode. ViewModel would expose UI state using StateFlow.
Q7. How do you handle scanner disconnect?
> I handle session termination callbacks, update UI state, clear active scanner information, and allow user-controlled reconnect. For automatic reconnect, I use limited retry/backoff and avoid infinite background loops.
Q8. What permissions are required?
> For Android 12+, Bluetooth scan/connect/advertise permissions are required at runtime. For older Android versions, legacy Bluetooth permissions are used with maxSdkVersion=30. Location permission may also be needed depending on scan behavior.
---
23. Final Revision Diagram
Zebra Scanner SDK
|
+-- Add AAR
+-- Add Bluetooth permissions
+-- Initialize SDKHandler
+-- Set operational mode
+-- Subscribe events
+-- Show Scan-To-Connect barcode
+-- Connect scanner
+-- Receive barcode callback
+-- Process scanned data
+-- Disconnect / close SDK---
24. Final Interview Pitch
> Zebra Android Scanner SDK is used when an Android app needs direct control over Zebra barcode scanners. I would add the SDK AAR, request Bluetooth permissions, initialize SDKHandler, set the required operation mode, subscribe to scanner events, and connect using dcssdkEstablishCommunicationSession. Barcode data is received through dcssdkEventBarcode. For senior-level design, I would wrap the SDK inside a repository/data-source layer and expose scanner state and barcode events using Flow/StateFlow. I would also handle permission denial, scanner disconnect, SDK cleanup, reconnect, and barcode validation carefully.