An XMPP Server for Google Cloud Messaging

In this post I am going to write about the server-side of upstream messages with Google Cloud Messaging. This is the second part of my three-part series on this topic. If you haven’t read the first part about the flow of events and the Android implementation of upstream messaging, please read that one first. The first sections of that post are important to understand the big picture of upstream messaging and the role of the server within it.

Sample project

I have created a sample project for the server side of upstream messaging with Google Cloud Messaging. Please note that this is a sample. It’s not suitable for production!

Permanent connection and XMPP

Just recall the flow of events, described in detail in my first post:

The communication model of Google Cloud Messaging with the new Cloud Connection Server

The communication model of Google Cloud Messaging with the new GCM Cloud Connection Server

For this flow to work, Google must contact your server whenever the user sends a message from his device upstream to Google’s cloud. There are many models of how to do that. The one chosen by Google is to require a permanent connection between your backend and one of Google’s endpoints.

That’s where XMPP comes into play. Google has chosen XMPP as the protocol of choice for communicating between its servers and your server. Google named its XMPP endpoint “GCM Cloud Connection Server” or CCS for short. XMPP is an XML-based protocol that was created for instant messaging (also known under it’s original name Jabber). You can read more about XMPP on Wikipedia.

Server side code

In the previous post about upstream messaging you have seen that the Android side of GCM messaging is as simple as it can get.

The server side though is another matter altogether and got more complicated with the new solution.

First of all you’re most likely not as familiar with XMPP as you are with HTTP. And you’re not alone with it. HTTP is probably the most used application layer protocol. Thus the online knowledge base for HTTP is huge. Less so for XMPP. You probably have to search longer for solutions when hitting a stumbling block with XMPP.

This situation also applies to libraries. While there is an abundance of HTTP libraries, there are way less for XMPP. For Java I have found only one library that is still actively maintained: The Smack library, which Google also uses in its sample code.

Luckily Google has a very detailed description of all the message types exchanged between your server and Google’s cloud. And since XMPP is text-based you could build a client on your own – no matter which language you use. Nevertheless I recommend to use a library for this – after all they not only ease your life but are also more heavily tested. It’s likely that others already have found a solution for a problem that would otherwise bite you in production when writing your own code.

I have taken Google’s sample code for XMPP and extended it to be more flexible and suit my needs. This code requires the Smack and the json-simple libraries. To repeat: The demo is there just to get you up and running, so that you can easily test the upstream messaging model and your Android code. It’s still very basic and rough!

Logging messages

When setting up the connection using Smack’s XMPPConnection, you can configure it to open a Swing window displaying all incoming and outgoing messages:

config.setDebuggerEnabled(mDebuggable);

I set the flag to true when using the main() method of CcsClient. That obviously wouldn’t work too well on a server so I made this configurable. From within my web project I set this flag to false.

There is another flag that configures if Smack logs every message:

XMPPConnection.DEBUG_ENABLED = true;

Within the sample code I simply set this to true to see every message. Very handy for finding problems during development and appropriate for this demo project.

Implementing a server

These are the things you have to take care of:

  • Establish the connection
  • Authenticate your server app
  • Receive messages from Google’s cloud
  • Send messages to Google’s cloud
  • Acknowledge messages
  • Deal with problems

Since all message types are described in detail on Google’s Cloud Connection Server page, you can use whatever solution you like. The following code samples are in Java and make use of the Smack library. While some stuff is from Google’s sample code, some contains additions and abstractions around that sample code.

The most important class is CcsClient. This class is responsible for logging in to the server, sending messages to Google’s Cloud, receiving incoming messages and handling ACKs and NACKs correctly.

Connect to the GCM Cloud Connection Server

For the permanent connection you open a TLS secured connection to gcm.googleapis.com at port 5235.

Within CcsClient the method connect() handles this. It needs a ConnectionConfiguration object.

Here’s how to set up the ConnectionConfiguration:

config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT);
config.setSecurityMode(SecurityMode.required);
config.setReconnectionAllowed(true);
config.setRosterLoadedAtLogin(false);
config.setSendPresence(false);
config.setSocketFactory(SSLSocketFactory.getDefault());

In the first line you specify which server and which port to use. As mentioned these have to be gcm.googleapis.com and 5235 respectively. And you have to ensure to use Transport Layer Security (TLS). That’s why you have to set the SSLSocketFactory.

Afterwards you can create a Connection object and use it to establish the connection to Google’s servers:

Connection connection = new XMPPConnection(config);
connection.connect();

Authenticate your server app

Google needs to ensure that you are allowed to send messages via Google Cloud Messaging – and that you are allowed to send them to the clients you are addressing. For this Google uses a project id and an API key specific for that Google Cloud project.

I have detailed in my previous post about upstream messaging how to create a project and how to generate a server API key for that project.

With XMPP you do not send the API key with every request. Instead you authenticate your server app directly after establishing the connection.

In Java just use the Connection object you created in the previous step to log in:

connection.login(mProjectId + "@gcm.googleapis.com", mApiKey);

Obviously you have to use the values created on Google’s Cloud Console for mProjectId and mApiKey. You either pass them as arguments to the main() method of CcsClient or you call prepareClient() with the correct values – which I do from within my web project.

After logging in, you can send and receive messages.

Message formats

Before I will cover how to send or receive messages, I’m going to show you some typical messages sent either from your server or back to your server.

Incoming upstream messages

The following is a message as it shows up on your server when a user clicks “Register” in the Android client sample:

<message 
      to="projectId@gcm.googleapis.com" 
      from="devices@gcm.googleapis.com">
   <gcm xmlns="google:mobile:data">
      {
      "category":"com.grokkingandroid.sampleapp.samples.gcm",
      "data":
         {
         "action":
            "com.grokkingandroid.sampleapp.samples.gcm.REGISTER",
         "account":"info@openminds.de"
         },
      "message_id":"20",
      "from":"someRegistrationId"
      }
   </gcm>
</message>

This message is no different from any other message sent from an Android device. It is obvious that the message consists of an outer XML part and an inner JSON part. You can safely ignore the XML part. It’s always the same and is only used since XMPP is an XML based protocol. What’s important is the JSON part. The JSON object contains all the attributes you need to react appropriately to incoming messages.

All upstream messages contain the following attributes:

The attributes of a received GCM upstream message
Attribute Meaning
category Package name of the sending app
data The payload of your app
message_id A unique id you need later on to acknowledge the message
from The registration id of the device from which the message was sent

Obviously only your apps can send data to your server. But you can use the same GCM server for multiple apps. That’s why the category attribute is needed.

The data attribute is where you can put all the stuff, that you want to transmit to your server. The value of the data attribute is a JSON object itself.

The registration id is sent with every message within the from attribute. It’s a very lengthy string which you must use to map the data to the correct user.

ACK messages

The next section explains what’s up with the ACK and NACK messages. For now, you just need to know what those messages look like.

An ACK message is the simpler of both and always looks the same:

<message>
   <gcm xmlns="google:mobile:data">
      {
      "message_id":"m-8238983812089683316",
      "message_type":"ack",
      "from":"someRegistrationId"
      }
   </gcm>
</message>
The attributes of an ACK message
Attribute Meaning
from The registration id to which the message was sent
message_id The id of the message, that is acknowledged
message_type ACK or NACK – for ACK messages obviously always “ack

Incoming NACK messages

NACK messages come in two types. A stanza message always indicates a malformed message on your side. Stanza is the weird name used in the XMPP specification for the different kinds of XML messages that XMPP supports. Any other erroneous condition is handled by the second type of NACK messages.

Let me show you a stanza message first:

<message 
      id="iUB3B-2" 
      to="someProjectId@gcm.googleapis.com" 
      type="error">
   <error 
         code="400" 
         type="MODIFY">
      <bad-request 
            xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
      <text 
            xml:lang="en" 
            xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">
            InvalidJson: JSON_PARSING_ERROR
                  : Missing Required Field: message_id
      </text>
   </error>
   <gcm xmlns="google:mobile:data">
      {
      "to":"someRegId",
      "delay_while_idle":true,
      "data":
         {
         "message":
               "Simple sample sessage"
         },
      "time_to_live":120000
      }
   </gcm>
</message>

The error element of the XML message contains the description of what went wrong. And the gcm element contains the complete message you have sent to the server. The descriptive error message together with the full message causing the problem makes it really simple to understand what went wrong. In this case, the message_id is missing. I won’t go into detail for this type. You get those messages only, if you do not provide all mandatory attributes.

Stanza error messages should only happen while developing your app. What might follow later on are other problem types. Here is a sample message for other failure situations:

<message>
   <gcm xmlns="google:mobile:data">
      {
      "message_id":"m-4370299872608467243",
      "from":"invalidRegId",
      "error":"BAD_REGISTRATION",
      "message_type":"nack"
      }
   </gcm>
</message>

In this case the registration id you sent to Google’s server is invalid. Note: You will also get NACK messages for as long as your sign-up form hasn’t been processed by Google.


The attributes of a NACK message
Attribute Meaning
error A short error message
from The registration id to which the message was sent
message_id The id of the message, that is acknowledged
message_type ACK or NACK – for NACK messages obviously always “nack

Outgoing messages to devices

The final message type is a message from your server to an Android device:

<message id="4icfN-5">
   <gcm xmlns="google:mobile:data">
      {
      "to":"someRegistrationId",
      "delay_while_idle":true,
      "data":
         {
         "message":"Test message to a registered device"
         },
      "message_id":"m-15",
      "time_to_live":10000
      }
   </gcm>
</message>

Some of the attributes for sending messages via the Cloud Connection Server are the same as with messages via Google’s HTTP server. Others though are new and still others are missing. The following table shows a list of all possible attributes for sending XMPP messages to a device.

The attributes of a push message
Attribute Meaning Mandatory
collapse_key A key indicating that only the last message of this type should be sent to a device when it comes online again No
data The payload of your app No
delay_while_idle A flag indicating that messages should be kept on Google’s server if the device is inactive No
message_id A unique id you need later when dealing with ACK and NACK messages Yes
time_to_live The amount of time for which Google should keep the message around if the device is offline No
to The registration id of the recipient Yes

If you have used GCM in the past you will notice the to attribute. That’s the XMPP replacement for registration_ids. And in contrast to registration_ids you can send a message to only one user. Which means that for a broadcast you have to iterate over all registration ids. See Google’s documentation for details.

The delay_while_idle attribute tells Google that it should not send a message when the client device is not active. A value of true means that messages are kept on Google’s server until the device is active again.

The collapse_key probably needs some more explanation. If a device is offline you do not want it to get swamped with messages when it goes online again. Instead you can use the attribute collapse_key to ensure that only the last message for this key gets delivered to the app. But note: You can use only four collapse keys at the same time. The collapse_key applies to messages not delivered right away because of an delay_while_idle flag, but also to messages than cannot be delivered because the device isn’t connected at all.

You might have noticed that the data attribute is optional. Now at first this might sound like a pointless exercise. Why send a message without any data in it? But it depends on the purpose of the message. You can use a GCM message as a tickle. To simply notify your app, that there’s new data on the server to download. Unless the app can download different types of data, an empty message would be enough. When such a message arrives, your app would try to contact your server and download what it has to know.

If you do not set a time_to_live value, the default is used. The default currently is four weeks.

Message acknowledgements

The GCM Cloud Connection Server expects your server to acknowledge each and every method it sends to you. Google states explicitly that you should never send a NACK!

Always having to acknowledge messages means you should be able to deal with those messages. Take care of exceptional conditions, that might come up at your end. Google will resend messages for which you fail to send an acknowledgement. So not acknowledging puts unnecessary burden on your server.

Here’s what Google expects your server to adhere to:

For each device message your app server receives from CCS, it needs to send an ACK message. It never needs to send a NACK message. If you don’t send an ACK for a message, CCS will just resend it.

Source: https://developer.android.com/google/gcm/ccs.html

Google sends back ACK or NACK messages for every message your backend sends towards Google’s cloud. Google obviously is allowed to send NACKs. A NACK coming from Google means that you did something wrong – most of the time at least. For example you will get NACK messages for trying to send messages to registration ids that aren’t valid anymore.

Google will also send NACKs if the service is down or in case an “Internal Server Error” occurred. In the first case you should simply queue the message to resend it sometime later. In the second case though, you are a bit on your own. Most likely resending should be fine since most other cases are handled with other exception codes. So most likely it’s a problem on Google’s end – but you cannot know for sure. Maybe the problem is caused by the content of your message after all. It might be a good idea to add an internal retry counter which you decrease with every transmission. At the very least log those cases and have a look at them.

Receive messages from Google’s cloud

To handle incoming messages with Smack, you first have to register a PacketListener object with the Connection you created in the first step above. This object is responsible for all incoming traffic. See this slightly adapted version of Google’s code:

connection.addPacketListener(new PacketListener() {
   @Override
   public void processPacket(Packet packet) {
      Message incomingMessage = (Message) packet;
      GcmPacketExtension gcmPacket =
            (GcmPacketExtension)incomingMessage
                  .getExtension(GCM_NAMESPACE);
      String json = gcmPacket.getJson();
      try {
         Map jsonMap =
               (Map)JSONValue.parseWithException(json);
         
         handleMessage(jsonMap);
      } catch (ParseException e) {
         logger.log(Level.SEVERE, "Error parsing JSON " + json, e);
      } catch (Exception e) {
         logger.log(Level.SEVERE, "Couldn't send echo.", e);
      }
   }
}, new PacketTypeFilter(Message.class));

And handleMessage() looks like this:

private void handleMessage(Map<String, Object> jsonMap) {
   // only present for "ack"/"nack" messages
   Object messageType = jsonMap.get("message_type");
   if (messageType == null) {
      // Normal upstream data message
      CcsMessage msg = getMessage(jsonMap);
      handleIncomingDataMessage(msg);
      // Send ACK to CCS
      String ack = createJsonAck(msg.getFrom(), msg.getMessageId());
      send(ack);
   } else if ("ack".equals(messageType.toString())) {
      // Process Ack
      handleAckReceipt(jsonMap);
   } else if ("nack".equals(messageType.toString())) {
      // Process Nack
      handleNackReceipt(jsonMap);
   } else {
      logger.log(Level.WARNING, "Unrecognized message type (%s)",
      messageType.toString());
   }
}

The PacketListener has just one method: processPackage() which takes a Packet as argument.

A data package – that is an upstream message coming from a device – is then delegated to handleIncomingDataMessage(). For my sample project I have modified Google’s original code quite a bit. For one I use a CcsMessage object here that represents the incoming message.

Next I use PayloadProcessors to deal with the different type of messages. For every possible type of message I have a specific implementation of this interface to actually deal with the incoming message. You can of course replace this logic with whatever suits you.

What you do within those PayloadProcessors is very app-specific. The sample code just provides very basic implementations to give you an understanding of how to deal with messages. Hopefully your app has more to offer than my sample :-)

Send messages to Google’s cloud

To send a message to Google’s Cloud Connection Server, you have to follow these steps:

  1. Create the JSON payload
  2. Create a Smack Packet for the message
  3. Send the XML message to Google’s cloud

Create the JSON payload

With json-simple you can create a JSON object from is a map by calling JSONValue.toJSONString(). Each key of the map corresponds to one JSON attribute. In the section about message types I have listed the possible attributes. With this you can first create the map:

