Barcode Scanning API Programmer's Guide

EMDK For Android 13.0

IMPORTANT: Support for SimulScan features has been removed from EMDK for Android 8.0 (and later) for devices running Android 10 (and later).


The EMDK Barcode API provides applications with the ability to read numerous barcode label formats using a variety of built-in and pluggable cameras, imagers, lasers and scanners. For the full list, see scanners supported by EMDK for Android.

Also see Barcode Sample 1 for a complete barcode scanning implementation.

Barcode API Notes

The BarcodeManager is the primary object to enumerate the supported scanner devices and access scanners for reading barcodes.

Points to consider when designing a barcode scanning app:

  • For scanning, apps should use either the EMDK barcode APIs or DataWedge but NOT both at the same time. When an EMDK app uses the barcode APIs, DataWedge is disabled until the app releases scanning resources. Here's how.
  • The EMDKManager > BarcodeManager takes precedence over DataCapture.
  • Control of scanning hardware is exclusive. When a scanning app takes control of a scanner, it must release it when quitting or going to the background before other apps can access any scanner on the device. Failure of a scanning app to release scanner resources prevents all other apps from scanning.
  • Similarly, if BarcodeManager is used in an app, it must be explicitly released before any other application (including DataWedge) can access scanning resources on the device.
  • When a scanner is disconnected and reconnected, calling any method on the barcode object results in an INVALID_OBJECT error. As a remedy, register the application for connection notifications so it can be notified of subsequent connections. Then programmatically re-initialize the scanner as needed.
  • If a Bluetooth Scanner is not paired, enabling that scanner automatically launches the pairing utility, prompting the user to scan a barcode (displayed on the mobile device) to pair the scanner with the mobile device.

Using the Barcode API

The guidance below is typical of many scenarios, but the process can vary depending individual needs.

1. Get Barcode Manager

EMDK must be opened before getting the BarcodeManager object:

    BarcodeManager barcodeManager = (BarcodeManager)emdkManager.getInstance(FEATURE_TYPE.BARCODE);

Before exiting, release the BarcodeManager object.

2. Get Scanner

There are two options for taking control of a scanner:

  1. Get Scanner using DeviceIdentifier without device enumeration:

    Use the BarcodeManager.getDevice(DeviceIdentifier deviceIdentifier) API call:

    Scanner scanner = barcodeManager.getDevice(DeviceIdentifier.BLUETOOTH_IMAGER_RS6000);

    If the specified DeviceIdentifier is not supported on the target platform, a call to getDevice will return null.

  2. Get Scanner using ScannerInfo with device enumeration:

    Use the BarcodeManager.getSupportedDevicesInfo() method first. Then pass one of the received ScannerInfo objects to BarcodeManager.getDevice(ScannerInfo scnInfo):

    List<ScannerInfo> supportedDevList = barcodeManager.getSupportedDevicesInfo();
    Scanner scanner = null;
    Iterator<ScannerInfo> it = deviceList.iterator();
        while(it.hasNext()) {
        ScannerInfo scnInfo =;
        scanner = barcodeManager.getDevice(scnInfo);

3. Use Scanner

The scanner must be enabled first to open a session with the hardware. If any scanner is enabled by another application, an exception will occur with the "scanner in use" error. Zebra recommends disabling the scanner when finished using it. Scanners otherwise remain locked by the application and are unavailable to other applications.

The Scanner.enable() method is an asynchronous call and an exception will be thrown if any error occurs during a request. After the scanner is successfully enabled, the IDLE status event is sent to the application using a registered status listener. If an error occurs while enabling the scanner, the ERROR status is sent to application using the registered status listener.

Issuing any read request while the previous read is pending will result in an error. Zebra recommends waiting for the IDLE status from the application before issuing subsequent commands to read barcodes.

4. Configure Scanner

The EMDK Barcode API provides three categories of scanner configuration to control the behavior of the scanner:

  • Decoder Parameters
  • Reader Parameters
  • Scan Parameters

An app can get current settings by calling the Scanner.getConfig() method after the scanner is successfully enabled. This method returns a ScannerConfig object.

An app can modify the ScannerConfig object returned by Scanner.getconfig. The modified ScannerConfig object must be set by calling Scanner.setConfig(ScannerConfig) before the settings will take effect. The user must call the Scanner.setConfig(ScannerConfig) only when the scanner is enabled and in an idle state. The modified settings applied will persist until the scanner object is released. This means that when an app calls enable() after disable(), all the latest configuration parameter values are set automatically.

Setting scanner configurations is not allowed while a read is pending. If a read is pending, the developer must call the Scanner.cancelRead() and wait for the idle status through the register status listener before setting the configuration.

The sample code below disables the Code 128 symbology and sets the beam timer for the imager:

    try {
            ScannerConfig scannerConfig = scanner.getConfig();
            scannerConfig.decoderParams.code128.enabled = false;

            //Set beam timer for imager
            config.readerParams.readerSpecific.imagerSpecific.beamTimer = 4000;
    } catch (ScannerException e) {
    //Error occurred and the error can be obtained by e.getResult()

Calling SetConfig() should be done in the Status callback. This allows a check that the scanner is indeed IDLE and that no scanner read is pending.

Below is an example of how that should be done:

    public void onStatus(StatusData statusData) {
            ScannerStates state = statusData.getState();
            switch(state) {
            case IDLE:
                    // call SetConfig() here

Set Decoder Parameters

The ScannerConfig.DecoderParams class provides an interface for the developer to enable or disable decoder symbologies, such as Code39, Code128, Code93, UPCEAN, etc.

The following code disables the Code128 symbology:

    scannerConfig.decoderParams.code128.enabled = false;

Set Reader Parameters

The ScannerConfig.ReaderParams class provides an interface for configuring scanner engine-specific settings for LaserSpecific, ImagerSpecific and CameraSpecific related parameters such as picklist, aim type, aim timer, beam timer, illumination mode, etc.

The following code shows how to modify the beam timer for different scanner engines:

    //Set beam timer for camera
    config.readerParams.readerSpecific. cameraSpecific.beamTimer = 4000;
    //Set beam timer for imager
    config.readerParams.readerSpecific.imagerSpecific.beamTimer = 4000;
    //Set beam timer for laser
    config.readerParams.readerSpecific.laserSpecific.beamTimer = 4000;

Set Scan Parameters

The ScannerConfig.ScanParams class provides an interface for configuring scanner parameters such as decode LED time, vibrate on successful decode, beep on successful decode, beep audio file, etc.

The following code sets the decode LED time to 75:

    config.scanParams.decodeLEDTime = 75;

5. Release Scanner

Control of scanning hardware is exclusive. When a scanning app takes control of scanning on the device, it must programmatically release it when quitting or going to the background before other apps (including DataWedge) can access any scanner on the device.

To release scanner resources, use the code below:

    // Release the barcode manager resources:
        if (emdkManager != null) {

Scanner States

The diagrams below illustrate the states that a barcode scanner will transition through while using the EMDK Barcode Scanning APIs.

Hardware Trigger


Software Trigger