Cloud to device messaging


SDK Version: 
M3

Android has so many features, that it's hard to go over every one of them. We wanted to try out cloud to device messeging (c2dm) for a long time now, and in the past few days I had some time to play with it. Here is a small tutorial on the topic.

Prerequisites:

  1. A google account's email and password. If you use 2 step verification, you need to generate a one time password for it!
  2. Sign up with the account, for the c2dm service. You need to supply the client android app's package name for it.
  3. Implement c2dm stuff in your android app. Commonsware has a very good sample app online, it would be easy to make a library from it. You don't have to modify anything in it, all you need is to provide an email address, which will be registered to receive the push messages. Of course you don't need user interaction to do this, you could use account manager to get the users email address.
  4. The android app can now register for the service(Commonsware's sample app: type in mail address, press button), it will give you the registration_id back, which you need to send over to your server (in Commonware's sample, check logcat).

Your server:
You have to be able to receive and manage the clients registration_id on your server.
Also, you might want to store some other identification from your clients too. For messaging, the registration_id is enough, but if you want to send out information to a specific client, than you need something more (email address maybe, or some other unique id).

The server too has to be registered at google.
It can be done via a HTTP post msg, which will give you back the Auth token (also a SID and LSID but you don't need those now).

Example using curl:
curl https://www.google.com/accounts/ClientLogin -d Email=YOUR_EMAIL_ADDRESS -d Passwd=YOUR_PASSWORD -d accountType=GOOGLE_OR_ -d source=YOUR_CLIENT_APP_PACKAGE_NAME -d service=ac2dm
I had some ssl trouble on my local pc, but if you run this on a webserver, you should not have any problems. If you do have ssl trouble, use the -k curl parameter.

Now with the Auth token and registration_id, you can start sending messages.

Data is sent in key-name valuepairs, in a HTTP post message.

Sending meessages:
Example using curl:
curl --header "Authorization: GoogleLogin auth=AUTH_GOES_HERE" "https://android.apis.google.com/c2dm/send" -d registration_id=REGISTRATION_ID_GOES_HERE collapse_key=COLLAPSE_KEY_GOES_HERE -d "data.YOUR_KEY=YOUR MESSAGE which can't be longer than 1024 bytes" -d data.YOUR_OTHER_KEY=you can send more key-value pairs in 1 message" -k

Avoid spamming:
collapse_key is mandatory. It is used to group your messages. The documentation sais: "when the device is offline, so that only the last message gets sent to the client."
There is also a delay_while_idle field
From the docs: "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."

Error handling:
There are error messages that you would need to handle, those are in the docs.
Avarage sending time on my tests was about 1 sec, but I guess network lag could make that go up to minutes.

Worth to read:
Docs: http://code.google.com/android/c2dm/index.html
https://github.com/commonsguy/cw-advandroid/tree/master/Push/C2DM/

Other articles about the topic:
http://www.vogella.de/articles/AndroidCloudToDeviceMessaging/article.html
http://www.scotthawker.com/articles/c2dm.html