You are on page 1of 53

Device To Device Messaging Using Google Cloud Messaging

GCM - Android Application


ABSTRACT:
Android Cloud to Device Messaging (C2DM), which is now deprecated, is a push
notification service that helps developers send data from servers to their applications on Android
devices and launched together with Android 2.2 by Google. The service provides a simple,
lightweight mechanism that servers can use to tell mobile applications to contact the server
directly, to fetch updated application or user data. The C2DM service handles all aspects of
queueing of messages and delivery to the target application running on the target device.
Applications on an Android device dont need to be running to receive messages. The
system will wake up the application via Intent broadcast when the message arrives, as long as the
application is set up with the proper broadcast receiver and permissions. C2DM does not provide
any built-in user interface or other handling for message data. Instead, it simply passes raw
message data received straight to the application, which has full control of how to handle it. For
example, the application might post a notification, display a custom user interface, or silently
sync data. It requires devices running Android 2.2 or higher that also have the Market application
installed. It uses an existing connection for Google services. This requires users to set up their
Google account on their mobile devices. Each notification message size is limited to 1024 bytes,
and Google limits the number of messages a sender sends in aggregate, and the number of
messages a sender sends to a specific device.

INTRODUCTION
Android is a Linux-based operating system for mobile devices such as smartphones and
tablet computers. It is developed by the Open Handset Alliance led by Google. Google purchased
the initial developer of the software, Android Inc., in 2005.The unveiling of the Android
distribution in 2007 was announced with the founding of the Open Handset Alliance, a
consortium of 86 hardware, software, and telecommunication companies devoted to advancing
open standards for mobile devices. Google releases the Android code as open-source, under the
Apache License. The Android Open Source Project (AOSP) is tasked with the maintenance and
further development of Android .Android has a large community of developers writing
applications ("apps") that extend the functionality of the devices. Developers write primarily in a
customized version of Java. Apps can be downloaded from third-party sites or through online
stores such as Google Play (formerly Android Market), the app store run by Google.
Applications on an Android device dont need to be running to receive messages. The
system will wake up the application via Intent broadcast when the message arrives, as long as the
application is set up with the proper broadcast receiver and permissions. C2DM does not provide
any built-in user interface or other handling for message data. Instead, it simply passes raw
message data received straight to the application, which has full control of how to handle it. For
example, the application might post a notification, display a custom user interface, or silently
sync data. It requires devices running Android 2.2 or higher that also have the Market application
installed. It uses an existing connection for Google services. This requires users to set up their
Google account on their mobile devices. Each notification message size is limited to 1024 bytes,
and Google limits the number of messages a sender sends in aggregate, and the number of
messages a sender sends to a specific device.

FEASIBILIT STUDY
As we have discussed in the introduction this project is developed based on the Android
OS and google Cloud this project s theoretically feasibility is observed and we intended to
introspect whether our postulates and hypothesis about the construction of the project. On throw
study on this the following finding were evolved.

Technical Feasibility
As this project is aimed to use HTTP based device to device messaging with the help of
implementing GCM Cloud Connection Server (CCS) to interact with Android devices . GCM
Cloud Connection Server (CCS) is a connection server based on XMPP. CCS allows 3rd-party
app servers to communicate with Android devices by establishing a persistent TCP connection
with Google servers using the XMPP protocol. This communication is asynchronous and
bidirectional (device to device). So this instant messaging can be achieved with appropriate
server side programming and Android application which can interact with the cloud is required
which can be easily built. So we decided and made a conclusion at the feasibility study that this
project is technical feasibility.

SYSTEM ANALYSIS
Existing System
Presently existing system uses the cloud for push mail and chat and messaging services
like whatsapp and wechat etc. all these are based on concealed business logic and uses their
existing mail servers and messaging system in connection with google cloud for messaging. But
to develop such systems will be time consuming and multi protocol based programming to cater
to all sort of devices available in the market place. Even though majority of these services started
with the same intention of providing simple device to device messaging they were diverted and
become hevy weight application which may be having huge overheads while running on smart
phones. So majority of the users find it that these are making their phone performance to getting
slower. So they users tend to close the application and invoke when it is required. This
completely defeats the concept of instant messaging.

Proposed System.
The proposed system is to develop a application for sending device to device (Mobile To
Mobile) messaging using google cloud messaging (GCM). it is the very basic method one can
use this to create advance level messaging application. Using android and SQLite database.

This system will be using HTTP based device to device messaging but Right way to achieve the
device to device messaging is to implement GCM Cloud Connection Server (CCS) . GCM Cloud
Connection Server (CCS) is a connection server based on XMPP. It will be simple and will not
take overhead so Applications on an Android device dont need to be running to receive
messages. The system will wake up the application via Intent broadcast when the message
arrives, as long as the application is set up with the proper broadcast receiver and permissions.
C2DM does not provide any built-in user interface or other handling for message data. Instead, it
simply passes raw message data received straight to the application, which has full control of
how to handle it.

SYSTEM REQUIREMENTS
HARDWRE REQUIRMENTS
For Development :
PC with Intel Duel Core Processor
Minimum of 4 GB RAM
500 GB HDD
VGA Card With Built in Video RAM
For Testing
Tablet PC or Smart phone with Sensors which adhering to th standards of Nexus 5
or above

