DEVELOPERS BLOG

Power your WebWorks Extension with Cordova

Now that WebWorks 2.0 is powered by Cordova, it’s time to convert our extensions from the previous WebWorks 1.0 format to the new Cordova and WebWorks 2.0 format. This conversion process is necessary to ensure your plugin is compatible with WebWorks 2.0. Thankfully, the majority of the changes are quite superficial and it really involves just swapping out one set of framework calls for another.

Power Your WebWorks Extension with Cordova

The approach that I think works best is to start from the new BB10-Cordova Template project, and move the functional code from your old extension into the new template. With this approach, your work will be more consistent with creating a new plugin, and you’ll have less potential for mixing the boilerplate code up.

For the first step, you’ll need to rename the Template to match the extension that you are porting. There are a lot of places where this will be done, from the namespace, to the individual file names, and the native project as well. Follow the guide given in the Template Readme to make those name changes. Then, let’s look at the changes you’ll need to make in each part of the plugin:

Plugin.xml

This file tells WebWorks how to install the plugin into your app. The namespace of the API is defined here, in the “id” property, and the same value is used in a few other spots. Usually you’ll choose a reverse domain name and descriptive name for your plugin. The Template uses “community.templateplugin”, but for all the ones we submit to the Cordova Plugin Registry, we use “com.blackberry.community.<plugin name>” for the ID and feature name/value. However, we usually use just the “community” namespace for the target JavaScript Module value. Here’s the Prevent Sleep plugin.xml as an example:

Power Your WebWorks Extension with Cordova_code 1

Client.js

This file is similar in many ways to what you will be used to with WebWorks 1.0. You are still going to define a series of methods to be exported as the API. However, instead of using the old “webworks” APIs to make the function calls, you will now use Cordova’s “exec” method. Also, the namespace of the API is defined here as the _ID value directly, rather than being pulled from the manifest.json file (which is no longer used at all). The “exec” method has a different signature than the WebWorks methods did. It will take success and fail callback functions, then the _ID, the method to call, and the input values in a JSON object. If the API that you are porting didn’t use success and fail callback functions before, then you can do as the Template does and define those methods inline. All the “webworks.event” code that was required before for asynchronous functions is also handled differently, but not in this file, so that will be removed for now.

Here’s how the _ID changes from WebWorks 1.0:

Power Your WebWorks Extension with Cordova_code 2

To WebWorks 2.0:

Power Your WebWorks Extension with Cordova_code 3

And here’s how one function call would change from WebWorks 1.0:

Power Your WebWorks Extension with Cordova_code 4

To WebWorks 2.0:

Power Your WebWorks Extension with Cordova_code 5

Index.js

This file also requires some changes. Instead of having a separate JNEXT file, that code is now integrated into index.js. Each method here will have 4 parameters: success, fail, args, and env. The very first line of code in each method should be:

var result = new PluginResult(args, env);

This PluginResult object is how communication is handled through Cordova. The object has methods for returning values, errors, for handling callbacks, and for sending back no result. The second parameter tells Cordova if it should keep the PluginResult object around. Many basic functions will set it false. If the method call is asynchronous or will have multiple results, that parameter should be set to true. In those cases, the PluginResult object is also put into a mapping so that it can be retrieved when the asynchronous results come back. The object automatically generates a unique callbackId value. The callbackId is used the reference the object in the mapping, and is also sent to the native code for use in communication.

If you have “success()” method calls in your old WebWorks 1.0 code, these will typically be replaced by “result.ok()” methods, or “result.noResult()” calls.

Here’s the same method in index.js changed from WebWorks 1.0:

Power Your WebWorks Extension with Cordova_code 6

To WebWorks 2.0:

Power Your WebWorks Extension with Cordova_code 7

JNEXT

This was a separate file in WebWorks 1.0, but now is included at the bottom of index.js. Instead of using hardcoded event names as done in WebWorks 1.0, the new way uses the unique callbackId value to link up asynchronous events with the original calling function. For this reason, the function calls in the JNEXT portion of the file will now include the callbackId as a parameter sent to the native code. Also, the onEvent function is much reduced in size. The callbackId is retrieved from each event, and the PluginResult object is pulled from the map. In most cases, calling “result.callbackOk(data, false)” and removing the result from the map is all that is needed.

Here’s the small change to send callbackId from WebWorks 1.0:

Power Your WebWorks Extension with Cordova_code 8

To WebWorks 2.0:

Power Your WebWorks Extension with Cordova_code 9

Template_js and Template_ndk

In the native portion, there are very few changes to make. Only asynchronous method calls are affected, and only by the need to update the event name to be dynamic. The callbackId will be parsed out in the “InvokeMethod” call, and this needs to be passed to any event that sends asynchronous results using the “NotifyEvent” call. Any call to that method should use the callbackId instead of the hardcoded event name that was used previously.

Here’s an example method from WebWorks 1.0 that sends back JSON Asynchronously:

Power Your WebWorks Extension with Cordova_code 10

And in WebWorks 2.0, here’s a similar method using the callbackId:

Power Your WebWorks Extension with Cordova_code 11

And that’s it! Small changes, really, across all the files, and almost no native code changes, makes for a fairly rapid porting process. In the end, I think the solution works better as well, with unique callbacks for each asynchronous method. If you’re interested in contributing your plugins to the public BlackBerry repositories on GitHub, we’d appreciate your input. Contact me to get started at @timothywindsor or on GitHub.

 

About timwin1