Android MultiCast Push Notifications using GCM [Greeting App]

In the previous posts, I discussed What is GCM and how to send Push notifications using GCM service. In this post, I am going to develop simple Android application called Greeting App to demonstrate how to send Push notifications to multiple devices.

I would recommend you to quickly take a look at the previous posts (Read: Introduction to GCM | How to send push notifications using GCM service?) so that you will get to know about basics of GCM.

What is GCM?

Google Cloud Messaging is a free service from Google which helps us to send messages (Push notifications) to Users’ device. It can also be used to send message from Users’ device to GCM server.

Here is the video demo of the Application we are about to develop, watch it.

Video Demo

I believe you got to know about the application from video demo.

About Application

  • It is a simple android application which shows the Greeting sent by sender.
  • Once sender composed the greeting and sent it to the selected Users. Greeting will arrive in mobile devices of selected Users

How it works technically?

Greeting_App_Steps

You can download source code from here if you don’t want to create Application from scratch, otherwise please proceed with below listings.

Steps involved in sending Greeting as Push notifications:

Developing the application involves two parts:

  1. GCM Server Application – Create Web application using Php to send Greeting to User via GCM Cloud server
  2. GCM Client Application – Create Android application which receive Greeting sent from GCM Server Web App

GCM_Overview

Prerequisite

You need to have Google Project Key, API Server Key, and GCM RegId with you in order to send and receive Message.

Steps to create Google Project Key:

Goto https://console.developers.google.com/project and then create Project.

Google_Project_Creation

Enter Project name and click create, a project will be created.

Google_Project_Creation_1

You can see Project ID, note it down as it will be used in Step 4 of GCM Client Application.

Google_Project_Creation_2

Steps to create API Server Key:

Enable Google Cloud Messaging as shown below.

Google_Project_Creation_3

Create Server Key as shown below,

Google_Project_Creation_4

Enter your public address in order to white-list a set of IP addresses as the server key is mapped to IP addresses for security purpose. (Get your public IP address by googling ‘my public ip address’ in Google) and click create.

Google_Project_Creation_5

You can see SERVER_API_KEY, note it down as it will be used in Step 2 of GCM Server Application creation.

Google_Project_Creation_6

You don’t need to worry about creating GCM RegId, as it will be created inside Android application which we will discuss in some time later.

[pglinkadssmall1]

GCM Server Application

I chose PHP/MySQL combo for creating API to connect and Android device to MySQL DB since the configuration is simple and easy and also it will be easy for you to start with.

Step 1: Create DB and Table in MySQL

  1. Create database called ‘db’ in phpMyAdmin or create it through command:
    create database db
  2. Select database db in phpMyAdmin or select it through command:
    use db
  3. Create table called ‘gcmusers’ in phpMyAdmin by pasting below SQL script in SQL Query box:
    CREATE TABLE IF NOT EXISTS `gcmusers` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `emailid` varchar(50) NOT NULL,
      `gcmregid` varchar(500) NOT NULL,
      PRIMARY KEY (`id`)
    )

Step 2: Create Php files under gcmwebapp folder under Apache’s ‘www’

config.php:

Has configuration variable like DB Host, DB Username and DB Pasword.

<?php
/**
 * DB configuration variables
 */
define("DB_HOST", "localhost");
define("DB_USER", "UserName");
define("DB_PASSWORD", "PWD");
define("DB_DATABASE", "db");
?>

db_connect.php:

Has methods to open and close DB connection.

<?php

class DB_Connect {

    // constructor
    function __construct() {

    }

    // destructor
    function __destruct() {
        // $this->close();
    }

    // Connecting to database
    public function connect() {
        require_once 'config.php';
        // connecting to mysql
        $con = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
        // selecting database
        mysql_select_db(DB_DATABASE);

        // return database handler
        return $con;
    }

    // Closing database connection
    public function close() {
        mysql_close();
    }

} 
?>

db_functions.php:

Has methods to perform DB operations.

<?php

class DB_Functions {

    private $db;

