Push Notification In Android

In this article you will learn about Push Notification in Android applications.

As per Google documentation,

“Google Cloud Messaging for Android (GCM) is a service that helps developers send data from servers to their Android applications on Android devices”.
 
Using this service you can send data to your application whenever new data is available instead of making requests to the server in a timely fashion. Integrating GCM in your Android application enhances user experience and saves a lot of battery power. I will explain how to send push notifications to Android devices from a Java server.

Steps required to do this are as follows:
  1. Register with Google Cloud Messaging from Google API console to get the sender id and API key for Google cloud messaging.
  2. Set emulator for Google cloud messaging library.
  3. Create an Android project to register with Google Cloud Messaging (GCM).
  4. Create a server side code that will accept the registration id and will send push messages to the Android devices.

Describing each steps in details,

  1. Go to Google API Console.

  2. If you haven’t created a project yet, this page will prompt you to do so.

    create a project

  3. After creating the project you can see the project Id in the url. Note down the project id which will be used further as SENDER_ID in the Android project, and it will be like the following.

    Sender ID

  4. In the API console page select services and toggle on Google Cloud Messaging for Android.

  5. Click API Access and note down the API Key.

    Api key

Before we start writing Android code we need to install the helper libraries and make required changes to the emulator. These library methods will be used to register and unregister with GCM.

  1. Go to Android SDK folder and open SDK Manager and install Google Cloud Messaging for Android library under Extras.

    Insrtall
    Code

  2. After installing the library it will create gcm.jar file in your ANDROID_SDK_FOLDEREXTRASGOOGLEGCM-CLIENTDIST.

  3. Now open your AVD Manager and create a new Google Api Emulator and start the emulator.

  4. After launching emulator press menu button, go to Settings, select Accounts & Sync. Then press Add Account button and add a Google account.

    NB: If you not add a google account and run this example then you will get an error account_missing.

Create the Android Application

AndroidManifest.xml

