转载请注明出处:http://blog.csdn.net/li0978/article/details/52792162
前言
WebView是android开发中专门用来加载网页的一种控件,它采用WebKit渲染引擎来显示网页包括控制网页的前进、后退、放大、缩小、执行文本、搜索等功能。WebKit是一种让网页浏览器绘制网页的排版引擎,被用于Apple Safari,其分支也用于基于Chromuim的网页浏览器,详细了解可移步于https://zh.wikipedia.org/zh/WebKit。WebView在开发项目中使用的频率非常高,尤其是H5的发展,开发模式也由原生开发逐步被混合开发所替代。
注册
WebView使用时一般情况下要远程加载,必须在AndroidManifest文件中注册网络权限:
<uses-permission android:name="android.permission.INTERNET" />
如果还要涉及到定位,还要注册定位权限:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
加载方式
//加载一个网页
webView.loadUrl(“http://www.google.com/“);
//加载项目中的一个html页面
webView.loadUrl(“file:///android_asset/test.html”);
//加载手机本地的一个html页面的方法
webView.loadUrl(“content://com.android.htmlfileprovider/sdcard/test.html”);
//加载一段Html代码
loadData(String data, String mimeType, String encoding);
loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl);
例:webView.loadDataWithBaseURL(null, htmlContent, “text/html”, “UTF-8”,null);
区别:loadDataWithBaseURL()比loadData()多两个参数,可以指定HTML代码片段中相关资源的相对根路径,也可以指定历史Url。两个方法的其余三个参数相同。但是loadData()中的html data中不能包含’#’, ‘%’, ‘\’, ‘?’四中特殊字符,使用时我们需要用UrlEncoder编码为%23, %25, %27, %3f 。
WebSettings
WebSettings类主要针对webview做一些相关的设置,包括自适应屏幕、缩放设置、js脚本控制、网页数据缓存等。
WebSettings webSettings = webView.getSettings();
// 设置自适应屏幕
webSettings.setUseWideViewPort(true); //设置成webview推荐使用的窗口,可任意比例缩放
webSettings.setLoadWithOverviewMode(true); //设置成webview加载的页面大小的模式,
// 设置缩放网页
webSettings.setSupportZoom(true); //是否支持屏幕双击缩放,但是下边的是前提
webSettings.setBuiltInZoomControls(true); //是否支持内置按钮缩放和手势“捏”缩放,如果设为false则webview不支持缩放功能
webSettings.setDisplayZoomControls(false); //是否隐藏原生的缩放控件
// 设置可以执行Javascript脚本
webSettings.setJavaScriptEnabled(true);
// 设置缓存网页数据
webSettings.setDomStorageEnabled(true); //开启 DOM storage API 功能
webSettings.setDatabaseEnabled(true); //开启 database storage API 功能
webSettings.setAppCacheEnabled(true); //开启 Application Caches 功能
// 设置支持多窗口,要复写 WebChromeClient的onCreateWindow方法
webSettings.setSupportMultipleWindows(true); //支持多窗口
webSettings.setJavaScriptCanOpenWindowsAutomatically(true); //支持js打开新窗口
// 支持自动加载图片
webSettings.setLoadsImagesAutomatically(true);
// 设置编码格式
webSettings.setDefaultTextEncodingName("utf-8");
缓存设置
webview中的缓存模式有四种:
- LOAD_CACHE_ONLY: 不使用网络,只读取本地缓存数据
- LOAD_DEFAULT: (默认)根据cache-control决定是否从网络上取数据。
- LOAD_NO_CACHE: 不使用缓存,只从网络获取数据.
- LOAD_CACHE_ELSE_NETWORK,只要本地有,无论是否过期,或者no-cache,都使用缓存中的数据。
根据网络合理加载网络数据:
if (NetStatusUtil.isConnected(getApplicationContext())) {
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);//有网,根据cache-control决定是否从网络上取数据。
} else {
webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK); //没网,则从本地获取,即离线加载
}
String appCachePath = getApplicationContext().getCacheDir().getAbsolutePath();
webSettings.setAppCachePath(appCachePath); //设置缓存数据目录
字体大小控制
Android版本4.0之前WebView支持字体大小分为5中:
- SMALLEST(50%),
- SMALLER(75%),
- NORMAL(100%),
- LARGER(150%),
- LARGEST(200%);
设定字体大小:
webSettings.setTextSize(TextSize.SMALLER);
Android4.0之后WebView使用起来更加灵活,可采用setTextZoom(int)设置字体大小,参数默认是100。上边的方法已经舍弃。
WebViewClient
主要展示webview网页加载的一个过程,用于帮助webview处理一些请求事件和通知。
WebViewClient webViewClient = new WebViewClient(){
//超链接加载,打开网页时不调用系统浏览器,而是在本WebView中显示。也可捕获超链接url,做相关操作
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true; //返回true表示在当前浏览器中加载
}
//网页开始加载
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
//网页加载结束
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
//网页加载失败
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
}
//对Https的支持
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
handler.proceed();
}
//针对页面中每一个资源都会调用一次,用于捕获页面资源
@Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
}
};
WebView调用:
webView.setWebViewClient(webViewClient);
WebChromeClient
WebChromeClient主要辅助WebView处理Javascript的对话框、网站图标、网站title、加载进度等。
WebChromeClient webChromeClient = new WebChromeClient(){
//获取网页加载进度
@Override
public void onProgressChanged(WebView view, int newProgress) {
if (newProgress < 100) {
String progress = newProgress + "%";
} else {
}
super.onProgressChanged(view, newProgress);
}
//=========捕获网页标题信息==========================================================
//获取标题
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
}
//获取标题ICON
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
}
//=========捕获弹框信息==========================================================
//警告框
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
if(message!=null){
//TODO
//捕获网页中弹框信息
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
}
result.cancel(); //
return true; //表示确认进行捕获
}
//确认框,会返回布尔值类型,通过这个值可判断点击时是确定还是取消,确定为true,取消为false
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
return super.onJsConfirm(view, url, message, result);
}
//输入框,会返回输入框中的值,点击取消返回null
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
return super.onJsPrompt(view, url, message, defaultValue, result);
}
//=========HTML5定位==========================================================
//需要先加入权限
//<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
//<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
@Override
public void onGeolocationPermissionsHidePrompt() {
super.onGeolocationPermissionsHidePrompt();
}
@Override
public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false); //注意个函数,第二个参数就是是否同意定位权限,第三个是是否希望内核记住
super.onGeolocationPermissionsShowPrompt(origin, callback);
}
//=========HTML5多窗口=========================================================
//WebSettings要支持多窗口
@Override
public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg) {
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(webView);
resultMsg.sendToTarget();
return true;
}
@Override
public void onCloseWindow(WebView window) {
super.onCloseWindow(window);
}
};
WebView调用:
webView.setWebChromeClient(webChromeClient);
支持文件下载
DownloadListener downloadListener = new DownloadListener() {
@Override
public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
Uri uri = Uri.parse(url);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
};
WebView调用:
webView.setDownloadListener(downloadListener);
JS交互
js交互说白了就两种形式,一种是由webview中的java方法去调用html中的js方法。另一种是html调用webview中java方法。注意在android4.2之前webview有一个漏洞,外部可通过反射来获取手机的联系方式等隐私,4.2以上官方已经修复,可在每个交互方法上添加一个注解“@JavascriptInterface”便可解决,漏洞详情可参阅:http://blog.csdn.net/leehong2005/article/details/11808557
webview设置对js的支持:
webSettings.setJavaScriptEnabled(true);
webview添加js交互接口:
webView.addJavascriptInterface(new JSInterface(),"jsinterface");
封装js交互类:
class JSInterface {
//js中可以通过:window.jsinterface.JS2Java();调用java无参方法。
@JavascriptInterface
public void JS2Java(){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(WebViewActivity.this,"js调用java无参方法。",Toast.LENGTH_SHORT).show();
}
});
}
//js中可以通过:window.jsinterface.JS2Java('hello java');调用java有参方法,并传参'hello java'。
@JavascriptInterface
public void JS2Java(final String str){
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(WebViewActivity.this,"js调用java有参方法,js传递的参数是:"+str,Toast.LENGTH_SHORT).show();
}
});
}
//Java调用JS中的无参方法
@JavascriptInterface
public void Java2JS(){
webView.loadUrl("javascript: fromJS1()");
Log.e("TAG","java调用js中的无参方法");
}
//Java调用JS中的有参方法,并传参数给js
@JavascriptInterface
public void Java2JS(final String str){
webView.loadUrl("javascript: fromJS2('"+str+"')");
Log.e("TAG","java调用js中的有参方法");
}
}
webview调用js中的方法:
//调用js有参方法
js_has_args_bt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new JSInterface().Java2JS("hello js");
}
});
WebView相关方法
- 前进,后退
goBack() //后退
goForward() //前进
goBackOrForward(intsteps) //以当前的index为起始点前进或者后退到历史记录中指定的steps,如果steps为负数则为后退,正数则为前进
canGoForward() //是否可以前进
canGoBack() //是否可以后退 - 清除缓存
clearCache(true) //清除网页访问留下的缓存,由于内核缓存是全局的因此这个方法不仅仅针对webview而是针对整个应用程序.
clearHistory() //清除当前webview访问的历史记录,只会webview访问历史记录里的所有记录除了当前访问记录.
clearFormData() //清除自动完成填充的表单数据,不会清除WebView存储到本地的数据。 - WebView状态
onResume() //激活WebView为活跃状态,能正常执行网页的响应
onPause() //WebView处于暂停状态,onPause动作通知内核暂停所有的动作,比如DOM的解析、plugin的执行、JavaScript执行。
pauseTimers() //暂停所有webview的layout,parsing,javascripttimer。降低CPU功耗。
resumeTimers() //恢复pauseTimers时的动作。
destroy() //销毁,关闭了Activity时,音乐或视频,还在播放。就必须销毁。 - 重新加载网页
reload()
重新加载网页将会重新调用WebClient类中的方法。 - 判断WebView滚动到顶端还是低端
// 已经处于底端
if (webView.getContentHeight() * webView.getScale() == (webView.getHeight() + webView.getScrollY())) {
}
// 处于顶端
if(webView.getScrollY() == 0){
}
- 退到后台关闭暂停音乐视频播放
public void onPause() {
super.onPause();
webView.onPause();
}
public void onResume() {
super.onResume();
webView.onResume();
}
- 设置手机返回按键监听
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
webView.goBack();
return true;
}
finish();
return super.onKeyDown(keyCode, event);
}
- Activity退出销毁WebView
这一步主要防止内存溢出,webview调用destory时,自定义webview仍绑定在Activity上.这是由于自定义webview构建时传入了该Activity的context对象,因此需要先从父容器中移除webview,然后再销毁webview。
@Override
protected void onDestroy() {
if (webView != null) {
webView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
webView.clearHistory();
((ViewGroup) webView.getParent()).removeView(webView);
webView.destroy();
webView = null;
}
super.onDestroy();
}
以上是个人总结WebView掌握的知识点,其他细节请移步官方文档查阅清楚,另外在系统级别4.4以上有一个开源引擎crosswalk对H5支持很好,可参阅crosswalk官方文档https://crosswalk-project.org/进行学习。