Jun 03

Urban Airship integration with an Android Phonegap app

For my new job I had to integrate Urban Airship with an Android Phonegap application. UA's documentation only provides an example for iPhone apps, so if you are looking for a way to integrate an Android phonegap with UA look no further!

The task is going to require you to write your own phonegap plugin with a javascript and a java part, without further ado:

PushNotification.js

function PushNotification() {
}

PushNotification.prototype.registerCallback = function(successCallback, failureCallback) {
     return PhoneGap.exec(
            successCallback,           // called when signature capture is successful
            failureCallback,           // called when signature capture encounters an error
            'PushNotificationPlugin',  // Tell PhoneGap that we want to run "PushNotificationPlugin"
            'registerCallback',        // Tell the plugin the action we want to perform
            []);                       // List of arguments to the plugin
};

PushNotification.prototype.notificationCallback = function (json) {
    var data = Ext.util.JSON.decode(json);
    Ext.Msg.alert("Success", data.msg);
};

PhoneGap.addConstructor(function() {
    if (typeof navigator.pushNotification == "undefined")
        navigator.pushNotification = new PushNotification();
});

Note that I'm also using Sencha Touch in this project, you will need a json decoder to decode the json message sent from java.

PushNotificationPlugin.java

package com.example;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

import com.phonegap.api.Plugin;
import com.phonegap.api.PluginResult;
import com.phonegap.api.PluginResult.Status;

public class PushNotificationPlugin extends Plugin {
    final static String TAG = PushNotificationPlugin.class.getSimpleName();

    static PushNotificationPlugin instance = null;

    public static final String ACTION = "registerCallback";

    public static PushNotificationPlugin getInstance() {
        return instance;
    }

    public void sendResultBack(String msg, String payload) {
        JSONObject data = new JSONObject();
        try {
            data.put("msg", msg);
            data.put("payload", payload);
        } catch (JSONException e) {
            Log.e(TAG, e.getMessage());
        }
        String js = String.format("navigator.pushNotification.notificationCallback('%s');", data.toString());
        //Log.d(TAG, "Sending javascript " + js);
        this.sendJavascript(js);
    }

    @Override
    public PluginResult execute(String action, JSONArray data,
            String callbackId) {
        Log.d(TAG, "Plugin Called");

        instance = this;

        PluginResult result = null;
        if (ACTION.equals(action)) {
            result = new PluginResult(Status.NO_RESULT);
            result.setKeepCallback(false);
        } else {
            Log.d(TAG, "Invalid action: " + action + " passed");
            result = new PluginResult(Status.INVALID_ACTION);
        }
        return result;
    }
}

MainApplication.java

package com.example;

import android.app.Application;
import android.content.Intent;
import android.util.Log;

import com.urbanairship.push.APIDReceiver;
import com.urbanairship.push.AirMail;
import com.urbanairship.push.PushReceiver;

public class MainApplication extends Application {

    final static String TAG = MainApplication.class.getSimpleName();

    public void onCreate() {
        AirMail am = AirMail.getInstance();
        am.acceptPush(this, new PushReceiver() {

            @Override
            public void onClick(String msg, String payload) {
                /*
                 * Fire up MainActivity when the user clicks the Status Bar
                 * Notification
                 */
                Intent intent = new Intent("android.intent.action.MAIN");
                intent.setClass(MainApplication.this,
                        MainActivity.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                MainApplication.this.startActivity(intent);
            }

            @Override
            public void onReceive(String msg, String payload) {
                // Get a reference to the plugin and send result to js
                PushNotificationPlugin plugin = PushNotificationPlugin.getInstance();
                plugin.sendResultBack(msg, payload);
            }

        });

        am.setAPIDReceiver(this, new APIDReceiver() {
            @Override
            public void onReceive(String apid, boolean valid) {
                if (valid) {
                    Log.d(TAG, "Got apid: " + apid);
                } else {
                    Log.d(TAG, "Application registration invalid!");
                }
            }

            @Override
            public void onAirMailInstallRefusal() {
                MainActivity.register = false;
                Log.d(TAG, "AirMail Install Refused!");
            }
        });
    }
}

You will need to set up your AndroidManifest.xml and the rest of the settings as described in the Android docs.