微信公众号

webview详解和常见的问题

WebView与js的交互包含两方面,一是在html中通过js调用java代码;二是在安卓java代码中调用js。

1.如果访问的界面中有JavaScript,则webview必须支持javascript。

1
2
WebSettings webSetting = webview.getSetting();
webSetting.setJavaScriptEnabled(true);

2.如果页面中链接,如果希望点击链接继续在当前browser中响应,而不是新开Android的系统browser中响应该链接,必须覆盖webview的WebViewClient对象。

1
2
3
4
5
6
mWebView.setWebViewClient(new WebViewClient(){
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
return true;
}
}

3.如果不做任何处理,浏览网页,点击系统“Back”键,整个Browser会调用finish()而结束自身,如果希望浏览的网页回退而不是推出浏览器,需要在当前Activity中处理并消费掉该Back事件。

1
2
3
4
5
6
7
public boolean onKeyDown(int keyCode, KeyEventevent) {      
if((keyCode == KeyEvent.KEYCODE_BACK) && mWebView.canGoBack()) {
mWebView.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}

4.如果webView中需要用户手动输入用户名、密码或其他,则webview必须设置支持获取手势焦点。

1
webview.requestFocusFromTouch();

5.原来是因为WebView默认没有开启文件下载的功能,如果要实现文件下载的功能,需要设置WebView的DownloadListener,通过实现自己的DownloadListener来实现文件的下载。具体操作如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1、设置WebView的DownloadListener:
webView.setDownloadListener(new MyWebViewDownLoadListener());
2、实现MyWebViewDownLoadListener这个类,具体可以如下这样:
private class MyWebViewDownLoadListener implements 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本身进行的文件下载,
不过,这也基本上满足我们的应用场景了。

WebSettings的常用方法介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1.setJavaScriptEnabled(true);
//支持js脚步

2.setPluginsEnabled(true);
//支持插件

3.setUseWideViewPort(false);
//将图片调整到适合webview的大小

4.setSupportZoom(true);
//支持变焦控制和手势缩放

5.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
//支持内容从新布局

6.supportMultipleWindows();
//多窗口

7.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
//关闭webview中缓存

8.setAllowFileAccess(true);
//设置可以访问文件

9.setNeedInitialFocus(true);
//当webview调用requestFocus时为webview设置节点

10.setBuiltInZoomControls(true);
//Sets whether the WebView should use its built-in zoom mechanisms.设置其webview内置的缩放机制

11.setJavaScriptCanOpenWindowsAutomatically(true);
//支持通过JS打开新窗口

12.setLoadsImagesAutomatically(true);
//支持自动加载图片

WebViewClient的方法全解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
1.doUpdateVisitedHistory(WebViewview,Stringurl, boolean isReload)
(更新历史记录)
2.onFormResubmission(WebViewview,MessagedontResend,Messageresend)
(应用程序重新请求网页数据)
3.onLoadResource(WebViewview,Stringurl)
在加载页面资源时会调用,每一个资源(比如图片)的加载都会调用一次。
4.onPageStarted(WebViewview,Stringurl,Bitmapfavicon)
这个事件就是开始载入页面调用的,通常我们可以在这设定一个loading的页面,告诉用户程序在等待网络响应。
5.onPageFinished(WebViewview,Stringurl)
在页面加载结束时调用。同样道理,我们知道一个页面载入完成,于是我们可以关闭loading 条,切换程序动作。
6.onReceivedError(WebViewview, int errorCode, Stringdescription,StringfailingUrl)
(报告错误信息)
7.onReceivedHttpAuthRequest(WebViewview,HttpAuthHandlerhandler,Stringhost,Stringrealm)
(获取返回信息授权请求)
8.onReceivedSslError(WebViewview,SslErrorHandlerhandler,SslErrorerror)
重写此方法可以让webview处理https请求。
9.onScaleChanged(WebViewview, float oldScale, float newScale)
(WebView发生改变时调用)
10.onUnhandledKeyEvent(WebViewview,KeyEventevent)
(Key事件未被加载时调用)
11.shouldOverrideKeyEvent(WebViewview,KeyEventevent)
重写此方法才能够处理在浏览器中的按键事件。
12.shouldOverrideUrlLoading(WebViewview,Stringurl)
在点击请求的是链接是才会调用,重写此方法返回true表明点击网页里面的链接还是在当前的webview里跳转,不跳到浏览器那边。这个函数
我们可以做很多操作,比如我们读取到某些特殊的URL,于是就可以不打开地址,取消这个操作,进行预先定义的其他操作。

常用步骤

1、添加上网权限:

2、设置webview

1
2
3
4
5
6
7
8
9
10
11
12
13
14
WebView webView = new WebView(this);
WebSettings ws = webView.getSettings();
ws.setAppCacheEnabled(true);// 设置启动缓存
ws.setAppCacheMaxSize(1024 * 10);// 设置最大缓存
ws.setSupportZoom(true);// 设置支持缩放
ws.setBuiltInZoomControls(true);
ws.setCacheMode(WebSettings.LOAD_NO_CACHE);// 设置缓存模式
// 设置支持Javascript
ws.setJavaScriptEnabled(true);
ws.setJavaScriptCanOpenWindowsAutomatically(true);
// 缓存,离线应用
ws.setAppCacheEnabled(true);
ws.setCacheMode(WebSettings.LOAD_DEFAULT);
ws.setAppCacheMaxSize(1024 * 1024 * 8);

3、获取网页对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
webView.setWebChromeClient(new WebChromeClient() {
@Overridepublic boolean onJsAlert(WebView view, String url, String message,final JsResult result) {
//构建一个Builder来显示网页中的对话框Builder builder = new Builder(context);
builder.setTitle("警告");
builder.setMessage(message);
builder.setPositiveButton(android.R.string.ok,new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {// 点击确定按钮之后,继续执行网页中的操作
result.confirm();
}
});
builder.setCancelable(false);
builder.create();
builder.show();return true;
}

@Overridepublic boolean onJsConfirm(WebView view, String url,
String message, final JsResult result) {// TODO Auto-generated method stub
Builder builder = new Builder(context);
builder.setTitle("confirm");
builder.setMessage(message);
builder.setPositiveButton(android.R.string.ok,new AlertDialog.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
result.confirm();
}
});
builder.setNegativeButton(android.R.string.cancel,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,int which) {
result.cancel();
}
});
builder.setCancelable(false);
builder.create();
builder.show();
return true;
}
@Overridepublic void onProgressChanged(WebView view, int newProgress) {// 加载进度//
super.onProgressChanged(view, newProgress);
}
});

