The 1st Part covers the server side implementation of the app i.e building the REST API and the server app. In this part we’ll integrate the GCM in your new / existing android app. In the 3rd part the final chat app modules will be integrated.

This article also provides you a test interface where you can test any of your gcm apps by sending a sample push notification message.

Integrating GCM In Your Project

I am also posting the project structure of the Android Project to get a clear picture file structure needed to build the final app.

android-gcm-simple-chat-app-project-structure-1

Once you got the idea of the project structure, let’s start add the gcm into your app.

1. Create a new project in Android Studio and fill all the details required. When it prompts to select a default activity, select Blank Activityand proceed.

2. The next step is downloading the google-services.json This configuration file contains google services information specific to your app. You can configure google services like cloud messaging, google analytics, admob, sign in with google in the same configuration file. But in this article, we’ll choose only the gcm.

Goto this doc and click on Get a configuration file which prompts you to fill quick app related information.

google-gcm-notification

3. On the developer console, choose the project that you previously created in Part 1, give the current project’s package nameEnable Google Cloud Messaging and click on Download google-services.json.

gcm-downloading-google-services-json

4. Add the downloaded google-services.json to your project’s app Make sure that you are placing this json file correctly under app folder. Otherwise you won’t be successful in implementing the gcm.

5. Open gradle located under applevel and do the below changes.

add apply plugin: ‘com.google.gms.google-services’ at the top.
add com.google.android.gms:play-services:8.3.0 dependency

build.gradle
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”

}

 

6. One more important change is, open gradlelocated in root directoryof 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.

build.gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.

 

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

}

 

7. Now under your project’s main package, create four packages named activityappgcmand helper. Move your main activity class into activity package.

8. Under apppackage, create a class named java. This class contains app configuration information related to gcm.

Config.java
package info.androidhive.gcm.app;

 

/**

* Created by Lincoln on 05/01/16.

*/

public class Config {

 

// flag to identify whether to show single line

// or multi line text in push notification tray

public static boolean appendNotificationMessages = true;

 

// global topic to receive app wide push notifications

public static final String TOPIC_GLOBAL = “global”;

 

// broadcast receiver intent filters

public static final String SENT_TOKEN_TO_SERVER = “sentTokenToServer”;

public static final String REGISTRATION_COMPLETE = “registrationComplete”;

public static final String PUSH_NOTIFICATION = “pushNotification”;

 

// type of push messages

public static final int PUSH_TYPE_CHATROOM = 1;

public static final int PUSH_TYPE_USER = 2;

 

// id to handle the notification in the notification try

public static final int NOTIFICATION_ID = 100;

public static final int NOTIFICATION_ID_BIG_IMAGE = 101;

}

 

9. Under helperpackage, create a class named java This class stores data in SharedPreferences. Here we temporarily stores the unread push notifications in order to append them to new messages.

MyPreferenceManager.java
package info.androidhive.gcm.helper;

 

import android.content.Context;

import android.content.SharedPreferences;

 

public class MyPreferenceManager {

 

private String TAG = MyPreferenceManager.class.getSimpleName();

 

// Shared Preferences

SharedPreferences pref;

 

// Editor for Shared preferences

SharedPreferences.Editor editor;

 

// Context

Context _context;

 

// Shared pref mode

int PRIVATE_MODE = 0;

 

// Sharedpref file name

private static final String PREF_NAME = “androidhive_gcm”;

 

// All Shared Preferences Keys

private static final String KEY_USER_ID = “user_id”;

private static final String KEY_USER_NAME = “user_name”;

private static final String KEY_USER_EMAIL = “user_email”;

private static final String KEY_NOTIFICATIONS = “notifications”;

 

// Constructor

public MyPreferenceManager(Context context) {

this._context = context;

pref = _context.getSharedPreferences(PREF_NAME, PRIVATE_MODE);

editor = pref.edit();

}

 

public void addNotification(String notification) {

 

// get old notifications

String oldNotifications = getNotifications();

 

if (oldNotifications != null) {

oldNotifications += “|” + notification;

} else {

oldNotifications = notification;

}

 

editor.putString(KEY_NOTIFICATIONS, oldNotifications);

editor.commit();

}

 

public String getNotifications() {

return pref.getString(KEY_NOTIFICATIONS, null);

}

 

public void clear() {

editor.clear();

editor.commit();

}

}

 

10. Create a class named javaunder apppackage. This is a singleton class needs to be added toAndroidManifest.xml file.

