Android Services
In Android, we have an interesting
tool to work with when we want to run background applications or processes.
Let's have a look at it!
How
Android Services Work
Sometimes, we would like to have an application
running in the background of our device, waiting for any change in the system,
or maybe we want to run an application with the usual Activities, and a “piece
of code” running, in the background that checks in on the Internet, waiting for
incoming SMS messages or other events.
In those cases Android Services are
available. They are classes without UI (Activities are classes with UI), so
they can be executed in the background, in a separate thread and you can start
and stop them from an Activity.
This could be difficult to
understand so to make it more clear we'll put up some examples.
Here's the classic example of when a
Service would be used: In an audio player. Imagine, you have an MP3 player
(downloaded from Android Market, done by yourself or the default media player
in the device), you can then select artist, albums, songs... you start playing
a song, and then you want to go back to the home screen to start another
activity (in this case I'm not talking about Android Activities, its just the common
word “activity”), you go to the home screen, but the song you have selected is
still playing...
A less classic example. You have a
simple RSS reader, with a list that includes all new posts from a very well
known blog. A Service will search for updates via the site, and then it will
update the screen with the new info. All while running in the background.
Now that we have a more clear
understanding of how a Service works, let's move deeper into the Service
construction.
Building
a Service
First of all, we need to create the
Service in the AndroidManifest.xml file. Remember, that every Activity,
Service, Content Provider you create in the code, you need to create a
reference for here, in the Manifest, if not, the application will not recognize
it.
<service
android:name=".subpackagename.ServiceName"/>
In the code, we need to create a
class that extends from “Service”
public class ServiceName extends
Service {
private Timer timer = new Timer();
protected void onCreate() {
super.onCreate();
startservice();
}
}
This is a way to create Services,
there are others ways, or the way I use to work with them. Here, we create a Timer,
that every X seconds, calls to a method. This is running until we stop it. This
can be used, for example, to check updates in an RSS feed. The “Timer” class is
used in the startservice method like this
private void startservice() {
timer.scheduleAtFixedRate( new
TimerTask() {
public void run() {
//Do whatever you want to do every
“INTERVAL”
}
}, 0, INTERVAL);
; }
Where INTERVAL, is the time, every time the run method is executed.
To stop the service, we can stop the
timer, for example, when the application is destroyed (in onDestroy())
private void stopservice() {
if (timer != null){
timer.cancel();
}
}
So, this application will be running
in the background... But...How do we bind it with Activities? Or how can we
start a Service from an Activity? In the next lesson we will delver deeper into
Services.
Short
term background process
Sometimes we need to accomplish
short background tasks. For this, I recommend using AsyncTasks. Here you will
find an article that explains how to work with them:
Working with AsyncTask in Android
Using Services in Android allows us
to have an application running in the background. But, what if we want to do a
simple task in the background? AsyncTask is the answer.
Our Android application can become
more complex with time, connections with a server, sending and receiving data
from the web, storing big amounts of data in the Android database while showing
a progress bar, or a notification in the notification bar... How do we do this,
without interrupting the UI Thread to show a notification while we are
receiving data from a server? First of all, what's the “UI Thread”?
If you are familiar with the
“Thread” term, it's easy to understand. Android applications have a main
thread where all is processed. It's like having “OneTask” that does
everything. If we had only this UI Thread to work with, you would not be able
to do some things like, storing 10,000 data rows in the application at the same
time you are using it. The application would stick, until the process “store 10,000
data rows” was finished. But, this is not the case! In Android you can have multiple
threads running at the same time in one application. The UI Thread, allows
you to move through the screen, while, for example, a background task is
receiving data from a server and storing it in the database.
Hope the term “Thread” is clear
enough to go on.
Now, how can we do this? Having a
task running in the background? There is (at least, in my knowledge) various
ways of doing it.
One way is the “Old-java-way”, and
it's using the class Thread, the Handlers and Runnables.
But I have a better way to do it, and it's using AsyncTask class.
The
AsyncTask class
Let's see the structure of a typical
AsyncTask class.
private class myBrightHubTask
extends AsyncTask<X, Y, Z>
protected void onPreExecute(){
}
This method is executed before
starting the new Thread. There is no input/output values, so just initialize
variables or whatever you think you need to do.
protected Z doInBackground(X...x){
}
The most important method in the
AsyncTask class. You have to place here all the stuff you want to do in the
background, in a different thread from the main one. Here we have as an input
value an array of objects from the type “X” (Do you see in the header? We have
“...extends AsyncTask<X,Y,Z>” These are the TYPES of the input
parameters) and returns an object from the type “Z”.
protected void onProgressUpdate(Y
y){
}
This method is called using the
method publishProgress(y) and it is usually used when you want to show
any progress or information in the main screen, like a progress bar showing the
progress of the operation you are doing in the background.
protected void onPostExecute(Z
z){
}
This method is called after the
operation in the background is done. As an input parameter you will receive the
output parameter of the doInBackground method.
What about the X, Y and Z types?
As you can deduce from the above
structure:
X – The type of the input variables
value you want to set to the background process. This can be an array of
objects.
Y – The type of the objects you are
going to enter in the onProgressUpdate method.
Z – The type of the result from the
operations you have done in the background process.
How do we call this task from an outside
class? Just with the following two lines:
myBrightHubTask brightHubTask
= new myBrightHubTask();
brightHubTask.execute(x);
Where x is the input parameter of
the type X.
Once we have our task running, we
can find out its status from “outside”. Using the “getStatus()” method.
brightHubTask.getStatus();
and we can receive the following
status:
RUNNING - Indicates that the task is running.
PENDING - Indicates that the task has not been executed yet.
FINISHED - Indicates that onPostExecute(Z) has finished.
Hints
Here are some hints about using AsyncTask
- Do not call the methods onPreExecute, doInBackground
and onPostExecute manually. This is automatically done by the
system.
- You cannot call an AsyncTask inside another AsyncTask
or Thread. The call of the method execute must be done in the UI Thread.
- The method onPostExecute is executed in the UI
Thread (here you can call another AsyncTask!).
- The input parameters of the task can be an Object
array, this way you can put whatever objects and types you want.
Android implements single thread model and whenever an Android application is launched, a thread is created. Now assume you have long running operations like a network call on a button click in your application. On button click a request would be made to the server and response will be awaited. Now due to the single thread model of Android, till the time response is awaited your UI screen hangs or in other words, it is non-responsive.
We can overcome this by creating a new Thread and implement the run method to perform the time consuming operation, so that the UI remains responsive.
As shown below a new Thread is created in onClick method
1
2
3
4
5
6
7
8
|
public
void onClick(View v) { Thread
t = new Thread(){ public
void run(){ //
Long running operation } }; t.start(); } |
There are various approaches via which control can be given back to UI thread (Main thread running the application). Handler approach is one among the various approaches.
Handler
Let us look at the code snippet below to understand Handler approach.
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public
void onClick(View v) { Thread
t = new Thread(){ public
void run(){ //
Long time comsuming operation Message
myMessage=new Message(); Bundle
resBundle = new Bundle(); resBundle.putString("status",
"SUCCESS"); myMessage.obj=resBundle; handler.sendMessage(myMessage); } }; t.start(); } |
1
2
3
4
5
6
|
private
Handler handler = new Handler() { @Override public
void handleMessage(Message msg) { //
Code to process the response and update UI. } }; |
Handler approach works fine, but with increasing number of long operations, Thread needs to be created, run method needs to be implemented and Handler needs to be created. This can be a bit cumbersome. The Android framework has identified this pattern and has nicely enveloped it into what is called an Android Async Task. Let us look at how it can help simplify things.
Async Task
Android Async Task takes cares of thread management and is the recommended mechanism for performing long running operations.Let us look at a sample class LongOperation, which extends the AsyncTask below:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
private
class LongOperation extends AsyncTask<String, Void, String> { @Override protected
String doInBackground(String... params) { //
perform long running operation operation return
null; } /*
(non-Javadoc) *
@see android.os.AsyncTask#onPostExecute(java.lang.Object) */ @Override protected
void onPostExecute(String result) { //
execution of result of Long time consuming operation } /*
(non-Javadoc) *
@see android.os.AsyncTask#onPreExecute() */ @Override protected
void onPreExecute() { //
Things to be done before execution of long running operation. For example
showing ProgessDialog } /*
(non-Javadoc) *
@see android.os.AsyncTask#onProgressUpdate(Progress[]) */ @Override protected
void onProgressUpdate(Void... values) { //
Things to be done while execution of long running operation is in progress.
For example updating ProgessDialog } } |
1
2
3
|
public
void onClick(View v) { new
LongOperation().execute(""); } |
- doInBackground: Code performing long running operation goes in this method. When onClick method is executed on click of button, it calls execute method which accepts parameters and automatically calls doInBackground method with the parameters passed.
- onPostExecute: This method is called after doInBackground method completes processing. Result from doInBackground is passed to this method.
- onPreExecute: This method is called before doInBackground method is called.
- onProgressUpdate: This method is invoked by calling publishProgress anytime from doInBackground call this method.
Points to remember:
- Instance of Async Task needs to be created in UI thread. As shown in onClick method a new instance of LongOperation is created there. Also execute method with parameters should be called from UI thread.
- Methods onPostExecute, onPreExecute and onProgressUpdate should not be explicitly called.
- Task can be executed only once.
0 coment�rios:
Post a Comment