Search This Blog

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) ;
 }
}

Saturday, 3 November 2012

Garbage Collection, Heap in android and Java

Garbage collection (GC) is the process that aims to free up occupied memory that is no longer referenced by any reachable Java object, and is an essential part of the Java virtual machine's (JVM's) dynamic memory management system. In a typical garbage collection cycle all objects that are still referenced, and thus reachable, are kept.
 Object no longer have any reference are elligble for garbage collection.

Before going further we need to discuss some important term in Garbage  Collection in android as well java. it works similar

    
  Heap Size or Java Heap or Heap : Every device allocate a specific amount of memory to run a process. It does not allocate all memory to one  process to ensure multitasking. e.g Let an android example, a device with 2 GB memory have heap size of 48 MB(this is my assumption, Heap size depends on device density and other factor). So this device will allow 26  process to run at a time and rest memory used in running OS files. when a process load in memory. It start allocating memory to object. So heap size start increasing. Eventually, the Java heap will be full, which means that an allocating thread is unable to find a large-enough consecutive section of free memory for the object it wants to allocate.At that point, the JVM determines that a garbage collection needs to  happen and it notifies the garbage collector. A garbage collection can also be triggered when a Java program calls System.gc(). Using  System.gc() does not guarantee a garbage collection. Before any garbage collection can start, a GC mechanism will first determine whether it is  safe to start it
  
A garbage collector should never reclaim an actively referenced object; to do so would break the Java virtual machine specification. A garbage collector is also not required to immediately collect dead objects. Dead objects are eventually collected during subsequent garbage collection cycles. While there are many ways to implement garbage collection, these two assumptions are true for all varieties. The real challenge of garbage collection is to identify everything that is live (still referenced) and reclaim any unreferenced memory, but do so without impacting running applications any more than necessary

Two kinds of garbage collection are present to determine which object will garbage collect--

  • Reference counting collectors
  • Tracing collector algorithms
Android News and source code