4、如果希望点击链接由自己处理,而不是新开Android的系统browser中响应该链接。
给WebView添加一个事件监听对象(WebViewClient)

5、webview取得焦点

6、提示加载对话框

1
2
pd=ProgressDialog.show(context, "请稍后", "正在加载中...");
当网页加载完成后,调用pd.dismiss();

webview和js之间数据的传送操作

Webview与js交互

Webview与js的双向交互才是android的webview强大所在,也是马甲精神能够彻底执行的基础保障。
将WebView接受到的数据传递给js
首先,webview可以定义一个在其内嵌页面中可以触发的事件

1
2
3
4
5
6
7
8
9
10
11
wv.addJavascriptInterface(new DemoJavaScriptInterface(), "demo");
private final class DemoJavaScriptInterface {
public void clickonAndroid( final String order){
mHandler.post(new Runnable(){
@Override
public void run(){
sonText="{"name":""+order+""}";
wv.loadUrl("javascript:wave("+jsonText+")");
}
});
}

将js接受到的数据传递给webview
如果你想获取页面的一些处理数据并交给webview客户端处理,可在wave函数里将数据alert,然后webview中重写WebChromeClient的onJsAlert函数,具体代码如下:

1
2
3
4
5
6
7
8
9
wv.setWebChromeClient(new MyWebChromeClient());  
final class MyWebChromeClient extends WebChromeClient{
//message就是wave函数里alert的字符串,这样你就可以在android客户端里对这个数据进行处理
@Override
public boolean onJsAlert(WebView view, String url, String message, final JsResult result) {
result.confirm();
return true;
}
}

loadData和loadDataWithBaseURL区别

loadData (String data, String mimeType, String encoding)

1
2
加载一段HTML代码时,如果出现中文乱码问题,
就写成loadData(String data, "text/html;charset=UTF-8",null)

loadDataWithBaseURL (String baseUrl, String data, String mimeType, String encoding, String historyUrl)

1
2
3
loadDataWithBaseURL()比loadData()多两个参数,可以指定HTML代码片段中相关资源的相对根路径,也可以指定历史Url。
两个方法的其余三个参数相同。
其次,两个方法加载的HTML代码片段有些不同,loadData()中的html data中不能包含'#', '%', '\', '?'四中特殊字符,这

WebView加载本地的css文件,js文件和图片,主要是覆盖WebViewClient中的shouldInterceptRequest(View view, String url)方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cacheWebview.setWebViewClient(new WebViewClient() {
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {

WebResourceResponse response = super.shouldInterceptRequest(view, url);

if (url.contains("weixin_qrcode_258.jpg")){
InputStream inputStream = null;
try {
inputStream = getResources().getAssets().open("weixin_qrcode_258.jpg");
response = new WebResourceResponse("image/png",
"utf-8", inputStream);
} catch (IOException e) {
e.printStackTrace();
}

}else if(url.contains(jsName)){
InputStream is = appRm.getInputStream(R.raw.jquery_min_js);
WebResourceResponse response = new WebResourceResponse("text/javascript","utf-8", is);
}else if(url.contains(cssName)){
InputStream is = appRm.getInputStream(R.raw.css;
WebResourceResponse response = new WebResourceResponse("text/css","utf-8", is);
}
return response;

}
});

加载assets文件夹下面的html资源

1
webView.loadUrl("file:///android_asset/1.html");

调用js可能出现的错误

1
2
3
4
5
6
7
8
9
10
11
12
13
Alert无法弹出
你应该是没有设置WebChromeClient,按照以下代码设置
myWebView.setWebChromeClient(new WebChromeClient() {});

Uncaught ReferenceError: functionName is not defined
问题出现原因,网页的js代码没有加载完成,就调用了js方法。解决方法是在网页加载完成之后调用js方法
myWebView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
//在这里执行你想调用的js函数
}
});

文章目录
|