3. "It allows third-party application servers
to send lightweight messages to their
Android applications"
Not designed to send a lot of content via messages. Instead
use C2DM to tell the application that there is new data on the
server to fetch.
4. "C2DM makes no guarantees about
delivery or the order of messages"
Eg. not suitable for instant messaging, instead use C2DM to
notify the user that there is new messages.
5. "An application on an Android device
doesn’t need to be running to receive
messages"
Intent broadcast wake up the app
6. "It does not provide any built-in user
interface or other handling for message
data"
Passes raw message data. You are free to do whatever you
want with the data. Fire a notification, send SMS, start another
application etc.
7. "It requires devices running Android 2.2
or higher that also have the Market
application installed"
Market is needed for technical reasons. No need to distribute
via Market.
8. "It uses an existing connection for
Google services"
Requires the user to be logged in with a Google Account on the
device.
9. Establish connection
with conn servers
Send to conn
Send to servers
device
Stores message
App server sends
HTTP POST
Google
http://code.google.com/events/io/2010/sessions/push-applications-android.html
11. Register device
App fires off Intent to register with Google
com.google.android.c2dm.intent.REGISTER
App receives Intent with registration ID from Google
com.google.android.c2dm.intent.REGISTRATION
App sends registration ID to app server
12. Register device
// Intent to register
Intent regIntent = new
Intent("com.google.android.c2dm.intent.REGISTER");
// Identifies the app
regIntent.putExtra("app",
PendingIntent.getBroadcast(context, 0, new Intent(), 0));
// Identifies the role account, same as used when sending
regIntent.putExtra("sender", senderEmail);
// Start registration process
context.startService(regIntent);
13. Register device
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("...REGISTRATION")) {
handleRegistration(context, intent);
}
}
private void handleRegistration(Context context, Intent intent) {
String registration = intent.getStringExtra("registration_id");
if (intent.getStringExtra("error") != null) {
// Registration failed, should try again later.
} else if (intent.getStringExtra("unregistered") != null) {
// unregistration done
} else if (registration != null) {
// Send the registration ID to app server
// This should be done in a separate thread.
// When done, remember that all registration is done.
}
}
14. Unregister device
App fires off a unregister Intent to register with Google com.
google.android.c2dm.intent.UNREGISTER
App tells app server to remove the stored registration ID
17. Send message
From the documentation:
For an application server to send a message, the following
things must be in place:
The application has a registration ID that allows it to receive
messages for a particular device.
The third-party application server has stored the registration
ID.
There is one more thing that needs to be in place for the
application server to send messages: a ClientLogin
authorization token. This is something that the developer must
have already set up on the application server for the
application (for more discussion, see Role of the Third-Party
Application Server). Now it will get used to send messages to
the device.
http://code.google.com/android/c2dm/index.html#lifecycle
18. Send message
Retrieve ac2dm auth token (put on app server)
Send authenticated POST
- GoogleLogin auth=<TOKEN>
- URL Encoded parameters
registration_id
collapse_key
deplay_while_idle - optional
data.<KEY> - optional
Using cURL to interact with Google Data services:
http://code.google.com/apis/gdata/articles/using_cURL.html
20. Token can change
URL url = new URL(serverConfig.getC2DMUrl());
HttpURLConnection conn =
(HttpURLConnection) url.openConnection();
...
// Check for updated token header
String updatedAuthToken =
conn.getHeaderField("Update-Client-Auth");
if (updatedAuthToken != null &&
!authToken.equals(updatedAuthToken)) {
serverConfig.updateToken(updatedAuthToken);
}
21. Send message
curl https://android.apis.google.com/c2dm/send
-d registration_id=<REGISTRATION ID>
-d collapse_key=foo
-d data.key1=bar
-d delay_while_idle=1
-H "Authorization: GoogleLogin auth=<AUTH TOKEN>"
Response codes
200 OK
- id=<MESSAGE ID> of sent message, success
- Error=<ERROR CODE>, failed to send
401 Not Authorized
503 Service Unavailable, retry
22. collapse_key
Only the latest message with the same key will be delivered
Avoids multiple messages of the same type to be delivered
to an offline device
State should be in app server and not in the message
Eg. could be the URL to fetch data from
24. Receive a message
Device receives the message and converts it to Intent
- com.google.android.c2dm.intent.RECEIVE
App wakes up to handle Intent
- data.<KEY> is translated to extras
curl https://android.apis.google.com/c2dm/send
...
-d data.key1=bar
...
protected void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("...RECEIVE")) {
String key1 = intent.getExtras().getString("key1");
// If starting another intent here remember to set the
// flag FLAG_ACTIVITY_NEW_TASK
}
}