summaryrefslogtreecommitdiffstats
path: root/docs/html/google
diff options
context:
space:
mode:
authorKatie McCormick <kmccormick@google.com>2014-05-28 17:31:23 -0700
committerKatie McCormick <kmccormick@google.com>2014-06-23 22:40:16 +0000
commite89c6ebeceb2a04d8ee05e73e15a899b686f811a (patch)
treef62a3f7c27234c985fa53c2c02650f7dd0c98545 /docs/html/google
parent7cfd2e03c474cccb413522b663cf08b9bbbc0cca (diff)
downloadframeworks_base-e89c6ebeceb2a04d8ee05e73e15a899b686f811a.zip
frameworks_base-e89c6ebeceb2a04d8ee05e73e15a899b686f811a.tar.gz
frameworks_base-e89c6ebeceb2a04d8ee05e73e15a899b686f811a.tar.bz2
Doc update: GCM changes for I/O.
Fixes for: b/15348323 b/15349955 b/15330953 Change-Id: Ie256a76ea83cf16256cded858531dd78b8da0558
Diffstat (limited to 'docs/html/google')
-rw-r--r--docs/html/google/gcm/ccs.jd149
-rw-r--r--docs/html/google/gcm/client.jd3
-rw-r--r--docs/html/google/gcm/gcm.jd2
-rw-r--r--docs/html/google/gcm/index.jd39
-rw-r--r--docs/html/google/gcm/notifications.jd129
-rw-r--r--docs/html/google/gcm/server.jd3
-rw-r--r--docs/html/google/gcs/gcs-signup.jd10
-rw-r--r--docs/html/google/gcs/index.jd30
-rw-r--r--docs/html/google/index.jd10
9 files changed, 300 insertions, 75 deletions
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index 03addfd..4389e3d 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -19,7 +19,11 @@ page.title=GCM Cloud Connection Server (XMPP)
<li><a href="#response">Response format</a></li>
</ol>
</li>
- <li><a href="#upstream">Upstream Messages</a> </li>
+ <li><a href="#upstream">Upstream Messages</a>
+ <ol>
+ <li><a href="#receipts">Receive return receipts</a></li>
+ </ol>
+ </li>
<li><a href="#flow">Flow Control</a> </li>
<li><a href="#implement">Implementing an XMPP-based App Server</a>
<ol class="toc">
@@ -43,9 +47,6 @@ target="_android">CCS and User Notifications Signup Form</a></li>
</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) is an XMPP endpoint that provides a
persistent, asynchronous, bidirectional connection to Google servers. The
connection can be used to send and receive messages between your server and
@@ -149,8 +150,8 @@ exceptions:</p>
<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 app servers to CCS.
-Therefore, it's important that this {@code message_id} not only be unique, but
-always present.</li>
+Therefore, it's important that this {@code message_id} not only be unique (per
+sender ID), but always present.</li>
</ul>
<p>In addition to regular GCM messages, control messages are sent, indicated by
@@ -188,7 +189,8 @@ parameters and which connection server(s) supports them.</p>
&quot;hello&quot;:&quot;world&quot;,
}
&quot;time_to_live&quot;:&quot;600&quot;,
- &quot;delay_while_idle&quot;: true/false
+ &quot;delay_while_idle&quot;: true/false,
+ &quot;delivery_receipt_requested&quot;: true/false
}
&lt;/gcm&gt;
&lt;/message&gt;
@@ -227,42 +229,48 @@ message is &quot;nack&quot;. A NACK message contains:</p>
<p>Below are some examples.</p>
<p>Bad registration:</p>
+
<pre>&lt;message&gt;
- &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
{
- &quot;error&quot;:&quot;BAD_REGISTRATION&quot;, // error code
+ &quot;message_type&quot;:&quot;nack&quot;,
&quot;message_id&quot;:&quot;msgId1&quot;,
- &quot;from&quot;:&quot;PA91bHFOtaQGSwupt5l1og&quot;,
- &quot;message_type&quot;:&quot;nack&quot;
+ &quot;from&quot;:&quot;SomeInvalidRegistrationId&quot;,
+ &quot;error&quot;:&quot;BAD_REGISTRATION&quot;,
+ &quot;error_description&quot;:&quot;Invalid token on 'to' field: SomeInvalidRegistrationId&quot;
}
- &lt;/data:gcm&gt;
+ &lt;/gcm&gt;
&lt;/message&gt;</pre>
-<p>Invalid "time to live":</p>
+<p>Invalid JSON:</p>
<pre>&lt;message&gt;
- &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
- {
- &quot;error&quot;:&quot;InvalidJson : INVALID_TTL : Invalid value (-1) for \&quot;time_to_live\&quot;: must be between 0 and \&quot;2419200\&quot;\n&quot;,
- &quot;message_id&quot;:&quot;msgId1&quot;,
- &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
- &quot;message_type&quot;:&quot;nack&quot;
- }
- &lt;/data:gcm&gt;
-&lt;/message&gt;</pre>
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;message_type&quot;:&quot;nack&quot;,
+ &quot;message_id&quot;:&quot;msgId1&quot;,
+ &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
+ &quot;error&quot;:&quot;INVALID_JSON&quot;,
+ &quot;error_description&quot;:&quot;InvalidJson: JSON_TYPE_ERROR : Field \&quot;time_to_live\&quot; must be a JSON java.lang.Number: abc&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;
+</pre>
-<p>JSON type error:</p>
+<p>Quota exceeded:</p>
<pre>&lt;message&gt;
- &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
- {
- &quot;error&quot;:&quot;InvalidJson : JSON_TYPE_ERROR : Field \&quot;delay_while_idle\&quot; must be a JSON java.lang.Boolean: not-boolean-user-supplied-value\n&quot;,
- &quot;message_id&quot;:&quot;msgId1&quot;,
- &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
- &quot;message_type&quot;:&quot;nack&quot;
- }
- &lt;/data:gcm&gt;
-&lt;/message&gt;</pre>
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+ &quot;message_type&quot;:&quot;nack&quot;,
+ &quot;message_id&quot;:&quot;msgId1&quot;,
+ &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
+ &quot;error&quot;:&quot;QUOTA_EXCEEDED&quot;,
+ &quot;error_description&quot;:&quot;Short-term downstream quota exceeded for this registration id&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;
+</pre>
<p>The following table lists NACK error codes. Unless otherwise
@@ -300,7 +308,7 @@ message should be immediately retried over another connection.</td>
</tr>
<tr>
<td>{@code INVALID_JSON}</td>
-<td>The JSON message payload was not valid.</td>
+<td>The JSON message payload is not valid.</td>
</tr>
<tr>
<td>{@code QUOTA_EXCEEDED}</td>
@@ -309,10 +317,10 @@ sender/device pair) is too high. If you want to retry the message, try using a s
rate.</td>
</tr>
<tr>
-<td>{@code SERVICE_UNAVAILABLE}</td>
-<td>CCS is not currently able to process the message. The
-message should be retried over the same connection using exponential backoff
-with an initial delay of 1 second.</td>
+ <td>{@code SERVICE_UNAVAILABLE}</td>
+ <td>CCS is not currently able to process the message. The
+ message should be retried over the same connection using exponential backoff
+ with an initial delay of 1 second.</td>
</tr>
</table>
@@ -382,8 +390,8 @@ Bundle data = new Bundle();
// Bundle data consists of a key-value pair
data.putString("hello", "world");
// "time to live" parameter
-// This is optional. It specifies a value in seconds up to 4 weeks.
-int ttl = [0 seconds, 4 weeks]
+// This is optional. It specifies a value in seconds up to 24 hours.
+int ttl = [0 seconds, 24 hours]
gcm.send(GCM_SENDER_ID + "&#64;gcm.googleapis.com", id, ttl, data);
</pre>
@@ -419,6 +427,69 @@ response to the above message:</p>
&lt;/gcm&gt;
&lt;/message&gt;</pre>
+<h3 id="receipts">Receive return receipts</h3>
+
+<p>You can use upstream messaging to get receipt notifications, confirming
+that a given message was sent to a device. Your 3rd-party app server receives the receipt
+notification from CCS once the message has been sent to the device.</p>
+
+<p>To enable this feature, the message your 3rd-party app server sends to CCS must include
+a field called <code>&quot;delivery_receipt_requested&quot;</code>. When this field is set to
+<code>true</code>, CCS sends a return receipt. Here is an XMPP stanza containing a JSON
+message with <code>&quot;delivery_receipt_requested&quot;</code> set to <code>true</code>:</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;message_id&quot;:&quot;m-1366082849205&quot;
+ &quot;data&quot;:
+ {
+ &quot;hello&quot;:&quot;world&quot;,
+ }
+ &quot;time_to_live&quot;:&quot;600&quot;,
+ &quot;delay_while_idle&quot;: true,
+ <strong>&quot;delivery_receipt_requested&quot;: true</strong>
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;
+</pre>
+
+<p>Here is an example of a receipt notification message that CCS sends back to your 3rd-party
+app server:</p>
+
+</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;:
+ {
+ &#x201c;message_status&quot;:&quot;MESSAGE_SENT_TO_DEVICE&quot;,
+ &#x201c;original_message_id&#x201d;:&#x201d;m-1366082849205&#x201d;
+ &#x201c;device_registration_id&#x201d;: &#x201c;REGISTRATION_ID&#x201d;
+ },
+ &quot;message_id&quot;:&quot;dr2:m-1366082849205&quot;,
+ &quot;message_type&quot;:&quot;receipt&quot;,
+ &quot;from&quot;:&quot;gcm.googleapis.com&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;</pre>
+
+<p>Note the following:</p>
+
+<ul>
+ <li>The {@code &quot;message_type&quot;} is set to {@code &quot;receipt&quot;}.
+ <li>The {@code &quot;message_status&quot;} is set to {@code &quot;MESSAGE_SENT_TO_DEVICE&quot;},
+ indicating that the message was delivered. Notice that in this case,
+{@code &quot;message_status&quot;} is not a field but rather part of the data payload.</li>
+ <li>The receipt message ID consists of the original message ID, but with a
+<code>dr:</code> prefix. Your 3rd-party app server must send an ACK back with this ID,
+which in this example is {@code dr2:m-1366082849205}.</li>
+ <li>The original message ID and status are inside the
+{@code &quot;data&quot;} field.</li>
+</ul>
+
<h2 id="flow">Flow Control</h2>
<p>Every message sent to CCS receives either an ACK or a NACK response. Messages
diff --git a/docs/html/google/gcm/client.jd b/docs/html/google/gcm/client.jd
index 42cebfc..ec7e748 100644
--- a/docs/html/google/gcm/client.jd
+++ b/docs/html/google/gcm/client.jd
@@ -246,7 +246,8 @@ private boolean checkPlayServices() {
<h3 id="sample-register">Register for GCM</h3>
<p>An Android application needs to register with GCM servers before it can receive
messages. When an app registers, it receives a registration ID, which it can then
-store for future use. In the following snippet the {@code onCreate()} method in the sample app's
+store for future use (note that registration IDs must be kept secret). In the
+following snippet the {@code onCreate()} method in the sample app's
main activity checks to see if the app is already registered with GCM and with
the server:</p>
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 88bf659..19151b9 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -123,7 +123,7 @@ it to receive messages. Once the Android application has the registration ID, it
it to the 3rd-party application server, which uses it to identify each device
that has registered to receive messages for a given Android application. In other words,
a registration ID is tied to a particular Android application running on a particular
-device.
+device. Note that registration IDs must be kept secret.
<br/>
<br/>
<strong>Note:</strong> If you use
diff --git a/docs/html/google/gcm/index.jd b/docs/html/google/gcm/index.jd
index 8f325b8..1f05a71 100644
--- a/docs/html/google/gcm/index.jd
+++ b/docs/html/google/gcm/index.jd
@@ -14,7 +14,10 @@ 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, 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.
+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>
@@ -27,31 +30,39 @@ from your server to your users' Android-powered device, and also to receive mess
<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>
+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>
+ <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">Learn more &raquo;</a></p>
<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>
+ <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">Learn more &raquo;</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>
+
+
+ <h4>Return Receipts</h4>
+ <p>You can use upstream messaging to get receipt notifications, confirming that a given
+ message was sent to a device. Your 3rd-party app server receives the receipt notification
+ from CCS once the message has been sent to the device.
+ <a href="{@docRoot}google/gcm/ccs.html#receipts">Learn more &raquo;</a></p>
+
<h4>Get Started</h4>
- <p>Get started using the new features with a tutorial that walks you through creating a GCM app. <a href="{@docRoot}google/gcm/gs.html">Learn more &raquo;</a></p>
+ <p>Get started with a tutorial that walks you through creating a GCM app.
+ <a href="{@docRoot}google/gcm/gs.html">Learn more &raquo;</a></p>
</div>
</div>
diff --git a/docs/html/google/gcm/notifications.jd b/docs/html/google/gcm/notifications.jd
index 43a7368..2815f3d 100644
--- a/docs/html/google/gcm/notifications.jd
+++ b/docs/html/google/gcm/notifications.jd
@@ -14,8 +14,8 @@ page.title=User Notifications
<h2>In this document</h2>
<ol class="toc">
- <li><a href="#request">Request Format</a></li>
- <li><a href="#create">Generate a Notification Key</a></li>
+ <li><a href="#gen-server">Generate a Notification Key on the Server</a></li>
+ <li><a href="#gen-client">Generate a Notification Key on the Client</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>
@@ -31,15 +31,11 @@ page.title=User Notifications
<ol class="toc">
<li><a href="{@docRoot}google/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>With user notifications, 3rd-party app 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
@@ -76,27 +72,23 @@ and then reconciling it with the corresponding notification.
<p>You can use this feature with either the <a href="ccs.html">XMPP</a> (CCS) or
<a href="http.html">HTTP</a> connection server.</p>
+<p>You can generate notification keys in two different ways: on the server, and on
+the client, if the user has a Google account. All of the associated registration IDs
+can be mapped to a single user.</p>
<p>The examples below 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>
-<h2 id="request">Request Format</h2>
-<p>To send a message, the application server issues a POST request to
-<code>https://android.googleapis.com/gcm/notification</code>.</p>
+<h2 id="gen-server">Generate a Notification Key on the Server</h2>
-<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>
-
-<h2 id="create">Generate a Notification Key</h2>
+<p>To generate a notification key on the server, you create a new
+create a new <code>notification_key</code> and map it to a
+<code>notification_key_name</code>.</p>
<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
+The {@code notification_key_name} is a name or identifier (it 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
@@ -116,10 +108,109 @@ to use in subsequent operations:</p>
&quot;registration_ids&quot;: [&quot;4&quot;, &quot;8&quot;, &quot;15&quot;, &quot;16&quot;, &quot;23&quot;, &quot;42&quot;]
}</pre>
+<h3 id="request-server">Request format</h3>
+
+<p>To send a message in cases where your notification key is generated on the server,
+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 server side create/add/remove operations:</p>
+
+<pre>content-type: "application/json"
+Header : "project_id": &lt;projectID&gt;
+Header: "Authorization", "key=API_KEY"
+</pre>
+
+
+<h2 id="gen-client">Generate a Notification Key on the Client</h2>
+
+<p>Generating a notification key on the client is useful for cases where a server is unavailable.
+To generate a notification key on the client, the device must have at least one
+Google account. Note that the process for generating a notification key on the client is significantly
+different from the server process described above.</p>
+
+<p>To generate a notification key on the client:</p>
+
+<ol>
+ <li>Open your project in the <a href="https://cloud.google.com/console">Google Developers Console</a>.</li>
+ <li>Click <strong>APIS &amp; AUTH &gt; Credentials</strong>.</li>
+ <li>Under OAuth, click <strong>Create new Client ID</strong>.</li>
+ <li>In the <strong>Create Client ID</strong> dialog, select <strong>Web Application</strong> as
+the application type, and click <strong>Create Client ID</strong>.</li>
+ <li>Copy the value from <strong>Client ID for web application &gt; Client ID</strong>.
+This client ID represents a Google account "scope" that you will use to generate an {@code id_token}.</li>
+</ol>
+
+<p>Once you've followed the above steps and gotten a client ID from Google Developers Console,
+ you're ready to add this feature to your app. First check the device for the presence of a Google
+account. For example:</p>
+
+<pre>// This snippet takes the simple approach of using the first returned Google account,
+// but you can pick any Google account on the device.
+public String getAccount() {
+ Account[] accounts = AccountManager.get(getActivity()).
+ getAccountsByType(&quot;com.google&quot;);
+ if (accounts.length == 0) {
+ return null;
+ }
+ return accounts[0].name;
+}</pre>
+
+<p>Next, get an authentication token ({@code id_token}) by using the <code><a href=
+"http://developer.android.com/reference/com/google/android/gms/auth/GoogleAuthUtil.html">GoogleAuthUtil</a></code>
+class. For example:</p>
+
+<pre>String accountName = getAccount();
+
+// Initialize the scope using the client ID you got from the Console.
+final String scope = &quot;audience:server:client_id:&quot;
+ + &quot;1262xxx48712-9qs6n32447mcj9dirtnkyrejt82saa52.apps.googleusercontent.com&quot;;
+String id_token = null;
+try {
+ id_token = GoogleAuthUtil.getToken(context, accountName, scope);
+} catch (Exception e) {
+ log(&quot;exception while getting id_token: &quot; + e);
+}
+...</pre>
+
+<p>Now use <code>id_token</code> to authenticate your request.
+This add operation returns a {@code notification_key}.
+Third parties must save this {@code notification_key} (as well as its mapping to the
+<code>notification_key_name</code>)
+to use in subsequent operations. Note that a client request only takes a single regID.
+The only operations supported on the client side are add/remove.</p>
+
+<pre>request:
+{
+ &quot;operation&quot;: &quot;add&quot;,
+ &quot;notification_key_name&quot;: &quot;appUser-Chris&quot;,
+ &quot;registration_ids&quot;: [&quot;4&quot;]
+ &quot;id_token&quot;: &quot;id_token&quot;
+}</pre>
+
+<h3 id="request-client">Request format</h3>
+
+<p>To send a message in cases where your notification key is generated on the client,
+the application server issues a POST request to
+<code>https://android.googleapis.com/gcm/googlenotification</code>.</p>
+
+<p>Here is the HTTP request header you should use for all add/remove operations. The
+client side doesn't support the create operation;
+the add operation has the effect of creating the notification key if it doesn't already
+exist:</p>
+
+<pre>content-type: "application/json"
+Header : "project_id": &lt;projectID&gt;
+</pre>
+
+<p>Note that the authentication token is passed in the JSON body as shown above, not the header.
+This is different from the server case.</p>
+
+
<h2 id="add">Add Registration IDs</h2>
<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>
+The maximum number of members allowed for a {@code notification_key} is 20.</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
diff --git a/docs/html/google/gcm/server.jd b/docs/html/google/gcm/server.jd
index ccd1267..e3a6b25 100644
--- a/docs/html/google/gcm/server.jd
+++ b/docs/html/google/gcm/server.jd
@@ -120,7 +120,8 @@ have an application server that meets the following criteria:</p>
<li>Able to store the API key and client registration IDs. The
API key is included in the header of POST requests that send
messages.</li>
- <li>Able to generate message IDs to uniquely identify each message it sends.</li>
+ <li>Able to generate message IDs to uniquely identify each message it sends. Message IDs
+should be unique per sender ID.</li>
</ul>
<h2 id="send-msg">Sending Messages</h2>
diff --git a/docs/html/google/gcs/gcs-signup.jd b/docs/html/google/gcs/gcs-signup.jd
new file mode 100644
index 0000000..7334cec
--- /dev/null
+++ b/docs/html/google/gcs/gcs-signup.jd
@@ -0,0 +1,10 @@
+page.title=Sign Up for Google Cloud Save
+
+@jd:body
+
+<p>Sign up to be a trial partner for Google Cloud Save.</p>
+
+
+<iframe src="https://docs.google.com/a/google.com/forms/d/1_V67YIXzLDLb-UzxOOpSjUDuJFfeYg3hEUT0oliK2ck/viewform?embedded=true" width="100%" height="930" frameborder="0" marginheight="0" marginwidth="0" id="signupform">Loading...</iframe>
+</body>
+</html>
diff --git a/docs/html/google/gcs/index.jd b/docs/html/google/gcs/index.jd
new file mode 100644
index 0000000..e5f4776
--- /dev/null
+++ b/docs/html/google/gcs/index.jd
@@ -0,0 +1,30 @@
+page.title=Google Cloud Save
+page.tags="gcs"
+header.hide=1
+@jd:body
+
+
+<div class="landing-banner">
+
+<div class="col-5" style="min-height:100px">
+ <img src="{@docRoot}images/google/gcs.png" />
+</div>
+<div class="col-7">
+
+ <h1 itemprop="name" style="margin-bottom:0;">Google Cloud Save</h1>
+ <p itemprop="description">
+ Google Cloud Save is a service that enables per-user data storage
+and sync in your apps with no backend programming required. Google Cloud Save
+stores its data
+in <a href="http://developers.google.com/datastore/">Google Cloud Datastore</a>,
+ a fully managed, schemaless database for storing non-relational data. Cloud
+Datastore automatically scales with your users.
+Google Cloud Save works even when your device is offline, and it
+provides an easy transition to server-side coding because
+the same database is accessible via App Engine and Compute Engine.
+Finally, Google Cloud Save provides a generous initial per-user free quota that
+expands as your user base grows.
+</p>
+<a href="{@docRoot}google/gcs/gcs-signup.html" class="button">Sign Up</a>
+</div>
+</div>
diff --git a/docs/html/google/index.jd b/docs/html/google/index.jd
index 2e97d62..4778a85 100644
--- a/docs/html/google/index.jd
+++ b/docs/html/google/index.jd
@@ -89,6 +89,16 @@ cloud messaging.</p>
to use Google Cloud Messaging.</p>
</div>
+<div class="landing-cell">
+ <div class="cell-icon">
+ <img src="{@docRoot}images/google/gcs-small.png" width="40" >
+ </div>
+ <h4><a href="{@docRoot}google/gcs/index.html"
+ >Google Cloud Save</a></h4>
+ <p>Enable per-user data storage and sync in your apps with no backend programming
+ required.</p>
+</div>
+
</div><!-- col-6 -->