SOFTWARE REQUIREMENTS
Either Windows 7 or Ubuntu 13
Software Development
Android ADK Studio
Android Development Kit Bundle 4.4 or later
Android OS 4.41 KIT KAT
Google Cloud Account
SQLite Database

SYSTEM DESCRIPTION

WORKFLOW:

PROJECT STRUCTURE

ABOUT THE SOFTWARE:


As this project used device level programming there is no concept of back end database
used in this Application We have used android OS and and Developed the application using
JAVA.
Android is an operating system based on the Linux kernel. The project responsible for
developing the Android system is called the Android Open Source Project (AOSP) and is
primarily lead by Google. The Android system supports background processing, provides a rich
user interface library, supports 2-D and 3-D graphics using the OpenGL-ES (short OpenGL)
standard and grants access to the file system as well as an embedded SQLite database An
Android application typically consists of different visual and non visual components and can
reuse components of other applications.
The Android system is a full software stack, which is typically divided into the four areas
as depicted in the following graphic.

The levels can be described as:


Applications - The Android Open Source Project contains several default application, like
the Browser, Camera, Gallery, Music, Phone and more.
Application framework - An API which allows high-level interactions with the Android
system from Android applications.
Libraries and runtime - The libraries for many common functions (e.g.: graphic rendering,
data storage, web browsing, etc.) of the Application Framework and the Dalvik runtime,
as well as the core Java libraries for running Android applications.
Linux kernel - Communication layer for the underlying hardware.

The Linux kernel, the libraries and the runtime are encapsulated by the application
framework. The Android application developer typically works with the two layers on top to
create new Android applications.

Android Development Tools


Android SDK
The Android Software Development Kit (Android SDK) contains the necessary tools to
create, compile and package Android applications. Most of these tools are command line based.
The primary way to develop Android applications is based on the Java programming language.

Android debug bridge (adb)


The Android SDK contains the Android debug bridge (adb), which is a tool that allows
you to connect to a virtual or real Android device, for the purpose of managing the device or
debugging your application.

Android Developer Tools and Android Studio


Google provides two integrated development environments (IDEs) to develop new
applications.
The Android Developer Tools (ADT) are based on the Eclipse IDE. ADT is a set of
components (plug-ins), which extend the Eclipse IDE with Android development capabilities.
Google also supports an IDE called Android Studio for creating Android applications. This IDE
is based on the IntelliJ IDE.
Both IDEs contain all required functionality to create, compile, debug and deploy
Android applications. They also allow the developer to create and start virtual Android devices
for testing.
Both tools provide specialized editors for Android specific files. Most of Android's
configuration files are based on XML. In this case these editors allow you to switch between the
XML representation of the file and a structured user interface for entering the data.

Dalvik Virtual Machine


The Android system uses a special virtual machine, i.e., the Dalvik Virtual Machine
(Dalvik) to run Java based applications. Dalvik uses a custom bytecode format which is different
from Java bytecode.
Therefore you cannot run Java class files on Android directly; they need to be converted into the
Dalvik bytecode format.

Just in time compiler on Dalvik

Similar to the JVM, Dalvik optimizes the application at runtime. This is known as Just In
Time (JIT) compilation. If a part of the application is called frequently, Dalvik will optimize this
part of the code and compile it into machine code which executes much faster.

Android RunTime (ART)


With Android 4.4, Google introduced the Android RunTime (ART) as optional runtime
for Android 4.4. It is expected that versions after 4.4 will use ART as default runtime.
ART uses Ahead Of Time compilation. During the deployment process of an application on an
Android device, the application code is translated into machine code. This results in approx. 30%
larger compile code, but allows faster execution from the beginning of the application.

How to develop Android applications


Android applications are primarily written in the Java programming language.
During development the developer creates the Android specific configuration files and writes the
application logic in the Java programming language.
The ADT or the Android Studio tools convert these application files, transparently to the
user, into an Android application. When developers trigger the deployment in their IDE, the
whole Android application is compiled, packaged, deployed and started.

Conversion process from source code to Android application

The Java source files are converted to Java class files by the Java compiler.
The Android SDK contains a tool called dx which converts Java class files into a .dex (Dalvik
Executable) file. All class files of the application are placed in this .dex file. During this
conversion process redundant information in the class files are optimized in the .dex file.
For example, if the same String is found in different class files, the .dex file contains only one
reference of this String.
These .dex files are therefore much smaller in size than the corresponding class files.
The .dex file and the resources of an Android project, e.g., the images and XML files, are packed
into an .apk (Android Package) file. The program aapt (Android Asset Packaging Tool) performs
this step.
The resulting .apk file contains all necessary data to run the Android application and can be
deployed to an Android device via the adb tool.

Android emulator and Android Virtual Device

The Android SDK contains an Android device emulator. This emulator can be used to run
an Android Virtual Device (AVD), which emulates a real Android phone. Such an emulator is
displayed in the following screenshot.

