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