page.title=GCM Cloud Connection Server @jd:body

Quickview

In this document

  1. CCS vs. GCM HTTP
  2. How to Use CCS
    1. Sending Messages
    2. Message Format
    3. Message Examples
  3. Control Flow

See Also

  1. Getting Started
  2. CCS and User Notifications Signup Form

Note: To try out this feature, sign up using this form.

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.

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:

The upstream messaging (device-to-cloud) feature of CCS is part of the Google Play services platform. Upstream messaging is available through the {@code GoogleCloudMessaging} APIs. To use upstream messaging and the new streamlined registration process, you must set up the Google Play services SDK.

CCS vs. GCM HTTP

CCS messaging differs from GCM HTTP messaging in the following ways:

This document describes how to use CCS. For general concepts and information on how to use GCM HTTP, see the GCM Architectural Overview.

How to Use CCS

GCM Cloud Connection Server (CCS) is an XMPP endpoint, running on {@code http://gcm.googleapis.com} port 5235.

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.

CCS requires a SASL PLAIN authentication mechanism using {@code <your_GCM_Sender_Id>@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 Getting Started.

You can use most XMPP libraries to interact with CCS.

Sending messages

The following snippets illustrate how to perform authentication in CCS.

Client

<stream:stream to="gcm.googleapis.com" 
        version="1.0" xmlns="jabber:client" 
        xmlns:stream="http://etherx.jabber.org/streams"/>

Server

<str:features xmlns:str="http://etherx.jabber.org/streams">
 <mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
   <mechanism>X-OAUTH2</mechanism>
   <mechanism>X-GOOGLE-TOKEN</mechanism>
   <mechanism>PLAIN</mechanism>
 </mechanisms>
</str:features>

Client

<auth mechanism="PLAIN"
xmlns="urn:ietf:params:xml:ns:xmpp-sasl">MTI2MjAwMzQ3OTMzQHByb2plY3RzLmdjbS5hb
mRyb2lkLmNvbQAxMjYyMDAzNDc5FzNAcHJvamVjdHMtZ2EtLmFuZHJvaWQuY29tAEFJe
mFTeUIzcmNaTmtmbnFLZEZiOW1oekNCaVlwT1JEQTJKV1d0dw==</auth>

Server

<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>

Message Format

CCS uses normal XMPP <message> stanzas. The body of the message must be:

<gcm xmlns:google:mobile:data>
    JSON payload
</gcm>

The JSON payload for server-to-device is similar to what the GCM http endpoint uses, with these exceptions:

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.

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.

Message Examples

Here is an XMPP stanza containing the JSON message from a 3rd-party server to CCS:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to":"REGISTRATION_ID",  // "to" replaces "registration_ids"
      "message_id":"m-1366082849205" // new required field
      "data":
      {
          "hello":"world",
      }
      "time_to_live":"600",
      "delay_while_idle": true/false
  }
  </gcm>
</message>

Here is an XMPP stanza containing the ACK/NACK message from CCS to 3rd-party server:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "from":"REGID",
      "message_id":"m-1366082849205"
      "message_type":"ack"
  }
  </gcm>
</message>

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "from":"REGID",
      "message_id":"m-1366082849205"
      "error": ERROR_CODE,
      "message_type":"nack"
  }
  </gcm>
</message>

Upstream Messages

Using CCS and the GoogleCloudMessaging API, you can send messages from a user's device to the cloud.

Here is how you send an upstream message using the GoogleCloudMessaging API. For a complete example, see Getting Started:

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 + "@gcm.googleapis.com", id, ttl, data);

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:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "category":"com.example.yourapp", // to know which app sent it
      "data":
      {
          "hello":"world",
      },
      "message_id":"m-123",
      "from":"REGID"
  }
  </gcm>
</message>

Here is the format of the ACK expected by CCS from 3rd-party servers in response to the above message:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to":"REGID",
      "message_id":"m-123"
      "message_type":"ack"
  }
  </gcm>
</message>

Python Example

This example illustrates how to connect, send, and receive GCM messages using XMPP. It shouldn't be used as-is on a production deployment.

import sys, json, xmpp
SERVER = ('gcm.googleapis.com', 5235)
#USERNAME = '<your_numeric_project_id>'
#PASSWORD = '<your_gcm_api_key>'

# 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 = ("<message from='{0}' to='gcm@google.com'>"
              "<gcm xmlns='google:mobile:data'>{1}</gcm></message>")
  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)

Control Flow

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.

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.

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.

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.