Friday, June 28, 2013

Google Cloud Messaging: Collapsible Messages

n a previous article, we looked at how to set up Google Cloud Messaging (GCM) in Android applications. We learned that GCM is a free service that allows us to push messages from the cloud to a number of mobile recipients running our Android application and registered with our service.
The push messages can be either collapsible or non-collapsible. “Collapsible” means that the most recent message overwrites any previous ones queued for sending. A typical example of collapsible messaging is a live game score. In case previous score updates haven’t reached their destination yet, the Android clients would only get the latest one. This happens however on a best effort basis: the order in which messages get sent in GCM is not guaranteed, so in some cases the “latest” message may not be actually the most recent one


Take a Baseball game between the Boston Red Sox and the New York Yankees as an example. Here’s how we would construct a collapsible update to send to devices registered with our sports push notification service. All code samples here are slight modifications of the GCM Demo application . As commented in the previous article, the reader is invited to download the Demo (both client and server) and experiment. The Demo uses theGCM helper library for Java that abstracts much of the low-level stuff (like handling messages in JSON format).
However, while being pretty useful for introducing GCM, the Demo doesn’t actually handle push content. It only fires & acknowledges the event, while the same notification (set up in the client’s configuration) is used in all cases (“From GCM: you got message!”). So let’s write some actual message sending & receiving code:
Server Code
1
2
3
4
5
6
7
8
9
10
11
12
13
// in imports
import com.google.android.gcm.server.Message;
 
// Inside send method, construct a collapsible message
Message message = new Message.Builder()
  .collapseKey("Fenway Park Game") // The key for all updates.
  .timeToLive(600) // Time in seconds to keep message queued if device offline.
  .delayWhileIdle(true) // Wait for device to become active before sending.
  .addData("team1", "Red Sox:1")
  .addData("team2", "Yankees:0")
  .build();
// send in chunks of 1,000 devices
//...
It’s worth noting that a given GCM message can be sent to up to 1,000 mobile clients at a time. In case our user base is larger than that, we’ll need to break the message sending process in chunks of 1,000 recipients. One way to do that would be to use a java.util.concurrent.Executor thread pool and send the chunks asynchronously, as does the GCM Demo server.
Client Code
Now we need to process the GCM message in our Android application:
1
2
3
4
5
6
7
8
9
10
11
12
// inside GCMIntentService
@Override
protected void onMessage(Context context, Intent intent) {
 
    String message = intent.getStringExtra("collapse_key")  + "\n"
                     + intent.getStringExtra("team1") + " "
                     + intent.getStringExtra("team2");
 
    displayMessage(context, message);
    // notify user
    generateNotification(context, message);
}
Notice how a collapse_key is set up by the server and retrieved by the client. That key is how GCM identifies the flow of collapsible updates for a given event. In case there are several push notifications queued for sending with the same collapse key “Fenway Park Game”, only the most recent one will be delivered.
Here’s how a the push notification above looks like on an actual Android device. The last screen is the opened GCMClient application turned into a “Sports Center” for demonstration purposes: