Search This Blog

Saturday, 17 November 2012

Android Webview example with progress dialog

In android, Webview is subclass of a view, and used for purpose to open a link inside our own custom application. As Webview is sub class of view, so we can used it where ever we want either using xml file or creating dynamically.

If i create this dynamically,

WebView webView = new WebView(this);
webView.setClickable(true);
webView.setFocusableInTouchMode(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.loadUrl("http://www.google.com");
setContentView(webView);

Now this will load a URL http://www.google.com if you have Internet connection and registered Internet permission inside android-manifest. But our main issue remain to make Webview more responsive. Until Webview load url , we will show a progress dialog when page start loadeding, And dismissed the progress dialog after page loaded. WebViewClient class provide a method to detect when page load start and when it finished.

So Lets make one Inner class

 
 public class WebClientClass extends WebViewClient {
  ProgressDialog pd = null;

  @Override
  public void onPageStarted(WebView view, String url, Bitmap favicon) {
   super.onPageStarted(view, url, favicon);
   pd = new ProgressDialog(WebViewDemo.this);
   pd.setTitle("Please wait");
   pd.setMessage("Page is loading..");
   pd.show();
  }

  @Override
  public void onPageFinished(WebView view, String url) {
   super.onPageFinished(view, url);
   pd.dismiss();
  }
 }

This Inner class can be attach to Webview to maintain progress dialog box life cycle WebClientClass webViewClient = new WebClientClass(); webView.setWebViewClient(webViewClient); One another important class is WebChromeClient, that handle JsAlert, Security Error and many other function. Add that also as same as above procedure

Combining all effort will look like this 



package com.example.webviewtag;

import android.app.Activity;
import android.app.ProgressDialog;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class WebViewDemo extends Activity {
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  WebView webView = new WebView(this);
  webView.setClickable(true);
  webView.setFocusableInTouchMode(true);
  webView.getSettings().setJavaScriptEnabled(true);
  webView.loadUrl("http://www.google.com");
  WebClientClass webViewClient = new WebClientClass();
  webView.setWebViewClient(webViewClient);
  WebChromeClient webChromeClient=new WebChromeClient();
  webView.setWebChromeClient(webChromeClient);
  setContentView(webView);
 }

 public class WebClientClass extends WebViewClient {
  ProgressDialog pd = null;

  @Override
  public void onPageStarted(WebView view, String url, Bitmap favicon) {
   super.onPageStarted(view, url, favicon);
   pd = new ProgressDialog(WebViewDemo.this);
   pd.setTitle("Please wait");
   pd.setMessage("Page is loading..");
   pd.show();
  }

  @Override
  public void onPageFinished(WebView view, String url) {
   super.onPageFinished(view, url);
   pd.dismiss();
  }
 }
 
 public class WebChromeClass extends WebChromeClient{
 }
}


Check Out Screen Shot Of application 

Webview
Loading..
Loaded
    

Thursday, 15 November 2012

Cross Platform development : Showing pop up by communication between Android and Java Script

Previous section discuss how to show progress dialog while Webview loading url. Further discussion will lead you to depth knowledge about Webview and its usefulness. This article will cover

  • How to load a custom HTML inside a Webview ?
  • How to add Java Script interface to android Webview ?
  • How to display Native Alert Dialog from Java Script code ?

Create one custom HTML file and keep into assets folder. Now just load it into Webview

        /**
         * Load Our Custom
JS Inside Webview
         */
        webView.loadUrl("file:///android_asset/myhtml.html");


we can add JS interface to android webview and can pop up our native dialog box. Webview provide a way to add JS interface. So just we have to make one class and add object of class to Webview like

        /**
         * Now Added Java Interface Class
         */
        webView.addJavascriptInterface(new myJsInterface(this), "Android");


Now create a class myJsInterface

 public class myJsInterface {
  
  private Context con;

  public myJsInterface(Context con) {
   this.con = con;
  }

  public void showToast(String mssg) {
   AlertDialog alert = new AlertDialog.Builder(con)
     .create();
   alert.setTitle("My Js Alert");
   alert.setMessage(mssg);
   alert.setButton("OK", new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {
     dialog.dismiss();
    }
   });

  }
 }

