Improved Cordova Android plugin API

Cordova has a nice API for creating your own plugins. When you need to do something in native code, (for improved speed or security) or need to access some hardware, you can create your own plugin. Our team is concentrating on Android and iOS at the moment and one thing that I noticed is how different the API is between those 2 platforms. For instance creating a Echo plugin on iOS that has a method called echo all you need is this:

- (void)echo:(CDVInvokedUrlCommand*)command
{
    CDVPluginResult* pluginResult = nil;
    NSString* echo = [command.arguments objectAtIndex:0];

    if (echo != nil && [echo length] > 0) {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:echo];
    } else {
        pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
    }

    [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}

But the same plugin on Android you’ll need:

@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
    if ("echo".equals(action)) {
        this.echo(args.getString(0), callbackContext);
        return true;
    }
    return false;  // Returning false results in a "MethodNotFound" error.
}

public void echo(String echo, CallbackContext callbackContext) {
    final PluginResult result;
    if (echo != null && echo.length() > 0) {
        result = new PluginResult(PluginResult.Status.OK, echo);
    } else {
        result = new PluginResult(PluginResult.Status.ERROR);
    }
    
    callbackContext.sendPluginResult(result);
}

Now there is a bit of boilerplate here where we get the action and dispatch it to the method. Wouldn’t it be nice to just create a method like on iOS? Well with the android-reflect-plugin you can, it will see if the method exists based on the action and invoke it making your plugin much smaller. All you need to do is declare this plugin as a dependency in your plugin xml:

<dependency id="org.jboss.aerogear.cordova.android.reflect" url="https://github.com/edewit/aerogear-reflect-cordova.git"/>

Then, you extend BasePlugin instead of CordovaPlugin and that it:

public class Echo extends BasePlugin {

public boolean echo(String echo, CallbackContext callbackContext) {
    callbackContext.success(message);
    return true;
}
*****
Written by Erik Jan de Wit on 08 July 2014