Home | History | Annotate | Download | only in gcm
      1 page.title=GCM Architectural Overview
      2 @jd:body
      3 
      4 <div id="qv-wrapper">
      5 <div id="qv">
      6 
      7 <h2>Quickview</h2>
      8 
      9 <ul>
     10 <li>Get an introduction to key GCM terms and concepts.</li>
     11 <li>Learn the basic features of a GCM application.</li>
     12 <li>Understand the role of the 3rd-party application server, and how to send messages and process results.</li>
     13 </ul>
     14 
     15 
     16 <h2>In this document</h2>
     17 
     18 <ol class="toc">
     19   <li><a href="#intro">Introduction</a> </li>
     20   <li><a href="#arch">Architectural Overview</a>
     21     <ol>
     22       <li><a href="#lifecycle">Lifecycle Flow</a></li>
     23         <ol>
     24           <li><a href="#register">Enable GCM</a></li>
     25           <li><a href="#push-process">Send a message</a></li>
     26           <li><a href="#receiving">Receive a message</a></li>
     27         </ol>
     28       <li><a href="#user">What Does the User See?</a></li>
     29     </ol>
     30   </li>
     31   <li><a href="#server">Role of  the 3rd-party Application Server</a>
     32     <ol class="toc">
     33       <li><a href="#send-msg">Sending Messages</a>
     34         <ol>
     35           <li><a href="#request">Request format</a></li>
     36           <li><a href="#response">Response format</a></li>
     37         </ol>
     38       </li>
     39     </ol>
     40     <li><a href="#stats">Viewing Statistics</a>
     41   </li>
     42 </ol>
     43 
     44 
     45 
     46 </div>
     47 </div>
     48 
     49 <p>Google Cloud Messaging for Android (GCM) is a free service that helps
     50 developers  send data from servers to their Android applications on  Android
     51 devices, and upstream messages from the user's device back to the cloud.
     52 This could be a lightweight message telling the Android application
     53 that there is new data to be fetched from the server (for instance, a movie
     54 uploaded by a friend), or it could be a message containing up to 4kb of payload
     55 data (so apps like instant messaging can consume the message directly). The GCM
     56 service handles all aspects  of queueing of messages and delivery to the target
     57 Android application running  on the target device.</p>
     58 
     59 <p>GCM introduces GCM Cloud Connection Server (CCS), which you can use
     60 in tandem with GCM HTTP service/endpoint/APIs.
     61 CCS uses XMPP, and it offers asynchronous, bidirectional
     62 messaging. For more information, see
     63 <a href="ccs.html">GCM Cloud Connection Server</a>.
     64   
     65   
     66 <p class="note"> To jump right into using GCM with your Android
     67   applications, see the instructions in <a href="gs.html">Getting Started</a>.</p>
     68 
     69 
     70 <h2 id="intro">Introduction</h2>
     71 
     72 <p>Here are the primary characteristics of Google Cloud 
     73 Messaging (GCM):</p>
     74 
     75 <ul>
     76   <li>It allows 3rd-party application servers to send messages to
     77 their Android applications.</li>
     78   <li>Using the <a href="ccs.html">GCM Cloud Connection Server</a>, you can receive upstream messages from the user's device.</li>
     79   <li>An Android application on an Android device doesn't need to be running to receive
     80 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
     81 broadcast receiver and permissions.</li>
     82   <li>It does not provide any  built-in user interface or other handling for
     83 message data. GCM  simply passes raw message data received straight to the
     84 Android application,  which has full control of how to handle it. For example, the
     85 application might post a notification, display a custom user interface, or 
     86 silently sync data.</li>
     87   <li>It requires devices running Android 2.2 or higher that also have the
     88 Google Play Store application installed, or or an emulator running Android 2.2 with Google APIs. However, you are not limited to deploying your
     89 Android applications through Google Play Store.</li>
     90   <li>It uses an existing connection for Google services. For pre-3.0 devices, this requires users to
     91 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>
     92 </ul>
     93 <h2 id="arch">Architectural Overview</h2>
     94 <p>This section gives an overview of how GCM works. </p>
     95 <p>This table summarizes the key terms and concepts involved in GCM. It is
     96 divided into these categories:</p>
     97 <ul>
     98   <li><strong>Components</strong> &mdash; The physical entities that play a role in
     99 GCM.</li>
    100   <li><strong>Credentials</strong> &mdash; The IDs and tokens that are used in
    101 different stages of GCM to ensure that all parties have been authenticated, and
    102 that the message is going to the correct place.</li>
    103 </ul>
    104 
    105 <table>
    106   <tr>
    107     <th colspan="2">Components</th>
    108   </tr>
    109   <tr>
    110     <td width="165"><strong>Mobile Device</strong></td>
    111     <td width="1176">The device that is running an Android application that uses
    112 GCM. This must be a 2.2 Android device that has Google Play Store installed, and it must
    113 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>
    114   </tr>
    115   <tr>
    116     <td><strong>3rd-party Application Server</strong></td>
    117     <td>An application server that  developers  set up as part of implementing
    118 GCM in their applications. The 3rd-party application server sends data to an
    119 Android application on the device via the GCM server.</td>
    120   </tr>
    121   <tr>
    122     <td><strong>GCM Servers</strong></td>
    123     <td>The Google servers involved in taking messages from the 3rd-party
    124 application server and sending them to the device. </td>
    125   </tr>
    126   <tr>
    127     <th colspan="2"><strong>Credentials</strong></th>
    128   </tr>
    129   <tr>
    130     <td><strong>Sender ID</strong></td>
    131     <td>A project number you acquire from the API console, as described in <a href="gs.html#create-proj">Getting Started</a>. The sender
    132 ID is used in the <a href="#registering">registration process</a> to identify an
    133 Android application that is permitted to send messages to the device.</td>
    134   </tr>
    135   <tr>
    136     <td><strong>Application ID</strong></td>
    137     <td>The Android application that is registering to receive messages. The Android application
    138 is identified by the package name from the <a href="#manifest">manifest</a>.
    139 This  ensures that the messages are targeted to the correct Android application.</td>
    140   </tr>
    141   <tr>
    142     <td><strong>Registration ID</strong></td>
    143     <td>An ID issued by the GCM servers to the Android application that allows
    144 it to receive messages. Once the Android application has the registration ID, it sends
    145 it to the 3rd-party application server, which uses it to identify each device 
    146 that has registered to receive messages for a given Android application. In other words,
    147 a registration ID is tied to a particular Android application running on a particular
    148 device.
    149 <br/>
    150 <br/>
    151 <strong>Note:</strong> If you use 
    152 <a href="https://developer.android.com/google/backup/index.html">backup and restore</a>,
    153 you should explicitly avoid backing up registration IDs. When you back up
    154 a device, apps back up shared prefs indiscriminately. If you don't explicitly
    155 exclude the GCM registration ID, it could get reused on a new device,
    156 which would cause delivery errors.
    157 </td>
    158   </tr>
    159   <tr>
    160     <td><strong>Google User Account</strong></td>
    161     <td>For GCM to work, the mobile device must include at least one Google account if the device is running a version lower than Android 4.0.4.</td>
    162   </tr>
    163   <tr>
    164     <td><strong>Sender Auth Token</strong></td>
    165     <td>An API key that is saved on the 3rd-party application
    166 server that gives the application server authorized access to Google services.
    167 The API key is included in the header of POST requests  that send messages.</td>
    168   </tr>
    169 
    170   <tr>
    171     <td><strong>Notification Key</strong></td>
    172     <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>
    173   </tr>
    174 
    175 <tr>
    176     <td><strong>Notification Key Name</strong></td>
    177     <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>
    178   </tr>
    179 
    180 </table>
    181 
    182 <h3 id="lifecycle">Lifecycle Flow</h3>
    183 
    184 <ul>
    185   <li><a href="#register">Enable GCM</a>. An Android application running on a
    186 mobile device registers to receive messages.</li>
    187  <li><a href="notifications.html">User Notifications</a>. A 3rd-party server can optionally group multiple registration IDs
    188 in a {@code notification_key} to send messages to multiple devices owned by a single user.</li>
    189   <li><a href="#push-process">Send a message</a>. A 3rd-party application
    190 server sends messages to the device.</li>
    191   <li><a href="#receiving">Receive a message</a>. An Android application
    192 receives a message from a GCM server.</li>
    193 </ul>
    194 
    195 <p>These processes are described in more detail below.</p>
    196 
    197 <h4 id="register">Enable GCM</h4>
    198 
    199 <p>This is the sequence of events that occurs when an Android application
    200 running on a mobile device registers to receive messages:<span
    201 class="red-text"></span></p>
    202 
    203 <ol>
    204   <li>The first time the Android application needs to use the messaging service, it
    205 fires off a registration Intent to a GCM server.
    206     <p>This registration Intent
    207 (<code>com.google.android.c2dm.intent.REGISTER</code>) includes the sender ID, and the Android application ID.</p>
    208 <p class="note"><strong>Note:</strong> Because there is no lifecycle method that is called when the application is run for
    209 the first time, the registration intent should be sent on <code>onCreate()</code>, but only if the application is not registered yet.
    210 </p>
    211   </li>
    212   <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
    213 ID. 
    214     <p>The Android application should store this ID for later use (for instance, to check on <code>onCreate()</code> if it is already registered).
    215 Note that Google may periodically refresh the registration ID, so you should design your Android application
    216 with the understanding that the <code>com.google.android.c2dm.intent.REGISTRATION</code> intent may be called
    217 multiple times. Your Android application needs to be able to respond
    218 accordingly.</p></li>
    219   <li>To complete the registration, the Android application sends the registration ID to
    220 the application server. The application server typically stores the registration
    221 ID in a database. </li>
    222 </ol>
    223 
    224 <p>The registration ID lasts until the Android application explicitly unregisters
    225 itself, or until Google refreshes the registration ID for your Android application.</p>
    226 
    227 <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>
    228   <p>
    229 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>
    230 
    231 
    232 
    233 
    234 <h4 id="push-process">Send a Message</h4>
    235 
    236 <p>For an application server to send a  message to an Android application, the following things must be in
    237 place:</p>
    238 
    239 <ul>
    240   <li>The Android application has stored a target that it can specify as the recipient of a message. This can be one of the following:
    241   <ul>
    242     <li>A single registration ID (or an array of registration IDs) that allows the app to receive messages
    243 for a particular device.</li>
    244     <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>
    245   </ul>
    246     </li>
    247 
    248 <li>An API key. This is something that the developer must have already
    249 set up on the application server for the Android application (for more discussion, see
    250 <a href="#server">Role of the 3rd-party Application Server</a>). Now it will
    251 get used to send messages to the device. </li>
    252 </ul>
    253 
    254 <p>Here is the sequence of events that occurs when the application server sends a 
    255 message:</p>
    256 
    257 <ol>
    258   <li>The application server sends a  message to  GCM servers.</li>
    259   <li>Google enqueues and stores the message in case the device is
    260 offline.</li>
    261   <li>When the device is online, Google sends the message to the device. </li>
    262   <li>On the device, the system  broadcasts the  message to the specified
    263 Android application via Intent broadcast with proper permissions, so that only the
    264 targeted Android application gets the message. This wakes the Android application up. The
    265 Android application does not need to be running beforehand to receive the message.</li>
    266   <li>The Android application processes the message. If the Android application is doing
    267 non-trivial processing, you may want to grab a {@link android.os.PowerManager.WakeLock} and do any processing in a Service.</li>
    268 </ol>
    269 
    270 <p> An Android application can  unregister GCM if it no longer wants to receive 
    271 messages.</p>
    272 
    273 <h4 id="receiving">Receive a Message</h4>
    274 
    275 <p>This is the sequence of events that occurs when an Android application
    276 installed on a mobile device receives a message:</p>
    277 
    278 <ol>
    279   <li>The system receives the incoming message and extracts the raw key/value
    280 pairs from the message payload, if any.</li>
    281   <li>The system passes the key/value pairs to the targeted Android application
    282 in a <code>com.google.android.c2dm.intent.RECEIVE</code> Intent as a set of
    283 extras.</li>
    284   <li>The Android application extracts the raw data
    285 from the <code>com.google.android.c2dm.intent.RECEIVE</code><code> </code>Intent by key and processes the data.</li>
    286 </ol>
    287 
    288 <h3 id="user">What Does the User See?</h3>
    289 
    290 <p>When mobile device users install Android applications that include GCM, the Google Play Store will inform them that the Android application
    291 includes GCM. They must approve the use of this feature to install the
    292 Android application. </p>
    293 
    294 
    295 <h2 id="server">Role of the 3rd-party Application Server</h2>
    296 
    297 <p>Before you can write client Android applications that use the GCM feature, you must
    298 have an  application server that meets the following criteria:</p>
    299 
    300 <ul>
    301   <li>Able to communicate with your client.</li>
    302   <li>Able to  fire off HTTPS requests to the GCM server.</li>
    303   <li>Able to handle requests and resend them as needed, using <a href="http://en.wikipedia.org/wiki/Exponential_backoff">exponential back-off.</a></li>
    304   <li>Able to store the API key and client registration IDs. The
    305 API key is included in the header of POST requests that send
    306 messages.</li>
    307 </ul>
    308 
    309 <h3 id="send-msg">Sending Messages</h3>
    310 <p>This section describes how the 3rd-party application server sends messages to one or more mobile devices. Note the following:</p>
    311 <ul>
    312   <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>
    313   <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>.
    314   
    315   <li>You have 2 choices in how you construct requests and responses: plain text or JSON.</li>
    316   <li>However, to send multicast messages, you must use JSON. Plain text will not work.</li>
    317 </ul>
    318 <p>Before the 3rd-party application server can send a  message to an
    319   Android application, it must have received a registration ID from it.</p>
    320 <h4 id="request">Request format</h4>
    321 <p>To send a  message, the application server issues a POST request to <code>https://android.googleapis.com/gcm/send</code>.</p>
    322 <p>A  message request is made of 2 parts: HTTP header and HTTP body.</p>
    323 
    324 <p>The HTTP header must contain the following headers:</p>
    325 <ul>
    326   <li><code>Authorization</code>: key=YOUR_API_KEY</li>
    327   <li><code>Content-Type</code>: <code>application/json</code> for JSON; <code>application/x-www-form-urlencoded;charset=UTF-8</code> for plain text.
    328   </li>
    329 </ul>
    330 
    331 <p>For example:
    332 </p>
    333 <pre>Content-Type:application/json
    334 Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA
    335 
    336 {
    337   "registration_ids" : ["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx..."],
    338   "data" : {
    339     ...
    340   },
    341 }</pre>
    342 <p class="note">
    343   <p><strong>Note:</strong> If <code>Content-Type</code> is omitted, the format is assumed to be plain text.</p>
    344 </p>
    345 
    346 <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>
    347 <table>
    348   <tr>
    349     <th>Field</th>
    350     <th>Description</th>
    351   </tr>
    352   <tr>
    353     <td><code>registration_ids</code></td>
    354     <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&mdash;this can be either a registration ID, an array of registration IDs, or a {@code notification_key}.</td>
    355   </tr>
    356  <tr>
    357     <td><code>notification_key</code></td>
    358     <td>A string that maps a single user to multiple registration IDs associated with that user. This
    359 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>
    360   </tr>
    361 
    362 <tr>
    363     <td><code>notification_key_name</code></td>
    364     <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>
    365   </tr>
    366 
    367   <tr>
    368     <td><code>collapse_key</code></td>
    369     <td>An arbitrary string (such as &quot;Updates Available&quot;) that is used to collapse a group of like messages
    370 when the device is offline, so that only the last message gets sent to the
    371 client. This is intended to avoid sending too many messages to the phone when it
    372 comes back online. Note that since there is no guarantee of the order in which
    373 messages get sent, the &quot;last&quot; message may not actually be the last
    374 message sent by the application server. See <a href="adv.html#collapsible">Advanced Topics</a> for more discussion of this topic. Optional.</td>
    375   </tr>
    376   <tr>
    377     <td><code>data</code></td>
    378     <td>A JSON object whose fields represents the key-value pairs of the message's payload data. If present, the payload data it will be
    379 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>. 
    380 
    381 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>
    382 
    383 
    384   </tr>
    385   <tr>
    386     <td><code>delay_while_idle</code></td>
    387     <td>If included, indicates that the message should not be sent immediately
    388 if the device is idle. The server will wait for the device to become active, and
    389 then only the last message for each <code>collapse_key</code> value will be
    390 sent. Optional. The default value is <code>false</code>, and must be a JSON boolean.</td>
    391   </tr>
    392   <tr>
    393     <td><code>time_to_live</code></td>
    394     <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>
    395   </tr>
    396 <tr>
    397   <td><code>restricted_package_name</code></td>
    398   <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.
    399   </td>
    400 </tr>
    401 <tr>
    402   <td><code>dry_run</code></td>
    403   <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.
    404   </td>
    405 </tr>
    406 </table>
    407 
    408 <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:
    409 <table>
    410   <tr>
    411     <th>Field</th>
    412     <th>Description</th>
    413   </tr>
    414   <tr>
    415     <td><code>registration_id</code></td>
    416     <td>Must contain the registration ID of the single device receiving the message. Required.</td>
    417   </tr>
    418   <tr>
    419     <td><code>collapse_key</code></td>
    420     <td>Same as JSON (see previous table). Optional.</td>
    421   </tr>
    422   <tr>
    423     <td><code>data.&lt;key&gt;</code></td>
    424 
    425     <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 
    426 <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>
    427 
    428   </tr>
    429   <tr>
    430     <td><code>delay_while_idle</code></td>
    431     <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>
    432   </tr>
    433   <tr>
    434     <td><code>time_to_live</code></td>
    435     <td>Same as JSON (see previous table). Optional.</td>
    436   </tr>
    437 <tr>
    438   <td><code>restricted_package_name</code></td>
    439   <td>Same as JSON (see previous table). Optional.
    440   </td>
    441 </tr>
    442 <tr>
    443   <td><code>dry_run</code></td>
    444   <td>Same as JSON (see previous table). Optional.
    445   </td>
    446 </tr>
    447 </table>
    448 
    449 <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>
    450 
    451   <h4 id="example-requests">Example requests</h4>
    452   <p>Here is the smallest possible request (a message without any parameters and just one recipient) using JSON:</p>
    453   <pre class="prettyprint pretty-json">{ &quot;registration_ids&quot;: [ &quot;42&quot; ] }</pre>
    454   
    455   <p>And here the same example using plain text:</p>
    456   <pre class="prettyprint">registration_id=42</pre>
    457   
    458   <p> Here is a message with a payload and 6 recipients:</p>
    459   <pre class="prettyprint pretty-HTML">{ "data": {
    460     "score": "5x1",
    461     "time": "15:10"
    462   },
    463   "registration_ids": ["4", "8", "15", "16", "23", "42"]
    464 }</pre>
    465   <p>Here is a message with all optional fields set and 6 recipients:</p>
    466   <pre class="prettyprint pretty-json">{ "collapse_key": "score_update",
    467   "time_to_live": 108,
    468   "delay_while_idle": true,
    469   "data": {
    470     "score": "4x8",
    471     "time": "15:16.2342"
    472   },
    473   "registration_ids":["4", "8", "15", "16", "23", "42"]
    474 }</pre>
    475   <p>And here is the same message using plain-text format (but just 1 recipient):  </p>
    476   
    477   <pre class="prettyprint">collapse_key=score_update&amp;time_to_live=108&amp;delay_while_idle=1&amp;data.score=4x8&amp;data.time=15:16.2342&amp;registration_id=42
    478   </pre>
    479 
    480 <p class="note"><strong>Note:</strong> If your organization has a firewall 
    481 that restricts the traffic to or 
    482 from the Internet, you need to configure it to allow connectivity with GCM in order for
    483 your Android devices to receive messages. 
    484 The ports to open are: 5228, 5229, and 5230. GCM typically only uses 5228, but
    485 it sometimes uses 5229 and 5230. GCM doesn't provide specific IPs, so you should allow
    486 your firewall to accept outgoing connections to all IP addresses
    487 contained in the IP blocks listed in Google's ASN of 15169.</p>
    488 
    489 
    490 <h4 id="response">Response format</h4>
    491 
    492 <p>There are two possible outcomes when trying to send a message:</p>
    493 <ul>
    494   <li>The message is processed successfully.</li>
    495   <li>The GCM server rejects the request.</li>
    496 </ul>
    497 
    498 <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, 
    499 the HTTP response contains a non-200 status code (such as 400, 401, or 503).</p>
    500 
    501 <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>
    502 <table border=1>
    503   <tr>
    504     <th>Response</th>
    505     <th>Description</th>
    506   </tr>
    507   <tr>
    508     <td>200</td>
    509     <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>
    510   </tr>
    511   <tr>
    512     <td>400</td>
    513     <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>
    514   </tr>
    515   <tr>
    516     <td>401</td>
    517     <td>There was an error authenticating the sender account. <a href="#auth_error">Troubleshoot</a></td>
    518   </tr>
    519   <tr>
    520     <td>5xx</td>
    521     <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>
    522   </tr>
    523 </table>
    524 
    525 <h4 id="success">Interpreting a success response</h4>
    526 <p>When a JSON request is successful (HTTP status code 200), the response body contains a JSON object with the following fields:</p>
    527 <table>
    528   <tr>
    529     <th>Field</th>
    530     <th>Description</th>
    531   </tr>
    532   <tr>
    533     <td><code>multicast_id</code></td>
    534     <td>Unique ID (number) identifying the multicast message.</td>
    535   </tr>
    536   <tr>
    537     <td><code>success</code></td>
    538     <td>Number of messages that were processed without an error.</td>
    539   </tr>
    540   <tr>
    541     <td><code>failure</code></td>
    542     <td>Number of messages that could not be processed.</td>
    543   </tr>
    544   <tr>
    545     <td><code>canonical_ids</code></td>
    546     <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>
    547   </tr>
    548   <tr>
    549     <td><code>results</code></td>
    550     <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>
    551       <ul>
    552         <li><code>message_id</code>: String representing the message when it was successfully processed.</li>
    553         <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.
    554         </li>
    555         <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 &quot;Unavailable&quot;  (meaning GCM servers were busy and could not process the message for that  particular recipient, so it could be retried).</li>
    556     </ul></td>
    557   </tr>
    558 </table>
    559 <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>
    560 <ul>
    561   <li>If <code>message_id</code> is set, check for <code>registration_id</code>:
    562     <ul>
    563       <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>
    564     </ul>
    565   </li>
    566   <li>Otherwise, get the value of <code>error</code>:
    567     <ul>
    568       <li>If it is <code>Unavailable</code>, you could retry to send it in another request.</li>
    569       <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>
    570       <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>
    571     </ul>
    572   </li>
    573 </ul>
    574 
    575 <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.
    576 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, 
    577 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>
    578 <ul>
    579   <li>If first line starts with <code>id</code>, check second line:
    580     <ul>
    581       <li>If second line starts with <code>registration_id</code>, gets its value and replace the registration IDs in your server database.</li>
    582     </ul>
    583   </li>
    584   <li>Otherwise, get the value of <code>Error</code>:
    585     <ul>
    586       <li>If it is <code>NotRegistered</code>, remove the registration ID from your server database.</li>
    587       <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>
    588     </ul>
    589   </li>
    590 </ul>
    591 
    592 <h4 id="error_codes">Interpreting an error response</h4>
    593 <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>
    594 
    595 <dl>
    596 <dt id="missing_reg"><strong>Missing Registration ID</strong></dt>
    597 <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). 
    598 <br/>Happens when error code is <code>MissingRegistration</code>.</dd>
    599 
    600 <dt id="invalid_reg"><strong>Invalid Registration ID</strong></dt>
    601 <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. 
    602 <br/>Happens when error code is <code>InvalidRegistration</code>.</dd>
    603 
    604 <dt id="mismatched_sender"><strong>Mismatched Sender</strong></dt>
    605 <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. 
    606 Happens when error code is <code>MismatchSenderId</code>.</dd>
    607 
    608 <dt id="unreg_device"><strong>Unregistered Device</strong></dt>
    609 <dd>An existing registration ID may cease to be valid in a number of scenarios, including:
    610 <ul>
    611   <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>
    612   <li>If the application is automatically unregistered, which can happen (but is not guaranteed) if the user uninstalls the application.</li>
    613   <li>If the registration ID expires. Google might decide to refresh registration IDs. </li>
    614   <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>
    615 </ul>
    616 For all these cases, you should remove this registration ID from the 3rd-party server and stop using it to send 
    617 messages. 
    618 <br/>Happens when error code is <code>NotRegistered</code>.</dd>
    619 
    620 <dt id="big_msg"><strong>Message Too Big</strong></dt>
    621   <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. 
    622 <br/>Happens when error code is <code>MessageTooBig</code>.</dd>
    623 
    624 <dt id="invalid_datakey"><strong>Invalid Data Key</strong></dt>
    625 <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. 
    626 <br />
    627 Happens when the error code is <code>InvalidDataKey</code>.</dd>
    628 
    629 <dt id="ttl_error"><strong>Invalid Time To Live</strong></dt>
    630   <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>.
    631 </dd>
    632 
    633   <dt id="auth_error"><strong>Authentication Error</strong></dt>
    634   <dd>The sender account that you're trying to use to send a message couldn't be authenticated. Possible causes are: <ul>
    635 <li>Authorization header missing or with invalid syntax.</li>
    636 <li>Invalid project number sent as key.</li>
    637 <li>Key valid but with GCM service disabled.</li>
    638 <li>Request originated from a server not whitelisted in the Server Key IPs.</li>
    639 
    640 </ul>
    641 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/>
    642 
    643 <pre># api_key=YOUR_API_KEY
    644 
    645 # curl --header "Authorization: key=$api_key" --header Content-Type:"application/json" https://android.googleapis.com/gcm/send  -d "{\"registration_ids\":[\"ABC\"]}"</pre>
    646 
    647 
    648 
    649 If you receive a 401 HTTP status code, your API key is not valid. Otherwise you should see something like this:<br/>
    650 
    651 <pre>
    652 {"multicast_id":6782339717028231855,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
    653 </pre>
    654 If you want to confirm the validity of a registration ID, you can do so by replacing "ABC" with the registration ID.
    655 <br/>
    656 Happens when the HTTP status code is 401.
    657 
    658   <dt id="timeout"><strong>Timeout</strong></dt>
    659 
    660 <dd>The server couldn't process the request in time. You should retry the
    661 same request, but you MUST obey the following requirements:
    662 
    663 <ul>
    664 
    665 <li>Honor the <code>Retry-After</code> header if it's included in the response from the GCM server.</li>
    666         
    667         
    668 <li>Implement exponential back-off in your retry mechanism. This means an
    669 exponentially increasing delay after each failed retry (e.g. if you waited one
    670 second before the first retry, wait at least two second before the next one,
    671 then 4 seconds and so on). If you're sending multiple messages, delay each one
    672 independently by an additional random amount to avoid issuing a new request for
    673 all messages at the same time.</li>
    674     
    675 
    676 Senders that cause problems risk being blacklisted. 
    677 <br />
    678 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>.
    679 </dd>
    680 
    681 <dt id="internal_error"><strong>Internal Server Error</strong></dt>
    682 
    683 <dd>
    684 The server encountered an error while trying to process the request. You
    685 could retry the same request (obeying the requirements listed in the <a href="#timeout">Timeout</a>
    686 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>.
    687 <br />
    688 Happens when the HTTP status code is 500, or when the <code>error</code> field of a JSON
    689 object in the results array is <code>InternalServerError</code>.
    690 </dd>
    691 
    692 <dt id="restricted_package_name"><strong>Invalid Package Name</strong></dt>
    693 
    694 <dd>
    695 A message was addressed to a registration ID whose package name did not match the value passed in the request. Happens when error code is 
    696 <code>InvalidPackageName</code>.
    697 </dd>
    698 
    699 
    700 </dl>
    701 <h4>Example responses</h4>
    702 <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>
    703 <p> Here is a simple case of a JSON message successfully sent to one recipient without canonical IDs in the response:</p>
    704 <pre class="prettyprint pretty-json">{ "multicast_id": 108,
    705   "success": 1,
    706   "failure": 0,
    707   "canonical_ids": 0,
    708   "results": [
    709     { "message_id": "1:08" }
    710   ]
    711 }</pre>
    712 
    713 <p>Or if the request was in plain-text format:</p>
    714 <pre class="prettyprint">id=1:08
    715 </pre>
    716 
    717 <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>
    718 <pre class="prettyprint pretty-json">{ "multicast_id": 216,
    719   "success": 3,
    720   "failure": 3,
    721   "canonical_ids": 1,
    722   "results": [
    723     { "message_id": "1:0408" },
    724     { "error": "Unavailable" },
    725     { "error": "InvalidRegistration" },
    726     { "message_id": "1:1516" },
    727     { "message_id": "1:2342", "registration_id": "32" },
    728     { "error": "NotRegistered"}
    729   ]
    730 }
    731 </pre>
    732 <p> In this example:</p>
    733 <ul>
    734   <li>First message: success, not required.</li>
    735   <li>Second message: should be resent (to registration ID 8).</li>
    736   <li>Third message: had an unrecoverable error (maybe the value got corrupted in the database).</li>
    737   <li>Fourth message: success, nothing required.</li>
    738   <li>Fifth message: success, but the registration ID should be updated in the server database (from 23 to 32).</li>
    739   <li>Sixth message: registration ID (42) should be removed from the server database because the application was uninstalled from the device.</li>
    740 </ul>
    741 <p>Or if just the 4th message above was sent using plain-text format:</p>
    742 <pre class="prettyprint">Error=InvalidRegistration
    743 </pre>
    744 <p>If the 5th message above was also sent using plain-text format:</p>
    745 <pre class="prettyprint">id=1:2342
    746 registration_id=32
    747 </pre>
    748 
    749 <h3 id="stats">Viewing Statistics</h3>
    750 
    751 <p>To view  statistics and any error messages for your GCM applications:</p>
    752 <ol>
    753   <li> Go to the <code><a href="http://play.google.com/apps/publish">Developer Console</a></code>.</li>
    754   <li>Login with your developer account. 
    755   <p>You will see a page that has a list of all of your apps.</p></li>
    756   <li> Click on the &quot;statistics&quot; link next to the app for which you want to view GCM stats. 
    757   <p>Now you are on the statistics page.</p> </li>
    758   <li>Go to the drop-down menu and select the GCM metric you want to view. 
    759   </li>
    760 </ol>
    761 <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>
    762 
    763 
    764