Home | History | Annotate | Download | only in cloudsync
      1 page.title=Making the Most of Google Cloud Messaging
      2 parent.title=Syncing to the Cloud
      3 parent.link=index.html
      4 
      5 trainingnavtop=true
      6 
      7 previous.title=Using the Backup API
      8 previous.link=backupapi.html
      9 
     10 @jd:body
     11 
     12 <div id="tb-wrapper">
     13   <div id="tb">
     14     <h2>This lesson teaches you to</h2>
     15     <ol>
     16       <li><a href="#multicast">Send Multicast Messages Efficiently</a></li>
     17       <li><a href="#collapse">Collapse Messages that can Be Replaced</a></li>
     18       <li><a href="#embed">Embed Data Directly in the GCM Message</a></li>
     19       <li><a href="#react">React Intelligently to GCM Messages</a></li>
     20     </ol>
     21     <h2>You should also read</h2>
     22     <ul>
     23       <li><a href="http://developer.android.com/guide/google/gcm/index.html">Google
     24       Cloud Messaging for Android</a></li>
     25     </ul>
     26   </div>
     27 </div>
     28 
     29 <p>Google Cloud Messaging (GCM) is a free service for sending
     30 messages to Android devices.  GCM messaging can greatly enhance the user
     31 experience.  Your application can stay up to date without wasting battery power
     32 on waking up the radio and polling the server when there are no updates.  Also,
     33 GCM allows you to attach up to 1,000 recipients to a single message, letting you easily contact
     34 large user bases quickly when appropriate, while minimizing the work load on
     35 your server.</p>
     36 
     37 <p>This lesson covers some of the best practices
     38 for integrating GCM into your application, and assumes you are already familiar
     39 with basic implementation of this service.  If this is not the case, you can read the <a
     40   href="{@docRoot}guide/google/gcm/demo.html">GCM demo app tutorial</a>.</p>
     41 
     42 <h2 id="multicast">Send Multicast Messages Efficiently</h2>
     43 <p>One of the most useful features in GCM is support for up to 1,000 recipients for
     44 a single message.  This capability makes it much easier to send out important messages to
     45 your entire user base.  For instance, let's say you had a message that needed to
     46 be sent to 1,000,000 of your users, and your server could handle sending out
     47 about 500 messages per second.  If you send each message with only a single
     48 recipient, it would take 1,000,000/500 = 2,000 seconds, or around half an hour.
     49 However, attaching 1,000 recipients to each message, the total time required to
     50 send a message out to 1,000,000 recipients becomes (1,000,000/1,000) / 500 = 2
     51 seconds. This is not only useful, but important for timely data, such as natural
     52 disaster alerts or sports scores, where a 30 minute interval might render the
     53 information useless.</p>
     54 
     55 <p>Taking advantage of this functionality is easy.  If you're using the <a
     56   href="http://developer.android.com/guide/google/gcm/gs.html#libs">GCM helper
     57   library</a> for Java, simply provide a <code>List<String></code> collection of
     58 registration IDs to the <code>send</code> or <code>sendNoRetry</code> method,
     59 instead of a single registration ID.</p>
     60 
     61 <pre>
     62 // This method name is completely fabricated, but you get the idea.
     63 List<String> regIds = whoShouldISendThisTo(message);
     64 
     65 // If you want the SDK to automatically retry a certain number of times, use the
     66 // standard send method.
     67 MulticastResult result = sender.send(message, regIds, 5);
     68 
     69 // Otherwise, use sendNoRetry.
     70 MulticastResult result = sender.sendNoRetry(message, regIds);
     71 </pre>
     72 
     73 <p>For those implementing GCM support in a language other than Java, construct
     74 an HTTP POST request with the following headers:</p>
     75 <ul>
     76   <li><code>Authorization: key=YOUR_API_KEY</code></li>
     77   <li><code>Content-type: application/json</code></li>
     78 </ul>
     79 
     80 <p>Then encode the parameters you want into a JSON object, listing all the
     81 registration IDs under the key <code>registration_ids</code>.  The snippet below
     82 serves as an example.  All parameters except <code>registration_ids</code> are
     83 optional, and the items nested in <code>data</code> represent the user-defined payload, not
     84 GCM-defined parameters.  The endpoint for this HTTP POST message will be
     85 <code>https://android.googleapis.com/gcm/send</code>.</p>
     86 
     87 <pre>
     88 { "collapse_key": "score_update",
     89    "time_to_live": 108,
     90    "delay_while_idle": true,
     91    "data": {
     92        "score": "4 x 8",
     93        "time": "15:16.2342"
     94    },
     95    "registration_ids":["4", "8", "15", "16", "23", "42"]
     96 }
     97 </pre>
     98 
     99 <p>For a more thorough overview of the format of multicast GCM messages, see the <a
    100   href="http://developer.android.com/guide/google/gcm/gcm.html#send-msg">Sending
    101   Messages</a> section of the GCM guide.</pre>
    102 
    103 <h2 id="collapse">Collapse Messages that Can Be Replaced</h2>
    104 <p>GCM messages are often a tickle, telling the mobile application to
    105 contact the server for fresh data.  In GCM, it's possible (and recommended) to
    106 create collapsible messages for this situation, wherein new messages replace
    107 older ones.  Let's take the example
    108 of sports scores.  If you send out a message to all users following a certain
    109 game with the updated score, and then 15 minutes later an updated score message
    110 goes out, the earlier one no longer matters.  For any users who haven't received
    111 the first message yet, there's no reason to send both, and force the device to
    112 react (and possibly alert the user) twice when only one of the messages is still
    113 important.</p>
    114 
    115 <p>When you define a collapse key, when multiple messages are queued up in the GCM
    116 servers for the same user, only the last one with any given collapse key is
    117 delivered.  For a situation like with sports scores, this saves the device from
    118 doing needless work and potentially over-notifying the user.  For situations
    119 that involve a server sync (like checking email), this can cut down on the
    120 number of syncs the device has to do.  For instance, if there are 10 emails
    121 waiting on the server, and ten "new email" GCM tickles have been sent to the
    122 device, it only needs one, since it should only sync once.</p>
    123 
    124 <p>In order to use this feature, just add a collapse key to your outgoing
    125 message.  If you're using the GCM helper library, use the Message class's <code>collapseKey(String key)</code> method.</p>
    126 
    127 <pre>
    128 Message message = new Message.Builder(regId)
    129     .collapseKey("game4_scores") // The key for game 4.
    130     .ttl(600) // Time in seconds to keep message queued if device offline.
    131     .delayWhileIdle(true) // Wait for device to become active before sending.
    132     .addPayload("key1", "value1")
    133     .addPayload("key2", "value2")
    134     .build();
    135 </pre>
    136 
    137 <p>If not using the helper library, simply add a variable to the
    138 POST header you're constructing, with <code>collapse_key</code> as the field
    139 name, and the string you're using for that set of updates as the value.</p>
    140 
    141 
    142 
    143 <h2 id="embed">Embed Data Directly in the GCM Message</h2>
    144 <p>Often, GCM messages are meant to be a tickle, or indication to the device
    145 that there's fresh data waiting on a server somewhere.  However, a GCM message
    146 can be up to 4kb in size, so sometimes it makes sense to simply send the
    147 data within the GCM message itself, so that the device doesn't need to contact the
    148 server at all.  Consider this approach for situations where all of the
    149 following statements are true:
    150 <ul>
    151   <li>The total data fits inside the 4kb limit.</li>
    152   <li>Each message is important, and should be preserved.</li>
    153   <li>It doesn't make sense to collapse multiple GCM messages into a single
    154   "new data on the server" tickle.</li>
    155 </ul>
    156 
    157 <p>For instance, short messages or encoded player moves
    158 in a turn-based network game are examples of good use-cases for data to embed directly
    159 into a GCM message. Email is an example of a bad use-case, since messages are
    160 often larger than 4kb,
    161 and users don't need a GCM message for each email waiting for them on
    162 the server.</p>
    163 
    164 <p>Also consider this approach when sending
    165 multicast messages, so you don't tell every device across your user base to hit
    166 your server for updates simultaneously.</p>
    167 <p>This strategy isn't appropriate for sending large amounts of data, for a few
    168 reasons:</p>
    169 <ul>
    170   <li>Rate limits are in place to prevent malicious or poorly coded apps from spamming an
    171   individual device with messages.</li>
    172   <li>Messages aren't guaranteed to arrive in-order.</li>
    173   <li>Messages aren't guaranteed to arrive as fast as you send them out.  Even
    174   if the device receives one GCM message a second, at a max of 1K, that's 8kbps, or
    175   about the speed of home dial-up internet in the early 1990's.  Your app rating
    176   on Google Play will reflect having done that to your users.</p>
    177 </ul>
    178 
    179 <p>When used appropriately, directly embedding data in the GCM message can speed
    180 up the perceived speediness of your application, by letting it skip a round trip
    181 to the server.</p>
    182 
    183 <h2 id="react">React Intelligently to GCM Messages</h2>
    184 <p>Your application should not only react to incoming GCM messages, but react
    185 <em>intelligently</em>.  How to react depends on the context.</p>
    186 
    187 <h3>Don't be irritating</h3>
    188 <p>When it comes to alerting your user of fresh data, it's easy to cross the line
    189 from "useful" to "annoying".  If your application uses status bar notifications,
    190 <a
    191   href="http://developer.android.com/guide/topics/ui/notifiers/notifications.html#Updating">update
    192   your existing notification</a> instead of creating a second one. If you
    193 beep or vibrate to alert the user, consider setting up a timer.  Don't let the
    194 application alert more than once a minute, lest users be tempted to uninstall
    195 your application, turn the device off, or toss it in a nearby river.</p>
    196 
    197 <h3>Sync smarter, not harder</h3>
    198 <p>When using GCM as an indicator to the device that data needs to be downloaded
    199 from the server, remember you have 4kb of metadata you can send along to
    200 help your application be smart about it.  For instance, if you have a feed
    201 reading app, and your user has 100 feeds that they follow, help the device be
    202 smart about what it downloads from the server!  Look at the following examples
    203 of what metadata is sent to your application in the GCM payload, and how the application
    204 can react:</p>
    205 <ul>
    206   <li><code>refresh</code> &mdash; Your app basically got told to request a dump of
    207   every feed it follows.  Your app would either need to send feed requests to 100 different servers, or
    208   if you have an aggregator on your server, send a request to retrieve, bundle
    209   and
    210   transmit recent data from 100 different feeds, every time one updates.</li>
    211   <li><code>refresh</code>, <code>feedID</code> &mdash; Better:  Your app knows to check
    212   a specific feed for updates.</li>
    213   <li><code>refresh</code>, <code>feedID</code>, <code>timestamp</code> &mdash;
    214   Best:  If the user happened to manually refresh before the GCM message
    215   arrived, the application can compare timestamps of the most recent post, and
    216   determine that it <em>doesn't need to do anything</em>.
    217 </ul>
    218