转载请注明出处: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文件中注册网络权限:
"android.permission.INTERNET" />
如果还要涉及到定位,还要注册定位权限:
"android.permission.ACCESS_FINE_LOCATION"/>
"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类主要针对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中的缓存模式有四种:
根据网络合理加载网络数据:
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中:
设定字体大小:
webSettings.setTextSize(TextSize.SMALLER);
Android4.0之后WebView使用起来更加灵活,可采用setTextZoom(int)设置字体大小,参数默认是100。上边的方法已经舍弃。
主要展示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主要辅助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定位==========================================================
//需要先加入权限
//
//
@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交互说白了就两种形式,一种是由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");
}
});
// 已经处于底端
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);
}
@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/进行学习。