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.

7-day free trial

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:
    1
    2
    3
    4
    5
    6
    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.

1
2
3
4
5
6
7
8
9
<?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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?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.,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
<html>
<head><title>View Users</title>
<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/>
</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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?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

1
2
3
4
5
6
7
<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

1
2
3
4
5
6
7
8
<?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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<shape
    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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<shape
    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

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
    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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<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.

1
2
3
4
5
6
7
8
9
10
11
12
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
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.\n\n"
                                    + msg, Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(
                            applicationContext,
                            "Reg ID Creation Failed.\n\nEither 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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
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.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s