page.title=GCM HTTP Connection Server @jd:body
This document describes the 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.
Note: See Implementing GCM Server for a list of all the message parameters and which connection server(s) supports them.
To send a message, the application server issues a POST request to
https://android.googleapis.com/gcm/send
.
A message request is made of 2 parts: HTTP header and HTTP body.
The HTTP header must contain the following headers:
Authorization
: key=YOUR_API_KEYContent-Type
: application/json
for JSON; application/x-www-form-urlencoded;charset=UTF-8
for plain text.
For example:
Content-Type:application/json Authorization:key=AIzaSyB-1uEai2WiUapxCs2Q0GZYzPu7Udno5aA { "registration_ids" : ["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx..."], "data" : { ... }, }
Note: If Content-Type
is omitted, the format
is assumed to be plain text.
The HTTP body content depends on whether you're using JSON or plain text. See Implementing GCM Server for a list of all the parameters your JSON or plain text message can contain.
Here is the smallest possible request (a message without any parameters and just one recipient) using JSON:
{ "registration_ids": [ "42" ] }
And here the same example using plain text:
registration_id=42
Here is a message with a payload and 6 recipients:
{ "data": { "score": "5x1", "time": "15:10" }, "registration_ids": ["4", "8", "15", "16", "23", "42"] }
Here is a message with all optional fields set and 6 recipients:
{ "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"] }
And here is the same message using plain-text format (but just 1 recipient):
collapse_key=score_update&time_to_live=108&delay_while_idle=1&data.score=4x8&data.time=15:16.2342®istration_id=42
Note: 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 Android devices 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.
There are two possible outcomes when trying to send a message:
When 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). When the request is rejected, the HTTP response contains a non-200 status code (such as 400, 401, or 503).
The following table summarizes the statuses that the HTTP response header might contain. Click the troubleshoot link for advice on how to deal with each type of error.
Response | Description |
---|---|
200 | Message was processed successfully. The response body will contain more details about the message status, but its format will depend whether the request was JSON or plain text. See Interpreting a success response for more details. |
400 | Only applies for JSON requests. Indicates that the request could not be parsed as JSON, or it contained invalid fields (for instance, passing a string where a number was expected). The exact failure reason is described in the response and the problem should be addressed before the request can be retried. |
401 | There was an error authenticating the sender account. Troubleshoot |
5xx | Errors in the 500-599 range (such as 500 or 503) indicate that there wa
an internal error in the GCM server while trying to process the request, or that
the server is temporarily unavailable (for example, because of timeouts). Sender
must retry later, honoring any Retry-After header included in the
response. Application servers must implement exponential back-off.
Troubleshoot |
When a JSON request is successful (HTTP status code 200), the response body contains a JSON object with the following fields:
Field | Description |
---|---|
multicast_id |
Unique ID (number) identifying the multicast message. |
success |
Number of messages that were processed without an error. |
failure |
Number of messages that could not be processed. |
canonical_ids |
Number of results that contain a canonical registration ID. See Advanced Topics for more discussion of this topic. |
results |
Array of objects representing the status of the messages processed. The
objects are listed in the same order as the request (i.e., for each registration
ID in the request, its result is listed in the same index in the response) and
they can have these fields:
|
If the value of failure
and canonical_ids
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:
message_id
is set, check for registration_id
:
registration_id
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 passed in the request (using the same index).error
:
Unavailable
, you could retry to send it in another
request.NotRegistered
, you should remove the registration
ID from your server database because the application was uninstalled from the
device or it does not have a broadcast receiver configured to receive
com.google.android.c2dm.intent.RECEIVE
intents.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 id=ID of
sent message
or Error=GCM error code
. The second
line, if available,
has the format of registration_id=canonical ID
. 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:
id
, check second line:
registration_id
, gets its value
and replace the registration IDs in your server database.Error
:
NotRegistered
, remove the registration ID from
your server database.Unavailable
as the
error code, they would have returned a 500 HTTP status instead).Here are the recommendations for handling the different types of error that might occur when trying to send a message to a device:
registration_id
parameter in a plain text message, or in the
registration_ids
field in JSON).
MissingRegistration
.com.google.android.c2dm.intent.REGISTRATION
intent and that you're
not truncating it or adding additional characters.
InvalidRegistration
.MismatchSenderId
.com.google.android.c2dm.intent.UNREGISTER
intent.com.google.android.c2dm.intent.RECEIVE
intents.NotRegistered
.MessageTooBig
.from
or any value
prefixed by google.
) that is used internally by GCM in the
com.google.android.c2dm.intent.RECEIVE
Intent and cannot be used.
Note that some words (such as collapse_key
) are also used by GCM
but are allowed in the payload, in which case the payload value will be
overridden by the GCM value.
InvalidDataKey
.InvalidTtl
.
Authorization
header
is the correct API key associated with your project. You can check the validity
of your API key by running the following command:# 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\"]}"If you receive a 401 HTTP status code, your API key is not valid. Otherwise you should see something like this:
{"multicast_id":6782339717028231855,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}If you want to confirm the validity of a registration ID, you can do so by replacing "ABC" with the registration ID.
Retry-After
header if it's included in the response
from the GCM server.error
field of a JSON object in the results array is Unavailable
.
error
field of a JSON
object in the results array is InternalServerError
.
InvalidPackageName
.
This section shows a few examples of responses indicating messages that were processed successfully. See Request Format for the requests these responses are based on.
Here is a simple case of a JSON message successfully sent to one recipient without canonical IDs in the response:
{ "multicast_id": 108, "success": 1, "failure": 0, "canonical_ids": 0, "results": [ { "message_id": "1:08" } ] }
Or if the request was in plain-text format:
id=1:08
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:
{ "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"} ] }
In this example:
Or if just the 4th message above was sent using plain-text format:
Error=InvalidRegistration
If the 5th message above was also sent using plain-text format:
id=1:2342 registration_id=32
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.
Requirements
For the web server:
For the Android application:
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 Google API Console.
For instructions on how to set up GCM, see Getting Started.
This section describes the different options for setting up an HTTP server.
To set up the server using a standard, servlet-compliant web server:
gcm-server
,
samples/gcm-demo-server
, and samples/gcm-demo-appengine
.
samples/gcm-demo-server/WebContent/WEB-INF/classes/api.key
and replace the existing text with the API key obtained above.samples/gcm-demo-server
directory.ant war
:$ 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: dist/gcm-demo.war BUILD SUCCESSFUL Total time: 0 seconds
dist/gcm-demo.war
to your running server. For instance, if you're using Jetty, copy gcm-demo.war
to the webapps
directory of the Jetty installation.http://192.168.1.10:8080/gcm-demo/home
, where gcm-demo
is the application context and /home
is the path of the main servlet.
Note: You can get the IP by running ifconfig
on Linux or MacOS, or ipconfig
on Windows.
You server is now ready.
To set up the server using a standard App Engine for Java:
samples/gcm-demo-appengine/src/com/google/android/gcm/demo/server/ApiKeyInitializer.java
and replace the existing text with the API key obtained above.
Note: 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 Datastore Viewer
to change
it later.
samples/gcm-demo-appengine
directory.ant runserver
,
using the -Dsdk.dir
to indicate the location of the App Engine SDK
and -Dserver.host
to set your server's hostname or IP address:$ 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
http://192.168.1.10:8080/home
, where /home
is the path of the main servlet.Note: You can get the IP by running ifconfig
on Linux or MacOS, or ipconfig
on Windows.
You server is now ready.