Service v/s AsyncTask - android

I am confused with respect to design of my app. I need to continuously poll a server to get new data from it. I am confused whether Async Task running at fixed interval or Service running is background is better option. The thread will run only when the app is running

You have already some answers to your question, but I think it worths a summary ...
What you need
When you want to run a peice of code that takes some time to complete you should always run it in a separate thread from the UI thread.
You can achieve that in 2 ways:
Using Thread:
This is the simplest one, if you don't need a lot of communication from the new thread to the UI thread. If you need the communication, you will probably have to use a Handler to do it.
Using AsyncTask:
Also runs in a separate thread and already implements some communications channels with the UI thread. So this one is preferable if you need this communication back to the UI.
What you don't need
Service
This serves mainly to keep some code running even after you exit the main application, and it will run in the UI thread unless you spawn a new thread using the options described above. You said that your thread are suposed to terminate when you exit application, so this is not what you need.
IntentService
This can be activated by an external event (i.e. BroadcastReceiver) that can start a piece of code defined by you, even if your application is not running. Once again, based on your requirements, this is not what you are looking for.
Regards.

an Android Service is not in a background thread.
Therefore you should have a Service running that will start an ASyncTask each time you want to poll.
Note that services, like other application objects, run in the main thread of their hosting process. This means that, if your service is going to do any CPU intensive (such as MP3 playback) or blocking (such as networking) operations, it should spawn its own thread in which to do that work. More information on this can be found in Processes and Threads. The IntentService class is available as a standard implementation of Service that has its own thread where it schedules its work to be done.

Service should not be compared to AsyncTask. I guess you most likely meant IntentService here - and this is slightly different thing than Service, despite the common name.
As for periodical fetching, I'd stick with recurrent alarm (using AlarmManager) and (most likely) use IntentService to do the fetching.
Here you got with AsyncTask fundamentals and some tutorials
And here you got with IntentService fundamentals and tutorials
Note, that IntentService jobs are queued by design, while AsyncTasks can run fully paralel. However be aware of regression related to AsyncTask handling in newer APIs. Not a big deal as workaround is just a few more code lines, however it's worth knowing that.
EDIT
There's misunderstanding floating among many concerning AsyncTask lifecycle being bond to Activity's life cycle. This is WRONG. AsyncTask is independent from an Activity. Finishing Activity does not do anything to any AsyncTasks, unless you are cleaning them up from onDestroy() by your code. Yet, if an activity's process is being killed while it is in the background, then AsyncTask will also be killed as well, as part of the entire process being killed

If you want to "continuously poll", an asyncTask won't do. The task stops when your app gets stopped by Android. A Service by itself won't do either, as Blundell already pointed out. A Service runs in the main thread, and you don't want to do polling in the main thread. There's two ways of doing it: you create a Service that spawns its own thread to do the stuff you want it to do, or you let it schedule polls that are executed in an AsyncTask or in a separate thread. I try not to have polling in my app, but if you have to, creating a special thread in your service that does the polling seems best to me.
Depending on what your app does and what the polling is about, you can give the separate thread a lower priority, so it doesn't get in the way of other processing.

The thread will run only when the app is running
Then AsyncTask will be the simplest solution. Send data periodically to app thread using publishProgress() from background thread. Set desired interval using Thread.sleep() in doInBackground(). Also, make sure you start a new task in onResume() method of Activity, and end this task in onPause() method of Activity.
Example:
public class MyActivity extends Activity {
private AsyncTask<Void,String,Void> mAsyncTask;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
super.onResume();
mAsyncTask = new MyTask();
mAsyncTask.execute();
}
#Override
protected void onPause() {
super.onPause();
if(mAsyncTask != null){
mAsyncTask.cancel(true);
}
}
private void onServerResponse(String response){
Toast.makeText(this, "Got response !", Toast.LENGTH_SHORT).show();
}
private final class MyTask extends AsyncTask<Void,String,Void>{
#Override
protected Void doInBackground(Void... voids) {
while (!isCancelled()){
String response = "";
//server query code here
publishProgress(response);
Log.i("TEST", "Response received");
//sleep for 5 sec, exit if interrupted ,likely due to cancel(true) called
try{
Thread.sleep(5000);
}catch (InterruptedException e){
return null;
}
}
return null;
}
#Override
protected void onProgressUpdate(String... values) {
super.onProgressUpdate(values);
if(values.length > 0){
onServerResponse(values[0]);
}
}
}
}

Related

AsyncTask for longer Processes

I know that AsyncTask are not preferred for long process. Their main objective is to take the load off from UI thread and do stuff in background. Later on completion update the respective UI thread.
I am aware of the memory leaks i.e when UI needs to be updated after doInBackground is done and there's a possibility that the activity is destroyed.
My question is can I use AsyncTask just like a simple Thread?
What happens to AsyncTask if Activity or Application dies, which started it?
Requirments
I dont need to update any UI.
I dont want my task to be associated with Activity(which starts it).
First Question :
Yes you can.Its totally depends on your logic.
Second Question :
The thread will be in the background though the application is killed by the user or by the system.
To resolve the second scenario use the following technique
Just make sure that you are finishing your AsyncTask before application or Activity closes
AsyncTask yourAsyncTask
#Override
public void onDestroy(){
//you may call the cancel() method but if it is not handled in doInBackground() method
if(yourAsyncTask!=null)
if (yourAsyncTask != null && yourAsyncTask.getStatus() != AsyncTask.Status.FINISHED)
yourAsyncTask.cancel(true);
super.onDestroy();
}
If you only need the 'doInBackground' just use a normal thread.
new Thread("threadName", new Runnable(){ #Override run(){ } }).start();
The whole reason to use an AsyncTask is to have the facilities of preExecute and postExecute, so you don't need to mess with handlers.
It remain started in background even the application is killed or crash.
First, a general note, as stated by the Android Docs:
AsyncTasks should ideally be used for short operations (a few seconds at the most). If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent pacakge such as Executor, ThreadPoolExecutor and FutureTask.
To answer your questions:
Yes - you can use Async task as if it were just a background thread - an Async task is merely a wrapper of Thread and Handler that allows the thread to seamlessly communicate with the UI thread. Warning! If you plan to update the UI thread, or otherwise reference an activity or fragment in the callbacks that reference the UI thread (i.e. onProgressUpdated and/or onPostExecute) you should explicitly check that the activity or fragment is still in a state from which it can be referenced and used. For example - here's the right and wrong way to do it when launching an AsyncTask from a fragment:
Create your task with a ref to the activity so you can do something when it's done:
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
Fragment mFragment;
public DownloadFilesTask(Fragment fragment){
mFragment = fragment;
}
WRONG:
protected void onPostExecute(Long result) {
// if the fragment has been detached, this will crash
mFragment.getView().findView...
}
RIGHT:
protected void onPostExecute(Long result) {
if (mFragment !=null && mFragment.isResumed())
... do something on the UI thread ...
}
}
If the Activity dies while an AsyncTask is executed, it will continue to run. Using the techniques listed above, you can avoid crashes by checking the lifecycle of the context that started the task.
Finally, if you have a very long-running operation that does not require the UI thread at all, you should look into using a Service. Here's a blurb:
A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use
My question is can I use AsyncTask just like a simple Thread?
Yes AsyncTask is android background thread , the task will be done in the background .
AsyncTask automatically creates a new Thread for you, so everything you do in doInBackground() is on another thread.
What happens to AsyncTask if Activity or Application dies, which
started it?
The AsyncTask is related to application , if application destroy or finish then all related AsyncTask of that application will be terminated .

What can cause a AsyncTask not to execute?

I have a very sporadic failure in my app I'm trying to resolve. On entry to the app, at one point the main UI thread processing ends and passes control to a background thread to retrieve some data. When the data is retrieved, control passes back to the main UI thread to process it for display. However, on some rare occassions (it works 99% of the time), the AsyncTask seems to be failing to be called leaving the app in a poor static state forever waiting for the AsyncTask to complete.
Here's a snapshot of the code in the Activity:
//method call from main UI thread
private void fetchSomeData() {
Log.d("myTag", "In fecthSomeData()");
new ReadFileAsyncTask<DataModel>().execute(this);
}
Here's the ReadFileAsyncTask implementation:
public class ReadFileAsyncTask<A> extends AsyncTask<I_ReadFileListener<A>, Void, A>
{
I_ReadFileListener<A> listener;
#Override
#SuppressWarnings("unchecked")
protected A doInBackground(I_ReadFileListener<A>... params)
{
listener = params[0];
Log.d("mytag", "BACKGROUND: Loading " + listener.getFilename() + " from disk");
A fileContents = (A) FileUtils.readDataFromInternalStorage(listener.getContext(), listener.getFilename());
return fileContents;
}
#Override
protected void onPostExecute(A result)
{
Log.d("myTag", "FOREGROUND: Executing onFileRetrieved listener");
listener.onFileRetrieved(result);
}
}
Capturing the logs on this rare failure yeilds:
In fetchSomeData()
...
(Other log messages from other interactions with the activity such as menu creation and navigation initialization)
but, crucially, not the log statement from the second line of code in the doInBackground method. One thought I had was that this log statement was failing, but I'm not seeing any force stop messages, error in my logs or ACRA crash reports. The application is still active (I can navigate to other activities and back) so I'm at a loss as to what might stop this background thread from running properly. Any ideas?
Sadly AsyncTask is not suitable for critical code execution since, depending on the ThreadPool base and max size, your AsyncTask may never execute.
Moreover, the onPostExecute method could be called when the Activity it is referring (i.e. its creating context) has already been destroyed. You have no way to synchronize with it rather then maybe using join() on the AsyncThread from the UI Thread.
Even though I've seen doing this also in the Android Camera App it isn't a good idea to block the UI Thread waiting for an event since you coulg get an ANR (Application Not Running) notification.
Take a look at this: Is AsyncTask really conceptually flawed or am I just missing something?
Consider using IntentServices, HandlerThread or ThreadPoolExecutors if you need a possibly better way to synchronize your worker thread with your your UIThread.
From http://developer.android.com/training/run-background-service/create-service.html:
Also, an IntentService isn't affected by most user interface lifecycle events, so it continues to run in circumstances that would shut down an AsyncTask

Async task does not work properly (doInBackground not executing) when service runs in background, Android

I noticed that sometimes Async task does not work properly , Actually its doInBackground() method does not get called , this happens mostly when any service run in background for that activity.
For Example , when music runs in background with service, the Async task does not parse XML in background as its doInBackground does not work that time and the progress Dialog or progressBar kept spinning.
I read in few articles that AsyncTask.THREAD_POOL_EXECUTOR can help in these issues like :
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new Test().execute();
}
but that did not help in my case. Having the same issue after the above implmentation.
Here I am giving just a bit of my sample code to understand what I am doing::
public class TestAct extends Activity {
ImageButton play,forward,backward;
private ListView mList;
// many more variables
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test_layout);
//binding the service here
// start service is called
init();
}
private void init(){
play=(ImageButton)findViewById(R.id.playBtn);
forward=(ImageButton)findViewById(R.id.forward);
backward=(ImageButton)findViewById(R.id.backward);
mList=(ListView)findViewById(R.id.list);
new GetData().execute();
play.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// calling the play() method of ServiceConnection here
}
});
// adding header to Listview
// other code and click listeners
}
class GetData extends AsyncTask<Void, Void, Void>{
#Override
protected void onPreExecute() {
super.onPreExecute();
// starting the progress Bar
// initializing the Arraylist,Maps etc
}
#Override
protected Void doInBackground(Void... params) {
//parsing the XML here
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
// stop the ProgressBar
// Updating my UI here
// setting Adapter for ListView
}
}
}
This works fine generally but hangs when Service runs in backgound (I mean when music is playing in back).
I am not getting the exact reason behind this problem of Async task.
Will mannual thread implementation help in this case ...??
Well, I think the problem is because "Service runs in main thread so when it runs, it blocks my AsyncTask to run"... So I think If we can run Service in background thread then that can help . Thats why I tried IntentService for running service in separate thread but I am in doubt... if IntentService can run for indefinite time similar to Service ... and Also IntentService blocks AsyncTask few times.
So I dont't think its 100% perfect solutions for this kind of problem.
Can anyone help me to sort out this problem and understand the complete scenario.
Thanks in advance.
Sometimes you will want more control over your service's lifecycle than what IntentService gives you, in those cases you can just create a thread in the service and run your background code in that. Actually, to be more specific, create a HandlerThread which includes a Looper so you can use the standard android method for communication (messages) between your main thread and the background thread.
Answered here
I think the problem is starting another GetData AsyncTask before the previous one has been finished. Before executing another task make sure that previous one is complete. To do this use following code:
// make sure we don't collide with another pending AsyncTask
if (getDataTask == null || getDataTask.getStatus() == AsyncTask.Status.FINISHED || getDataTask.isCancelled()) {
getDataTask= new GetData();
getDataTask.execute();
}
Also make sure that you have a reference for running tasks. You can use subclass of Application class for doing this while your application is running or override onSaveInstanceState(Bundle outState)
and receive a reference to it in onCreate(Bundle savedInstanceState).
Read all the problem and Answers which has been posted here. correct me if i am wrong your scenario is you are parsing the xml and getting the list of songs and when user select any song you want that to be played with service right?
if the Scenario is correct then we can implement it in the much simpler way.
In the Activity, onResume() method parse the XML file and get the list of songs and update the list view(do not start anything related to service here)
when user click on the song then pass the particular key/string to the service with intent and start the service
In the service's OnStartCommand() method get the identifier and start the song as with normal media APIs
That will actually do the work for you.
Regarding the problem of
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
new Test().execute();
}
This is for different behavior of the AsyncTask on Different version of the Android.
Looking at your code what is being done is in the Activity you are initializing the service hence the service is running in the background without doing anything fruitful.
and when user click on play you are calling play function of service which created problme here.
so to call the function of service from Activity you should right AIDL which you have not mentioned. and if you have wrote so it should be perfect.
but here recommendation is pass the song id to service and it should play from service should not call Service's function in activity.
if you want to update the Song List in the onResume of the activity then you must write AIDL and accomplish the scenario
Hope this will help.
I noticed that sometimes Async task does not work properly , Actually
its doInBackground() method does not get called , this happens mostly
You know that there is a limit of AsyncTasks that can be executed at a time? I had once an issue where a task did't start/work properly and this was because I exceeded that number. Check Android AsyncTask threads limits? for more on that topic.
when any service run in background for that activity. For Example ,
when music runs in background with service, the Async task does not
parse XML in background as its doInBackground does not work that time
and the progress Dialog or progressBar kept spinning.
Have you checked the possibilities of dead locks (in particular, if you're using wait() and notify())?
Well, I think the problem is because "Service runs in main thread so
when it runs, it blocks my AsyncTask to run"... So I think If we can
run Service in background thread then that can help . Thats why I
The things you are going to do in a service should run in an own thread anyway. That way you can be sure that nothing is going to be blocked. If you have something to populate you could use a receiver, for instance.
Hope I could help a bit ...
Here is a hint, How I finally solved my Problem ::
1) I used IntentService instead of Service as Service runs in mainThread while IntentService runs in a separate Thread than mainThread to make sure that my background Service does not effect my current task . Also , I am using AIDL for communication between my UI and background Thread (this was already working for Service , so nothing new in this part).
2) I used painless thread instead of AsyncTask, I interrupt the thread in onDestroy() method to make sure that the Thread does continue indefinitely.
App seems to perform much better than Earlier now.
Hope this will help others too :)
Per the Threading Rules section of the Android Developer AsyncTask document, the AsyncTask has to be created and launched on the UI thread, so if you are launching it from a background thread in a Service, that would account for the faulty behavior.
http://developer.android.com/reference/android/os/AsyncTask.html
You really shouldn't be using AsyncTasks in general :) There is a pretty good explanation here . Think about what will happen if the user rotates the device, while your task is running. The Activity is recreated, but the task runs in the background and holds a reference to the "old" activity. There are ways to get around this, and they are surely still some cases where an AsyncTasks is the correct approach.
However, your really should consider switching to a Loader or (if you feel adventurous) try RoboSpice :)

