Tuesday, February 3, 2015

How to create your own background for Google Docs



As i was making documents to share with my students using Google Docs, i wanted to create a background for all these documents. Hence i had to do the necessary research to achieve this. I would like to share it with you which may help the Google docs user.

Step I:

Load the background image to the google drive.

Step II:

Create a URL for this image. To do that first go to the sharing option of that image in google docs and make it publicly available. Then open the website

http://www.gdurl.com/ and copy the sharable link to this site to create a permalink.

Step III:

Open the website https://chrome.google.com/webstore/category/apps in chrome browser and search for Stylish extension.



And install this extension. It will add an icon on the right side of the address bar.

Step IV:

  • Open any google docs and click on the stylish icon.
  • Click the first link Find more styles for this site
  • You may search for Linen Background for Google Docs and click the link
  • Now open your Google docs and you will see a nice background
  • Click on the Stylish icon on the right hand side of the address bar and this time click “Manage installed styles”
  • Then in the right pane click the button edit.
  • Replace the background url with the permlink that you have got in step II. It will look something like the following
#docs-editor {
background: url(http://gdurl.com/lQ3I) !important;
}
.docs-title-inner {font-family: Georgia !important;}
.docs-menubar {height:28px !important;}

Step V:

Refresh the open google docs and enjoy the background you have just created.

Monday, January 26, 2015

The Designing of a Software System from scratch with the help of OOAD & UML - A Restaurant System


Note : See the source code from this link.

From the last few days i have been thinking to share my idea about how to design software system from scratch with the help of object oriented principles. The way the OOPS is taught to the students may enable them to write small programming assignments, but when it comes to design a whole system, many of them may falter. I would like to address that part with the  basic principle of OOAD and tell you how to traverse from the problem domain to the solution domain with the help of OOAD.


So, lets start. I have thought of an example to design a Restaurant system from scratch. I have used Java as the language, but one can use any OO language to achieve it.


To start designing of a software system using OOAD, one has to first identify the main entities participating in that system. So, in a Restaurant system who are the main participants? You guessed it right. A restaurant itself. Then the next entity is of course a customer. I think these are the main two entities. Now what does a restaurant consist of. It consists of some tables, a menu card, and food items. Another thing i have forgotten to mention. A restaurant should have a FIFO queue for its customers… right?


Now what kind of operation a Restaurant has to do? It should have some functionality to know if all tables are occupied, and if not which one is vacant; it should be able to book a vacant table when a new customer arrives. And when the customer leaves, it should be able to release that table and if anybody is waiting in its FIFO queue, it should be able to allocate that vacant table to that customer. It should also keep a track about who is the current customer it is serving and which customer has been allocated which table. Then it should also be able to generate a bill.


Now what does a Menu consist of? It has a list of some food items… right? So from Menu’s angle, it needs an entity called Item. Now what are the attributes of a food item vis-a-vis a restaurant? Each item should have an ID, a Name and its Price… right?


Now think that a restaurant will have a list of tables scattered systematically. So what kind of attributes a Table in a Restaurant may have? It should have an ID and it should know whether it is occupied or not. What kind of operation does a Table need? When a customer leaves the table, it should be able to tell the outside that it is occupied… right? On the other hand when a customer leaves the table it should let the outside world know that it is vacant and ready to accept new customer.


With these things in mind lets design the Restaurant, Table, Menu and Item classes.


Restaurant.pngitem.png


menu.pngtable.png


Now lets talk about the other main entity called the Customer. What are the attributes of a customer should have when he enters a restaurant. he must have an ID. i am not talking about his passport or SSN or Aadhar card ID. This ID is with respect to the restaurant by which the customer can be identified within the Restaurant premise. We will also add Name as another attribute to a customer. Although there is no absolute need for this from the OOAD designer’s perspective, this is needed only for decoration as you will see later. And what kind of operation a customer usually does. He looks at the menu, decides what he wants to have and how many plates… right? So the customer entity should have an operation called giveOrder. Now think about this. In order to give order customer needs an entity which will hold the customer’s choice, i.e., which item and how many plates for that item. Lets call this entity as ItemOrder, each ItemOrder object representing a specific Item and its number of plates ordered by the customer. So in the actual order by a customer, there will be a collection for all these ItemOrders objects created by the customer. Lets create a class as Order which will hold a list of such ItemOrder objects. This Order class can be used by the Resaturant entity for calculating the total amount to be billed to the customer… right? So in essence, we have got three major classes to design the customer and his flow of orders, namely Customer, ItemOrder, Order. Lets see how these classes will look like.