    function __construct() {
        include_once './db_connect.php';
        // Connect to database
        $this->db = new DB_Connect();
        $this->db->connect();
    }
    // destructor
    function __destruct() {

    }
    /**
     * Insert new user
     * 
     */
    public function insertUser($emailId, $gcmRegId) {
        // Insert user into database
        $result = mysql_query("INSERT INTO gcmusers (emailid,gcmregid) VALUES('$emailId','$gcmRegId')");		
        if ($result) {
			return true;
        } else {			 
			return false;			          
        }
    }
	/**
     * Select all user
     * 
     */
	 public function getAllUsers() {
        $result = mysql_query("select * FROM gcmusers");
        return $result;
    }
	/**
     * Get GCMRegId
     * 
     */
	public function getGCMRegID($emailID){
		 $result = mysql_query("SELECT gcmregid FROM gcmusers WHERE emailid = "."'$emailID'");
		 return $result;
	}
}
?>

insertuser.php:

Insert User’s email id and gcm reg id in DB.

<?php
include_once './db_functions.php';
//Create Object for DB_Functions clas
$db = new DB_Functions(); 
$emailID = $_POST["emailId"];
$regId = $_POST["regId"];
$res = $db->insertUser($emailID, $regId);
echo "Email Id ".$emailID." RegId ".$regId ;
if ($res) {
	echo "GCM Reg Id bas been shared successfully with Server";
} else {			 
	echo "Error occured while sharing GCM Reg Id with Server web app";			          
}
?>

processmessage.php:

Send greeting json to selected users.

Download processmessage.php from here.

viewusers.php:

Greeting web app screen that display list of users, greeting cards etc.,

<html>
<head><title>View Users</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<style>
body {
  font: normal medium/1.4 sans-serif;
}
div.greetblock, div.serverresponse {
  border-collapse: collapse;
  width: 60%;
  margin-left: auto;
  margin-right: auto;
  align: center;
}
tr > td {
  padding: 0.25rem;
  text-align: center;
  border: 1px solid #ccc;
}
tr:nth-child(even) {
  background: #fff;

}
tr:nth-child(odd) {
  background: #FA9A8B;
  color: #fff;
}
tr#header{
background: #F78371;
}

div#norecord{
margin-top:10px;
width: 15%;
margin-left: auto;
margin-right: auto;
}
input,select{
cursor: pointer;
}
img{
margin-top: 10px;
height: 200px;
width: 300px;
}
select{
width: 200px
}
div.leftdiv{
width: 45%;
padding: 0 10px;
float: left;
border: 1px solid #ccc;
margin: 5px;
height: 320px;
text-align:center;
}
div.rightdiv{
width: 45%;
padding: 0 10px;
float: right;
border: 1px solid #ccc;
margin: 5px;
height: 320px;
text-align:center;
}
hidediv{
display: none;
}
p.header{
height: 40px;
background-color: #EB5038;
padding: 10px;
color: #fff;
text-align:center;
margin: 0;
margin-bottom: 10px;
}
textarea{
font-size: 25px;
font-weight: bold;
}

</style>
<script>
function sendMsg(){
var msgLength = $.trim($("textarea").val()).length;
var checkedCB = $("input[type='checkbox']:checked").length;
if( checkedCB == 0){
	alert("You must select atleast one User to send message");
}else if(msgLength == 0){
	alert("You left the message field blank, please fill it");
}else{
	var formData = $(".wrapper").find("input").serialize() + "&imgurl="+ $("#festival").val() + "&message=" + $("textarea").val();	
	$.ajax({type: "POST",data: formData, url: "processmessage.php", success:function(res){
		$(".greetblock").slideUp(1000);
		$(".serverresponse").prepend(res).hide().fadeIn(2000);
	}});
}
}
$(function(){
	$(".serverresponse").hide()
	$("input[type='checkbox']").click(function(){
		if($(this).is(':checked')){
			$(this).parent().css("border","3px solid red");
		}else{
			$(this).parent().css("border","0px");
		}
	});

	$("div.leftdiv, div.rightdiv").hover(function(){
		$(this).css("background","#FAFAFA");
	},function(){
		$(this).css("background","#fff");
	});

	$("#festival").change(function(){
		$("img").attr("src",$(this).val());
	});

	$("#sendmsg").click(function(){
		$(".serverresponse").fadeOut(300,function(){
			$(".greetblock").fadeIn(1000);
		});		
	});
});
</script>
</head>
<body>
<?php
    include_once 'db_functions.php';
    $db = new DB_Functions();
    $users = $db->getAllUsers();
    if ($users != false)
        $no_of_users = mysql_num_rows($users);
    else
        $no_of_users = 0;	