The following permissions are required to make your application support GCM:

  • NTERNET – To make your application use internet services.
  • ACCESS_NETWORK_STATE – To access network states.
  • 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 application support vibration when receiving notification also add some broadcast receivers as mentioned below:
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <manifest  
    3.     xmlns:android="http://schemas.android.com/apk/res/android" package="com.javapapers.android" android:versionCode="1" android:versionName="1.0">  
    4.     <uses-permission android:name="android.permission.INTERNET" />  
    5.     <uses-permission android:name="android.permission.GET_ACCOUNTS" />  
    6.     <uses-permission android:name="android.permission.WAKE_LOCK" />  
    7.     <permission android:name="com.javapapers.android.permission.C2D_MESSAGE" android:protectionLevel="signature" />  
    8.     <uses-permission android:name="com.javapapers.android.permission.C2D_MESSAGE" />  
    9.     <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />  
    10.     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
    11.     <uses-permission android:name="android.permission.VIBRATE" />  
    12.     <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="16" />  
    13.     <application android:icon="@drawable/ic_launcher" android:label="@string/app_name">  
    14.         <activity android:name=".RegisterActivity" android:label="@string/app_name">  
    15.             <intent-filter>  
    16.                 <action android:name="android.intent.action.MAIN" />  
    17.                 <category android:name="android.intent.category.LAUNCHER" />  
    18.             </intent-filter>  
    19.         </activity>  
    20.         <activity android:name="com.javapapers.android.MainActivity" android:configChanges="orientation|keyboardHidden" android:label="@string/app_name"></activity>  
    21.         <receiver android:name=".GcmBroadcastReceiver" android:permission="com.google.android.c2dm.permission.SEND">  
    22.             <intent-filter>  
    23.                 <action android:name="com.google.android.c2dm.intent.RECEIVE" />  
    24.                 <action android:name="com.google.android.c2dm.intent.REGISTRATION" />  
    25.                 <category android:name="com.javapapers.android" />  
    26.             </intent-filter>  
    27.         </receiver>  
    28.         <service android:name=".GCMNotificationIntentService" /><  
    29.      /application>  
    Config.java

    Model class contains all the configuration values.

    APP_SERVER_URL – your web server url or localhost.

    GOOGLE_PROJECT_ID = Google project id you have got from Google API console.
    1. public interface Config  
    2. {  
    3.     static final String APP_SERVER_URL = "http://192.168.1.28:8080/GCM-App-Server/GCMNotification?shareRegId=1";  
    4.     static final String GOOGLE_PROJECT_ID = "324797211425";  
    5.     static final String MESSAGE_KEY = "message";  
    6. }  
    RegisterActivity.java

    This class contains two buttons and these button handling the registration and sharing of registration id.

    The register button click will register your application with the Google server and it will give a registration id. This id is required to send push notification from server.

    And the share button click will share this registration id with our java server.
    1. public class RegisterActivity extends Activity  
    2. {  
    3.     Button btnGCMRegister;  
    4.     Button btnAppShare;  
    5.     GoogleCloudMessaging gcm;  
    6.     Context context;  
    7.     String regId;  
    8.     public static final String REG_ID = "regId";  
    9.     private static final String APP_VERSION = "appVersion";  
    10.     static final String TAG = "Register Activity";  
    11.     @Override  
    12.     public void onCreate(Bundle savedInstanceState)  
    13.     {  
    14.         super.onCreate(savedInstanceState);  
    15.         setContentView(R.layout.activity_register);  
    16.         context = getApplicationContext();  
    17.         btnGCMRegister = (Button) findViewById(R.id.btnGCMRegister);  
    18.         btnGCMRegister.setOnClickListener(new View.OnClickListener()  
    19.         {  
    20.             @Override  
    21.             public void onClick(View arg0)  
    22.             {  
    23.                 if (TextUtils.isEmpty(regId))  
    24.                 {  
    25.                     regId = registerGCM();  
    26.                     Log.d("RegisterActivity""GCM RegId: " + regId);  
    27.                 }  
    28.                 else  
    29.                 {  
    30.                     Toast.makeText(getApplicationContext(), "Already Registered with GCM Server!", Toast.LENGTH_LONG).show();  
    31.                 }  
    32.             }  
    33.         });  
    34.         btnAppShare = (Button) findViewById(R.id.btnAppShare);  
    35.         btnAppShare.setOnClickListener(new View.OnClickListener()  
    36.         {  
    37.             @Override  
    38.             public void onClick(View arg0)  
    39.             {  
    40.                 if (TextUtils.isEmpty(regId))  
    41.                 {  
    42.                     Toast.makeText(getApplicationContext(), "RegId is empty!", Toast.LENGTH_LONG).show();  
    43.                 }  
    44.                 else  
    45.                 {  
    46.                     Intent i = new Intent(getApplicationContext(), MainActivity.class);  
    47.                     i.putExtra("regId", regId);  
    48.                     Log.d("RegisterActivity""onClick of Share: Before starting main activity.");  
    49.                     startActivity(i);  
    50.                     finish();  
    51.                     Log.d("RegisterActivity""onClick of Share: After finish.");  
    52.                 }  
    53.             }  
    54.         });  
    55.     }  
    56.     public String registerGCM()  
    57.     {  
    58.         gcm = GoogleCloudMessaging.getInstance(this);  
    59.         regId = getRegistrationId(context);  
    60.         if (TextUtils.isEmpty(regId))  
    61.         {  
    62.             registerInBackground();  
    63.             Log.d("RegisterActivity""registerGCM - successfully registered with GCM server - regId: " + regId);  
    64.         }  
    65.         else  
    66.         {  
    67.             Toast.makeText(getApplicationContext(), "RegId already available. RegId: " + regId, Toast.LENGTH_LONG).show();  
    68.         }  
    69.         return regId;  
    70.     }  
    71.     private String getRegistrationId(Context context)  
    72.     {  
    73.         final SharedPreferences prefs = getSharedPreferences(MainActivity.class.getSimpleName(), Context.MODE_PRIVATE);  
    74.         String registrationId = prefs.getString(REG_ID, "");  
    75.         if (registrationId.isEmpty())  
    76.         {  
    77.             Log.i(TAG, "Registration not found.");  
    78.             return "";  
    79.         }  
    80.         int registeredVersion = prefs.getInt(APP_VERSION, Integer.MIN_VALUE);  
    81.         int currentVersion = getAppVersion(context);  
    82.         if (registeredVersion != currentVersion)  
    83.         {  
    84.             Log.i(TAG, "App version changed.");  
    85.             return "";  
    86.         }  
    87.         return registrationId;  
    88.     }  
    89.     private static int getAppVersion(Context context)  
    90.     {  
    91.         try  
    92.         {  
    93.             PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);  
    94.             return packageInfo.versionCode;  
    95.         }  
    96.         catch (NameNotFoundException e)  
    97.         {  
    98.             Log.d("RegisterActivity""I never expected this! Going down, going down!" + e);  
    99.             throw new RuntimeException(e);  
    100.         }  
    101.     }  
    102.     private void registerInBackground()  
    103.     {  
    104.         new AsyncTask < Void, Void, String > ()  
    105.         {  
    106.             @Override  
    107.             protected String doInBackground(Void...params)  
    108.             {  
    109.                 String msg = "";  
    110.                 try  
    111.                 {  
    112.                     if (gcm == null)  
    113.                     {  
    114.                         gcm = GoogleCloudMessaging.getInstance(context);  
    115.                     }  
    116.                     regId = gcm.register(Config.GOOGLE_PROJECT_ID);  
    117.                     Log.d("RegisterActivity""registerInBackground - regId: " + regId);  
    118.                     msg = "Device registered, registration ID=" + regId;  
    119.                     storeRegistrationId(context, regId);  
    120.                 }  
    121.                 catch (IOException ex)  
    122.                 {  
    123.                     msg = "Error :" + ex.getMessage();  
    124.                     Log.d("RegisterActivity""Error: " + msg);  
    125.                 }  
    126.                 Log.d("RegisterActivity""AsyncTask completed: " + msg);  
    127.                 return msg;  
    128.             }  
    129.             @Override  
    130.             protected void onPostExecute(String msg)  
    131.             {  
    132.                 Toast.makeText(getApplicationContext(), "Registered with GCM Server." + msg, Toast.LENGTH_LONG).show();  
    133.             }  
    134.         }.execute(nullnullnull);  
    135.     }  
    136.     private void storeRegistrationId(Context context, String regId)  
    137.     {  
    138.         final SharedPreferences prefs = getSharedPreferences(MainActivity.class.getSimpleName(), Context.MODE_PRIVATE);  
    139.         int appVersion = getAppVersion(context);  
    140.         Log.i(TAG, "Saving regId on app version " + appVersion);  
    141.         SharedPreferences.Editor editor = prefs.edit();  
    142.         editor.putString(REG_ID, regId);  
    143.         editor.putInt(APP_VERSION, appVersion);  
    144.         editor.commit();  
    145.     }  
    ShareExternalServer.java

    This class is used to share our registration id with the Java service.
    1. public class ShareExternalServer  
    2. {  
    3.     public String shareRegIdWithAppServer(final Context context, final String regId)  
    4.     {  
    5.         String result = "";  
    6.         Map < String, String > paramsMap = new HashMap < String, String > ();  
    7.         paramsMap.put("regId", regId);  
    8.         try  
    9.         {  
    10.             URL serverUrl = null;  
    11.             try  
    12.             {  
    13.                 serverUrl = new URL(Config.APP_SERVER_URL);  
    14.             }  
    15.             catch (MalformedURLException e)  
    16.             {  
    17.                 Log.e("AppUtil""URL Connection Error: " + Config.APP_SERVER_URL, e);  
    18.                 result = "Invalid URL: " + Config.APP_SERVER_URL;  
    19.             }  
    20.             StringBuilder postBody = new StringBuilder();  
    21.             Iterator < Entry < String, String >> iterator = paramsMap.entrySet().iterator();  
    22.             while (iterator.hasNext())  
    23.             {  
    24.                 Entry < String, String > param = iterator.next();  
    25.                 postBody.append(param.getKey()).append('=').append(param.getValue());  
    26.                 if (iterator.hasNext())  
    27.                 {  
    28.                     postBody.append('&');  
    29.                 }  
    30.             }  
    31.             String body = postBody.toString();  
    32.             byte[] bytes = body.getBytes();  
    33.             HttpURLConnection httpCon = null;  
    34.             try  
    35.             {  
    36.                 httpCon = (HttpURLConnection) serverUrl.openConnection();  
    37.                 httpCon.setDoOutput(true);  
    38.                 httpCon.setUseCaches(false);  
    39.                 httpCon.setFixedLengthStreamingMode(bytes.length);  
    40.                 httpCon.setRequestMethod("POST");  
    41.                 httpCon.setRequestProperty("Content-Type""application/x-www-form-urlencoded;charset=UTF-8");  
    42.                 OutputStream out = httpCon.getOutputStream();  
    43.                 out.write(bytes);  
    44.                 out.close();  
    45.                 int status = httpCon.getResponseCode();  
    46.                 if (status == 200)  
    47.                 {  
    48.                     result = "RegId shared with Application Server. RegId: " + regId;  
    49.                 }  
    50.                 else  
    51.                 {  
    52.                     result = "Post Failure." + " Status: " + status;  
    53.                 }  
    54.             }  
    55.             finally  
    56.             {  
    57.                 if (httpCon != null)  
    58.                 {  
    59.                     httpCon.disconnect();  
    60.                 }  
    61.             }  
    62.         }  
    63.         catch (IOException e)  
    64.         {  
    65.             result = "Post Failure. Error in sharing with App Server.";  
    66.             Log.e("AppUtil""Error in sharing with App Server: " + e);  
    67.         }  
    68.         return result;  
    69.     }  
    70. }  
    MainActivity.java
    1. public class MainActivity extends Activity  
    2. {  
    3.     ShareExternalServer appUtil;  
    4.     String regId;  
    5.     AsyncTask < Void, Void, String > shareRegidTask;  
    6.     @Override  
    7.     public void onCreate(Bundle savedInstanceState)  
    8.     {  
    9.         super.onCreate(savedInstanceState);  
    10.         setContentView(R.layout.activity_main);  
    11.         appUtil = new ShareExternalServer();  
    12.         regId = getIntent().getStringExtra("regId");  
    13.         Log.d("MainActivity""regId: " + regId);  
    14.         final Context context = this;  
    15.         shareRegidTask = new AsyncTask < Void, Void, String > ()  
    16.         {  
    17.             @Override  
    18.             protected String doInBackground(Void...params)  
    19.             {  
    20.                 String result = appUtil.shareRegIdWithAppServer(context, regId);  
    21.                 return result;  
    22.             }  
    23.             @Override  
    24.             protected void onPostExecute(String result)  
    25.             {  
    26.                 shareRegidTask = null;  
    27.                 Toast.makeText(getApplicationContext(), result, Toast.LENGTH_LONG).show();  
    28.             }  
    29.         };  
    30.         shareRegidTask.execute(nullnullnull);  
    31.     }  
    32. }  
    33. GCMNotificationIntentService.java  
    34. public class GCMNotificationIntentService extends IntentService  
    35. {  
    36.     public static final int NOTIFICATION_ID = 1;  
    37.     private NotificationManager mNotificationManager;  
    38.     NotificationCompat.Builder builder;  
    39.     public GCMNotificationIntentService()  
    40.     {  
    41.         super("GcmIntentService");  
    42.     }  
    43.     public static final String TAG = "GCMNotificationIntentService";  
    44.     @Override  
    45.     protected void onHandleIntent(Intent intent)  
    46.     {  
    47.         Bundle extras = intent.getExtras();  
    48.         GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);  
    49.         String messageType = gcm.getMessageType(intent);  
    50.         if (!extras.isEmpty())  
    51.         {  
    52.             if (GoogleCloudMessaging.MESSAGE_TYPE_SEND_ERROR.equals(messageType))  
    53.             {  
    54.                 sendNotification("Send error: " + extras.toString());  
    55.             }  
    56.             else if (GoogleCloudMessaging.MESSAGE_TYPE_DELETED.equals(messageType))  
    57.             {  
    58.                 sendNotification("Deleted messages on server: " + extras.toString());  
    59.             }  
    60.             else if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType))  
    61.             {  
    62.                 for (int i = 0; i < 3; i++)  
    63.                 {  
    64.                     Log.i(TAG, "Working... " + (i + 1) + "/5 @ " + SystemClock.elapsedRealtime());  
    65.                     try  
    66.                     {  
    67.                         Thread.sleep(5000);  
    68.                     }  
    69.                     catch (InterruptedException e)  
    70.                     {}  
    71.                 }  
    72.                 Log.i(TAG, "Completed work @ " + SystemClock.elapsedRealtime());  
    73.                 sendNotification("" + extras.get(Config.MESSAGE_KEY));  
    74.                 Log.i(TAG, "Received: " + extras.toString());  
    75.             }  
    76.         }  
    77.         GcmBroadcastReceiver.completeWakefulIntent(intent);  
    78.     }  
    79.     private void sendNotification(String msg)  
    80.     {  
    81.         Log.d(TAG, "Preparing to send notification...: " + msg);  
    82.         mNotificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);  
    83.         PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), 0);  
    84.         NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this).setSmallIcon(R.drawable.gcm_cloud).setContentTitle("GCM Notification").setStyle(new NotificationCompat.BigTextStyle().bigText(msg)).setContentText(msg);  
    85.         mBuilder.setContentIntent(contentIntent);  
    86.         mNotificationManager.notify(NOTIFICATION_ID, mBuilder.build());  
    87.         Log.d(TAG, "Notification sent successfully.");  
    88.     }  
    89. }  
    GCMBroadcassReceiver.java
    1. public class GcmBroadcastReceiver extends WakefulBroadcastReceiver  
    2. {  
    3.     @Override  
    4.     public void onReceive(Context context, Intent intent)  
    5.     {  
    6.         ComponentName comp = new ComponentName(context.getPackageName(), GCMNotificationIntentService.class.getName());  
    7.         startWakefulService(context, (intent.setComponent(comp)));  
    8.         setResultCode(Activity.RESULT_OK);  
    9.     }  
    10. }  
    JAVA Service ( GCMNotification.java)
    1. @WebServlet("/GCMNotification")  
    2. public class GCMNotification extends HttpServlet  
    3. {  
    4.     private static final long serialVersionUID = 1 L;  
    5.     // Put your Google API Server Key here  
    6.     private static final String GOOGLE_SERVER_KEY = "GOOGLE_API_KEY";  
    7.     static final String MESSAGE_KEY = "message";  
    8.     public GCMNotification()  
    9.     {  
    10.         super();  
    11.     }  
    12.     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException  
    13.     {  
    14.         doPost(request, response);  
    15.     }  
    16.     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException  
    17.     {  
    18.         String share = request.getParameter("shareRegId");  
    19.         // GCM RedgId of Android device to send push notification  
    20.         String regId = "";  
    21.         if (share != null && !share.isEmpty())  
    22.         {  
    23.             regId = request.getParameter("regId");  
    24.             PrintWriter writer = new PrintWriter("GCMRegId.txt");  
    25.             writer.println(regId);  
    26.             writer.close();  
    27.             request.setAttribute("pushStatus""GCM RegId Received.");  
    28.             request.getRequestDispatcher("index.jsp").forward(request, response);  
    29.         }  
    30.         else  
    31.         {  
    32.             try  
    33.             {  
    34.                 String id = "REG_ID";  
    35.                 StringBuffer buffer = new StringBuffer();  
    36.                 buffer.append("tets one #STATUS OnGoing #COMMENT test one sample notification #EFFORT .5hrs");  
    37.                 //buffer.append("\n");  
    38.                 //buffer.append("tetst two #STATUS OnGoing #COMMENT test two sample notification #EFFORT .5hrs");  
    39.                 String userMessage = request.getParameter("message");  
    40.                 Sender sender = new Sender("GOOGLE_SERVER_KEY");  
    41.                 Message message = new Message.Builder().timeToLive(3).delayWhileIdle(true).addData(MESSAGE_KEY, userMessage).build();  
    42.                 System.out.println("regId: " + id);  
    43.                 Result result = sender.send(message, id, 1);  
    44.                 request.setAttribute("pushStatus", result.toString());  
    45.             }  
    46.             catch (IOException ioe)  
    47.             {  
    48.                 ioe.printStackTrace();  
    49.                 request.setAttribute("pushStatus""RegId required: " + ioe.toString());  
    50.             }  
    51.             catch (Exception e)  
    52.             {  
    53.                 e.printStackTrace();  
    54.                 request.setAttribute("pushStatus", e.toString());  
    55.             }  
    56.             request.getRequestDispatcher("index.jsp").forward(request, response);  
    57.         }  
    58.     }  
    59. }  

Read more articles on Android: