Life at PharmEasy Stories by PharmEasy

Barcode Reader Android App With Data Wedge APIs In Zebra Devices.

Barcode Reader Android App With Data Wedge APIs In Zebra Devices - PharmEasy
Click to rate this post!
[Total: 8 Average: 3.9]
Reading Time: 4 minutes

Barcode reading in Zebra Device can be done in two possible ways: 

  1.  Using EMDK
  2.  Using Datawedge APIs. (Zebra recommends the use of Datawedge) 

What is Datawedge? 

Datawedge is a popular way to access zebra device hardware with minimal code and helps in easy reading of barcode data. It offers a simple interface that is easy to use but compromises on a more fine-grained control of the hardware. However, Datawedge APIs are continuously evolving to offer more features and control. 

Using Datawedge has several advantages over EMDK. The following are the advantages: 

  1. Does not required any external dependency or library to be integrated. 
  2. Ease of integration. Continued support and improvements in Datawedge APIs. 
  3. Faster barcode reading. 

I believe that this post eases the process of integrating the zebra device barcode reading capabilities in your app as I found the official documentation to be too comprehensive and also lacks a few key information. This article will feature a really simple configuration for a zebra device to fetch the barcode data using the native scanner. 

The following are the steps to be performed to read barcode data from the barcode reader:

 I) Create a custom profile.

II) Switch to the profile.

III) Reading the barcode data via broadcast intent.

I) Create a custom profile: 

  1. Let us create a custom profile with “Test” as the profile name. We do that by sending a 

“com.symbol.datawedge.api.CREATE_PROFILE” broadcast as follows: 

fun createProfileForZebraDevice(){ 

val intent = Intent() intent.setAction(“com.symbol.datawedge.api.ACTION”) intent.putExtra(“com.symbol.datawedge.api.CREATE_PROFILE”, “Test”) sendBroadcast(intent) } 
  1. For the barcode reading, we create the barcode plugin with the help of android bundle and configure the desired parameters. To keep it simple we create a barcode plugin and reset the existing configuration. 
val barcodeBundle = Bundle() barcodeBundle.putString("PLUGIN_NAME", “BARCODE”) barcodeBundle.putString("RESET_CONFIG","true"

      3. To make it simple we will not set any additional parameter to the barcode plugin. Hence we will create a new Bundle object and name it as barcodeBundleParams. The barcodeBundleParams is set as a bundle against the barcodeBundle created above. 

val barcodeBundleParams = Bundle() barcodeBundle.putBundle(“PARAM_LIST”,barcodeBundleParams) 
  1. The “Test” profile created above should be associated with a package name and also with the activities in which this plugin is required. In this example, the barcode profile will be associated with all the activities (represented by “*”) as shown below: 
val appConfig = Bundle() appConfig.putString("PACKAGE_NAME",packageName) appConfig.putStringArray("ACTIVITY_LIST", arrayOf("*")) 
  1. A main bundle is created by associating the created profile (“Test”) with it, this profile is further enabled and updated as shown below : 
val mainBundle = Bundle() mainBundle.putString("PROFILE_NAME", “Test") // will enable this profile. mainBundle.putString("PROFILE_ENABLED", "true") // this profile will be updated on top of the existing profile. mainBundle.putString("CONFIG_MODE", "UPDATE"

The barcodeBundle is set as bundle and the appConfig bundle is set as parcelableArray against the main bundle. 

mainBundle.putBundle("PLUGIN_CONFIG",barcodeBundle) mainBundle.putParcelableArray("APP_LIST", arrayOf(appConfig)) 

The main bundle is added as an extra to a newly created Intent object with key as “com.symbol.datawedge.api.SET_CONFIG” (using the SET_CONFIG API in Datawedge API) with the action “com.symbol.datawedge.api.ACTION” and is broadcasted: 

val intent = Intent() intent.setAction(“com.symbol.datawedge.api.ACTION”) intent.putExtra(“com.symbol.datawedge.api.SET_CONFIG”,mainBundle) sendBroadcast(intent) 

 II) Switching to the created profile: 

This is done as a broadcast by creating an intent with action “com.symbol.datawedge.api.ACTION_SWITCHTOPROFILE” and passing the profile name as an extra as shown below: 

val intent = Intent() intent.setAction(“com.symbol.datawedge.api.ACTION_SWITCHTOPROFILE”) intent.putExtra(“com.symbol.datawedge.api.EXTRA_PROFILENAME”, “Test”) sendBroadcast(intent) 

III) Reading the barcode data via broadcast intent: 

Just like barcode bundle was configured with params, in order for the barcode output to be delivered via broadcast an “INTENT” plugin has to be created, configured and associated with the main profile bundle. 

