Android Cloud to Device Messaging (C2DM) is a service that helps developers send data from servers to their applications on Android devices. The service provides a simple, lightweight mechanism that servers can use to tell mobile applications to contact the server directly, to fetch updated application or user data. The C2DM service handles all aspects of queueing of messages and delivery to the target application running on the target device.
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.
Here are the primary characteristics of Android Cloud to Device Messaging (C2DM):
This section gives an overview of how C2DM works.
This table summarizes the key terms and concepts involved in C2DM. It is divided into these categories:
Components | |
---|---|
Mobile Device | The device that is running an Android application that uses C2DM. This must be a 2.2 Android device that has Market installed, and it must have at least one logged in Google account. |
Third-Party Application Server | An application server that developers set up as part of implementing C2DM in their applications. The third-party application server sends data to an Android application on the device via the C2DM server. |
C2DM Servers | The Google servers involved in taking messages from the third-party application server and sending them to the device. |
Credentials | |
Sender ID | An email account associated with the application's developer. The sender ID is used in the registration process to identify a Android application that is permitted to send messages to the device. This ID is typically role-based rather than being a personal account—- for example, [email protected]. |
Application ID | The application that is registering to receive messages. The application is identified by the package name from the manifest . This ensures that the messages are targeted to the correct application. |
Registration ID | An ID issued by the C2DM servers to the Android application that allows it to receive messages. Once the application has the registration ID, it sends it to the third-party application server, which uses it to identify each device that has registered to receive messages for a given application. In other words, a registration ID is tied to a particular application running on a particular device. |
Google User Account | For C2DM to work, the mobile device must include at least one logged in Google account. |
Sender Auth Token | A ClientLogin Auth token that is saved on the third-party application server that gives the application server authorized access to Google services. The token is included in the header of POST requests that send messages. For more discussion of ClientLogin Auth tokens, see ClientLogin for Installed Applications . |
Here are the primary processes involved in cloud-to-device messaging:
These processes are described in more detail below.
This is the sequence of events that occurs when an Android application running on a mobile device registers to receive messages:
This registration Intent (com.google.android.c2dm.intent.REGISTER) includes the sender ID (that is, the account authorized to send messages to the application, which is typically the email address of an account set up by the application's developer), and the application ID.
The application should store this ID for later use. Note that Google may periodically refresh the registration ID, so you should design your application with the understanding that the REGISTRATION Intent may be called multiple times. Your application needs to be able to respond accordingly.
The registration ID lasts until the application explicitly unregisters itself, or until Google refreshes the registration ID for your application.
For an application server to send a message, the following things must be in place:
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.
The ClientLogin token authorizes the application server to send messages to a particular Android application. An application server has one ClientLogin token for a particular 3rd party app, and multiple registration IDs. Each registration ID represents a particular device that has registered to use the messaging service for a particular 3rd party app.
Here is the sequence of events that occurs when the application server sends a message:
An application can unregister C2DM if it no longer wants to receive messages.
This is the sequence of events that occurs when an Android application running on a mobile device receives a message:
When mobile device users install an applications that include C2DM, they will get a permission from Android Market informing them that the application includes C2DM. They must approve the use of this feature to install the application. Depending on the implementation of the application, it may offer users the option of unregistering to receive messages. Uninstalling the application also has the effect of unregistering.
To write Android applications that use C2DM, you must have an application server that can perform the tasks described in Role of the Third-Party Application Server . This section describes the steps you take to create a client application that uses C2DM.
Remember that there is no user interface associated with the C2DM Framework. However you choose to process messages in your application is up to you.
There are two primary steps involved in writing a client application:
Every application must have an AndroidManifest.xml file (with precisely that name) in its root directory. The manifest presents essential information about the application to the Android system, information the system must have before it can run any of the application's code (for more discussion of the manifest file, see the Android Developers Guide ). To use the C2DM feature, the manifest must include the following:
Received C2D_MESSAGE Intents have all key/value pairs sent by the 3rd party server as extras. One special key is collapse_key, which is specified by the sender to allow handling of messages waiting for an off-line device.
Here are excerpts from a manifest that supports C2DM:
<manifest package="com.example.myapp" ...>
<!-- Only this application can receive the messages and registration result --> <permission android:name="com.example.myapp.permission.C2D_MESSAGE " android:protectionLevel="signature" /> <uses-permission android:name="com.example.myapp.permission.C2D_MESSAGE " /> <!-- This app has permission to register and receive message --> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE " /> <!-- Send the registration id to the server --> <uses-permission android:name="android.permission.INTERNET" /> <application...> <!-- Only C2DM servers can send messages for the app. If permission is not set - any other app can generate it --> <receiver android:name=".C2DMReceiver" android:permission="com.google.android.c2dm.permission.SEND <!-- Receive the actual message --> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE " /> <category android:name="com.example.myapp" /> </intent-filter> <!-- Receive the registration id --> <intent-filter> <action android:name="com.google.android.c2dm.intent.REGISTRATION " /> <category android:name="com.example.myapp" /> </intent-filter> </receiver> ... </application> ... </manifest>
An Android application needs to register with C2DM servers before receiving any message. To register it needs to send an Intent (com.google.android.c2dm.intent.REGISTER), with 2 extra parameters:
For example:
Intent registrationIntent = new Intent("com.google.android.c2dm.intent.REGISTER"); registrationIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); // boilerplate registrationIntent.putExtra("sender", emailOfSender); startService(registrationIntent); Registration is not complete until the application sends the registration ID to the third-party application server. The application server uses the registration ID to send messages that are targeted to the application running on that particular device.
To unregister from C2DM:
Intent unregIntent = new Intent("com.google.android.c2dm.intent.UNREGISTER"); unregIntent.putExtra("app", PendingIntent.getBroadcast(this, 0, new Intent(), 0)); startService(unregIntent);
As discussed in Creating the Manifest , the manifest defines a receiver for com.google.android.c2dm.intent.REGISTRATION. It also defines a receiver for com.google.android.c2dm.intent.RECEIVE. Note that both registration and the receiving of messages are implemented as Intents .
The main use of REGISTRATION is to allow the application to receive the registration ID. The Intent can be sent at any time. Google may periodically refresh the receiver ID. An application receiving this Intent with a registration_id parameter must ensure that the third-party application server receives the registration ID. It may do so by saving the registration ID and sending it to the server. If the network is down or there are errors, the application should retry sending the registration ID when the network is up again or the next time it starts. An application should keep track of its registration status and attempt to register again if the process is not fully completed.
The REGISTRATION Intent is generated with an error parameter if the registration couldn't be completed. If that happens, the application should try again later with exponential back off. When the application unregisters, the REGISTRATION Intent will be sent with an unregistered extra parameter.
Here are the possible error codes for the REGISTRATION Intent:
Error Code | Description |
---|---|
SERVICE_NOT_AVAILABLE | The device can't read the response, or there was a 500/503 from the server that can be retried later. The application should use exponential back off and retry. |
ACCOUNT_MISSING | There is no Google account on the phone. The application should ask the user to open the account manager and add a Google account. Fix on the device side. |
AUTHENTICATION_FAILED | Bad password. The application should ask the user to enter his/her password, and let user retry manually later. Fix on the device side. |
TOO_MANY_REGISTRATIONS | The user has too many applications registered. The application should tell the user to uninstall some other applications, let user retry manually. Fix on the device side. |
INVALID_SENDER | The sender account is not recognized. |
PHONE_REGISTRATION_ERROR | Incorrect phone registration with Google. This phone doesn't currently support C2DM. |
The application receives a REGISTRATION Intent broadcast whenever the application server attempts to send a message to it. But registration IDs can be nonexistent or invalid for a variety of reasons:
An application must be prepared to handle every case. For example:
public void onReceive(Context context, Intent intent) { if (intent.getAction().equals("com.google.android.c2dm.intent.REGISTRATION )) { handleRegistration(context, intent); } else if (intent.getAction().equals("com.google.android.c2dm.intent.RECEIVE ")) { handleMessage(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, new messages from the authorized sender will be rejected } else if (registration != null) { // Send the registration ID to the 3rd party site that is sending the messages. // This should be done in a separate thread. // When done, remember that all registration is done. } }
When the C2DM server receives a message from the third-party application server, C2DM extracts the raw key/value pairs from the message payload and passes them to the Android application in the com.google.android.c2dm.intent.RECEIVE Intent as a set of extras. The application extracts the data by key and processes it, whatever that means for that application.
Here is an example:
protected void onReceive(Context context, Intent intent) { String accountName = intent.getExtras().getString(Config.C2DM_ACCOUNT_EXTRA); String message = intent.getExtras().getString(Config.C2DM_MESSAGE_EXTRA);
if (Config.C2DM_MESSAGE_SYNC.equals(message)) { if (accountName != null) { if (Log.isLoggable(TAG, Log.DEBUG)) { Log.d(TAG, "Messaging request received for account " + accountName); } ContentResolver.requestSync(new Account(accountName, SyncAdapter.GOOGLE_ACCOUNT_TYPE),JumpNoteContract.AUTHORITY, new Bundle()); } } }
Here are some guidelines for developing and testing an Android application that uses the C2DM feature:
Before you can write client applications that use the C2DM feature, you must have an HTTPS application server that meets the following criteria:
This section describes how the third-party application server sends messages to a 3rd party client application running on a mobile device.
Before the third-party application server can send a message to an application, it must have received a registration ID from it.
To send a message, the application server issues a POST request to https://android.apis.google.com/c2dm/send that includes the following:
Field | Description |
---|---|
registration_id | The registration ID retrieved from the Android application on the phone. Required. |
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. |
data.<key> | Payload data, expressed as key-value pairs. If present, it will be included in the Intent as application data, with the <key>. There is no limit on the number of key/value pairs, though there is a limit on the total size of the message. Optional. |
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. |
Authorization: GoogleLogin auth=[AUTH_TOKEN] | Header with a ClientLogin Auth token. The cookie must be associated with the ac2dm service. Required. |
This table lists the possible response codes:
Response | Description |
---|---|
200 | Includes body containing:
|
503 | Indicates that the server is temporarily unavailable (i.e., because of timeouts, etc ). Sender must retry later, honoring any Retry-After header included in the response. Application servers must implement exponential back off. Senders that create problems risk being blacklisted. |
401 | Indicates that the ClientLogin AUTH_TOKEN used to validate the sender is invalid. |
Here are a few complete examples to get you started:
To view the source code, open the Source tab and click Browse . From there, you can navigate through the source tree.
C2DM imposes the following limitations: