summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkmccormick <kmccormick@google.com>2013-04-18 10:57:59 -0700
committerkmccormick <kmccormick@google.com>2013-05-13 19:49:54 -0700
commiteeaac812be2231cae29394050b2b9f8a1b17fea0 (patch)
tree8ea1d15b81dd90dfd9b7de97930db5ca5283643b
parent4da9c11b2758d55c67f7a24c3eb519c36497ba5d (diff)
downloadframeworks_base-eeaac812be2231cae29394050b2b9f8a1b17fea0.zip
frameworks_base-eeaac812be2231cae29394050b2b9f8a1b17fea0.tar.gz
frameworks_base-eeaac812be2231cae29394050b2b9f8a1b17fea0.tar.bz2
Doc update: CCS and notifications
Change-Id: I607441a39b420ef1ebcaeb676a4f97dcd7286fe3
-rw-r--r--docs/html/google/gcm/ccs.jd297
-rw-r--r--docs/html/google/gcm/demo.jd5
-rw-r--r--docs/html/google/gcm/gcm.jd146
-rw-r--r--docs/html/google/gcm/gs.jd388
-rw-r--r--docs/html/google/gcm/helper.jd182
-rw-r--r--docs/html/google/gcm/index.jd60
-rw-r--r--docs/html/google/gcm/notifications.jd171
-rw-r--r--docs/html/google/google_toc.cs33
8 files changed, 1042 insertions, 240 deletions
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
new file mode 100644
index 0000000..ffe15c5
--- /dev/null
+++ b/docs/html/google/gcm/ccs.jd
@@ -0,0 +1,297 @@
+page.title=GCM Cloud Connection Server
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Quickview</h2>
+
+<ul>
+<li>Get an introduction to key CCS terms and concepts.</li>
+<li>Learn how to send and receive both upstream and downstream messages in CCS.</li>
+</ul>
+
+
+<h2>In this document</h2>
+
+<ol class="toc">
+ <li><a href="#gcm">CCS vs. GCM HTTP</a> </li>
+ <li><a href="#usage">How to Use CCS</a>
+ <ol>
+ <li><a href="#send_msg">Sending Messages</a></li>
+ <li><a href="#format">Message Format</a></li>
+ <li><a href="#msg_examples">Message Examples</a></li>
+ </ol>
+ </li>
+ <li><a href="#flow">Control Flow</a> </li>
+</ol>
+
+<h2>See Also</h2>
+
+<ol class="toc">
+<li><a href="{@docRoot}google/play-services/gcm/gs.html">Getting Started</a></li>
+<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
+</ol>
+
+</div>
+</div>
+
+<p class="note"><strong>Note:</strong> To try out this feature, sign up using <a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
+
+<p>The GCM Cloud Connection Server (CCS) allows third party servers to communicate with Android devices by establishing a persistent TCP connection with Google servers using the XMPP protocol. This communication is asynchronous and bidirectional.</p>
+<p>You can continue to use the HTTP request mechanism to send messages to GCM servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:</p>
+<ul>
+ <li>The asynchronous nature of XMPP allows you to send more messages with fewer resources.</li>
+ <li>Communication is bidirectional&mdash;not only can the server send messages to the device, but the device can send messages back to the server.</li>
+<li>You can send messages back using the same connection used for receiving, thereby improving battery life.</li>
+</ul>
+
+<p>The upstream messaging (device-to-cloud) feature of CCS is part of the Google Play services platform. Upstream messaging is available through the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. To use upstream messaging and the new streamlined registration process, you must <a href="{@docRoot}google/play-services/setup.html">set up</a> the Google Play services SDK.</p>
+
+<h2 id="gcm">CCS vs. GCM HTTP</h2>
+
+<p>CCS messaging differs from GCM HTTP messaging in the following ways:</p>
+<ul>
+ <li>Upstream/Downstream messages
+ <ul>
+ <li>GCM HTTP: Downstream only: cloud-to-device. </li>
+ <li>CCS: Upstream and downstream (device-to-cloud, cloud-to-device). </li>
+ </ul>
+ </li>
+ <li>Asynchronous messaging
+ <ul>
+ <li>GCM HTTP: 3rd-party servers send messages as HTTP POST requests and wait for a response. This mechanism is synchronous and causes the sender to block before sending another message.</li>
+ <li>CCS: 3rd-party servers connect to Google infrastructure using a persistent XMPP connection and send/receive messages to/from all their devices at full line speed. CCS sends acknowledgements or failure notifications (in the form of special ACK and NACK JSON-encoded XMPP messages) asynchronously.</li>
+ </ul>
+ </li>
+
+ <li>JSON
+ <ul>
+ <li>GCM HTTP: JSON messages sent as HTTP POST.</li>
+ <li>CCS: JSON messages encapsulated in XMPP messages.</li>
+ </ul>
+ </li>
+</ul>
+<p>This document describes how to use CCS. For general concepts and information on how to use GCM HTTP, see the <a href="gcm.html">GCM Architectural Overview</a>.</p>
+
+<h2 id="usage">How to Use CCS</h2>
+
+<p>GCM Cloud Connection Server (CCS) is an XMPP endpoint, running on {@code http://gcm.googleapis.com} port 5235.</p>
+
+<p>CCS requires a Transport Layer Security (TLS) connection. That means the XMPP client must initiate a TLS connection.
+For example in smack, you would call {@code setSocketFactory(SSLSocketFactory)}, similar to “old style SSL” XMPP connections and https.</p>
+
+<p>CCS requires a SASL PLAIN authentication mechanism using {@code &lt;your_GCM_Sender_Id&gt;&#64;gcm.googleapis.com} (GCM sender ID) and the API key as the password, where the sender ID and API key are the same as described in <a href="gs.html">Getting Started</a>.</p>
+
+<p> You can use most XMPP libraries to interact with CCS.</p>
+
+<h3 id="send_msg">Sending messages</h3>
+
+<p>The following snippets illustrate how to perform authentication in CCS.</p>
+<h4>Client</h4>
+<pre>&lt;stream:stream to=&quot;gcm.googleapis.com&quot;
+ version=&quot;1.0&quot; xmlns=&quot;jabber:client&quot;
+ xmlns:stream=&quot;http://etherx.jabber.org/streams&quot;/&gt;
+</pre>
+<h4>Server</h4>
+<pre>&lt;str:features xmlns:str=&quot;http://etherx.jabber.org/streams&quot;&gt;
+ &lt;mechanisms xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;
+   &lt;mechanism&gt;X-OAUTH2&lt;/mechanism&gt;
+   &lt;mechanism&gt;X-GOOGLE-TOKEN&lt;/mechanism&gt;
+   &lt;mechanism&gt;PLAIN&lt;/mechanism&gt;
+ &lt;/mechanisms&gt;
+&lt;/str:features&gt;
+</pre>
+
+<h4>Client</h4>
+<pre>&lt;auth mechanism=&quot;PLAIN&quot;
+xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;MTI2MjAwMzQ3OTMzQHByb2plY3RzLmdjbS5hb
+mRyb2lkLmNvbQAxMjYyMDAzNDc5FzNAcHJvamVjdHMtZ2EtLmFuZHJvaWQuY29tAEFJe
+mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==&lt;/auth&gt;
+</pre>
+<h4>Server</h4>
+<pre>&lt;success xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;/&gt;</pre>
+
+<h3 id="format">Message Format</h3>
+<p>CCS uses normal XMPP <code>&lt;message&gt;</code> stanzas. The body of the message must be:
+</p>
+<pre>
+&lt;gcm xmlns:google:mobile:data&gt;
+ <em>JSON payload</em>
+&lt;/gcm&gt;
+</pre>
+
+<p>The JSON payload for server-to-device is similar to what the GCM http endpoint uses, with these exceptions:</p>
+<ul>
+ <li>There is no support for multiple recipients.</li>
+ <li>{@code to} is used instead of {@code registration_ids}.</li>
+ <li>CCS adds the field {@code message_id}, which is required. This ID uniquely identifies the message in an XMPP connection. The ACK or NACK from CCS uses the {@code message_id} to identify a message sent from 3rd-party servers to CCS. Therefore, it's important that this {@code message_id} not only be unique, but always present.</li>
+
+ <li>For ACK/NACK messages that are special control messages, you also need to include a {@code message_type} field in the JSON message. For example:
+
+<pre>message_type = ('ack' OR 'nack');</pre>
+ </li>
+</ul>
+<p>For each message a device sends to the server, you need to send an ACK message. You never need to send a NACK message. If you don't send an ACK for a message, CCS will just resend it.
+</p>
+<p>CCS also sends an ACK or NACK for each server-to-device message. If you do not receive either, it means that the TCP connection was closed in the middle of the operation and your server needs to resend the messages.
+</p>
+
+<h3 id="msg_examples">Message Examples</h3>
+
+<p>Here is an XMPP stanza containing the JSON message from a 3rd-party server to CCS:
+
+</p>
+<pre>&lt;message id=&quot;&quot;&gt;
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;to&quot;:&quot;REGISTRATION_ID&quot;, // &quot;to&quot; replaces &quot;registration_ids&quot;
+ &quot;message_id&quot;:&quot;m-1366082849205&quot; // new required field
+ &quot;data&quot;:
+ {
+ &quot;hello&quot;:&quot;world&quot;,
+ }
+ &quot;time_to_live&quot;:&quot;600&quot;,
+ &quot;delay_while_idle&quot;: true/false
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;
+</pre>
+
+<p>Here is an XMPP stanza containing the ACK/NACK message from CCS to 3rd-party server:
+</p>
+<pre>&lt;message id=&quot;&quot;&gt;
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;from&quot;:&quot;REGID&quot;,
+ &quot;message_id&quot;:&quot;m-1366082849205&quot;
+ &quot;message_type&quot;:&quot;ack&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;
+
+&lt;message id=&quot;&quot;&gt;
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;from&quot;:&quot;REGID&quot;,
+ &quot;message_id&quot;:&quot;m-1366082849205&quot;
+ &quot;error&quot;: ERROR_CODE,
+ &quot;message_type&quot;:&quot;nack&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;
+</pre>
+
+<h4>Upstream Messages</h4>
+
+<p>Using CCS and the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> API, you can send messages from a user's device to the cloud.</p>
+
+<p>Here is how you send an upstream message using the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> API. For a complete example, see <a href="gs.html#gs_example">Getting Started</a>:</p>
+
+<pre>GoogleCloudMessaging gcm = GoogleCloudMessaging.get(context);
+String GCM_SENDER_ID = "Your-Sender-ID";
+AtomicInteger msgId = new AtomicInteger();
+String id = Integer.toString(msgId.incrementAndGet());
+Bundle data = new Bundle();
+// Bundle data consists of a key-value pair
+data.putString("hello", "world");
+// "time to live" parameter
+int ttl = [0 seconds, 4 weeks]
+
+gcm.send(GCM_SENDER_ID + "&#64;gcm.googleapis.com", id, ttl, data);
+</pre>
+
+<p>This call generates the necessary XMPP stanza for sending the upstream message. The message goes from the app on the device to CCS to the 3rd-party server. The stanza has the following format:</p>
+
+<pre>&lt;message id=&quot;&quot;&gt;
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;category&quot;:&quot;com.example.yourapp&quot;, // to know which app sent it
+ &quot;data&quot;:
+ {
+ &quot;hello&quot;:&quot;world&quot;,
+ },
+ &quot;message_id&quot;:&quot;m-123&quot;,
+ &quot;from&quot;:&quot;REGID&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;</pre>
+
+<p>Here is the format of the ACK expected by CCS from 3rd-party servers in response to the above message:</p>
+
+<pre>&lt;message id=&quot;&quot;&gt;
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;to&quot;:&quot;REGID&quot;,
+ &quot;message_id&quot;:&quot;m-123&quot;
+ &quot;message_type&quot;:&quot;ack&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;</pre>
+
+<h4 id="python">Python Example</h4>
+<p>This example illustrates how to connect,
+send, and receive GCM messages using XMPP. It shouldn't be used as-is
+on a production deployment.</p>
+
+<pre>
+import sys, json, xmpp
+SERVER = ('gcm.googleapis.com', 5235)
+#USERNAME = '&lt;your_numeric_project_id&gt;'
+#PASSWORD = '&lt;your_gcm_api_key&gt;'
+
+# Unique message id for downstream messages
+sent_message_id = 0
+
+def message_callback(session, message):
+ global sent_message_id
+ gcm = message.getTags('gcm')
+
+ if gcm:
+ gcm_json = gcm[0].getData()
+ msg = json.loads(gcm_json)
+ msg_id = msg['message_id']
+ device_reg_id = msg['from']
+
+ # Ignore non-standard messages (e.g. acks/nacks).
+ if not msg.has_key('message_type'):
+ # Acknowledge the incoming message.
+ send({'to': device_reg_id,
+ 'message_type': 'ack',
+ 'message_id': msg_id})
+
+ # Send a response back to the server.
+ send({'to': device_reg_id,
+ 'message_id' : str(sent_message_id),
+ 'data': {'pong': 1}})
+ sent_message_id = sent_message_id + 1
+
+def send(json_dict):
+ template = (&quot;&lt;message from='{0}' to='gcm@google.com'&gt;&quot;
+ &quot;&lt;gcm xmlns='google:mobile:data'&gt;{1}&lt;/gcm&gt;&lt;/message&gt;&quot;)
+ client.send(xmpp.protocol.Message(
+ node=template.format(client.Bind.bound[0],
+ json.dumps(json_dict))))
+
+client = xmpp.Client(SERVER[0], debug=['socket'])
+client.connect(server=SERVER, secure=1, use_srv=False)
+auth = client.auth(USERNAME, PASSWORD, 'test')
+if not auth:
+ print 'Authentication failed!'
+ sys.exit(1)
+
+client.RegisterHandler('message', message_callback)
+
+while True:
+ client.Process(1)</pre>
+
+<h2 id="flow">Control Flow</h2>
+
+<p>Every message sent by a 3rd-party server to CCS receives either an ACK or a NACK response. A single connection can have at most 1000 messages that were sent without having yet received a response.</p>
+
+<p>To enforce this policy, the app can maintain a counter of sent messages that increments on each send and decrements on each ACK or NACK. If the counter exceeds 1000, the app should stop sending messages until an ACK or NACK is received.</p>
+
+<p>Conversely, when CCS sends messages to a 3rd-party server, it expects ACKs for each message it sends, and it will not send more than 1000 unacknowledged messages.</p>
+
+<p>The ACKs and messages must match on each connection. You can only send an ACK for a message on the connection on which it was received.</p>
+
diff --git a/docs/html/google/gcm/demo.jd b/docs/html/google/gcm/demo.jd
index 1b6b368..6da9e98 100644
--- a/docs/html/google/gcm/demo.jd
+++ b/docs/html/google/gcm/demo.jd
@@ -30,6 +30,8 @@ page.title=GCM Demo Application
</div>
</div>
+<p class="note"><strong>Note:</strong> This tutorial describes how to develop GCM-enabled apps using the helper libraries. This is just one approach. For a more comprehensive discussion of the available APIs and development paths, see <a href="gs.html">Getting Started</a>.
+
<p>The Google Cloud Messaging (GCM) Demo demonstrates how to use the Google Cloud Messaging framework in your Android application. This tutorial walks you through setting up and running the demo.</p>
@@ -106,7 +108,7 @@ Total time: 0 seconds
</li>
</ol>
<p class="note"><strong>Note:</strong> You can get the IP by running <code>ifconfig</code> on Linux or MacOS, or <code>ipconfig</code> on Windows. </p>
-<p><img src="{@docRoot}images/gcm/gcm-demo-homepage.png" class="screenshot" /></p>
+
<p> You server is now ready.</p>
<h3 id="appengine-setup">Using App Engine for Java</h3>
@@ -157,7 +159,6 @@ runserver:
<p class="note"><strong>Note:</strong> You can get the IP by running <code>ifconfig</code> on Linux or MacOS, or <code>ipconfig</code> on Windows.</p>
- <p><img src="{@docRoot}images/gcm/gcm-demo-homepage-appengine.png" class="screenshot" /></p>
</ol>
<p> You server is now ready.</p>
<h2 id="device-setup">Setting Up the Device</h2>
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index ce28fb8..7486d7b 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -1,4 +1,4 @@
-page.title=GCM Architectural Overview
+page.title=Google Cloud Messaging for Android
@jd:body
<div id="qv-wrapper">
@@ -20,6 +20,11 @@ page.title=GCM Architectural Overview
<li><a href="#arch">Architectural Overview</a>
<ol>
<li><a href="#lifecycle">Lifecycle Flow</a></li>
+ <ol>
+ <li><a href="#register">Enable GCM</a></li>
+ <li><a href="#push-process">Send a message</a></li>
+ <li><a href="#receiving">Receive a message</a></li>
+ </ol>
<li><a href="#user">What Does the User See?</a></li>
</ol>
</li>
@@ -27,8 +32,8 @@ page.title=GCM Architectural Overview
<ol>
<li><a href="#manifest">Creating the Manifest</a></li>
<li><a href="#registering">Registering for GCM</a></li>
- <li><a href="#unregistering">Unregistering from GCM</a></li>
- <li><a href="#handling_intents">Handling Intents sent by GCM</a>
+
+ <li><a href="#handling_intents">Handling Intents Sent by GCM</a>
<ol>
<li><a href="#handling_reg">Handling Registration Results</a></li>
<li><a href="#received_data">Handling Received Data</a></li>
@@ -46,7 +51,7 @@ page.title=GCM Architectural Overview
</ol>
</li>
</ol>
- <li><a href="#stats">Viewing statistics</a>
+ <li><a href="#stats">Viewing Statistics</a>
</li>
<li><a href="#example">Examples</a></li>
</ol>
@@ -58,20 +63,25 @@ page.title=GCM Architectural Overview
<p>Google Cloud Messaging for Android (GCM) is a free service that helps
developers send data from servers to their Android applications on Android
-devices. This could be a lightweight message telling the Android application
+devices, and upstream messages from the user's device back to the cloud.
+This could be a lightweight message telling the Android application
that there is new data to be fetched from the server (for instance, a movie
uploaded by a friend), or it could be a message containing up to 4kb of payload
data (so apps like instant messaging can consume the message directly). The GCM
service handles all aspects of queueing of messages and delivery to the target
Android application running on the target device.</p>
+
+<p>GCM introduces GCM Cloud Connection Server (CCS), which you can use
+in tandem with GCM HTTP service/endpoint/APIs.
+CCS uses XMPP, and it offers asynchronous, bidirectional
+messaging. For more information, see
+<a href="ccs.html">GCM Cloud Connection Server</a>.
<p class="note"> To jump right into using GCM with your Android
applications, see the instructions in <a href="gs.html">Getting Started</a>.</p>
-
-
<h2 id="intro">Introduction</h2>
<p>Here are the primary characteristics of Google Cloud
@@ -80,6 +90,7 @@ Messaging (GCM):</p>
<ul>
<li>It allows 3rd-party application servers to send messages to
their Android applications.</li>
+ <li>Using the <a href="ccs.html">GCM Cloud Connection Server</a>, you can receive upstream messages from the user's device.</li>
<li>An Android application on an Android device doesn't need to be running to receive
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
broadcast receiver and permissions.</li>
@@ -170,24 +181,35 @@ which would cause delivery errors.
server that gives the application server authorized access to Google services.
The API key is included in the header of POST requests that send messages.</td>
</tr>
+
+ <tr>
+ <td><strong>Notification Key</strong></td>
+ <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>
+ </tr>
+
+<tr>
+ <td><strong>Notification Key Name</strong></td>
+ <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>
+ </tr>
+
</table>
<h3 id="lifecycle">Lifecycle Flow</h3>
-<p>Here are the primary processes involved in cloud-to-device messaging:</p>
-
<ul>
- <li><a href="#register">Enabling GCM</a>. An Android application running on a
+ <li><a href="#register">Enable GCM</a>. An Android application running on a
mobile device registers to receive messages.</li>
- <li><a href="#push-process">Sending a message</a>. A 3rd-party application
+ <li><a href="notifications.html">User Notifications</a>. A 3rd-party server can optionally group multiple registration IDs
+in a {@code notification_key} to send messages to multiple devices owned by a single user.</li>
+ <li><a href="#push-process">Send a message</a>. A 3rd-party application
server sends messages to the device.</li>
- <li><a href="#receiving">Receiving a message</a>. An Android application
+ <li><a href="#receiving">Receive a message</a>. An Android application
receives a message from a GCM server.</li>
</ul>
<p>These processes are described in more detail below.</p>
-<h4 id="register">Enabling GCM</h4>
+<h4 id="register">Enable GCM</h4>
<p>This is the sequence of events that occurs when an Android application
running on a mobile device registers to receive messages:<span
@@ -195,7 +217,7 @@ class="red-text"></span></p>
<ol>
<li>The first time the Android application needs to use the messaging service, it
-fires off a registration Intent to a GCM server.
+fires off a registration Intent to a GCM server.
<p>This registration Intent
(<code>com.google.android.c2dm.intent.REGISTER</code>) includes the sender ID, and the Android application ID.</p>
<p class="note"><strong>Note:</strong> Because there is no lifecycle method that is called when the application is run for
@@ -204,7 +226,7 @@ the first time, the registration intent should be sent on <code>onCreate()</code
</li>
<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
ID.
- <p>The Android application should store this ID for later use (for instance, to check on <code>onCreate()</code> if it is already registered).
+ <p>The Android application should store this ID for later use (for instance, to check on <code>onCreate()</code> if it is already registered).
Note that Google may periodically refresh the registration ID, so you should design your Android application
with the understanding that the <code>com.google.android.c2dm.intent.REGISTRATION</code> intent may be called
multiple times. Your Android application needs to be able to respond
@@ -217,22 +239,26 @@ ID in a database. </li>
<p>The registration ID lasts until the Android application explicitly unregisters
itself, or until Google refreshes the registration ID for your Android application.</p>
-<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 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>
<p>
-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>
-</p>
+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>
+
+
-<h4 id="push-process">Sending a Message</h4>
+
+<h4 id="push-process">Send a Message</h4>
<p>For an application server to send a message to an Android application, the following things must be in
place:</p>
<ul>
- <li>The Android application has a registration ID that allows it to receive messages
+ <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:
+ <ul>
+ <li>A single registration ID (or an array of registration IDs) that allows the app to receive messages
for a particular device.</li>
- <li>The 3rd-party application server has stored the registration ID.</li>
-
-
+ <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>
+ </ul>
+ </li>
<li>An API key. This is something that the developer must have already
set up on the application server for the Android application (for more discussion, see
@@ -259,7 +285,7 @@ non-trivial processing, you may want to grab a {@link android.os.PowerManager.Wa
<p> An Android application can unregister GCM if it no longer wants to receive
messages.</p>
-<h4 id="receiving">Receiving a Message</h4>
+<h4 id="receiving">Receive a Message</h4>
<p>This is the sequence of events that occurs when an Android application
installed on a mobile device receives a message:</p>
@@ -313,25 +339,21 @@ simpler approach), see <a href="gs.html">GCM: Getting Started</a>.
<h3 id="manifest">Creating the Manifest</h3>
-<p>Every Android application must have an <code>AndroidManifest.xml</code> file (with
-precisely that name) in its root directory. The manifest presents essential
-information about the Android application to the Android system, information the
-system must have before it can run any of the Android application's code (for more
-discussion of the manifest file, see the <a href="{@docRoot}guide/topics/manifest/manifest-intro.html">Android Developers Guide</a>. To use the GCM feature, the
-manifest must include the following:</p>
+<p>To use the GCM feature, the
+<code>AndroidManifest.xml</code> file must include the following:</p>
<ul>
<li>The <code>com.google.android.c2dm.permission.RECEIVE</code> permission so the Android application can register and receive messages.</li>
- <li>The <code>android.permission.INTERNET</code> permission so the Android application can send the registration ID to the 3rd party server.</li>
+ <li>The <code>android.permission.INTERNET</code> permission so the Android application can send the registration ID to the 3rd-party server.</li>
<li>The <code>android.permission.GET_ACCOUNTS</code> permission as GCM requires a Google account (necessary only if if the device is running a version lower than Android 4.0.4)</li>
- <li>The <code>android.permission.WAKE_LOCK</code> permission so the application can keep the processor from sleeping when a message is received.</li>
+ <li>The <code>android.permission.WAKE_LOCK</code> permission so the application can keep the processor from sleeping when a message is received. Optional&mdash;use only if the app wants to keep the device from sleeping.</li>
<li>An <code>applicationPackage + &quot;.permission.C2D_MESSAGE</code> permission to prevent other Android applications from registering and receiving the Android application's
messages. The permission name must exactly match this pattern&mdash;otherwise the Android application will not receive the messages.</li>
- <li>A receiver for <code>com.google.android.c2dm.intent.RECEIVE</code> and <code>com.google.android.c2dm.intent.REGISTRATION</code>, with the category set
+ <li>A receiver for <code>com.google.android.c2dm.intent.RECEIVE</code> and <code>com.google.android.c2dm.intent.REGISTRATION</code>, with the category set
as <code>applicationPackage</code>. The receiver should require the <code>com.google.android.c2dm.SEND</code> permission, so that only the GCM
Framework can send a message to it. Note that both registration and the receiving
of messages are implemented as <a href="{@docRoot}guide/components/intents-filters.html">Intents</a>.</li>
- <li>An intent service to handle the intents received by the broadcast receiver.</li>
+ <li>An intent service to handle the intents received by the broadcast receiver. Optional.</li>
<li>If the GCM feature is critical to the Android application's function, be sure to
set <code>android:minSdkVersion=&quot;8&quot;</code> in the manifest. This
ensures that the Android application cannot be installed in an environment in which it
@@ -368,8 +390,19 @@ could not run properly. </li>
&lt;/manifest&gt;
</pre>
+
<h3 id="registering">Registering for GCM</h3>
+<div class="sidebox-wrapper">
+<div class="sidebox">
+ <h2>Streamlined Registration</h2>
+ <p>There is now a simpler alternative to registering and unregistering. Simply call the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> method
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html#register">{@code register(senderID...)}</a>.
+This method registers the application for GCM and returns the registration ID. To unregister, call the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html#unregister">{@code unregister()}</a> method (though you should rarely if ever need to unregister).</p>
+</div>
+</div>
+
<p>An Android application needs to register with GCM servers before it can receive messages. To register, the application sends an Intent
(<code>com.google.android.c2dm.intent.REGISTER</code>), with 2 extra parameters:
</p>
@@ -383,7 +416,7 @@ allow the registration service to extract Android application information. </li>
<p>For example:</p>
-<pre class="prettyprint pretty-java">Intent registrationIntent = new Intent(&quot;com.google.android.c2dm.intent.REGISTER&quot;);
+<pre style="clear:right">Intent registrationIntent = new Intent(&quot;com.google.android.c2dm.intent.REGISTER&quot;);
// sets the app name in the intent
registrationIntent.putExtra(&quot;app&quot;, PendingIntent.getBroadcast(this, 0, new Intent(), 0));
registrationIntent.putExtra(&quot;sender&quot;, senderID);
@@ -415,10 +448,10 @@ startService(unregIntent);
defines a broadcast receiver for the <code>com.google.android.c2dm.intent.REGISTRATION</code> and <code>com.google.android.c2dm.intent.RECEIVE</code> intents.
These <a href="{@docRoot}guide/components/intents-filters.html">intents</a> are sent by GCM to indicate that a device was registered (or unregistered), or to deliver messages, respectively.</p>
-<p>Handling these intents might require I/O operations (such as network calls to the 3rd party server), and
+<p>Handling these intents might require I/O operations (such as network calls to the 3rd-party server), and
such operations should not be done in the receiver's <code>onReceive()</code> method.
-You may be tempted to spawn a new thread directly, but there are no guarantees that the process will run long enough for the thread to finish the work.
-Thus the recommended way to handle the intents is to delegate them to a service, such as an {@link android.app.IntentService}.
+You may be tempted to spawn a new thread directly, but there are no guarantees that the process will run long enough for the thread to finish the work.
+Thus the recommended way to handle the intents is to delegate them to a service, such as an {@link android.app.IntentService}.
For example:</p>
@@ -476,18 +509,18 @@ public class MyIntentService extends IntentService {
<p>When a <code>com.google.android.c2dm.intent.REGISTRATION</code> intent is received, it could potentially contain 3 extras: <code>registration_id</code>, <code>error</code>, and <code>unregistered</code>.
-<p>When a registration succeeds, <code>registration_id</code> contains the registration ID and the other extras are not set.
-The application must ensure that the 3rd-party server receives the registration ID. It may do so by saving the registration ID and sending it to the server.
+<p>When a registration succeeds, <code>registration_id</code> contains the registration ID and the other extras are not set.
+The application must ensure that the 3rd-party server receives the registration ID. It may do so by saving the registration ID and sending it to the server.
If the network is down or there are errors, the application should retry sending the registration ID when the network is up again or the next time it starts.</p>
<p class="note"><strong>Note:</strong> Although the <code>com.google.android.c2dm.intent.REGISTRATION</code> intent is typically received after a request was made by the application,
Google may periodically refresh the registration ID. So the application must be prepared to handle it at any time.</p>
-<p>When an unregistration succeeds, only the <code>unregistered</code> extra is set, and similar to the registration workflow,
-the application must contact the 3rd-party server to remove the registration ID (note that the registration ID is not available in the intent,
+<p>When an unregistration succeeds, only the <code>unregistered</code> extra is set, and similar to the registration workflow,
+the application must contact the 3rd-party server to remove the registration ID (note that the registration ID is not available in the intent,
but the application should have saved the registration ID when it got it).<p>
-<p>If the application request (be it register or unregister) fails, the <code>error</code> will be set with an error code, and the other extras will not be set.
+<p>If the application request (be it register or unregister) fails, the <code>error</code> will be set with an error code, and the other extras will not be set.
Here are the possible error codes:</p>
@@ -536,7 +569,7 @@ phone doesn't currently support GCM.</td>
private void handleRegistration(Intent intent) {
String registrationId = intent.getStringExtra("registration_id");
String error = intent.getStringExtra("error");
- String unregistered = intent.getStringExtra("unregistered");
+ String unregistered = intent.getStringExtra("unregistered");
// registration succeeded
if (registrationId != null) {
// store registration ID on shared preferences
@@ -561,12 +594,14 @@ private void handleRegistration(Intent intent) {
}
}</pre>
+
+
<h4 id="received_data">Handling Received Data</h4>
-<p>The <code>com.google.android.c2dm.intent.RECEIVE</code> intent is used by GCM to
+<p>The <code>com.google.android.c2dm.intent.RECEIVE</code> intent is used by GCM to
deliver the messages sent by the 3rd-party server to the application running in the device.
-If the server included key-pair values in the <code>data</code> parameter, they are available as
-extras in this intent, with the keys being the extra names. GCM also includes an extra called
+If the server included key-pair values in the <code>data</code> parameter, they are available as
+extras in this intent, with the keys being the extra names. GCM also includes an extra called
<code>from</code> which contains the sender ID as an string, and another called <code>collapse_key</code> containing the collapse key (when in use).
<p>Here is an example, again using the <code>MyIntentReceiver</code> class:</p>
@@ -620,6 +655,7 @@ messages.</li>
<p>This section describes how the 3rd-party application server sends messages to one or more mobile devices. Note the following:</p>
<ul>
<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>
+ <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>.
<li>You have 2 choices in how you construct requests and responses: plain text or JSON.</li>
<li>However, to send multicast messages, you must use JSON. Plain text will not work.</li>
@@ -660,8 +696,19 @@ Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA
</tr>
<tr>
<td><code>registration_ids</code></td>
- <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). Required.</td>
+ <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>
+ </tr>
+ <tr>
+ <td><code>notification_key</code></td>
+ <td>A string that maps a single user to multiple registration IDs associated with that user. This
+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>
+ </tr>
+
+<tr>
+ <td><code>notification_key_name</code></td>
+ <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>
</tr>
+
<tr>
<td><code>collapse_key</code></td>
<td>An arbitrary string (such as &quot;Updates Available&quot;) that is used to collapse a group of like messages
@@ -1043,8 +1090,7 @@ A message was addressed to a registration ID whose package name did not match th
registration_id=32
</pre>
-
-<h3 id="stats">Viewing statistics</h3>
+<h3 id="stats">Viewing Statistics</h3>
<p>To view statistics and any error messages for your GCM applications:</p>
<ol>
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index e96b204..d938bd6 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -1,16 +1,10 @@
-page.title=GCM: Getting Started
+page.title=Getting Started with GCM
page.tags="cloud","push","messaging"
@jd:body
<div id="qv-wrapper">
<div id="qv">
-<h2>Quickview</h2>
-
-<ul>
-<li>Walk through the steps of creating a GCM app.</li>
-</ul>
-
<h2>In this document</h2>
@@ -18,15 +12,37 @@ page.tags="cloud","push","messaging"
<li><a href="#create-proj">Creating a Google API Project</a></li>
<li><a href="#gcm-service">Enabling the GCM Service</a></li>
<li><a href="#access-key">Obtaining an API Key</a></li>
-<li><a href="#libs">Installing the Helper Libraries</a></li>
<li><a href="#android-app">Writing the Android Application</a>
-<li><a href="#server-app">Writing the Server-side Application</a> </li>
+</ol>
+
+<h2>See Also</h2>
+
+<ol class="toc">
+<li><a href="https://code.google.com/apis/console">Google APIs Console page</a></li>
+<li><a href="{@docRoot}google/gcm/helper.html">Using the GCM Helper Libraries</a></li>
+<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
</ol>
</div>
</div>
-<p>This document describes how to write an Android application and the server-side logic, using the client and server <a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a> provided by GCM.</p>
+<p>The sections below guide you through the process of setting up a GCM
+implementation.
+Before you start, make sure to <a href="/google/play-services/setup.html">set up
+the Google Play Services SDK</a>. You need this SDK to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> methods. Strictly speaking, the only thing you absolutely need this API for is upstream (device-to-cloud) messaging, but it also offers a streamlined registration API that is recommended.</p>
+
+
+<!--the basic steps are:
+
+<ul>
+<li>Creating a Google APIs Project</li>
+<li>Setting up GCM in your apps</li>
+<li>Integrating </li>
+
+<p>Note that a full GCM implementation requires a server-side implementation, in addition to the client implementation in your app. For complete information, make sure to read the <a href="/google/gcm/index.html">Google Cloud Messaging documentation</a>.
+-->
+
+
<h2 id="create-proj">Creating a Google API project</h2>
@@ -58,174 +74,260 @@ page.tags="cloud","push","messaging"
<ol>
<li> In the main Google APIs Console page, select <strong>API Access</strong>. You will see a screen that resembles the following:</li><br />
-<div style="width:408px;margin:1.5em;">
-<div style="width:410px;border:1px solid #DDD;">
+
<img src="{@docRoot}images/gcm/gcm-api-access.png" style="width:400px;padding:4px;margin-bottom:0em;">
-</div>
-</div>
+
<li>Click <strong>Create new Server key</strong>. Either a server key or a browser key should work. The advantage to using a server key is that it allows you to whitelist IP addresses. The following screen appears:</li><br />
-<div style="width:408px;margin:1.5em;">
-<div style="width:410px;border:1px solid #DDD;">
+
<img src="{@docRoot}images/gcm/gcm-config-server-key.png" style="width:400px;padding:4px;margin-bottom:0em;">
-</div>
-</div>
+
<li>Click <strong>Create</strong>:</li><br />
-<div style="width:408px;margin:1.5em;">
-<div style="width:410px;border:1px solid #DDD;">
+
<img src="{@docRoot}images/gcm/gcm-api-key.png" style="width:400px;padding:4px;margin-bottom:0em;">
-</div>
-</div>
+
</ol>
<p> Take note of the <strong>API key</strong> value (<code>YourKeyWillBeShownHere</code>) in this example, as it will be used later on.</p>
<p class="note"><strong>Note:</strong> If you need to rotate the key, click <strong>Generate new key</strong>. A new key will be created while the old one will still be active for up to 24 hours. If you want to get rid of the old key immediately (for example, if you feel it was compromised), click <strong>Delete key</strong>.</p>
-<h2 id="libs">Install the Helper Libraries</h2>
-<p>To perform the steps described in the following sections, you must first install the
-<a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a>. Note that while using the helper libraries is recommended, it is not required. See the <a href="gcm.html#writing_apps">GCM Architectural Overview</a> for a description of how to write apps without using the helper libraries.
-
-<p>To install the helper libraries, choose
-<strong>Extras &gt; Google Cloud Messaging for Android Library</strong>
-from the SDK Manager. This creates a <code>gcm</code> directory under
-<code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these
-subdirectories: <code>gcm-client</code>, <code>gcm-server</code>,
-<code>samples/gcm-demo-client</code>, <code>samples/gcm-demo-server</code>,
-and <code>samples/gcm-demo-appengine</code>.</p>
-
-<p class="note"><strong>Note:</strong> If you don't see <strong>Extras &gt; Google Cloud Messaging for Android Library</strong> in the SDK Manager, make sure you are running version 20 or higher. Be sure to restart the SDK Manager after updating it.</p>
<h2 id="android-app">Writing the Android Application</h2>
<p>This section describes the steps involved in writing an Android application that uses GCM.</p>
-<h4>Step 1: Copy the gcm.jar file into your application classpath</h4>
-<p> To write your Android application, first copy the <code>gcm.jar</code> file from the SDK's <code>gcm-client/dist</code> directory to your application classpath.</p>
-<h4>Step 2: Make the following changes in the application's Android manifest</h4>
-<ol>
- <li>GCM requires Android 2.2 or later, so if your application cannot work without GCM, add the following line, where <em>xx</em> is the latest target SDK version:</li>
-
-<pre class="prettyprint pretty-xml">&lt;uses-sdk android:minSdkVersion=&quot;8&quot; android:targetSdkVersion=&quot;xx&quot;/&gt;</pre>
-
- <li>Declare and use a custom permission so only this application can receive GCM messages:<br>
- </li>
-<pre class="prettyprint pretty-xml">&lt;permission android:name=&quot;my_app_package.permission.C2D_MESSAGE&quot; android:protectionLevel=&quot;signature&quot; /&gt;
-&lt;uses-permission android:name=&quot;my_app_package.permission.C2D_MESSAGE&quot; /&gt; </pre>
-<p> This permission must be called <code>my_app_package.permission.C2D_MESSAGE</code> (where <code>my_app_package</code> is the package name of your app as defined by the manifest tag), otherwise it will not work.</p>
-<p class="note"><strong>Note:</strong> This permission is not required if you are targeting your application to 4.1 or above (i.e., minSdkVersion 16)</p>
+<h4 id="manifest">Step 1: Make the following changes in the application's Android manifest</h4>
+<ul>
+ <li>The <code>com.google.android.c2dm.permission.RECEIVE</code> permission so the Android application can register and receive messages.</li>
+ <li>The <code>android.permission.INTERNET</code> permission so the Android application can send the registration ID to the 3rd party server.</li>
+ <li>The <code>android.permission.GET_ACCOUNTS</code> permission as GCM requires a Google account (necessary only if if the device is running a version lower than Android 4.0.4)</li>
+ <li>The <code>android.permission.WAKE_LOCK</code> permission so the application can keep the processor from sleeping when a message is received. Optional&mdash;use only if the app wants to keep the device from sleeping.</li>
+ <li>An <code>applicationPackage + &quot;.permission.C2D_MESSAGE</code> permission to prevent other Android applications from registering and receiving the Android application's
+messages. The permission name must exactly match this pattern&mdash;otherwise the Android application will not receive the messages.</li>
+ <li>A receiver for <code>com.google.android.c2dm.intent.RECEIVE</code>, with the category set
+as <code>applicationPackage</code>. The receiver should require the <code>com.google.android.c2dm.SEND</code> permission, so that only the GCM
+Framework can send a message to it. Note that the receiving
+of messages is implemented as an <a href="{@docRoot}guide/components/intents-filters.html">intent</a>.</li>
+ <li>An intent service to handle the intents received by the broadcast receiver. Optional.</li>
+ <li>If the GCM feature is critical to the Android application's function, be sure to
+set <code>android:minSdkVersion=&quot;8&quot;</code> in the manifest. This
+ensures that the Android application cannot be installed in an environment in which it
+could not run properly. </li>
+</ul>
- <li>Add the following permissions:</li>
+<p>Here are excerpts from a manifest that supports GCM:</p>
-<pre class="prettyprint pretty-xml">&lt;!-- App receives GCM messages. --&gt;
-&lt;uses-permission android:name=&quot;com.google.android.c2dm.permission.RECEIVE&quot; /&gt;
-&lt;!-- GCM connects to Google Services. --&gt;
-&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
-&lt;!-- GCM requires a Google account. --&gt;
-&lt;uses-permission android:name=&quot;android.permission.GET_ACCOUNTS&quot; /&gt;
-&lt;!-- Keeps the processor from sleeping when a message is received. --&gt;
-&lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot; /&gt;</pre>
+<pre class="prettyprint pretty-xml">
+&lt;manifest package="com.example.gcm" ...&gt;
- <li>Add the following broadcast receiver:</li>
+ &lt;uses-sdk android:minSdkVersion="8" android:targetSdkVersion="17"/&gt;
+ &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
+ &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
+ &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
+ &lt;uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" /&gt;
-<pre class="prettyprint pretty-xml">&lt;receiver android:name=&quot;com.google.android.gcm.GCMBroadcastReceiver&quot; android:permission=&quot;com.google.android.c2dm.permission.SEND&quot; &gt;
- &lt;intent-filter&gt;
- &lt;action android:name=&quot;com.google.android.c2dm.intent.RECEIVE&quot; /&gt;
- &lt;action android:name=&quot;com.google.android.c2dm.intent.REGISTRATION&quot; /&gt;
- &lt;category android:name=&quot;my_app_package&quot; /&gt;
- &lt;/intent-filter&gt;
-&lt;/receiver&gt;</pre>
-<p> This broadcast receiver is responsible for handling the 2 intents that can be sent by GCM (<code>com.google.android.c2dm.intent.RECEIVE</code> and <code>com.google.android.c2dm.intent.REGISTRATION</code>) and should be defined in the manifest (rather than programmatically) so that these intents can be received even if the application is not running. By setting the <code>com.google.android.c2dm.permission.SEND</code> permission, you are ensuring that only intents sent by the GCM system framework are sent to the receiver (a regular application cannot issue intents with that permission).</p>
-<p> Notice that <code>android:name</code> in the category tag must be replaced by your application's package name (and the category tag is not required for applications targeted to minSdkVersion 16 and higher).<br>
- </p>
+ &lt;permission android:name="com.example.gcm.permission.C2D_MESSAGE"
+ android:protectionLevel="signature" /&gt;
+ &lt;uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" /&gt;
- <li>Add the following intent service:</li>
+ &lt;application ...&gt;
+ &lt;receiver
+ android:name=".MyBroadcastReceiver"
+ android:permission="com.google.android.c2dm.permission.SEND" &gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="com.google.android.c2dm.intent.RECEIVE" /&gt;
+ &lt;category android:name="com.example.gcm" /&gt;
+ &lt;/intent-filter&gt;
+ &lt;/receiver&gt;
+ &lt;service android:name=".MyIntentService" /&gt;
+ &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
- <pre class="prettyprint pretty-xml">&lt;service android:name=&quot;.GCMIntentService&quot; /&gt;</pre>
-</ol>
-<p>This intent service will be called by the <code>GCMBroadcastReceiver</code> (which is provided by the GCM library), as shown in the next step. It must be a subclass of <code>com.google.android.gcm.GCMBaseIntentService</code>, must contain a public constructor, and should be named <code>my_app_package.GCMIntentService</code> (unless you use a subclass of <code>GCMBroadcastReceiver</code> that overrides the method used to name the service).</p>
+<h4>Step 2: Register for GCM</h4>
-<p>The intent service must also define its sender ID(s). It does this as follows:</p>
-<ul>
- <li>If the value is static, the service's default constructor should call <code>super(senderIds)</code>.</li>
- <li>If the value is dynamic, the service should override the <code>getSenderIds()</code> method.</li>
-</ul>
+<p>An Android application running on a mobile device registers to receive messages by calling
+the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> method
+<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html#register">{@code register(senderID...)}</a>.
+This method registers the application for GCM and returns the registration ID. This streamlined approach replaces the previous
+GCM registration process.</p>
+<h4> Step 3: Write your application</h4>
-<h4>Step 3: Write the my_app_package.GCMIntentService class</h4>
+<p>Finally, write your application. GCM offers a variety of ways to get the job done:</p>
-<p>Next write the <code>my_app_package.GCMIntentService</code> class, overriding the following callback methods (which are called by <code>GCMBroadcastReceiver</code>):<br>
-</p>
<ul>
- <li><code>onRegistered(Context context, String regId)</code>: Called after a registration intent is received, passes the registration ID assigned by GCM to that device/application pair as parameter. Typically, you should send the <code>regid</code> to your server so it can use it to send messages to this device.</li>
- <li><code>onUnregistered(Context context, String regId)</code>: Called after the device has been unregistered from GCM. Typically, you should send the <code>regid</code> to the server so it unregisters the device.</li>
- <li><code>onMessage(Context context, Intent intent)</code>: Called when your server sends a message to GCM, and GCM delivers it to the device. If the message has a payload, its contents are available as extras in the intent.</li>
- <li><code>onError(Context context, String errorId)</code>: Called when the device tries to register or unregister, but GCM returned an error. Typically, there is nothing to be done other than evaluating the error (returned by errorId) and trying to fix the problem.</li>
- <li> <code>onRecoverableError(Context context, String errorId)</code>: Called when the device tries to register or unregister, but the GCM servers are unavailable. The GCM library will retry the operation using exponential backup, unless this method is overridden and returns false. This method is optional and should be overridden only if you want to display the message to the user or cancel the retry attempts.
- </li>
+ <li>For your messaging server, you can either use the new <a href="ccs.html">GCM Cloud Connection Server</a> (CCS), the older <a href="gcm.html">GCM HTTP server</a>, or both in tandem.</li>
+ <li>To write your client application, you can use any of the following:
+ <ul>
+ <li>The helper libraries, which are described in the <a href="{@docRoot}google/gcm/demo.html">Demo App Tutorial</a> and <a href="{@docRoot}google/gcm/helper.html">Using the GCM Helper Libraries</a>.</li>
+ <li>The approach described in the <a href="{@docRoot}google/gcm/gcm.html#writing_apps">GCM Architectural Overview</a>.</li>
+ <li>Regardless, you must use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs if you are doing upstream (device-to-cloud) messaging. Even if you are not doing upstream messaging, we recommend that you use this API to take advantage of the streamlined registration process&mdash;described above and shown in the following sample.</li>
+</ul>
+</li>
+
</ul>
-<p class="note"><strong>Note:</strong> The methods above run in the intent service's thread and hence are free to make network calls without the risk of blocking the UI thread.</p>
-
-<h4> Step 4: Write your application's main activity</h4>
-Add the following import statement in your application's main activity:
-<pre class="prettyprint pretty-java">import com.google.android.gcm.GCMRegistrar;</pre>
-<p> In the <code>onCreate()</code> method, add the following code:</p>
-<pre class="prettyprint pretty-java">GCMRegistrar.checkDevice(this);
-GCMRegistrar.checkManifest(this);
-final String regId = GCMRegistrar.getRegistrationId(this);
-if (regId.equals("")) {
- GCMRegistrar.register(this, SENDER_ID);
-} else {
- Log.v(TAG, "Already registered");
+<h5 id="gs_example">Example</h5>
+
+<p>Here is a sample application that illustrates how to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">{@code GoogleCloudMessaging}</a> APIs. In this example, the sender is a <a href="{@docRoot}google/gcm/ccs.html">CCS</a> echo server. The sample consists of a main Activity ({@code DemoActivity}) and a broadcast receiver ({@code GcmBroadcastReceiver}).</p>
+
+<p>An Android application needs to register with GCM servers before it can receive messages. So in its {@code onCreate()} method, {@code DemoActivity} checks to see whether the app is registered with GCM and with the server:</p>
+
+<pre>public class DemoActivity extends Activity {
+
+ public static final String EXTRA_MESSAGE = "message";
+ public static final String PROPERTY_REG_ID = "registration_id";
+ /**
+ * You can use your own project ID instead. This sender is a test CCS
+ * echo server.
+ */
+ String GCM_SENDER_ID = "Your-Sender-ID";
+
+ // Tag for log messages.
+ static final String TAG = "GCMDemo";
+
+ TextView mDisplay;
+ GoogleCloudMessaging gcm;
+ AtomicInteger msgId = new AtomicInteger();
+ SharedPreferences prefs;
+ String regid;
+
+ &#64;Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Make sure the app is registered with GCM and with the server
+ prefs = getSharedPreferences(DemoActivity.class.getSimpleName(),
+ Context.MODE_PRIVATE);
+ setContentView(R.layout.main);
+
+ mDisplay = (TextView) findViewById(R.id.display);
+
+ regid = prefs.getString(PROPERTY_REG_ID, null);
+
+ // If there is no registration ID, the app isn't registered.
+ // Call registerBackground() to register it.
+ if (regid == null) {
+ registerBackground();
+ }
+
+ gcm = GoogleCloudMessaging.getInstance(this);
+ }</pre>
+
+<p>If the app isn't registered, {@code DemoActivity} calls the following {@code registerBackground()} method to register it. Note that because GCM methods are blocking, this has to take place on a background thread. This sample uses {@link android.os.AsyncTask} to accomplish this:</p>
+
+<pre>private void registerBackground() {
+ new AsyncTask<Void, Void, String>() {
+ &#64;Override
+ protected String doInBackground(Void... params) {
+ String msg = "";
+ try {
+ regid = gcm.register(GCM_SENDER_ID);
+ msg = "Device registered, registration id=" + regid;
+
+ // You should send the registration ID to your server over HTTP,
+ // so it can use GCM/HTTP or CCS to send messages to your app.
+
+ // For this demo: we don't need to send it because the device
+ // will send upstream messages to a server that will echo back
+ // the message using the 'from' address in the message.
+
+ // Save the regid for future use - no need to register again.
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putString(PROPERTY_REG_ID, regid);
+ editor.commit();
+ } catch (IOException ex) {
+ msg = "Error :" + ex.getMessage();
+ }
+ return msg;
+ }
+ // Once registration is done, display the registration status
+ // string in the Activity's UI.
+ &#64;Override
+ protected void onPostExecute(String msg) {
+ mDisplay.append(msg + "\n");
+ }
+ }.execute(null, null, null);
}</pre>
-<p>The <code>checkDevice()</code> method verifies that the device supports GCM and throws an exception if it does not (for instance, if it is an emulator that does not contain the Google APIs). Similarly, the <code>checkManifest()</code> method verifies that the application manifest contains meets all the requirements described in <a href="#android-app">Writing the Android Application</a> (this method is only necessary when you are developing the application; once the application is ready to be published, you can remove it).</p>
-
-<p>Once the sanity checks are done, the device calls <code>GCMRegsistrar.register()</code> to register the device, passing the <code>SENDER_ID</code> you got when you signed up for GCM. But since the <code>GCMRegistrar</code> singleton keeps track of the registration ID upon the arrival of registration intents, you can call <code>GCMRegistrar.getRegistrationId()</code> first to check if the device is already registered.</p>
-<p class="note"><strong>Note:</strong> It is possible that the device was successfully registered to GCM but failed to send the registration ID to your server, in which case you should retry. See <a href="adv.html#reg-state">Advanced Topics</a> for more details on how to handle this scenario.</p>
-
-<h2 id="server-app">Writing the Server-side Application</h2>
-
-<p>To write the server-side application:</p>
-<ol>
- <li> Copy the <code>gcm-server.jar</code> file from the SDK's <code>gcm-server/dist</code> directory to your server classpath.</li>
- <li>Create a servlet (or other server-side mechanism) that can be used by the Android application to send the registration ID received by GCM . The application might also need to send other information&mdash;such as the user's email address or username&mdash;so that the server can associate the registration ID with the user owning the device.</li>
- <li>Similarly, create a servlet used to unregister registration IDs.<br>
- </li>
-<li>When the server needs to send a message to the registration ID, it can use the <code>com.google.android.gcm.server.Sender</code> helper class from the GCM library. For example:</li>
-</ol>
-<pre class="prettyprint pretty-java">import com.google.android.gcm.server.*;
-
-Sender sender = new Sender(myApiKey);
-Message message = new Message.Builder().build();
-MulticastResult result = sender.send(message, devices, 5);</pre>
+<p>When the user clicks the app's <strong>Echo</strong> button, the app generates the necessary XMPP stanza for the message, which it sends to the echo server:</p>
+<pre>public void onClick(final View view) {
+ if (view == findViewById(R.id.send)) {
+ new AsyncTask<Void, Void, String>() {
+ &#64;Override
+ protected String doInBackground(Void... params) {
+ String msg = "";
+ try {
+ Bundle data = new Bundle();
+ // data is a key-value pair.
+ data.putString("hello", "world");
+ String id = Integer.toString(msgId.incrementAndGet());
+ gcm.send(GCM_SENDER_ID + "&#64;gcm.googleapis.com", id, data);
+ msg = "Sending message";
+ } catch (IOException ex) {
+ msg = "Error :" + ex.getMessage();
+ }
+ return msg;
+ }
+
+ &#64;Override
+ protected void onPostExecute(String msg) {
+ // Displays the text "Sending message"
+ mDisplay.append(msg + "\n");
+ }
+ }.execute(null, null, null);
+ }
+}</pre>
-<p> The snippet above does the following:
-<ul>
-<li>Creates a <code>Sender</code> object using your project's API key.</li>
-<li>Creates a message using a given registration ID (the message builder also has methods to set all message parameters such as the collapse key and payload data).</li>
-<li>Sends the message with a maximum of 5 retry attempts (in case the GCM servers are unavailable), and stores the response on result. </li>
-</ul>
-<p>It's now necessary to parse the result and take the proper action in the following cases:</p>
-<ul>
- <li>If the message was created but the result returned a canonical registration ID, it's necessary to replace the current registration ID with the canonical one.</li>
- <li>If the returned error is <code>NotRegistered</code>, it's necessary to remove that registration ID, because the application was uninstalled from the device.</li>
-</ul>
-<p> Here's a code snippet that handles these 2 conditions:</p>
-<pre class="prettyprint pretty-java">
-if (result.getMessageId() != null) {
- String canonicalRegId = result.getCanonicalRegistrationId();
- if (canonicalRegId != null) {
- // same device has more than on registration ID: update database
- }
-} else {
- String error = result.getErrorCodeName();
- if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
- // application has been removed from device - unregister database
- }
+<p>As described above in <a href="#manifest">Step 1</a>, the app includes a broadcast receiver for the <code>com.google.android.c2dm.intent.RECEIVE</code> intent. This is the mechanism GCM uses to deliver messages. When {@code onClick()} calls {@code gcm.send()}, it triggers the broadcast receiver's {@code onReceive()} method, which has the responsibility of handling the GCM message. In this sample the receiver's {@code onReceive()} method calls {@code sendNotification()} to put the message into a notification:</p>
+
+<pre>public class GcmBroadcastReceiver extends BroadcastReceiver {
+ static final String TAG = "GCMDemo";
+ public static final int NOTIFICATION_ID = 1;
+ private NotificationManager mNotificationManager;
+ NotificationCompat.Builder builder;
+ Context ctx;
+
+
+ &#64;Override
+ public void onReceive(Context context, Intent intent) {
+ GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
+ ctx = context;
+ String messageType = gcm.getMessageType(intent);
+ if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
+ sendNotification("Send error: " + intent.getExtras().toString());
+ } else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
+ sendNotification("Deleted messages on server: " +
+ intent.getExtras().toString());
+ } else {
+ sendNotification("Received: " + intent.getExtras().toString());
+ }
+ setResultCode(Activity.RESULT_OK);
+ }
+
+ // Put the GCM message into a notification and post it.
+ private void sendNotification(String msg) {
+ mNotificationManager = (NotificationManager)
+ ctx.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ PendingIntent contentIntent = PendingIntent.getActivity(ctx, 0,
+ new Intent(ctx, DemoActivity.class), 0);
+
+ NotificationCompat.Builder mBuilder =
+ new NotificationCompat.Builder(ctx)
+ .setSmallIcon(R.drawable.ic_stat_notification)
+ .setContentTitle("GCM Notification")
+ .setStyle(new NotificationCompat.BigTextStyle()
+ .bigText(msg))
+ .setContentText(msg);
+
+ mBuilder.setContentIntent(contentIntent);
+ mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());
+ }
}</pre>
diff --git a/docs/html/google/gcm/helper.jd b/docs/html/google/gcm/helper.jd
new file mode 100644
index 0000000..bde2df0
--- /dev/null
+++ b/docs/html/google/gcm/helper.jd
@@ -0,0 +1,182 @@
+page.title=Using the GCM Helper Libraries
+page.tags="cloud","push","messaging"
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Quickview</h2>
+
+<ul>
+<li>Walk through the steps of creating a GCM app.</li>
+</ul>
+
+
+<h2>In this document</h2>
+
+<ol class="toc">
+<li><a href="#libs">Installing the Helper Libraries</a></li>
+<li><a href="#android-app">Writing the Android Application</a>
+<li><a href="#server-app">Writing the Server-side Application</a> </li>
+</ol>
+
+<h2>See Also</h2>
+
+<ol class="toc">
+<li><a href="{@docRoot}google/play-services/gcm/gs.html">Getting Started with GCM Extensions</a></li>
+<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>This document describes how to write an Android application and the server-side logic, using the client and server <a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a> provided by GCM.</p>
+
+<p>The helper libraries are one option for creating an Android application that uses GCM. You can alternatively use the approach described in the <a href="{@docRoot}google/gcm/gcm.html#writing_apps">GCM Architectural Overview</a>. If you need to perform upstream messaging, you must use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> APIs, and <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> also provides a streamlined registration process.</p>
+
+<p>For information on how to get started creating an Android GCM application and an example of how to use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> APIs, see <a href="{@docRoot}google/gcm/gs.html">Getting Started</a>.</p>
+
+<h2 id="libs">Installing the Helper Libraries</h2>
+<p>To perform the steps described in the following sections, you must first install the
+<a href="{@docRoot}reference/com/google/android/gcm/package-summary.html">helper libraries</a>. Note that while using the helper libraries is recommended, it is not required. See the <a href="gcm.html#writing_apps">GCM Architectural Overview</a> for a description of how to write apps without using the helper libraries.
+
+<p>To install the helper libraries, choose
+<strong>Extras &gt; Google Cloud Messaging for Android Library</strong>
+from the SDK Manager. This creates a <code>gcm</code> directory under
+<code><em>YOUR_SDK_ROOT</em>/extras/google/</code> containing these
+subdirectories: <code>gcm-client</code>, <code>gcm-server</code>,
+<code>samples/gcm-demo-client</code>, <code>samples/gcm-demo-server</code>,
+and <code>samples/gcm-demo-appengine</code>.</p>
+
+<p class="note"><strong>Note:</strong> If you don't see <strong>Extras &gt; Google Cloud Messaging for Android Library</strong> in the SDK Manager, make sure you are running version 20 or higher. Be sure to restart the SDK Manager after updating it.</p>
+
+<h2 id="android-app">Writing the Android Application</h2>
+<p>This section describes the steps involved in writing an Android application that uses GCM.</p>
+<h4>Step 1: Copy the gcm.jar file into your application classpath</h4>
+<p> To write your Android application, first copy the <code>gcm.jar</code> file from the SDK's <code>gcm-client/dist</code> directory to your application classpath.</p>
+<h4>Step 2: Make the following changes in the application's Android manifest</h4>
+<ol>
+ <li>GCM requires Android 2.2 or later, so if your application cannot work without GCM, add the following line, where <em>xx</em> is the latest target SDK version:</li>
+
+<pre class="prettyprint pretty-xml">&lt;uses-sdk android:minSdkVersion=&quot;8&quot; android:targetSdkVersion=&quot;xx&quot;/&gt;</pre>
+
+ <li>Declare and use a custom permission so only this application can receive GCM messages:<br>
+ </li>
+
+<pre class="prettyprint pretty-xml">&lt;permission android:name=&quot;my_app_package.permission.C2D_MESSAGE&quot; android:protectionLevel=&quot;signature&quot; /&gt;
+&lt;uses-permission android:name=&quot;my_app_package.permission.C2D_MESSAGE&quot; /&gt; </pre>
+<p> This permission must be called <code>my_app_package.permission.C2D_MESSAGE</code> (where <code>my_app_package</code> is the package name of your app as defined by the manifest tag), otherwise it will not work.</p>
+<p class="note"><strong>Note:</strong> This permission is not required if you are targeting your application to 4.1 or above (i.e., minSdkVersion 16)</p>
+
+ <li>Add the following permissions:</li>
+
+<pre class="prettyprint pretty-xml">&lt;!-- App receives GCM messages. --&gt;
+&lt;uses-permission android:name=&quot;com.google.android.c2dm.permission.RECEIVE&quot; /&gt;
+&lt;!-- GCM connects to Google Services. --&gt;
+&lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
+&lt;!-- GCM requires a Google account. --&gt;
+&lt;uses-permission android:name=&quot;android.permission.GET_ACCOUNTS&quot; /&gt;
+&lt;!-- Keeps the processor from sleeping when a message is received. --&gt;
+&lt;uses-permission android:name=&quot;android.permission.WAKE_LOCK&quot; /&gt;</pre>
+
+ <li>Add the following broadcast receiver:</li>
+
+<pre class="prettyprint pretty-xml">&lt;receiver android:name=&quot;com.google.android.gcm.GCMBroadcastReceiver&quot; android:permission=&quot;com.google.android.c2dm.permission.SEND&quot; &gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name=&quot;com.google.android.c2dm.intent.RECEIVE&quot; /&gt;
+ &lt;action android:name=&quot;com.google.android.c2dm.intent.REGISTRATION&quot; /&gt;
+ &lt;category android:name=&quot;my_app_package&quot; /&gt;
+ &lt;/intent-filter&gt;
+&lt;/receiver&gt;</pre>
+<p> This broadcast receiver is responsible for handling the 2 intents that can be sent by GCM (<code>com.google.android.c2dm.intent.RECEIVE</code> and <code>com.google.android.c2dm.intent.REGISTRATION</code>) and should be defined in the manifest (rather than programmatically) so that these intents can be received even if the application is not running. By setting the <code>com.google.android.c2dm.permission.SEND</code> permission, you are ensuring that only intents sent by the GCM system framework are sent to the receiver (a regular application cannot issue intents with that permission).</p>
+<p> Notice that <code>android:name</code> in the category tag must be replaced by your application's package name (and the category tag is not required for applications targeted to minSdkVersion 16 and higher).<br>
+ </p>
+
+ <li>Add the following intent service:</li>
+
+
+ <pre class="prettyprint pretty-xml">&lt;service android:name=&quot;.GCMIntentService&quot; /&gt;</pre>
+
+</ol>
+<p>This intent service will be called by the <code>GCMBroadcastReceiver</code> (which is provided by the GCM library), as shown in the next step. It must be a subclass of <code>com.google.android.gcm.GCMBaseIntentService</code>, must contain a public constructor, and should be named <code>my_app_package.GCMIntentService</code> (unless you use a subclass of <code>GCMBroadcastReceiver</code> that overrides the method used to name the service).</p>
+
+<p>The intent service must also define its sender ID(s). It does this as follows:</p>
+<ul>
+ <li>If the value is static, the service's default constructor should call <code>super(senderIds)</code>.</li>
+ <li>If the value is dynamic, the service should override the <code>getSenderIds()</code> method.</li>
+</ul>
+
+
+<h4>Step 3: Write the my_app_package.GCMIntentService class</h4>
+
+<p>Next write the <code>my_app_package.GCMIntentService</code> class, overriding the following callback methods (which are called by <code>GCMBroadcastReceiver</code>):<br>
+</p>
+<ul>
+ <li><code>onRegistered(Context context, String regId)</code>: Called after a registration intent is received, passes the registration ID assigned by GCM to that device/application pair as parameter. Typically, you should send the <code>regid</code> to your server so it can use it to send messages to this device.</li>
+ <li><code>onUnregistered(Context context, String regId)</code>: Called after the device has been unregistered from GCM. Typically, you should send the <code>regid</code> to the server so it unregisters the device.</li>
+ <li><code>onMessage(Context context, Intent intent)</code>: Called when your server sends a message to GCM, and GCM delivers it to the device. If the message has a payload, its contents are available as extras in the intent.</li>
+ <li><code>onError(Context context, String errorId)</code>: Called when the device tries to register or unregister, but GCM returned an error. Typically, there is nothing to be done other than evaluating the error (returned by errorId) and trying to fix the problem.</li>
+ <li> <code>onRecoverableError(Context context, String errorId)</code>: Called when the device tries to register or unregister, but the GCM servers are unavailable. The GCM library will retry the operation using exponential backup, unless this method is overridden and returns false. This method is optional and should be overridden only if you want to display the message to the user or cancel the retry attempts.
+ </li>
+</ul>
+
+<p class="note"><strong>Note:</strong> The methods above run in the intent service's thread and hence are free to make network calls without the risk of blocking the UI thread.</p>
+
+<h4> Step 4: Write your application's main activity</h4>
+Add the following import statement in your application's main activity:
+<pre class="prettyprint pretty-java">import com.google.android.gcm.GCMRegistrar;</pre>
+<p> In the <code>onCreate()</code> method, add the following code:</p>
+<pre class="prettyprint pretty-java">GCMRegistrar.checkDevice(this);
+GCMRegistrar.checkManifest(this);
+final String regId = GCMRegistrar.getRegistrationId(this);
+if (regId.equals("")) {
+ GCMRegistrar.register(this, SENDER_ID);
+} else {
+ Log.v(TAG, "Already registered");
+}</pre>
+<p>The <code>checkDevice()</code> method verifies that the device supports GCM and throws an exception if it does not (for instance, if it is an emulator that does not contain the Google APIs). Similarly, the <code>checkManifest()</code> method verifies that the application manifest contains meets all the requirements described in <a href="#android-app">Writing the Android Application</a> (this method is only necessary when you are developing the application; once the application is ready to be published, you can remove it).</p>
+
+<p>Once the sanity checks are done, the device calls <code>GCMRegsistrar.register()</code> to register the device, passing the <code>SENDER_ID</code> you got when you signed up for GCM. But since the <code>GCMRegistrar</code> singleton keeps track of the registration ID upon the arrival of registration intents, you can call <code>GCMRegistrar.getRegistrationId()</code> first to check if the device is already registered.</p>
+<p class="note"><strong>Note:</strong> It is possible that the device was successfully registered to GCM but failed to send the registration ID to your server, in which case you should retry. See <a href="adv.html#reg-state">Advanced Topics</a> for more details on how to handle this scenario.</p>
+
+<h2 id="server-app">Writing the Server-side Application</h2>
+
+<p>To write the server-side application:</p>
+<ol>
+ <li> Copy the <code>gcm-server.jar</code> file from the SDK's <code>gcm-server/dist</code> directory to your server classpath.</li>
+ <li>Create a servlet (or other server-side mechanism) that can be used by the Android application to send the registration ID received by GCM . The application might also need to send other information&mdash;such as the user's email address or username&mdash;so that the server can associate the registration ID with the user owning the device.</li>
+ <li>Similarly, create a servlet used to unregister registration IDs.<br>
+ </li>
+<li>When the server needs to send a message to the registration ID, it can use the <code>com.google.android.gcm.server.Sender</code> helper class from the GCM library. For example:</li>
+</ol>
+
+<pre class="prettyprint pretty-java">import com.google.android.gcm.server.*;
+
+Sender sender = new Sender(myApiKey);
+Message message = new Message.Builder().build();
+MulticastResult result = sender.send(message, devices, 5);</pre>
+
+<p> The snippet above does the following:
+<ul>
+<li>Creates a <code>Sender</code> object using your project's API key.</li>
+<li>Creates a message using a given registration ID (the message builder also has methods to set all message parameters such as the collapse key and payload data).</li>
+<li>Sends the message with a maximum of 5 retry attempts (in case the GCM servers are unavailable), and stores the response on result. </li>
+</ul>
+<p>It's now necessary to parse the result and take the proper action in the following cases:</p>
+<ul>
+ <li>If the message was created but the result returned a canonical registration ID, it's necessary to replace the current registration ID with the canonical one.</li>
+ <li>If the returned error is <code>NotRegistered</code>, it's necessary to remove that registration ID, because the application was uninstalled from the device.</li>
+</ul>
+<p> Here's a code snippet that handles these 2 conditions:</p>
+<pre class="prettyprint pretty-java">
+if (result.getMessageId() != null) {
+ String canonicalRegId = result.getCanonicalRegistrationId();
+ if (canonicalRegId != null) {
+ // same device has more than on registration ID: update database
+ }
+} else {
+ String error = result.getErrorCodeName();
+ if (error.equals(Constants.ERROR_NOT_REGISTERED)) {
+ // application has been removed from device - unregister database
+ }
+}</pre>
diff --git a/docs/html/google/gcm/index.jd b/docs/html/google/gcm/index.jd
index 320bd5b..f9c3ed3 100644
--- a/docs/html/google/gcm/index.jd
+++ b/docs/html/google/gcm/index.jd
@@ -13,37 +13,43 @@ header.hide=1
<h1 itemprop="name" style="margin-bottom:0;">Google Cloud Messaging for Android</h1>
<p itemprop="description">
Google Cloud Messaging for Android (GCM) is a service that allows you to send data
-from your server to your users' Android-powered device. This could be a lightweight
-message telling your app there is new data to be fetched from the
-server (for instance, a movie uploaded by a friend), or it could be a message containing
-up to 4kb of payload data (so apps like instant messaging can consume the message directly).
+from your server to your users' Android-powered device, and also to receive messages from devices on the same connection. The GCM service handles all aspects of queueing of messages and delivery to the target Android application running on the target device. GCM is completely free no matter how big your messaging needs are, and there are no quotas.
</p>
+
</div>
</div>
-<p class="clear:both">
-The GCM service handles all aspects of queueing of messages and delivery to the target Android
-application running on the target device.
-GCM is completely free no matter how big your messaging needs are, and there are no quotas.</p>
-
-<p>To learn more about GCM, you can join the <a
-href="https://groups.google.com/forum/?fromgroups#!forum/android-gcm">android-gcm group</a>
-and read the following documents:</p>
-
-<dl>
- <dt><strong><a href="{@docRoot}google/gcm/gs.html">Getting Started</a></strong></dt>
- <dd>Read this document to learn the basic steps involved in developing Android applications based on GCM.</dd>
- <dt><strong><a href="{@docRoot}google/gcm/gcm.html">Architectural Overview</a></strong></dt>
- <dd>Read this document for a description of the underlying concepts and architecture in GCM.</dd>
- <dt><strong><a href="{@docRoot}google/gcm/demo.html">Demo App Tutorial</a></strong></dt>
- <dd>Read this document to walk through setting up and running the GCM demo app.</dd>
- <dt><strong><a href="{@docRoot}google/gcm/adv.html">Advanced Topics</a></strong></dt>
- <dd>Read this document to get a more in-depth understanding of key GCM features.</dd>
- <dt><a href="{@docRoot}google/gcm/c2dm.html"><strong>Migration</strong></a></dt>
- <dd>Read this document if you are a C2DM developer moving to GCM.</dd>
- <dt><a href="{@docRoot}reference/gcm-packages.html"><strong>API Reference</strong></a></dt>
- <dd>Helper libraries for client and server development.</dd>
-</dl>
+<div class="landing-docs">
+ <div class="col-6 normal-links">
+ <h3 style="clear:left">Key Developer Features</h3>
+ <h4>Send data from your server to users' Android-powered devices</h4>
+ <p>This could be a lightweight
+message telling your app there is new data to be fetched from the
+server (for instance, a movie uploaded by a friend), or it could be a message containing
+up to 4kb of payload data (so apps like instant messaging can consume the message directly). <a href="{@docRoot}google/gcm/gcm.html">GCM Architectural Overview.</a></p>
+
+ <h4>Send "send-to-sync" messages</h4>
+ <p>A send-to-sync (collapsible) message is often a "tickle" that tells a mobile application to sync data from the server. For example, suppose you have an email application. When a user receives new email on the server, the server pings the mobile application with a "New mail" message. This tells the application to sync to the server to pick up the new email.
+ <a href="{@docRoot}google/gcm/adv.html#s2s">Send-to-sync messages</a>.</p>
+ </a>
+
+ <h4>Send messages with payload</h4>
+ <p>Unlike a send-to-sync message, every "message with payload" (non-collapsible message) is delivered. The payload the message contains can be up to 4kb.
+ <a href="{@docRoot}google/gcm/adv.html#payload">Messages with payload</a>.</p>
+ </div>
+
+
+ <div class="col-6 normal-links">
+ <h3 style="clear:left">New Features</h3>
+ <h4>Faster, easier GCM setup</h4>
+ <p>Streamlined registration makes it simple and fast to add GCM support to your Android app. <a href="{@docRoot}google/gcm/gs.html">Learn more &raquo;</a></p>
+ <h4>Upstream messaging over XMPP</h4>
+ <p>GCM's Cloud Connection Service (CCS) lets you communicate with Android devices over a persistent XMPP connection. The primary advantages of CCS are speed, and the ability to receive upstream messages (that is, messages from a device to the cloud). You can use the service in tandem with existing GCM APIs. Use <a href="https://services.google.com/fb/forms/gcm/">this form</a> to sign up for CCS. <a href="{@docRoot}google/gcm/ccs.html">Learn more &raquo;</a></p>
+
+ <h4>Seamless multi-device messaging</h4>
+ <p>Maps a single user to a notification key, which you can then use to send a single message to multiple devices owned by the user. Use <a href="https://services.google.com/fb/forms/gcm/">this form</a> to sign up for User Notifications. <a href="{@docRoot}google/gcm/notifications.html">Learn more &raquo;</a></p>
+ </div>
+</div>
diff --git a/docs/html/google/gcm/notifications.jd b/docs/html/google/gcm/notifications.jd
new file mode 100644
index 0000000..6a4b34a
--- /dev/null
+++ b/docs/html/google/gcm/notifications.jd
@@ -0,0 +1,171 @@
+page.title=User Notifications
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+
+<h2>Quickview</h2>
+
+<ul>
+<li>Learn how to send a single message to multiple devices owned by a single user.</li>
+</ul>
+
+
+<h2>In this document</h2>
+
+<ol class="toc">
+ <li><a href="#what">What are User Notifications?</a> </li>
+ <li><a href="#examples">Examples</a>
+ <ol>
+ <li><a href="#create">Generate a notification key</a></li>
+ <li><a href="#add">Add registration IDs</a></li>
+ <li><a href="#remove">Remove registration IDs</a></li>
+ <li><a href="#upstream">Send upstream messages</a></li>
+ <li><a href="#response">Response formats</a></li>
+ </ol>
+ </li>
+</ol>
+
+<h2>See Also</h2>
+
+<ol class="toc">
+<li><a href="{@docRoot}google/play-services/gcm/gs.html">Getting Started</a></li>
+<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
+</ol>
+
+</div>
+</div>
+
+<p class="note"><strong>Note:</strong> To try out this feature, sign up using <a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
+
+<p>The upstream messaging (device-to-cloud) feature described in this document is part of the Google Play services platform. Upstream messaging is available through the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> APIs. To use upstream messaging and the new streamlined registration process, you must <a href="{@docRoot}google/play-services/setup.html">set up</a> the Google Play services SDK.</p>
+
+<h2 id="what">What are User Notifications?</h2>
+
+<p>Third party servers can send a single message to multiple instance of an app running on devices owned by a single user. This feature is called <em>user notifications</em>. User notifications make it possible for every app instance that a user owns to reflect the latest messaging state. For example:</p>
+
+ <ul>
+ <li>If a message has been handled on one device, the GCM message on the other devices are dismissed. For example, if a user has handled a calendar notification on one device, the notification will go away on the user's other devices.</li>
+ <li>If a message has not been delivered yet to a device and but it has been handled, the GCM server removes it from the unsent queue for the other devices.</li>
+ <li>Likewise, a device can send messages to the {@code notification_key}, which is the token that GCM uses to fan out notifications to all devices whose registration IDs are associated with the key.</li>
+</ul>
+
+<p>The way this works is that during registration, the 3rd-party server requests a {@code notification_key}. The {@code notification_key} maps a particular user to all of the user's associated registration IDs (a regID represents a particular Android application running on a particular device). Then instead of sending one message to one regID at a time, the 3rd-party server can send a message to to the {@code notification_key}, which then sends the message to all of the user's regIDs.</p>
+
+<p>You can use this feature with either the new <a href="ccs.html">GCM Cloud Connection Server</a> (CCS), or the older <a href="gcm.html">GCM HTTP server</a>.</p>
+
+
+<h3 id="examples">Examples</h3>
+
+<p>The examples in this section show you how to perform generate/add/remove operations, and how to send upstream messages. For generate/add/remove operations, the message body is JSON.</p>
+
+<h4 id="request">Request format</h4>
+<p>To send a message, the application server issues a POST request to <code>https://android.googleapis.com/gcm/notification</code>.</p>
+
+<p>Here is the HTTP request header you should use for all create/add/remove operations:</p>
+
+<pre>content-type: "application/json"
+Header : "project_id": &lt;projectID&gt;
+Header: "Authorization", "key=API_KEY"
+</pre>
+
+<h4 id="create">Generate a notification key</h4>
+
+<p>This example shows how to create a new <code>notification_key</code> for a <code>notification_key_name</code> called <code>appUser-Chris</code>. 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. Note that <code>notification_key_name</code> and <code>notification_key</code> are unique to a group of registration IDs. It is also important that <code>notification_key_name</code> 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.</p>
+
+
+<p>A create operation returns a token (<code>notification_key</code>). Third parties must save this token (as well as its mapping to the <code>notification_key_name</code>) to use in subsequent operations:</p>
+
+<pre>request:
+{
+ &quot;operation&quot;: &quot;create&quot;,
+ &quot;notification_key_name&quot;: &quot;appUser-Chris&quot;,
+ &quot;registration_ids&quot;: [&quot;4&quot;, &quot;8&quot;, &quot;15&quot;, &quot;16&quot;, &quot;23&quot;, &quot;42&quot;]
+}</pre>
+
+<h4 id="add">Add registration IDs</h4>
+
+<p>This example shows how to add registration IDs for a given notification key. The maximum number of members allowed for a {@code notification_key} is 10.</p>
+
+<p>Note that the <code>notification_key_name</code> is not strictly required for adding/removing regIDs. But including it protects you against accidentally using the incorrect <code>notification_key</code>.</p>
+
+<pre>request:
+{
+ &quot;operation&quot;: &quot;add&quot;,
+ &quot;notification_key_name&quot;: &quot;appUser-Chris&quot;,
+ &quot;notification_key&quot;: &quot;aUniqueKey&quot;
+ &quot;registration_ids&quot;: [&quot;4&quot;, &quot;8&quot;, &quot;15&quot;, &quot;16&quot;, &quot;23&quot;, &quot;42&quot;]
+}</pre>
+
+<h4 id="remove">Remove registration IDs</h4>
+
+<p>This example shows how to remove registration IDs for a given notification key:</p>
+<pre>request:
+{
+ &quot;operation&quot;: &quot;remove&quot;,
+ &quot;notification_key_name&quot;: &quot;appUser-Chris&quot;,
+ &quot;notification_key&quot;: &quot;aUniqueKey&quot;
+ &quot;registration_ids&quot;: [&quot;4&quot;, &quot;8&quot;, &quot;15&quot;, &quot;16&quot;, &quot;23&quot;, &quot;42&quot;]
+}</pre>
+
+<h4 id="upstream">Send upstream messages</h4>
+
+<p>To send an upstream (device-to-cloud) message, you must use the <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">GoogleCloudMessaging</a> API. Specifying a {@code notification_key} as the target for an upstream message allows a user on one device to send a message to other devices in the notification group&mdash;for example, to dismiss a notification. Here is an example that shows targeting a {@code notification_key}:</p>
+
+<pre>GoogleCloudMessaging gcm = GoogleCloudMessaging.get(context);
+String to = NOTIFICATION_KEY;
+AtomicInteger msgId = new AtomicInteger();
+String id = Integer.toString(msgId.incrementAndGet());
+Bundle data = new Bundle();
+data.putString("hello", "world");
+
+gcm.send(to, id, data);
+</pre>
+
+<p>This call generates the necessary XMPP stanza for sending the message. The Bundle data consists of a key-value pair.</p>
+
+<p>For a complete example, see <a href="gs.html#gs_example">Getting Started</a>.
+
+<h4 id="response">Response formats</h4>
+
+<p>This section shows examples of the responses that can be returned for notification key operations.</p>
+
+<h5>Response for create/add/remove operations</h5>
+
+<p>When you make a request to create a {@code notification_key} or to add/remove its the wayregIDs, a successful response always returns the <code>notification_key</code>. This is the {@code notification_key} you will use for sending messages:</p>
+
+<pre>HTTP status: 200
+{
+ &quot;notification_key&quot;: &quot;aUniqueKey&quot;, // to be used for sending
+}</pre>
+
+
+<h5>Response for send operations</h5>
+
+<p>For a send operation that has a {@code notification_key} as its target, the possible responses are success, partial success, and failure.</p>
+
+<p>Here is an example of "success"&mdash;the {@code notification_key} has 2 regIDs associated with it, and the message was successfully sent to both of them:</p>
+
+<pre>{
+ "success": 2,
+ "failure": 0
+}</pre>
+
+<p>Here is an example of "partial success"&mdash;the {@code notification_key} has 3 regIDs associated with it. The message was successfully send to 1 of the regIDs, but not to the other 2. The response message lists the regIDs that failed to receive the message:</p>
+
+<pre>{
+ "success":1,
+ "failure":2,
+ "failed_registration_ids":[
+ "regId1",
+ "regId2"
+ ]
+}</pre>
+
+<p>In the case of failure, the response has HTTP code 503 and no JSON. When a message fails to be delivered to one or more of the regIDs associated with a {@code notification_key}, the 3rd-party server should retry.</p>
+
+
+
+
+
+
diff --git a/docs/html/google/google_toc.cs b/docs/html/google/google_toc.cs
index fa9b9c9..a703832 100644
--- a/docs/html/google/google_toc.cs
+++ b/docs/html/google/google_toc.cs
@@ -27,31 +27,18 @@
<li><a href="<?cs var:toroot?>google/play-services/setup.html">
<span class="en">Setup</span></a>
</li>
- <li><a href="<?cs var:toroot?>google/play-services/games.html">
- <span class="en">Games</span></a>
+
+ <li><a href="<?cs var:toroot?>google/play-services/auth.html">
+ <span class="en">Authorization</span></a>
</li>
+
<li><a href="<?cs var:toroot?>google/play-services/plus.html">
<span class="en">Google+</span></a>
</li>
+
<li><a href="<?cs var:toroot?>google/play-services/maps.html">
<span class="en">Google Maps</span></a>
</li>
- <li><a href="<?cs var:toroot?>google/play-services/location.html">
- <span class="en">Location</span></a>
- </li>
- <li><a href="<?cs var:toroot?>google/play-services/gcm.html">
- <span class="en">GCM</span></a>
- </li>
- <li><a href="<?cs var:toroot?>google/play-services/auth.html">
- <span class="en">Authorization</span></a>
- </li>
- <li id="gms-tree-list" class="nav-section">
- <div class="nav-section-header">
- <a href="<?cs var:toroot ?>reference/gms-packages.html">
- <span class="en">Reference</span>
- </a>
- <div>
- </li>
</ul>
</li>
@@ -151,9 +138,19 @@
<li><a href="<?cs var:toroot?>google/gcm/gcm.html">
<span class="en">Architectural Overview</span></a>
</li>
+
+ <li><a href="<?cs var:toroot?>google/gcm/ccs.html">
+ <span class="en">Cloud Connection Server</span></a>
+ </li>
+ <li><a href="<?cs var:toroot?>google/gcm/notifications.html">
+ <span class="en">User Notifications</span></a>
+ </li>
<li><a href="<?cs var:toroot?>google/gcm/demo.html">
<span class="en">Demo App Tutorial</span></a>
</li>
+ <li><a href="<?cs var:toroot?>google/gcm/helper.html">
+ <span class="en">Using the Helper Libraries</span></a>
+ </li>
<li><a href="<?cs var:toroot?>google/gcm/adv.html">
<span class="en">Advanced Topics</span></a>
</li>