val outputBundle = Bundle() outputBundle.putString("PLUGIN_NAME", "INTENT") outputBundle.putString("RESET_CONFIG","true"

The parameters to be passed are set via another bundle called the outputParamsBundle. Three flags have to be set “intent_output_enabled”,”intent_action” and “intent_delivery” as shown below: 

val outputBundleParams = Bundle() // Enable the intent output outputBundleParams.putString("intent_output_enabled" , "true") // Set the action string to which the broadcast listener listens to get barcode outputBundleParams.putString("intent_action",”com.test.barcode”) // Deliver via broadcast the barcode which was read. outputBundleParams.putString("intent_delivery" , "2"

The “intent_delivery” flag is set to “2” to configure the barcode output to be delivered via broadcast. 

The outputParamsBundle is added as a bundle to the outputBundle

outputBundle.putBundle(“PARAM_LIST”,outputBundleParams) 

The outputBundle is associated with the mainBundle containing the profile details and is broadcasted. This is the same as what was done for the barcode plugin configuration: 

val mainBundle = Bundle() mainBundle.putString("PROFILE_NAME", "Test") // will enable this profile. mainBundle.putString("PROFILE_ENABLED", "true") // this profile will be updated on top of the existing profile. mainBundle.putString("CONFIG_MODE", "UPDATE") mainBundle.putBundle("PLUGIN_CONFIG" ,outputBundle) 
val intent = Intent() intent.setAction(“com.symbol.datawedge.api.ACTION”)) intent.putExtra(“com.symbol.datawedge.api.SET_CONFIG”,mainBundle) sendBroadcast(intent) 

The barcode data can be received from the native scanner by registering a broadcast receiver with the action to be set in the intent filter as “com.symbol.datawedge.api.RESULT_ACTION ”.

registerReceiver(ZebraBroadcast,”com.symbol.datawedge.api.RESULT_ACTION”

The ZebraBroadCastReceiver can be written as follows: 

The action string should be the same as what was configured during the “INTENT” creation plugin: 

“com.test.barcode” 
class ZebraBroadcast : BroadcastReceiver() { 

val TAG = ZebraBroadcast::class.java.simpleName 

override fun onReceive(context: Context?, intent: Intent?) { 

val action = intent?.action val bundle = intent?.extras 

Log.d(TAG,">>>>>> onReceive:: ZebraBroadcast <<<<<< Action:${action}, bundle:${bundle}"

if(action?.equals(“com.test.barcode”){ 

try 

displayResults(intent!!,"via broadcast",context) }catch (e: Exception){ 

} } 

} private fun displayResults(initiatingIntent:Intent,howDataReceived:String,context: Context?){ 

var decodedSource = initiatingIntent.getStringExtra(“com.symbol.datawedge.source”) var decodedData decodedLabelType = initiatingIntent.getStringExtra(“com.symbol.datawedge.label_type”) 

var decodedLabelType = initiatingIntent.getStringExtra(“com.symbol.datawedge.data_string”) 

if(null==decodedSource){ 

// For legacy devices 

decodedSource = initiatingIntent.getStringExtra(“com.motorolasolutions.emdk.datawedge.source") 

decodedData = initiatingIntent.getStringExtra(“com.motorolasolutions.emdk.datawedge.label_type”) 

decodedLabelType = initiatingIntent.getStringExtra(“com.motorolasolutions.emdk.datawedge.data_string”) 

} Log.d(TAG,">>>>>>>> Barcode <<<<<<<<<<< :::: ${decodedData}"

} }

Use Case at PharmEasy: 

At Pharmeasy, previously we were using the EDMK method.This cause this issue ( https:// developer.zebra.com/thread/32976 ) which made our warehouse apps to be highly unstable. 

By Using Datawedge APIs in our android apps, not only did we reduce and improve the crashes but also integrating these APIs helped us to scan the barcode labels in our warehouses faster without any sluggishness which was observed previously, thereby increasing the productivity. 

References: 

https://developer.zebra.com/community/home/blog/2017/06/27/datawedge-apis-benefits- challenges 

https://techdocs.zebra.com/datawedge/6-8/guide/api/createprofile/ 

https://techdocs.zebra.com/datawedge/7-4/guide/api/setconfig/#intentoutputparameters 

https://techdocs.zebra.com/datawedge/7-4/guide/setup/ 

About the author

Akshay Kumar

I am a self-taught programmer, youtuber and pet lover. I am very passionate about photography and I shoot portraits and landscapes. I am an Android Developer in the supply chain team of PharmEasy. I am an ardent traveller, love to explore new places and try out the local cuisine when I am free.

Leave a Comment