Implementing a cyclic executive in android?

I am writing an android app and I need to be able to do certain things periodically/continuously. I am coming from a C/C++ embedded firmware background and this new-fangled way of doing things is going to take some getting used to. It seems that there is no such thing as a "main loop" in Android, that everything is event-driven... I also understand that by default all code you write operates on the GUI thread, and I should probably make a new thread to execute the equivalent of a "main loop"...
So far what I have is an implementation of the AsyncTask class who's "doInBackground" method contains an infinite loop (my main loop), I create an instance of this class and run it immediately when my app starts. The problem I am having is in the interaction between this thread and the user interface... when something occurs in my main loop thread and I want to update the GUI understand that I must call "publishProgress", which is executed on the GUI thread. There are a few problems with this, primarily that many things I have tried to do in this "onProgressUpdate" method do not work, or do not occur in a predictable amount of time.
My question, is there a better way to accomplish what I am trying to do? In general, what do most people do when they have code that they want to run periodically and/or continuously while their application is running, code that must interact with the user interface in a timely manner (by timely I mean with zero delay).
Thank you.
public class MainLoopThread extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... arg0)
{
while(true)
{
//Do stuff
//Update GUI
publishProgress();
}
}
protected void onProgressUpdate(Void...voids)
{
//Update GUI
}
}
It is unclear what you are trying to do, however just let me say using AsyncTask in this way may have negative consequences.
AsyncTask internally uses a thread pool pattern for running the stuff from doInBackground(). On Android OS before 1.6 and starting from 3.0 the pool size is just 1, meaning no parallel computations for a bunch of AsyncTasks. More details on this here.
So, this may result that only this current AsyncTask is running, while others even if started will have to wait untill the current one is done.
Depending on your needs for things to be done periodically Android exposes:
AlarmManager
Handler - it allows to post a runnable on UI thread with a delay or periodically
Timer + Activity.runOnUiThread(Runnable action) inside of TimerTask
UPDATE: basing on your comments it looks like you need a Service, that starts a thread that periodically sends broadcasts with the data for UI. Then your UI (Activity) registers broadcast receivers to catch those broadcasts, extract the data and use for UI updates.
So your saying that onProgessUpdate() isn't working? That seems weird because it should.
Another option that you have is just to make a Thread that loops.
The trick is that if you want to update the UI thread you will have to make a call to view.post() and give it a runnable that will actually perform the update. The idea here is that you must schedule an update on the UI thread, you can't just take it and say NOW!

