Thursday 21 June 2012

Application Class: Application-wide data sharing #android

There are cases when we need to share same data to all application components and we want anyone to be able to update that data. Example of this use-case can be application settings e.g shared preferences.

Application class instance is initiated before any other component and remained there till the application terminate. You can think of application class as parent of all other application component (activities, services and broadcast receivers).

We can use application class as a global space available for all application components.We can get application object with getApplication() and call its public methods and variables where ever we like.

Lets see how can we create application class and use it:

1- Create new java class lets say MyApplication and extend it from Application

public class MyApplication extends Application {

int myGlobal;

@Override
public void onTerminate() {
// TODO Auto-generated method stub 
super.onTerminate();

@Override
public void onCreate() {

// TODO Auto-generated method stub super.onCreate();

myGlobal=0;

Log.d("sohail","MyApplication created, calling initSingleton");
}

public int getGlobal {

// TODO Auto-generated method stub
return myGlobal;
}

public void setGlobal(int in){

myGlobal=in;

} 

}

2. Set application name = MyApplication in manifest.xml. like


<application

android:icon="@drawable/ic_launcher"

android:label="@string/app_name" 

android:name=".MyApplication"

> 
..... 
..... 

</application> 
3- Now we can set and get our Global variable from any activity, service or broacast receiver like:

MyApplication appObj= (MyApplication) getApplication(); 

appObj.setGlobal(123);

appObj.getGlobal();


There are various useful methods which can be override in application class e.g

onConfigurationChanged() : called when device configuration changes while this application is running.

 onLowMemory(): "called when system is going in low memory and applications may get killed". We can override this function to release application resources and gracefully terminate the application before system terminate it.

Application class is good place for application centric data sharing, however normal intents should be used to pass data between application components and one should not abuse this space to make android a procedural language.

Note: Android application are not actually terminated when user close/exit the app (calling finish()), rather android System push the application on stack and decides itself when to actually terminate (kill process) the application. So Do not rely on application OnCreate and OnTerminate methods to initialize or de-initialize any variables. If application is not actually terminated by System, neither OnTerminate will be called nor OnCreate (on Second launch).

Monday 18 June 2012

Scheduling activities, services and broadcasts #Android

AlarmManager comes into play when we need to schedule different task in some future time/date or we need to execute some task repeatedly. AlarmManager is android service provided for scheduling purposes. We can use AlarmManager to start activities/services and to send broadcast in some future date/time. Activities, Services or broadcasts registered with AlarmManager will be executed no matter your application is running or not. You can also make AlarmManager to wake up the device (if in sleep state) on given schedule.

In order to registered application components (activities, services and broadcasts) with AlarmManager, we need to obtain a Pending Intent  of an Intent and the use this Intent to  register with AlarmManager. The difference between Pending Intent and normal Intent is that "they are launched with the your application permissions rather than the one who is launching them".

Below is the comparison of pendingInent and normal Inents for starting activities, services and broadcasts:

PendingInent.getActivity =~ startActivity (Inent)
PendingInent.getService =~ startService(Intent)
PendingInent.getBroadcast =~ sendBroadcast(Inent)

Lets say we want to launch an activity called MyActivity after 5 seconds of the current time. We will:

  • Create an Intent of the activity we want to launch.
  • Obtain a PendingIntent of this Intent.Registered this pending intent with AlarmManager.
 
Intent i = new Intent(getApplicationContext(), MyActivity.class);
PendingIntent pi = PendingIntent.getActivity(getApplicationContext(),3333,i,
PendingIntent.FLAG_CANCEL_CURRENT);
 


Lets quickly explain the getActivity arguments, first one is context, second one is
optional number (lets say identification number, fourth one is the intent we want to launch and the last one is again optional flag (in this case we are telling the system that if this intent (3333) is already running cancel it and run again.

  • Registered it with alarmmanager,

 
//getting current time and add 5 seconds in it 
Calendar cal = Calendar.getInstance(); 
cal.add(Calendar.SECOND, 5); 
//registering our pending intent with alarmmanager 
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE); 
am.set(AlarmManager.RTC_WAKEUP,cal.getTimeInMillis(), pi);
 

First argument of am is the flag telling the system what to do, in this case we are telling the system that wake up the system if its in sleep state while launching the intent on this particular time.
In order to start service or send broadcast we only need to create pending intent
these and pass to alarmmanager, e.g lets say we have service called MyService


 
Intent ii = new Intent(getApplicationContext(), MyService.class);
PendingIntent pii = PendingIntent.getService(getApplicationContext(), 2222, ii,
PendingIntent.FLAG_CANCEL_CURRENT);
 

and for broadcast

 
Intent i= new Intent(); 
i.setAction("my.action"); //the name which we will specify in our receiver 
i.putExtra("counter",234); PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(),
1111, i,PendingIntent.FLAG_CANCEL_CURRENT);
 


Thats for today. Have a question ? ask!