Custom Cordova plugin

I’m not going to spend too much time on introduction and start right away. I had to renew an outdated mobile app running on windows mobile 6.5. The new mobile should support multiple operating systems and different kind of devices. Therefore I’ve decided to create a Hybrid Mobile app. As a SAP Developer I’ve created this app using the WebIDE and the HAT toolkit. I started creating a SAPUI5 app and deployed this app to my local computer using the HAT toolkit. The HAT toolkit generated a Cordova project which I could build on my local computer. In this Hybrid Mobile App there were two native requirements:

  • Offline
  • Barcode scanning with laser scanners

For the offline part I didn’t use SAP HCPms or SMP. Instead I’ve used a cordova SQLite plugin. This plugin supports almost all kind of mobile platforms. (The offline scenario was very basic)

The Laser Barcode Scanning was not that easy. I had to support multiple platforms and different type of devices. The Laser Barcode Scanner is different on each type of devices. It works different on each device, for some devices this is integrated, for others there is an API, … . This means there can be two different devices with the same operating system require different coding, for example:

  • Intermec   –> Android
  • Panasonic –> Android

Both devices will require different code to use the Laser Barcode Scanner. For Android running on Intermec there already exist a plugin:
https://www.npmjs.com/package/com.shahidachmat.intermec.scanner

For the Panasonic device there wasn’t and the Intermec plugin was not compatible. 🙁  Based on the Intermec plugin I started creating a plugin for Panasonic. Besides Android there were also Panasonic devices running the Universal Windows Platform (aka Windows 10). Also for these devices I needed to create a Laser Barcode Scanner plugin. For the Panasonic devices I’ve created one plugin that can be used for the android version as well as for the UWP version.

Panasonic Android plugin

I will only explain the most time consuming parts of creating my own plugin.

A Cordova plugin for android always requires an “execute” function. This function will be called from the JavaScript. It receives the following parameters:

  • Action : to know which function it has to execute
  • Arguments: parameters that can be passed from the JavaScript
  • CallbackContext: an object that can be used to respond to the JavaScript

In my plugin I’ve created an action “activateReader” to activate the Laser Barcode Scanner. This function will keep the callbackContext in a private property so I could use it when a barcode is scanned.

private void activateReader(CallbackContext callbackContext){
	try {
		List<BarcodeReader> readers = BarcodeReaderManager.getBarcodeReaders();
		BarcodeReader selectedReader = readers.get(0);
		//selectedReader.addBarcodeListener(this);
		EnableReaderTask task = new EnableReaderTask();
		task.execute(selectedReader);
		callbackContextReference = callbackContext;
	} catch (Exception e) {
		Log.e(TAG, e.toString());
	}	
}

The “onRead” function is the callback function of the scanner. Which means that every barcode scan will execute this function. This part took me most of the time. Returning a result of the scan was easy but this only worked once. After some research I figured out that I had to turn the keepCallback property to true. With this property I could return as much barcodes to the Fiori app as I wanted.

public void onRead(BarcodeReader paramBarcodeReader, BarcodeData paramBarcodeData)
{
     //String strDeviceId =  paramBarcodeData.getDeviceId();
     String strBarcodeData =  paramBarcodeData.getTextData();
     String strSymbologyId = paramBarcodeData.getSymbology();
     message = strBarcodeData;
     cordova.getActivity().runOnUiThread(new Runnable() {
          public void run() {
		PluginResult result = new PluginResult(PluginResult.Status.OK, message);
		result.setKeepCallback(true);
		callbackContextReference.sendPluginResult(result);
         }
     });
}

You can find the full code of the android plugin on the github:
https://github.com/lemaiwo/PanasonicScanner/blob/master/src/android/PanasonicScanner.java

Panasonic Windows plugin

Besides the Panasonic device running on Android I also had to support Panasonic devices running on the Universal Windows Platform (aka Windows 10).

For this plugin I had no example of a comparable Cordova windows plugin. I asked a .NET developer for supporting me with the C# code for communicating with the Barcode LAser Scanner on the Panasonic device! The next step was to make a Cordova plugin of this C# code. After some research I found out that there was more required then only C# coding. A cordova windows plugin contained two parts:

  • Windows Runtime Component
  • JavaScript Proxy

I started creating a Windows Runtime Component based on the Microsoft documentation:https://msdn.microsoft.com/en-us/library/windows/apps/hh779077.aspx

 

A few things I want to indicate:

  • Defining a class in a Windows Runtime Component requires the “sealed” statement:

 

  • Calling an “async Task” function is not possible. This was the case of the code I received of the .NET developer. He created a wrapper for this function to make it compatible for cordova. This wrapper function will be called from the JavaScript proxy. (The activateHelper is the original function.):

 

In the activate scanner function I define a callback function for the Barcode Laser Scanner. Each scan will trigger this callback function. In this callback function I’ll send the barcode back to the JavaScript Proxy. Sending the barcode back to the JavaScript proxy took me a lot of time. It was not that straightforward and there were not much code examples. After a while I found out that I had to use events to send something back to the JavaScript proxy. There are three ways to trigger events in Windows Runtime Components:

https://msdn.microsoft.com/en-us/library/windows/apps/dn169426.aspx

I did it this way:

 

In the OnBarcode function I trigger an event. This event will send the barcode to the JavaScript proxy.

In the JavaScript proxy I have a function activate. This function will be called from the Cordova plugin. Here I create an object the class in my Windows Runtime Component. Then I use this object to execute the “activate” function. This is also the place where I catch the C# event. In the eventhandler I call the succesCallback of cordova to return the result, in this case the barcode. In this successCallback I pass the barcode and I turn the keepCallback parameter to true. This is needed to keep the successCallback function alive. Otherwise I would not be able to return the barcode more than once.

 

cordova.commandProxy.add("PanasonicScanner",{
    activate:function(successCallback,errorCallback) {
	var ps = new PanasonicScanner.PanasonicScanner()
	var res = ps.activate();
	if (res) {
	     ps.onbarcodeevent = function (bc) {
	          if (bc && bc.detail && bc.detail[0] && bc.detail[0].code) {
		       successCallback(bc.detail[0].code, { keepCallback :true});
                  }
	     };
        }else{
		errorCallback(res);
	}
    }
});

 

More information about the Cordova Windows plugin on:
https://cordova.apache.org/docs/en/latest/guide/platforms/win8/plugin.html

You can find the full Windows Runtime Component and JavaScript proxy on the github:
https://github.com/lemaiwo/PanasonicScanner/tree/master/src/windows

Get the plugin

After a long way of research and trying I completed the Laser Barcode Scanner on Panasonic devices for Android and Windows.

The plugin is available on github https://github.com/lemaiwo/PanasonicScanner

It’s also on NPM: https://www.npmjs.com/package/cordova-panasonic-scanner

It should also come in the Cordova Search, but for some reason it doesn’t show up:
https://cordova.apache.org/plugins/?q=panasonic

Enjoy using it!

Kind regards,
Wouter

To report this post you need to login first.

Be the first to leave a comment

You must be Logged on to comment or reply to a post.

Leave a Reply