?>
<?php
    if ($no_of_users > 0) {
?>

<div class="greetblock">
<div class="leftdiv">
<p class="header">Select Users to whom you want to send Greeting message
</p>
<table>
<tr id="header"><td>Id</td><td>EmailId</td><td>Send Message?</td></tr>
<?php
    while ($row = mysql_fetch_array($users)) {
?> 
<tr>
<td><span><?php echo $row["id"] ?></span></td>
<td><span><?php echo $row["emailid"] ?></span></td>
<td><span class="wrapper"><input type="checkbox" name="sendmsg[]" value="<?php echo $row["emailid"] ?>"/></span></td>
</tr>
<?php } ?>
</table>
</div>
<div class="rightdiv">
<p class="header">Select Greeting Card
</p>
<select id="festival">
<option value="http://192.168.2.4:9000/gcmwebapp/img/diwali.png">Diwali</option>
<option value="http://192.168.2.4:9000/gcmwebapp/img/pongal.png">Pongal</option>
<option value="http://192.168.2.4:9000/gcmwebapp/img/christmas.png">Christmas</option>
<option value="http://192.168.2.4:9000/gcmwebapp/img/ramzan.png">Ramadan</option>
</select>
<br/>
<img src="http://192.168.2.4:9000/gcmwebapp/img/diwali.png"/>
</div>
<div class="leftdiv">
<p class="header">Type your message
</p>
<textarea cols="15" rows="5" value="txtarea">

</textarea>
</div>
<div class="rightdiv">
<p class="header">Send your customized message to your Users
</p>
<center>
<button onclick="sendMsg()">Send Message</button>
</center>
</div>
</div>
<div class="serverresponse hidediv">
<center><button id="sendmsg">Send Message Again</button></center>
</div>
<?php }else{ ?>
<div id="norecord">
No records in MySQL DB
</div>
<?php } ?>

</body>
</html>

Step 3: Update API Server Key

Update ‘API_SERVER_KEY’ in function ‘sendMessageThroughGCM’ present in processmessage.php with the one you created.

GCM Client Application

Step 1: Create Android Application Project

  • Create new android project [File >> New >> Android Application Project] with project name GCMGreetingApp
  • Enter package name as ‘com.prgguru.example’
  • Choose Minimum Required SDK, Target SDK and Compile with as shown in the below screen-print. If you don’t have latest SDK installed, they will not be populated in the dropdownlist, I would recommend you to update Android SDK manager with latest SDKs. Confused on choosing these options? Take a look at Minimum Required SDK – Target SDK – Compile With post.
  • Click Next button and finally click ‘Finish’ to create project

Step 2: Add library to project

Add below third party library into project’s ‘libs’ folder. You can also download it if you don’t have it with you.

1. Android Asynchronous Http Client – An asynchronous callback-based Http client for Android built on top of Apache’s HttpClient libraries which is used by Pinterest, Instagram etc.,. Download

Step 3: Setup Google Play Services library project

To write GCM client application, we need to use the GoogleCloudMessaging API. To use this API, we must set up the project to use the Google Play services SDK.

Take help from here to setup Google Play Service library project.

Step 4: Design Screens

We are going to have two activities:

MainActivity – Launch Screen of the Application

GreetingActivity – Greeting Screen of the Application

Before creating the layouts, make sure below resources are added.

Add string resources to strings.xml present under /res/values folder.

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">GCMGreetingApp</string>
    <string name="hello_world">Hello world!</string>
    <string name="action_settings">Settings</string>
    <string name="welcome">GCM Greeting App</string>
    <string name="email">Email Address</string>
    <string name="login">Register Me</string>
    <string name="signup">Don't have account? Sign Up</string>
    <string name="defaultmsg">Message sent by server will appear here.</string>
    <string name="msg_title">Message</string>
    <string name="user_title">Hello User</string>

</resources>

Add dimension resource to dimens.xml present under /res/values folder.

dimens.xml

<resources>

    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>

</resources>

Add color resources to colors.xml present under /res/values folder.

colors.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="white">#ffffff</color>
    <color name="black">#000000</color>
    <color name="bg_gradient_start">#EB5038</color>
    <color name="bg_gradient_end">#CA3822</color>
    <color name="bg_button_login">#A92815</color>