customer.pngorder.pngitemOrder.png


Remember, all setters and getters functions have been removed from these diagrams (except ItemOrder) to make it simple.


Okay, another helper class we need. That is the bill class. It should have the functionality to calculate the total amount to be billed for a particular customer.
bill.png
With all these classes ready, lets design the complete class diagram of the Restaurant System.


As you have probably guessed that a Restaurant HAS Tables and Restaurant HAS Menu. Menu HAS Item (rather items, a list of item). Restaurant has an ASSOCIATION with the Customer. The Bill stores a reference to a Customer for future use. Hence Bill has an AGGREGATION relationship with Customer. Each Customer creates an Order. Hence Customer HAS Order. And an Order holds a list of ItemOrders each representing and amount ordered for a particular Item. Hence Order HAS ItemOrder. Each ItemOrder keeps a reference of Item. Hence ItemOrder has an AGGREGATION relationship with Item. The Restaurant USEs Bill to calculate the total bill.


And with this explanation, the complete class diagram will look as the following.
Class Diagram.png


Please note that the complete signatures of the operations are not given in the UML diagrams to make it simple. You can refer the respective class from the source code attached to have an idea of each operation.


Let me  explain the UML in more detail. As you can see that Restaurant has a one-to-one HAS relationship with Menu and an one-to-many HAS relationship with the TABLE. This is quite obvious… right? Because a single Restaurant will have only one Menu list and it may have one to many number of TABLEs. The relationship of the Restaurant with the Customer is Association. Because a customer is an Independent entity. The Restaurant simply adds the new customer to its FIFO queue. As i have already mentioned, that a Customer HAS a Order (one-to-one relationship). Because whenever a customer plans to order, he needs to create an Order which he will populate with different ItemOrders(remember ItemOrder keeps a reference to an Item and how many plates the customer needs). As the ItemOrder keeps a reference to the Items, it obviously has an Aggregation relationship with the Item. A bill also has to keep a reference of the customer because it needs to identify for which customer the Bill has been generated. Hence the Bill also has an Aggregation relationship with Customer. The Restaurant has a USE relationship with the Bill because it creates the Bill object as a local variable in the generateBill function. Now probably you have acquired some sorts of idea about how this whole system has been designed using UML and OOAD.
The code for this whole Restaurant System is here. It is, of course in accordance to this class diagram given earlier.

Hope this helps the OOAD learners....

Tuesday, December 30, 2014

The story of a dream chaser

Here is my story of the journey to become an able software engineer...

The dream-chaser...

Friday, October 31, 2014

Generic Asynchronous Task for HTTP connection in Android

As I was working on the development of an Android app,  i created a generic Asynchronous task for HTTP connection. I thought its a idea to share it here.

The HttpAsyncTask class


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONObject;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

public class HTTPAsyncTask extends AsyncTask<String, Void, String> {
 
 private CallBack mCb;
 HashMap<Object, Object> mData = null;
 //List mParams= new ArrayList();
 HashMap<Object, Object> mParams = new HashMap<Object, Object>();
 String mTypeOfRequest;
 String mStrToBeAppended = "";
 boolean isPostDataInJSONFormat = false;
 JSONObject mJSONPostData = null;
 Context mContext = null;
 
 public HTTPAsyncTask(Context context, CallBack c, HashMap<Object, Object> data, JSONObject jsonObj, String request) {
  mContext = context;
  mCb = c;
  mTypeOfRequest = request;
  mJSONPostData = jsonObj;
  
  //Log.i("JSONDATA", mJSONPostData.toString());
  if((data != null) && (jsonObj == null)){
   mData = data;
   if(mTypeOfRequest.equalsIgnoreCase("GET")){
    Object key = null;
    Iterator<Object> it = mData.keySet().iterator();
    while(it.hasNext()){
     key = it.next();
     mParams.put(key, mData.get(key));
    }
    for (int i = 0; i<mParams.size()-1; i++){
     mStrToBeAppended+= "?" + key + "=" + mParams.get(key) + "&"; 
    }
    //add the last parameter without the "&"
    mStrToBeAppended+= "?" + key + "=" + mParams.get(key);
    
   }
   
   if(mTypeOfRequest.equalsIgnoreCase("POST")){
     Object key = null;
     isPostDataInJSONFormat = false;
     Iterator<Object> it = mData.keySet().iterator();
     while(it.hasNext()){
      key = it.next();
      mParams.put(key, mData.get(key));
     }
   }
  
  }
  if ((mData == null) && (mJSONPostData != null) && (mTypeOfRequest.equalsIgnoreCase("POST") == true)){
   isPostDataInJSONFormat = true;
   //Log.i("ISJSONDATA",Boolean.toString(isPostDataInJSONFormat) );
  }
  
 }
 
 
 
    @Override
    protected String doInBackground(String... baseUrls) {
     
     //android.os.Debug.waitForDebugger();
     
     publishProgress(null);
     if(mTypeOfRequest.equalsIgnoreCase("GET")){
      String finalURL = baseUrls[0]+ mStrToBeAppended;
       return HttpUtility.GET(finalURL);
     }
     
     if (mTypeOfRequest.equalsIgnoreCase("POST")){
      if(isPostDataInJSONFormat == false){
       return HttpUtility.POST(baseUrls[0],mParams );
      }
      if(isPostDataInJSONFormat == true){
       Log.i("JSONDATAPOSTMETHOd","JSON POST method to be called...");
       return HttpUtility.POST(baseUrls[0], mJSONPostData);
      }
     
     }
     
     return null;
    
    }
    // onPostExecute displays the results of the AsyncTask.
    @Override
    protected void onPostExecute(String result) {
     //if(mContext != null){
      mCb.onResult(result);
     //}
       
       
       
   }
    
    @Override
    protected void onProgressUpdate(Void...voids ) {
     //if(mContext != null){
      mCb.onProgress();
     //}
        
   }
}

The HttpUtility Class


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONObject;

import android.util.Log;

public class HttpUtility {
 
 private final static HttpClient mHhttpclient = new DefaultHttpClient();
 
 public static String GET(String url){
        InputStream inputStream = null;
        String result = "";
        try {
 
            // create HttpClient
            //HttpClient httpclient = new DefaultHttpClient();
 
            // make GET request to the given URL
            HttpResponse httpResponse = mHhttpclient.execute(new HttpGet(url));
 
            // receive response as inputStream
            inputStream = httpResponse.getEntity().getContent();
 
            // convert inputstream to string
            if(inputStream != null){
             result = convertInputStreamToString(inputStream);
             //inputStream.close();
            }
                
            else
                result = "Did not work!";
 
        } catch (Exception e) {
            Log.d("InputStream", e.getLocalizedMessage());
        }
 
        return result;
    }
 
 public static String POST(String url, HashMap&lt;Object, Object&gt; mParams){
  InputStream inputStream = null;
        String result = "";
  try{
   //HttpClient httpclient = new DefaultHttpClient();
         HttpPost post = new HttpPost(url);
         post.setEntity(new UrlEncodedFormEntity((List extends NameValuePair&gt;) mParams, "UTF-8"));
         HttpResponse httpResponse = mHhttpclient.execute(post);
         
      // receive response as inputStream
            inputStream = httpResponse.getEntity().getContent();
 
            // convert inputstream to string
            if(inputStream != null){
             result = convertInputStreamToString(inputStream);
             //inputStream.close();
            }
                
            else
                result = "Did not work!";
 
        } catch (Exception e) {
            Log.d("InputStream", e.getLocalizedMessage());
        }
 
        return result;
  
        
 }
 public static String POST(String url, JSONObject obj){
  
  Log.i("JSONPOSTBEGIN", "Beginning of JSON POST");
  InputStream inputStream = null;
        String result = "";
     
     //HttpClient httpclient = new DefaultHttpClient();

     try{
      HttpPost post = new HttpPost(url);
      post.setHeader("Content-type", "application/json");
      post.setHeader("Accept", "application/json");
      
      StringEntity se = new StringEntity(obj.toString());
      //se.setContentType("application/json;charset=UTF-8");
         se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
         post.setEntity(se);
         
         HttpResponse httpResponse = mHhttpclient.execute(post);
         
         // receive response as inputStream
            inputStream = httpResponse.getEntity().getContent();
      
            // convert inputstream to string
            if(inputStream != null){
             result = convertInputStreamToString(inputStream);
            }
                
            else
                result = "Did not work!";
 
        } catch (Exception e) {
            Log.d("InputStream", e.getLocalizedMessage());
        }
     Log.i("JSONPOSTEND", "End of JSON data post methos...");
     return result;
 }
 
 public static String convertInputStreamToString(InputStream inputStream) throws IOException{
        BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(inputStream));
        String line = "";
        String result = "";
        while((line = bufferedReader.readLine()) != null)
            result += line;
 
        inputStream.close();
        return result;
 
    }
}

The CallBack Interface


public interface CallBack {
 public void onProgress();
 public void onResult(String result);
 public void onCancel();
}

The callback interface has to be implemented in the Activity from where the Asynctask is called as the following


final CallBack cb = new CallBack(){
   @Override
   public void onProgress() {
    // TODO Auto-generated method stub
    mProgressDialogSignup.show();
   }

   @Override
   public void onResult(String result) {
    // TODO Auto-generated method stub
    
    mProgressDialogSignup.dismiss();
    mStrResult = result;
    //Now process the result 
   }

   @Override
   public void onCancel() {
    // TODO Auto-generated method stub
    
   }
  };

The way these Asynctasks are called are as follows:

String url=  "Your URL"
JSONObject postData = new JSONObject();

postData.put(Key1, Data1);
postData.put(Key2, Data2);

HTTPAsyncTask asyncTask = new AsyncTask(mContext,cb, null, postData, "POST");

asyncTask.execute(url);

Hope this helps the Android learners...

Monday, February 24, 2014

Structural Relationship between Content Resolver and Content Provider - an example of Proxy Design Pattern...

As i was digging into the source code of Content Provider and Content Resolver, i found a nice structural relationship among the two and it closely resembles the Proxy Pattern of the GoF book. We need Proxy Pattern whenever there is a need of a sophisticated reference to an object other than the simple pointer.


The class diagram of the Proxy Pattern is something similar to the following:





What it actually does is that it adds a level of indirection when accessing an object. Whenever a client needs to interact with an object of a RealSubject, it instead interacts with a Proxy of it. The proxy forwards the request to the RealSubject.


Now let us dig into the source code of Content Resolver and Content Provider to understand how it resembles the Proxy Pattern. The Content Provider offers the client of it all of the CRUD (create, read, update & delete) functionalities. Internally what it does it forwards these functionalities to the Content Provider. There is an one to one mapping between the CRUD functions of the Content Resolver with the Content Providers. A simplistic version of the structural relationship between the Content Resolver and the Content Provider can be depicted as follows.



Whenever the client calls any of the above functions on the ContentResolver, it just gets a reference to the appropriate Content Provider by the function called aquireProvider and then delegates that function to that of the ContentProvider. In each of these CRUD functions, the ContentResolver also manages the lifecycle of the ContentProvider it acquires through a function called releaseProvider.


Thus we can say that to a client, the ContentResolver works as a proxy of ContentProviders.

Monday, February 17, 2014

Question Bank for Advanced Android Learners...

I am trying to create a question bank for advanced android learners. You can find it at

http://www.classmarker.com/online-test/start/?quiz=mhy52fd5f7c711fa

Please send me more relevant questions which i can add to this list.

I hope this will give clue to many Android learners to explore more and Google different topics. 

Friday, January 10, 2014

Implementation of a State machine for a long running background task in an Android service

In the below example i will show how we can break a long running background task running in a service into different states of a state machine and notify the front end UI about each and every stage as they occur in the service. Here i have used a service called LongRunningService which actually (theoretically) does the task of downloading a big file from a network server (however, for simplicity i have just stubbed out the actual download code with a thread having delay of 1000 ms). This background task has been splitted into different states according to the state machine like “Start Connection”, “Connection Completed”, “Start Downloading” and “Stop Downloading”. This application also showcases the concept of communicating from a background service to the frontend UI through Android messenger framework.

So lets start digging into the source code of the application.

First of all the main Activity class.

As it is clear from the code that the main activity has a messenger whose message handling part has been defined by a class called MessageHandler (derived from Handler). This is the messenger object through which the background service notifies the UI thread.

The UI has a button. Upon clicking it, it starts the service and as soon as it starts the service the service starts notifying about the different states of the Service through the messenger.

This is pretty simple. Right!!!

The class MainActivity.Java


package com.somitsolutions.android.example.statepatterninservice;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Messenger;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener{
          private static final int CONNECTING = 1;
          private static final int CONNECTED = 2;
          private static final int DOWNLOADSTARTED = 3;
          private static final int DOWNLOADFINISHED = 4;
          
          Button startButton;
          private MessageHandler handler;
          private static MainActivity mMainActivity;
          
          public Messenger mMessenger = new Messenger(new MessageHandler(this));
          private class MessageHandler extends Handler{
                   private Context c;
                   
                   MessageHandler(Context c){
                   this.c = c;     
                   }
                   @Override
       public void handleMessage(Message msg) {
                             switch(msg.what){
                             case CONNECTING:
                                      Toast.makeText(getApplicationContext(), "Connecting", Toast.LENGTH_LONG).show();
                                      break;
                             case CONNECTED:
                                      Toast.makeText(getApplicationContext(), "Connected", Toast.LENGTH_LONG).show();
                                      break;
                             case DOWNLOADSTARTED:
                                      Toast.makeText(getApplicationContext(), "Download Started", Toast.LENGTH_LONG).show();
                                      break;
                             case DOWNLOADFINISHED:
                                      Toast.makeText(getApplicationContext(), "Download Finished", Toast.LENGTH_LONG).show();
                                      break;
                             default:
                                      super.handleMessage(msg);
                                                
                             }
                   }
          }
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       mMainActivity = this;
       startButton = (Button)findViewById(R.id.button1);
     
       startButton.setOnClickListener(this);
   }


   @Override
   public boolean onCreateOptionsMenu(Menu menu) {
       // Inflate the menu; this adds items to the action bar if it is present.
       getMenuInflater().inflate(R.menu.main, menu);
       return true;
   }
   public static MainActivity getMainActivity(){
          return mMainActivity;
   }


          @Override
          public void onClick(View arg0) {
                   // TODO Auto-generated method stub
                   Intent serv = new Intent(MainActivity.this, LongRunningService.class);
       startService(serv);
          }
}


Now lets start digging the LongrunningServivce class.

As we know that a service usually runs in the main thread. Hence the UI thread may seem to be frozen in case of a long background service. To overcome that a background thread is being created the moment one starts the service and the task is executed in that thread. This is clear from the following piece of code.

@Override
           public void onCreate() {
             // Start up the thread running the service.  Note that we create a
             // separate thread because the service normally runs in the process's
             // main thread, which we don't want to block.  We also make it
             // background priority so CPU-intensive work will not disrupt our UI.
             HandlerThread thread = new HandlerThread("ServiceStartArguments",
                     Thread.NORM_PRIORITY);
             thread.start();

             // Get the HandlerThread's Looper and use it for our Handler
             mServiceLooper = thread.getLooper();
             mServiceHandler = new ServiceHandler(mServiceLooper);
           }

The service class also has a Handler class called ServiceHandler through which we send messages from the service to the thread’s message loop. Inside the message loop, we actually accomplish the long running task. Lets have a look at this ServiceHandler class


private final class ServiceHandler extends Handler {
               public ServiceHandler(Looper looper) {
                   super(looper);
               }
               @Override
               public void handleMessage(Message msg) {
                 
                    
                     Messenger messenger= MainActivity.getMainActivity().mMessenger;
                             
                           try {
                             
                             
                             messenger.send(Message.obtain(null, CONNECTING, "Connecting"));
                             // Normally we would do some work here, like download a file.
                                      // For our sample, we just sleep for 10 seconds.
                                                Thread.sleep(1000);
                                                // Normally we would do some work here, like download a file.
                                      // For our sample, we just sleep for 10 seconds.
                                                
                                                messenger.send(Message.obtain(null, CONNECTED, "Connected"));
                                                // Normally we would do some work here, like download a file.
                                    // For our sample, we just sleep for 10 seconds.
                                                Thread.sleep(1000);
                                                
                                                
                                                messenger.send(Message.obtain(null, DOWNLOADSTARTED, "Download Started"));
                                                // Normally we would do some work here, like download a file.
                                    // For our sample, we just sleep for 10 seconds.
                                                Thread.sleep(1000);
                                                
                                                
                                                messenger.send(Message.obtain(null, DOWNLOADFINISHED, "Download Finished"));
                                                
                                                
                                      } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                      } catch (RemoteException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                      }
                   // Stop the service using the startId, so that we don't stop
                   // the service in the middle of handling another job
                   stopSelf(msg.arg1);
               }
           }

As it becomes clear from the above code that in this overridden HandleMessage function of the service handler, we acquire a reference to the messenger of the main activity and it falls through different states like “Connecting”, “Connected”, “Start Downloading” and “Finish Downloading”. In each state a different integer constant is being passed to the UI thread through the messenger.

In the main UI thread the handler function of the messenger handles these messages from the service and displays the status of the each state.

After that the service stops itself.


package com.somitsolutions.android.example.statepatterninservice;


import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.widget.Toast;

public class LongRunningService extends Service {
          
          private static final int CONNECTING = 1;
          private static final int CONNECTED = 2;
          private static final int DOWNLOADSTARTED = 3;
          private static final int DOWNLOADFINISHED = 4;
          
          private Looper mServiceLooper;
          private ServiceHandler mServiceHandler;   // Handler that receives messages from the thread
          private final class ServiceHandler extends Handler {
               public ServiceHandler(Looper looper) {
                   super(looper);
               }
               @Override
               public void handleMessage(Message msg) {
                 
                    
                     Messenger messenger= MainActivity.getMainActivity().mMessenger;
                             
                           try {
                             
                             
                             messenger.send(Message.obtain(null, CONNECTING, "Connecting"));
                             // Normally we would do some work here, like download a file.
                                      // For our sample, we just sleep for 10 seconds.
                                                Thread.sleep(1000);
                                                // Normally we would do some work here, like download a file.
                                      // For our sample, we just sleep for 10 seconds.
                                                
                                                messenger.send(Message.obtain(null, CONNECTED, "Connected"));
                                                // Normally we would do some work here, like download a file.
                                    // For our sample, we just sleep for 10 seconds.
                                                Thread.sleep(1000);
                                                
                                                
                                                messenger.send(Message.obtain(null, DOWNLOADSTARTED, "Download Started"));
                                                // Normally we would do some work here, like download a file.
                                    // For our sample, we just sleep for 10 seconds.
                                                Thread.sleep(1000);
                                                
                                                
                                                messenger.send(Message.obtain(null, DOWNLOADFINISHED, "Download Finished"));
                                                
                                                
                                      } catch (InterruptedException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                      } catch (RemoteException e) {
                                                // TODO Auto-generated catch block
                                                e.printStackTrace();
                                      }
                   // Stop the service using the startId, so that we don't stop
                   // the service in the middle of handling another job
                   stopSelf(msg.arg1);
               }
           }
          
          @Override
           public void onCreate() {
             // Start up the thread running the service.  Note that we create a
             // separate thread because the service normally runs in the process's
             // main thread, which we don't want to block.  We also make it
             // background priority so CPU-intensive work will not disrupt our UI.
             HandlerThread thread = new HandlerThread("ServiceStartArguments",
                     Thread.NORM_PRIORITY);
             thread.start();

             // Get the HandlerThread's Looper and use it for our Handler
             mServiceLooper = thread.getLooper();
             mServiceHandler = new ServiceHandler(mServiceLooper);
           }

           @Override
           public int onStartCommand(Intent intent, int flags, int startId) {
               Toast.makeText(this, "download service starting", Toast.LENGTH_SHORT).show();

               // For each start request, send a message to start a job and deliver the
               // start ID so we know which request we're stopping when we finish the job
               Message msg = mServiceHandler.obtainMessage();
               msg.arg1 = startId;
               mServiceHandler.sendMessage(msg);
              
               // If we get killed, after returning from here, restart
               return START_STICKY;
           }

           @Override
           public IBinder onBind(Intent intent) {
               // We don't provide binding, so return null
               return null;
           }

           @Override
           public void onDestroy() {
             Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
           }
          }

The main.xml layout file looks like the following:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:paddingBottom="@dimen/activity_vertical_margin"
   android:paddingLeft="@dimen/activity_horizontal_margin"
   android:paddingRight="@dimen/activity_horizontal_margin"
   android:paddingTop="@dimen/activity_vertical_margin"
   tools:context=".MainActivity" >

   <Button
       android:id="@+id/button1"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentTop="true"
       android:layout_centerHorizontal="true"
       android:layout_marginTop="165dp"
       android:text="Start Service" />

</RelativeLayout>

And the manifest file of this application is as follows:

xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.somitsolutions.android.example.statepatterninservice"
   android:versionCode="1"
   android:versionName="1.0" >

   <uses-sdk
       android:minSdkVersion="8"
       android:targetSdkVersion="17" />

   <application
       android:allowBackup="true"
       android:icon="@drawable/ic_launcher"
       android:label="@string/app_name"
       android:theme="@style/AppTheme" >
       <activity
           android:name="com.somitsolutions.android.example.statepatterninservice.MainActivity"
           android:label="@string/app_name" >
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
       </activity>
       <service android:name=".LongRunningService"></service>
   </application>
 
</manifest>

Hope it clears some of the ideas behind Android messenger and how we can use it for notification from a background service to the frontend UI.
You may also read or download the document from here.

Share