In webView.addJavascriptInterface(new myJsInterface(this), "Android"), Android ensure that which method need to be called when you perform action inside a Html (its Java Script)

HTML and JS file , Keep this file inside assets folder


<html>
 <head>
  My custom js Interface
 </head>
 <body>
  <input type="button" value="Show Dialog" onClick="showAndroidToast('This is Js Alert.')" />
  <script type="text/javascript">
   function showAndroidToast(toast) {
    Android.showToast(toast);
   }
  </script>
 <body>
</html>

See the Java script function, it have the Tag we pass from android activity. So it will redirect to myJsInterface's method showToast(mssg) , and alert dialog is populated
 
       function showAndroidToast(toast) {
                                              Android.showToast(toast); 
                                                                 }

Lets combine all except HTML


package com.example.webviewtag;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class WebViewDemo extends Activity {
 WebSettings wSettings;

 @SuppressLint("SetJavaScriptEnabled")
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  WebView webView = new WebView(this);
  webView.setClickable(true);
  wSettings = webView.getSettings();
  wSettings.setJavaScriptEnabled(true);

  /**
   * <b> Support Classes For WebView </b>
   */
  WebClientClass webViewClient = new WebClientClass();
  webView.setWebViewClient(webViewClient);
  WebChromeClient webChromeClient = new WebChromeClient();
  webView.setWebChromeClient(webChromeClient);

  /**
   * Now Added Java Interface Class
   */
  webView.addJavascriptInterface(new myJsInterface(this), "Android");

  /**
   * Load Our Custom JS Inside WebView
   */
  webView.loadUrl("file:///android_asset/myhtml.html");
  setContentView(webView);

 }

 public class WebClientClass extends WebViewClient {
  ProgressDialog pd = null;

  @Override
  public void onPageStarted(WebView view, String url, Bitmap favicon) {
   super.onPageStarted(view, url, favicon);
   pd = new ProgressDialog(WebViewDemo.this);
   pd.setTitle("Please wait");
   pd.setMessage("Page is loading..");
   pd.show();
  }

  @Override
  public void onPageFinished(WebView view, String url) {
   super.onPageFinished(view, url);
   pd.dismiss();
  }
 }

 public class WebChromeClass extends WebChromeClient {
 }

 public class myJsInterface {


  
  private Context con;

  public myJsInterface(Context con) {
   this.con = con;
  }

  public void showToast(String mssg) {
   AlertDialog alert = new AlertDialog.Builder(con)
     .create();
   alert.setTitle("My Js Alert");
   alert.setMessage(mssg);
   alert.setButton("OK", new DialogInterface.OnClickListener() {

    @Override
    public void onClick(DialogInterface dialog, int which) {
     dialog.dismiss();
    }
   });

  }
 }
}

Have a look on Screen Shot of application



Why non static variable are not allow to use in static method in Java?

Most common thing about static variable we know, static means no need to create a instance. static variable can used with out instantiating class. Another fact about static variable is, we can not use non static variable inside a static method. if we forcefully go against it and use non static variable inside a static method then we get compile time error

      "Cannot make a static reference to the non-static field rectArea"   

Why it so ? why Java keeps such restriction? 

Compile this code -   


public class A {

 private static float rectArea;

 public static void main(String[] args) {
  A one = new A();
  one.setArea(200);
  A two = new A();
  two.setArea(300);
  A three = new A();
  three.setArea(400);
  System.out.print("Print Area = " + rectArea);
 }

 public void setArea(float areap) {
  rectArea = areap;
 }
}

This indicate a compile time error. So for a moment just ignore the error and let analyze our main issue. A class has instantiated three times. Variable rectArea has value corresponding to each instance.

  Lets go to System.out.print("Print Area = " + rectArea). 