AVDs allow you to test your Android applications on different Android versions and
configurations without access to the real hardware.
During the creation of your AVD you define the configuration for the virtual device. This
includes, for example, the resolution, the Android API version and the density of your display.
You can define multiple AVDs with different configurations and start them in parallel. This
allows you to test different device configurations at once.

Source Code :
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.androidexample.mobilegcm"
android:versionCode="1"
android:versionName="1.0" >
<!-- GCM requires Android SDK version 2.2 (API level 8) or above. -->
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
<!-- Main activity. -->
<application
android:name="com.androidexample.mobilegcm.Controller"
android:icon="@drawable/user_thumb"
android:label="@string/app_name" >
<!-- Register Activity -->
<activity
android:name=".Main"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.DELETE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="com.androidexample.mobilegcm" />
</intent-filter>
</activity>
<activity android:name=".RegisterActivity"></activity>
<!-- Main Activity -->
<activity
android:name="com.androidexample.mobilegcm.MainActivity"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden"
android:label="@string/app_name" >
</activity>
<activity android:name=".GridViewExample" android:screenOrientation="portrait"></activity>
<activity android:name=".SendPushNotification" android:screenOrientation="portrait"></activity>
<activity android:name=".ShowMessage" android:screenOrientation="portrait"></activity>
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND" >

<intent-filter>
<!-- Receives the actual messages. -->
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<!-- Receives the registration id. -->
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.androidexample.mobilegcm" />
</intent-filter>
</receiver>
<service android:name="com.androidexample.mobilegcm.GCMIntentService" />
</application>
<!-- GCM connects to Internet Services. -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- GCM requires a Google account. -->
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<!-- Keeps the processor from sleeping when a message is received. -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Creates a custom permission so only this app can receive its messages. -->
<permission
android:name="com.androidexample.mobilegcm.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.androidexample.mobilegcm.permission.C2D_MESSAGE" />
<!-- This app has permission to register and receive data message. -->
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<!-- Network State Permissions to detect Internet status -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<!-- Permission to vibrate -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
</manifest>

JAVA FILE : Config.java

This is the main client side configuration file.


package com.androidexample.mobilegcm;
public interface Config {
// CONSTANTS
// When you are using two simulator for testing application.
// Then Make SECOND_SIMULATOR value true when opening/installing application
in second simulator
// Actually we are validating/saving device data on IMEI basis.
// if it is true IMEI number change for second simulator
static final boolean SECOND_SIMULATOR = false;

// Server Url absolute url where php files are placed.


static final String YOUR_SERVER_URL = "YOUR_SERVER_URL/FOLDER_NAMES_WHERE_SERVER_FILES_PLACED
// Google project id
static final String GOOGLE_SENDER_ID = "943293855675";
/**
* Tag used on log messages.
*/
static final String TAG = "GCM Android Example";
// Broadcast reciever name to show gcm registration messages on screen
static final String DISPLAY_REGISTRATION_MESSAGE_ACTION =
"com.androidexample.gcm.DISPLAY_REGISTRATION_MESSAGE";
// Broadcast reciever name to show user messages on screen
static final String DISPLAY_MESSAGE_ACTION =
"com.androidexample.gcm.DISPLAY_MESSAGE";
// Parse server message with this name
static final String EXTRA_MESSAGE = "message";

JAVA FILE : UserData.java


This is the model class to show user data.
package com.androidexample.mobilegcm;
public class UserData {
//private variables
int _id;
String _imei;
String _name;
String _message;
// Empty constructor
public UserData(){
}
// constructor
public UserData(int id, String imei, String name, String message){
this._id
= id;
this._imei = imei;
this._name = name;
this._message = message;
}
// getting ID
public int getID(){
return this._id;
}

// setting id
public void setID(int id){
this._id = id;
}
// getting imei
public String getIMEI(){
return this._imei;
}
// setting imei
public void setIMEI(String imei){
this._imei = imei;
}

// getting name
public String getName(){
return this._name;
}

// setting name
public void setName(String name){
this._name = name;
}

// getting Message
public String getMessage(){
return this._message;
}
// setting Message
public void setMessage(String message){
this._message = message;
}

/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "UserInfo [name=" + _name + "]";
}
}

JAVA FILE : DBAdapter.java


Sqlite
database
helper
class
that
defined
This class contains funtions to insert/update/delete user data.

user

and

package com.androidexample.mobilegcm;
import
import
import
import
import
import
import
import
import
import
import

java.util.ArrayList;
java.util.List;
com.androidexample.mobilegcm.UserData;
android.content.ContentValues;
android.content.Context;
android.database.Cursor;
android.database.DatabaseUtils;
android.database.SQLException;
android.database.sqlite.SQLiteDatabase;
android.database.sqlite.SQLiteOpenHelper;
android.util.Log;

