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