We know we can access static variable without creating object, means static variable value does not depends on object of a class. Same things applied to methods.   So when we are trying to access rectArea which value depends on object of class A (as rectArea is not a static variable), it gives error. Because compiler get confused which value to use 200,300,or 400 for rectArea.  To avoiding this issue Java restrict that we can not use non static variable inside a static method. Same applies when you try to use non static method inside a static method 

Thursday, 8 November 2012

why two way exist to implement thread in java ?

Java has great concept called Thread. Thread is most discussed and assume to be most difficult  concept by people. while creating a simple thread, Java provide two ways

1) Extends Thread class 

public class Method1 extends Thread {

 public static void main(String[] args) {
  Method1 tm = new Method1();
  Thread th = new Thread(tm);
  th.start();
 }

 @Override
 public void run() {
  super.run();
  System.out.println("Extends Thread to create a Thread :)");
 }
}

2) Implement Runnable interface

public class Method2 implements Runnable {

 public static void main(String[] args) {
  Method2 tm = new Method2();
  Thread th = new Thread(tm);
  th.start();
 }

 @Override
 public void run() {
  System.out.print("Implement Runnable interface to create a Thread");
 }
}

So doubt goes increasing for a new programmer. Two ways to doing same thing ? why these necessity exists Let them clarify

Noted : Java provide inheritance . So we can use on class property inside another class by extending class. Consider class MN has method addSum(), iNeedMn want to use this addSum() then simple iNeedMn extends MN is solution. This is called single inheritance

    public class MN{
       
        public void addSum(){
            System.out.print("From MN");
        }
    }
   
    public class iNeedMn extends MN{
        @Override
        public void addSum() {
            super.addSum();
        }
    }

Consider now iNeedMn want to access the property of Thread class also (So called multiple Inheritance(is not allowed in JAVA) i.e one class can extends any number of class) or say iNeedMn need to be use as Thread somewhere. Impossible ???

Cause of providing two to make a thread is to avoid impact of banned multiple inheritance.We can not extends two classes but we can implement any number of interface

Which way to prefer ?

Implementing Runnable is preferred way.It's generally discouraged to extend the Thread class. The Thread class has a lot of overhead and the Runnable interface doesn't   

Difference between interface and abstract class in Java ?

Difference between interface and abstract class is most asked question in interview. Even i have face this question five times among 11 interviews.  Defination of abstract class and interface is completely different and easily undestandable but the main issue is to learn where to use abstract,interface.This post will contain a a example to clarify this issue

Main Difference between interface and abstract class


1) Interface allow only declaration of method, where as you can assign a body of a method inside a abstract class

 
public interface TestInterface {

 public String sumOfTwoNumber(int a,int b){    /// Abstract methods do not specify a body. So its not allowed
  int c = a + b;
  System.out.print(c);
  return String.valueOf(c);
 }
 
 public void abs(int a,int b);                 // Allowed
}

 
public abstract class TestAbstract {
 
       public String sumOfTwoNumber(int a, int b) {   // Allowed
  int c = a + b;
  System.out.print(c);
  return String.valueOf(c);
 }
 
 public abstract void sumb();                 // Allowed
}

2) By default every method of interface is abstract. but this is not true for abstract class. we can say that interface is implicitly abstract

3) Interface is fully abstract so we can not instantiate an interface. Making object of abstract class is not possible but it can revoke if its contain main
 like this

public abstract class StaticInner {

 public static void main(String[] args) {
  System.out.print("Invoked");
 }
} 
 

Now comes to general difference

 

1) a class use interface by keyword implements and abstract class with keyword extends

2) one interface can not extends a class but can extends any number of interface

 public interface A {
  public void add();
 }

 public interface B {
  public void minus();
 }

 public interface C extends A, B {
  public void Div();
 }

an abstract class can extends only one class but can implement any number of interface

 public class ABC{
  
 }
 public abstract class CanExtendsOnlyABC extends ABC implements A,B,C{
  
 } 
 
Final Note : Java interface works slow in comparision of abstract class

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