public static Map createAttributeMap(
      String to, 
      String messageId, 
      Map<String, String> payload,
      String collapseKey, 
      Long timeToLive, 
      Boolean delayWhileIdle) {
   Map<String, Object> message =
         new HashMap<String, Object>();
   if (to != null) {
      message.put("to", to);
   }
   if (collapseKey != null) {
      message.put("collapse_key", collapseKey);
   }
   if (timeToLive != null) {
      message.put("time_to_live", timeToLive);
   }
   if (delayWhileIdle != null && delayWhileIdle) {
      message.put("delay_while_idle", true);
   }
   if (messageId != null) {
      message.put("message_id", messageId);
   }
   message.put("data", payload);
   return message;
}

Using this method creating a JSON string for sending a message is simple:

public static String createJsonMessage(
      String to, 
      String messageId, 
      Map<String, String> payload,
      String collapseKey, 
      Long timeToLive, 
      Boolean delayWhileIdle) {
   return createJsonMessage(
         createAttributeMap(
               to, 
               messageId, 
               payload,
               collapseKey, 
               timeToLive, 
               delayWhileIdle));
}

public static String createJsonMessage(Map map) {
   return JSONValue.toJSONString(map);
}

Create a Smack Packet for the message

Creating a Packet object is even simpler. Google’s code makes use of the extension mechanism of Smack. Smack’s extensions are handlers for specific message types. The code uses them for processing incoming as well as outgoing messages.

Google’s inner class GcmPacketExtension is an implementation of Smack’s PacketExtension interface.

It’s method toPacket() creates an XML Packet, in this case it wraps the JSON with appropriate XML as required by XMPP.

Packet request = new GcmPacketExtension(jsonRequest).toPacket();

Send the message to Google’s cloud

If you have a Packet object you simply call send() on your XMPPConnection object that you created connecting to Google’s server in step one.

My demo follows Google’s sample code in combining the last two steps in the method send() of the CcsClient class:

public void send(String jsonRequest) {
   Packet request = new GcmPacketExtension(jsonRequest).toPacket();
   connection.sendPacket(request);
}

Sending to multiple recipients via Google’s Cloud Connection Server

You cannot send a message to multiple recipients when using Google’s Cloud Connection Server. Instead you have to send one message for every registration id you want to send a message to. That’s why I added the message sendBroadcast() which simply iterates over all recipients:

public void sendBroadcast(Map<String, String> payload, String collapseKey,
      long timeToLive, Boolean delayWhileIdle, List<String> recipients) {
   Map map = 
         createAttributeMap(null, null, payload, 
         collapseKey, timeToLive, delayWhileIdle);
   for (String toRegId: recipients) {
      String messageId = getRandomMessageId();
      map.put("message_id", messageId);
      map.put("to", toRegId);
      String jsonRequest = createJsonMessage(map);
      send(jsonRequest);
   }
}

Note: There actually is one option to target multitple registrations ids with just one message. With user specific messages you can target all devices of one user. But you’re still limited to one user only with this option. Since I’m going to cover user specific messages in my next post, I won’t deal with this option here.

You can combine HTTP and XMPP

Google allows you to use HTTP at the same time as XMPP to send messages to devices. It’s up to you if you want to use XMPP just to receive upstream messages of devices and to acknowledge those messages or if you want to use XMPP to talk to Google’s Cloud Connection Server (CCS) for everything.

Actually there is one use case for which you have to use HTTP – at least at the moment. I very much hope that this will change when the final version of those new services is released for everyone. I will cover that specific use case next week.

One final thing

I have written most of the server code in preparation of my talk at the Dutch Android User Group meetup. As I have written in my previous post about Google Cloud Messaging, you have to sign up to use the new features like upstream messaging, XMPP or user notifications. After signing up, Google processes your request and some time later comes back with the approval. In my case the approval took a while and the preparation for the talk was in jeopardy.

Gladly Dennis Geurts offered to use his testing API key and project id for which he had signed up much earlier. A big thanks for that, Dennis!

Lessons learned

With this post I have shown you some aspects of the server side of Google Cloud Messaging using the new upstream messaging model.

You have seen the different message types, have heard of the need to acknowledge messages and how to receive and send messages using Smack’s Java library for XMPP. Since XMPP is text based those code snippets should be easy to transform to any other language.

