In this example sending device to device (Mobile To Mobile) messaging using google cloud messaging (GCM). it is the very basic example you can use this to create advance level messaging application. Using php as server side language and mysql database , you can use other server side language (jsp/asp.net/asp) and database (sqlserver/oracle).
Students can also use this project for semester project. They can modify and inhance example source code.
Here i am 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. 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).
Check this URL for XMPP based GCM Cloud Connection Server (CCS):
http://developer.android.com/google/gcm/ccs.html this url is using Smack API for JAVA
Later i will give example to send device to device message with CCS and XMPP.
But now going with this HTTP based messaging(chatting).
If you are new in Google Cloud Messaging (GCM) implementation then must be read first this example.
Android Push Notifications using Google Cloud Messaging (GCM) - PART 1
In this example using custom grid layout so also read this example.
Custom Grid Layout - Android Example
In this example using custom spinner so also read this example.
Custom Spinner With Image And Text - Android Example
Assuming you have read previous GCM example and familiar with Google cloud messaging basics.
See above image.....
Now We will follow these steps
1. Edit configuration files and create support files.
2. Check device is registered for webserver or not.
2A. if device is not registered then send to registration screen and after gcm registration save GCM regID and device IMEI to mysql database on server , After registration redirect to show all registered devices screen.
2B. if device is registered then get this device regID and IMEI from server and store it in SQLite database on phone and redirect to show all registered devices screen.
3. Select user to send message and after selection show send message screen.
4. When user sending message then send sender IMEI , sendto IMEI and message to web server , webserver get user device data (regID) from mysql database and call gcm to send message to regID.
5. When GCM Client on device get new message store it in SQLite database on phone and show new notification message in notification bar.
6. After clicking notification showmessage screen will open and show all got messages and on showmessage screen user can also send message to other devices (See output video).
In this example i am showing java/xml/php files step by step.
The following permission are required to make your project support gcm.
INTERNET – To make your app use internet services.
ACCESS_NETWORK_STATE – To access network state (used to detect internet status)
GET_ACCOUNTS – Required as GCM needs google account
WAKE_LOCK – Needed if your app need to wake your device when it sleeps
VIBRATE – Needed if your support vibration when receiving notification
Also add some broadcast receivers as mentioned below.
<?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>
In this Example Using two configuration files.
Config.java for client side and config.php for server side.
Using three support files for clients Controller.java, DBAdapter.java, UserData.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"; }
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 + "]"; } }
Sqlite database helper class that defined user and message specific funtions.
This class contains funtions to insert/update/delete user data.
package com.androidexample.mobilegcm; import java.util.ArrayList; import java.util.List; import com.androidexample.mobilegcm.UserData; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import 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"; /**** 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; } }
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 java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Random; import java.util.Map.Entry; import com.google.android.gcm.GCMRegistrar; import android.app.AlertDialog; import android.app.Application; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.PowerManager; import 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 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 ;
To get GOOGLE_API_KEY see this url :
Android Push Notifications using Google Cloud Messaging (GCM) - PART 1
Contains all functions responsible for gcm registration , fetch/insert/delete user data to mysql database.
<?php /** * Storing new user * returns user details */ function storeUser($name, $email, $gcm_regid,$imei) { // insert user into database $result = mysql_query("INSERT INTO gcm_users( name, email, gcm_regid, imei , created_at) VALUES( '$name', '$email', '$gcm_regid', '$imei', NOW())" ); // check for successful store if ($result) { // get user details $id = mysql_insert_id(); // last inserted id $result = mysql_query("SELECT * FROM gcm_users WHERE id = $id") or die(mysql_error()); // return user details if (mysql_num_rows($result) > 0) { return mysql_fetch_array($result); } else { return false; } } else { return false; } } /** * Get user by email */ function getUserByEmail($email) { $result = mysql_query("SELECT * FROM gcm_users WHERE email = '$email' LIMIT 1"); return $result; } /** * Getting all registered users */ function getAllUsers() { $result = mysql_query("select * FROM gcm_users"); return $result; } /** * Getting users detail by IMEI */ function getIMEIUser($imei) { $result = mysql_query("select * FROM gcm_users where imei='$imei'"); return $result; } /** * Getting users detail by REGID */ function getRegIDUser($regID) { $result = mysql_query("select * FROM gcm_users where gcm_regid='$regID'"); return $result; } /** * Getting users */ function getIMEIUserName($imei) { $UserName = ""; $result = mysql_query("select name FROM gcm_users where imei='$imei'"); if(mysql_num_rows($result)) { while($row = mysql_fetch_assoc($result)) { $UserName = $row['name']; } } return $UserName; } /** * Validate user */ function isUserExisted($email,$gcmRegID) { $result = mysql_query("SELECT email from gcm_users WHERE email = '$email' and gcm_regid = '$gcmRegID'"); $NumOfRows = mysql_num_rows($result); if ($NumOfRows > 0) { // user existed return true; } else { // user not existed return false; } } /** * Sending Push Notification */ function send_push_notification($registatoin_ids, $message) { // Set POST variables $url = 'https://android.googleapis.com/gcm/send'; $fields = array( 'registration_ids' => $registatoin_ids, 'data' => $message, ); $headers = array( 'Authorization: key=' . GOOGLE_API_KEY, 'Content-Type: application/json' ); //print_r($headers); // Open connection $ch = curl_init(); // Set the url, number of POST vars, POST data curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Disabling SSL Certificate support temporarly curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields)); // Execute post $result = curl_exec($ch); if ($result === FALSE) { die('Curl failed: ' . curl_error($ch)); } // Close connection curl_close($ch); echo $result; } function stripUnwantedTags($str) { $tempStr = $str; $tempStr = str_replace('script','scriptd',$tempStr); $tempStr = str_replace('iframe','iframed',$tempStr); $tempStr = str_replace('base64','',$tempStr); $tempStr = str_replace('eval(','',$tempStr); $tempStr = str_replace('data:','',$tempStr); //$tempStr = htmlentities($tempStr, ENT_QUOTES, "UTF-8"); return $tempStr; } function escapeStr($str) { $tempStr = htmlentities($str, ENT_QUOTES, "UTF-8"); return str_replace("'","",$tempStr); } function escapeStrMysql($str){ return mysql_real_escape_string($str); } function stripHtmlTags($str){ return strip_tags($str); } function stripUnwantedHtmlEscape($str) { return escapeStrMysql(escapeStr(stripUnwantedTags(stripHtmlTags($str)))); } ?>
Include configuration and function file and make database connection. loader.php is centralized file and it will include by other php file.
<?php require_once('config.php'); require_once('function.php'); // connecting to mysql $conn = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD); // selecting database if(!mysql_select_db(DB_DATABASE)) print "Not connected with database."; ?>
Validate device from client side and from server side.
package com.androidexample.mobilegcm; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.app.Activity; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncTask; import android.os.Bundle; import android.telephony.TelephonyManager; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import com.androidexample.mobilegcm.R; import com.androidexample.mobilegcm.GridViewExample.LongOperation; import com.google.android.gcm.GCMRegistrar; public class Main extends Activity { // label to display gcm messages TextView lblMessage; Controller aController; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /******************* Intialize Database *************/ DBAdapter.init(this); // Get Global Controller Class object // (see application tag in AndroidManifest.xml) aController = (Controller) getApplicationContext(); // Check if Internet present if (!aController.isConnectingToInternet()) { // Internet Connection is not present aController.showAlertDialog(Main.this, "Internet Connection Error", "Please connect to Internet connection", false); // stop executing code by return return; } //Check device contains self information in sqlite database or not. int vDevice = DBAdapter.validateDevice(); if(vDevice > 0) { // Launch Main Activity Intent i = new Intent(getApplicationContext(), GridViewExample.class); startActivity(i); finish(); } else { String deviceIMEI = ""; if(Config.SECOND_SIMULATOR){ //Make it true in CONFIG if you want to open second simutor // for testing actually we are using IMEI number to save a unique device deviceIMEI = "000000000000001"; } else { // GET IMEI NUMBER TelephonyManager tManager = (TelephonyManager) getBaseContext() .getSystemService(Context.TELEPHONY_SERVICE); deviceIMEI = tManager.getDeviceId(); } /******* Validate device from server ******/ // WebServer Request URL String serverURL = Config.YOUR_SERVER_URL+"validate_device.php"; // Use AsyncTask execute Method To Prevent ANR Problem LongOperation serverRequest = new LongOperation(); serverRequest.execute(serverURL,deviceIMEI,"",""); } } // Class with extends AsyncTask class public class LongOperation extends AsyncTask<String, Void, String> { // Required initialization //private final HttpClient Client = new DefaultHttpClient(); // private Controller aController = null; private String Error = null; private ProgressDialog Dialog = new ProgressDialog(Main.this); String data =""; int sizeData = 0; protected void onPreExecute() { // NOTE: You can call UI Element here. //Start Progress Dialog (Message) Dialog.setMessage("Validating Device.."); Dialog.show(); } // Call after onPreExecute method protected String doInBackground(String... params) { /************ Make Post Call To Web Server ***********/ BufferedReader reader=null; String Content = ""; // Send data try{ // Defined URL where to send data URL url = new URL(params[0]); // Set Request parameter if(!params[1].equals("")) data +="&" + URLEncoder.encode("data1", "UTF-8") + "="+params[1].toString(); if(!params[2].equals("")) data +="&" + URLEncoder.encode("data2", "UTF-8") + "="+params[2].toString(); if(!params[3].equals("")) data +="&" + URLEncoder.encode("data3", "UTF-8") + "="+params[3].toString(); Log.i("GCM",data); // Send POST data request URLConnection conn = url.openConnection(); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write( data ); wr.flush(); // Get the server response reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line = null; // Read Server Response while((line = reader.readLine()) != null) { // Append server response in string sb.append(line + " "); } // Append Server Response To Content String Content = sb.toString(); } catch(Exception ex) { Error = ex.getMessage(); } finally { try { reader.close(); } catch(Exception ex) {} } /*****************************************************/ return Content; } protected void onPostExecute(String Content) { // NOTE: You can call UI Element here. // Close progress dialog Dialog.dismiss(); if (Error != null) { } else { // Show Response Json On Screen (activity) /****************** Start Parse Response JSON Data *************/ aController.clearUserData(); JSONObject jsonResponse; try { // Creates a new JSONObject with name/value mappings from the JSON string. jsonResponse = new JSONObject(Content); // Returns the value mapped by name if it exists and is a JSONArray. // Returns null otherwise. JSONArray jsonMainNode = jsonResponse.optJSONArray("Android"); /*********** Process each JSON Node ************/ int lengthJsonArr = jsonMainNode.length(); for(int i=0; i < lengthJsonArr; i++) { /****** Get Object for each JSON node.***********/ JSONObject jsonChildNode = jsonMainNode.getJSONObject(i); /******* Fetch node values **********/ String Status = jsonChildNode.optString("status").toString(); Log.i("GCM","---"+Status); // IF server response status is update if(Status.equals("update")){ String RegID = jsonChildNode.optString("regid").toString(); String Name = jsonChildNode.optString("name").toString(); String Email = jsonChildNode.optString("email").toString(); String IMEI = jsonChildNode.optString("imei").toString(); // add device self data in sqlite database DBAdapter.addDeviceData(Name, Email,RegID, IMEI); // Launch GridViewExample Activity Intent i1 = new Intent(getApplicationContext(), GridViewExample.class); startActivity(i1); finish(); //Log.i("GCM","---"+Name); } else if(Status.equals("install")){ // IF server response status is install // Launch RegisterActivity Activity Intent i1 = new Intent(getApplicationContext(), RegisterActivity.class); startActivity(i1); finish(); } } /****************** End Parse Response JSON Data *************/ } catch (JSONException e) { e.printStackTrace(); } } } } @Override protected void onDestroy() { super.onDestroy(); } }
This will validate user from mysql database by IMEI number posted from Main.java
if IMEI number found then send user data as JSON to device with status "update".
if IMEI number not found then send user data as JSON to device with status "install".
<?php require_once('loader.php'); $imei = $_REQUEST['data1']; $regID = $_REQUEST['data2']; //$resultUsers = getRegIDUser($regID); $resultUsers = getIMEIUser($imei); if ($resultUsers != false) $NumOfUsers = mysql_num_rows($resultUsers); else $NumOfUsers = 0; $jsonData = array(); if ($NumOfUsers > 0) { while ($rowUsers = mysql_fetch_array($resultUsers)) { $jsonTempData = array(); $jsonTempData['regid'] = $rowUsers["gcm_regid"]; $jsonTempData['name'] = $rowUsers["name"]; $jsonTempData['email'] = $rowUsers["email"]; $jsonTempData['imei'] = $rowUsers["imei"]; $jsonTempData['status'] = "update"; $jsonData[] = $jsonTempData; } } else{ $jsonTempData = array(); $jsonTempData['regid'] = ""; $jsonTempData['name'] = ""; $jsonTempData['email'] = ""; $jsonTempData['imei'] = ""; $jsonTempData['status'] = "install"; $jsonData[] = $jsonTempData; } $outputArr = array(); $outputArr['Android'] = $jsonData; // Encode Array To JSON Data print_r( json_encode($outputArr)); ?>
2A. if device is not registered then send to registration screen and after gcm registration store GCM regID and device IMEI to mysql database on server , After registration redirect to show all registered devices screen.
Registration screen layout , fill name and mail id and send to MainActivity.java for GCM registration.
package com.androidexample.mobilegcm; import com.androidexample.mobilegcm.R; import com.androidexample.mobilegcm.DBAdapter; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; public class RegisterActivity extends Activity { // UI elements EditText txtName; EditText txtEmail; // Register button Button btnRegister; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /******************* Intialize Database *************/ DBAdapter.init(this); setContentView(R.layout.activity_register); //Get Global Controller Class object (see application tag in AndroidManifest.xml) final Controller aController = (Controller) getApplicationContext(); // Check if Internet Connection present if (!aController.isConnectingToInternet()) { // Internet Connection is not present aController.showAlertDialog(RegisterActivity.this, "Internet Connection Error", "Please connect to working Internet connection", false); // stop executing code by return return; } // Check if GCM configuration is set if (Config.YOUR_SERVER_URL == null || Config.GOOGLE_SENDER_ID == null || Config.YOUR_SERVER_URL.length() == 0 || Config.GOOGLE_SENDER_ID.length() == 0) { // GCM sernder id / server url is missing aController.showAlertDialog(RegisterActivity.this, "Configuration Error!", "Please set your Server URL and GCM Sender ID", false); // stop executing code by return return; } txtName = (EditText) findViewById(R.id.txtName); txtEmail = (EditText) findViewById(R.id.txtEmail); btnRegister = (Button) findViewById(R.id.btnRegister); // Click event on Register button btnRegister.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // Get data from EditText String name = txtName.getText().toString(); String email = txtEmail.getText().toString(); // Check if user filled the form if(name.trim().length() > 0 && email.trim().length() > 0){ // Launch Main Activity Intent i = new Intent(getApplicationContext(), MainActivity.class); // Registering user on our server // Sending registraiton details to MainActivity i.putExtra("name", name); i.putExtra("email", email); startActivity(i); finish(); }else{ // user doen't filled that data aController.showAlertDialog(RegisterActivity.this, "Registration Error!", "Please enter your details", false); } } }); } }
<LinearLayout 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:orientation="vertical" android:background="#ffffff"> <ImageView android:src="@drawable/user_thumb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="10px" android:layout_marginBottom="20dip"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Full Name:" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:layout_marginTop="20dip" android:textColor="#000000"/> <EditText android:id="@+id/txtName" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="10dip" android:layout_marginBottom="20dip"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Email:" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:textColor="#000000"/> <EditText android:id="@+id/txtEmail" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_margin="10dip" android:layout_marginBottom="20dip"/> <Button android:id="@+id/btnRegister" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Register" android:layout_margin="10dip"/> </LinearLayout>
Register device for Google Cloud Messaging(GCM) after successfull gcm registartion sending gcm regID to server and store regID ,name,IMEI in mysql database for further use to send messages from gcm.
MainActivity.java file is using Controller.java methods for registration(see controller class register() and post() method).
Creating a broadcast receiver to get gcm message and show on screen(MainActivity.java).
package com.androidexample.mobilegcm; import android.app.Activity; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.AsyncTask; import android.os.Bundle; import android.telephony.TelephonyManager; import android.util.Log; import android.widget.TextView; import android.widget.Toast; import com.androidexample.mobilegcm.R; import com.google.android.gcm.GCMRegistrar; public class MainActivity extends Activity { // label to display gcm messages TextView lblMessage; Controller aController; // Asyntask AsyncTask<Void, Void, Void> mRegisterTask; public static String name; public static String email; public static String imei; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Get Global Controller Class object // (see application tag in AndroidManifest.xml) aController = (Controller) getApplicationContext(); // Check if Internet present if (!aController.isConnectingToInternet()) { // Internet Connection is not present aController.showAlertDialog(MainActivity.this, "Internet Connection Error", "Please connect to Internet connection", false); // stop executing code by return return; } String deviceIMEI = ""; if(Config.SECOND_SIMULATOR){ //Make it true in CONFIG if you want to open second simutor // for testing actually we are using IMEI number to save a unique device deviceIMEI = "000000000000001"; } else { // GET IMEI NUMBER TelephonyManager tManager = (TelephonyManager) getBaseContext() .getSystemService(Context.TELEPHONY_SERVICE); deviceIMEI = tManager.getDeviceId(); } // Getting name, email from intent Intent i = getIntent(); name = i.getStringExtra("name"); email = i.getStringExtra("email"); imei = deviceIMEI; // Make sure the device has the proper dependencies. GCMRegistrar.checkDevice(this); // Make sure the manifest permissions was properly set GCMRegistrar.checkManifest(this); lblMessage = (TextView) findViewById(R.id.lblMessage); // Register custom Broadcast receiver to show messages on activity registerReceiver(mHandleMessageReceiver, new IntentFilter( Config.DISPLAY_REGISTRATION_MESSAGE_ACTION)); // Get GCM registration id final String regId = GCMRegistrar.getRegistrationId(this); // Check if regid already presents if (regId.equals("")) { Log.i("GCM K", "--- Regid = ''"+regId); // Register with GCM GCMRegistrar.register(this, Config.GOOGLE_SENDER_ID); } else { // Device is already registered on GCM Server if (GCMRegistrar.isRegisteredOnServer(this)) { final Context context = this; // Skips registration. Toast.makeText(getApplicationContext(), "Already registered with GCM Server", Toast.LENGTH_LONG).show(); Log.i("GCM K", "Already registered with GCM Server"); //GCMRegistrar.unregister(context); } else { Log.i("GCM K", "-- gO for registration--"); // Try to register again, but not in the UI thread. // It's also necessary to cancel the thread onDestroy(), // hence the use of AsyncTask instead of a raw thread. final Context context = this; mRegisterTask = new AsyncTask<Void, Void, Void>() { @Override protected Void doInBackground(Void... params) { // Register on our server // On server creates a new user aController.register(context, name, email, regId,imei); return null; } @Override protected void onPostExecute(Void result) { mRegisterTask = null; finish(); } }; // execute AsyncTask mRegisterTask.execute(null, null, null); } } } // Create a broadcast receiver to get message and show on screen private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String newMessage = intent.getExtras().getString(Config.EXTRA_MESSAGE); // Waking up mobile if it is sleeping aController.acquireWakeLock(getApplicationContext()); // Display message on the screen lblMessage.append(newMessage + " "); Toast.makeText(getApplicationContext(), "Got Message: " + newMessage, Toast.LENGTH_LONG).show(); // Releasing wake lock aController.releaseWakeLock(); } }; @Override protected void onDestroy() { // Cancel AsyncTask if (mRegisterTask != null) { mRegisterTask.cancel(true); } try { // Unregister Broadcast Receiver unregisterReceiver(mHandleMessageReceiver); //Clear internal resources. GCMRegistrar.onDestroy(this); } catch (Exception e) { Log.e("UnRegister Receiver Error", "> " + e.getMessage()); } super.onDestroy(); } }
MainActivity.java file is using register.php file to post GCM and device data to server.
This file will get post data and store it in mysql database.
Send a registration confirm message to device.
<?php require_once('loader.php'); // return json response $json = array(); $nameUser = stripUnwantedHtmlEscape($_POST["name"]); $emailUser = stripUnwantedHtmlEscape($_POST["email"]); $gcmRegID = stripUnwantedHtmlEscape($_POST["regId"]); // GCM Registration ID got from device $imei = stripUnwantedHtmlEscape($_POST["imei"]); // Send this message to device $message = $nameUser."^".$imei."^Registered on server."; /** * Registering a user device in database * Store reg id in users table */ if ( isset($nameUser) && isset($emailUser) && isset($gcmRegID) && $nameUser!="" && $imei!="" && $gcmRegID!="" && $emailUser!="" ) { if(!isUserExisted($emailUser,$gcmRegID)) { // Store user details in db $res = storeUser($nameUser, $emailUser, $gcmRegID,$imei); $registatoin_ids = array($gcmRegID); $messageSend = array("message" => $message); $result = send_push_notification($registatoin_ids, $messageSend); }//echo $result; } else { // user details not found echo "Wrong values."; } ?>
Used for MainActivity.java file layout.
<LinearLayout 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:orientation="vertical" android:background="#ffffff" > <TextView android:id="@+id/lblMessage" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textSize="16dip" android:layout_margin="10dip" android:textColor="#000000"/> </LinearLayout>
2B. if device is already registered then get this device regID and IMEI from server and store it in SQLite database on phone and redirect to show all registered devices screen.
This file is showing all registered user in a Custom grid view.
Calling userdata.php file from server and get all user data as JSON and show data in a custom gridview (see custom grid view example).
After grid selection redirect to ShowMessage.java file with selected user data.
package com.androidexample.mobilegcm; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import com.androidexample.mobilegcm.CustomGridAdapter; import android.app.Activity; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.widget.AdapterView; import android.widget.GridView; import android.telephony.TelephonyManager; import android.util.Log; import android.view.View; import android.widget.AdapterView.OnItemClickListener; public class GridViewExample extends Activity { GridView gridView; Controller aController = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.grid_view_android_example); //Get gridview object from xml file gridView = (GridView) findViewById(R.id.gridView1); // Get Global variable instance aController = (Controller) getApplicationContext(); // WebServer Request URL to get All registered devices String serverURL = Config.YOUR_SERVER_URL+"userdata.php"; // Use AsyncTask execute Method To Prevent ANR Problem LongOperation serverRequest = new LongOperation(); serverRequest.execute(serverURL,"rrr","",""); gridView.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> parent, View v, int position, long id) { String deviceIMEI = ""; if(Config.SECOND_SIMULATOR){ //Make it true in CONFIG if you want to open second simutor // for testing actually we are using IMEI number to save a unique device deviceIMEI = "000000000000001"; } else { // GET IMEI NUMBER TelephonyManager tManager = (TelephonyManager) getBaseContext() .getSystemService(Context.TELEPHONY_SERVICE); deviceIMEI = tManager.getDeviceId(); } String uIMEI = aController.getUserData(position).getIMEI(); String uName = aController.getUserData(position).getName(); // Launch Main Activity Intent i = new Intent(getApplicationContext(), SendPushNotification.class); // Registering user on our server // Sending registraiton details to MainActivity i.putExtra("name", uName); i.putExtra("imei", uIMEI); // Send to i.putExtra("sendfrom", deviceIMEI); startActivity(i); } }); } // Class with extends AsyncTask class public class LongOperation extends AsyncTask<String, Void, String> { // Required initialization //private final HttpClient Client = new DefaultHttpClient(); // private Controller aController = null; private String Error = null; private ProgressDialog Dialog = new ProgressDialog(GridViewExample.this); String data =""; int sizeData = 0; protected void onPreExecute() { // NOTE: You can call UI Element here. //Start Progress Dialog (Message) Dialog.setMessage("Getting registered users .."); Dialog.show(); } // Call after onPreExecute method protected String doInBackground(String... params) { /************ Make Post Call To Web Server ***********/ BufferedReader reader=null; String Content = ""; // Send data try{ // Defined URL where to send data URL url = new URL(params[0]); // Set Request parameter if(!params[1].equals("")) data +="&" + URLEncoder.encode("data", "UTF-8") + "="+params[1].toString(); if(!params[2].equals("")) data +="&" + URLEncoder.encode("data2", "UTF-8") + "="+params[2].toString(); if(!params[3].equals("")) data +="&" + URLEncoder.encode("data3", "UTF-8") + "="+params[3].toString(); Log.i("GCM",data); // Send POST data request URLConnection conn = url.openConnection(); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write( data ); wr.flush(); // Get the server response reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line = null; // Read Server Response while((line = reader.readLine()) != null) { // Append server response in string sb.append(line + " "); } // Append Server Response To Content String Content = sb.toString(); } catch(Exception ex) { Error = ex.getMessage(); } finally { try { reader.close(); } catch(Exception ex) {} } /*****************************************************/ return Content; } protected void onPostExecute(String Content) { // NOTE: You can call UI Element here. // Close progress dialog Dialog.dismiss(); if (Error != null) { } else { // Show Response Json On Screen (activity) /****************** Start Parse Response JSON Data *************/ aController.clearUserData(); JSONObject jsonResponse; try { // Creates a new JSONObject with name/value mappings from the JSON string. jsonResponse = new JSONObject(Content); // Returns the value mapped by name if it exists and is a JSONArray. // Returns null otherwise. JSONArray jsonMainNode = jsonResponse.optJSONArray("Android"); /*********** Process each JSON Node ************/ int lengthJsonArr = jsonMainNode.length(); for(int i=0; i < lengthJsonArr; i++) { /****** Get Object for each JSON node.***********/ JSONObject jsonChildNode = jsonMainNode.getJSONObject(i); /******* Fetch node values **********/ String IMEI = jsonChildNode.optString("imei").toString(); String Name = jsonChildNode.optString("name").toString(); Log.i("GCM","---"+Name); UserData userdata = new UserData(); userdata.setIMEI(IMEI); userdata.setName(Name); //Add user data to controller class UserDataArr arraylist aController.setUserData(userdata); } /****************** End Parse Response JSON Data *************/ // Set grid adapter to CustomGridAdapter gridView.setAdapter(new CustomGridAdapter(getBaseContext(), aController)); } catch (JSONException e) { e.printStackTrace(); } } } } }
GridViewExample.java file used userdata.php to get all registered user devices.
Return all registered user device data as JSON.
<?php require_once('loader.php'); $resultUsers = getAllUsers(); if ($resultUsers != false) $NumOfUsers = mysql_num_rows($resultUsers); else $NumOfUsers = 0; $jsonData = array(); if ($NumOfUsers > 0) { $jsonTempData = array(); $jsonTempData['imei'] = "All"; $jsonTempData['regid'] = "All"; $jsonTempData['name'] = "Send To All"; $jsonTempData['error'] = "y"; $jsonData[] = $jsonTempData; while ($rowUsers = mysql_fetch_array($resultUsers)) { $jsonTempData = array(); $jsonTempData['imei'] = $rowUsers["imei"]; $jsonTempData['regid'] = $rowUsers["gcm_regid"]; $jsonTempData['name'] = $rowUsers["name"]; $jsonTempData['error'] = "y"; $jsonData[] = $jsonTempData; } } else{ $jsonTempData = array(); $jsonTempData['imei'] = "Data not found."; $jsonTempData['regid'] = "Data not found."; $jsonTempData['name'] = "Data not found."; $jsonTempData['error'] = "n"; $jsonData[] = $jsonTempData; } $outputArr = array(); $outputArr['Android'] = $jsonData; // Encode Array To JSON Data print_r( json_encode($outputArr)); ?>
<?xml version="1.0" encoding="utf-8"?> <GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gridView1" android:numColumns="auto_fit" android:gravity="center" android:columnWidth="100dp" android:stretchMode="columnWidth" android:layout_width="fill_parent" android:layout_height="fill_parent" > </GridView>
package com.androidexample.mobilegcm; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class CustomGridAdapter extends BaseAdapter { private Context context; //private final String[] gridValues; private Controller aController; //Constructor to initialize values public CustomGridAdapter(Context context, Controller aController) { this.context = context; this.aController = aController; } @Override public int getCount() { // Number of times getView method call depends upon gridValues.length return aController.getUserDataSize(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } // Number of times getView method call depends upon gridValues.length public View getView(int position, View convertView, ViewGroup parent) { //LayoutInflator to call external grid_item.xml file LayoutInflater inflater = (LayoutInflater) context .getSystemService(Context.LAYOUT_INFLATER_SERVICE); View gridView; if (convertView == null) { gridView = new View(context); // get layout from grid_item.xml gridView = inflater.inflate(R.layout.grid_item, null); UserData userdataObj = aController.getUserData(position); // set value into textview TextView textView = (TextView) gridView .findViewById(R.id.grid_item_label); textView.setText(userdataObj.getName()); } else { gridView = (View) convertView; } return gridView; } }
xml file used in CustomGridAdapter.java file.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:orientation="vertical" > <ImageView android:id="@+id/grid_item_image" android:layout_width="50px" android:layout_height="50px" android:layout_marginRight="10px" android:src="@drawable/user_thumb" > </ImageView> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="0dp" android:orientation="vertical"> <TextView android:id="@+id/grid_item_label" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:layout_marginTop="3px" android:textSize="15px" android:textStyle="bold"> </TextView> <TextView android:id="@+id/grid_item_label_static" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" android:layout_marginTop="3px" android:textSize="12px" /> </LinearLayout> </LinearLayout>
Get user values got from GridViewExample.java file.
Write your message.
Send message and values to sendpush.php file.
package com.androidexample.mobilegcm; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import com.androidexample.mobilegcm.R; import com.androidexample.mobilegcm.DBAdapter; import android.app.Activity; import android.app.ProgressDialog; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class SendPushNotification extends Activity { // UI elements EditText txtMessage; TextView sendTo; // Register button Button btnSend; Controller aController = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); /******************* Intialize Database *************/ DBAdapter.init(this); setContentView(R.layout.send_push_notification); //Get Global Controller Class object (see application tag in AndroidManifest.xml) aController = (Controller) getApplicationContext(); // Check if Internet Connection present if (!aController.isConnectingToInternet()) { // Internet Connection is not present aController.showAlertDialog(SendPushNotification.this, "Internet Connection Error", "Please connect to working Internet connection", false); // stop executing code by return return; } // Getting name, email from intent Intent i = getIntent(); final String name = i.getStringExtra("name"); final String imei = i.getStringExtra("imei"); final String sendfrom = i.getStringExtra("sendfrom"); txtMessage = (EditText) findViewById(R.id.txtMessage); sendTo = (TextView) findViewById(R.id.sendTo); btnSend = (Button) findViewById(R.id.btnSend); sendTo.setText("Send To : "+name); // Click event on Register button btnSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // Get data from EditText String message = txtMessage.getText().toString(); // WebServer Request URL String serverURL = Config.YOUR_SERVER_URL+"sendpush.php"; // Use AsyncTask execute Method To Prevent ANR Problem new LongOperation().execute(serverURL,imei,message,sendfrom); txtMessage.setText(""); } }); } public class LongOperation extends AsyncTask<String, Void, String> { // Required initialization //private final HttpClient Client = new DefaultHttpClient(); // private Controller aController = null; private String Error = null; private ProgressDialog Dialog = new ProgressDialog(SendPushNotification.this); String data = ""; int sizeData = 0; protected void onPreExecute() { // NOTE: You can call UI Element here. //Start Progress Dialog (Message) Dialog.setMessage("Please wait.."); Dialog.show(); } // Call after onPreExecute method protected String doInBackground(String... params) { /************ Make Post Call To Web Server ***********/ BufferedReader reader=null; String Content = ""; // Send data try{ // Defined URL where to send data URL url = new URL(params[0]); // Set Request parameter if(!params[1].equals("")) data +="&" + URLEncoder.encode("data1", "UTF-8") + "="+params[1].toString(); if(!params[2].equals("")) data +="&" + URLEncoder.encode("data2", "UTF-8") + "="+params[2].toString(); if(!params[3].equals("")) data +="&" + URLEncoder.encode("data3", "UTF-8") + "="+params[3].toString(); // Send POST data request URLConnection conn = url.openConnection(); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write( data ); wr.flush(); // Get the server response reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line = null; // Read Server Response while((line = reader.readLine()) != null) { // Append server response in string sb.append(line + " "); } // Append Server Response To Content String Content = sb.toString(); } catch(Exception ex) { Error = ex.getMessage(); } finally { try { reader.close(); } catch(Exception ex) {} } /*****************************************************/ return Content; } protected void onPostExecute(String Result) { // NOTE: You can call UI Element here. // Close progress dialog Dialog.dismiss(); if (Error != null) { Toast.makeText(getBaseContext(), "Error: "+Error, Toast.LENGTH_LONG).show(); } else { // Show Response Json On Screen (activity) Toast.makeText(getBaseContext(), "Message sent."+Result, Toast.LENGTH_LONG).show(); } } } }
Got imei number and message , send gcm message to device.
<?php require_once('loader.php'); $imei = $_REQUEST['data1']; $message = $_REQUEST['data2']; $sendToIMEI = $_REQUEST['data3']; $regID = $_REQUEST['data4']; $UserName = getIMEIUserName($sendToIMEI); $message = $UserName."^".$sendToIMEI."^".$message; if($imei == "All") $resultUsers = getAllUsers(); else $resultUsers = getRegIDUser($regID) if ($resultUsers != false) $NumOfUsers = mysql_num_rows($resultUsers); else $NumOfUsers = 0; if ($NumOfUsers > 0) { while ($rowUsers = mysql_fetch_array($resultUsers)) { $gcmRegID = $rowUsers["gcm_regid"]; // GCM Registration ID got from device $pushMessage = $message; if (isset($gcmRegID) && isset($pushMessage)) { $registatoin_ids = array($gcmRegID); $messageSend = array("message" => $pushMessage); $result = send_push_notification($registatoin_ids, $messageSend); echo $result; //echo "Message sent."; } } } else print "Data not found."; ?>
<LinearLayout 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:orientation="vertical" android:background="#ffffff"> <ImageView android:src="@drawable/user_thumb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="10px" android:layout_marginBottom="5dip"/> <TextView android:id="@+id/sendTo" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Send To : " android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:textColor="#000000"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Message:" android:layout_marginLeft="10dip" android:layout_marginRight="10dip" android:layout_marginTop="20dip" android:textColor="#000000"/> <EditText android:id="@+id/txtMessage" android:layout_width="fill_parent" android:textColor="#000000" android:layout_height="116dp" android:layout_margin="10dip" android:layout_marginBottom="20dip" android:height="100dp" /> <Button android:id="@+id/btnSend" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Send" android:layout_margin="10dip"/> </LinearLayout>
This is the main GCM Client file. this file methods automatically called when GCM events occoured.
onRegistered() : This method automatically called when GCMRegistrar.register(this, Config.GOOGLE_SENDER_ID) method call.
onUnregistered() : This method automatically called when GCMRegistrar.unregister(context) method call.
onMessage() : This method automatically called when Receiving a new message from GCM server.
For other functions see comments in GCMIntentService.java file.
package com.androidexample.mobilegcm; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.util.Log; import android.widget.Toast; import com.androidexample.mobilegcm.R; import com.google.android.gcm.GCMBaseIntentService; public class GCMIntentService extends GCMBaseIntentService { private static final String TAG = "GCMIntentService"; private Controller aController = null; public GCMIntentService() { // Call extended class Constructor GCMBaseIntentService super(Config.GOOGLE_SENDER_ID); } /** * Method called on device registered **/ @Override protected void onRegistered(Context context, String registrationId) { //Get Global Controller Class object (see application tag in AndroidManifest.xml) if(aController == null) aController = (Controller) getApplicationContext(); Log.i(TAG, "---------- onRegistered -------------"); Log.i(TAG, "Device registered: regId = " + registrationId); aController.displayRegistrationMessageOnScreen(context, "Your device registred with GCM"); Log.d("NAME", MainActivity.name); aController.register(context, MainActivity.name, MainActivity.email, registrationId,MainActivity.imei); DBAdapter.addDeviceData(MainActivity.name, MainActivity.email, registrationId, MainActivity.imei); } /** * Method called on device unregistred * */ @Override protected void onUnregistered(Context context, String registrationId) { if(aController == null) aController = (Controller) getApplicationContext(); Log.i(TAG, "---------- onUnregistered -------------"); Log.i(TAG, "Device unregistered"); aController.displayRegistrationMessageOnScreen(context, getString(R.string.gcm_unregistered)); aController.unregister(context, registrationId,MainActivity.imei); } /** * Method called on Receiving a new message from GCM server * */ @Override protected void onMessage(Context context, Intent intent) { if(aController == null) aController = (Controller) getApplicationContext(); Log.i(TAG, "---------- onMessage -------------"); String message = intent.getExtras().getString("message"); Log.i("GCM","message : "+message); String[] StringAll; StringAll = message.split("\^"); String title = ""; String imei = ""; int StringLength = StringAll.length; if (StringLength > 0) { title = StringAll[0]; imei = StringAll[1]; message = StringAll[2]; } // Call broadcast defined on ShowMessage.java to show message on ShowMessage.java screen aController.displayMessageOnScreen(context, title,message,imei); // Store new message data in sqlite database UserData userdata = new UserData(1,imei,title,message); DBAdapter.addUserData(userdata); // generate notification to notify user generateNotification(context, title,message,imei); } /** * Method called on receiving a deleted message * */ @Override protected void onDeletedMessages(Context context, int total) { if(aController == null) aController = (Controller) getApplicationContext(); Log.i(TAG, "---------- onDeletedMessages -------------"); String message = getString(R.string.gcm_deleted, total); String title = "DELETED"; // aController.displayMessageOnScreen(context, message); // notifies user generateNotification(context,title, message,""); } /** * Method called on Error * */ @Override public void onError(Context context, String errorId) { if(aController == null) aController = (Controller) getApplicationContext(); Log.i(TAG, "---------- onError -------------"); Log.i(TAG, "Received error: " + errorId); aController.displayRegistrationMessageOnScreen(context, getString(R.string.gcm_error, errorId)); } @Override protected boolean onRecoverableError(Context context, String errorId) { if(aController == null) aController = (Controller) getApplicationContext(); Log.i(TAG, "---------- onRecoverableError -------------"); // log message Log.i(TAG, "Received recoverable error: " + errorId); aController.displayRegistrationMessageOnScreen(context, getString(R.string.gcm_recoverable_error, errorId)); return super.onRecoverableError(context, errorId); } /** * Create a notification to inform the user that server has sent a message. */ private static void generateNotification(Context context,String title, String message, String imei) { int icon = R.drawable.user_thumb; long when = System.currentTimeMillis(); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = new Notification(icon, message, when); Intent notificationIntent = new Intent(context, ShowMessage.class); // set intent so it does not start a new activity notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); notificationIntent.putExtra("name", title); notificationIntent.putExtra("message", message); notificationIntent.putExtra("imei", imei); PendingIntent intent = PendingIntent.getActivity(context, 0, notificationIntent, 0); notification.setLatestEventInfo(context, title, message, intent); notification.flags |= Notification.FLAG_AUTO_CANCEL; // Play default notification sound notification.defaults |= Notification.DEFAULT_SOUND; /*notification.sound = Uri.parse("android.resource://" + context.getPackageName() + "your_sound_file_name.mp3");*/ // Vibrate if vibrate is enabled notification.defaults |= Notification.DEFAULT_VIBRATE; notificationManager.notify(0, notification); } }
This activity is in two parts
In first part showing incomming messages in a scrollview.
In second part showing send message and select user UI, For select user to send message using custom spinner (See custom spinner android example).
Created BroadcastReceiver to update incomming messages on screen.
package com.androidexample.mobilegcm; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.app.ProgressDialog; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.res.Resources; import android.os.AsyncTask; import android.os.Bundle; import android.telephony.TelephonyManager; import android.util.Log; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemSelectedListener; import android.widget.Button; import android.widget.EditText; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.androidexample.mobilegcm.R; public class ShowMessage extends Activity { // UI elements EditText txtMessage; // Send Message button Button btnSend; // label to display gcm messages TextView lblMessage; Controller aController; // Asyntask AsyncTask<Void, Void, Void> mRegisterTask; String name; String message; String UserDeviceIMEI; /************** Intialize Variables *************/ public ArrayList<UserData> CustomListViewValuesArr = new ArrayList<UserData>(); TextView output = null; CustomAdapter adapter; ShowMessage activity = null; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.show_message); /******************* Intialize Database *************/ DBAdapter.init(this); // Get Global Controller Class object // (see application tag in AndroidManifest.xml) aController = (Controller) getApplicationContext(); // Check if Internet present if (!aController.isConnectingToInternet()) { // Internet Connection is not present aController.showAlertDialog(ShowMessage.this, "Internet Connection Error", "Please connect to Internet connection", false); // stop executing code by return return; } lblMessage = (TextView) findViewById(R.id.lblMessage); if(lblMessage.getText().equals("")){ // Register custom Broadcast receiver to show messages on activity registerReceiver(mHandleMessageReceiver, new IntentFilter( Config.DISPLAY_MESSAGE_ACTION)); } List<UserData> data = DBAdapter.getAllUserData(); for (UserData dt : data) { lblMessage.append(dt.getName()+" : "+dt.getMessage()+" "); } /*************** Spinner data Start *****************/ activity = this; List<UserData> SpinnerUserData = DBAdapter.getDistinctUser(); for (UserData spinnerdt : SpinnerUserData) { UserData schedSpinner = new UserData(); /******* Firstly take data in model object ********/ schedSpinner.setName(spinnerdt.getName()); schedSpinner.setIMEI(spinnerdt.getIMEI()); Log.i("GCMspinner", "-----"+spinnerdt.getName()); /******** Take Model Object in ArrayList **********/ CustomListViewValuesArr.add(schedSpinner); } Spinner SpinnerExample = (Spinner)findViewById(R.id.spinner); // Resources passed to adapter to get image Resources res = getResources(); // Create custom adapter object ( see below CustomAdapter.java ) adapter = new CustomAdapter(activity, R.layout.spinner_rows, CustomListViewValuesArr,res); // Set adapter to spinner SpinnerExample.setAdapter(adapter); // Listener called when spinner item selected SpinnerExample.setOnItemSelectedListener(new OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> parentView, View v, int position, long id) { // your code here // Get selected row data to show on screen String UserName = ((TextView) v.findViewById(R.id.username)).getText().toString(); UserDeviceIMEI = ((TextView) v.findViewById(R.id.imei)).getText().toString(); String OutputMsg = "Selected User : "+UserName+" "+UserDeviceIMEI; Toast.makeText( getApplicationContext(),OutputMsg, Toast.LENGTH_LONG).show(); } @Override public void onNothingSelected(AdapterView<?> parentView) { // your code here } }); txtMessage = (EditText) findViewById(R.id.txtMessage); btnSend = (Button) findViewById(R.id.btnSend); // Click event on Register button btnSend.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) { // Get data from EditText String message = txtMessage.getText().toString(); // WebServer Request URL to send message to device. String serverURL = Config.YOUR_SERVER_URL+"sendpush.php"; if(!UserDeviceIMEI.equals("")) { String deviceIMEI = ""; if(Config.SECOND_SIMULATOR){ //Make it true in CONFIG if you want to open second simutor // for testing actually we are using IMEI number to save a unique device deviceIMEI = "000000000000001"; } else { // GET IMEI NUMBER TelephonyManager tManager = (TelephonyManager) getBaseContext() .getSystemService(Context.TELEPHONY_SERVICE); deviceIMEI = tManager.getDeviceId(); } // Use AsyncTask execute Method To Prevent ANR Problem new LongOperation().execute(serverURL,UserDeviceIMEI,message,deviceIMEI); txtMessage.setText(""); } else { Toast.makeText( getApplicationContext(), "Please select send to user.", Toast.LENGTH_LONG).show(); } } }); } // Create a broadcast receiver to get message and show on screen private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String newMessage = intent.getExtras().getString(Config.EXTRA_MESSAGE); String newName = intent.getExtras().getString("name"); String newIMEI = intent.getExtras().getString("imei"); Log.i("GCMBroadcast","Broadcast called."+newIMEI); // Waking up mobile if it is sleeping aController.acquireWakeLock(getApplicationContext()); String msg = lblMessage.getText().toString(); msg = newName+" : "+newMessage+" "+msg; // Display message on the screen lblMessage.setText(msg); //lblMessage.append(" "+newName+" : "+newMessage); Toast.makeText(getApplicationContext(), "Got Message: " + newMessage, Toast.LENGTH_LONG).show(); /************************************/ //CustomListViewValuesArr.clear(); int rowCount = DBAdapter.validateNewMessageUserData(newIMEI); Log.i("GCMBroadcast", "rowCount:"+rowCount); if(rowCount <= 1 ){ final UserData schedSpinner = new UserData(); /******* Firstly take data in model object ********/ schedSpinner.setName(newName); schedSpinner.setIMEI(newIMEI); /******** Take Model Object in ArrayList **********/ CustomListViewValuesArr.add(schedSpinner); adapter.notifyDataSetChanged(); } //CustomListViewValuesArr.addAll(SpinnerUserData); /************************************/ // Releasing wake lock aController.releaseWakeLock(); } }; /*********** Send message *****************/ public class LongOperation extends AsyncTask<String, Void, String> { // Required initialization //private final HttpClient Client = new DefaultHttpClient(); // private Controller aController = null; private String Error = null; private ProgressDialog Dialog = new ProgressDialog(ShowMessage.this); String data = ""; int sizeData = 0; protected void onPreExecute() { // NOTE: You can call UI Element here. //Start Progress Dialog (Message) Dialog.setMessage("Please wait.."); Dialog.show(); } // Call after onPreExecute method protected String doInBackground(String... params) { /************ Make Post Call To Web Server ***********/ BufferedReader reader=null; String Content = ""; // Send data try{ // Defined URL where to send data URL url = new URL(params[0]); // Set Request parameter if(!params[1].equals("")) data +="&" + URLEncoder.encode("data1", "UTF-8") + "="+params[1].toString(); if(!params[2].equals("")) data +="&" + URLEncoder.encode("data2", "UTF-8") + "="+params[2].toString(); if(!params[3].equals("")) data +="&" + URLEncoder.encode("data3", "UTF-8") + "="+params[3].toString(); // Send POST data request URLConnection conn = url.openConnection(); conn.setDoOutput(true); OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream()); wr.write( data ); wr.flush(); // Get the server response reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); StringBuilder sb = new StringBuilder(); String line = null; // Read Server Response while((line = reader.readLine()) != null) { // Append server response in string sb.append(line + " "); } // Append Server Response To Content String Content = sb.toString(); } catch(Exception ex) { Error = ex.getMessage(); } finally { try { reader.close(); } catch(Exception ex) {} } /*****************************************************/ return Content; } protected void onPostExecute(String Result) { // NOTE: You can call UI Element here. // Close progress dialog Dialog.dismiss(); if (Error != null) { Toast.makeText(getBaseContext(), "Error: "+Error, Toast.LENGTH_LONG).show(); } else { // Show Response Json On Screen (activity) Toast.makeText(getBaseContext(), "Message sent."+Result, Toast.LENGTH_LONG).show(); } } } protected void onPause() { super.onPause(); } @Override protected void onStop() { super.onStop(); } @Override protected void onDestroy() { try { // Unregister Broadcast Receiver unregisterReceiver(mHandleMessageReceiver); } catch (Exception e) { Log.e("UnRegister Receiver Error", "> " + e.getMessage()); } super.onDestroy(); } }
ShowMessage.java file used sendpush.php file to send message.
This file is defined in above codes.
This custom adapter is used for spinner to select user.
package com.androidexample.mobilegcm; import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.content.res.Resources; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.TextView; //Adapter class extends with BaseAdapter and implements with OnClickListener public class CustomAdapter extends ArrayAdapter<String>{ private Activity activity; private ArrayList data; public Resources res; UserData tempValues=null; LayoutInflater inflater; /************* CustomAdapter Constructor *****************/ public CustomAdapter( ShowMessage activitySpinner, int textViewResourceId, ArrayList objects, Resources resLocal ) { super(activitySpinner, textViewResourceId, objects); /********** Take passed values **********/ activity = activitySpinner; data = objects; res = resLocal; /*********** Layout inflator to call external xml layout () **********************/ inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getDropDownView(int position, View convertView,ViewGroup parent) { return getCustomView(position, convertView, parent); } @Override public View getView(int position, View convertView, ViewGroup parent) { return getCustomView(position, convertView, parent); } public View getCustomView(int position, View convertView, ViewGroup parent) { /********** Inflate spinner_rows.xml file for each row ( Defined below ) ************/ View row = inflater.inflate(R.layout.spinner_rows, parent, false); /***** Get each Model object from Arraylist ********/ tempValues = null; tempValues = (UserData) data.get(position); TextView Username = (TextView)row.findViewById(R.id.username); TextView Userimei = (TextView)row.findViewById(R.id.imei); ImageView UserImage = (ImageView)row.findViewById(R.id.image); // Set values for spinner each row Username.setText(tempValues.getName()); Userimei.setText(tempValues.getIMEI()); UserImage.setImageResource(res.getIdentifier( "com.androidexample.mobilegcm:drawable/user_thumb",null,null)); return row; } }
Used for custom adapter to create layout of spinner rows.
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="3dip" > <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:layout_toRightOf="@+id/image" android:padding="3dip" android:layout_marginTop="2dip" android:textColor="@drawable/red" android:textStyle="bold" android:id="@+id/username" android:layout_marginLeft="5dip" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:layout_toRightOf="@+id/image" android:padding="2dip" android:textColor="@drawable/darkgrey" android:layout_marginLeft="5dip" android:id="@+id/imei" android:layout_below="@+id/username" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
Best way to use two or more real devices to test this example.
If you want to test this example in simulators then use these steps.
To test gcm application in emulator you need to test it on Google API simulator only.
STEP1 : Make variable SECOND_SIMULATOR value to false (Config.java) and open first simulator.
static final boolean SECOND_SIMULATOR = false;
STEP2 : Make variable SECOND_SIMULATOR value to true (Config.java) and open second simulator.
static final boolean SECOND_SIMULATOR = true;
STEP3 : Run application for second simulator.
STEP4 : Add google account in second simulator.
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