MyApplication.java
package info.androidhive.gcm.app;

import android.app.Application;

 

import info.androidhive.gcm.helper.MyPreferenceManager;

 

public class MyApplication extends Application {

 

public static final String TAG = MyApplication.class

.getSimpleName();

 

private static MyApplication mInstance;

 

private MyPreferenceManager pref;

 

@Override

public void onCreate() {

super.onCreate();

mInstance = this;

}

 

public static synchronized MyApplication getInstance() {

return mInstance;

}

 

 

public MyPreferenceManager getPrefManager() {

if (pref == null) {

pref = new MyPreferenceManager(this);

}

 

return pref;

}

}

 

11. Create a folder named raw under res. Download mp3 and paste it in res => raw folder. This is a custom notification sound which will be played whenever a new push notification is received.

12. Create a class named java under gcm package. This class is used to show the notification in notification tray. This also contains major functions like checking app’s running state (background / foreground), downloading notification image attachment from url, playing notification sound and clearing notification messages.

NotificationUtils.java
package info.androidhive.gcm.gcm;

 

import android.app.ActivityManager;

import android.app.Notification;

import android.app.NotificationManager;

import android.app.PendingIntent;

import android.content.ComponentName;

import android.content.ContentResolver;

import android.content.Context;

import android.content.Intent;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.media.Ringtone;

import android.media.RingtoneManager;

import android.net.Uri;

import android.os.Build;

import android.support.v4.app.NotificationCompat;

import android.text.Html;

import android.text.TextUtils;

import android.util.Patterns;

 

import java.io.IOException;

import java.io.InputStream;

import java.net.HttpURLConnection;

import java.net.URL;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Arrays;

import java.util.Date;

import java.util.List;

 

import info.androidhive.gcm.R;

import info.androidhive.gcm.app.Config;

import info.androidhive.gcm.app.MyApplication;

 

 

/**

* Created by Ravi on 01/06/15.

*/

public class NotificationUtils {

 

private static String TAG = NotificationUtils.class.getSimpleName();

 

private Context mContext;

 

public NotificationUtils() {

}

 

public NotificationUtils(Context mContext) {

this.mContext = mContext;

}

 

public void showNotificationMessage(String title, String message, String timeStamp, Intent intent) {

showNotificationMessage(title, message, timeStamp, intent, null);

}

 

public void showNotificationMessage(final String title, final String message, final String timeStamp, Intent intent, String imageUrl) {

// Check for empty push message

if (TextUtils.isEmpty(message))

return;

 

 

// notification icon

final int icon = R.mipmap.ic_launcher;

 

intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

final PendingIntent resultPendingIntent =

PendingIntent.getActivity(

mContext,

0,

intent,

PendingIntent.FLAG_CANCEL_CURRENT

);

 

final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(

mContext);

 

final Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE

+ “://” + mContext.getPackageName() + “/raw/notification”);

 

if (!TextUtils.isEmpty(imageUrl)) {

 

if (imageUrl != null && imageUrl.length() > 4 && Patterns.WEB_URL.matcher(imageUrl).matches()) {

 

Bitmap bitmap = getBitmapFromURL(imageUrl);

 

if (bitmap != null) {

showBigNotification(bitmap, mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);

} else {

showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);

}

}

} else {

showSmallNotification(mBuilder, icon, title, message, timeStamp, resultPendingIntent, alarmSound);

playNotificationSound();

}

}

 

 

private void showSmallNotification(NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {

 

NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();

 

if (Config.appendNotificationMessages) {

// store the notification in shared pref first

MyApplication.getInstance().getPrefManager().addNotification(message);

 

// get the notifications from shared preferences

String oldNotification = MyApplication.getInstance().getPrefManager().getNotifications();

 

List<String> messages = Arrays.asList(oldNotification.split(“\\|”));

 

for (int i = messages.size() – 1; i >= 0; i–) {

inboxStyle.addLine(messages.get(i));

}

} else {

inboxStyle.addLine(message);

}

 

 

Notification notification;

notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)

.setAutoCancel(true)

.setContentTitle(title)

.setContentIntent(resultPendingIntent)

.setSound(alarmSound)

.setStyle(inboxStyle)

.setWhen(getTimeMilliSec(timeStamp))

.setSmallIcon(R.mipmap.ic_launcher)

.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))

.setContentText(message)

.build();

 

NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(Config.NOTIFICATION_ID, notification);

}

 

