Implementing Android Push Notification using GCM


Sending Push notification is one of the important features of an mobile application.Most of the marketing things  happens the way push notifications are sent. Polling is quite hard on server as it may miss to update.To solve this we need push notification from server and here GCM (Google cloud messaging) help us.
Google Cloud Messaging is a free service from Google to send push notifications to device on demand.Enabling GCM to your application:
There are two part of it. The first part will show how to setup GCM in android Studio. Enabling and testing basic client side push notifications in android.


Installing Necessary Dependencies and plugins:
Before we get start to code we need to install the basic required dependencies and plugin to Project and Apps (build.gradle)
Adding the playservice dependencies to Module(App) build.gradle
compile "com.google.android.gms:play-services:8.3.0"
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'

android {
    compileSdkVersion 'Google Inc.:Google APIs:23'
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "info.androidhive.gcm"
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.+'
    compile 'com.android.support:design:23.+'
    compile "com.google.android.gms:play-services:8.3.0"
}

Adding the global dependencies to project module.

One more important change is, open build.gradle located in root directory of the project and add
classpath ‘com.google.gms:google-services:1.5.0-beta2’

classpath ‘com.android.tools.build:gradle:2.0.0-alpha6’ in dependency and clean the project from Build => Clean Project.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.0.0-alpha6'
        classpath 'com.google.gms:google-services:1.5.0-beta2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}



Getting the configuration file Googleservice.json 

Generate the necessary configuration to GCM from google developer site which will identify the provide you with necessary api servce key and automatically enable the GCM api in developer console.

Adding the configuration file to the project
Once the configuration gets completed download the Googleservice.json to your local path 
Copy the Googleservice.json files to App folders

Note Copy the Apps secret and app id which will use later while testing the GCM notification.
Once the setup is completed we are ready to put some code to get the things working!.
Create a RegistrationService class name as GCMRegistrationIntentService.java
This class will fetch the required token to authenticate from server.

package androidgreeve.android.com.gcmpushnotify;

import android.app.IntentService;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;

import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.google.android.gms.iid.InstanceID;

/**
 * Created by venkatesh on 15-05-2016.
 */
public class GCMRegistrationIntentService extends IntentService {
    //Assigning success and failure Messages
    public static final String REGISTRATION_SUCCESS = "RegistrationSuccess";
    public static final String REGISTRATION_ERROR = "RegistrationError";

    public GCMRegistrationIntentService() {
        super("");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        registerGCM();
    }

    private void registerGCM() {
        Intent registrationComplete = null;
        String token = null;
        try {
            InstanceID instanceID = InstanceID.getInstance(getApplicationContext());
            token = instanceID.getToken(getString(R.string.gcm_defaultSenderId), GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);
            Log.w("GCMRegIntentService", "token:" + token);
            //notify to UI that registration complete success
            registrationComplete = new Intent(REGISTRATION_SUCCESS);
            registrationComplete.putExtra("token", token);
        } catch (Exception e) {
            Log.w("GCMRegIntentService", "Registration error"+e);
            registrationComplete = new Intent(REGISTRATION_ERROR);
        }
        //Send broadcast
        LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);
    }
}


Create a RefreshTokenListener class name it as GCMTokenRefreshListenerService.java


package androidgreeve.android.com.gcmpushnotify;

import android.content.Intent;
import com.google.android.gms.iid.InstanceIDListenerService;


/**
 * Created by venkatesh on 15-05-2016.
 */
public class GCMTokenRefreshListenerService extends InstanceIDListenerService {
    /**
     * When token refresh, start service to get new token
     */
    @Override
    public void onTokenRefresh() {
        Intent intent;
        intent = new Intent(this, GCMRegistrationIntentService.class);
        startService(intent);
    }
}

Adding the PushReceiver which will send the required notification with the specified token.
Create a class GCMPushReceiverService.java file and paste the below code it.
package androidgreeve.android.com.gcmpushnotify;

import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;

import com.google.android.gms.gcm.GcmListenerService;

/**
 * Created by venkatesh on 15-05-2016.
 */
public class GCMPushReceiverService extends GcmListenerService {
    @Override
    public void onMessageReceived(String from, Bundle data) {
        String message = data.getString("message");
        sendNotification(message);
    }
    private void sendNotification(String message) {
        Intent intent = new Intent(this, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        int requestCode = 0;//Your request code
        PendingIntent pendingIntent = PendingIntent.getActivity(this, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
        //Setup notification
        //Sound
        Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        //Build notification
        NotificationCompat.Builder noBuilder = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentText("My GCM message :X:X")
                .setContentText(message)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent);

        NotificationManager notificationManager = (NotificationManager)getSystemService
(Context.NOTIFICATION_SERVICE);
        notificationManager.notify(0, noBuilder.build()); //0 = ID of notification
    }
}


Making the things done with Mainactivity , the main class which will communicate and generate the notify the device with notifications. 
Copy and paste the code in MainActivity.java
package androidgreeve.android.com.gcmpushnotify;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;

/**
 * Created by venkatesh on 15-05-2016.
 */
public class MainActivity extends Activity {
    private BroadcastReceiver mRegistrationBroadcastReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRegistrationBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                //Check type of intent filter
                if(intent.getAction().equals(GCMRegistrationIntentService.REGISTRATION_SUCCESS)){
                    //Registration success
                    String token = intent.getStringExtra("token");
                    Toast.makeText(getApplicationContext(), "GCM token:" + token, Toast.LENGTH_LONG).show();
                } else if(intent.getAction().equals(GCMRegistrationIntentService.REGISTRATION_ERROR)){
                    //Registration error
                    Toast.makeText(getApplicationContext(), "GCM registration error!!!", Toast.LENGTH_LONG).show();
                } else {
                    //Tobe define
                }
            }
        };

        //Check status of Google play service in device
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getApplicationContext());
        if(ConnectionResult.SUCCESS != resultCode) {
            //Check type of error
            if(GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
                Toast.makeText(getApplicationContext(), "Google Play Service is not install/enabled in this device!", Toast.LENGTH_LONG).show();
                //So notification
                GooglePlayServicesUtil.showErrorNotification(resultCode, getApplicationContext());
            } else {
                Toast.makeText(getApplicationContext(), "This device does not support for Google Play Service!", Toast.LENGTH_LONG).show();
            }
        } else {
            //Start service
            Intent itent = new Intent(this, GCMRegistrationIntentService.class);
            startService(itent);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.w("MainActivity", "onResume");
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(GCMRegistrationIntentService.REGISTRATION_SUCCESS));
        LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,
                new IntentFilter(GCMRegistrationIntentService.REGISTRATION_ERROR));
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.w("MainActivity", "onPause");
        LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);
    }
}


Adding the permission to manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="androidgreeve.android.com.gcmpushnotify">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

    <permission
        android:name="androidgreeve.android.com.gcmpushnotify.permission.C2D_MESSAGE"
        android:protectionLevel="signature" />
    <uses-permission android:name="androidgreeve.android.com.gcmpushnotify.permission.C2D_MESSAGE" />


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <receiver
            android:name="com.google.android.gms.gcm.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="androidgreeve.android.com.gcmpushnotify"/>
            </intent-filter>
        </receiver>
        <service android:name=".GCMPushReceiverService" android:exported="false">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE"/>
            </intent-filter>
        </service>
        <service android:name=".GCMRegistrationIntentService" android:exported="false">
            <intent-filter>
                <action android:name="com.google.android.gms.iid.InstanceID"/>
            </intent-filter>
        </service>
    </application>

</manifest>

Testing !
Run the app and you can find the generated token for GCM.
Open the link to test generate notification.
You need to pass the token generated,message and Api key which you generated while generating configuration file(googleservices.json)

Result
You would see a notification on your device.
If you face any issue ,Feel free to send me message of comment below.
What's Next ?
we have tested the woking of basic push notification through client side.
This post covers the complete basic to get started with push notification using GCM(Google Cloud Messaging) in android.
Next we will be trying to serve push notification through server side with the help of PHP and Mysql .
Happy Coding!

Hey I'm Venkat
Developer, Blogger, Thinker and Data scientist. nintyzeros [at] gmail.com I love the Data and Problem - An Indian Lives in US .If you have any question do reach me out via below social media