Search This Blog

Support my cause by downloading

Thursday, 8 November 2012

Progressive download : Showing progress of download in android

So many times we download data and upload data to server. But for interactive user designed, process of downloading and uploading should show update about how data is downloaded or uploaded. Putting just one dialog box with "loading.." message is not a right way.

Uploading or downloading with progress  are very easy but both are different process. So this article will only include the process of showing progress (how much downloaded/how much remaining) for downloading purpose. It base on genernal math formula

  •  Total length of data to be downloaded let say length
  •  Data downloaded with one attempt . add the from previous attempt say totalread
  •  How much percentage downloaded ?

    private float getPercentage(long totalLenght, long read) {
        return ((read * 100)/ totalLenght) ;
    }

But main concern is how to get total length of a file on server ? Java provide a way to get content length of server file (to being downloading)


                HttpClient httpclient = new DefaultHttpClient();

                HttpPost httppost = new HttpPost(url);

                HttpResponse response = httpclient.execute(httppost);

                HttpEntity entity = response.getEntity();

                long length = entity.getContentLength();  

So the main headache is solved. Now just read the amount the InputStream read at a time and added into old value to keep track total downloaded data. This application downloaded data from URL and save it as file. For this, it need one OutputStream. Read data from InputStream and write to file using OutputStream.

Application need access of memory to save image and Internet So these permission are necessary in andorid manifest

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"  />

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <uses-permission android:name="android.permission.INTERNET" />

Before starting a Thread we just check Internet connection availability and then go further

    private boolean CheckConnection() {

        ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo networkInfo = connMgr

                .getNetworkInfo(ConnectivityManager.TYPE_WIFI);

        boolean isConnected = networkInfo.isConnected();

        if (isConnected)

            return isConnected;

        networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);

        isConnected = networkInfo.isConnected();

        return isConnected;

    }

 Application has simple UI with one TextView to showing update of progress so layout will be very simple

   <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:id="@+id/progress"
        android:padding="@dimen/padding_medium"
        android:text="@string/hello_world"
        tools:context=".ProgressiveDownload" />

    </RelativeLayout>

If i combine my all effort then it looks some bigger  piece of code so let's have complete class 


public class ProgressiveDownload extends Activity {
 private TextView txtView;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_progressive_download);
  txtView = (TextView) findViewById(R.id.progress);
  txtView.setText("0 % downloaded");
  if (CheckConnection()) {
   String url="http://www.carbodybids.co.uk/public/upload/cardamageimg/464/4_1343297960_theatre1.jpg";
   File file = new File("/mnt/sdcard/sample_image_15.jpg");
   DownLoadAndShowProgress dps = new DownLoadAndShowProgress(url, file);
   Thread th = new Thread(dps);
   th.start();
  }
 }

 private float progress = 0;

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.activity_progressive_download, menu);
  return true;
 }

 private boolean CheckConnection() {
  ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
  NetworkInfo networkInfo = connMgr
    .getNetworkInfo(ConnectivityManager.TYPE_WIFI);
  boolean isConnected = networkInfo.isConnected();
  if (isConnected)
   return isConnected;
  networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
  isConnected = networkInfo.isConnected();
  return isConnected;
 }

 public class DownLoadAndShowProgress implements Runnable {

  private String url = "";
  private File file;

  public DownLoadAndShowProgress(String url, File file) {
   this.url = url;
   this.file = file;
  }

  @Override
  public void run() {
   FileOutputStream fos = null;
   InputStream is = null;
   try {
    HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost(url);
    HttpResponse response = httpclient.execute(httppost);
    HttpEntity entity = response.getEntity();
    long length = entity.getContentLength();
    fos = new FileOutputStream(file);
    is = entity.getContent();
    long totalread = 0;
    byte[] bytes = new byte[1024];
    for (;;) {
     int count = is.read(bytes, 0, 1024);
     if (count == -1)
      break;
     fos.write(bytes, 0, count);
     txtView.post(new Runnable() {
      @Override
      public void run() {
       txtView.setText(progress + " % downloaded");
      }
     });
     totalread += count;
     progress = getPercentage(length, totalread);
    }
   } catch (MalformedURLException e) {
    e.printStackTrace();
   } catch (IOException e) {
    e.printStackTrace();
   } finally {
    try {
     if (is != null)
      is.close();
     if (fos != null)
      fos.close();
    } catch (IOException e) {
     e.printStackTrace();
    }

   }
  }
 }

 private float getPercentage(long totalLenght, long read) {
  return ((read * 100)/ totalLenght) ;
 }
}
Android News and source code