Wednesday, 14 October 2015

Push Notification using GCM in Android Studio | Google Cloud Messaging

Hey guys today i am going to share with you push notification using google cloud messaging.  I will teach you how to register your app on Google Cloud Messaging (gcm) server and get registration id from google.


In this post i am going to share with you only android side coding. we will do it in step by step. we are going to follow these steps:

  1. First of all you need to create a project on Google Developer Console.
  2. Enable Google Cloud messaging api
  3. Generate Server key copy and same time you get a project number of project copy and save both for further use.
  4. Register your app from android using that project number  i have discussed already
  5. Google will return a registration ID send this ID to your server
  6. Send message from your server to gcm to corresponding registrartion ID
  7. Gcm will send you push msg get it through BroadCast Reciever and show it as a notification and you are done.


  I have created a architecture for complete process of push notification using Google Cloud Messaging.



Now Lets Start with code. First of all go to Google Developer Console or  click on below link.


 Sign in with your google account and create new project as you can see in below picture.


Enable Google cloud messaging for android as you can see in below picture.


Click on credentials and click on Add credentials and select server key after messing with this you can see your server API KEY like below picture.


Click on Home where you can find your project number or project ID like below picture.


In above picture project number is 1037583112903.
Now we are done with one phase.  Now Lets start with android side programming . I will take you through easiest way so just follow below steps.
  • Create a new project in android studio or start with existing project.
  • Add gcm library to your build.gradle file like below picture.

compile 'com.google.android.gms:play-services:8.1.0'


  •  Now add Gcm permissions to manifest file as Your app will need to have the ability to make Internet connection and request wake locks. Wake locks are needed so that the receiving GCM service that you will implement will be able to receive the full payload before the devices goes to sleep.  

  <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" />  

  •  Now copy  GCMClientManager.java class from below and add this class to your project. 

 GCMClientManager.java
 import android.app.Activity;  
 import android.content.Context;  
 import android.content.SharedPreferences;  
 import android.content.pm.PackageInfo;  
 import android.content.pm.PackageManager.NameNotFoundException;  
 import android.os.AsyncTask;  
 import android.util.Log;  
 import com.google.android.gms.common.ConnectionResult;  
 import com.google.android.gms.common.GooglePlayServicesUtil;  
 import com.google.android.gms.gcm.GoogleCloudMessaging;  
 import com.google.android.gms.iid.InstanceID;  
 import java.io.IOException;  
 public class GCMClientManager {  
      // Constants  
      public static final String TAG = "GCMClientManager";  
      public static final String EXTRA_MESSAGE = "message";  
      public static final String PROPERTY_REG_ID = "registration_id";  
      private static final String PROPERTY_APP_VERSION = "appVersion";  
      private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;   
      // Member variables  
      private GoogleCloudMessaging gcm;  
      private String regid;  
      private String projectNumber;  
      private Activity activity;  
      public GCMClientManager(Activity activity, String projectNumber) {  
       this.activity = activity;  
       this.projectNumber = projectNumber;  
       this.gcm = GoogleCloudMessaging.getInstance(activity);  
      }  
      /**  
       * @return Application's version code from the {@code PackageManager}.  
       */  
      private static int getAppVersion(Context context) {  
        try {  
          PackageInfo packageInfo = context.getPackageManager()  
              .getPackageInfo(context.getPackageName(), 0);  
          return packageInfo.versionCode;  
        } catch (NameNotFoundException e) {  
          // should never happen  
          throw new RuntimeException("Could not get package name: " + e);  
        }  
      }  
      // Register if needed or fetch from local store  
      public void registerIfNeeded(final RegistrationCompletedHandler handler) {  
       if (checkPlayServices()) {  
         regid = getRegistrationId(getContext());  
         if (regid.isEmpty()) {  
           registerInBackground(handler);  
         } else { // got id from cache  
              Log.i(TAG, regid);  
              handler.onSuccess(regid, false);  
         }        
       } else { // no play services  
         Log.i(TAG, "No valid Google Play Services APK found.");  
       }  
      }  
     /**  
      * Registers the application with GCM servers asynchronously.  
      * <p>  
      * Stores the registration ID and app versionCode in the application's  
      * shared preferences.  
     */  
      private void registerInBackground(final RegistrationCompletedHandler handler) {  
           new AsyncTask<Void, Void, String>() {  
                @Override  
                protected String doInBackground(Void... params) {  
                     try {  
                          if (gcm == null) {  
                               gcm = GoogleCloudMessaging.getInstance(getContext());  
                          }  
                          InstanceID instanceID = InstanceID.getInstance(getContext());  
                     regid = instanceID.getToken(projectNumber, GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);  
                          Log.i(TAG, regid);  
                          // Persist the regID - no need to register again.  
                          storeRegistrationId(getContext(), regid);  
                     } catch (IOException ex) {  
                          // If there is an error, don't just keep trying to register.  
                          // Require the user to click a button again, or perform  
                          // exponential back-off.  
                          handler.onFailure("Error :" + ex.getMessage());  
                     }  
                     return regid;  
                }  
                @Override  
                protected void onPostExecute(String regId) {  
                  if (regId != null) {  
                    handler.onSuccess(regId, true);  
                  }  
                }  
           }.execute(null, null, null);  
      }  
      /**  
       * Gets the current registration ID for application on GCM service.  
       * <p>  
       * If result is empty, the app needs to register.  
       *  
       * @return registration ID, or empty string if there is no existing  
       *     registration ID.  
       */  
      private String getRegistrationId(Context context) {  
        final SharedPreferences prefs = getGCMPreferences(context);  
        String registrationId = prefs.getString(PROPERTY_REG_ID, "");  
        if (registrationId.isEmpty()) {  
          Log.i(TAG, "Registration not found.");  
          return "";  
        }  
        // Check if app was updated; if so, it must clear the registration ID  
        // since the existing regID is not guaranteed to work with the new  
        // app version.  
        int registeredVersion = prefs.getInt(PROPERTY_APP_VERSION, Integer.MIN_VALUE);  
        int currentVersion = getAppVersion(context);  
        if (registeredVersion != currentVersion) {  
          Log.i(TAG, "App version changed.");  
          return "";  
        }  
        return registrationId;  
      }  
      /**  
       * Stores the registration ID and app versionCode in the application's  
       * {@code SharedPreferences}.  
       *  
       * @param context application's context.  
       * @param regId registration ID  
       */  
      private void storeRegistrationId(Context context, String regId) {  
        final SharedPreferences prefs = getGCMPreferences(context);  
        int appVersion = getAppVersion(context);  
        Log.i(TAG, "Saving regId on app version " + appVersion);  
        SharedPreferences.Editor editor = prefs.edit();  
        editor.putString(PROPERTY_REG_ID, regId);  
        editor.putInt(PROPERTY_APP_VERSION, appVersion);  
        editor.commit();   
      }  
      private SharedPreferences getGCMPreferences(Context context) {  
        // This sample app persists the registration ID in shared preferences, but  
        // how you store the regID in your app is up to you.  
        return getContext().getSharedPreferences(context.getPackageName(),  
            Context.MODE_PRIVATE);  
      }  
      /**  
       * Check the device to make sure it has the Google Play Services APK. If  
       * it doesn't, display a dialog that allows users to download the APK from  
       * the Google Play Store or enable it in the device's system settings.  
       */  
      private boolean checkPlayServices() {  
        int resultCode = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getContext());  
        if (resultCode != ConnectionResult.SUCCESS) {  
          if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {  
            GooglePlayServicesUtil.getErrorDialog(resultCode, getActivity(),  
                PLAY_SERVICES_RESOLUTION_REQUEST).show();  
          } else {  
            Log.i(TAG, "This device is not supported.");  
          }  
          return false;  
        }  
        return true;  
      }  
      private Context getContext() {  
           return activity;  
      }  
      private Activity getActivity() {  
           return activity;  
      }  
      public static abstract class RegistrationCompletedHandler {  
           public abstract void onSuccess(String registrationId, boolean isNewRegistration);  
           public void onFailure(String ex) {  
             // If there is an error, don't just keep trying to register.  
             // Require the user to click a button again, or perform  
             // exponential back-off.  
             Log.e(TAG, ex);  
           }  
      }  

This class takes project number from you and register your app with gcm client and save registeration ID to shared prefrences. 
  • Now we will make object of above class and pass two parameter to constructor , Context and project number and call a method registerIfNeeded in your MainActivity or from where you want to register. like below code.

 Making object 
GcmClientManager class , pushClientManager and calling method registerIfNeeded of GcmClientManager.

 String PROJECT_NUMBER="your project number";
 GCMClientManager pushClientManager = new GCMClientManager(this, PROJECT_NUMBER);  
     pushClientManager.registerIfNeeded(new GCMClientManager.RegistrationCompletedHandler() {  
       @Override  
       public void onSuccess(String registrationId, boolean isNewRegistration) {  
         
         Log.d("Registration id",registrationId);  
         //send this registrationId to your server
       }  
       @Override  
       public void onFailure(String ex) {  
         super.onFailure(ex);  
       }  
     });  

As in above code you can see when you call registerIfNeeded method you pass



GCMClientManager.RegistrationCompletedHandler()  

as parameter and it will implement two method onSuccess and onFailure.In onSuccess you get registeration ID. Send this registeration ID to your server from onSuccess method. 

Now we will create a service to receive push message from gcm. so create a new java class in my case name is PushNotification.java and extend GcmListenerServiceGcmListenerService will implement a method onMessageRecieved like below code .


 public class PushNotificationService extends GcmListenerService {  
   @Override  
   public void onMessageReceived(String from, Bundle data) {  
     String message = data.getString("message");  
     //createNotification(mTitle, push_msg);  
   }  
 }  

In onMessageReceived method you can extract data from bundle like above code  and create Notification according to your need. 
Now we need to complete last part in which we will add service and Broadcast Receiver to manifest file.

Add your service to Manifest file like below code.

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

Add gcm Broadcast Receiver to manifest file like below code.

 <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="Your Package Name" />  
       </intent-filter>  
     </receiver>  

Finally we have completed this tutorial. If you are still facing any problem feel free to comment below.

http://www.mediafire.com/download/l62aw7vqbb7e3a4/GcmDemo.zip

6 comments:

  1. after we create GCMClientManager then what class bellow it???

    ReplyDelete
  2. From MainActivity you call method of GcmClientManager registerIfNeeded(). which returns you Registeration id in onSuccess.

    ReplyDelete
  3. are you talking about PushNotification service class ?? this class is used to handle your push notification comes from google

    ReplyDelete
  4. after we create GCMClientManager then what class bellow it???

    ReplyDelete