public class DBAdapter {


/***** if debug is set true then it will show all Logcat message ****/
public static final boolean DEBUG = true;
/******************** Logcat TAG ************/
public static final String LOG_TAG = "DBAdapter";
/******************** Table Fields ************/
public static final String KEY_ID = "_id";
public static final String KEY_USER_IMEI = "user_imei";
public static final String KEY_USER_NAME

= "user_name";

public static final String KEY_USER_MESSAGE = "user_message";


public static final String KEY_DEVICE_IMEI = "device_imei";
public static final String KEY_DEVICE_NAME = "device_name";
public static final String KEY_DEVICE_EMAIL = "device_email";
public static final String KEY_DEVICE_REGID = "device_regid";

/******************** Database Name ************/


public static final String DATABASE_NAME = "DB_sqllite";

message

specific

funtions.

/**** Database Version (Increase one if want to also upgrade your database) ****/
public static final int DATABASE_VERSION = 1;// started at 1

/** Table names */


public static final String USER_TABLE = "tbl_user";
public static final String DEVICE_TABLE = "tbl_device";
/*** Set all table with comma seperated like USER_TABLE,ABC_TABLE ***/
private static final String[] ALL_TABLES = { USER_TABLE,DEVICE_TABLE };
/** Create table syntax */

private static final String USER_CREATE =


"create table tbl_user(_id integer primary key autoincrement,
user_name text not null,
user_imei text not null,
user_message text not null);";

private static final String DEVICE_CREATE =


"create table tbl_device(_id integer primary key autoincrement,
device_name text not null,
device_email text not null,
device_regid text not null,
device_imei text not null);";
/**** Used to open database in syncronized way ****/
private static DataBaseHelper DBHelper = null;

protected DBAdapter() {
}
/******************* Initialize database *************/
public static void init(Context context) {
if (DBHelper == null) {
if (DEBUG)
Log.i("DBAdapter", context.toString());
DBHelper = new DataBaseHelper(context);
}
}

/***** Main Database creation INNER class ******/


private static class DataBaseHelper extends SQLiteOpenHelper {
public DataBaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
if (DEBUG)
Log.i(LOG_TAG, "new create");
try {
//db.execSQL(USER_MAIN_CREATE);
db.execSQL(USER_CREATE);
db.execSQL(DEVICE_CREATE);

} catch (Exception exception) {


if (DEBUG)
Log.i(LOG_TAG, "Exception onCreate() exception");
}
}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (DEBUG)
Log.w(LOG_TAG, "Upgrading database from version" + oldVersion
+ "to" + newVersion + "...");

for (String table : ALL_TABLES) {


db.execSQL("DROP TABLE IF EXISTS " + table);
}
onCreate(db);
}
} // Inner class closed

/**** Open database for insert,update,delete in syncronized manner ****/


private static synchronized SQLiteDatabase open() throws SQLException {
return DBHelper.getWritableDatabase();
}

// Insert installing device data


public static void addDeviceData(String DeviceName, String DeviceEmail,
String DeviceRegID,String DeviceIMEI)
{
try{
final SQLiteDatabase db = open();
String imei = sqlEscapeString(DeviceIMEI);
String name = sqlEscapeString(DeviceName);
String email = sqlEscapeString(DeviceEmail);
String regid = sqlEscapeString(DeviceRegID);

ContentValues cVal = new ContentValues();


cVal.put(KEY_DEVICE_IMEI, imei);
cVal.put(KEY_DEVICE_NAME, name);
cVal.put(KEY_DEVICE_EMAIL, email);
cVal.put(KEY_DEVICE_REGID, regid);

db.insert(DEVICE_TABLE, null, cVal);


db.close(); // Closing database connection
} catch (Throwable t) {
Log.i("Database", "Exception caught: " + t.getMessage(), t);
}
}

// Adding new user


public static void addUserData(UserData uData) {
try{
final SQLiteDatabase db = open();

String imei = sqlEscapeString(uData.getIMEI());


String name = sqlEscapeString(uData.getName());
String message = sqlEscapeString(uData.getMessage());

ContentValues cVal = new ContentValues();


cVal.put(KEY_USER_IMEI, imei);
cVal.put(KEY_USER_NAME, name);
cVal.put(KEY_USER_MESSAGE, message);
db.insert(USER_TABLE, null, cVal);
db.close(); // Closing database connection

} catch (Throwable t) {
Log.i("Database", "Exception caught: " + t.getMessage(), t);
}
}

// Getting single user data


public static UserData getUserData(int id) {
final SQLiteDatabase db = open();
Cursor cursor = db.query(USER_TABLE, new String[] { KEY_ID,
KEY_USER_NAME, KEY_USER_IMEI,KEY_USER_MESSAGE}, KEY_ID + "=?",
new String[] { String.valueOf(id) }, null, null, null, null);
if (cursor != null)
cursor.moveToFirst();

UserData data = new UserData(Integer.parseInt(cursor.getString(0)),


cursor.getString(1), cursor.getString(2), cursor.getString(3));
// return contact
return data;
}

// Getting All user data


public static List<UserData> getAllUserData() {
List<UserData> contactList = new ArrayList<UserData>();
// Select All Query
String selectQuery = "SELECT * FROM " + USER_TABLE+" ORDER BY "+KEY_ID+" desc";
final SQLiteDatabase db = open();
Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
UserData data = new UserData();
data.setID(Integer.parseInt(cursor.getString(0)));
data.setName(cursor.getString(1));
data.setIMEI(cursor.getString(2));
data.setMessage(cursor.getString(3));
// Adding contact to list
contactList.add(data);
} while (cursor.moveToNext());
}

cursor.close();
// return contact list
return contactList;
}

// Getting users Count


public static int getUserDataCount() {
String countQuery = "SELECT * FROM " + USER_TABLE;
final SQLiteDatabase db = open();
Cursor cursor = db.rawQuery(countQuery, null);

int count = cursor.getCount();


cursor.close();
// return count
return count;
}

// Getting installed device have self data or not


public static int validateDevice() {
String countQuery = "SELECT * FROM " + DEVICE_TABLE;
final SQLiteDatabase db = open();
Cursor cursor = db.rawQuery(countQuery, null);
int count = cursor.getCount();
cursor.close();
// return count
return count;
}

// Getting distinct user data use in spinner


public static List<UserData> getDistinctUser() {
List<UserData> contactList = new ArrayList<UserData>();
// Select All Query
String selectQuery = "SELECT distinct(user_imei),user_name
FROM " + USER_TABLE+"
ORDER BY "+KEY_ID+" desc";

final SQLiteDatabase db = open();


Cursor cursor = db.rawQuery(selectQuery, null);
// looping through all rows and adding to list
if (cursor.moveToFirst()) {
do {
UserData data = new UserData();

data.setIMEI(cursor.getString(0));
data.setName(cursor.getString(1));
// Adding contact to list
contactList.add(data);
} while (cursor.moveToNext());
}
cursor.close();

return contactList;
}

// Getting imei already in user table or not


public static int validateNewMessageUserData(String IMEI) {
int count = 0;
try {
String countQuery = "SELECT "+KEY_ID+"
FROM " + USER_TABLE + "
WHERE user_imei='"+IMEI+"'";
final SQLiteDatabase db = open();
Cursor cursor = db.rawQuery(countQuery, null);
count = cursor.getCount();
cursor.close();
} catch (Throwable t) {
count = 10;
Log.i("Database", "Exception caught: " + t.getMessage(), t);
}
return count;
}

// Escape string for single quotes (Insert,Update)


private static String sqlEscapeString(String aString) {
String aReturn = "";

if (null != aString) {
//aReturn = aString.replace("'", "''");
aReturn = DatabaseUtils.sqlEscapeString(aString);
// Remove the enclosing single quotes ...
aReturn = aReturn.substring(1, aReturn.length() - 1);
}
return aReturn;
}
// UnEscape string for single quotes (show data)
private static String sqlUnEscapeString(String aString) {
String aReturn = "";
if (null != aString) {
aReturn = aString.replace("''", "'");
}
return aReturn;
}
}

JAVA FILE : Controller.java


Controller.java is very important class , its contains all the client side function responsible for user data flow.
Controller class extends with android.app.Application and defined in the application tag in your
AndroidManifest.xml file. Android will create an instance of Controller class and make it available for your entire
application context. You can get object of your class on any activity / broadcast receiver / service in application
context(environment) by calling Context.getApplicationContext() method.
package com.androidexample.mobilegcm;
import
import
import
import
import
import
import
import
import
import
import

java.io.IOException;
java.io.OutputStream;
java.net.HttpURLConnection;
java.net.MalformedURLException;
java.net.URL;
java.util.ArrayList;
java.util.HashMap;
java.util.Iterator;
java.util.Map;
java.util.Random;
java.util.Map.Entry;

import com.google.android.gcm.GCMRegistrar;
import
import
import
import
import
import
import
import
import

android.app.AlertDialog;
android.app.Application;
android.content.Context;
android.content.DialogInterface;
android.content.Intent;
android.net.ConnectivityManager;
android.net.NetworkInfo;
android.os.PowerManager;
android.util.Log;

public class Controller extends Application{


private final int MAX_ATTEMPTS = 5;
private final int BACKOFF_MILLI_SECONDS = 2000;
private final Random random = new Random();
private ArrayList<UserData> UserDataArr = new ArrayList<UserData>();

// Register this account with the server.

void register(final Context context, String name,


String email, final String regId,final String IMEI)
{
Log.i(Config.TAG, "registering device (regId = " + regId + ")");
// Server url to post gcm registration data
String serverUrl = Config.YOUR_SERVER_URL+"register.php";
Map<String, String> params = new HashMap<String, String>();
params.put("regId", regId);
params.put("name", name);
params.put("email", email);
params.put("imei", IMEI);
long backoff = BACKOFF_MILLI_SECONDS + random.nextInt(1000);

// Once GCM returns a registration id, we need to register on our server


// As the server might be down, we will retry it a couple
// times.
for (int i = 1; i <= MAX_ATTEMPTS; i++) {
Log.d(Config.TAG, "Attempt #" + i + " to register");
try {
//Send Broadcast to Show message on screen
displayRegistrationMessageOnScreen(context, context.getString(
R.string.server_registering, i, MAX_ATTEMPTS));

// Post registration values to web server


post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, true);
//Send Broadcast to Show message on screen
String message = context.getString(R.string.server_registered);
displayRegistrationMessageOnScreen(context, message);
DBAdapter.addDeviceData(name, email, regId, IMEI);

// Launch Main Activity


Intent i1 = new Intent(getApplicationContext(), GridViewExample.class);
i1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(i1);
return;
} catch (IOException e) {

// Here we are simplifying and retrying on any error; in a real


// application, it should retry only on unrecoverable errors
// (like HTTP error code 503).
Log.e(Config.TAG, "Failed to register on attempt " + i + ":" + e);
if (i == MAX_ATTEMPTS) {
break;
}
try {

Log.d(Config.TAG, "Sleeping for " + backoff + " ms before retry");


Thread.sleep(backoff);
} catch (InterruptedException e1) {
// Activity finished before we complete - exit.
Log.d(Config.TAG, "Thread interrupted: abort remaining retries!");
Thread.currentThread().interrupt();
return;
}
// increase backoff exponentially
backoff *= 2;
}
}
String message = context.getString(R.string.server_register_error,
MAX_ATTEMPTS);
//Send Broadcast to Show message on screen
displayRegistrationMessageOnScreen(context, message);
}
// Unregister this account/device pair within the server.
void unregister(final Context context, final String regId,final String IMEI) {
Log.i(Config.TAG, "unregistering device (regId = " + regId + ")");
String serverUrl = Config.YOUR_SERVER_URL+"unregister.php";
Map<String, String> params = new HashMap<String, String>();

params.put("regId", regId);
params.put("imei", IMEI);
try {

post(serverUrl, params);
GCMRegistrar.setRegisteredOnServer(context, false);
String message = context.getString(R.string.server_unregistered);
displayRegistrationMessageOnScreen(context, message);
} catch (IOException e) {

// At this point the device is unregistered from GCM, but still


// registered in the our server.
// We could try to unregister again, but it is not necessary:
// if the server tries to send a message to the device, it will get
// a "NotRegistered" error message and should unregister the device.
String message = context.getString(R.string.server_unregister_error,
e.getMessage());
Log.i("GCM K", message);
displayRegistrationMessageOnScreen(context, message);
}
}

// Issue a POST request to the server.


private static void post(String endpoint, Map<String, String> params)
throws IOException {
URL url;
try {
url = new URL(endpoint);
} catch (MalformedURLException e) {
throw new IllegalArgumentException("invalid url: " + endpoint);
}

StringBuilder bodyBuilder = new StringBuilder();


Iterator<Entry<String, String>> iterator = params.entrySet().iterator();
// constructs the POST body using the parameters
while (iterator.hasNext()) {
Entry<String, String> param = iterator.next();
bodyBuilder.append(param.getKey()).append('=')
.append(param.getValue());
if (iterator.hasNext()) {
bodyBuilder.append('&');
}
}

String body = bodyBuilder.toString();


Log.v(Config.TAG, "Posting '" + body + "' to " + url);
byte[] bytes = body.getBytes();
HttpURLConnection conn = null;
try {
Log.e("URL", "> " + url);
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setFixedLengthStreamingMode(bytes.length);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded;charset=UTF-8");
// post the request
OutputStream out = conn.getOutputStream();
out.write(bytes);
out.close();
// handle the response
int status = conn.getResponseCode();
// If response is not success
if (status != 200) {
throw new IOException("Post failed with error code " + status);
}
} finally {
if (conn != null) {
conn.disconnect();
}
}
}

// Checking for all possible internet providers


public boolean isConnectingToInternet(){

ConnectivityManager connectivity =
(ConnectivityManager) getSystemService(
Context.CONNECTIVITY_SERVICE);
if (connectivity != null)
{
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null)
for (int i = 0; i < info.length; i++)
if (info[i].getState() == NetworkInfo.State.CONNECTED)
{
return true;
}
}
return false;
}

// Notifies UI to display a message.


void displayRegistrationMessageOnScreen(Context context, String message) {
Intent intent = new Intent(Config.DISPLAY_REGISTRATION_MESSAGE_ACTION);
intent.putExtra(Config.EXTRA_MESSAGE, message);
// Send Broadcast to Broadcast receiver with message
context.sendBroadcast(intent);
}
// Notifies UI to display a message.
void displayMessageOnScreen(Context context, String title,String message,String imei) {
Intent intent = new Intent(Config.DISPLAY_MESSAGE_ACTION);
intent.putExtra(Config.EXTRA_MESSAGE, message);
intent.putExtra("name", title);
intent.putExtra("imei", imei);
// Send Broadcast to Broadcast receiver with message
context.sendBroadcast(intent);
}

//Function to display simple Alert Dialog


public void showAlertDialog(Context context, String title, String message,
Boolean status) {
AlertDialog alertDialog = new AlertDialog.Builder(context).create();

// Set Dialog Title


alertDialog.setTitle(title);
// Set Dialog Message
alertDialog.setMessage(message);

if(status != null)
// Set alert dialog icon
alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail);
// Set OK Button
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
});
// Show Alert Message
alertDialog.show();
}
private PowerManager.WakeLock wakeLock;
public void acquireWakeLock(Context context) {
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, "WakeLock");
wakeLock.acquire();
}
public void releaseWakeLock() {
if (wakeLock != null) wakeLock.release(); wakeLock = null;
}
// Get UserData model object from UserDataArrlist at specified position
public UserData getUserData(int pPosition) {

return UserDataArr.get(pPosition);
}
// Add UserData model object to UserDataArrlist
public void setUserData(UserData Products) {
UserDataArr.add(Products);
}
//Get Number of UserData model object contains by UserDataArrlist
public int getUserDataSize() {
return UserDataArr.size();
}
// Clear all user data from arraylist
public void clearUserData() {
UserDataArr.clear();
}
}

Create SQLite table :


CREATE TABLE IF NOT EXISTS `gcm_users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`gcm_regid` text,
`name` varchar(50) NOT NULL,
`email` varchar(255) NOT NULL,
`imei` varchar(20) NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `imei` (`imei`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Screen Shots:

NOTE : If you will not add google account in your device and run this example you will get gcm error
account_missing.see this screenshot

TESTING:

Create a Test Case


Activity tests are written in a structured way. Make sure to put your tests in a separate package,
distinct from the code under test.
By convention, your test package name should follow the same name as the application package,
suffixed with ".tests". In the test package you created, add the Java class for your test case. By
convention, your test case name should also follow the same name as the Java or Android class
that you want to test, but suffixed with Test.
To create a new test case in Eclipse:
a. In the Package Explorer, right-click on the /src directory for test project and select New >
Package.
b. Set the Name field to <your_app_package_name>.tests (for example,
com.example.android.testingfun.tests) and click Finish.
c. Right-click on the test package you created, and select New > Class.
d. Set the Name field to <your_app_activity_name>Test (for example, MyFirstTestActivityTest) and
click Finish.

Set Up Your Test Fixture


A test fixture consists of objects that must be initialized for running one or more tests. To set up
the test fixture, you can override the setUp() and tearDown() methods in this test. The test runner
automatically runs setUp() before running any other test methods, and tearDown() at the end of
each test method execution. It can use these methods to keep the code for test initialization and
clean up separate from the tests methods.
As a sanity check, it is good practice to verify that the test fixture has been set up correctly, and
the objects that you want to test have been correctly instantiated or initialized. That way, wont
have to see tests failing because something was wrong with the setup of your test fixture. By
convention, the method for verifying test fixture is called testPreconditions().

The assertion methods are from the JUnit Assert class. Generally, you can use
assertions to verify if a specific condition that you want to test is true.

If the condition is false, the assertion method throws an AssertionFailedError exception, which is
then typically reported by the test runner. You can provide a string in the first argument of your
assertion method to give some contextual details if the assertion fails.
If the condition is true, the test passes.

Build and Run Your Test

build and run project test easily from the Package Explorer in Eclipse.
To build and run your test:
1. Connect an Android device to your machine. On the device or emulator, open the Settings menu,
select Developer options and make sure that USB debugging is enabled.
2. In the Project Explorer, right-click on the test class that created earlier and select Run As >
Android Junit Test.
3. In the Android Device Chooser dialog, select the device that just connected, then click OK.
4. In the JUnit view, verify that the test passes with no errors or failures.

In both cases, the test runner proceeds to run the other test methods in the test case.

Creating Unit Tests

An Activity unit test is an excellent way to quickly verify the state of an Activity and its
interactions with other components in isolation (that is, disconnected from the rest of the
system). A unit test generally tests the smallest possible unit of code (which could be a method,
class, or component), without dependencies on system or network resources. For example, you
can write a unit test to check that an Activity has the correct layout or that it triggers an Intent
object correctly.
Unit tests are generally not suitable for testing complex UI interaction events with the system.
Instead, you should use the ActivityInstrumentationTestCase2 class, as described in Testing UI
Components.

MAINTENANCE
Maintenance of Android Application

Install a good ROM and a good Kernel


Official ROMs are good but custom ROMs are usually faster and in many cases as stable as
official ROMs. This is because ROMs are released and thereafter rarely change, custom ROMs
are already made by developers who are constantly improving their job to get the most out of the
phone. It's very important to research before installing a new ROM, searching always for the one
that meets expectations and relates well with device since the same ROM can work very well
on my x10 but not as well on x10 my brothers for example
The same goes for Kernels, but with Kernels take extra care to make sure that the Kernel is
compatible with desired ROM and phone-

Keep clean caches Caches are good to keep certain information and have access to these faster
but with these files and information some "garbage" is stored . The solutions to this can be pretty
basic or advanced, the most basic way is to enter Application Manager (Settings> Applications>
Manage Applications) and clear the cache for each application. It is important to clear the cache
only and not application data as these may be important such as the files that resemble progress
in a game. Already the most advanced solution is to clear the Dalvik Cache and Cache Partition
through recovery.Both solutions dont need to be made with daily frequency, for example I
usually clean my caches every 45 days or when I feel that the phone is getting slow.

Make a full, but clean, backup

Full backups (full system backup) like those made by recovery or nandroid are great to store
complete setups but when they are done with dirty files in the the phones memory restoring
these files may worsen rather than help the situation of device
Ideally, do a full backup after completely configure phone (configure account, set homescreens,
install the required applications, etc.) but before using it for real.
That way if phone starts getting slow and nothing works to reverse the situation it can easily go
back to it's original settings without the hassle of customizing everything in its way again.

Do not touch the CPU / GPU the first dayLike people, phones also take a while to adapt to a
new environment, or in our case new ROMs, so during the first 24 hours of use is important to
use the settings of CPU and GPU that came with the ROM, no overclock, undervolt and things
like that.
Another important step in the process of adaptation to the new ROM is really using and
exploring the device in this very first day so it "get used" to the change. Do not mind the battery
consumption, that should stabilize after a few days.
Its also iimportant to remember that some ROMs already comes with overclock, undervolt and
improvements in battery usage. In this case there is no problem in using these settings from the
first minute because if they are there since the installation of the ROM, it is because they are part
of the default settings already programmed and develop on this particular ROM and it will work
better this way.

Use the maximum batteryBatteries seem to last less and less as time goes on, in part this is
because battery is uncalibrated and there are ways to fix it.

Applications: less is more Having millions of apps is the glory and the doom of smartphones,
the glory because it can do everything on device and doom because of the following reasons:
As a computer a phone also slows down the as it becomes full and in most cases blame it on the
number of apps that havebeen installed on it. So try to leave installed only the applications
actually use and uninstall the ones that no longer use so can have more free memory and
consequently a faster device.
Some applications can not be uninstalled because they are system applications; in order to
remove those apps are going to need uninstallers that have root access (ex: RootUninstaller)
which are capable of removing these applications but before taking such a measure is necessary
to look for a safelist (a list of applications that can be removed without causing system
problems).
Keeping a low number of applications but doing so by installing and uninstalling new apps every
day also usually let the machine slower so if it find an application for a specific function that fits
needs one should stay with it instead of testing another 10 before returning to it
PS: A good way to avoid testing several applications before finding the right one is reading
reviews and comments before making onece choice

Repair defective applicationsOften the phone is working fine but a certain application or
function is not, which can cause slowdowns and FCs (force close); depending on the situation
there is not much to do but some of these solutions may take care of the problem:The first thing
to do is to uninstall and reinstall the apps via Play Store to make sure that the problem was not
caused by a corrupted file when downloaded the application, if the problem persists there are
some more advanced alternatives: in the advanced settings of recovery select fix permissions,
this function should make sure that every application has the necessary permissions to work
properly Keep some free spaceFull memory is often a problem on any device, especially in
older phones like ours, after all the more files the longer it takes read all these files if it is
necessary, so the tip is this: the more free space the better.

Avoid keeping some applications running all the timeIts very common to close an
application and assume that it stopped running on the system but this is not always the case
because it actually still cached in the memory of the device, Android makes it to be faster on
reopening it later and often the system itself definitively closes the application automatically but
thats not always the case.Firstly it is important to prevent certain applications from even
opening and to do this we use apps known as Startup Managers, there are several options in the
Play Store but I particularly like Autostarts. Once inside the Startup Manager one can choose
which applications will be opened as the system is started or any action is taken (for example
changing the state of your Wi-Fi); the ideal is to minimize the number of self-starting
applications, leaving only the truly necessary ones without forgetting to be very careful to avoid
stopping system applications because if they are unable to open themselves it can cause
instability. Another way to prevent applications from opening or stay on cache all the time is to
disable automatic updates of apps such as email clients and social networks but this is a more
personal matter that varies from user to user,
It's easy to know when to quit an application completely but it is necessary to first understand a
basic concept about the system: applications and processes cached in memory are not always a
bad thing, in fact as stated at the beginning of the topic they are a good thing because the
application should open faster when launched again (hence the use of Task Killers usually
worsens more than help if not done properly) but if use an application to view the weather every
morning and will only use it again the next morning this application can be closed without
problems.

CONCLUSION
As it is intended in the Device To Device Messaging Using Google Cloud Messaging GCM Android Application has been developed and tested with Android KIT KAT OS and successfully
running. As initially planed this project was developed as light weight app which will not be
continuously running on android phones but once the message is received the intent will be
created and it will invoke this activity. Thus a robes application which uses PHP as the server
side and JAVA programming for android in devices makes the program to run effectively with
high security and reliability.

FUTURE ENHANCEMENTS
Even though the project is developed successfully it is observed that the following enhancement
and changes will make this project as more effective. The suggested and observed future
enhancements are :

1. Attaching file/files with messaging


2. Attaching videos with instant message
3. Voice chat can also be a future enhancement
4. As it is developed in Android Kit Kat , it need to be redeveloped to suit the old
versions of Android so that majority of the Android Phone and Tab user can use
this applications
5. Incorporating encryption in various level to enhance the security

BIBLIOGRAPHY
Google inc 2014, Android Quick Start Guide
Frank Zammetti -2013. Apress,Specifications of Pro IOS and Android Apps for
Business: With Jquery Mobile, Node.Js, and Mongodb

Ian F. Darwin-2013, Shroff-O'Reilly,Android Cookbook: Problems


and Solutions for Android Developers
https://developer.android.com
www.tutorialspoint.com