</resources>

Create bg_button_rounded.xml under /res/drawable-mdpi folder and add below code to it.

bg_button_rounded.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <!-- Background color -->
    <solid
        android:color="@color/bg_button_login" >
    </solid>

    <!-- Padding -->
    <padding
        android:left="5dp"
        android:top="5dp"
        android:right="5dp"
        android:bottom="5dp"    >
    </padding>

    <!-- Corner radius -->
    <corners
        android:radius="6dp"   >
    </corners>

</shape>

Create bg_form_rounded.xml under /res/drawable-mdpi folder and add below code to it.

bg_form_rounded.xml

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <!-- Background color -->
    <solid
        android:color="@color/white" >
    </solid>

    <!-- Padding -->
    <padding
        android:left="5dp"
        android:top="5dp"
        android:right="5dp"
        android:bottom="5dp"    >
    </padding>

    <!-- Corner radius -->
    <corners
        android:radius="6dp"   >
    </corners>

</shape>

Create bg_gradient.xml under /res/drawable-mdpi folder and add below code to it.

bg_gradient.xml

<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >

    <gradient
        android:gradientRadius="750"
        android:endColor="@color/bg_gradient_end"
        android:startColor="@color/bg_gradient_start"
        android:type="radial" />
</shape>

Create two layout XMLs under /res/layout folder:

activity_main.xml

Launch Screen

<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:background="@drawable/bg_gradient"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:gravity="center"
        android:orientation="vertical" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="40dp"
            android:text="@string/welcome"
            android:textColor="@color/white"
            android:textSize="25sp"
            android:textStyle="bold" />

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_form_rounded"
            android:orientation="vertical" >

            <EditText
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginBottom="10dp"
                android:background="@null"
                android:hint="@string/email"
                android:padding="5dp"
                android:singleLine="true" 
                android:id="@+id/email" android:textColor="@color/black"/>
        </LinearLayout>

        <Button
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="25dp"
            android:background="@drawable/bg_button_rounded"
            android:text="@string/login"
            android:textColor="@color/white" android:onClick="RegisterUser"/>
    </LinearLayout>

</RelativeLayout>

activity_greeting.xml

Greeting Screen

<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:background="@drawable/bg_gradient"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".GreetingActivity" >

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="15dp"
        android:layout_marginRight="15dp"
        android:gravity="center"
        android:orientation="vertical" >
         <ProgressBar
            android:id="@+id/progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:visibility="invisible" />

        <ImageView
           android:layout_width="275dip"
         android:layout_height="275dip"
            android:layout_marginBottom="10dp"
            android:src="@drawable/greeting_default" android:id="@+id/greetimg"/>

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/bg_form_rounded"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/greetingmsg"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_marginBottom="40dp"
                android:gravity="center"
                android:text="@string/welcome"
                android:textColor="@color/black"
                android:textSize="20sp" />

        </LinearLayout>

    </LinearLayout>

</RelativeLayout>

Step 5: ApplicationConstants.java

We are done with Layout designing, let us jump into Coding.

Create ApplicationConstants.Java under the package com.prgguru.example and fill it with below code. It has constants used across application. Make sure your updated Google_Project_Key with the one you created above.

Make sure you changed the IP address mentioned in the APP_SERVER_URL constant with your Machine/LAN IP address.

package com.prgguru.example;

public interface ApplicationConstants {

	// Php Application URL to store Reg ID created
	static final String APP_SERVER_URL = "http://192.168.2.4:9000/gcmwebapp/insertuser.php";

	// Google Project Number
	static final String GOOGLE_PROJ_ID = "837715578074";
	static final String MSG_KEY = "m";

}

Step 6: Utility.java

Create Utility.Java under the package com.prgguru.example and fill it with below code. It has Utility methods.

package com.prgguru.example;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * Class which has Utility methods
 * 
 */
public class Utility {
    private static Pattern pattern;
    private static Matcher matcher;
    //Email Pattern
    private static final String EMAIL_PATTERN = 
            "^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*@"
            + "[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$";

    /**
     * Validate Email with regular expression
     * 
     * @param email
     * @return true for Valid Email and false for Invalid Email
     */
    public static boolean validate(String email) {
        pattern = Pattern.compile(EMAIL_PATTERN);
        matcher = pattern.matcher(email);
        return matcher.matches();
    }
}

