在Android中有WebView Widget,它内置了WebKit引擎,同时,WebKit也是Mac OS X的Safari网页浏览器的基础。WebKit是一个开源的浏览器引擎,Chrome浏览器也是基于它的。所以很多表现WebView和Chrome是一样的。
该篇针对Android 中 的WebView 和 JS 交互需要注意的事项。
一.WebView相关setting
1.属性汇总
WebSettings常用方法:
setAllowFileAccess 启用或禁止WebView访问文件数据
setBlockNetworkImage 是否显示网络图像
setBuiltInZoomControls 设置是否支持缩放
setCacheMode 设置缓冲的模式
setDefaultFontSize 设置默认的字体大小
setDefaultTextEncodingName 设置在解码时使用的默认编码
setFixedFontFamily 设置固定使用的字体
setJavaSciptEnabled 设置是否支持Javascript
setLayoutAlgorithm 设置布局方式
setLightTouchEnabled 设置用鼠标激活被选项
setSupportZoom 设置是否支持变焦
WebViewClient常用方法:
doUpdate VisitedHistory 更新历史记录
onFormResubmission 应用程序重新请求网页数据
onLoadResource 加载指定地址提供的资源
onPageFinished 网页加载完毕
onPageStarted 网页开始加载
onReceivedError 报告错误信息
onScaleChanged WebView发生改变
shouldOverrideUrlLoading 控制新的连接在当前WebView中打开
WebChromeClient常用方法:
onCloseWindow 关闭WebView
onCreateWindow 创建WebView
onJsAlert 处理Javascript中的Alert对话框
onJsConfirm处理Javascript中的Confirm对话框
onJsPrompt处理Javascript中的Prompt对话框
onProgressChanged 加载进度条改变
onReceivedlcon 网页图标更改
onReceivedTitle 网页Title更改
onRequestFocus WebView显示焦点
2.页面缩放
适应手机屏幕:
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
放大设置:
webView.getSettings().setDisplayZoomControls(true);
无限放大:
webView.getSettings().setSupportZoom(true);
比例缩放:
webView.setInitialScale(50);
3.页面缓存
缓存存放地址路径:
/data/data/package_name/cache/
/data/data/package_name/database/webview.db
/data/data/package_name/database/webviewCache.db
缓存模式
LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
LOAD_DEFAULT: 根据cache-control决定是否从网络上取数据。
LOAD_CACHE_NORMAL: API level 17中已经废弃, 从API level 11开始作用同LOAD_DEFAULT模式
LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
如:www.taobao.com的cache-control为no-cache,在模式LOAD_DEFAULT下,无论如何都会从网络上取数据,如果没有网络,就会出现错误页面;在LOAD_CACHE_ELSE_NETWORK模式下,无论是否有网络,只要本地有缓存,都使用缓存。本地没有缓存时才从网络上获取。www.360.com.cn的cache-control为max-age=60,在两种模式下都使用本地缓存数据。
总结:根据以上两种模式,建议缓存策略为,判断是否有网络,有的话,使用LOAD_DEFAULT,无网络时,使用LOAD_CACHE_ELSE_NETWORK。
清理cache 和历史记录
webView.clearCache(true);
webView.clearHistory();
4、错误页面
出现网络异常、地址不存在的错误问题,而默认的错误页面比较难看,这时需要加载自己设计好的页面。
webView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
//显示错误页面
@Override
public void onReceivedError(WebView view, int errorCode,
String description, String failingUrl) {
// 静态页存放在assets文件夹下
view.loadUrl("file:///android_asset/www/index.html");
super.onReceivedError(view, errorCode, description, failingUrl);
}
});
5、加载进度
/*
* 需要自己定义一个进度条控件
* 这里已经定义好了progressBar
*/
webView.setWebChromeClient(new WebChromeClient(){
@Override
public void onProgressChanged(WebView view, int newProgress) {
// TODO Auto-generated method stub
if(newProgress < 100){
//更新当前进度
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(newProgress);
}else{
//加载完成因此进度条
progressBar.setVisibility(View.GONE);
}
super.onProgressChanged(view, newProgress);
}
});
二.WebView和js交互
1.调用js代码
在程序中调用js代码,只需要将webview控件的支持js的属性设置为true,,然后通过loadUrl就可以直接进行调用,如下所示:
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.loadUrl("javascript:test()");
2.js调用android中java代码的方法
在html中调用java代码,需要在webview控件中添加javascriptInterface。如下所示:
mWebView.addJavascriptInterface(new DemoJavaScriptInterface(), "images");
final class DemoJavaScriptInterface {
DemoJavaScriptInterface() {
}
@JavascriptInterface
public void clickOnAndroid() {
mHandler.post(new Runnable() {
public void run() {
//调用js中wave方法;("javascript:"+js方法)固定写法
mWebView.loadUrl("javascript:wave()");
}
});
}
}
注意:对于安卓开发有一段时间的人来说,知道安卓4.4以前谷歌的webview存在安全漏洞,网站可以通过js注入就可以随便拿到客户端的重要信息,甚至轻而易举的调用本地代码进行流氓行为,谷歌后来发现有此漏洞后,增加了防御措施,如果要是js调用本地代码,开发者必须在代码申明JavascriptInterface,例如在4.0之前我们要使得webView加载js只需本文中介绍的方法。4.4之后调用需要在调用方法加入加入@JavascriptInterface注解,如果代码无此申明,那么也就无法使得js生效,也就是说这样就可以避免恶意网页利用js对安卓客户端的窃取和攻击。
在网页中,只需要像调用js方法一样,进行调用就可以。
<div id='b'><a onclick="window.demo.clickOnAndroid()">b.c</a></div>
3.Java代码调用js并传参
首先需要带参数的js函数,如function test(str),然后只需在调用js时传入参数即可,如下所示:
mWebView.loadUrl("javascript:test('aa')");
三.注意事项
1.有时会出现混淆打包失效问题,需要在proguard.cfg文件中添加
//表示WebHost类下的所有方法不被混淆
-keep public class com.cx.httpwebview.WebHost{
public <methods>
}