<li>An Android application on an Android device doesn't need to be running to receive
messages. The system will wake up the Android application via Intent broadcast when the message arrives, as long as the application is set up with the proper
broadcast receiver and permissions.</li>
<li>It does not provide any built-in user interface or other handling for
message data. GCM simply passes raw message data received straight to the
Android application, which has full control of how to handle it. For example, the
application might post a notification, display a custom user interface, or
silently sync data.</li>
<li>It requires devices running Android 2.2 or higher that also have the
Google Play Store application installed, or or an emulator running Android 2.2 with Google APIs. However, you are not limited to deploying your
Android applications through Google Play Store.</li>
<li>It uses an existing connection for Google services. For pre-3.0 devices, this requires users to
set up their Google account on their mobile devices. A Google account is not a requirement on devices running Android 4.0.4 or higher.</li>
</ul>
<h2 id="arch">Architectural Overview</h2>
<p>This section gives an overview of how GCM works. </p>
<p>This table summarizes the key terms and concepts involved in GCM. It is
divided into these categories:</p>
<ul>
<li><strong>Components</strong> — The physical entities that play a role in
GCM.</li>
<li><strong>Credentials</strong> — The IDs and tokens that are used in
different stages of GCM to ensure that all parties have been authenticated, and
that the message is going to the correct place.</li>
<td width="1176">The device that is running an Android application that uses
GCM. This must be a 2.2 Android device that has Google Play Store installed, and it must
have at least one logged in Google account if the device is running a version lower than Android 4.0.4. Alternatively, for testing you can use an emulator running Android 2.2 with Google APIs.</td>
<td>Part of the user notifications feature, which provides a mapping between a user and instances of an app running on multiple devices owned by the user. The {@code notification_key} is the token that GCM uses to fan out notifications to all devices whose registration IDs are associated with the key. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>.</td>
</tr>
<tr>
<td><strong>Notification Key Name</strong></td>
<td>Part of the user notifications feature. The {@code notification_key_name} is a name or identifier (can be a username for a 3rd-party app) that is unique to a given user. It is used by third parties to group together registration IDs for a single user. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>.</td>
(<code>com.google.android.c2dm.intent.REGISTER</code>) includes the sender ID, and the Android application ID.</p>
<p class="note"><strong>Note:</strong> Because there is no lifecycle method that is called when the application is run for
the first time, the registration intent should be sent on <code>onCreate()</code>, but only if the application is not registered yet.
</p>
</li>
<li>If the registration is successful, the GCM server broadcasts a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent which gives the Android application a registration
<p class="note"><strong>Note:</strong> When users uninstall an application, it is not automatically unregistered on GCM. It is only unregistered when the GCM server tries to send a message to the device and the device answers that the application is uninstalled or it does not have a broadcast receiver configured to receive <code>com.google.android.c2dm.intent.RECEIVE</code> intents. At that point, your server should mark the device as unregistered (the server will receive a <code><a href="#unreg_device">NotRegistered</a></code> error).</p>
Note that it might take a few minutes for the registration ID to be completely removed from the GCM server. So if the 3rd-party server sends a message during this time, it will get a valid message ID, even though the message will not be delivered to the device.</p>
<li>A {@code notification_key} and corresponding {@code notification_key_name}, used to map a single user to multiple registration IDs. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>.</li>
<li>Able to store the API key and client registration IDs. The
API key is included in the header of POST requests that send
messages.</li>
</ul>
<h3 id="send-msg">Sending Messages</h3>
<p>This section describes how the 3rd-party application server sends messages to one or more mobile devices. Note the following:</p>
<ul>
<li>A 3rd-party application server can either send messages to a single device or to multiple devices. A message sent to multiple devices simultaneously is called a <em>multicast message</em>.</li>
<li>To send a single message to multiple devices owned by a single user, you can use a {@code notification_key}, as described in <a href="notifications.html">User Notifications</a>.
<p><strong>Note:</strong> If <code>Content-Type</code> is omitted, the format is assumed to be plain text.</p>
</p>
<p>The HTTP body content depends on whether you're using JSON or plain text. For JSON, it must contain a string representing a JSON object with the following fields:</p>
<td>A string array with the list of devices (registration IDs) receiving the message. It must contain at least 1 and at most 1000 registration IDs. To send a multicast message, you must use JSON. For sending a single message to a single device, you could use a JSON object with just 1 registration id, or plain text (see below). A request must include a recipient—this can be either a registration ID, an array of registration IDs, or a {@code notification_key}.</td>
</tr>
<tr>
<td><code>notification_key</code></td>
<td>A string that maps a single user to multiple registration IDs associated with that user. This
allows a 3rd-party server to send a single message to multiple app instances (typically on multiple devices) owned by a single user. A 3rd-party server can use {@code notification_key} as the target for a message instead of an individual registration ID (or array of registration IDs). The maximum number of members allowed for a {@code notification_key} is 10. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>. Optional.</td>
</tr>
<tr>
<td><code>notification_key_name</code></td>
<td>A name or identifier (can be a username for a 3rd-party app) that is unique to a given user. It is used by 3rd parties to group together registration IDs for a single user. The <code>notification_key_name</code> should be uniquely named per app in case you have multiple apps for the same project ID. This ensures that notifications only go to the intended target app. For more discussion of this topic, see <a href="notifications.html">User Notifications</a>.</td>
included in the Intent as application data, with the key being the extra's name. For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>.
There is no limit on the number of key/value pairs, though there is a limit on the total size of the message (4kb). The values could be any JSON object, but we recommend using strings, since the values will be converted to strings in the GCM server anyway. If you want to include objects or other non-string data types (such as integers or booleans), you have to do the conversion to string yourself. Also note that the key cannot be a reserved word (<code>from</code> or any word starting with <code>google.</code>). To complicate things slightly, there are some reserved words (such as <code>collapse_key</code>) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.</td>
<td>How long (in seconds) the message should be kept on GCM storage if the device is offline. Optional (default time-to-live is 4 weeks, and must be set as a JSON number).</td>
<td>A string containing the package name of your application. When set, messages will only be sent to registration IDs that match the package name. Optional.
<td>If included, allows developers to test their request without actually sending a message. Optional. The default value is <code>false</code>, and must be a JSON boolean.
<p>If you are using plain text instead of JSON, the message fields must be set as HTTP parameters sent in the body, and their syntax is slightly different, as described below:
<table>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
<tr>
<td><code>registration_id</code></td>
<td>Must contain the registration ID of the single device receiving the message. Required.</td>
</tr>
<tr>
<td><code>collapse_key</code></td>
<td>Same as JSON (see previous table). Optional.</td>
<td>Payload data, expressed as parameters prefixed with <code>data.</code> and suffixed as the key. For instance, a parameter of <code>data.score=3x1</code> would result in an intent extra named <code>score</code> whose value is the string <code>3x1</code>. There is no limit on the number of key/value parameters, though there is a limit on the total size of the message. Also note that the key cannot be a reserved word (<code>from</code> or any word starting with
<code>google.</code>). To complicate things slightly, there are some reserved words (such as <code>collapse_key</code>) that are technically allowed in payload data. However, if the request also contains the word, the value in the request will overwrite the value in the payload data. Hence using words that are defined as field names in this table is not recommended, even in cases where they are technically allowed. Optional.</td>
<td>Should be represented as <code>1</code> or <code>true</code> for <code>true</code>, anything else for <code>false</code>. Optional. The default value is <code>false</code>.</td>
</tr>
<tr>
<td><code>time_to_live</code></td>
<td>Same as JSON (see previous table). Optional.</td>
<p>If you want to test your request (either JSON or plain text) without delivering the message to the devices, you can set an optional HTTP or JSON parameter called <code>dry_run</code> with the value <code>true</code>. The result will be almost identical to running the request without this parameter, except that the message will not be delivered to the devices. Consequently, the response will contain fake IDs for the message and multicast fields (see <a href="#response">Response format</a>).</p>
<p>When the message is processed successfully, the HTTP response has a 200 status and the body contains more information about the status of the message (including possible errors). When the request is rejected,
the HTTP response contains a non-200 status code (such as 400, 401, or 503).</p>
<p>The following table summarizes the statuses that the HTTP response header might contain. Click the troubleshoot link for advice on how to deal with each type of error.</p>
<table border=1>
<tr>
<th>Response</th>
<th>Description</th>
</tr>
<tr>
<td>200</td>
<td>Message was processed successfully. The response body will contain more details about the message status, but its format will depend whether the request was JSON or plain text. See <a href="#success">Interpreting a success response</a> for more details.</td>
</tr>
<tr>
<td>400</td>
<td><span id="internal-source-marker_0.2">Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields (for instance, passing a string where a number was expected). The exact failure reason is described in the response and the problem should be addressed before the request can be retried.</td>
</tr>
<tr>
<td>401</td>
<td>There was an error authenticating the sender account. <a href="#auth_error">Troubleshoot</a></td>
<td>Errors in the 500-599 range (such as 500 or 503) indicate that there was an internal error in the GCM server while trying to process the request, or that the server is temporarily unavailable (for example, because of timeouts). Sender must retry later, honoring any <code>Retry-After</code> header included in the response. Application servers must implement exponential back-off. <a href="#internal_error">Troubleshoot</a></td>
<h4 id="success">Interpreting a success response</h4>
<p>When a JSON request is successful (HTTP status code 200), the response body contains a JSON object with the following fields:</p>
<table>
<tr>
<th>Field</th>
<th>Description</th>
</tr>
<tr>
<td><code>multicast_id</code></td>
<td>Unique ID (number) identifying the multicast message.</td>
</tr>
<tr>
<td><code>success</code></td>
<td>Number of messages that were processed without an error.</td>
</tr>
<tr>
<td><code>failure</code></td>
<td>Number of messages that could not be processed.</td>
</tr>
<tr>
<td><code>canonical_ids</code></td>
<td>Number of results that contain a canonical registration ID. See <a href="adv.html#canonical">Advanced Topics</a> for more discussion of this topic.</td>
</tr>
<tr>
<td><code>results</code></td>
<td>Array of objects representing the status of the messages processed. The objects are listed in the same order as the request (i.e., for each registration ID in the request, its result is listed in the same index in the response) and they can have these fields:<br>
<ul>
<li><code>message_id</code>: String representing the message when it was successfully processed.</li>
<li><code>registration_id</code>: If set, means that GCM processed the message but it has another canonical registration ID for that device, so sender should replace the IDs on future requests (otherwise they might be rejected). This field is never set if there is an error in the request.
<li><code>error</code>: String describing an error that occurred while processing the message for that recipient. The possible values are the same as documented in the above table, plus "Unavailable" (meaning GCM servers were busy and could not process the message for that particular recipient, so it could be retried).</li>
</ul></td>
</tr>
</table>
<p>If the value of <code>failure</code> and <code>canonical_ids</code> is 0, it's not necessary to parse the remainder of the response. Otherwise, we recommend that you iterate through the results field and do the following for each object in that list:</p>
<ul>
<li>If <code>message_id</code> is set, check for <code>registration_id</code>:
<ul>
<li>If <code>registration_id</code> is set, replace the original ID with the new value (canonical ID) in your server database. Note that the original ID is not part of the result, so you need to obtain it from the list of <code>registration_ids</code> passed in the request (using the same index).</li>
</ul>
</li>
<li>Otherwise, get the value of <code>error</code>:
<ul>
<li>If it is <code>Unavailable</code>, you could retry to send it in another request.</li>
<li>If it is <code>NotRegistered</code>, you should remove the registration ID from your server database because the application was uninstalled from the device or it does not have a broadcast receiver configured to receive <code>com.google.android.c2dm.intent.RECEIVE</code> intents.</li>
<li>Otherwise, there is something wrong in the registration ID passed in the request; it is probably a non-recoverable error that will also require removing the registration from the server database. See <a href="#error_codes">Interpreting an error response</a> for all possible error values.</li>
</ul>
</li>
</ul>
<p>When a plain-text request is successful (HTTP status code 200), the response body contains 1 or 2 lines in the form of key/value pairs.
The first line is always available and its content is either <code>id=<em>ID of sent message</em></code> or <code>Error=<em>GCM error code</em></code>. The second line, if available,
has the format of <code>registration_id=<em>canonical ID</em></code>. The second line is optional, and it can only be sent if the first line is not an error. We recommend handling the plain-text response in a similar way as handling the JSON response:</p>
<ul>
<li>If first line starts with <code>id</code>, check second line:
<ul>
<li>If second line starts with <code>registration_id</code>, gets its value and replace the registration IDs in your server database.</li>
</ul>
</li>
<li>Otherwise, get the value of <code>Error</code>:
<ul>
<li>If it is <code>NotRegistered</code>, remove the registration ID from your server database.</li>
<li>Otherwise, there is probably a non-recoverable error (<strong>Note: </strong>Plain-text requests will never return <code>Unavailable</code> as the error code, they would have returned a 500 HTTP status instead).</li>
</ul>
</li>
</ul>
<h4 id="error_codes">Interpreting an error response</h4>
<p>Here are the recommendations for handling the different types of error that might occur when trying to send a message to a device:</p>
<dd>Check that the request contains a registration ID (either in the <code>registration_id</code> parameter in a plain text message, or in the <code>registration_ids</code> field in JSON).
<br/>Happens when error code is <code>MissingRegistration</code>.</dd>
<dd>Check the formatting of the registration ID that you pass to the server. Make sure it matches the registration ID the phone receives in the <code>com.google.android.c2dm.intent.REGISTRATION</code> intent and that you're not truncating it or adding additional characters.
<br/>Happens when error code is <code>InvalidRegistration</code>.</dd>
<dd>A registration ID is tied to a certain group of senders. When an application registers for GCM usage, it must specify which senders are allowed to send messages. Make sure you're using one of those when trying to send messages to the device. If you switch to a different sender, the existing registration IDs won't work.
Happens when error code is <code>MismatchSenderId</code>.</dd>
<dd>An existing registration ID may cease to be valid in a number of scenarios, including:
<ul>
<li>If the application manually unregisters by issuing a <span class="prettyprint pretty-java"><code>com.google.android.c2dm.intent.UNREGISTER</code></span><code> </code>intent.</li>
<li>If the application is automatically unregistered, which can happen (but is not guaranteed) if the user uninstalls the application.</li>
<li>If the registration ID expires. Google might decide to refresh registration IDs. </li>
<li>If the application is updated but the new version does not have a broadcast receiver configured to receive <code>com.google.android.c2dm.intent.RECEIVE</code> intents.</li>
<dd>The total size of the payload data that is included in a message can't exceed 4096 bytes. Note that this includes both the size of the keys as well as the values.
<br/>Happens when error code is <code>MessageTooBig</code>.</dd>
<dt id="invalid_datakey"><strong>Invalid Data Key</strong></dt>
<dd>The payload data contains a key (such as <code>from</code> or any value prefixed by <code>google.</code>) that is used internally by GCM in the <code>com.google.android.c2dm.intent.RECEIVE</code> Intent and cannot be used. Note that some words (such as <code>collapse_key</code>) are also used by GCM but are allowed in the payload, in which case the payload value will be overridden by the GCM value.
<br />
Happens when the error code is <code>InvalidDataKey</code>.</dd>
<dt id="ttl_error"><strong>Invalid Time To Live</strong></dt>
<dd>The value for the Time to Live field must be an integer representing a duration in seconds between 0 and 2,419,200 (4 weeks). Happens when error code is <code>InvalidTtl</code>.
Check that the token you're sending inside the <code>Authorization</code> header is the correct API key associated with your project. You can check the validity of your API key by running the following command:<br/>
Happens when the HTTP status code is between 501 and 599, or when the <code>error</code> field of a JSON object in the results array is <code>Unavailable</code>.
section), but if the error persists, please report the problem in the <a href="https://groups.google.com/forum/?fromgroups#!forum/android-gcm">android-gcm group</a>.
<br />
Happens when the HTTP status code is 500, or when the <code>error</code> field of a JSON
object in the results array is <code>InternalServerError</code>.
<p>This section shows a few examples of responses indicating messages that were processed successfully. See <a href="#example-requests">Example requests</a> for the requests these responses are based on.</p>
<p> Here is a simple case of a JSON message successfully sent to one recipient without canonical IDs in the response:</p>
<p>Or if the request was in plain-text format:</p>
<pre class="prettyprint">id=1:08
</pre>
<p>Here are JSON results for 6 recipients (IDs 4, 8, 15, 16, 23, and 42 respectively) with 3 messages successfully processed, 1 canonical registration ID returned, and 3 errors:</p>
<p class="note"><strong>Note:</strong> Stats on the Google API Console are not enabled for GCM. You must use the <a href="http://play.google.com/apps/publish">Developer Console</a>.</p>