private void showBigNotification(Bitmap bitmap, NotificationCompat.Builder mBuilder, int icon, String title, String message, String timeStamp, PendingIntent resultPendingIntent, Uri alarmSound) {

NotificationCompat.BigPictureStyle bigPictureStyle = new NotificationCompat.BigPictureStyle();

bigPictureStyle.setBigContentTitle(title);

bigPictureStyle.setSummaryText(Html.fromHtml(message).toString());

bigPictureStyle.bigPicture(bitmap);

Notification notification;

notification = mBuilder.setSmallIcon(icon).setTicker(title).setWhen(0)

.setAutoCancel(true)

.setContentTitle(title)

.setContentIntent(resultPendingIntent)

.setSound(alarmSound)

.setStyle(bigPictureStyle)

.setWhen(getTimeMilliSec(timeStamp))

.setSmallIcon(R.mipmap.ic_launcher)

.setLargeIcon(BitmapFactory.decodeResource(mContext.getResources(), icon))

.setContentText(message)

.build();

 

NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.notify(Config.NOTIFICATION_ID_BIG_IMAGE, notification);

}

 

/**

* Downloading push notification image before displaying it in

* the notification tray

*/

public Bitmap getBitmapFromURL(String strURL) {

try {

URL url = new URL(strURL);

HttpURLConnection connection = (HttpURLConnection) url.openConnection();

connection.setDoInput(true);

connection.connect();

InputStream input = connection.getInputStream();

Bitmap myBitmap = BitmapFactory.decodeStream(input);

return myBitmap;

} catch (IOException e) {

e.printStackTrace();

return null;

}

}

 

// Playing notification sound

public void playNotificationSound() {

try {

Uri alarmSound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE

+ “://” + MyApplication.getInstance().getApplicationContext().getPackageName() + “/raw/notification”);

Ringtone r = RingtoneManager.getRingtone(MyApplication.getInstance().getApplicationContext(), alarmSound);

r.play();

} catch (Exception e) {

e.printStackTrace();

}

}

 

/**

* Method checks if the app is in background or not

*/

public static boolean isAppIsInBackground(Context context) {

boolean isInBackground = true;

ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {

List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();

for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {

if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {

for (String activeProcess : processInfo.pkgList) {

if (activeProcess.equals(context.getPackageName())) {

isInBackground = false;

}

}

}

}

} else {

List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);

ComponentName componentInfo = taskInfo.get(0).topActivity;

if (componentInfo.getPackageName().equals(context.getPackageName())) {

isInBackground = false;

}

}

 

return isInBackground;

}

 

// Clears notification tray messages

public static void clearNotifications() {

NotificationManager notificationManager = (NotificationManager) MyApplication.getInstance().getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.cancelAll();

}

 

public static long getTimeMilliSec(String timeStamp) {

SimpleDateFormat format = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);

try {

Date date = format.parse(timeStamp);

return date.getTime();

} catch (ParseException e) {

e.printStackTrace();

}

return 0;

}

}

 

13. Create a class named javaunder gcmpackage. This service extends IntentService which acts as a background service. This service basically used for three purposes.

> To connect with gcm server and fetch the registration token. Uses registerGCM() method.

> Subscribe to a topic. Uses subscribeToTopic(“topic”) method.

> Unsubscribe from a topic. Uses unsubscribeFromTopic(“topic”) method.

GcmIntentService.java
package info.androidhive.gcm.gcm;

 

import android.app.IntentService;

import android.content.Intent;

import android.content.SharedPreferences;

import android.preference.PreferenceManager;

import android.support.v4.content.LocalBroadcastManager;

import android.util.Log;

import android.widget.Toast;

 

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

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

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

 

import java.io.IOException;

 

import info.androidhive.gcm.R;

import info.androidhive.gcm.app.Config;

 

 

public class GcmIntentService extends IntentService {

 

private static final String TAG = GcmIntentService.class.getSimpleName();

 

public GcmIntentService() {

super(TAG);

}

 

public static final String KEY = “key”;

public static final String TOPIC = “topic”;

public static final String SUBSCRIBE = “subscribe”;

public static final String UNSUBSCRIBE = “unsubscribe”;

 

 

@Override

protected void onHandleIntent(Intent intent) {

String key = intent.getStringExtra(KEY);

switch (key) {

case SUBSCRIBE:

// subscribe to a topic

String topic = intent.getStringExtra(TOPIC);

subscribeToTopic(topic);

break;

case UNSUBSCRIBE:

String topic1 = intent.getStringExtra(TOPIC);

unsubscribeFromTopic(topic1);

break;

default:

// if key is not specified, register with GCM

registerGCM();

}

 

}

 

/**

* Registering with GCM and obtaining the gcm registration id

*/

private void registerGCM() {

SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);

String token = null;

 

try {

InstanceID instanceID = InstanceID.getInstance(this);

token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),

GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

 

Log.e(TAG, “GCM Registration Token: ” + token);

 

// sending the registration id to our server

sendRegistrationToServer(token);

 

sharedPreferences.edit().putBoolean(Config.SENT_TOKEN_TO_SERVER, true).apply();

} catch (Exception e) {

Log.e(TAG, “Failed to complete token refresh”, e);

 

sharedPreferences.edit().putBoolean(Config.SENT_TOKEN_TO_SERVER, false).apply();

}

// Notify UI that registration has completed, so the progress indicator can be hidden.

Intent registrationComplete = new Intent(Config.REGISTRATION_COMPLETE);

registrationComplete.putExtra(“token”, token);

LocalBroadcastManager.getInstance(this).sendBroadcast(registrationComplete);

}

 

private void sendRegistrationToServer(final String token) {

// Send the registration token to our server

// to keep it in MySQL

 

}

 

/**

* Subscribe to a topic

*/

public void subscribeToTopic(String topic) {

GcmPubSub pubSub = GcmPubSub.getInstance(getApplicationContext());

InstanceID instanceID = InstanceID.getInstance(getApplicationContext());

String token = null;

try {

token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),

GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

if (token != null) {

pubSub.subscribe(token, “/topics/” + topic, null);

Log.e(TAG, “Subscribed to topic: ” + topic);

} else {

Log.e(TAG, “error: gcm registration id is null”);

}

} catch (IOException e) {

Log.e(TAG, “Topic subscribe error. Topic: ” + topic + “, error: ” + e.getMessage());

Toast.makeText(getApplicationContext(), “Topic subscribe error. Topic: ” + topic + “, error: ” + e.getMessage(), Toast.LENGTH_SHORT).show();

}

}

 

public void unsubscribeFromTopic(String topic) {

GcmPubSub pubSub = GcmPubSub.getInstance(getApplicationContext());

InstanceID instanceID = InstanceID.getInstance(getApplicationContext());

String token = null;

try {

token = instanceID.getToken(getString(R.string.gcm_defaultSenderId),

GoogleCloudMessaging.INSTANCE_ID_SCOPE, null);

if (token != null) {

pubSub.unsubscribe(token, “”);

Log.e(TAG, “Unsubscribed from topic: ” + topic);

} else {

Log.e(TAG, “error: gcm registration id is null”);

}

} catch (IOException e) {

Log.e(TAG, “Topic unsubscribe error. Topic: ” + topic + “, error: ” + e.getMessage());

Toast.makeText(getApplicationContext(), “Topic subscribe error. Topic: ” + topic + “, error: ” + e.getMessage(), Toast.LENGTH_SHORT).show();

}

}

}

 

14. Create a class named javaunder gcmpackage. This service invokesonTokenRefresh() method whenever there is a change in gcm registration token.

MyInstanceIDListenerService.java
package info.androidhive.gcm.gcm;

 

import android.content.Intent;

import android.util.Log;

 

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

 

public class MyInstanceIDListenerService extends InstanceIDListenerService {

 

private static final String TAG = MyInstanceIDListenerService.class.getSimpleName();

 

/**

* Called if InstanceID token is updated. This may occur if the security of

* the previous token had been compromised. This call is initiated by the

* InstanceID provider.

*/

@Override

public void onTokenRefresh() {

Log.e(TAG, “onTokenRefresh”);

// Fetch updated Instance ID token and notify our app’s server of any changes (if applicable).

Intent intent = new Intent(this, GcmIntentService.class);

startService(intent);

}

}

 

15. Create a class javaunder gcmpackage. This is a receiver class in whichonMessageReceived() method will be triggered whenever device receives new push notification.

MyGcmPushReceiver.java
package info.androidhive.gcmtest.gcm;

 

import android.content.Context;

import android.content.Intent;

import android.os.Bundle;

import android.support.v4.content.LocalBroadcastManager;

import android.text.TextUtils;

import android.util.Log;

 

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

 

import info.androidhive.gcmtest.activity.MainActivity;

import info.androidhive.gcmtest.app.Config;

 

public class MyGcmPushReceiver extends GcmListenerService {

 

private static final String TAG = MyGcmPushReceiver.class.getSimpleName();

 

private NotificationUtils notificationUtils;

 

/**

* Called when message is received.

*

* @param from   SenderID of the sender.

* @param bundle Data bundle containing message data as key/value pairs.

*               For Set of keys use data.keySet().

*/

 

@Override

public void onMessageReceived(String from, Bundle bundle) {

String title = bundle.getString(“title”);

String message = bundle.getString(“message”);

String image = bundle.getString(“image”);

String timestamp = bundle.getString(“created_at”);

Log.e(TAG, “From: ” + from);

Log.e(TAG, “Title: ” + title);

Log.e(TAG, “message: ” + message);

Log.e(TAG, “image: ” + image);

Log.e(TAG, “timestamp: ” + timestamp);

 

if (!NotificationUtils.isAppIsInBackground(getApplicationContext())) {

 

// app is in foreground, broadcast the push message

Intent pushNotification = new Intent(Config.PUSH_NOTIFICATION);

pushNotification.putExtra(“message”, message);

LocalBroadcastManager.getInstance(this).sendBroadcast(pushNotification);

 

// play notification sound

NotificationUtils notificationUtils = new NotificationUtils();

notificationUtils.playNotificationSound();

} else {

 

Intent resultIntent = new Intent(getApplicationContext(), MainActivity.class);

resultIntent.putExtra(“message”, message);

 

if (TextUtils.isEmpty(image)) {

showNotificationMessage(getApplicationContext(), title, message, timestamp, resultIntent);

} else {

showNotificationMessageWithBigImage(getApplicationContext(), title, message, timestamp, resultIntent, image);

}

}

}

 

/**

* Showing notification with text only

*/

private void showNotificationMessage(Context context, String title, String message, String timeStamp, Intent intent) {

notificationUtils = new NotificationUtils(context);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

notificationUtils.showNotificationMessage(title, message, timeStamp, intent);

}

 

/**

* Showing notification with text and image

*/

private void showNotificationMessageWithBigImage(Context context, String title, String message, String timeStamp, Intent intent, String imageUrl) {

notificationUtils = new NotificationUtils(context);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

notificationUtils.showNotificationMessage(title, message, timeStamp, intent, imageUrl);

}

}

 

16. Open xmland do the below necessary changes.

> Add MyApplication to <application> tag using name attribute

> Add INTERNETWAKE_LOCKGET_TASKS and C2D_MESSAGE permissions.

> Add MyGcmPushReceiver & GcmIntentService as services and GcmReceiver as receiver.

> Replace info.androidhive.gcm with your current project’s package name.

AndroidManifest.xml
<?xml version=”1.0″ encoding=”utf-8″?>

<manifest xmlns:android=”http://schemas.android.com/apk/res/android

package=”info.androidhive.gcm”>

 

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

 

<!– needed for older devices –

used to check app background / foreground status –>

<uses-permission android:name=”android.permission.GET_TASKS” />

 

<!– START Added for GCM –>

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

<permission

android:name=”info.androidhive.gcm.permission.C2D_MESSAGE”

android:protectionLevel=”signature” />

 

<uses-permission android:name=”info.androidhive.gcm.permission.C2D_MESSAGE” />

<!– END Added for GCM –>

 

<application

android:allowBackup=”true”

android:name=”.app.MyApplication”

android:icon=”@mipmap/ic_launcher”

android:label=”@string/app_name”

android:supportsRtl=”true”

android:theme=”@style/AppTheme”>

<activity

android:name=”.activity.MainActivity”

android:label=”@string/app_name”

android:theme=”@style/AppTheme.NoActionBar”>

<intent-filter>

<action android:name=”android.intent.action.MAIN” />

 

<category android:name=”android.intent.category.LAUNCHER” />

</intent-filter>

</activity>

 

 

<!– START Added for GCM –>

<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=”info.androidhive.gcm” />

</intent-filter>

</receiver>

 

<service

android:name=”.gcm.MyGcmPushReceiver”

android:exported=”false”>

<intent-filter>

<action android:name=”com.google.android.c2dm.intent.RECEIVE” />

</intent-filter>

</service>

 

<service

android:name=”.gcm.GcmIntentService”

android:exported=”false”>

<intent-filter>

<action android:name=”com.google.android.gms.iid.InstanceID” />

</intent-filter>

</service>

 

<!– END Added for GCM –>

 

</application>

 

</manifest>

 

17. Finally open javaand make the following changes.

> In order to receive the push notifications, device has to support google play services. So checkPlayServices()method is used to check the availability of google play services. If the play services are not available, we’ll simply close the app.

> Register a broadcast receiver in onResume() method for both REGISTRATION_COMPLETE andPUSH_NOTIFICATION intent filters.

> Unregister the broadcast receiver in onPause() method.

> Create an instance of broadcast receiver in onCreate() method in which onReceive() method will be triggered whenever gcm registration process is completed and a new push message is received.

MainActivity.java
package info.androidhive.gcm.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.support.v7.app.AppCompatActivity;

import android.support.v7.widget.Toolbar;

import android.util.Log;

import android.widget.Toast;

 

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

import com.google.android.gms.common.GoogleApiAvailability;

 

import info.androidhive.gcm.R;

import info.androidhive.gcm.app.Config;

import info.androidhive.gcm.gcm.GcmIntentService;

 

public class MainActivity extends AppCompatActivity {

 

private String TAG = MainActivity.class.getSimpleName();

private static final int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

private BroadcastReceiver mRegistrationBroadcastReceiver;

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

setSupportActionBar(toolbar);

 

mRegistrationBroadcastReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

 

// checking for type intent filter

if (intent.getAction().equals(Config.REGISTRATION_COMPLETE)) {

// gcm successfully registered

// now subscribe to `global` topic to receive app wide notifications

String token = intent.getStringExtra(“token”);

 

Toast.makeText(getApplicationContext(), “GCM registration token: ” + token, Toast.LENGTH_LONG).show();

 

} else if (intent.getAction().equals(Config.SENT_TOKEN_TO_SERVER)) {

// gcm registration id is stored in our server’s MySQL

 

Toast.makeText(getApplicationContext(), “GCM registration token is stored in server!”, Toast.LENGTH_LONG).show();

 

} else if (intent.getAction().equals(Config.PUSH_NOTIFICATION)) {

// new push notification is received

 

Toast.makeText(getApplicationContext(), “Push notification is received!”, Toast.LENGTH_LONG).show();

}

}

};

 

if (checkPlayServices()) {

registerGCM();

}

}

 

// starting the service to register with GCM

private void registerGCM() {

Intent intent = new Intent(this, GcmIntentService.class);

intent.putExtra(“key”, “register”);

startService(intent);

}

 

private boolean checkPlayServices() {

GoogleApiAvailability apiAvailability = GoogleApiAvailability.getInstance();

int resultCode = apiAvailability.isGooglePlayServicesAvailable(this);

if (resultCode != ConnectionResult.SUCCESS) {

if (apiAvailability.isUserResolvableError(resultCode)) {

apiAvailability.getErrorDialog(this, resultCode, PLAY_SERVICES_RESOLUTION_REQUEST)

.show();

} else {

Log.i(TAG, “This device is not supported. Google Play Services not installed!”);

Toast.makeText(getApplicationContext(), “This device is not supported. Google Play Services not installed!”, Toast.LENGTH_LONG).show();

finish();

}

return false;

}

return true;

}

 

@Override

protected void onResume() {

super.onResume();

 

// register GCM registration complete receiver

LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,

new IntentFilter(Config.REGISTRATION_COMPLETE));

 

// register new push message receiver

// by doing this, the activity will be notified each time a new message arrives

LocalBroadcastManager.getInstance(this).registerReceiver(mRegistrationBroadcastReceiver,

new IntentFilter(Config.PUSH_NOTIFICATION));

}

 

@Override

protected void onPause() {

LocalBroadcastManager.getInstance(this).unregisterReceiver(mRegistrationBroadcastReceiver);

super.onPause();

}

}

Now run & deploy the app on a device. Make sure that your device is having internet connection and you followed the above steps correctly. After the app is launched, you should able see the gcm registration token as a Toast message. You can also find the registration token in LogCat.

gcm-registration-token

Testing Push Notifications

In order to test the push notifications, I have created a simple interface where you can type a sample message and send it to devices. Note that the sensitive information (API key & registration token) you are providing is not stored on the server in any manner. Also the demo test panel works when you are following the steps explained in this article only.

1. Goto to the push notifications test panel.

2. Enter your GCM API Key that you have obtained from google developer console.

3. Enter the gcm registration token which is logged in your Android Studio LogCat.

4. Type a message and click on Send Push Notification There is also an option provided to test push notification with image attachment.

Download Full Code

Demo