446 lines
17 KiB
Plaintext
446 lines
17 KiB
Plaintext
page.title=GCM HTTP Connection Server
|
||
@jd:body
|
||
|
||
<div id="qv-wrapper">
|
||
<div id="qv">
|
||
|
||
|
||
<h2>In this document</h2>
|
||
|
||
<ol class="toc">
|
||
<li><a href="#auth">Authentication</a> </li>
|
||
<li><a href="#request">Request Format</a> </li>
|
||
<li><a href="#response">Response Format</a>
|
||
<ol class="toc">
|
||
<li><a href="#success">Interpreting a success response</a>
|
||
<li><a href="#error_codes">Interpreting an error response</a>
|
||
<li><a href="#example-responses">Example responses</a>
|
||
</ol>
|
||
</li>
|
||
<li><a href="#app-server">Implementing an HTTP-Based App Server</a>
|
||
</ol>
|
||
|
||
<h2>See Also</h2>
|
||
|
||
<ol class="toc">
|
||
<li><a href="server-ref.html">Server Reference</a></li>
|
||
<li><a href="gs.html">Getting Started</a></li>
|
||
<li><a href="client.html">Implementing GCM Client</a></li>
|
||
<li><a href="ccs.html">Cloud Connection Server</a></li>
|
||
|
||
|
||
</ol>
|
||
|
||
</div>
|
||
</div>
|
||
|
||
<p>This document describes the Google Cloud Messaging (GCM) HTTP
|
||
connection server. Connection servers
|
||
are the Google-provided servers that take messages from the 3rd-party
|
||
application server and sending them to the device.</p>
|
||
|
||
<p class="note"><strong>Note:</strong> The content in this document
|
||
applies to <a href="http://developer.chrome.com/apps/cloudMessaging">
|
||
GCM with Chrome apps</a> as well as Android.</p>
|
||
|
||
<p>See the
|
||
<a href="server-ref.html">Server Reference</a> for a list of all the message
|
||
parameters and which connection server(s) supports them.</p>
|
||
|
||
|
||
<h2 id="auth">Authentication</h2>
|
||
|
||
<p>To send a message, the application server issues a POST request. For example:</p>
|
||
<pre>https://android.googleapis.com/gcm/send</pre>
|
||
<p>A message request is made of 2 parts: HTTP header and HTTP body.</p>
|
||
|
||
<p>The HTTP header must contain the following headers:</p>
|
||
<ul>
|
||
<li><code>Authorization</code>: key=YOUR_API_KEY</li>
|
||
<li><code>Content-Type</code>: <code>application/json</code> for JSON;
|
||
<code>application/x-www-form-urlencoded;charset=UTF-8</code> for plain text.
|
||
If <code>Content-Type</code> is omitted, the format
|
||
is assumed to be plain text.
|
||
</li>
|
||
</ul>
|
||
|
||
<p>For example:
|
||
</p>
|
||
|
||
<pre>Content-Type:application/json
|
||
Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA
|
||
|
||
{
|
||
"registration_ids" : ["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx..."],
|
||
"data" : {
|
||
...
|
||
},
|
||
}</pre>
|
||
|
||
|
||
<p>The HTTP body content depends on whether you're using JSON or plain text.
|
||
See
|
||
<a href="server-ref.html#params">the Server Reference</a> for a list of all the
|
||
parameters your JSON or plain text message can contain.</p>
|
||
|
||
<h3 id="checkAPIkey">Checking the validity of an API key</h3>
|
||
|
||
<p>If you receive authentication errors when sending messages, check the validity
|
||
of your API key. For example, on Android, run the following command:</p>
|
||
|
||
<pre># api_key=YOUR_API_KEY
|
||
|
||
# curl --header "Authorization: key=$api_key" \
|
||
--header Content-Type:"application/json" \
|
||
https://android.googleapis.com/gcm/send \
|
||
-d "{\"registration_ids\":[\"ABC\"]}"</pre>
|
||
|
||
<p>
|
||
If you receive a 401 HTTP status code, your API key is not valid. Otherwise you
|
||
should see something like this:</p>
|
||
|
||
<pre>
|
||
{"multicast_id":6782339717028231855,"success":0,"failure":1,
|
||
"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
|
||
</pre>
|
||
|
||
<p>
|
||
If you want to confirm the validity of a registration ID, you can do so by
|
||
replacing "ABC" with the registration ID.
|
||
</p>
|
||
|
||
|
||
<h2 id="request">Request Format</h2>
|
||
|
||
<p>This section shows you how to format a request for both JSON and plain text. See
|
||
the <a href="server-ref.html#table1">Server Reference</a> for a complete
|
||
list of the fields you can include in a request.</p>
|
||
|
||
<p>Here is the smallest possible request (a message without any parameters and
|
||
just one recipient) using JSON:</p>
|
||
|
||
<pre class="prettyprint pretty-json">{ "registration_ids": [ "42" ] }</pre>
|
||
|
||
<p>And here the same example using plain text:</p>
|
||
<pre class="prettyprint">registration_id=42</pre>
|
||
|
||
<p> Here is a message with a payload and 6 recipients:</p>
|
||
|
||
<pre class="prettyprint pretty-HTML">{ "data": {
|
||
"score": "5x1",
|
||
"time": "15:10"
|
||
},
|
||
"registration_ids": ["4", "8", "15", "16", "23", "42"]
|
||
}</pre>
|
||
<p>Here is a message with all optional fields set and 6 recipients:</p>
|
||
<pre class="prettyprint pretty-json">{ "collapse_key": "score_update",
|
||
"time_to_live": 108,
|
||
"delay_while_idle": true,
|
||
"data": {
|
||
"score": "4x8",
|
||
"time": "15:16.2342"
|
||
},
|
||
"registration_ids":["4", "8", "15", "16", "23", "42"]
|
||
}</pre>
|
||
<p>And here is the same message using plain-text format (but just 1 recipient): </p>
|
||
|
||
<pre class="prettyprint">collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.score=4x8&data.time=15:16.2342&registration_id=42
|
||
</pre>
|
||
|
||
<p>Here is a message that includes a notification key and payload:</p>
|
||
|
||
<pre>
|
||
{
|
||
"data": {
|
||
"message": "ciao"
|
||
},
|
||
"notification_key":"aUniqueKey"
|
||
}
|
||
</pre>
|
||
|
||
<p>For more information about notifications and how to use them, see
|
||
<a href="{@docRoot}google/gcm/notifications.html">User Notifications</a>.</p>
|
||
|
||
|
||
<p class="note"><strong>Note:</strong> If your organization has a firewall
|
||
that restricts the traffic to or
|
||
from the Internet, you need to configure it to allow connectivity with GCM in order for
|
||
your GCM client apps to receive messages.
|
||
The ports to open are: 5228, 5229, and 5230. GCM typically only uses 5228, but
|
||
it sometimes uses 5229 and 5230. GCM doesn't provide specific IPs, so you should allow
|
||
your firewall to accept outgoing connections to all IP addresses
|
||
contained in the IP blocks listed in Google's ASN of 15169.</p>
|
||
|
||
|
||
|
||
<h2 id="response">Response format</h2>
|
||
|
||
<p>There are two possible outcomes when trying to send a message:</p>
|
||
<ul>
|
||
<li>The message is processed successfully. The HTTP response has a 200 status, and
|
||
the body contains more information about the status of the message (including possible errors).</li>
|
||
<li>The GCM server rejects the request. The HTTP response contains a
|
||
non-200 status code (such as 400, 401 or 5xx).</li>
|
||
</ul>
|
||
|
||
<p>When a JSON request is successful (HTTP status code 200), the JSON object returned
|
||
contains the <a href="{@docRoot}google/gcm/server-ref.html#table4">
|
||
Downstream HTTP message response body</a>.</p>
|
||
|
||
<p>If the value of <code>failure</code> and <code>canonical_ids</code> is 0, it's
|
||
not necessary to parse the remainder of the response. Otherwise, we recommend
|
||
that you iterate through the results field and do the following for each object
|
||
in that list:</p>
|
||
<ul>
|
||
<li>If <code>message_id</code> is set, check for <code>registration_id</code>:
|
||
<ul>
|
||
<li>If <code>registration_id</code> is set, replace the original ID with
|
||
the new value (canonical ID) in your server database. Note that the original ID
|
||
is not part of the result, so you need to obtain it from the list of
|
||
code>registration_ids</code> passed in the request (using the same index).</li>
|
||
</ul>
|
||
</li>
|
||
<li>Otherwise, get the value of <code>error</code>:
|
||
<ul>
|
||
<li>If it is <code>Unavailable</code>, you could retry to send it in another
|
||
request.</li>
|
||
<li>If it is <code>NotRegistered</code>, you should remove the registration
|
||
ID from your server database because the application was uninstalled from the
|
||
device, or the client app isn't configured to receive
|
||
messages.</li>
|
||
<li>Otherwise, there is something wrong in the registration ID passed in
|
||
the request; it is probably a non-recoverable error that will also require removing
|
||
the registration from the server database. See
|
||
<a href="{@docRoot}google/gcm/server-ref.html#error-codes">Downstream message error response
|
||
codes</a> for all possible error values.</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
<p>When a plain-text request is successful (HTTP status code 200), the response
|
||
body contains 1 or 2 lines in the form of key/value pairs.
|
||
The first line is always available and its content is either <code>id=<em>ID of
|
||
sent message</em></code> or <code>Error=<em>GCM error code</em></code>. The second
|
||
line, if available,
|
||
has the format of <code>registration_id=<em>canonical ID</em></code>. The second
|
||
line is optional, and it can only be sent if the first line is not an error. We
|
||
recommend handling the plain-text response in a similar way as handling the
|
||
JSON response:</p>
|
||
<ul>
|
||
<li>If first line starts with <code>id</code>, check second line:
|
||
<ul>
|
||
<li>If second line starts with <code>registration_id</code>, gets its value
|
||
and replace the registration IDs in your server database.</li>
|
||
</ul>
|
||
</li>
|
||
<li>Otherwise, get the value of <code>Error</code>:
|
||
<ul>
|
||
<li>If it is <code>NotRegistered</code>, remove the registration ID from
|
||
your server database.</li>
|
||
<li>Otherwise, there is probably a non-recoverable error (<strong>Note:
|
||
</strong>Plain-text requests will never return <code>Unavailable</code> as the
|
||
error code, they would have returned a 500 HTTP status instead).</li>
|
||
</ul>
|
||
</li>
|
||
</ul>
|
||
|
||
|
||
<h3 id="example-responses">Example responses</h3>
|
||
<p>This section shows a few examples of responses indicating messages that were
|
||
processed successfully. See <a href="#request">Request Format</a> for
|
||
the requests these responses are based on.</p>
|
||
<p> Here is a simple case of a JSON message successfully sent to one recipient
|
||
without canonical IDs in the response:</p>
|
||
<pre class="prettyprint pretty-json">{ "multicast_id": 108,
|
||
"success": 1,
|
||
"failure": 0,
|
||
"canonical_ids": 0,
|
||
"results": [
|
||
{ "message_id": "1:08" }
|
||
]
|
||
}</pre>
|
||
|
||
<p>Or if the request was in plain-text format:</p>
|
||
<pre class="prettyprint">id=1:08
|
||
</pre>
|
||
|
||
<p>Here are JSON results for 6 recipients (IDs 4, 8, 15, 16, 23, and 42 respectively)
|
||
with 3 messages successfully processed, 1 canonical registration ID returned,
|
||
and 3 errors:</p>
|
||
<pre class="prettyprint pretty-json">{ "multicast_id": 216,
|
||
"success": 3,
|
||
"failure": 3,
|
||
"canonical_ids": 1,
|
||
"results": [
|
||
{ "message_id": "1:0408" },
|
||
{ "error": "Unavailable" },
|
||
{ "error": "InvalidRegistration" },
|
||
{ "message_id": "1:1516" },
|
||
{ "message_id": "1:2342", "registration_id": "32" },
|
||
{ "error": "NotRegistered"}
|
||
]
|
||
}
|
||
</pre>
|
||
<p> In this example:</p>
|
||
<ul>
|
||
<li>First message: success, not required.</li>
|
||
<li>Second message: should be resent (to registration ID 8).</li>
|
||
<li>Third message: had an unrecoverable error (maybe the value got corrupted
|
||
in the database).</li>
|
||
<li>Fourth message: success, nothing required.</li>
|
||
<li>Fifth message: success, but the registration ID should be updated in the
|
||
server database (from 23 to 32).</li>
|
||
<li>Sixth message: registration ID (42) should be removed from the server database
|
||
because the application was uninstalled from the device.</li>
|
||
</ul>
|
||
<p>Or if just the 4th message above was sent using plain-text format:</p>
|
||
<pre class="prettyprint">Error=InvalidRegistration
|
||
</pre>
|
||
<p>If the 5th message above was also sent using plain-text format:</p>
|
||
<pre class="prettyprint">id=1:2342
|
||
registration_id=32
|
||
</pre>
|
||
|
||
|
||
<h2 id="app-server">Implementing an HTTP-Based App Server</h2>
|
||
|
||
<p>This section gives examples of implementing an app server that works with the
|
||
GCM HTTP connection server. Note that a full GCM implementation requires a
|
||
client-side implementation, in addition to the server. This example is based on Android.</a>
|
||
|
||
|
||
<p>Requirements</p>
|
||
<p>For the web server:</p>
|
||
<ul>
|
||
<li> <a href="http://ant.apache.org/">Ant 1.8</a> (it might work with earlier versions, but it's not guaranteed).</li>
|
||
<li>One of the following:
|
||
<ul>
|
||
<li>A running web server compatible with Servlets API version 2.5, such as
|
||
<a href="http://tomcat.apache.org/">Tomcat 6</a> or <a href="http://jetty.codehaus.org/">Jetty</a>, or</li>
|
||
<li><a href="http://code.google.com/appengine/">Java App Engine SDK</a>
|
||
version 1.6 or later.</li>
|
||
</ul>
|
||
</li>
|
||
<li>A Google account registered to use GCM.</li>
|
||
<li>The API key for that account.</li>
|
||
</ul>
|
||
<p>For the Android application:</p>
|
||
<ul>
|
||
<li>Emulator (or device) running Android 2.2 (ideally, 2.3 or above) with Google APIs.</li>
|
||
<li>The Google API project number of the account registered to use GCM.</li>
|
||
</ul>
|
||
|
||
<h3 id="gcm-setup">Setting Up GCM</h3>
|
||
<p>Before proceeding with the server and client setup, it's necessary to register
|
||
a Google account with the Google API Console, enable Google Cloud Messaging in GCM,
|
||
and obtain an API key from the <a href="https://code.google.com/apis/console">
|
||
Google API Console</a>.</p>
|
||
<p>For instructions on how to set up GCM, see <a href="gs.html">Getting Started</a>.</p>
|
||
|
||
|
||
<h3 id="server-setup">Setting Up an HTTP Server</h3>
|
||
<p>This section describes the different options for setting up an HTTP server.</p>
|
||
|
||
<h4 id="webserver-setup">Using a standard web server</h4>
|
||
<p>To set up the server using a standard, servlet-compliant web server:</p>
|
||
<ol>
|
||
<li>From the <a href="http://code.google.com/p/gcm">open source site</a>,
|
||
download the following directories: <code>gcm-server</code>,
|
||
<code>samples/gcm-demo-server</code>, and <code>samples/gcm-demo-appengine</code>.</p>
|
||
|
||
|
||
<li>In a text editor, edit the <code>samples/gcm-demo-server/WebContent/WEB-INF/classes/api.key</code> and replace the existing text with the API key obtained above.</li>
|
||
<li>In a shell window, go to the <code>samples/gcm-demo-server</code> directory.</li>
|
||
<li>Generate the server's WAR file by running <code>ant war</code>:</li>
|
||
|
||
<pre class="prettyprint">$ ant war
|
||
|
||
Buildfile:build.xml
|
||
|
||
init:
|
||
[mkdir] Created dir: build/classes
|
||
[mkdir] Created dir: dist
|
||
|
||
compile:
|
||
[javac] Compiling 6 source files to build/classes
|
||
|
||
war:
|
||
[war] Building war: <strong>dist/gcm-demo.war</strong>
|
||
|
||
BUILD SUCCESSFUL
|
||
Total time: 0 seconds
|
||
</pre>
|
||
|
||
<li>Deploy the <code>dist/gcm-demo.war</code> to your running server. For instance, if you're using Jetty, copy <code>gcm-demo.war</code> to the <code>webapps</code> directory of the Jetty installation.</li>
|
||
<li>Open the server's main page in a browser. The URL depends on the server you're using and your machine's IP address, but it will be something like <code>http://192.168.1.10:8080/gcm-demo/home</code>, where <code>gcm-demo</code> is the application context and <code>/home</code> is the path of the main servlet.
|
||
|
||
</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> You server is now ready.</p>
|
||
|
||
<h4 id="appengine-setup">Using App Engine for Java</h4>
|
||
|
||
<p>To set up the server using a standard App Engine for Java:</p>
|
||
<ol>
|
||
<li>Get the files from the <a href="http://code.google.com/p/gcm">open source
|
||
site</a>, as described above.</p>
|
||
</li>
|
||
<li>In a text editor, edit
|
||
<code>samples/gcm-demo-appengine/src/com/google/android/gcm/demo/server/ApiKeyInitializer.java</code>
|
||
and replace the existing text with the API key obtained above.
|
||
|
||
<p class="note"><strong>Note:</strong> The API key value set in that class will
|
||
be used just once to create a persistent entity on App Engine. If you deploy
|
||
the application, you can use App Engine's <code>Datastore Viewer</code> to change
|
||
it later.</p>
|
||
|
||
</li>
|
||
<li>In a shell window, go to the <code>samples/gcm-demo-appengine</code> directory.</li>
|
||
<li>Start the development App Engine server by <code>ant runserver</code>,
|
||
using the <code>-Dsdk.dir</code> to indicate the location of the App Engine SDK
|
||
and <code>-Dserver.host</code> to set your server's hostname or IP address:</li>
|
||
|
||
<pre class="prettyprint">
|
||
$ ant -Dsdk.dir=/opt/google/appengine-java-sdk runserver -Dserver.host=192.168.1.10
|
||
Buildfile: gcm-demo-appengine/build.xml
|
||
|
||
init:
|
||
[mkdir] Created dir: gcm-demo-appengine/dist
|
||
|
||
copyjars:
|
||
|
||
compile:
|
||
|
||
datanucleusenhance:
|
||
[enhance] DataNucleus Enhancer (version 1.1.4) : Enhancement of classes
|
||
[enhance] DataNucleus Enhancer completed with success for 0 classes. Timings : input=28 ms, enhance=0 ms, total=28 ms. Consult the log for full details
|
||
[enhance] DataNucleus Enhancer completed and no classes were enhanced. Consult the log for full details
|
||
|
||
runserver:
|
||
[java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.jetty.JettyLogger info
|
||
[java] INFO: Logging to JettyLogger(null) via com.google.apphosting.utils.jetty.JettyLogger
|
||
[java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.config.AppEngineWebXmlReader readAppEngineWebXml
|
||
[java] INFO: Successfully processed gcm-demo-appengine/WebContent/WEB-INF/appengine-web.xml
|
||
[java] Jun 15, 2012 8:46:06 PM com.google.apphosting.utils.config.AbstractConfigXmlReader readConfigXml
|
||
[java] INFO: Successfully processed gcm-demo-appengine/WebContent/WEB-INF/web.xml
|
||
[java] Jun 15, 2012 8:46:09 PM com.google.android.gcm.demo.server.ApiKeyInitializer contextInitialized
|
||
[java] SEVERE: Created fake key. Please go to App Engine admin console, change its value to your API Key (the entity type is 'Settings' and its field to be changed is 'ApiKey'), then restart the server!
|
||
[java] Jun 15, 2012 8:46:09 PM com.google.appengine.tools.development.DevAppServerImpl start
|
||
[java] INFO: The server is running at http://192.168.1.10:8080/
|
||
[java] Jun 15, 2012 8:46:09 PM com.google.appengine.tools.development.DevAppServerImpl start
|
||
[java] INFO: The admin console is running at http://192.168.1.10:8080/_ah/admin
|
||
</pre>
|
||
|
||
<li>Open the server's main page in a browser. The URL depends on the server
|
||
you're using and your machine's IP address, but it will be something like
|
||
<code>http://192.168.1.10:8080/home</code>, where <code>/home</code>
|
||
is the path of the main servlet.</li>
|
||
|
||
<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>
|
||
|
||
</ol>
|
||
<p> You server is now ready.</p>
|