A Journey into Google Cloud Messaging: exploring the roots of crucial service for the Android eco-system What is the main component that connects millions of Android devices around the world and makes them interact each other? Which is the relationship between a device and a backend server deployed on the Google platform? Let's explore the technique and the magic behind the Google Cloud Messaging service and its infrastracture that dispatches a huge number of messages every day, reaching end users devices. We'll have a look together to a bit of theory and then we will examine the API exposed by this service to understand the basics.
Text of A Journey into Google Cloud Messaging
A Journey into Google Cloud Messaging exploring the roots of crucial service for the Android eco- system
Main topics Overview with architectural tidbits Lifecycle Client setup and code 3rd party server with HTTP messages
About Push communication Its a kind of Internet-based communication between two parties Its based on the publish-subscribe model Transaction is initiated by the publisher (server) Clients subscribe a set of preferences in advance
Push-based chat services and so on.
Components Client application: Android device with Android 2.2, Google Play Store installed, logged Google account 3rd party Application Server: possibly a backend component deployed on a server of your own that send messages to Android devices using GCM GCM Connection Server: Google provided servers that enables GCM
Credentials 1. Sender ID (obtained from API Console) 2. Application ID (declared on the android application manifest.xml) 3. Registration ID (assigned by GCM servers to your Android app) 4. Google account (needed for Android < 4.0.4) 5. Sender auth token (API key needed by 3rd party application server to use GCM service)
GCM service architecture
Lifecycle (1 of 3): Enable GCM We have to declare our intent to use GCM on the Android app, obtaining our registration id We need to do it just ONE TIME in our application life (i. e we have to store our registration id on the device using SharedPreferences) String SENDER_ID = "My-Sender-ID"; GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context); String registrationId = gcm.register(SENDER_ID);
Lifecycle (2 of 3): msg send 3rd party server sends a message to GCM servers GCM servers enqueue and store it! As soon as each Android device is online, GCM sends the msg to it On the device, Android OS broadcast msg to the specified Android application using Intent broadcast (only the right application receives the msg). Android application could also be in a not running state Android app processes the msg
Lifecycle (3 of 3): msg receive Android receives the msg, then extract key/value pairs from the payload Pairs are passed to the target app in a com. google.android.c2dm.intent.RECEIVE Intent Target app extracts the values from Intent to process them (it references them via keys)
Setup howto This is what you need to start developing: 1. Google Play Services (http://developer.android. com/google/play-services/setup.html) 2. Google API project from the cloud console (https: //cloud.google.com/console) to obtain the project number (your sender ID) 3. Turn on the GCM service 4. Obtain the API Key (needed for server side billing)
And now. Your GCM Service is ready! Its up to you to code your Android client and your server application (backend). Let me show you how easy it is!
Client: check Play Services Call checkPlayServices() inside onCreate() and onResume()
Receive a message We need: a special mechanism to accept our RECEIVE intent, a type of Broadcast Receiver. It receives the message from the channel, passing it to.. .an Intent Service that parses the message and calls our logic (what we want do with this message)
Wakeful Broadcast Receiver
Intent Service (1 of 2)
Intent Service (2 of 2)
Some defs for you about msgs Send to sync message: a message sent by server to tell the client that theres something new server side Payload message: a message sent by server to the client that contains some data for the client (a payload)
And now...lets go server side! Its important to remember that you can connect to GCM using two protocols: HTTP XMPP In this talk well cover HTTP only connections (you can find lots of documentation on the internet on how to use XMPP with GCM)
HTTP Server vs Cloud Connection Server 1. Cloud to device only 2. Uses HTTP POST and a synchronous mechanism (wait until received) 3. JSON msg on HTTP POST 1. Cloud to device and device to cloud 2. Uses an XMPP persistent asynchronous connection with ACK e NACK encapsulated in JSON 3. JSON msg on XMPP HTTP CCS
What you need to implement In our 3rd party server we need to: 1. Send a msg to GCM server 2. Expose an interface to our client (Android) to communicate with it 3. Store API key and registration IDs 4. Generate unique message IDs for each msg sent
Message parameters Time to go deep into a GCM message format. Well look at required [R] and optional [O] message parameters. Remember well discuss HTTP message parameters only!
Here you are...parameters! registration_ids [R]: string array of devices. range: 1 to 1000 notification_key [O]: maps an user to a set of registration_ids. Msg will be sent to the whole group of registration_ids covered by notification_key. Example: owner of multiple android devices (phone, tablet etc) with the same app installed on each of them. collapse_key [O]: an arbitrary string to mark n message. If the device is offline, and n message have been stored by GCM with the same collapse key, only the last one will be sent to the device as soon as it will be online again. No guarantee on the fact that the last message pushed by 3rd party server on GCM will be the one sent. range: 1 to 4 data [O]: optional payload of 4kb maximus stored as a JSON object. Keys are restricted to avoid using some reserved words. Values can be also json object but GCM will convert them to strings. delay_while_idle [O]: a json boolean. If true, msg will be sent when the device wakes up from idle. If collapse_key was defined, last message enqueued with that key will be sent time_to_live [O]: time in seconds. Time for GCM to store a message if device is in idle or offline state. Default is 4 weeks restricted_package_name[O]: package name of your app. Msg will be sent to registration_ids that match this package name dry_run [O]: json boolean. If true no msg will be sent. Just a test for your 3rd party server during some debug!
Http header for JSON msg Two headers for the GCM needed! Authorization: key = your_api_key Content-type: application/json
Message example 1
Message example 2
Message example 3
HTTP Response codes 200: Yes!!! Done. See the response message to have more details 400: Problem parsing a JSON request. See the response message for more details 401: Authentication problem 5xx: GCM service issue. Want to retry? See the suggested time provided in the response message
JSON Response fields multicast_id : unique id identifying a multicast message success: number of message sent failure: number of message failed to be sent canonical_ids: number of results that contain a canonical registration_id results: array of objects with the status of each message processed by GCM, listed in request order. It contains these fields: message_id: id of the message processed succefully error: a string with an error message registration_id: this message was processed but next time the client should use the registration_id specified, not the previous one. This field is not set in case of an error.
Error messages Missing registration ID: you forget to insert a registration ID in your request Invalid registration ID: it does not match the registration ID on the device (check length for example) Mismatched sender: Youre not a valid sender for this registration ID (the client hasnt declared you as a valid sender) Unregistered device: device is unregistered (for example: application has been uninstalled or registration id is expired due to Google decision to renew it Message too big: