Monday 30 March 2015

How to use Async Task in a Service in android ?

Performing Tasks in a Service Asynchronously


1 . Using the same project created in the previous post, add the following statements in bold to the MyService.java file:
 

package ​com.emergingandroidtech.Services;
import ​android.app.Service;
import​ android.content.Intent;
import​ android.os.IBinder;
import ​android.util.Log;
import​ android.widget.Toast;
import​ java.net.MalformedURLException;
import​ java.net.URL;
import android.os.AsyncTask;

public​ class ​MyService ​extends​ Service​
{
​​​​@Override
​​​​public​ IBinder ​onBind(Intent​ arg0)​
{
​​​​​​​​return ​null;
​​​​}
​​​​
@Override ​
​​​public​ int ​onStartCommand(Intent ​intent,​int​ flags,​int ​startId)​
{
​​​​​​​​
//​We​ want ​this ​service ​to ​continue ​running ​until​ it ​is ​explicitly
​​​​​​​​//​stopped,​so​ return ​sticky. ​​​​​​​​
Toast.makeText(this,​“Service​Started”,​Toast.LENGTH_LONG).show();
​​​​​​​​try
{
​​​​​​​​​​​​new DoBackgroundTask().execute(
​​​​​​​​​​​​​​​​​​​​new URL(“http://www.amazon.com/somefiles.pdf”),
​​​​​​​​​​​​​​​new URL(“http://www.google.com/somefiles.pdf”),
​​​​​​​​​​​​​​​​​​​​new URL(“http://emergingandroidtech.blogspot.in”)); ​​​​​​​​
}
catch (MalformedURLException e)
{
​​​​​​​​​​​​e.printStackTrace();
​​​​​​​​}
​​​​​​​​return ​START_STICKY; ​
​​​}
​​​​
@Override
​​​​public ​void ​onDestroy()
​{
​​​​​​​​super.onDestroy();
​​​​​​​​Toast.makeText(this,​“Service​Destroyed”,​Toast.LENGTH_LONG).show(); ​​​
​} ​​​​

​​​​private ​int ​DownloadFile(URL​ url)
​{
​try​
{
​​​​​​​​​​​​//---simulate​ taking ​some​time ​to ​download ​a​ file--- ​​​​​​​​​​​​
Thread.sleep(5000);
​​​​​​​​}
​catch​(InterruptedException ​e)​
{
​​​​​​​​​​​​e.printStackTrace(); ​
​​​​​​​}
​​​​​​​​//---return ​an ​arbitrary ​number​ representing ​
​​​​​​//​the ​size​ of ​the ​file ​downloaded--- ​
​​​​​​​return​ 100; ​
​​​}
​​​​
private class DoBackgroundTask extends AsyncTask<URL, Integer, Long>
{
​​​​​​​​protected Long doInBackground(URL... urls)
{
 ​​​​​​​​​​​​int count = urls.length;
​​​​​​​​​​​​long totalBytesDownloaded = 0;
​​​​​​​​​​​​for (int i = 0; i < count; i++)
{
​​​​​​​​​​​​​​​​totalBytesDownloaded += DownloadFile(urls[i]);

​​​​​​​​​​​​​​​​//---calculate percentage downloaded and
​​​​​​​​​​​​​​​​// report its progress--- ​
​​​​​​​​​​​​​​​publishProgress((int) (((i+1) / (float) count) * 100)); ​
​​​​​​​​​​​}
​​​​​​​​​​​​return totalBytesDownloaded; ​​
​​​​​​}
​​​​​​​​
protected void onProgressUpdate(Integer... progress)
{
​​​​​​​​​​​​Log.d(“Downloading files”, ​​​​​​​​​​​​​​​​​​​​String.valueOf(progress[0]) + “% downloaded”); ​​​​​​​​​​​​

Toast.makeText(getBaseContext(), ​​​​​​​​​​​​​​​​String.valueOf(progress[0]) + “% downloaded”, ​​​​​​​​​​​​​​​​Toast.LENGTH_LONG).show(); ​​​​​​​​
}
​​​​​​​​
protected void onPostExecute(Long result)
{
​​​​​​​​​​​​Toast.makeText(getBaseContext(), ​​​​​​​​​​​​​​​​​​​​“Downloaded “ + result + “ bytes”, ​​​​​​​​​​​​​​​​​​​​Toast.LENGTH_LONG).show(); ​​
​​​​​​​​​​stopSelf();
​​​​​​​​} ​
​​​}
}

2. Click the Start Service button. 
The Toast class will display a message indicating what percentage of the download is completed. 
You should see four of them: 25%, 50%, 75%, and 100%.  

3 . You will also observe the following output in the LogCat window: 

01-16​02:56:29.051:​DEBUG/Downloading​files(8844):​25%​downloaded
01-16​02:56:34.071:​DEBUG/Downloading​files(8844):​50%​downloaded
01-16​02:56:39.106:​DEBUG/Downloading​files(8844):​75%​downloaded
01-16​02:56:44.173:​DEBUG/Downloading​files(8844):​100%​downloaded

How It Works

This example illustrates one way in which you can execute a task asynchronously within your service. You do so by creating an inner class that extends the AsyncTask class. The AsyncTask class enables you to perform background execution without needing to manually handle threads and handlers. The DoBackgroundTask class extends the AsyncTask class by specifying three generic types:

​​​​private ​class ​DoBackgroundTask ​extends ​AsyncTask<URL,​Integer,​Long>​{

In this case, the three types specified are URL, Integer and Long. These three types specify the data type used by the following three methods that you implement in an AsyncTask class:

doInBackground()— This method takes an array of the first generic type specified earlier. In this case, the type is URL. This method is executed in the background thread and is where you put your long-running code. To report the progress of your task, you call the publishProgress() method, which invokes the next method, onProgressUpdate(), which you implement in an AsyncTask class. The return type of this method takes the third generic type specified earlier, which is Long in this case.

onProgressUpdate()— This method is invoked in the UI thread and is called when you call the publishProgress() method. It takes an array of the second generic type specified earlier. In this case, the type is Integer. Use this method to report the progress of the background task to the user.

onPostExecute()— This method is invoked in the UI thread and is called when the doInBackground() method has finished execution. This method takes an argument of the third generic type specified earlier, which in this case is a Long.

To download multiple files in the background, you created an instance of the DoBackgroundTask class and then called its execute() method by passing in an array of URLs:

​​​​​​​​try
​{
​​​​​​​​​​​​new​DoBackgroundTask().execute(
​​​​​​​​​​​​​​​​​​​​new​URL(“http://www.amazon.com/somefiles.pdf”),​
​​​​​​​​​​​​​​new​URL(“http://www.google.com/somefiles.pdf”),
​​​​​​​​​​​​​​​​​​​​new​URL(“http://emergingandroidtech.blogspot.in”)); ​​​​​​​​
}
​catch​(MalformedURLException ​e)
​{
​​​​​​​​​​​​//​TODO​ Auto-generated ​catch ​block ​​
​​​​​​​​​​e.printStackTrace(); ​
​​​​​​​}

The preceding causes the service to download the files in the background, and reports the progress as a percentage of files downloaded. More important, the activity remains responsive while the files are downloaded in the background, on a separate thread.
Note that when the background thread has finished execution, you need to manually call the stopSelf() method to stop the service:

​​​​​​​​protected ​void ​onPostExecute(Long​ result)
​{
​​​​​​​​​​​​Toast.makeText(getBaseContext(), ​​​​​​​​​​​​​​​​​​​​“Downloaded​“​+​result​+​“​bytes”,​ ​​​​​​​​​​​​​​​​​​​​Toast.LENGTH_LONG).show(); ​​​​​​​​​​​​stopSelf(); ​​​​​​​​
}

The stopSelf() method is the equivalent of calling the stopService() method to stop the service.

No comments:

Post a Comment