Help me learn how to use Services and Threads correctly

I'm asking for help so my life, and more importantly my user's lives will not be ruined by me not knowing how to use Services and Threads correctly.
I'm not asking for a long explanation, but more of a confirmation. It's fine if I'm dead wrong. I'm here to learn.
If I understand correctly:
1. a service runs in the background (no UI).
2. a service theoretically will run forever until it kills itself (I'm taking a big guess here)
3. a service will continue to run even when the main Activity is not visible (how about even destroyed?)
So here's my coding question.
I've got my service setup and a thread. Everything works great, but it only works once. I need it to loop and keep checking back. Once it's done run() how do I go about telling it to run() again?
public class NotifyService extends Service{
private long mDoTask;
NoteThread notethread;
#Override
public IBinder onBind(Intent arg0) {
return null;
}
#Override
public void onCreate() {
mDoTask = System.currentTimeMillis();
notethread = new NoteThread();
notethread.start();
}
public class NoteThread extends Thread {
NotificationManager nManager;
Notification myNote;
#Override
public synchronized void start() {
super.start();
//init some stuff
}
#Override
public void run() {
//If it's been x time since the last task, do it again
//For testing set to every 15 seconds...
if(mDoTask + 15000 < System.currentTimeMillis()){
//Take care of business
mDoTask = System.currentTimeMillis();
}
}
}
}
From the Android docs:
A Service is an application component
representing either an application's
desire to perform a longer-running
operation while not interacting with
the user or to supply functionality
for other applications to use. Each
service class must have a
corresponding declaration in
its package's AndroidManifest.xml.
Services can be started with
Context.startService() and
Context.bindService().
Note that services, like other
application objects, run in the main
thread of their hosting process. This
means that, if your service is going
to do any CPU intensive (such as MP3
playback) or blocking (such as
networking) operations, it should
spawn its own thread in which to do
that work. More information on this
can be found in Processes and Threads.
The IntentService class is available
as a standard implementation of
Service that has its own thread where
it schedules its work to be done.
You can find a detailed discussion
about how to create services in the
Services document.
In other words, a service does NOT run in the background unless you put it in a thread. If you put a service that never ends in your application without manually threading the service, then it WILL block.
Android provides an API to do background tasks for you without having to poke around with Java threads; it's called AsyncTask and it's one of the few GOOD design decisions that the Android team has ever made.
EDIT I forgot to address your question about multithreading. You don't want to make a thread execute its run() method more than once. Either instantiate a new thread or put a while loop around the contents of the run logic that you would like to have repeated.
To understand threads better, read "Java Concurrency In Practice" by Brian Goetz.
To understand services better, I think you should write them to be single threaded and let the Java EE container you deploy them to handle threading issues. A pooled servlet is a better solution than having your code shoulder the burden of managing threads for users.

Categories

Resources