WebView与js的交互包含两方面,一是在html中通过js调用java代码;二是在安卓java代码中调用js。

一、html中通过js调用java代码

js中调用java代码其实就记住一点,WebView设置一个和js交互的接口(这里的接口是一般的意思,不是java中接口的含义),这个接口其实就是一个一般的类,同时为这个接口取一个别名。这个过程如下:

mWebView.addJavaScriptInterface(new DemoJavaScriptInterface(),"demo");

new DemoJavaScriptInterface()就是这个接口,demo就是这个接口的别名。

上面的代码执行后在html中js就能通过别名(这里是“demo”)来调用DemoJavaScriptInterface类中的任何方法了。

如果我们想让html中的一个button点击之后调用java中的函数可以这样:

但是因为安全问题,在Android4.2中(如果应用的android:targetSdkVersion为17+)JS只能访问带有@javaScriptInterface注解的java函数,所以开发版本较高的时候,在需要被调用的函数前加上这个注解。4.2以下为了安全尽量不要调用addJavascriptInterface,需要另谋他法。

下面是google官方给的实例:

WebViewDemo.java

[代码]java代码:

package com.google.android.webviewdemo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
/**
* Demonstrates 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 javascript.
* 
* In this example, clicking on the android in the   WebView will result in a call into
* the activities code in {@link   DemoJavaScriptInterface#clickOnAndroid()}. This code
* will turn around and invoke javascript using   the {@link WebView#loadUrl(String)}
* method.
* 
* Obviously all of this could have been   accomplished without calling into the activity
* and then back into javascript, but this code is   intended to show how to set up the
* code paths for this sort of communication.
*
*/
public class WebViewDemo extends Activity {
private static final String   LOG_TAG = "WebViewDemo";
private WebView mWebView;
private Handler mHandler = new Handler();
@Override
public void onCreate(Bundle   icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
mWebView   = (WebView) findViewById(R.id.webview);
WebSettings   webSettings = mWebView.getSettings();
webSettings.setSavePassword(false);
webSettings.setSaveFormData(false);
webSettings.setJavaScriptEnabled(true);
webSettings.setSupportZoom(false);
mWebView.setWebChromeClient(new   MyWebChromeClient());
mWebView.addJavascriptInterface(new   DemoJavaScriptInterface(), "demo");
mWebView.loadUrl("file:///android_asset/demo.html");
}
final class DemoJavaScriptInterface   {
DemoJavaScriptInterface()   {
}
/**
*   This is not called on the UI thread. Post a runnable to invoke
*   loadUrl on the UI thread.
*/
public void   clickOnAndroid() {
mHandler.post(new   Runnable() {
public   void run() {
mWebView.loadUrl("javascript:wave()");
}
});
}
}
/**
* Provides a hook for   calling "alert" from javascript. Useful for
* debugging your   javascript.
*/
final class MyWebChromeClient   extends WebChromeClient {
@Override
public boolean   onJsAlert(WebView view, String url, String message, JsResult result) {
Log.d(LOG_TAG,   message);
result.confirm();
return   true;
}
}
}
demo.html

[代码]xml代码:

/* This   function is invoked by the activity */
function   wave() {
alert("1");
document.getElementById("droid"). src="" data-original="android_waving.png";
alert("2");
}
 
 
Click   me!
 
 
main.xml

[代码]xml代码:

android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/intro"
android:padding="4dip"
android:textSize="16sp"
/>
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
/>

Android调用js

调用webview页面内的js方法,调用形式:

mWebView.loadUrl("javascript:wave()");

其中wave()是js中的一个方法,当然你可以把这个方法改成其他的方法,也就是android调用其他的方法。但java不能直接获取Js方法的返回结果。

小结

具体交互流程如下:

o    点击图片,则在js端直接调用android上的方法clickOnAndroid();

o    clickOnAndroid()方法(利用线程)调用js的方法。

o    被调用的js直接控制html。

利用webView的这种方式在有些时候UI布局就可以转成相应的html代码编写了,而html布局样式之类有DW这样强大的工具,而且网上很多源码,很多代码片。在UI和视觉效果上就会节省很多时间,重复发明轮子没有任何意义。

交互结果

Android Webview中Java调用Js方法很容易,loadUrl("javascript:isOk()")就可以调用isOk这个Js方法,但不能直接获取Js方法的返回结果。

1.传统的方法中,Js获取Java信息可以采用如下方式:

[代码]java代码:

class JsObject {
@JavascriptInterface
public String   toString() { return "injectedObject"; }
}
webView.addJavascriptInterface(new JsObject(),   "injectedObject");
webView.loadData("", "text/html",   null);
webView.loadUrl("javascript:alert(injectedObject.toString())");

2.Java获取Js信息(如通过Js获取网页源代码)可以这样:

[代码]java代码:

import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class HtmlSource extends Activity {
private WebView webView;
@Override
public void onCreate(Bundle   savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
webView   = (WebView)findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new   InJavaScriptLocalObj(), "local_obj");
webView.setWebViewClient(new   MyWebViewClient());
webView.loadUrl("");
}
final class MyWebViewClient extends WebViewClient{
public boolean   shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return   true;
}
public void   onPageStarted(WebView view, String url, Bitmap favicon) {
Log.d("WebView","onPageStarted");
super.onPageStarted(view,   url, favicon);
}
public void   onPageFinished(WebView view, String url) {
Log.d("WebView","onPageFinished   ");
view.loadUrl("javascript:window.local_obj.showSource(''+"   +
"document.getElementsByTagName('html')[0].innerHTML+'');");
super.onPageFinished(view,   url);
}
}
final class InJavaScriptLocalObj   {
public void   showSource(String html) {
Log.d("HTML",   html);
}
}
}

当网页中有超链接跳转时,将会调用WebClient的shouldOverrideUrlLoading方法,若设置 WebViewClient 且该方法返回 true,则说明由应用的代码处理该 url,WebView 不处理,就可以达到拦截跳转的效果。