Saturday, May 21, 2011

WebView - Part 3 How to customize WebView?


WebViews can be customized in Variety of ways, where you can add your own behaviour; this can be done in following ways:

1.      Overriding “android.webkit.WebChromeClient” class we can override the UI behaviour, because this class or subclass of this class is called when something that may effect the UI happens, e.g. progress update and Javascript Alerts
2.      Overriding “android.webkit.WebViewClient” class we can override page loading behaviour; because this class or its subclass is called whenever something that can impact page rendering happens e.g. errors or form submissions. You can also intercept URLs here.
3.      You can also modify the “android.webkit.WebSettings” class e.g. you can enable JavaScript with setJavaScriptEnabled() method.
4.      You can also add JavaScript to Java interfaces with the addJavaScriptInterface(Object, String) method. This method lets you bind Java Object into the WebView so that they can be controlled by web pages JavaScript

Here we’ll discuss all of them one by one.

Handling UI State with WebChromeClient Class:

Here in this sample we are overriding the Progress of page loading for this we’ll override WebChromeClient.onProgressChanged method this sample will also explain the way of getting the Settings for your WebView and setting some of the settings e.g. enabling JavaScript.

So, here’s the Sample code that you can use in your activity:

browser = (WebView)findViewById(R.id.webbrowser);
           
getWindow().requestFeature(Window.FEATURE_PROGRESS);
browser.getSettings().setJavaScriptEnabled(true);
           
browser.setWebChromeClient(new WebChromeClient(){
      public void onProgressChanged(WebView View, int progress){
                        WebBrowser.this.setProgress(progress * 1000);
                  }
});

So, here in first line we are getting reference to WebView widget that we have specified in XML in this layout.
Then we request FEATURE_PROGRESS feature of this activity’s Window this will display the progress in Title bar of the window and progress will automatically disappear when it reaches 100%.

Then we call getSettings() method of WebView this method returns the reference to WebSettings class’s object associated with this WebView object. When a WebView is first created, it obtains a set of default settings. These default settings will be returned from any getter call. A WebSettings object obtained from WebView.getSettings() is tied to the life of the WebView. If a WebView has been destroyed, any method call on WebSettings will throw an IllegalStateException.

We use this reference to enable JavaScript on this WebView object.

Next, we are setting a new object for WebChromeClient of WebView and overriding its onProgressChanged method, this method tells the host application about the progress of loading the page.

Handling page loading behaviour using WebViewClient class:

browser.setWebViewClient(new WebViewClient(){
public void onRecievedError(WebView View, int errorCode,
String description, String failingURL){
            AlertDialog.Builder dlg = new
                        AlertDialog.Builder(WebBrowser.this);
            dlg.setMessage(description);
            dlg.setTitle(R.string.app_name);
            dlg.setPositiveButton(R.string.ok_button, new
DialogInterface.OnClickListener() {                   public void onClick(DialogInterface
arg0, int arg1) {
                                   
                              }
                  });
            }
      });

Here, we are setting a new object for WebViewClient of WebView and overriding its onRecievedError method, this method is called whenever there is some error in loading the page.
Similar to this approach you can override the

public boolean shouldOverrideUrlLoading(WebView view, String url)

method of WebViewClient; this method returns “true” if it is overriding the Url Loading otherwise “false

Adding Javascript to Java interfaces

final Context myApp = this;
/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface {
@SuppressWarnings("unused")
public void showHTML(String html) {
new AlertDialog.Builder(myApp)
.setTitle("HTML")
.setMessage(html)
.setPositiveButton(android.R.string.ok, null) .setCancelable(false)
.create()
.show();
}
}

final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */ browser.getSettings().setJavaScriptEnabled(true);

/* Register a new JavaScript interface called HTMLOUT */ browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");

/* WebViewClient must be set BEFORE calling loadUrl! */ browser.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) {

/* This call inject JavaScript into the page which just finished loading. */ browser.loadUrl("javascript:window.HTMLOUT.showHTML('<head>'+document.getElementsBy
TagName('html') [0].innerHTML+'</head>');"); } });

/* load a web page */
browser.loadUrl("someUrl");

  • First, a class called MyJavaScriptInterface is defined. It implements a single public method showHTML() which displays a dialog with the HTML it receives as a parameter.
  • Then, an instance of this class is registered as a JavaScript interface called HTMLOUT. The showHTML() method can now be accessed from JavaScript like this: window.HTMLOUT.showHTML(‘…’)
  • In order to call showHTML() when the page finishes loading, a WebViewClient instance which overrides onPageFinished() is added to the WebView. When the page finishes loading, this method will inject a piece of JavaScript code into the page, using the method I described in an earlier post.
  • Finally, a web page is loaded.

showHTML method can also be called from other Javascript that may get loaded into your browser control, so, use carefully.


Cheers!!
Vivek Jain
Hello Everyone, I came across an application which allowed me to produce nice effects on Images that are in my phone and Images that I take from my phones camera, its available here, 

No comments:

Post a Comment