Step 7: MainActivity.java

Create MainActivity.Java under the package com.prgguru.example and fill it with below code.

It is the launch screen activity which asks User to enter Email ID, once Email ID is submitted Application will try to register User’s device in Google Cloud Messaging server. Registration Id will be generated once the registration is successfully completed.

Registration Id will be stored in GCM Server Application (created above) as text file (GCMRegId.txt).

package com.prgguru.example;

import java.io.IOException;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.gcm.GoogleCloudMessaging;
import com.loopj.android.http.AsyncHttpClient;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;

public class MainActivity extends Activity {
	ProgressDialog prgDialog;
	RequestParams params = new RequestParams();
	GoogleCloudMessaging gcmObj;
	Context applicationContext;
	String regId = "";

	private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

	AsyncTask<Void, Void, String> createRegIdTask;

	public static final String REG_ID = "regId";
	public static final String EMAIL_ID = "eMailId";
	EditText emailET;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		applicationContext = getApplicationContext();
		emailET = (EditText) findViewById(R.id.email);

		prgDialog = new ProgressDialog(this);
		// Set Progress Dialog Text
		prgDialog.setMessage("Please wait...");
		// Set Cancelable as False
		prgDialog.setCancelable(false);

		SharedPreferences prefs = getSharedPreferences("UserDetails",
				Context.MODE_PRIVATE);
		String registrationId = prefs.getString(REG_ID, "");

