Thursday, July 14, 2011

Android #11: Working with WebViews

WebView is a view that displays web pages. WebViews can be used to render HTML content within your Android application. Typically a WebView uses the Android web kit browser within, but the difference or benefit we achieve is that we can embed HTML content from within our native application. A WebView uses the same rendering and JavaScript engine as the browser, but it runs under the control of your application. Another main feature in this approach is that we can have Activity-to-JavaScript communication possible. That is, a JavaScript function can invoke an Activity function and vice versa.

Embedding a WebView into an application activity

Android platform provides the API for rendering arbitrary HTML within your app by allowing the built-in web browser as a widget within the app. HTML content can come from anywhere, either from any of the below
  • Local HTML files stored in your assets of your Android app
  • Downloaded from the web
  • HTML strings
Here is an example on dealing with the three WebViews embedding three different sources of HTML content (as above) and also demonstrates on how to bind Java and JavaScript code for activity and web content communication




layout/main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="WebViewDemo"
android:padding="4dip" android:textSize="16sp" />

<WebView android:id="@+id/webview1" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="0" />

<WebView android:id="@+id/webview2" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="0" />

<WebView android:id="@+id/webview3" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="0" />

</LinearLayout>

WebViewActivity.java
package in.satworks.android.samples.activity;import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

/** * This class demonstrates on how to embed a WebView in your activity. Also
* demonstrates how to have JavaScript in the WebView call into the activity,
* and how the activity can invoke a JavaScript function.
*/

public class WebViewActivity extends Activity { private WebView mWebView1, mWebView2, mWebView3;
private Handler mHandler = new Handler();

/** Called when the activity is first created. */ @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

// First WebView with HTML Strings
mWebView1 = (WebView) findViewById(R.id.webview1);
mWebView1.loadData("This is plain HTML text string - BOLDED and
COLORED RED
",
"text/html", "utf-8");

// Second WebView with Local HTML file stored under Android Assets
mWebView2 = (WebView) findViewById(R.id.webview2);
mWebView2.setWebChromeClient(new MyWebChromeClient());
mWebView2.loadUrl("file:///android_asset/demo.html");
WebSettings webSettings2 = mWebView2.getSettings();
// By default, the JavaScript support of the WebView object we are
// working with is turned off.
// In order to turn on the web view support for the JavaScript language
// we should call the setJavaScriptEnabled() method.
webSettings2.setJavaScriptEnabled(true);
// register interface class containing methods to be exposed
// to JavaScript. Takes two params namely, java object we need to expose
// and the reference name to use within JavaScript code
mWebView2.addJavascriptInterface(new MyJavaScriptInterface(),
"androidmethodref");

// Third WebView with external HTML reference mWebView3 = (WebView) findViewById(R.id.webview3);
mWebView3.loadUrl("http://www.google.com/");
WebSettings webSettings3 = mWebView3.getSettings();
webSettings3.setJavaScriptEnabled(true);
// Below is required in order to embed the HTML response output within
// the current activity instead of moving out to Android Browser window
mWebView3.setWebViewClient(new MyWebViewClient());

}/**
* WebViewClient provides a way to embed the WebView call of loadUrl within
* the app layout instead of opening a new independent Android browser
* window
*/
final class MyWebViewClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}

}/**
* WebChromeClient provides a hook for calling "alert" from JavaScript.
* Useful for debugging JavaScript.
*/
final class MyWebChromeClient extends WebChromeClient {
@Override
public boolean onJsAlert(WebView view, String url, String message,
JsResult result) {
System.out.println("This message is from Javascript alert=>"
+ message);
Toast.makeText(
getApplicationContext(),
"Activity to WebView Communication: \n" + message
+ " from JavaScript function", Toast.LENGTH_SHORT)
.show();
result.confirm();
return true;
}
}

/** * JavaScript interface containing methods that can be invoked by the
* JavaScript within HTML. It also in turn invokes the JavaScript method
*/
final class MyJavaScriptInterface {

MyJavaScriptInterface() { }

/** * This method will be invoked via the JavaScript event from within HTML
* through the registered reference name 'androidmethodref'. This is not
* called on the UI thread. Post a runnable to invoke loadUrl on the UI
* thread.
*/
public void clickOnAndroid() {
System.out.println("Method - clickOnAndroid called from Javascript embedded within HTML (demo.html).");
Toast.makeText(
getApplicationContext(),
"WebView to Activity Communication: \nclickOnAndroid: Called from Javascript Event",
Toast.LENGTH_SHORT).show();
mHandler.post(new Runnable() {
// Call to the HTML JavaScript Method
public void run() {
mWebView2.loadUrl("javascript:greetUser()");
}
});
}
}

}

assets/demo.html
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
// This function is invoked by the Android Activity
function greetUser()
{
alert("Welcome! "+document.forms[0].nameVal.value);
}
</script>
</head>
<form>
<body bgcolor="lavender">
<input type="text" name="nameVal" value="Sat"/>
<!-- Calls into the JavaScript interface for the activity //-->
<input type="button" value="Greet User" onClick="window.androidmethodref.clickOnAndroid()"/>
</body>
</form>
</html>

values/strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">WebViewApp</string>
</resources>

AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="in.satworks.android.samples.activity" android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".WebViewActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />

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

Reference: