什么是WebView
WebView用于展示Web页面,使用它我们可以很方便在我们的应用中显示网页。WebView使用WebKit渲染引擎来显示Web页面,同时它包含了前进/后退,放大/缩小以及进行文本搜索等方法。(从Android 4.4开始,WebView使用Chromium作为内核) 若我们想在应用中使用WebView来加载网页,需要在AndroidManifest.xml添加网络访问权限:
WebViewClient
WebViewClient和下面将要提到的WebChromeClient的功能都是帮助WebView分担一些工作,这样一来WebView就只需专注于自己的加载网页的工作,而加载网页过程中所需处理的一些其他事宜便交给WebViewClient和WebChromeClient去处理。这种设计一定程度上体现了单一职责原则。
WebViewClient的主要职责是帮助WebView处理各种通知、回调事件。比如在点击WebView中网页的链接时,默认行为是打开系统浏览器,而我们想要直接由WebView响应对链接的点击,这时我们可以为WebView设置一个自定义WebViewClient并重写shouldOverrideUrlLoading方法。
再比如WebViewClient类中有如下几个方法:
//当WebView的缩放因子改变时这个方法会被回调
public void onScaleChanged (WebView view, float oldScale, float newScale)
//当网页加载完毕后这个方法会被回调
public void onPageFinished (WebView view, String url)
//当网页开始加载时这个方法会被回调
public void onPageStarted (WebView view, String url, Bitmap favicon)
WebChromeClient
WebChromeClient的作用是监听网页加载进度以及对网页标题,网页图标、JS对话框进行处理等等。
比如WebChromeClient的onProgressChanged方法监听网页的加载进度:
public void onProgressChanged(WebView view, int newProgress) {
//newProgress为当前最新加载进度
}
WebChromeClient的onReceivedTitle方法中可获取到网页标题:
public void onReceivedTitle(WebView view, String title) {
//title为网页标题,在获取失败时则为“找不该网页”
}
onReceivedIcon方法中则可以获取到网页图标:
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
//icon为网页图标
}
WebChromeClient的以下三个方法用于处理JS对话框:
//处理alert对话框
@Override
public boolean onJsAlert(WebView view, String url,
String message, JsResult result) {
. . .
}
//处理confirm对话框
@Override
public boolean onJsPrompt(WebView view, String url,
String message, String defaultValue, JsPromptResult result) {
. . .
}
//处理prompt对话框
@Override
public boolean onJsConfirm(WebView view, String url,
String message, JsResult result) {
. . .
}
基本使用
编辑res/layout/activity_main.xml内容如下:
然后在MainActivity中:
public class MainActivity extends Activity {
private WebView mWebView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mWebView = (WebView) findViewById(R.id.wv_demo);
/** 加载本地html
* local.html存放于assets目录下
* mWebView.loadUrl("file:///android_asset/local.html");
*/
mWebView.loadUrl("http://www.jianshu.com");
}
}
支持JavaScript
若要加载的网页中含有JavaScript脚本,则必须开启对JavaScript的支持:
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
WebView自己响应链接
默认情况下,我们在WebView加载的网页中点击一个链接,系统会打开自带浏览器来响应这个链接。若想由WebView自身响应而不打开系统自带浏览器,只需进行如下设置:
mWebView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view,String url) {
view.loadUrl(url);
return true;
}
});
WebView的页面导航
默认情况下,我们在WebView界面点击Back键,WebView的finish方法会被调用从而结束自己。若我们想实现点击Back键能够实现浏览器的后退功能,只需重写onKeyDown方法:
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
上面代码中的canGoBack方法用于判断历史记录中是否存在曾经访问过的页面,goBack方法用于后退到刚刚访问过的页面。
WebView缓存
若我们的应用使用了WebView,则会在"/data/data/<应用包名>"目录下生成 database 与 cache 两个文件夹。
是否使用缓存是可以控制的,如以下代码所示:
//使用缓存
WebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//不使用缓存
WebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
与JavaScript交互
作为示例的html文件内容如下:
JSDemo
在Java代码中调用JS方法
调用无返回值的JS方法
示例代码如下:
mWebView.post(new Runnable() {
@Override
public void run() {
mWebView.loadUrl("javascript:alertMessage(\"" + "Hello, World!" + "\")");
}
});
调用有返回值的JS方法
在Android 4.4之前没有提供获取JS函数的返回值的方法,所以需要我们“曲线救国”,具体做法是在我们调用的有返回值的JS方法中调用Java方法,并把返回值通过Java方法传进来。如以下代码所示:
mWebView.post(new Runnable() {
@Override public void run() {
mWebView.loadUrl( "javascript:sumJava(1,2)");
}
});
然后我们定义一个Java方法:
@JavascriptInterface
public void onSumResult(int result) {
//传入的result参数即为JS方法的返回值
}
以上代码中的@JavascriptInterface注解表示onSumResult方法会被JS代码调用,具体介绍请看下文。
从Android 4.4开始,我们可以直接使用evaluateJavascript方法来方便地获取JS方法的返回值,示例代码如下:
mWebView.evaluateJavascript("sumJS(1, 2)", new ValueCallback() {
@Override
public void onReceiveValue(String str) {
//str为JS方法的返回值的字符串形式
}
});
在JS代码中调用Java方法
方法一:通过window.control接口
首先在Java代码中定义如下方法:
@JavascriptInterface
public void showToast(String msg) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
然后在JS代码中:
function toastMsg(msg) {
window.control.showToast(msg)
}
通过这种方式调用Java方法很简单直接。
方法二:通过自定义接口
首先在Java代码中定义一个JSInterface类:
public class JSInterface {
Context mContext;
JSInterface(Context context) {
mContext = context;
}
@JavascriptInterface
public void showToast(String msg) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
}
然后还需要用addJavascriptInterface创建接口:
mWebView.addJavascriptInterface(new JSInterface(getApplicationContext()),
"toast");
这样一来我们在JS代码中就可以按如下方式调用showToast方法了:
function toastMsg(msg) {
toast.showToast(msg)
}
关于addJavascriptInterface方法我们需要注意以下几点:
- addJavascriptInterface方法中要绑定的Java对象运行在另外的线程中,而非构造它的线程中
- 若targetSdkVersion大于等于17(android 4.2),则必须使用 @JavascriptInterface注解,否则JS代码会访问不到相应的Java方法
参考资料
- 谈谈WebView的使用
- 深入讲解WebView
- WebView你真的熟悉吗?看了才知道
**长按或扫描二维码关注我们,让您利用每天等地铁的时间就能学会怎样写出优质app。 **