		if (!TextUtils.isEmpty(registrationId)) {
			Intent i = new Intent(applicationContext, GreetingActivity.class);
			i.putExtra("regId", registrationId);
			startActivity(i);
			finish();
		}

	}

	// When Register Me button is clicked
	public void RegisterUser(View view) {
		String emailID = emailET.getText().toString();

		if (!TextUtils.isEmpty(emailID) && Utility.validate(emailID)) {
			// Check if Google Play Service is installed in Device
			// Play services is needed to handle GCM stuffs
			if (checkPlayServices()) {

				// Register Device in GCM Server
				registerInBackground(emailID);
			}
		}
		// When Email is invalid
		else {
			Toast.makeText(applicationContext, "Please enter valid email",
					Toast.LENGTH_LONG).show();
		}
	}

	// AsyncTask to register Device in GCM Server
	private void registerInBackground(final String emailID) {
		new AsyncTask<Void, Void, String>() {
			@Override
			protected String doInBackground(Void... params) {
				String msg = "";
				try {
					if (gcmObj == null) {
						gcmObj = GoogleCloudMessaging
								.getInstance(applicationContext);
					}
					regId = gcmObj
							.register(ApplicationConstants.GOOGLE_PROJ_ID);
					msg = "Registration ID :" + regId;

				} catch (IOException ex) {
					msg = "Error :" + ex.getMessage();
				}
				return msg;
			}

			@Override
			protected void onPostExecute(String msg) {
				if (!TextUtils.isEmpty(regId)) {
					storeRegIdinSharedPref(applicationContext, regId, emailID);
					Toast.makeText(
							applicationContext,
							"Registered with GCM Server successfully.nn"
									+ msg, Toast.LENGTH_SHORT).show();
				} else {
					Toast.makeText(
							applicationContext,
							"Reg ID Creation Failed.nnEither you haven't enabled Internet or GCM server is busy right now. Make sure you enabled Internet and try registering again after some time."
									+ msg, Toast.LENGTH_LONG).show();
				}
			}
		}.execute(null, null, null);
	}

	// Store RegId and Email entered by User in SharedPref
	private void storeRegIdinSharedPref(Context context, String regId,
			String emailID) {
		SharedPreferences prefs = getSharedPreferences("UserDetails",
				Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = prefs.edit();
		editor.putString(REG_ID, regId);
		editor.putString(EMAIL_ID, emailID);
		editor.commit();
		storeRegIdinServer(regId, emailID);

	}

	// Share RegID and Email ID with GCM Server Application (Php)
	private void storeRegIdinServer(String regId2, String emailID) {
		prgDialog.show();
		params.put("emailId", emailID);
		params.put("regId", regId);
		System.out.println("Email id = " + emailID + " Reg Id = " + regId);
		// Make RESTful webservice call using AsyncHttpClient object
		AsyncHttpClient client = new AsyncHttpClient();
		client.post(ApplicationConstants.APP_SERVER_URL, params,
				new AsyncHttpResponseHandler() {
					// When the response returned by REST has Http
					// response code '200'
					@Override
					public void onSuccess(String response) {
						// Hide Progress Dialog
						prgDialog.hide();
						if (prgDialog != null) {
							prgDialog.dismiss();
						}
						Toast.makeText(applicationContext,
								"Reg Id shared successfully with Web App ",
								Toast.LENGTH_LONG).show();
						Intent i = new Intent(applicationContext,
								GreetingActivity.class);
						i.putExtra("regId", regId);
						startActivity(i);
						finish();
					}

					// When the response returned by REST has Http
					// response code other than '200' such as '404',
					// '500' or '403' etc
					@Override
					public void onFailure(int statusCode, Throwable error,
							String content) {
						// Hide Progress Dialog
						prgDialog.hide();
						if (prgDialog != null) {
							prgDialog.dismiss();
						}
						// When Http response code is '404'
						if (statusCode == 404) {
							Toast.makeText(applicationContext,
									"Requested resource not found",
									Toast.LENGTH_LONG).show();
						}
						// When Http response code is '500'
						else if (statusCode == 500) {
							Toast.makeText(applicationContext,
									"Something went wrong at server end",
									Toast.LENGTH_LONG).show();
						}
						// When Http response code other than 404, 500
						else {
							Toast.makeText(
									applicationContext,
									"Unexpected Error occcured! [Most common Error: Device might "
											+ "not be connected to Internet or remote server is not up and running], check for other errors as well",
									Toast.LENGTH_LONG).show();
						}
					}
				});
	}

	// Check if Google Playservices is installed in Device or not
	private boolean checkPlayServices() {
		int resultCode = GooglePlayServicesUtil
				.isGooglePlayServicesAvailable(this);
		// When Play services not found in device
		if (resultCode != ConnectionResult.SUCCESS) {
			if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
				// Show Error dialog to install Play services
				GooglePlayServicesUtil.getErrorDialog(resultCode, this,
						PLAY_SERVICES_RESOLUTION_REQUEST).show();
			} else {
				Toast.makeText(
						applicationContext,
						"This device doesn't support Play services, App will not work normally",
						Toast.LENGTH_LONG).show();
				finish();
			}
			return false;
		} else {
			Toast.makeText(
					applicationContext,
					"This device supports Play services, App will work normally",
					Toast.LENGTH_LONG).show();
		}
		return true;
	}

	// When Application is resumed, check for Play services support to make sure
	// app will be running normally
	@Override
	protected void onResume() {
		super.onResume();
		checkPlayServices();
	}
}

Step 8: GreetingActivity.java

Create GreetingActivity.Java under the package com.prgguru.example and fill it with below code.

It is the Greeting screen activity which display the message sent from GCM Server Application.

package com.prgguru.example;

import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

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

public class GreetingActivity extends Activity {
	TextView emailET;
	private AQuery aq;
	// Progress Dialog bar object
	ProgressDialog prgDialog;
	private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 9000;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_test);
		aq = new AQuery(this);
		String json = getIntent().getStringExtra("greetjson");
		SharedPreferences prefs = getSharedPreferences("UserDetails",
				Context.MODE_PRIVATE);
		emailET = (TextView) findViewById(R.id.greetingmsg);

		// Check if Google Play Service is installed in Device
		// Play services is needed to handle GCM stuffs
		if (!checkPlayServices()) {
			Toast.makeText(
					getApplicationContext(),
					"This device doesn't support Play services, App will not work normally",
					Toast.LENGTH_LONG).show();
		}

		// When json is not null
		if (json != null) {
			try {
				JSONObject jsonObj = new JSONObject(json);
				SharedPreferences.Editor editor = prefs.edit();
				editor.putString("greetimgurl", jsonObj.getString("greetImgURL"));
				editor.putString("greetmsg", jsonObj.getString("greetMsg"));
				editor.commit();

				emailET.setText(prefs.getString("greetmsg", ""));
				// Render Image read from Image URL using aquery 'image' method
				aq.id(R.id.greetimg)
						.progress(R.id.progress)
						.image(prefs.getString("greetimgurl", ""), true, true,
								0, 0, null, AQuery.FADE_IN);
			} catch (JSONException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		} 
		// When Json is null
		else if (!"".equals(prefs.getString("greetimgurl", ""))	&& !"".equals(prefs.getString("greetmsg", "") != null)) {
			emailET.setText(prefs.getString("greetmsg", ""));
			aq.id(R.id.greetimg)
					.progress(R.id.progress)
					.image(prefs.getString("greetimgurl", ""), true, true, 0,
							0, null, AQuery.FADE_IN);
		}
	}

	// Check if Google Playservices is installed in Device or not
	private boolean checkPlayServices() {
		int resultCode = GooglePlayServicesUtil
				.isGooglePlayServicesAvailable(this);
		// When Play services not found in device
		if (resultCode != ConnectionResult.SUCCESS) {
			if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
				// Show Error dialog to install Play services
				GooglePlayServicesUtil.getErrorDialog(resultCode, this,
						PLAY_SERVICES_RESOLUTION_REQUEST).show();
			} else {
				Toast.makeText(
						getApplicationContext(),
						"This device doesn't support Play services, App will not work normally",
						Toast.LENGTH_LONG).show();
				finish();
			}
			return false;
		} else {
			Toast.makeText(
					getApplicationContext(),
					"This device supports Play services, App will work normally",
					Toast.LENGTH_LONG).show();
		}
		return true;
	}

	// When Application is resumed, check for Play services support to make sure
	// app will be running normally
	@Override
	protected void onResume() {
		super.onResume();
		checkPlayServices();
	}
}

Step 9: GcmBroadcastReceiver.java

Create GcmBroadcastReceiver.Java under the package com.prgguru.example and fill it with below code.

A broadcast receiver is the mechanism GCM uses to deliver messages. When message is sent through GCM Server application, it triggers the broadcast receiver’s onReceive() method, which has the responsibility of making sure that the GCM message gets handled.

A WakefulBroadcastReceiver is a special type of broadcast receiver that takes care of creating and managing a partial wake lock for your app.

package com.prgguru.example;

import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.WakefulBroadcastReceiver;

public class GcmBroadcastReceiver extends WakefulBroadcastReceiver {

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

Step 10: GCMNotificationIntentService.java

Create GcmBroadcastReceiver.Java under the package com.prgguru.example and fill it with below code.

The intent service shown below does the actual work of handling the GCM message. This class processes the GCM message based on message type, and posts the result in a notification.

package com.prgguru.example;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;

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

public class GCMNotificationIntentService extends IntentService {
	// Sets an ID for the notification, so it can be updated
	public static final int notifyID = 9001;
	NotificationCompat.Builder builder;

	public GCMNotificationIntentService() {
		super("GcmIntentService");
	}

	public static final String TAG = "GCMNotificationIntentService";

	@Override
	protected void onHandleIntent(Intent intent) {
		Bundle extras = intent.getExtras();
		GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);

		String messageType = gcm.getMessageType(intent);

		if (!extras.isEmpty()) {
			if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR
					.equals(messageType)) {
				sendNotification("Send error: " + extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED
					.equals(messageType)) {
				sendNotification("Deleted messages on server: "
						+ extras.toString());
			} else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE
					.equals(messageType)) {

				sendNotification(""	+ extras.get(ApplicationConstants.MSG_KEY)); //When Message is received normally from GCM Cloud Server
			}
		}
		GcmBroadcastReceiver.completeWakefulIntent(intent);
	}

	private void sendNotification(String greetMsg) {
	        Intent resultIntent = new Intent(this, GreetingActivity.class);
	        resultIntent.putExtra("greetjson", greetMsg);
	        resultIntent.setAction(Intent.ACTION_MAIN);
	        resultIntent.addCategory(Intent.CATEGORY_LAUNCHER);
	        PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0,
	                resultIntent, PendingIntent.FLAG_ONE_SHOT);

	        NotificationCompat.Builder mNotifyBuilder;
	        NotificationManager mNotificationManager;

	        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

	        mNotifyBuilder = new NotificationCompat.Builder(this)
	                .setContentTitle("Alert")
	                .setContentText("You've received new messages.")
	                .setSmallIcon(R.drawable.ic_launcher);
	        // Set pending intent
	        mNotifyBuilder.setContentIntent(resultPendingIntent);

	        // Set Vibrate, Sound and Light	        
	        int defaults = 0;
	        defaults = defaults | Notification.DEFAULT_LIGHTS;
	        defaults = defaults | Notification.DEFAULT_VIBRATE;
	        defaults = defaults | Notification.DEFAULT_SOUND;

	        mNotifyBuilder.setDefaults(defaults);
	        // Set the content for Notification 
	        mNotifyBuilder.setContentText("New message from Server");
	        // Set autocancel
	        mNotifyBuilder.setAutoCancel(true);
	        // Post a notification
	        mNotificationManager.notify(notifyID, mNotifyBuilder.build());
	}
}

Demo

That’s all. It’s time to test our code.

Run the application using emulator or device by right clicking on the project >> Run as >> Android applicaiton >> Choose emulator or device.

 

Download Source Code

Entire project is zipped and is available for download. Unzip the downloaded project and to import the project into eclipse, launch eclipse >> File >> Import.. >> Choose downloaded project(How to import android project in eclipse).

Download Source Code

*apk in Android  is the installation file similar to exe in windows.

[pglinkadssmall]

If you feel this article is helpful and interesting please spread a word about it to your friends and colleagues by sharing the article in Facebook or Twitter.

Share

You are always welcome to provide your comments and feedback from comment box.

Reference

Android GCM

[pgwriteforus]

[pgfeedback]

Related Articles

Author: Udhay

Share This Post On
468 ad
  • Monowar Hossain

    Wow! Very Nice post and also helpful. I am really surprised
    to read this post. I know here about GCM. Nice post BOSS!!!

  • Thank you.

  • Rahul Chauhan

    Nice post buddy.

  • abul

    i’d success run this project, i’d send message successfully but suddenly i got fail:
    {“multicast_id”:….,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”NotRegistered”}]}.
    i have to reinstall the application or delete mydevice’s data from the DB and re-register so I can send messages successfully again.
    It occured repeatly. why did it happen? and how can i check the error that make me got failed to send message?

  • joe

    I have successfully created and ran the app,but when i opened the app and try to register..it created the register id but then gives me an error

    Unexpected Error Occcured~ [Most Common Error : Device not be connected to internet or remote server is not up and running, check other errors as well.

    I am running xampp on localhost.

    please help..thank you

  • abul

    why i got failure? where can i see the error?

  • abul

    “You are always welcome to provide your comments and feedback from comment box.”

    I’d try to discuss about this project, but my questions have never been approved. ckckck

  • joe

    Great Job on the tutorial..but i am having some trouble with the app..
    I ran the app and the server..but when i run the app it tells me “This app won’t run unless you update google play services”?i am running a emulator..

    thank you.

  • Ray

    HI, I’M HAVING PROBLEMS WITH THAT

    AsyncHttpClient client = new AsyncHttpClient();

    client.post(ApplicationConstants.APP_SERVER_URL, params,

    new AsyncHttpResponseHandler() {

    // When the response returned by REST has Http

    // response code ‘200’

    @Override

  • Francesco Ferigo

    Many many thanks

  • Did you change the IP address in Java file to your LAN IP address?

  • Please see the error in logcat.

  • HI Abul,

    I am not full time blogger so when I get time I write tutorials and also approve comments. You can see your questions today. 🙂

  • Google Play Service is needed for invoking GCM service. It is the pre-check I am doing in code.

  • You need to use your server URL.

  • You are welcome.

  • Jigar

    Thank you so much for this tutorial!! Good going! YOU are AWESOME! 🙂 ^_^

  • Thanks you.

  • shwe

    i m gettting {“multicast_id”:6593733127016446845,”success”:0,”failure”:1,”canonical_ids”:0,”results”:[{“error”:”InvalidRegistration”}]} after messagesend

  • amit basliyal

    thank you so much awesome tutorial ??

  • amit basliyal

    thank for save me but want to create this type of notification please suggest with this code

Join now to get more access to our Android Tutorials

Join now to get more access to our Android Tutorials

Once you Join, you will receive Mail containing latest Android Tutorials once a month !!

I promise I wont spam you !!

You have Successfully Subscribed!

Pin It on Pinterest

Shares