相信大家看完代码就会明白:
MainActivity.java
package com.example.testjs;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.webkit.JavascriptInterface;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebSettings.RenderPriority;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import com.example.testjs.utils.Constant;
/**
* 实现Android本地Java与JS的互调
* 1.Android调用JS:
* mWebView.loadUrl("javascript:" + "function()");
*
* 2.JS调用Android:
* a.设置WebView支持JS:mWebView.getSettings().setJavaScriptEnabled(true);
* b.创建一个JS调用代理类:class JavascriptInterfaceProxy
* 1).Android 4.2 以后需要将代理类中的方法注解:@JavascriptInterface
* c.mWebView.addJavascriptInterface(new JavascriptInterfaceProxy(), "MyJsInterface");
*
* @author Yanbao_Wu
*
*/
public class MainActivity extends Activity {
public static final String TAG = MainActivity.class.getSimpleName();
public static final int SAY_HELLO = 0;
public static final int SAY_BYEBYE = 1;
private WebView mWebView = null;
@SuppressLint("HandlerLeak")
public Handler mHandler = new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case SAY_HELLO:
Toast.makeText(MainActivity.this, "just say hello from JS", Toast.LENGTH_SHORT).show();
break;
case SAY_BYEBYE:
Toast.makeText(MainActivity.this, "Bye-bye called from JS", Toast.LENGTH_SHORT).show();
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findId();
initWebView(mWebView);
}
/**
* @author Yanbao_Wu
*/
public void findId(){
mWebView = (WebView) findViewById(R.id.webview_contend);
}
/**
* Init the web settings.
*
* @author Yanbao_Wu
*/
@SuppressLint("SetJavaScriptEnabled")
public void initWebView(WebView mWebView){
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.getSettings().setRenderPriority(RenderPriority.HIGH);
mWebView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
// 设置可以使用localStorage
mWebView.getSettings().setDomStorageEnabled(true);
// 应用可以有数据库
mWebView.getSettings().setDatabaseEnabled(true);
String cacheDirPath = getFilesDir().getAbsolutePath() + Constant.APP_H5_CACHE_DIRNAME;
// 设置 H5缓存目录
mWebView.getSettings().setAppCachePath(cacheDirPath);
// 应用可以有缓存
mWebView.getSettings().setAppCacheEnabled(true);
/**
* 注意:
* 由于4.4之前使用的是WebKit内核,而4.4使用的是chromium内核,
* 所以WebViewClient中的方法调用的次数和顺序会不一样,如果按照正常的逻辑处理,
* 可能会出现一些问题,这里可以做些版本兼容性判断。
*/
mWebView.setWebViewClient(new WebViewClient(){
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
// 自定义加载过程中的动画,例如一个loading的界面
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
// TODO Auto-generated method stub
super.onPageFinished(view, url);
}
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
// 可以自定义错误页面覆盖WebView
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
mWebView.setWebChromeClient(new WebChromeClient(){
@Override
public void onReceivedTitle(WebView view, String title) {
/*
* 可以获取Web页面的Title来设置移动端的Title,
* 但是在部分手机上,调用goBack()方法时,不会触发onReceivedTitle()方法所以onTitle没有变化,
* 所以需要做简单的处理:
* 1.已知WebView最多只有二级页面,不存在更深层次的页面时,可以在调用goBack的时候,直接将Title设置回去就可以了
* 2.当WebView的页面层次不确定时,可能会有很深层次的页面,这时需要我们手动的去维护对应页面的Title的一个栈了,我们可以
* 使用HashMap去维护这样的(url,title)的栈,当进去新的页面时直接加到Map中即可,当回退是进行退栈操作就可以了
* 当WebView加载出错时,Title会显示"找不到该网页",所以需要我们在onReceivedError方法中自行更改Title
*/
super.onReceivedTitle(view, title);
}
});
/*
* 第一个参数代理类的对象,第二个参数供JS调用方法的对象名称
* JS调用的方式大致可以通过:
* MyJsInterface.testJS();
* MyJsInterface.testLowVerssion(); // Android 4.2以后不能调用
*/
mWebView.addJavascriptInterface(new JavascriptInterfaceProxy(), "MyJsInterface");
mWebView.loadUrl("file:///android_asset/js.html");
}
/**
* The proxy class which used by JS.
*
* @author Yanbao_Wu
*/
public class JavascriptInterfaceProxy{
@JavascriptInterface
public void testJS(){
mHandler.sendEmptyMessage(SAY_HELLO);
mWebView.loadUrl("javascript:wave()");
}
// 4.2以后不能被JS调用
public void testLowVerssion(){
mHandler.sendEmptyMessage(SAY_BYEBYE);
}
}
@Override
protected void onDestroy() {
// 如果WebView中加载音频后退出Activity音频声音无法消失,可通过以下方法解决
// rootLayout.removeView(webView);
// webView.destroy();
super.onDestroy();
}
}
下面是一个HTML的代码,放在项目的assets目录下:
<html>
<script language="javascript">
function wave() {}
</script>
<body>
<a onClick="MyJsInterface.testJS()">
<br>
Click me!
</a>
</body>
</html>