Blog

Ideas and insights from our team

Creating Cordova/Phonegap plugins


Building hybrid mobile apps is all nice and easy until you need some native feature that does not yet have a cordova package. But don't you worry, we will show you how to do it. We will be writing a plugin to run some simple android code and call it from the javascript side.

I'll be running Cordova version 4.3, so be aware things might be different for other versions.

A native toast plugin

We will be working on a native toast plugin for android devices. This will allow us to walk through most of the basic concepts of plugin development.

The plugin.xml file

First, create a new folder to start your plugin development outside from your project.

mkdir my_alert_plugin

Now create a file inside it and call it plugin.xml. This file is where you do all the configuration and tell Cordova how to install the plugin. It should be placed at the root of your project. Let's start with a simple configuration:

 <?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    id="br.com.vinta.cordova.toast"
    version="0.0.1">
    <name>Toast</name>
    <description>Cordova native toast pluggin for Android</description>
    <license>Apache 2.0</license>
    <keywords>cordova,toast</keywords>
</plugin>

This is a pretty standard configuration file, all the tags are self explanatory. The only thing you should be be careful is with the plugin:id property. This property should be an string that uniquely identifies your plugin. It's a convention to use the reverse domain name notation.

The native code

Let's now move to create the native code that shows the alert. This will be a standard java file, that has access to all the default Android and Cordova libraries.

Place the code in src/android/MyToast.java This is the basic structure of the Java class:

package br.com.vinta.cordova.toast;

import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaInterface;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.content.Context;
import android.widget.Toast;

public class MyToast extends CordovaPlugin {

    public MyToast() {

    }

    @Override
    public void initialize(CordovaInterface cordova, CordovaWebView webView) {
        super.initialize(cordova, webView);
    }

    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {

    }
}

The initialize method should call it's super and can also be used to do any extra initialization work you need.
The execute method is where the magic happens. All javascript calls to your plugin will go through this method and it's its responsibility to route then to run the appropriate code.

Showing a toast message

Inside the MyToast class we will create the method that shows the alert:

public void showToast(String message, final CallbackContext callbackContext){
    Context context = this.cordova.getActivity().getApplicationContext();
    Toast toast = Toast.makeText(context, message, Toast.LENGTH_SHORT);
    toast.show();

    callbackContext.success("Nice!");
}

This is also pretty simple, we are creating a toast and showing it with a given message. In the and we call callbackContext.success to return a message to the javascript code.

Executing the the showToast method

As previously said, all native calls are sent to the execute method. We have to manually define how the call will be treated.

@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
    if ("showToast".equals(action)) {
        this.showToast(args.getString(0), callbackContext);
    }else{
        return false;
    }
    return true;
}

The action will tell us witch method should run. args will contain arguments passed, in our case, it will contain only one argument with the message to be passed to the showToast method. It's also worth noticing that the execute method should return true in case the requested action was found and false otherwise.

The javascript interface

Almost done! Create a folder named www and a file toast.xml. This is how it will look like:

var obj = {};

obj.show = function(message, successCallback, errorCallback) {
    cordova.exec(
      successCallback, errorCallback,
      "MyToast", "showToast", [message]);
};

module.exports = obj;

We defined the show function that receives a message to be shown and callbacks of success and error. The cordova.exec function is responsible to make the bridge from the javascript to the native code. It receives the callbacks, a service, witch in our case is MyToast, an action, and a list of parameters. And that's all we need in the javascript side.

Connecting everything in plugin.xml

All is left is to teach Cordova how to install the plugin. This is done in the plugin.xml:

 <?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
    xmlns:android="http://schemas.android.com/apk/res/android"
    id="br.com.vinta.cordova.toast"
    version="0.0.1">
    <name>Toast</name>
    <description>Cordova native toast pluggin for Android</description>
    <license>Apache 2.0</license>
    <keywords>cordova,toast</keywords>

    <js-module src="www/toast.js" name="toast">
        <clobbers target="toast" />
    </js-module>

    <!-- android -->
    <platform name="android">
        <config-file target="res/xml/config.xml" parent="/*">
            <feature name="MyToast" >
                <param name="android-package" value="br.com.vinta.cordova.toast.MyToast"/>
            </feature>
        </config-file>

        <source-file src="src/android/MyToast.java" target-dir="src/br/com/vinta/cordova/toast"/>
    </platform>
</plugin>
  • js-module: sets the name of your plugin and where the javascript interface is.
  • clobbers: sets the global variable name used access your plugin.
  • config-file: target tells where to place the configuration about the feature you are developing.
  • feature: is the name of the service.
  • param: tells the package where the service is placed.
  • source-file: tells where a file should be placed. Is our case, MyToast.java will be placed in the src directory corresponding to its package name.

Testing our plugin

To install our plugin, we will use plugman, install it using:

npm install -g plugman

and run from the root folder of the project you want it to be installed:

plugman install --platform android --project platforms/android/ --plugin /path/to/plugin/root/folder/ --plugins_dir plugins/

now place the code to show the toast in your project:

toast.show("It works!!!", successCallback, errorCallback);

and run from terminal:

cordova run android

Great, that's all!
Link to full project here.
If you are interested in developing web or mobile apps, send a message about your project to contato@vinta.com.br

About Filipe Ximenes

Bike enthusiast, software developer and former director at Python Brasil Association. Likes open source and how people interact in open source communities.

Comments