1

My Android application has to:

  • upload an image to the server

  • make 3 ( quick ) calls to a REST web service using the uploaded image image

  • get output from webservice

  • display output on ui.

I'm confused about whether I should use a Service or AsyncTask.

I think I should use an AsyncTask because the tasks need to be done in the background and the outcome needs to be displayed on the UI once the process is complete. The doInBackground() and postExecute() methods seem perfect for this sort of thing.

However, I've read from the Android Documentation and several StackOverflow answers that using Services is more appropriate. The problem is that I want to display the output on the UI as soon as the task is complete. If the user quits the app, then I want the upload to stop.

I'm confused: Is AsyncTask really the better choice?

W.K.S
  • 9,787
  • 15
  • 75
  • 122
  • does the task of uploading take longer? If that's the case don't use asycntask – Raghunandan Jun 13 '13 at 16:32
  • 1
    I've used AsyncTask for exactly the sort of thing that you describe. I'd be interested to see links to the other advice that you've seen? One thought, though, is that AsyncTask isn't meant to be used for tasks that take too long, i.e. 1 or 2 secs max. Another thoughts is that one thread is used to process all AsyncTasks, so that might be relevant. – Stochastically Jun 13 '13 at 16:33
  • Uploading the image is going to be a bit slow but the REST calls are quite fast. – W.K.S Jun 13 '13 at 16:34
  • I read this discussion here: http://stackoverflow.com/questions/13706059/is-it-better-to-use-asynctask-or-service-to-upload-a-file-in-background?rq=1 and the Android documentation of AsyncTask and IntentServices – W.K.S Jun 13 '13 at 16:36
  • AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.). Quote from doc – Raghunandan Jun 13 '13 at 16:36
  • @Stochastically: Would you recommend AsyncTask then? Did it turn out ok for your app? – W.K.S Jun 13 '13 at 16:37
  • 1
    I was just loading small ish web pages, and it worked fine for that. Another possibility is to create your own thread. – Stochastically Jun 13 '13 at 16:38
  • I'll give it a try using AsyncTask then and see what happens, then – W.K.S Jun 13 '13 at 16:41

2 Answers2

2

You should create an IntentService. Send an intent to the service to start it. Send back an intent with the result using a LocalBroadcastManager (from the support library). The IntentService stops itself when it completes, unlike regular Services.

If the user rotates the device while the AsyncTask is executing the result will be lost since the AsyncTask thread is associated with the activity that was destroyed by the rotation. You can find an example here on StackOverflow of how to circumvent this problem, but it's much more code and more complex than writing an IntentService. Since the IntentService is on its own thread, it doesn't get lost when the activity is destroyed.

public class MyIntentService extends IntentService {

    public static final String SERVICE_NAME ="whatever";

    public MyIntentService() {
        super("MyIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        //Get input from the intent, do your http stuff here, 
        //  create a new intent to send back

        LocalBroadcastManager.getInstance(this).sendBroadcast(intentToSendBack);
    }
}

Check out the IntentService docs: Intent Service is about 1/3 down the page

Use a LocalBroadcastManager in your activity to listen for the returning intents. You just hook it up in the OnResume event handler and unhook it in the OnPause handler. So after your original activity is destroyed on the rotation, the new one will start listening. The magic of LocalBroadcastManager queues up the intent for that small period of time between the destruction of the first activity and the creation of the second.

@Override
protected void onResume() {
    super.onResume();

    IntentFilter filter = new IntentFilter(MyIntentService.SERVICE_NAME);
    LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, filter);
}

@Override
protected void onPause() {
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);
}

private BroadcastReceiver onNotice = new BroadcastReceiver() {

    @Override
    public void onReceive(Context context, Intent intent) {
    //Do your UI stuff here....
    }
}

There is more detail on LocalBroadcastManager in the docs. There are some other good side effects of LocalBroadcastManager. Intents sent this way do not leave the application scope, so other apps can't snoop on data you pass around, and your activity processes the result without being forced into the foreground.

Don't forget to register the service in your AndroidManifest.xml.

Community
  • 1
  • 1
DaveTrux
  • 476
  • 5
  • 11
0

IF you are doing network related stuff in your app you need to use an AsyncTask no matter what you do because you will get a NetowrkOnMainThreadException. you are not allowed to do anything network related on the UI thread. Since a service runs on the UI thread you will still need an AsyncTask in the service.

So if it were me I would not worry about the service if you need to update the UI when its done

tyczj
  • 71,600
  • 54
  • 194
  • 296
  • you have to create some sort of callback with `handlers` and `messages` or bind the service to your activity, Its just going to be easier to use a AsyncTask in your activity though – tyczj Jun 13 '13 at 16:40
  • I agree, AsyncTask seems much easier even though I expect the task will take more than 1-2 seconds. – W.K.S Jun 13 '13 at 16:43
  • does not matter how long it takes, like I said you will get an error if you try to make a network connection on the main thread – tyczj Jun 13 '13 at 16:44
  • This solution tells us to do it differently - http://stackoverflow.com/questions/13706059/is-it-better-to-use-asynctask-or-service-to-upload-a-file-in-background What is the right approach? – user2635088 Aug 19 '15 at 06:50