2012-06-20 17:19:42 -07:00
|
|
|
page.title=Making the Most of Google Cloud Messaging
|
|
|
|
|
|
|
|
trainingnavtop=true
|
|
|
|
|
|
|
|
@jd:body
|
|
|
|
|
|
|
|
<div id="tb-wrapper">
|
|
|
|
<div id="tb">
|
|
|
|
<h2>This lesson teaches you to</h2>
|
|
|
|
<ol>
|
|
|
|
<li><a href="#multicast">Send Multicast Messages Efficiently</a></li>
|
|
|
|
<li><a href="#collapse">Collapse Messages that can Be Replaced</a></li>
|
|
|
|
<li><a href="#embed">Embed Data Directly in the GCM Message</a></li>
|
|
|
|
<li><a href="#react">React Intelligently to GCM Messages</a></li>
|
|
|
|
</ol>
|
|
|
|
<h2>You should also read</h2>
|
|
|
|
<ul>
|
2012-11-29 17:25:09 -08:00
|
|
|
<li><a href="http://developer.android.com/google/gcm/index.html">Google
|
2012-06-20 17:19:42 -07:00
|
|
|
Cloud Messaging for Android</a></li>
|
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p>Google Cloud Messaging (GCM) is a free service for sending
|
|
|
|
messages to Android devices. GCM messaging can greatly enhance the user
|
|
|
|
experience. Your application can stay up to date without wasting battery power
|
|
|
|
on waking up the radio and polling the server when there are no updates. Also,
|
|
|
|
GCM allows you to attach up to 1,000 recipients to a single message, letting you easily contact
|
|
|
|
large user bases quickly when appropriate, while minimizing the work load on
|
|
|
|
your server.</p>
|
|
|
|
|
|
|
|
<p>This lesson covers some of the best practices
|
|
|
|
for integrating GCM into your application, and assumes you are already familiar
|
|
|
|
with basic implementation of this service. If this is not the case, you can read the <a
|
2012-11-29 17:25:09 -08:00
|
|
|
href="{@docRoot}google/gcm/demo.html">GCM demo app tutorial</a>.</p>
|
2012-06-20 17:19:42 -07:00
|
|
|
|
|
|
|
<h2 id="multicast">Send Multicast Messages Efficiently</h2>
|
|
|
|
<p>One of the most useful features in GCM is support for up to 1,000 recipients for
|
|
|
|
a single message. This capability makes it much easier to send out important messages to
|
|
|
|
your entire user base. For instance, let's say you had a message that needed to
|
|
|
|
be sent to 1,000,000 of your users, and your server could handle sending out
|
|
|
|
about 500 messages per second. If you send each message with only a single
|
|
|
|
recipient, it would take 1,000,000/500 = 2,000 seconds, or around half an hour.
|
|
|
|
However, attaching 1,000 recipients to each message, the total time required to
|
|
|
|
send a message out to 1,000,000 recipients becomes (1,000,000/1,000) / 500 = 2
|
|
|
|
seconds. This is not only useful, but important for timely data, such as natural
|
|
|
|
disaster alerts or sports scores, where a 30 minute interval might render the
|
|
|
|
information useless.</p>
|
|
|
|
|
|
|
|
<p>Taking advantage of this functionality is easy. If you're using the <a
|
2012-11-29 17:25:09 -08:00
|
|
|
href="{@docRoot}google/gcm/gs.html#libs">GCM helper
|
2012-06-20 17:19:42 -07:00
|
|
|
library</a> for Java, simply provide a <code>List<String></code> collection of
|
|
|
|
registration IDs to the <code>send</code> or <code>sendNoRetry</code> method,
|
|
|
|
instead of a single registration ID.</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
// This method name is completely fabricated, but you get the idea.
|
|
|
|
List<String> regIds = whoShouldISendThisTo(message);
|
|
|
|
|
|
|
|
// If you want the SDK to automatically retry a certain number of times, use the
|
|
|
|
// standard send method.
|
|
|
|
MulticastResult result = sender.send(message, regIds, 5);
|
|
|
|
|
|
|
|
// Otherwise, use sendNoRetry.
|
|
|
|
MulticastResult result = sender.sendNoRetry(message, regIds);
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>For those implementing GCM support in a language other than Java, construct
|
|
|
|
an HTTP POST request with the following headers:</p>
|
|
|
|
<ul>
|
|
|
|
<li><code>Authorization: key=YOUR_API_KEY</code></li>
|
|
|
|
<li><code>Content-type: application/json</code></li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>Then encode the parameters you want into a JSON object, listing all the
|
|
|
|
registration IDs under the key <code>registration_ids</code>. The snippet below
|
|
|
|
serves as an example. All parameters except <code>registration_ids</code> are
|
|
|
|
optional, and the items nested in <code>data</code> represent the user-defined payload, not
|
|
|
|
GCM-defined parameters. The endpoint for this HTTP POST message will be
|
|
|
|
<code>https://android.googleapis.com/gcm/send</code>.</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
{ "collapse_key": "score_update",
|
|
|
|
"time_to_live": 108,
|
|
|
|
"delay_while_idle": true,
|
|
|
|
"data": {
|
|
|
|
"score": "4 x 8",
|
|
|
|
"time": "15:16.2342"
|
|
|
|
},
|
|
|
|
"registration_ids":["4", "8", "15", "16", "23", "42"]
|
|
|
|
}
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>For a more thorough overview of the format of multicast GCM messages, see the <a
|
2012-11-29 17:25:09 -08:00
|
|
|
href="{@docRoot}google/gcm/gcm.html#send-msg">Sending
|
2012-06-20 17:19:42 -07:00
|
|
|
Messages</a> section of the GCM guide.</pre>
|
|
|
|
|
|
|
|
<h2 id="collapse">Collapse Messages that Can Be Replaced</h2>
|
|
|
|
<p>GCM messages are often a tickle, telling the mobile application to
|
|
|
|
contact the server for fresh data. In GCM, it's possible (and recommended) to
|
|
|
|
create collapsible messages for this situation, wherein new messages replace
|
|
|
|
older ones. Let's take the example
|
|
|
|
of sports scores. If you send out a message to all users following a certain
|
|
|
|
game with the updated score, and then 15 minutes later an updated score message
|
|
|
|
goes out, the earlier one no longer matters. For any users who haven't received
|
|
|
|
the first message yet, there's no reason to send both, and force the device to
|
|
|
|
react (and possibly alert the user) twice when only one of the messages is still
|
|
|
|
important.</p>
|
|
|
|
|
|
|
|
<p>When you define a collapse key, when multiple messages are queued up in the GCM
|
|
|
|
servers for the same user, only the last one with any given collapse key is
|
|
|
|
delivered. For a situation like with sports scores, this saves the device from
|
|
|
|
doing needless work and potentially over-notifying the user. For situations
|
|
|
|
that involve a server sync (like checking email), this can cut down on the
|
|
|
|
number of syncs the device has to do. For instance, if there are 10 emails
|
|
|
|
waiting on the server, and ten "new email" GCM tickles have been sent to the
|
|
|
|
device, it only needs one, since it should only sync once.</p>
|
|
|
|
|
|
|
|
<p>In order to use this feature, just add a collapse key to your outgoing
|
|
|
|
message. If you're using the GCM helper library, use the Message class's <code>collapseKey(String key)</code> method.</p>
|
|
|
|
|
|
|
|
<pre>
|
|
|
|
Message message = new Message.Builder(regId)
|
|
|
|
.collapseKey("game4_scores") // The key for game 4.
|
|
|
|
.ttl(600) // Time in seconds to keep message queued if device offline.
|
|
|
|
.delayWhileIdle(true) // Wait for device to become active before sending.
|
|
|
|
.addPayload("key1", "value1")
|
|
|
|
.addPayload("key2", "value2")
|
|
|
|
.build();
|
|
|
|
</pre>
|
|
|
|
|
|
|
|
<p>If not using the helper library, simply add a variable to the
|
|
|
|
POST header you're constructing, with <code>collapse_key</code> as the field
|
|
|
|
name, and the string you're using for that set of updates as the value.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<h2 id="embed">Embed Data Directly in the GCM Message</h2>
|
|
|
|
<p>Often, GCM messages are meant to be a tickle, or indication to the device
|
|
|
|
that there's fresh data waiting on a server somewhere. However, a GCM message
|
|
|
|
can be up to 4kb in size, so sometimes it makes sense to simply send the
|
|
|
|
data within the GCM message itself, so that the device doesn't need to contact the
|
|
|
|
server at all. Consider this approach for situations where all of the
|
|
|
|
following statements are true:
|
|
|
|
<ul>
|
|
|
|
<li>The total data fits inside the 4kb limit.</li>
|
|
|
|
<li>Each message is important, and should be preserved.</li>
|
|
|
|
<li>It doesn't make sense to collapse multiple GCM messages into a single
|
|
|
|
"new data on the server" tickle.</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>For instance, short messages or encoded player moves
|
|
|
|
in a turn-based network game are examples of good use-cases for data to embed directly
|
|
|
|
into a GCM message. Email is an example of a bad use-case, since messages are
|
|
|
|
often larger than 4kb,
|
|
|
|
and users don't need a GCM message for each email waiting for them on
|
|
|
|
the server.</p>
|
|
|
|
|
|
|
|
<p>Also consider this approach when sending
|
|
|
|
multicast messages, so you don't tell every device across your user base to hit
|
|
|
|
your server for updates simultaneously.</p>
|
|
|
|
<p>This strategy isn't appropriate for sending large amounts of data, for a few
|
|
|
|
reasons:</p>
|
|
|
|
<ul>
|
|
|
|
<li>Rate limits are in place to prevent malicious or poorly coded apps from spamming an
|
|
|
|
individual device with messages.</li>
|
|
|
|
<li>Messages aren't guaranteed to arrive in-order.</li>
|
|
|
|
<li>Messages aren't guaranteed to arrive as fast as you send them out. Even
|
|
|
|
if the device receives one GCM message a second, at a max of 1K, that's 8kbps, or
|
|
|
|
about the speed of home dial-up internet in the early 1990's. Your app rating
|
|
|
|
on Google Play will reflect having done that to your users.</p>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>When used appropriately, directly embedding data in the GCM message can speed
|
|
|
|
up the perceived speediness of your application, by letting it skip a round trip
|
|
|
|
to the server.</p>
|
|
|
|
|
|
|
|
<h2 id="react">React Intelligently to GCM Messages</h2>
|
|
|
|
<p>Your application should not only react to incoming GCM messages, but react
|
|
|
|
<em>intelligently</em>. How to react depends on the context.</p>
|
|
|
|
|
|
|
|
<h3>Don't be irritating</h3>
|
|
|
|
<p>When it comes to alerting your user of fresh data, it's easy to cross the line
|
|
|
|
from "useful" to "annoying". If your application uses status bar notifications,
|
|
|
|
<a
|
|
|
|
href="http://developer.android.com/guide/topics/ui/notifiers/notifications.html#Updating">update
|
|
|
|
your existing notification</a> instead of creating a second one. If you
|
|
|
|
beep or vibrate to alert the user, consider setting up a timer. Don't let the
|
|
|
|
application alert more than once a minute, lest users be tempted to uninstall
|
|
|
|
your application, turn the device off, or toss it in a nearby river.</p>
|
|
|
|
|
|
|
|
<h3>Sync smarter, not harder</h3>
|
|
|
|
<p>When using GCM as an indicator to the device that data needs to be downloaded
|
|
|
|
from the server, remember you have 4kb of metadata you can send along to
|
|
|
|
help your application be smart about it. For instance, if you have a feed
|
|
|
|
reading app, and your user has 100 feeds that they follow, help the device be
|
|
|
|
smart about what it downloads from the server! Look at the following examples
|
|
|
|
of what metadata is sent to your application in the GCM payload, and how the application
|
|
|
|
can react:</p>
|
|
|
|
<ul>
|
|
|
|
<li><code>refresh</code> — Your app basically got told to request a dump of
|
|
|
|
every feed it follows. Your app would either need to send feed requests to 100 different servers, or
|
|
|
|
if you have an aggregator on your server, send a request to retrieve, bundle
|
|
|
|
and
|
|
|
|
transmit recent data from 100 different feeds, every time one updates.</li>
|
|
|
|
<li><code>refresh</code>, <code>feedID</code> — Better: Your app knows to check
|
|
|
|
a specific feed for updates.</li>
|
|
|
|
<li><code>refresh</code>, <code>feedID</code>, <code>timestamp</code> —
|
|
|
|
Best: If the user happened to manually refresh before the GCM message
|
|
|
|
arrived, the application can compare timestamps of the most recent post, and
|
|
|
|
determine that it <em>doesn't need to do anything</em>.
|
|
|
|
</ul>
|