2011年5月16日月曜日

AndroidStudyMemo=Browsing the Web with WebView

Applications that retrieve and display content from the Web often end up displaying that

data on the screen. Instead of customizing various screens with custom controls,Android

applications can simply use the WebView control to display web content to the screen.You

can think of the WebView control as a browser-like view.

 

The WebView control uses the WebKit rendering engine to draw HTML content on

the screen.This content could be HTML pages on the Web or it can be locally sourced.

WebKit is an open source browser engine.You can read more about it on its official website

at http://webkit.org.

 

Using the WebView control requires the android.permission.INTERNET permission.You

can add this permission to your application's Android manifest file as follows:

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

 

When deciding if the WebView control is right for your application, consider that you

can always launch the Browser application using an Intent.When you want the user to

have full access to all Browser features, such as bookmarking and browsing, you're better

off launching into the Browser application to a specific website, letting users do their

browsing, and having them return to your application when they're done.You can do this

as follows:

Uri uriUrl = Uri.parse("http://androidbook.blogspot.com/");

Intent launchBrowser = new Intent(Intent.ACTION_VIEW, uriUrl);

startActivity(launchBrowser);

 

Launching the Browser via an Intent does not require any special permissions.This means

that your application is not required to have the android.permission.INTERNET permission.

In addition, because Android transitions from your application's current activity to a

specific Browser application's activity, and then returns when the user presses the back key,

the experience is nearly as seamless as implementing your own Activity class with an

embedded WebView.

 

Loading Content into a WebView Control

You can load content into a WebView control in a variety of ways. For example, a WebView

control can load a specific website or render raw HTML content.Web pages can be stored

on a remote web server or stored on the device.

Here is an example of how to use a WebView control to load content from a specific

website:

final WebView wv = (WebView) findViewById(R.id.web_holder);

wv.loadUrl("http://www.perlgurl.org/");

 

You do not need to add any additional code to load the referenced web page on the

screen. Similarly, you could load an HTML file called webby.html stored in the application's

assets directory like this:

wv.loadUrl("file:///android_asset/webby.html");

 

If, instead, you want to render raw HTML, you can use the loadData() method:

String strPageTitle = "The Last Words of Oscar Wilde";

String strPageContent = "<h1>" + strPageTitle +

": </h1>\"Either that wallpaper goes, or I do.\"";

String myHTML = "<html><title>" + strPageTitle

+"</title><body>"+ strPageContent +"</body></html>";

wv.loadData(myHTML, "text/html", "utf-8");

 

Unfortunately, not all websites are designed for mobile devices. It can be handy to

change the scale of the web content to fit comfortably within the WebView control.You

can achieve this by setting the initial scale of the control, like this:

wv.setInitialScale(30);

 

The call to the setInitialScale() method scales the view to 30 percent of the original

size. For pages that specify absolute sizes, scaling the view is necessary to see the entire

page on the screen. Some text might become too small to read, though, so you might

need to test and make page design changes (if the web content is under your control) for a

good user experience.

 

 

Adding Features to the WebView Control

You might have noticed that the WebView control does not have all the features of a full

browser. For example, it does not display the title of a webpage or provide buttons for reloading

pages. In fact, if the user clicks on a link within the WebView control, that action

does not load the new page within the view. Instead, it fires up the Browser application.

By default, all the WebView control does is display the web content provided by the developer

using its internal rendering engine,WebKit.You can enhance the WebView control

in a variety of ways, though.You can use three classes, in particular, to help modify the behavior

of the control: the WebSettings class, the WebViewClient class, and the

WebChromeClient class.

 

Modifying WebView Settings with WebSettings

By default, a WebView control has various default settings: no zoom controls, JavaScript

disabled, default font sizes, user-agent string, and so on.You can change the settings of a

WebView control using the getSettings() method.The getSettings() method returns

a WebSettings object that can be used to configure the desired WebView settings. Some

useful settings include

Enabling and disabling zoom controls using the setSupportZoom() and

setBuiltInZoomControls() methods

Enabling and disabling JavaScript using the setJavaScriptEnabled() method

Enabling and disabling mouseovers using the setLightTouchEnabled() method

Configuring font families, text sizes, and other display characteristics

You can also use the WebSettings class to configure WebView plug-ins and allow for multiple

windows.

 

Handling WebView Events with WebViewClient

The WebViewClient class enables the application to listen for certain WebView events, such

as when a page is loading, when a form is submitted, and when a new URL is about to be

loaded.You can also use the WebViewClient class to determine and handle any errors that

occur with page loading.You can tie a valid WebViewClient object to a WebView using the

setWebViewClient() method.

The following is an example of how to use WebViewClient to handle the

onPageFinished() method to draw the title of the page on the screen:

WebViewClient webClient = new WebViewClient() {

public void onPageFinished(WebView view, String url) {

super.onPageFinished(view, url);

String title = wv.getTitle();

pageTitle.setText(title);

}};

wv.setWebViewClient(webClient);

 

When the page finishes loading, as indicated by the call to onPageFinished(), a call to

the getTitle() method of the WebView object retrieves the title for use.

 

Adding Browser Chrome with WebChromeClient

You can use the WebChromeClient class in a similar way to the WebViewClient.However,

WebChromeClient is specialized for the sorts of items that will be drawn outside the region

in which the web content is drawn, typically known as browser chrome.The

WebChromeClient class also includes callbacks for certain JavaScript calls, such as

onJsBeforeUnload(), to confirm navigation away from a page.A valid WebChromeClient

object can be tied to a WebView using the setWebChromeClient() method.

 

The following code demonstrates using WebView features to enable interactivity with

the user.An EditText and a Button control are added below the WebView control, and a

Button handler is implemented as follows:

 

Button go = (Button) findViewById(R.id.go_button);

go.setOnClickListener(new View.OnClickListener() {

public void onClick(View v) {

wv.loadUrl(et.getText().toString());

}

});

 

Calling the loadUrl() method again, as shown, is all that is needed to cause the WebView

control to download another HTML page for display, as shown in Figure 13.3. From here,

you can build a generic web browser in to any application, but you can apply restrictions

so that the user is restricted to browsing relevant materials.

 

Using WebChromeClient can help add some typical chrome on the screen. For instance,

you can use it to listen for changes to the title of the page, various JavaScript dialogs

that might be requested, and even for developer-oriented pieces, such as the console

messages.

WebChromeClient webChrome = new WebChromeClient() {

@Override

public void onReceivedTitle

(WebView view, String title) {

Log.v(DEBUG_TAG, "Got new title");

super.onReceivedTitle(view, title);

pageTitle.setText(title);

}

};

wv.setWebChromeClient(webChrome);

 

Here the default WebChromeClient is overridden to receive changes to the title of the

page.This title of the web page is then set to a TextView visible on the screen.

Whether you use WebView to display the main user interface of your application or use

it sparingly to draw such things as help pages, there are circumstances where it might be

the ideal control for the job to save coding time, especially when compared to a custom

screen design. Leveraging the power of the open source engine, WebKit, WebView can provide

a powerful, standards-based HTML viewer for applications. Support for WebKit is

widespread because it is used in various desktop browsers, including Apple Safari and

Google Chrome, a variety of mobile browsers, including those on the Apple iOS, Nokia,

Palm WebOS, and BlackBerry handsets, and various other platforms, such as Adobe AIR.

 

Building Web Extensions Using WebKit

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.

 

 

@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();" /><br />

<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

addJavaScriptInterface() 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.

 

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. Learn more about

PhoneGap at http://phonegap.com.

 

0 件のコメント:

コメントを投稿