Overview of Google Cloud Messaging, PHP and MySQL
In this tutorial i used PHP as server side programming language and MySQL as server side database. I installed WAMP server to install php, MySQL, Apache for me. If you are new to connecting PHP, MySQL to android application, i suggest you go through this tutorialHow to connect Android with PHP, MySQL
You can go through the official documentation if you want to know more about GCM.
The following diagram is illustrating the overview of the tutorial and the purpose of each entity involved in this tutorial.
Registering with Google Cloud Messaging
1. Goto Google APIs Console page and create a new project. (If you haven’t created already otherwise it will take you to dashboard)
2. After creating project you can see the project id in the url. Note down the project id which will be used as SENDER ID in android project. (Example: in #project:460866929976 after semicolon 460866929976 is the sender id)
3. After that click on Services on the left panel and turn on Google Cloud Messaging for Android.
4. Once you are done, click on API Access and note down the API Key. This API key will be used when sending requests to GCM server.
2. After creating the database, select the database and execute following query in SQL tab to create gcm_users table.
Check the following video to know about creating database and php project.
Left Click on the WAMP icon the system try -> PHP -> PHP Extensions -> Enable php_curl
1. Goto your WAMP folder and inside www folder create a folder called gcm_server_php. (In my case i installed wamp in C:\WAMP)
2. Create a filed called config.php This fill holds the database configuration and google api key.
3. Create another file called db_connect.php This file handles database connections, mainly opens and closes connection.
4. Create a new file named db_functions.php This file contains function to perform database CRUD operations. But i wrote function for creating user only.
5. Create another file named GCM.php This file used to send push notification requests to GCM server.
6. Create a new file called register.php This file receives requests from android device and stores the user in the database.
7. Create another file called send_message.php This file used to send pushnotification to android device by making a request to GCM server.
8. Finally create a file called index.php
and paste the following code. The following code will create a simple
admin panel to list all the user devices and provides a panel to send
push notification to individual devices.
Following is a screenshot of the admin panel generated by above code (with users registered)
Until now we are done with setting up server side part. Now we can start writing android code.
1. Goto your android SDK folder and open SDK Manager and install Google Cloud Messaging for Android Library under Extras section. (If you don’t see Google Cloud Messaging for Android Library update your SDK manager to latest version)
2. After installing the library it will create gcm.jar file in your Andoird_SDK_Folder\extras\google\gcm\gcm-client\dist. Later you need to add this .jar file to your android project.
3. Now open your AVD Manager and create a new Google API emulator and start the emulator. (Note: To test gcm application in emulator you need to test it on Google API device only)
4. After launching emulator press Menu button goto Settings. Select Accounts & Sync. And then press Add Account button and add a Google account.
Check the following video to know about adding google account in the emulator
Once you are done adding google account you are good to start android project.
2. After creating new project open AndroidManifest.xml file and do the following changes.
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.
In the following code replace all com.androidhive.pushnotifications with your android package name.
3. Open your strings.xml file under res -> values folder and paste following strings. (If you don’t have strings.xml file, create a new one)
4. Create a new class named AlertDialogManager.java and paste the following code. This class used to show alert dialog in your application.
5. Create another class named ConnectionDetector.java This class used to detect internet connection status.
6. Create class file called CommonUtilities.java and type the following code. This class contains the GCM configuration and our server registration url.
SERVER_URL – Your server user registration url
SENDER_ID – Google project id
7. Create a new class called ServerUtilities.java with following content. This class has following funtions
8. Add a new class file called GCMIntentService.java This class handles all GCM related services.
9. Here i am adding a registration screen where user
can register using their details. To make this tutorial simple i am
asking only name and email only. Once user registration is done the user
details will be sent to our server where the user details will be
stored in mysql database.
Create a new xml file called activity_register.xml under res -> layout folder and paste the following code.
10. Create a new class called RegisterActivity.java This class will be used to handler user registration.
In the following code first internet status and gcm configuration is checked and once user presses the registration button user details will be send to MainActivity.java from there they will send to our server.
11. Now open your main activity file (In my case MainActivity.java) and type the following code.
In the following code
I am receiving name, email sent from RegisterActivity and storing them in static variables.
Then i am checking whether this device has gcm registration id, if not i am registering it on gcm by calling GCMRegistrar.register(this, SENDER_ID) method
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() method will be called when device gets a new push notification message. For now i am displaying the message on the screen. You might need to take appropriate action on the message depending upon your app requirement. (Example: Storing it in SQLite database)
Now we are done with our android project. Following are the enhancements to enhance the user experience.
Add a new class file named WakeLocker.java and paste the following code.
and call the following lines code in private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() presents in MainActivity.java.
Creating MySQL Database
1. Open phpmyadmin panel by going to http://localhost/phpmyadmin and create a database called gcm. (if your localhost is running on port number add port number to url)2. After creating the database, select the database and execute following query in SQL tab to create gcm_users 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 , `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP , PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; |
Creating & Running the PHP Project
When we are making request to GCM server using PHP i used curl to make post request. Before creating php project enable curl module in your php extensions.Left Click on the WAMP icon the system try -> PHP -> PHP Extensions -> Enable php_curl
1. Goto your WAMP folder and inside www folder create a folder called gcm_server_php. (In my case i installed wamp in C:\WAMP)
2. Create a filed called config.php This fill holds the database configuration and google api key.
<?php /** * Database config variables */ define( "DB_HOST" , "localhost" ); define( "DB_USER" , "root" ); define( "DB_PASSWORD" , "root" ); define( "DB_DATABASE" , "gcm" ); /* * Google API Key */ define( "GOOGLE_API_KEY" , "BIzaSyCRLa4LQZWNQBcRCYcIVYA45i9i8zfClqc" ); // Place your Google API Key ?> |
<?php class DB_Connect { // constructor function __construct() { } // destructor function __destruct() { // $this->close(); } // Connecting to database public function connect() { require_once 'config.php' ; // connecting to mysql $con = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD); // selecting database mysql_select_db(DB_DATABASE); // return database handler return $con ; } // Closing database connection public function close() { mysql_close(); } } ?> |
<?php class DB_Functions { private $db ; //put your code here // constructor function __construct() { include_once './db_connect.php' ; // connecting to database $this ->db = new DB_Connect(); $this ->db->connect(); } // destructor function __destruct() { } /** * Storing new user * returns user details */ public function storeUser( $name , $email , $gcm_regid ) { // insert user into database $result = mysql_query( "INSERT INTO gcm_users(name, email, gcm_regid, created_at) VALUES('$name', '$email', '$gcm_regid', 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; } } /** * Getting all users */ public function getAllUsers() { $result = mysql_query( "select * FROM gcm_users" ); return $result ; } } ?> |
<?php class GCM { //put your code here // constructor function __construct() { } /** * Sending Push Notification */ public function send_notification( $registatoin_ids , $message ) { // include config include_once './config.php' ; // Set POST variables $fields = array ( 'registration_ids' => $registatoin_ids , 'data' => $message , ); $headers = array ( 'Authorization: key=' . GOOGLE_API_KEY, 'Content-Type: application/json' ); // 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 ; } } ?> |
<?php // response json $json = array (); /** * Registering a user device * Store reg id in users table */ if (isset( $_POST [ "name" ]) && isset( $_POST [ "email" ]) && isset( $_POST [ "regId" ])) { $name = $_POST [ "name" ]; $email = $_POST [ "email" ]; $gcm_regid = $_POST [ "regId" ]; // GCM Registration ID // Store user details in db include_once './db_functions.php' ; include_once './GCM.php' ; $db = new DB_Functions(); $gcm = new GCM(); $res = $db ->storeUser( $name , $email , $gcm_regid ); $registatoin_ids = array ( $gcm_regid ); $message = array ( "product" => "shirt" ); $result = $gcm ->send_notification( $registatoin_ids , $message ); echo $result ; } else { // user details missing } ?> |
<?php if (isset( $_GET [ "regId" ]) && isset( $_GET [ "message" ])) { $regId = $_GET [ "regId" ]; $message = $_GET [ "message" ]; include_once './GCM.php' ; $gcm = new GCM(); $registatoin_ids = array ( $regId ); $message = array ( "price" => $message ); $result = $gcm ->send_notification( $registatoin_ids , $message ); echo $result ; } ?> |
<!DOCTYPE html> <html> <head> <title></title> <meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" > <script type= "text/javascript" > $(document).ready( function (){ }); function sendPushNotification(id){ var data = $( 'form#' +id).serialize(); $( 'form#' +id).unbind( 'submit' ); $.ajax({ url: "send_message.php" , type: 'GET' , data: data, beforeSend: function () { }, success: function (data, textStatus, xhr) { $( '.txt_message' ).val( "" ); }, error: function (xhr, textStatus, errorThrown) { } }); return false; } </script> <style type= "text/css" > .container{ width: 950px; margin: 0 auto; padding: 0; } h1{ font-family: 'Helvetica Neue' , Helvetica, Arial, sans-serif; font-size: 24px; color: #777; } div.clear{ clear: both; } ul.devices{ margin: 0; padding: 0; } ul.devices li{ float: left; list-style: none; border: 1px solid #dedede; padding: 10px; margin: 0 15px 25px 0; border-radius: 3px; -webkit-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.35); -moz-box-shadow: 0 1px 5px rgba(0, 0, 0, 0.35); box-shadow: 0 1px 5px rgba(0, 0, 0, 0.35); font-family: 'Helvetica Neue' , Helvetica, Arial, sans-serif; color: #555; } ul.devices li label, ul.devices li span{ font-family: 'Helvetica Neue' , Helvetica, Arial, sans-serif; font-size: 12px; font-style: normal; font-variant: normal; font-weight: bold; color: #393939; display: block; float: left; } ul.devices li label{ height: 25px; width: 50px; } ul.devices li textarea{ float: left; resize: none; } ul.devices li .send_btn{ background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#0096FF), to(#005DFF)); background: -webkit-linear-gradient(0% 0%, 0% 100%, from(#0096FF), to(#005DFF)); background: -moz-linear-gradient(center top, #0096FF, #005DFF); background: linear-gradient(#0096FF, #005DFF); text-shadow: 0 1px 0 rgba(0, 0, 0, 0.3); border-radius: 3px; color: #fff; } </style> </head> <body> <?php include_once 'db_functions.php' ; $db = new DB_Functions(); $users = $db ->getAllUsers(); if ( $users != false) $no_of_users = mysql_num_rows( $users ); else $no_of_users = 0; ?> <div class = "container" > <h1>No of Devices Registered: <?php echo $no_of_users ; ?></h1> <hr/> <ul class = "devices" > <?php if ( $no_of_users > 0) { ?> <?php while ( $row = mysql_fetch_array( $users )) { ?> <li> <form id= "<?php echo $row[" id "] ?>" name= "" method= "post" onsubmit= "return sendPushNotification('<?php echo $row[" id "] ?>')" > <label>Name: </label> <span><?php echo $row [ "name" ] ?></span> <div class = "clear" ></div> <label>Email:</label> <span><?php echo $row [ "email" ] ?></span> <div class = "clear" ></div> <div class = "send_container" > <textarea rows= "3" name= "message" cols= "25" class = "txt_message" placeholder= "Type message here" ></textarea> <input type= "hidden" name= "regId" value= "<?php echo $row[" gcm_regid "] ?>" /> <input type= "submit" class = "send_btn" value= "Send" onclick= "" /> </div> </form> </li> <?php } } else { ?> <li> No Users Registered Yet! </li> <?php } ?> </ul> </div> </body> </html> |
Installing helper libraries and setting up the Emulator
Before start writing android code we need to install the helper libraries and make required changes to the emulator.1. Goto your android SDK folder and open SDK Manager and install Google Cloud Messaging for Android Library under Extras section. (If you don’t see Google Cloud Messaging for Android Library update your SDK manager to latest version)
2. After installing the library it will create gcm.jar file in your Andoird_SDK_Folder\extras\google\gcm\gcm-client\dist. Later you need to add this .jar file to your android project.
4. After launching emulator press Menu button goto Settings. Select Accounts & Sync. And then press Add Account button and add a Google account.
Creating Android Project
1. Create a new android project and fill the required details. While creating project select minimum SDK version API 8 to support wider range of devices.2. After creating new project open AndroidManifest.xml file and do the following changes.
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.
In the following code replace all com.androidhive.pushnotifications with your android package name.
<? xml version = "1.0" encoding = "utf-8" ?> package = "com.androidhive.pushnotifications" 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" /> <!-- 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.androidhive.pushnotifications.permission.C2D_MESSAGE" android:protectionLevel = "signature" /> < uses-permission android:name = "com.androidhive.pushnotifications.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" /> <!-- Main activity. --> < application android:icon = "@drawable/ic_launcher" android:label = "@string/app_name" > <!-- Register Activity --> < activity android:name = ".RegisterActivity" android:label = "@string/app_name" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > <!-- Main Activity --> < activity android:name = ".MainActivity" android:configChanges = "orientation|keyboardHidden" android:label = "@string/app_name" > </ 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.androidhive.pushnotifications" /> </ intent-filter > </ receiver > < service android:name = ".GCMIntentService" /> </ application > </ manifest > |
< resources > < string name = "app_name" >AndroidHive GCM</ string > < string name = "hello_world" >Hello world!</ string > < string name = "menu_settings" >Settings</ string > < string name = "title_activity_main" >Push Notifications</ string > < string name = "error_config" >Please set the %1$s constant and recompile the app.</ string > < string name = "already_registered" >Device is already registered on server.</ string > < string name = "gcm_registered" >From GCM: device successfully registered!</ string > < string name = "gcm_unregistered" >From GCM: device successfully unregistered!</ string > < string name = "gcm_message" >From GCM: you got message!</ string > < string name = "gcm_error" >From GCM: error (%1$s).</ string > < string name = "gcm_recoverable_error" >From GCM: recoverable error (%1$s).</ string > < string name = "gcm_deleted" >From GCM: server deleted %1$d pending messages!</ string > < string name = "server_registering" >Trying (attempt %1$d/%2$d) to register device on Demo Server.</ string > < string name = "server_registered" >From Demo Server: successfully added device!</ string > < string name = "server_unregistered" >From Demo Server: successfully removed device!</ string > < string name = "server_register_error" >Could not register device on Demo Server after %1$d attempts.</ string > < string name = "server_unregister_error" >Could not unregister device on Demo Server (%1$s).</ string > < string name = "options_register" >Register</ string > < string name = "options_unregister" >Unregister</ string > < string name = "options_clear" >Clear</ string > < string name = "options_exit" >Exit</ string > </ resources > |
package com.androidhive.pushnotifications; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; public class AlertDialogManager { /** * Function to display simple Alert Dialog * @param context - application context * @param title - alert dialog title * @param message - alert message * @param status - success/failure (used to set icon) * - pass null if you don't want icon * */ public void showAlertDialog(Context context, String title, String message, Boolean status) { AlertDialog alertDialog = new AlertDialog.Builder(context).create(); // Setting Dialog Title alertDialog.setTitle(title); // Setting Dialog Message alertDialog.setMessage(message); if (status != null ) // Setting alert dialog icon alertDialog.setIcon((status) ? R.drawable.success : R.drawable.fail); // Setting OK Button alertDialog.setButton( "OK" , new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { } }); // Showing Alert Message alertDialog.show(); } } |
package com.androidhive.pushnotifications; import android.content.Context; import android.net.ConnectivityManager; import android.net.NetworkInfo; public class ConnectionDetector { private Context _context; public ConnectionDetector(Context context){ this ._context = context; } /** * Checking for all possible internet providers * **/ public boolean isConnectingToInternet(){ ConnectivityManager connectivity = (ConnectivityManager) _context.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 ; } } |
SERVER_URL – Your server user registration url
SENDER_ID – Google project id
package com.androidhive.pushnotifications; import android.content.Context; import android.content.Intent; public final class CommonUtilities { // give your server registration url here // Google project id static final String SENDER_ID = "903913289319" ; /** * Tag used on log messages. */ static final String TAG = "AndroidHive GCM" ; static final String DISPLAY_MESSAGE_ACTION = "com.androidhive.pushnotifications.DISPLAY_MESSAGE" ; static final String EXTRA_MESSAGE = "message" ; /** * Notifies UI to display a message. * <p> * This method is defined in the common helper because it's used both by * the UI and the background service. * * @param context application's context. * @param message message to be displayed. */ static void displayMessage(Context context, String message) { Intent intent = new Intent(DISPLAY_MESSAGE_ACTION); intent.putExtra(EXTRA_MESSAGE, message); context.sendBroadcast(intent); } } |
// function to register a user on our server(name, email, gcm reg id) static void register() // function to unregister the device static void unregister() // method to POST data to server private static void post() |
package com.androidhive.pushnotifications; import static com.androidhive.pushnotifications.CommonUtilities.SERVER_URL; import static com.androidhive.pushnotifications.CommonUtilities.TAG; import static com.androidhive.pushnotifications.CommonUtilities.displayMessage; import java.io.IOException; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Random; import android.content.Context; import android.util.Log; import com.google.android.gcm.GCMRegistrar; public final class ServerUtilities { private static final int MAX_ATTEMPTS = 5 ; private static final int BACKOFF_MILLI_SECONDS = 2000 ; private static final Random random = new Random(); /** * Register this account/device pair within the server. * */ static void register( final Context context, String name, String email, final String regId) { Log.i(TAG, "registering device (regId = " + regId + ")" ); String serverUrl = SERVER_URL; Map<String, String> params = new HashMap<String, String>(); params.put( "regId" , regId); params.put( "name" , name); params.put( "email" , email); 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(TAG, "Attempt #" + i + " to register" ); try { displayMessage(context, context.getString( R.string.server_registering, i, MAX_ATTEMPTS)); post(serverUrl, params); GCMRegistrar.setRegisteredOnServer(context, true ); String message = context.getString(R.string.server_registered); CommonUtilities.displayMessage(context, message); 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(TAG, "Failed to register on attempt " + i + ":" + e); if (i == MAX_ATTEMPTS) { break ; } try { Log.d(TAG, "Sleeping for " + backoff + " ms before retry" ); Thread.sleep(backoff); } catch (InterruptedException e1) { // Activity finished before we complete - exit. Log.d(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); CommonUtilities.displayMessage(context, message); } /** * Unregister this account/device pair within the server. */ static void unregister( final Context context, final String regId) { Log.i(TAG, "unregistering device (regId = " + regId + ")" ); String serverUrl = SERVER_URL + "/unregister" ; Map<String, String> params = new HashMap<String, String>(); params.put( "regId" , regId); try { post(serverUrl, params); GCMRegistrar.setRegisteredOnServer(context, false ); String message = context.getString(R.string.server_unregistered); CommonUtilities.displayMessage(context, message); } catch (IOException e) { // At this point the device is unregistered from GCM, but still // registered in the 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()); CommonUtilities.displayMessage(context, message); } } /** * Issue a POST request to the server. * * @param endpoint POST address. * @param params request parameters. * * @throws IOException propagated from POST. */ 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(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 (status != 200 ) { throw new IOException( "Post failed with error code " + status); } } finally { if (conn != null ) { conn.disconnect(); } } } } |
// method called once the device successfully registered with GCM protected void onRegistered() // called when a new message arrived to device protected void onMessage() // called when device is unregistered with GCM services protected void onUnregistered() // On receiving an error public void onError() // method to generate a notification private static void generateNotification() |
package com.androidhive.pushnotifications; 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 com.google.android.gcm.GCMBaseIntentService; import static com.androidhive.pushnotifications.CommonUtilities.SENDER_ID; import static com.androidhive.pushnotifications.CommonUtilities.displayMessage; public class GCMIntentService extends GCMBaseIntentService { private static final String TAG = "GCMIntentService" ; public GCMIntentService() { super (SENDER_ID); } /** * Method called on device registered **/ @Override protected void onRegistered(Context context, String registrationId) { Log.i(TAG, "Device registered: regId = " + registrationId); displayMessage(context, "Your device registred with GCM" ); Log.d( "NAME" , MainActivity.name); ServerUtilities.register(context, MainActivity.name, MainActivity.email, registrationId); } /** * Method called on device un registred * */ @Override protected void onUnregistered(Context context, String registrationId) { Log.i(TAG, "Device unregistered" ); displayMessage(context, getString(R.string.gcm_unregistered)); ServerUtilities.unregister(context, registrationId); } /** * Method called on Receiving a new message * */ @Override protected void onMessage(Context context, Intent intent) { Log.i(TAG, "Received message" ); String message = intent.getExtras().getString( "price" ); displayMessage(context, message); // notifies user generateNotification(context, message); } /** * Method called on receiving a deleted message * */ @Override protected void onDeletedMessages(Context context, int total) { Log.i(TAG, "Received deleted messages notification" ); String message = getString(R.string.gcm_deleted, total); displayMessage(context, message); // notifies user generateNotification(context, message); } /** * Method called on Error * */ @Override public void onError(Context context, String errorId) { Log.i(TAG, "Received error: " + errorId); displayMessage(context, getString(R.string.gcm_error, errorId)); } @Override protected boolean onRecoverableError(Context context, String errorId) { // log message Log.i(TAG, "Received recoverable error: " + errorId); displayMessage(context, getString(R.string.gcm_recoverable_error, errorId)); return super .onRecoverableError(context, errorId); } /** * Issues a notification to inform the user that server has sent a message. */ private static void generateNotification(Context context, String message) { int icon = R.drawable.ic_launcher; long when = System.currentTimeMillis(); NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); Notification notification = new Notification(icon, message, when); String title = context.getString(R.string.app_name); Intent notificationIntent = new Intent(context, MainActivity. class ); // set intent so it does not start a new activity notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); 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; // Vibrate if vibrate is enabled notification.defaults |= Notification.DEFAULT_VIBRATE; notificationManager.notify( 0 , notification); } } |
Create a new xml file called activity_register.xml under res -> layout folder and paste the following code.
android:layout_width = "match_parent" android:layout_height = "match_parent" android:orientation = "vertical" > < 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" /> < 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" /> < 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 > |
In the following code first internet status and gcm configuration is checked and once user presses the registration button user details will be send to MainActivity.java from there they will send to our server.
package com.androidhive.pushnotifications; import static com.androidhive.pushnotifications.CommonUtilities.SENDER_ID; import static com.androidhive.pushnotifications.CommonUtilities.SERVER_URL; 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 { // alert dialog manager AlertDialogManager alert = new AlertDialogManager(); // Internet detector ConnectionDetector cd; // UI elements EditText txtName; EditText txtEmail; // Register button Button btnRegister; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_register); cd = new ConnectionDetector(getApplicationContext()); // Check if Internet present if (!cd.isConnectingToInternet()) { // Internet Connection is not present alert.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 (SERVER_URL == null || SENDER_ID == null || SERVER_URL.length() == 0 || SENDER_ID.length() == 0 ) { // GCM sernder id / server url is missing alert.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) { // Read EditText dat 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 // ask him to fill the form alert.showAlertDialog(RegisterActivity. this , "Registration Error!" , "Please enter your details" , false ); } } }); } } |
In the following code
I am receiving name, email sent from RegisterActivity and storing them in static variables.
Then i am checking whether this device has gcm registration id, if not i am registering it on gcm by calling GCMRegistrar.register(this, SENDER_ID) method
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() method will be called when device gets a new push notification message. For now i am displaying the message on the screen. You might need to take appropriate action on the message depending upon your app requirement. (Example: Storing it in SQLite database)
package com.androidhive.pushnotifications; import static com.androidhive.pushnotifications.CommonUtilities.DISPLAY_MESSAGE_ACTION; import static com.androidhive.pushnotifications.CommonUtilities.EXTRA_MESSAGE; import static com.androidhive.pushnotifications.CommonUtilities.SENDER_ID; 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.util.Log; import android.widget.TextView; import android.widget.Toast; import com.google.android.gcm.GCMRegistrar; public class MainActivity extends Activity { // label to display gcm messages TextView lblMessage; // Asyntask AsyncTask<Void, Void, Void> mRegisterTask; // Alert dialog manager AlertDialogManager alert = new AlertDialogManager(); // Connection detector ConnectionDetector cd; public static String name; public static String email; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); cd = new ConnectionDetector(getApplicationContext()); // Check if Internet present if (!cd.isConnectingToInternet()) { // Internet Connection is not present alert.showAlertDialog(MainActivity. 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(); name = i.getStringExtra( "name" ); email = i.getStringExtra( "email" ); // Make sure the device has the proper dependencies. GCMRegistrar.checkDevice( this ); // Make sure the manifest was properly set - comment out this line // while developing the app, then uncomment it when it's ready. GCMRegistrar.checkManifest( this ); lblMessage = (TextView) findViewById(R.id.lblMessage); registerReceiver(mHandleMessageReceiver, new IntentFilter( DISPLAY_MESSAGE_ACTION)); // Get GCM registration id final String regId = GCMRegistrar.getRegistrationId( this ); // Check if regid already presents if (regId.equals( "" )) { // Registration is not present, register now with GCM GCMRegistrar.register( this , SENDER_ID); } else { // Device is already registered on GCM if (GCMRegistrar.isRegisteredOnServer( this )) { // Skips registration. Toast.makeText(getApplicationContext(), "Already registered with GCM" , Toast.LENGTH_LONG).show(); } else { // 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 ServerUtilities.register(context, name, email, regId); return null ; } @Override protected void onPostExecute(Void result) { mRegisterTask = null ; } }; mRegisterTask.execute( null , null , null ); } } } /** * Receiving push messages * */ private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String newMessage = intent.getExtras().getString(EXTRA_MESSAGE); // Waking up mobile if it is sleeping WakeLocker.acquire(getApplicationContext()); /** * Take appropriate action on this message * depending upon your app requirement * For now i am just displaying it on the screen * */ // Showing received message lblMessage.append(newMessage + "\n" ); Toast.makeText(getApplicationContext(), "New Message: " + newMessage, Toast.LENGTH_LONG).show(); // Releasing wake lock WakeLocker.release(); } }; @Override protected void onDestroy() { if (mRegisterTask != null ) { mRegisterTask.cancel( true ); } try { unregisterReceiver(mHandleMessageReceiver); GCMRegistrar.onDestroy( this ); } catch (Exception e) { Log.e( "UnRegister Receiver Error" , "> " + e.getMessage()); } super .onDestroy(); } } |
Playing custom notification sound
If you want to play custom notification sound, copy your sound file in your project assets folder and write the following code in in private static void generateNotification() function which presents in GCMIntentService.java file.notification.sound = Uri.parse( "android.resource://" + context.getPackageName() + "your_sound_file_name.mp3" ); |
Vibrating device on receiving new notification
If you wan’t to vibrate the device on receiving a new notification add the following lines of code in private static void generateNotification() function which presents in GCMIntentService.java file. Also make sure that you added following permission in AndroidManifest.xml file< uses-permission android:name = "android.permission.VIBRATE" /> |
// Vibrate if vibrate is enabled notification.defaults |= Notification.DEFAULT_VIBRATE; |
Waking up device on receiving new notification
You can also wake the device on receiving new notification if the device is sleeping. Add the following permission in your AndroidManifest.xml file< uses-permission android:name = "android.permission.WAKE_LOCK" /> |
package com.androidhive.pushnotifications; import android.content.Context; import android.os.PowerManager; public abstract class WakeLocker { private static PowerManager.WakeLock wakeLock; public static void acquire(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 static void release() { if (wakeLock != null ) wakeLock.release(); wakeLock = null ; } } |
// Waking up mobile if it is sleeping
WakeLocker.acquire(getApplicationContext());
// new message code here
// Releasing wake lock
WakeLocker.release();
then run the project ...................
if any querry related to this example then i will be happy to solve it.....