Together with the source of the demo project this post should get you on the right track to set up your own project.

If you want to start using Google Cloud Messaging, be sure to read the official documentation. I couldn’t cover all in this post. Be sure to not forget the document about advanced topics. There is also a nice blog post by Ryan Oldenburg of Pushbullet about some thinks to keep in mind when using GCM. It might help you to avoid problems right away. For another perspective on the topic you might also want to read Antoine Campbell’s Cloud Connection Server Tutorial.

One final problem: Right now I don’t know any SaaS or BaaS provider to support the XMPP messaging model for Google Cloud Messaging. This is a serious limitation in my opinion – one which I expect to get much better when this model gets adopted more often and is published to all without approval process. Should you know of any provider supporting the new GCM model, please drop me a line.

Share this article:

You can leave a response, or trackback from your own site.

43 Responses to “An XMPP Server for Google Cloud Messaging”

  1. RM says:

    Thank you again Wolfram, looking forward to the last installment.

    BTW, we’re going on a couple of weeks now waiting for Google XMPP approval. How long did it take for your approval?

    • It took Google about two weeks to approve. But I applied at the beginning of the year. The backlog probably was quite low then because of (nearly) no one applying around Christmas and New Year’s Eve.

      Because it’s for my demo and my the talk preparation, I selected the lowest “Active User” estimate possible, though. I would expect all other numbers to be processed faster.

  2. emilio says:

    I try this (just to test connection):

    public static void main(String[] args) {

    ProxyInfo proxyInfo = new ProxyInfo(ProxyInfo.ProxyType.HTTP, PROXY_HOST, PROXY_PORT, “”, “”);

    ConnectionConfiguration config = new ConnectionConfiguration(GCM_SERVER, GCM_PORT,proxyInfo);
    config.setDebuggerEnabled(true);
    config.setSecurityMode(SecurityMode.required);
    config.setReconnectionAllowed(true);
    config.setRosterLoadedAtLogin(false);
    config.setSendPresence(false);
    config.setSocketFactory(SSLSocketFactory.getDefault());

    XMPPConnection.DEBUG_ENABLED = true;

    Connection connection = new XMPPConnection(config);
    try {
    connection.connect();
    } catch (XMPPException e) {
    e.printStackTrace();
    }

    }
    but i get only
    gcm.googleapis.com:5235 Exception: XMPPError connecting to gcm.googleapis.com:5235.; : remote-server-error(502)

    Any idea?

    • Not really. I have tried to use it using a proxy once and failed as well. If I recall it correctly I have read somewhere that the Smack proxy support only works for XMPP via HTTP. XMPP via HTTP would be valid if both sides agree to do that. But Google doesn’t support that AFAIK – and I think this makes sense. Otherwise: Why choose to use XMPP in the first place?

      But I’m on very shaky ground here. So maybe you can get it to work. If you do so, please let us know! I’m quite sure there are plenty of kindred devs who would love to find a solution for this. After all this probably is the usual setup in corporate environments.

  3. rev says:

    I tried your code.
    But when i try to connect

    connection = new XMPPConnection(config);
    connection.connect();
    I get the following error
    gcm.googleapis.com:5235 Exception: XMPPError connecting to gcm.googleapis.com:5235.; : remote-server-error(502)
    — caused by: XMPPError connecting to gcm.googleapis.com:5235.: remote-server-error(502) XMPPError connecting to gcm.googleapis.com:5235.
    — caused by: java.net.ConnectException: Connection timed out: connect
    at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection.java:592)
    at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1010)
    at CcsClient.connect(CcsClient.java:348)
    at CcsClient.main(CcsClient.java:452)
    Nested Exception:
    XMPPError connecting to gcm.googleapis.com:5235.: remote-server-error(502) XMPPError connecting to gcm.googleapis.com:5235.
    — caused by: java.net.ConnectException: Connection timed out: connect
    at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection.java:565)
    at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1010)
    at CcsClient.connect(CcsClient.java:348)
    at CcsClient.main(CcsClient.java:452)
    Nested Exception:
    java.net.ConnectException: Connection timed out: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(Unknown Source)
    at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
    at java.net.PlainSocketImpl.connect(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.createSocket(Unknown Source)
    at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection.java:557)
    at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:1010)
    at CcsClient.connect(CcsClient.java:348)
    at CcsClient.main(CcsClient.java:452)
    Exception in thread “main” java.lang.IllegalStateException: Not connected to server.
    at org.jivesoftware.smack.XMPPConnection.sendPacket(XMPPConnection.java:483)
    at CcsClient.send(CcsClient.java:171)
    at CcsClient.main(CcsClient.java:464)

    I am using smack library 3.4.1
    Please help me how to resolve this.

    • How do you connect? Directly or via Proxy? Many problems can crop up in corporate networks, since firewalls might block access to the rather unusual port or proxies might interfere with any outgoing traffic. The exception indicates a networking problem on your part – it’s simply getting a timeout. I guess neither Google nor your provider are the problem here :-)

      Check your setup and any firewalls (corporate or personal) between you and the outer internet.

  4. Akshay says:

    I can’t find the org.v1.xmlpullparser refrence in CcsClient..?? its for android devices not for server

  5. Akshay says:

    another thing ur CcsClient uses connection = new XMPPConnection(config); but it says cannot instantiate XMPPConnection

  6. Akshay says:

    Connection connection = new XMPPConnection(config);
    is uninstantiable

  7. […] součástí celý zdroják pro navázání komunikace s GCM. Existují i nějaké další poměrně detailní tutoriály. Kámen úrazu byl, že jsem (už po několikáté) přehlédnul nenápadný řádek […]

  8. Dean Blakely says:

    Thanks for publishing this tutorial!
    I understand everything you have written and also xmpp. But the void for me is how to package your server java code into an actual working server. The Android docs also stopped short of that for CCS (but not for HTTP).

    how to I package your server project into something that actually works?
    TIA
    Dean

    • Alberto says:

      I’ve the same problem too!
      If it had been a servlet it would have been obvious but with just java classes I can’t really understand how to deploy it

      Any explanation woult be great!

      Thanks

    • Think of this as some kind of library. You just prepare the client somewhere in your code and are good to go. Of course you would have to make CcsClient more robust to cope with connection loss and the like and you would have to provide a real persistence solution instead of the dummy in-memory one I use.

      @Alberto: I actually tested my code using a standard Java EE Web app with Servlets and (cough) JSPs. I plan to release this as part of the testing app as well – but right now I have other priorities.

      • Dean Blakely says:

        Sounds like this technology is embryonic.

        My android apps use internal SMS to communicate between phones and then KitKat broke that up. I was looking at this XMPP as a replacement for that but if it’s not ready, it seems we have a technology hole?

        • I expect Google to change it slightly after the trial period. But as with Cloud to Devive Messaging which ended up as Google Cloud Messaging, the transition between the current form and the final form should be easy enough.

          If you want to enable user specific notifications and notification cancellation, I think Google Cloud messaging and applying for this new mode is the way to go.

          • Dean Blakely says:

            I ended up using GCM HTTP. It works reliably and it is very quick – very often within a second or two. Surely fast enough for a messaging app. Maybe not fast enough for a Walkie – talkie app.
            Dean

        • BTW: For user notifications you do not necessarily need an XMPP based backend yourself. Expect more about that in my next post.

          • Tim Meyer says:

            For implementing user notifications on XMPP, is there sample code anywhere on the web? I have been trying to implement an XMPP server with User Notification support but, have’nt figured out the format for creating/updating/deleting a notification key. Sending and receiving messages worked fine. Even the official documentation does’nt help too much. Thanks in advance.

  9. Kris says:

    Hi,

    I got my project ID whitelisted. I am able to send message to the device using your server code. However when the client sends a message using the same project id, I am not able to receive it on the server end.

    There is not log being printed and the ack or nack is also not received by the device.

    Please provide any suggestion to resolve the issue, I am struck at this point.

    Thanks,
    Kris

    • How did you get the registration id of your device to the server? While writing this and the preceding post I used upstream messaging for this as well. Did you transmit it via HTTP instead? And which version of Play Services are you using?

      • Kris says:

        Thanks for the reply.

        I have a HTTP request to register the GCM id in the server when the user logs into the App.

        As I was not able to proceed further with Upstream messaging, temporarily I tried using HTTP to send the chat message to the server and then using XMPP to forward that to client.

        We are using play services version 16 and com.google.android.gms.version is 4323000.

  10. Bogdan says:

    Hi.

    I’ve implemented GCM CCS myself. Downstream messages work as expected. Unfortunately, upstream messages are not received on the server, although they seem to be sent just fine from the client side. Using Glassfish and initializing the XMPP connection inside a servlet. ACKs for downstream messages are being received.

    Seems that I have the same problem as Kris. Might there be a temporary problem with GCM servers ?

    Stack Overflow post for reference: http://stackoverflow.com/questions/23366588/gcm-ccs-server-implementation-not-receiving-upstream-messages

    Thanks,
    Bogdan

    • I will check if this still works as expected this weekend.

      • Bogdan says:

        Hello again, Wolfram.

        I’m still having the stability issues that I described in the StackOverflow chat, with no luck figuring out what’s wrong… now I’m trying to get the debugger set up in order to maybe see more info from it. Unfortunately, every time I enable the debugger with (config.setDebuggerEnabled(true);), I get:

        java.lang.IllegalArgumentException: Can’t initialize the configured debugger

        Have you encountered this or do you have any idea what’s causing it ? I’ve tried both using Smack v3.2.1 and Smack v4.0.0-rc2.

        Thanks !
        Bogdan

  11. nan.xiangn says:

    hi!
    I’ve implemented GCM CCS myself,but it login error,I am sure my username and password is correct,how to resolve it,or it Instable itself?

    SASL authentication PLAIN failed: text:
    at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:342)
    at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:243)
    at org.jivesoftware.smack.Connection.login(Connection.java:368)
    at com.taobao.wireless.gcmagent.SmackCCSClient.connect(SmackCCSClient.java:391)
    at com.taobao.wireless.gcmagent.SmackCCSClient.main(SmackCCSClient.java:426)

  12. Aftab Saraz says:

    Hi,

    Firstly, Thanks a lot for making this GCM Upstream messaging much easier to understand.
    I have followed your code for Android client side. For making the server I have a php developer
    to work on it. I showed him the server code but he is not able to understand the Java code. Is there
    anything you know about making this server using php, please do help me. Any link or any blog will be
    much helpful.

    Kind Regards
    Aftab Saraz

    • Well apart from the library specifics there is nothing special. I think any developer should be able to at least understand code in other languages – unless they are too obscure.

      Anyway: He either has to look for an XMPP library for PHP first or he could implement everything based on the XML/JSON mix that I have described in detail. The protocol is text-based so you can easily implement it yourself in whatever language you (or in this case your developer) likes. I nevertheless recommed to use a library as I have written in my post.

  13. Christian says:

    Hello,

    That configuration should have the server side to install the SmackCcsClient
    It can be used in some hosting? which recommend use?

  14. Mike says:

    Can I use parts of your code for my app?

  15. Ryan Gralinski says:

    it works perfect but i have one problem when i run the app
    it runs main and sends a message to the device and then stops,
    if i turn on the smack debugging it opens a window and runs as a server stays running
    after it sends the message, i need this to run in the console with no window so how
    do i make it to run like a server without the debugging window??? please help

    Ryan

  16. Onkar Kulkarni says:

    Sir,
    I read your post. But still m not getting the clear idea about GCM. We have to create our application server and run it continuously right?

    Thanks,
    OnK

Leave a Reply

You can also subscribe without commenting.

Subscribe to RSS Feed My G+-Profile Follow me on Twitter!