1page.title=GCM Advanced Topics 2@jd:body 3 4<div id="qv-wrapper"> 5<div id="qv"> 6 7<h2>Quickview</h2> 8 9<ul> 10<li>Learn more about GCM advanced features.</li> 11</ul> 12 13 14<h2>In this document</h2> 15 16<ol> 17<li><a href="#lifetime">Lifetime of a Message</a></li> 18<li><a href="#throttling">Throttling</a></li> 19<li><a href="#reg-state">Keeping the Registration State in Sync</a> 20 <ol> 21 <li><a href="#canonical">Canonical IDs</a></li> 22 </ol> 23</li> 24<li><a href="#retry">Automatic Retry Using Exponential Back-Off</a></li> 25<li><a href="#unreg">Unregistration</a> 26 <ol> 27 <li><a href="#unreg-why">Why you should rarely unregister</a></li> 28 <li><a href="#unreg-how">How unregistration works</a></li> 29 </ol> 30</li> 31<li><a href="#collapsible">Send-to-Sync vs. Messages with Payload</a> 32 <ol> 33 <li><a href="#s2s">Send-to-sync messages</a></li> 34 <li><a href="#payload">Messages with payload</a></li> 35<li><a href="#which">Which should I use?</a></li> 36 </ol> 37</li> 38<li><a href="#ttl">Setting an Expiration Date for a Message</a> </li> 39<li><a href="#throttling"></a><a href="#multi-senders">Receiving Messages from 40Multiple Senders</a></li> 41</ol> 42 43</div> 44</div> 45<p>This document covers advanced topics for GCM.</p> 46 47 48 49 50<h2 id="msg-lifetime">Lifetime of a Message</h2> 51<p>When a 3rd-party server posts a message to GCM and receives a message ID back, 52it does not mean that the message was already delivered to the device. Rather, it 53means that it was accepted for delivery. What happens to the message after it is 54accepted depends on many factors.</p> 55 56<p>In the best-case scenario, if the device is connected to GCM, the screen is on, 57and there are no throttling restrictions (see <a href="#throttling">Throttling</a>), 58the message will be delivered right away.</p> 59 60<p>If the device is connected but idle, the message will still be 61delivered right away unless the <code>delay_while_idle</code> flag is set to true. 62Otherwise, it will be stored in the GCM servers until the device is awake. And 63that's where the <code>collapse_key</code> flag plays a role: if there is already 64a message with the same collapse key (and registration ID) stored and waiting for 65delivery, the old message will be discarded and the new message will take its place 66(that is, the old message will be collapsed by the new one). However, if the collapse 67key is not set, both the new and old messages are stored for future delivery. 68Collapsible messages are also called <a href="#s2s">send-to-sync messages</a>.</p> 69 70<p class="note"><strong>Note:</strong> There is a limit on how many messages can 71be stored without collapsing. That limit is currently 100. If the limit is reached, 72all stored messages are discarded. Then when the device is back online, it receives 73a special message indicating that the limit was reached. The application can then 74handle the situation properly, typically by requesting a full sync. 75<br><br> 76Likewise, there is a limit on how many <code>collapse_key</code>s you can have for 77a particular device. GCM allows a maximum of 4 different collapse keys to be used 78by the GCM server per device 79any given time. In other words, the GCM server can simultaneously store 4 different 80send-to-sync messages, each with a different collapse key. If you exceed this number 81GCM will only keep 4 collapse keys, with no guarantees about which ones they will be. 82See <a href="#s2s">Send-to-sync messages</a> for more information. 83</p> 84 85<p>If the device is not connected to GCM, the message will be stored until a 86connection is established (again respecting the collapse key rules). When a connection 87is established, GCM will deliver all pending messages to the device, regardless of 88the <code>delay_while_idle</code> flag. If the device never gets connected again 89(for instance, if it was factory reset), the message will eventually time out and 90be discarded from GCM storage. The default timeout is 4 weeks, unless the 91<code>time_to_live</code> flag is set.</p> 92 93<p>Finally, when GCM attempts to deliver a message to the device and the 94application was uninstalled, GCM will discard that message right away and 95invalidate the registration ID. Future attempts to send a message to that device 96will get a <code>NotRegistered</code> error. See <a href="#unreg"> 97How Unregistration Works</a> for more information.</p> 98<p>Although is not possible to track the status of each individual message, the 99Google Cloud Console stats are broken down by messages sent to device, messages 100collapsed, and messages waiting for delivery.</p> 101 102<h2 id="throttling">Throttling</h2> 103<p>To prevent abuse (such as sending a flood of messages to a device) and 104to optimize for the overall network efficiency and battery life of 105devices, GCM implements throttling of messages using a token bucket 106scheme. Messages are throttled on a per application and per <a href="#collapsible">collapse 107key</a> basis (including non-collapsible messages). Each application 108collapse key is granted some initial tokens, and new tokens are granted 109periodically therefter. Each token is valid for a single message sent to 110the device. If an application collapse key exhausts its supply of 111available tokens, new messages are buffered in a pending queue until 112new tokens become available at the time of the periodic grant. Thus 113throttling in between periodic grant intervals may add to the latency 114of message delivery for an application collapse key that sends a large 115number of messages within a short period of time. Messages in the pending 116queue of an application collapse key may be delivered before the time 117of the next periodic grant, if they are piggybacked with messages 118belonging to a non-throttled category by GCM for network and battery 119efficiency reasons.</p> 120 121<h2 id="reg-state">Keeping the Registration State in Sync</h2> 122<p>Whenever the application registers as described in 123<a href="{@docRoot}google/gcm/client.html">Implementing GCM Client</a>, 124it should save the registration ID for future use, pass it to the 1253rd-party server to complete the registration, and keep track of 126whether the server completed the registration. If the server fails 127to complete the registration, it should try again or unregister from GCM.</p> 128 129<p>There are also two other scenarios that require special care:</p> 130<ul> 131 <li>Application update</li> 132 <li>Backup and restore 133 </li> 134</ul> 135<p>When an application is updated, it should invalidate its existing registration 136ID, as it is not guaranteed to work with the new version. Because there is no 137lifecycle method called when the application is updated, the best way to achieve 138this validation is by storing the current application version when a registration 139ID is stored. Then when the application is started, compare the stored value with 140the current application version. If they do not match, invalidate the stored data 141and start the registration process again.</p> 142 143<p>Similarly, you should not save the registration ID when an application is 144backed up. This is because the registration ID could become invalid by the time 145the application is restored, which would put the application in an invalid state 146(that is, the application thinks it is registered, but the server and GCM do not 147store that registration ID anymore—thus the application will not get more 148messages).</p> 149<h3 id="canonical">Canonical IDs</h3> 150<p>On the server side, as long as the application is behaving well, everything 151should work normally. However, if a bug in the application triggers multiple 152registrations for the same device, it can be hard to reconcile state and you might 153end up with duplicate messages.</p> 154<p>GCM provides a facility called "canonical registration IDs" to easily 155recover from these situations. A canonical registration ID is defined to be the ID 156of the last registration requested by your application. This is the ID that the 157server should use when sending messages to the device.</p> 158<p>If later on you try to send a message using a different registration ID, GCM 159will process the request as usual, but it will include the canonical registration 160ID in the <code>registration_id</code> field of the response. Make sure to replace 161the registration ID stored in your server with this canonical ID, as eventually 162the ID you're using will stop working.</p> 163 164<h2 id="retry">Automatic Retry Using Exponential Back-Off</h2> 165 166<p>When registration or unregistration fails, the app should retry the failed operation.</p> 167<p>In the simplest case, if your application attempts to register and GCM is not a 168fundamental part of the application, the application could simply ignore the error 169and try to register again the next time it starts. Otherwise, it should retry the 170previous operation using exponential back-off. In exponential back-off, each time 171there is a failure, it should wait twice the previous amount of time before trying 172again. If the register (or unregister) operation was synchronous, it could be retried 173in a simple loop. However, since it is asynchronous, the best approach is to schedule 174a {@link android.app.PendingIntent} to retry the operation. 175 176<h2 id="unreg">Unregistration</h2> 177 178<p>This section explains when you should unregister in GCM and what happens 179when you do.</p> 180 181<h3 id="unreg-why">Why you should rarely unregister</h3> 182 183<p>A registration ID (regID) represents a particular Android application running 184on a particular device. You should only need to unregister in rare cases, such as 185if you want an app to stop receiving messages, or if you suspect that the regID has 186been compromised. In general, though, once an app has a regID, you shouldn't need 187to change it.</p> 188 189<p>In particular, you should never unregister your app as a mechanism for 190logout or for switching between users, for the following reasons:</p> 191 192<ul> 193 <li>A regID maps an app to a device. It isn't associated with a particular 194 logged in user. If you unregister and then re-register, GCM may return the same 195 ID or a different ID—there's no guarantee either way.</li> 196 197 <li>Unregistration may take up to 5 minutes to propagate.</li> 198 <li>After unregistration, re-registration may again take up to 5 minutes to 199propagate. During this time messages may be rejected due to the state of being 200unregistered, and after all this, messages may still go to the wrong user.</li> 201</ul> 202 203 204<p>The solution is to manage your own mapping between users, the regID, and 205individual messages:</p> 206 207<ul> 208 <li>Your app server should maintain a mapping between the current user 209and the regID. This should include information about which user is supposed to 210receive a particular message.</li> 211 <li>The app running on the device should check to ensure that messages it 212receives match the logged in user.</li> 213</ul> 214 215 216<h3 id="unreg-how">How unregistration works</h3> 217 218<p>An application can be automatically unregistered after it is uninstalled from 219the device. However, this process does not happens right away, as Android does not 220provide an uninstall callback. What happens in this scenario is as follows:</p> 221<ol> 222 <li>The end user uninstalls the application.</li> 223 <li>The 3rd-party server sends a message to GCM server.</li> 224 <li>The GCM server sends the message to the device.</li> 225 <li>The GCM client receives the message and queries Package Manager about 226whether there are broadcast receivers configured to receive it, which returns 227<code>false</code>. 228</li> 229 <li>The GCM client informs the GCM server that the application was uninstalled.</li> 230 <li>The GCM server marks the registration ID for deletion.</li> 231 <li>The 3rd-party server sends a message to GCM.</li> 232 <li>The GCM returns a <code>NotRegistered</code> error message to the 3rd-party server.</li> 233 <li>The 3rd-party deletes the registration ID. 234 </li> 235</ol> 236 237<p class ="note"><strong>Note:</strong> The GCM client is the Google Cloud 238Messaging framework present on the device.</p> 239 240<p>Note that it might take a while for the registration ID be completely removed 241from GCM. Thus it is possible that messages sent during step 7 above gets a valid 242message ID as response, even though the message will not be delivered to the device. 243Eventually, the registration ID will be removed and the server will get a 244<code>NotRegistered</code> error, without any further action being required from 245the 3rd-party server (this scenario happens frequently while an application is 246being developed and tested).</p> 247 248<h2 id="collapsible">Send-to-Sync vs. Messages with Payload</h2> 249 250<p>Every message sent in GCM has the following characteristics:</p> 251<ul> 252 <li>It has a payload limit of 4096 bytes.</li> 253 <li>By default, it is stored by GCM for 4 weeks.</li> 254</ul> 255 256<p>But despite these similarities, messages can behave very differently depending 257on their particular settings. One major distinction between messages is whether 258they are collapsed (where each new message replaces the preceding message) or not 259collapsed (where each individual message is delivered). Every message sent in GCM 260is either a "send-to-sync" (collapsible) message or a "message with 261payload" (non-collapsible message). These concepts are described in more 262detail in the following sections.</p> 263 264<h3 id="s2s"><strong>Send-to-sync messages</strong></h3> 265 266<p>A send-to-sync (collapsible) message is often a "tickle" that tells 267a mobile application to sync data from the server. For example, suppose you have 268an email application. When a user receives new email on the server, the server 269pings the mobile application with a "New mail" message. This tells the 270application to sync to the server to pick up the new email. The server might send 271this message multiple times as new mail continues to accumulate, before the application 272has had a chance to sync. But if the user has received 25 new emails, there's no 273need to preserve every "New mail" message. One is sufficient. Another 274example would be a sports application that updates users with the latest score. 275Only the most recent message is relevant, so it makes sense to have each new 276message replace the preceding message. </p> 277 278<p>The email and sports applications are cases where you would probably use the 279GCM <code>collapse_key</code> parameter. A <em>collapse key</em> is an arbitrary 280string that is used to collapse a group of like messages when the device is offline, 281so that only the most recent message gets sent to the client. For example, 282"New mail," "Updates available," and so on</p> 283<p>GCM allows a maximum of 4 different collapse keys to be used by the GCM server 284at any given time. In other words, the GCM server can simultaneously store 4 285different send-to-sync messages per device, each with a different collapse key. 286For example, Device A can have A1, A2, A3, and A4. Device B can have B1, B2, B3, 287and B4, and so on. If you exceed this number GCM will only keep 4 collapse keys, with no 288guarantees about which ones they will be.</p> 289 290<h3 id="payload">Messages with payload</h3> 291<p>Unlike a send-to-sync message, every "message with payload" 292(non-collapsible message) is delivered. The payload the message contains can be 293up to 4kb. For example, here is a JSON-formatted message in an IM application in 294which spectators are discussing a sporting event:</p> 295 296<pre class="prettyprint pretty-json">{ 297 "registration_id" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...", 298 "data" : { 299 "Nick" : "Mario", 300 "Text" : "great match!", 301 "Room" : "PortugalVSDenmark", 302 }, 303}</pre> 304 305<p>A "message with payload" is not simply a "ping" to the 306mobile application to contact the server to fetch data. In the aforementioned IM 307application, for example, you would want to deliver every message, because every 308message has different content. To specify a non-collapsible message, you simply 309omit the <code>collapse_key</code> parameter. Thus GCM will send each message 310individually. Note that the order of delivery is not guaranteed.</p> 311 312<p>GCM will store up to 100 non-collapsible messages. After that, all messages 313are discarded from GCM, and a new message is created that tells the client how 314far behind it is. The message is delivered through a regular 315<code>com.google.android.c2dm.intent.RECEIVE</code> intent with the 316extra <code>message_type</code>, for which the value is always the string 317"deleted_messages".</p> 318 319<p>The application should respond by syncing with the server to recover the 320discarded messages. </p> 321 322<h3 id="which">Which should I use?</h3> 323 <p>If your application does not need to use non-collapsible messages, collapsible 324messages are a better choice from a performance standpoint, because they put less 325of a burden on the device battery. However, if you use collapsible messages, remember that 326<strong>GCM only allows a maximum of 4 different collapse keys to be used by the GCM server 327per device at any given time</strong>. You must not exceed this number, or it could cause 328unpredictable consequences.</p> 329 330<h2 dir="ltr" id="ttl">Setting an Expiration Date for a Message</h2> 331<p>The Time to Live (TTL) feature lets the sender specify the maximum lifespan 332of a message using the <code>time_to_live</code> parameter in the send request. 333The value of this parameter must be a duration from 0 to 2,419,200 seconds, and 334it corresponds to the maximum period of time for which GCM will store and try to 335deliver the message. Requests that don't contain this field default to the maximum 336period of 4 weeks.</p> 337<p>Here are some possible uses for this feature:</p> 338<ul> 339 <li>Video chat incoming calls</li> 340 <li>Expiring invitation events</li> 341 <li>Calendar events</li> 342</ul> 343<h3 id="bg">Background </h3> 344<p>GCM will usually deliver messages immediately after they are sent. However, 345this might not always be possible. For example, the device could be turned off, 346offline, or otherwise unavailable. In other cases, the sender itself might request 347that messages not be delivered until the device becomes active by using the 348<code>delay_while_idle</code> flag. Finally, GCM might intentionally delay messages 349to prevent an application from consuming excessive resources and negatively 350impacting battery life.</p> 351 352<p>When this happens, GCM will store the message and deliver it as soon as it's 353feasible. While this is fine in most cases, there are some applications for which 354a late message might as well never be delivered. For example, if the message is 355an incoming call or video chat notification, it will only be meaningful for a 356small period of time before the call is terminated. Or if the message is an 357invitation to an event, it will be useless if received after the event has ended.</p> 358 359<p>Another advantage of specifying the expiration date for a message is that GCM 360will never throttle messages with a <code>time_to_live</code> value of 0 seconds. 361In other words, GCM will guarantee best effort for messages that must be delivered 362"now or never." Keep in mind that a <code>time_to_live</code> value of 3630 means messages that can't be delivered immediately will be discarded. However, 364because such messages are never stored, this provides the best latency for 365sending notifications.</p> 366 367<p>Here is an example of a JSON-formatted request that includes TTL:</p> 368<pre class="prettyprint pretty-json"> 369{ 370 "collapse_key" : "demo", 371 "delay_while_idle" : true, 372 "registration_ids" : ["xyz"], 373 "data" : { 374 "key1" : "value1", 375 "key2" : "value2", 376 }, 377 "time_to_live" : 3 378}, 379</pre> 380 381 382<h2 id="multi-senders">Receiving Messages from Multiple Senders</h2> 383 384<p>GCM allows multiple parties to send messages to the same application. For 385example, suppose your application is an articles aggregator with multiple 386contributors, and you want each of them to be able to send a message when they 387publish a new article. This message might contain a URL so that the application 388can download the article. Instead of having to centralize all sending activity in 389one location, GCM gives you the ability to let each of these contributors send 390its own messages.</p> 391 392<p>To make this possible, all you need to do is have each sender generate its own 393project number. Then include those IDs in the sender field, separated by commas, 394when requesting a registration. Finally, share the registration ID with your 395partners, and they'll be able to send messages to your application using their 396own authentication keys.</p> 397<p>This code snippet illustrates this feature. Senders are passed as an intent 398extra in a comma-separated list:</p> 399 400<pre class="prettyprint pretty-java">Intent intent = new Intent(GCMConstants.INTENT_TO_GCM_REGISTRATION); 401intent.setPackage(GSF_PACKAGE); 402intent.putExtra(GCMConstants.EXTRA_APPLICATION_PENDING_INTENT, 403 PendingIntent.getBroadcast(context, 0, new Intent(), 0)); 404String senderIds = "968350041068,652183961211"; 405intent.putExtra(GCMConstants.EXTRA_SENDER, senderIds); 406ontext.startService(intent); 407 </pre> 408 409<p>Note that there is limit of 100 multiple senders.</p> 410