Building Web Extensions Using WebKit Android

All HTML rendering on the Android platform is done using the WebKit rendering engine. The android.webkit package provides a number of APIs for browsing the Internet using the powerful WebView control. You should be aware of the WebKit interfaces and classes available, as you are likely to need them to enhance the WebView user experience.

These are not classes and interfaces to the Browser app (although you can interact with the Browser data using contact providers). Instead, these are the classes and interfaces that you must use to control the browsing abilities of WebView controls you implement in your applications.

Browsing the WebKit APIs

Some of the most helpful classes of the android.webkit package are

  • The CacheManager class gives you some control over cache items of a WebView.
  • The ConsoleMessage class can be used to retrieve JavaScript console output from a WebView.
  • The CookieManager class is used to set and retrieve user cookies for a WebView.
  • The URLUtil class is handy for validating web addresses of different types.
  • The WebBackForwardList and WebHistoryItem classes can be used to inspect the web history of the WebView.

Now let’s take a quick look at how you might use some of these classes to enhance a WebView.

Extending Web Application Functionality to Android

Let’s take some of the WebKit features we have discussed so far in this chapter and work through an example. It is fairly common for mobile developers to design their applications as web applications in order to reach users across a variety of platforms. This minimizes the amount of platform-specific code to develop and maintain. However, on its own, a web application cannot call into native platform code and take advantage of the features that native apps (such as those written in Java for the Android platform) can, such as using a built-in camera or accessing some other underlying Android feature.

Developers can enhance web applications by designing a lightweight shell application in Java and using a WebView control as a portal to the web application content. Two-way communication between the web application and the native Java application is possible through scripting languages such as JavaScript.

Let’s create a simple Android application that illustrates communication between web content and native Android code. This example requires that you understand JavaScript. To create this application, take the following steps:

  1. Create a new Android application.
  2. Create a layout with a WebView control called html_viewer and a Button control called call_js. Set the onClick attribute of the Button control to a method called setHTMLText.
  3. In the onCreate() method of your application activity, retrieve the WebView control using the findViewById() method.
  4. Enable JavaScript within the WebView by retrieving its WebSettings and calling the setJavaScriptEnabled() method.
  5. Create a WebChromeClient object and implement its onConsoleMessage() method in order to monitor the JavaScript console messages.
  6. Add the WebChromeClient object to the WebView using the setWebChromeClient() method.
  7. Allow the JavaScript interface to control your application by calling the addJavascriptInterface() method of the WebView control. You will need to define the functionality that you want the JavaScript interface to be able to control and within what namespace the calls will be available. In this case, we allow the JavaScript to initiate Toast messages.
  8. Load your content into the WebView control using one of the standard methods, such as the loadUrl() method. In this case, we load an HTML asset we defined within the application package.

If you followed these steps, you should end up with your activity’s onCreate() method looking something like this:

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final WebView wv = (WebView) findViewById(R.id.html_viewer);
WebSettings settings = wv.getSettings();
settings.setJavaScriptEnabled(true);
WebChromeClient webChrome = new WebChromeClient() {
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Log.v(DEBUG_TAG, consoleMessage.lineNumber()
+ “: “ + consoleMessage.message());
return true;
}
};
wv.setWebChromeClient(webChrome);
wv.addJavascriptInterface(new JavaScriptExtensions(), “jse”);
wv.loadUrl(“file:///android_asset/sample.html”);
}

A custom WebChromeClient class is set so that any JavaScript console.log messages go out to LogCat output, using a custom debug tag as usual to enable easy tracking of log output specific to the application. Next, a new JavaScript interface is defined with the namespace called jse—the namespace is up to you. To call from JavaScript to this Java class, the JavaScript calls must all start with namespace jse., followed by the appropriate exposed method—for instance, jse.javaMethod().

You can define the JavaScriptExtensions class as a subclass within the activity as a subclass with a single method that can trigger Android Toast messages:

class JavaScriptExtensions {
public static final int TOAST_LONG = Toast.LENGTH_LONG;
public static final int TOAST_SHORT = Toast.LENGTH_SHORT;
public void toast(String message, int length) {
Toast.makeText(SimpleWebExtension.this, message, length).show();
}
}

The JavaScript code has access to everything in the JavaScriptExtensions class, including the member variables as well as the methods. Return values work as expected from the methods, too. Now switch your attention to defining the web page to load in the WebView control. For this example, simply create a file called sample.html in the /assets directory of the application.

The contents of the sample.html file are shown here:

<html>
<head>
<script type=”text/javascript”>
function doToast() {
jse.toast(“‘“+document.getElementById(‘form_text’).value +
“‘ -From Java!”, jse.TOAST_LONG);
}
function doConsoleLog() {
console.log(“Console logging.”);
}
function doAlert() {
alert(“This is an alert.”);
}
function doSetFormText(update) {
document.getElementById(‘form_text’).value = update;
}</script></head>
<body>
<h2>This is a test.</h2>
<input type=”text” id=”form_text” value=”Enter something here...” />
<input type=”button” value=”Toast” onclick=”doToast();” /><br />
<input type=”button” value=”Log” onclick=”doConsoleLog();” />
<input type=”button” value=”Alert” onclick=”doAlert();” />
</body>
</html>

The sample.html file defines four JavaScript functions and displays the form shown within the WebView:

  • The doToast() function calls into the Android application using the jse object defined earlier with the call to the addJavaScriptInterface() method. The add JavaScriptInterface() method, for all practical intents and purposes, can be treated literally as the JavaScriptExtensions class as if that class had been written in JavaScript. If the doToast() function had returned a value, we could assign it to a variable here.
  • The doConsoleLog() function writes into the JavaScript console log, which is picked up by the onConsoleMessage() callback of the WebChromeClient.
  • The doAlert() function illustrates how alerts work within the WebView control by launching a dialog. If you want to override what the alert looks like, you can override the WebChromeClient.onJSAlert() method.
  • The doSetFormText() function illustrates how native Java code can communicate back through the JavaScript interface and provide data to the web application.

Finally, to demonstrate making a call from Java back to JavaScript, you need to define the click handler for the Button control within your Activity class. Here, the onClick handler, called setHTMLText(), executes some JavaScript on the currently loaded page by calling a JavaScript function called doSetFormText(), which we defined earlier in the web page. Here is an implementation of the setHTMLText() method:

public void setHTMLText(View view) {
WebView wv = (WebView) findViewById(R.id.html_viewer);
wv.loadUrl(“javascript:doSetFormText(‘Java->JS call’);”);
}

This method of making a call to the JavaScript on the currently loaded page does not allow for return values. There are ways, however, to structure your design to allow checking of results, generally by treating the call as asynchronous and implementing another method for determining the response.

Figure shows how this application might behave on an Android device.

This style of development has been popularized by the open source PhoneGap project, which aims to provide a set of standard JavaScript interfaces to native code across a variety of platforms, including iOS,Android, BlackBerry, Symbian, and Palm.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

Android Topics