开发中使用WebView加载url、html标签必不可少,比如广告、活动界面通过WebView加载具有实效性。下面介绍WebView使用方法。
webView.loadUrl(url);
loadUrl(url)这样可以直接加载网页,但此时是通过手机浏览器打开的网页,如果要使用WebView直接打开则需设置WebViewClient。
webView.setWebViewClient(new WebViewClient());
有关WebViewClient下面再详细介绍。
对于加载Url注意如下:
1、如果是在线网址记得添加网络访问权限
2、在线网址中,如果要使用webview打开,记得设置WebViewClient
3、打开本地html文件时,是不需要设置WebViewClient,对应的asstes目录的url 为:file:///android_asset/xxxxx*
我们先来看如何根据需求设置webView属性,可以调用WebView.getSettings()获取设置WebView的WebSettings对象,通过WebSettings做属性配置,各配置说明如下:
WebSettings webSettings = webView.getSettings();
//设置开启javascript支持
webSettings.setJavaScriptEnabled(true);
//设置支持缩放
webSettings.setSupportZoom(true);
//开启缩放工具(会出现放大缩小的按钮)
webSettings.setBuiltInZoomControls(true);
//WebView两种缓存(网页、H5)方式,此处网页不缓存
webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
//允许JS打开新窗口(默认false)
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
//打开本地缓存供JS调用
webSettings.setDomStorageEnabled(true);
//H5缓存内存大小(已过时,不必设置已可自动管理)
//webSettings.setAppCacheMaxSize(1024 * 1024 * 8);
//H5缓存路径
String absolutePath = getApplicationContext().getCacheDir().getAbsolutePath();
//H5缓存大小
webSettings.setAppCachePath(absolutePath);
//是否允许WebView访问内部文件(默认true)
webSettings.setAllowFileAccess(true);
//支持存储H5缓存
webSettings.setAppCacheEnabled(true);
//启动概述模式浏览界面,当页面宽度超过WebView显示宽度时,缩小页面适应WebView(默认false)
webSettings.setLoadWithOverviewMode(true);
//支持手势缩放(如webView中需要手动输入用户名、密码等,则webview必须设置支持获取手势焦点)
webView.requestFocusFromTouch();
// 清除缓存
webView.clearCache(true);
// 清除缓存防止登录上次的账号
CookieManager.getInstance().removeAllCookie();
Java调用JavaScript
java调用JavaScript中的函数很简单,只需要执行如下代码即可:
webView.loadUrl("javascript:toast()");
toast()是JS中方法。
JavaScript调用Java
三个步骤:
1.调用WebSettings的setJavaScriptEnabled方法使支持JavaScript调用。
2.调用WebView的addJavascriptInterface方法将应用中的Java对象暴露给JavaScript;
3.在JavaScript脚本中调用步骤二暴露出来的Java对象的方法。
在webView.addJavascriptInterface(new JsBradge(), "android");实现;其中JsBradge()中是申明了JS可调用的本地方法,“android”是与JS协商的对象名称,JS端可通过android.toastMessage(" ")调用Java方法。
注:如下需加上@JavascriptInterface注解,避免引起WebView远程代码执行漏洞。
public class JsBradge {
@JavascriptInterface
public void toastMessage(String message) {
Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
}
}
WebViewClient
WebViewClient可以拿到WebView在访问网络各个阶段的回调,包括加载前后,失败等(以下注释来源"启舰"博客)
/**
* 在开始加载网页时会回调
*/
public void onPageStarted(WebView view, String url, Bitmap favicon)
/**
* 在结束加载网页时会回调
*/
public void onPageFinished(WebView view, String url)
/**
* 拦截 url 跳转,在里边添加点击链接跳转或者操作
*/
public boolean shouldOverrideUrlLoading(WebView view, String url)
/**
* 加载错误的时候会回调,在其中可做错误处理,比如再请求加载一次,或者提示404的错误页面
*/
public void onReceivedError(WebView view, int errorCode,String description, String failingUrl)
/**
* 当接收到https错误时,会回调此函数,在其中可以做错误处理
*/
public void onReceivedSslError(WebView view, SslErrorHandler handler,SslError error)
/**
* 在每一次请求资源时,都会通过这个函数来回调
*/
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
return null;
}
以上可以根据需求做相应处理,其中shouldOverrideUrlLoading方法会在加载超链接时回调过来,当需要WAP与原生互调等劫持URL时用到,重写该方法然后return true即可,当不需要劫持在else中重新loadUrl(url)即可。
// 当点击链接时,希望覆盖而不是打开新窗口
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// showProgressDlg();
// 拦截抢购商品,跳回APP抢购商品详情
if (url.contains("proId") && url.contains("qgDetail.html")) {
String actid = url.split("\\?")[1].split("&")[0].split("=")[1];
ActivityController.startActProductDetailActivity(WebActivity.this, actid, "");
} else if (url.contains("goodDetail.html") && url.contains("proId")) {
String id = url.split("\\?")[1].split("&")[0].split("=")[1];
ActivityController.startGoodsDetailActivity(WebActivity.this, id);
} else {
view.loadUrl(url);
}
return true;
}
WebChromeClient
可以在其中加载进度条,获取链接的标题等方法。
/**
* 当网页调用alert()来弹出alert弹出框前回调,用以拦截alert()函数
*/
public boolean onJsAlert(WebView view, String url, String message,JsResult result)
/**
* 当网页调用confirm()来弹出confirm弹出框前回调,用以拦截confirm()函数
*/
public boolean onJsConfirm(WebView view, String url, String message,JsResult result)
/**
* 当网页调用prompt()来弹出prompt弹出框前回调,用以拦截prompt()函数
*/
public boolean onJsPrompt(WebView view, String url, String message,String defaultValue, JsPromptResult result)
/**
* 打印 console 信息
*/
public boolean onConsoleMessage(ConsoleMessage consoleMessage)
/**
* 通知程序当前页面加载进度
*/
public void onProgressChanged(WebView view, int newProgress)
下面附上我项目里的一段代码,加载进度条跟获取Title:
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
if (newProgress == 100) {
progressBar.setVisibility(View.GONE);
} else {
if (progressBar.getVisibility() == View.GONE)
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(newProgress);
}
}
@Override
public void onReceivedTitle(WebView view, String title) {
setActivityTitle(title);
}
webView加载html
当后台返回不是url而是一连串的html标签时,可以通过
webView.loadDataWithBaseURL(null, html , "text/html", "UTF-8", "");
之前可以设置:
//水平不显示滚动条
webView.setHorizontalScrollBarEnabled(false);
//垂直不显示滚动条
webView.setVerticalScrollBarEnabled(false);
//初始化压缩比例
webView.setInitialScale(50);
// webview自适应屏幕尺寸
webView.getSettings().setSupportZoom(true);
webView.getSettings().setUseWideViewPort(true);
webView.getSettings().setLoadWithOverviewMode(true);
//设置图片显示方式
webView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);
// 设置背景色
//webView.setBackgroundColor(0);
webView.getSettings().setDefaultTextEncodingName("UTF-8");
//设置图片最大尺寸,高度自适应;文字颜色、字体大小、行高、首行缩进两个字符
// 包含去除img style 的js代码
String head = " "
+ "";
html = head + "" + html + ""
+ "";
回退事件处理
当回退时,若不监听回退键点击返回时不会回退到上一web界面,而是直接结束当前Activity,通过canGoBack判断是否可回退,goBack进行回退。代码如下:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && webView.canGoBack()) {
if (webView.copyBackForwardList().getItemAtIndex(webView.copyBackForwardList().getSize() - 1).getUrl().contains("activity/201412/act_common.html")) {
//解决活动重定向无法回退到原生界面
return super.onKeyDown(keyCode, event);
} else {
webView.goBack();
return true;
}
}
return super.onKeyDown(keyCode, event);
}
以上你看到copyBackForwardList方法,这个是为了解决重定向可以正确退出当前Activity而设置。
先说下问题,当你loadUrl(url1)时,web端将url1更换成了url2,所以显示出来的是url2界面。webview中copyBackForwardList是专门用来管理url栈的,但此时,不光url2入栈,url1也入栈了,所以当在url2界面时,canGoBack返回的也是true,当按回退键时就会回到url1(不会显示)然后马上又回到url2界面,这就是按回退无法finish当前Activity而陷入重新加载url2界面的原因和解决办法。
注意在拥有WebVie的Activity中需要在onDestory方法中销毁webView以防内存泄漏,代码如下:
@Override
protected void onDestroy() {
//销毁webview,避免内在泄漏
if (webView != null) {
//移除webView确保Detach
ViewGroup parent = (ViewGroup) webView.getParent();
if (parent != null) {
parent.removeView(webView);
}
webView.removeAllViews();
webView.clearHistory();
webView.destroy();
webView = null;
}
super.onDestroy();
}
参考:
WebView使用详解(二)——WebViewClient与常用事件监听
《Android高级进阶》——顾浩鑫/著