Custom Cordova Plugin – Mobile Hybrid App
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
Hi Wouter
Great Work!!
Did you create the plugin for the Panasonic FZ-X1 running in Android 4.2.2 or 5.1.1?
Your Plugin worked on my device with 4.2.2, but not after upgrading it to 5.1.1.
Do you know if there is any issue after upgrading the device?
Best regards
Dominik
Hi Dominik,
Indeed, we had similar problem. De Panasonic SDK is using intent which is changed in latest android version. To solve it, we've added targetSDK to 19 in the androidmanifest:
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" />
Kr,
Wouter
Hello Wouter,
great work! I read the solution youve built.
I am working on a task where a similar challenge lies. Would it be possible to hire you for this job?
I write the notes in Dutch ....
Bij Techedge maken wij mobiele toepassingen op basis van de SAP Backend, via een add-on in SAP genaamd Neptune. De applicaties gemaakt met behulp van Neptune hebben een front-end in Javascript / HTML5 schermen. Geschikt en schaalbaar voor IOS, Android en Windows.
We hebben nu een klant die Panasonic Toughpad op Windows gebruikt waarmee het mogelijk is Barcodes te scannen.
Met de Native camera werkt het goed maar er is ook nog een InfraRood-scanner hardwarematig aan boord.
Is het mogelijk om via de route Cordova dit stuk HW eveneens te gaan benutten?
Ik begrijp dat ook hiervoor een zogenaamde 'bridge' nodig is, we hebben gezocht naar nieuwe add-ons, momenteel zijn die niet voorhanden.
Is het mogelijk: voor onze klant / voor de community binnen Cordova (Apache) kan in Java, C# of .Net een zelfde soort bridge te bouwen?
Kunnen we voor het bouwen van deze bridge een offerte krijgen?
Wij hebben momenteel binnen Techedge Duitsland onvoldoende JAVA dev. capaciteit om dit te realiseren. Een klant van ons heeft verschillende van deze Toughbooks en wil graag aan de slag met de InfraRood scanner.
Reply in German or English is OK for us.
Best Regards,
Jan Coerts
Techedge GmbH
Hauptstraße 5
69190 Walldorf
0049-152-228 35 629
Hi Jan,
It's indeed very similar as what I did. I guess you'll have to access the infrared scanner instead of the laser scanner. I would love to help you with that but, you'll have to contact my company, Flexso www.flexso.com
Best regards,
Wouter
Dear Wouter
thanks for the great post. Is there an option to add custom cordova plugins to the SAP Cloud Platform Mobile Services based build of the Fiori Client ?
Thanks!
Best regards,
Martin
Not sure for the Fiori client.. It was possible in the on premise build, don't know for the cloud build...
Hi Martin
you can try the plugin cordova-plugin-panasonic-toughpadapi.
I didn't check the build result of the custom fiori client, but the plugin works in a packaged app (cloud built).
Best regards
Dominik