Google Cloud Messaging
- Push message service
- No more client polling
- Messages are queued while device is offline
- Two types of messages
- send-to-sync
- with payload
Send-to-sync message
- Collapsible message
- Tickle to notify a need of update
Message with payload
- Non-collapsible message
- Up to 4 kb of payload data
- Delivery order not guaranteed
- Max 100 non-collapsible messages per queue
Main advantages
- Reduces update latency
- Preserves battery life
- Part of Google Play Services
- Available back to Android 2.2
- No quota limits
- Unicast/multicast
- App doesn’t need to be running to receive messages
Message format
{
"collapse_key": "your_collapse_key",
"time_to_live": 108,
"delay_while_idle": true,
"data": {
"message": "Hi from GCM!"
},
"restricted_package_name": "com.devoxx.gcm" ,
"dry_run": false,
"registration_ids": ["1", "2"]
}
Sample request
var request = require('request');
...
request(
{ method: 'POST',
uri:"https://android.googleapis.com/gcm/send",
headers:{'Content-type': 'application/json',
'Authorization': 'key=YOUR_KEY'},
json:{
'registration_ids': ['1', '2', '3', '4', '5', '6'],
'collapse_key': 'Update now'
}
},function(err,res,gcmResult){
// Handle the result
}
}
)
Response format
{
"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"}
]
}
Permissions
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission
android:name="com.devoxx.gcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.devoxx.gcm.permission.C2D_MESSAGE" />
Play services, are you there?
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Log.i(TAG, "This device is not supported.");
finish();
}
return false;
}
return true;
}
Registration
try {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String registrationId = gcm.register(getString(R.string.sender_id));
if (sendRegistrationIdToServer(registrationId)) {
storeRegistrationId(context, registrationId);
}
} catch (IOException e) {
Log.i(TAG, "Registration failed");
}
Message reception
Broadcast Receiver
public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ComponentName comp = new ComponentName(context.getPackageName(),
GcmMessageHandlerIntentService.class.getName());
startWakefulService(context, intent.setComponent(comp));
setResultCode(Activity.RESULT_OK);
}
}
Message reception
Service
@Override
protected void onHandleIntent(Intent intent) {
Bundle extras = intent.getExtras();
if (!extras.isEmpty()) {
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
String messageType = gcm.getMessageType(intent);
if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
String message = intent.getStringExtra("message");
}
}
GcmBroadcastReceiver.completeWakefulIntent(intent);
}
What’s new?
- GCM HTTP
- Upstream (GCM Cloud Connection Server)
- User notifications