Article Image
read

Google Cloud Messaging (GCM) is a service that enables developers to send data from servers to both Android applications or Chrome apps and extensions. Wikipedia.


GCM basics involves four steps

  • Registering the client (Android Device)
  • Provide the registration ID to server
  • Send notifications from Server to GCM with registration ID
  • Receive notifications on the client

Prerequisite

  • Project Number (845696541232)
  • Server API Key (XIzaSyBDRJ00YJbTE011CbWWjlcKYUGI3eLccdI)

Refer to Create Project on creating a new project and Generate API Key for generating a Server key(API Key)

Once we have all the required data we can start with our client registration process.

Creating a new Project

Ensure that we have the necessary dependencies added.

app/build.gradle

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:21.0.3'
    compile 'com.google.android.gms:play-services:6.5.87'
}

Adding Permissions

app/src/main/Androidmanifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    ...
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
    <permission android:name="com.example.gcm.permission.C2D_MESSAGE" android:protectionLevel="signature" />
    <uses-permission android:name="com.example.gcm.permission.C2D_MESSAGE" />
    ...      
</manifest>

Registering the client (Android Device)

The client part has an interface with a registration button. On click of the button a call to GCM is made and Registration ID is obtained. While making the request it is necessary to note that we have the correct Project Number from the developers console.

res/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingLeft="@dimen/activity_horizontal_margin"
                android:paddingRight="@dimen/activity_horizontal_margin"
                android:paddingTop="@dimen/activity_vertical_margin"
                android:paddingBottom="@dimen/activity_vertical_margin"
                tools:context=".MainActivity">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Register"
        android:id="@+id/register"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="117dp"/>

</RelativeLayout>

src/main/java/.../MainActivity.java

Declaring necessary variables and functions

Button register_button;
String PROJECT_NUMBER = "845696541232";
GoogleCloudMessaging gcmObj;
String regId;

 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    register_button = (Button) findViewById(R.id.register);
    register_button.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {
        registerInBackground();
      }
    });

Writing the registration function

private void registerInBackground() {
    new AsyncTask<Void, Void, String>() {
        @Override
        protected String doInBackground(Void... params) {
            String msg = "";
            try {
                gcmObj = GoogleCloudMessaging.getInstance(getApplicationContext());
                regId = gcmObj.register(PROJECT_NUMBER);
                msg = "Registration ID :" + regId;
            } catch (IOException ex) { msg = ex.getMessage();}
            return msg;
        }
        @Override
        protected void onPostExecute(String msg) {
            Toast.makeText(getApplicationContext(),"Registered with GCM Server successfully.\n\n"+ msg, Toast.LENGTH_SHORT).show();
            Log.d("MainActivity", regId);
        }
    }.execute(null, null, null);
}

Provide the registration ID to server

Once the registration is successful, Registration ID is obtained. This Registration ID is used by the server to send notifications to device. In our sample the Registration ID printed in logs is copied and used in the server part.

Send notifications from Server to GCM with Registration ID (Server Part)

The sample server code here is written in Nodejs. Using node-gcm library we can easily send messages to GCM. The server part includes two files.

  • package.json
  • node-gcm-sample.js

package.json

{
  "dependencies": {
    "node-gcm": "git+https://github.com/ToothlessGear/node-gcm.git"
  }
}

node-gcm-sample.js

var gcm = require('node-gcm');
var message = new gcm.Message();
message.addData('key1', 'Awesome World!!'); /*Message to the client*/

var regIds = ['COPIED_ID_FROM_ANDROID_LOGS'];
var sender = new gcm.Sender('SERVER_API_KEY');

sender.send(message, { registrationIds: regIds } , function (err, result) {
  if(err) console.error(err);
  else    console.log(result);
});

Create both the files in a project folder, and execute npm install

Receive notifications on the client

Now we enter into the last part of preparing our client to receive notifications. We have to intimate the client to listen for notifications using a Receiver and a Service to handle the data from server.

src/main/java/.../GCMReceiver.java

Receiver code stating the necessary service (GCMIntentService) to be triggered.

public class GCMReceiver extends WakefulBroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent) {
        ComponentName comp = new ComponentName(context.getPackageName(),GCMIntentService.class.getName());
        startWakefulService(context, (intent.setComponent(comp)));
        setResultCode(Activity.RESULT_OK);
    }
}

Update Androidmanifest

app/src/main/Androidmanifest.xml

<receiver
    android:name=".GCMReceiver"
    android:exported="true"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="com.example.gcm" />
    </intent-filter>
</receiver>

src/main/java/.../GCMReceiver.java

Service code for handling the notifications part. Here MESSAGE_KEY is the expected key that is set from the server.

public class GCMIntentService extends IntentService {
    String MESSAGE_KEY = "key1";
    public GCMIntentService() {
        super("Message");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        String message = intent.getStringExtra(MESSAGE_KEY);
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        String messageType = gcm.getMessageType(intent);
        final int notificationID = (int) (Math.random() * 100000000);

        if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType)) {
            sendNotification("GCM notification: Send error" + extras.toString(), notificationID);
        }else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType)) {
            sendNotification("Deleted messages on server" + extras.toString(), notificationID);
        }else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
            sendNotification(message, notificationID);
        }
        GCMReceiver.completeWakefulIntent(intent);
    }

    private void sendNotification(String msg, int notificationID) {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
        .setSmallIcon(R.drawable.common_ic_googleplayservices);
        .setContentTitle("Notification");
        .setContentText(msg);
        Intent resultIntent = new Intent(this, MainActivity.class);
        PendingIntent resultPendingIntent = PendingIntent.getActivity(this,0,resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        NotificationManager mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        mNotifyMgr.notify(notificationID, builder.build());
    }
}

Update Androidmanifest

app/src/main/Androidmanifest.xml

<service
    android:name=".GCMIntentService"
    android:exported="false" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    </intent-filter>
</service>

Now we are ready to check if our GCM component is working. Run the app in a device connected to internet, and open your server project folder from termial. Run node node-gcm-sample.js.Source code for Android Client and Node Server

Blog Logo

Shrikanth


Published

Image

Blog

How did I do

Back to Overview