Android PUSH Notifications using Google’s C2DM Framework

Contributed by Khurshidali Shaikh on 9 Jun 2011

Unlike other mobile platforms like the Blackberry or iPhone, Android does not support PUSH notifications out of the box. There is speculation that it may be added in future releases of Android, but as of Gingerbread(2.3), it isn’t part of the SDK.

But in true Google fashion, they have come out with a service to provide PUSH notifications on Android using their existing Gmail framework . For it to work, at least one Google account should be logged in on the device. This service is called C2DM (Cloud to Device Messaging). Also C2DM works only from Android 2.2 onwards. The C2DM site provides the following note :

Note:Android C2DM will ultimately be available to all developers. However, it is currently launched in Labs, and not universally available. If you’re interested in using C2DM with your Android applications, go to the signup page to request access. Google will contact you when you’ve been granted access.

So how do you go about setting up C2DM push notifications in your Android app from your web application? Here are the steps to follow for both the Android app and Web server.

Signing up for C2DM

The first step is to signup at http://code.google.com/android/c2dm/signup.html. Fill in the relevant information, the most important being the package name of your app and Role account email. This is the email id you will use to setup and run C2DM notifications. It has to be a valid gmail account. Make sure you don’t use this email id on any device. Once you finish signing up, you have to wait to receive a confirmation email from Google that your registration has been accepted.

Things needed to do on the Android front

After you’ve registered, you have to make your android app C2DM enabled. Your app on a device needs to register with Google’s C2DM server for receiving messages. This requires quite a bit of plumbing code. The classes from Google’s C2DM sample project ChromeToPhone can be used as a base and expanded on if required. The project can be checked out from the following SVN repository http://chrometophone.googlecode.com/svn/trunk/android

Define the following constants in a Constants class. These are used in the code snippets below.


public static final String SEND_REGISTRATION_TO_GOOGLE = "com.google.android.c2dm.intent.REGISTER";
public static final String SEND_UNREGISTER_TO_GOOGLE = "com.google.android.c2dm.intent.UNREGISTER";
public static final String RECVD_REGID_FROM_GOOGLE = "com.google.android.c2dm.intent.REGISTRATION";
public static final String RECVD_C2DM_MSG_FROM_GOOGLE = "com.google.android.c2dm.intent.RECEIVE";
public static final String ACCOUNT_ID = "";
public static final String ANDROID_PUSH_SERVER_URL = “”;

In the Activity that will be registering/unregistering your app with the C2DM server add the following methods


private void register() {
Intent registrationIntent = new Intent(Constants.SEND_REGISTRATION_TO_GOOGLE);
registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
registrationIntent.putExtra("sender", Constants.ACCOUNT_ID);
startService(registrationIntent);
}

private void unregister() {
Intent unregIntent = new Intent(Constants.SEND_UNREGISTER_TO_GOOGLE);
unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0));
startService(unregIntent);
}

The method register() sends a registration request to Google’s C2DM server, and in response the C2DM server will send back the registration id to the device and a com.google.android.c2dm.intent.REGISTRATION intent will be called. You need a BroadcastReceiver that will register for this intent and once the BroadcastReceiver receives the intent we can send that registration id to our Web App Server.

The method unregister() simply unregisters the app from the server and it will no longer receive any messages.

Below is a sample BroadcastReceiver to handle the push notifications


public class C2DMBroadcastReceiver extends BroadcastReceiver {
@Override
public final void onReceive(Context context, Intent intent) {
if (Constants.RECVD_REGID_FROM_GOOGLE.equals(intent.getAction())) {
Log.d(TAG, "Received a registration ID from Google.");
final String registrationId = intent.getStringExtra(EXTRA_REGISTRATION_ID);
String error = intent.getStringExtra(EXTRA_ERROR);
if (error == null) {
// Launch a service or Async task to send this id to your web server
} else {
handleRegistrationError(error);
}
} else if (Constants.RECVD_C2DM_MSG_FROM_GOOGLE.equals(intent.getAction())) {
Log.d(TAG, "Received a C2DM message from Google.");
if (intent.hasExtra("content")) {
String pushMessage = callingIntent.getExtras().getString("content");
}
//Handle PUSH message received..
}
}
}

Once you receive the registration id, you should send it to your web server using HTTP post or something. Along with the registration id you may also want to send some other device information(maybe the device id) to identify the device on the server. Google updates the registration id every now and then, so when ever it does, you’ll receive this intent again and its important to update this registration id on your web application.

The maximum data that can be received in a message is 4kb, so if you need substantial data to be updated on your device, then on receiving the push message, the device can make a direct HTTP call to your web application to pull the required data

To handle PUSH you need to add some permissions to the AndroidManifest.xml. Below is a sample.
















This completes the setup on the Android application.

Things to do on the web application

Your web application will store (or update) the registration id received from the device, after it has successfully registered with the C2DM server, into its local database. So eventually the server will have registration ids from all the devices. To send a message to a particular device, the server needs to send an HTTP Post to the C2DM Server https://android.apis.google.com/c2dm/send with the following data

  1. registration_id: The registration ID retrieved from the Android application on the phone. Required

  2. collapse_key: An arbitrary string that is used to collapse a group of like messages when the device is offline, so that only the last message gets sent to the client. This is intended to avoid sending too many messages to the phone when it comes back online. Note that since there is no guarantee of the order in which messages get sent, the “last” message may not actually be the last message sent by the application server. Required.

  3. data: Payload data, expressed as key-value pairs. If present, it will be included in the Intent as application data. There is no limit on the number of key/value pairs, though there is a limit on the total size of the message. Optional.

  4. delay_while_idle: If included, indicates that the message should not be sent immediately if the device is idle. The server will wait for the device to become active, and then only the last message for each collapse_key value will be sent. Optional.

  5. Include this in the header – Authorization: GoogleLogin auth=<Your Auth Token> . See below on how to get an authentication token.

How to get an authentication token
You can get the authentication token by sending an HTTP Post request to https://www.google.com/accounts/ClientLogin with the following data

  1. accountType: Type of account to request authorization for. Possible values are:
    GOOGLE (get authorization for a Google account only)
    HOSTED (get authorization for a hosted account only)
    HOSTED_OR_GOOGLE (get authorization first for a hosted account; if attempt fails, get authorization for a Google account)
    Use HOSTED_OR_GOOGLE if you’re not sure which type of account you want authorization for. If the user information matches both a hosted and a Google account, only the hosted account is authorized.

  2. Email: Email id using which you signed up for C2DM

  3. Passwd: The password for the above email id

  4. service: Use – ac2dm

  5. source: Short string identifying your application, for logging purposes. This string should take the form:”companyName-applicationName-versionID”.


Credits
This blog post was composed with help from Dannon D’Mello. Dannon is a senior software developer at Neev Technologies and involved in J2EE and Android application development.

Visit us at Neevtech.com to know more about our offerings.

Tags: , , ,

3 Comments

  1. [...] Shaikh, Chief Architect – Neev Technologies, … See one article here – http://neevtech.com/blog/?p=131This answer .Please specify the necessary improvements. Edit Link Text Show answer summary [...]

  2. kshaikh says:

    Hi,

    The code snippets for java and the configuration for AndroidManifest are already included in the article. You need to take that and build your application based on your specific requirements.

    Best of luck.

  3. new_user says:

    Hi,

    Thanks for the tutorial,, can you upload source code as it would be more helpfull.

Leave a Comment

Security Code: