這邊總結(jié)幾個(gè)WebView的常見(jiàn)問(wèn)題暮胧,以及相應(yīng)的解決方法
一问麸、重定向問(wèn)題
問(wèn)題描述:我們從網(wǎng)頁(yè)A跳到網(wǎng)頁(yè)B,但是跳轉(zhuǎn)到B的過(guò)程其實(shí)經(jīng)歷了C頁(yè)面席舍,有C頁(yè)面重定向到達(dá)的B哮笆,A->(C->B),這個(gè)時(shí)候想要從B返回A,使用webview的goBack方法脚曾,會(huì)直接到C启具,由C又會(huì)回到B珊泳,導(dǎo)致無(wú)法跳出。
解決:?jiǎn)栴}的原因是因?yàn)槲以趙ebview的shouldOverrideUrlLoading里使用view.loadUrl(url)薯演,并且返回true導(dǎo)致秧了。查閱官方文檔,對(duì)于shouldOverrideUrlLoading的解釋是這樣的:
/**
* Give the host application a chance to take over the control when a new
* url is about to be loaded in the current WebView. If WebViewClient is not
* provided, by default WebView will ask Activity Manager to choose the
* proper handler for the url. If WebViewClient is provided, return true
* means the host application handles the url, while return false means the
* current WebView handles the url.
* This method is not called for requests using the POST "method".
*
* @param view The WebView that is initiating the callback.
* @param url The url to be loaded.
* @return True if the host application wants to leave the current WebView
* and handle the url itself, otherwise return false.
* @deprecated Use {@link #shouldOverrideUrlLoading(WebView, WebResourceRequest)
* shouldOverrideUrlLoading(WebView, WebResourceRequest)} instead.
*/
@Deprecated
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
簡(jiǎn)單來(lái)說(shuō)衡创,return true 表示webview不會(huì)幫你處理內(nèi)部跳轉(zhuǎn)璃氢,而是根據(jù)你自己的代碼實(shí)現(xiàn)(webView.loadUrl)狮辽,反之巢寡,webview內(nèi)部會(huì)幫你處理跳轉(zhuǎn);
簡(jiǎn)單舉個(gè)例子:這邊的http://3g.cib.com.cn/home/00000.html
會(huì)重定向到https://mobile.cib.com.cn/netbank/cn/index.html
椰苟,打印跳轉(zhuǎn)后的歷史堆棧:
- 使用webView.loadUrl,return true 方式
WebHistoryItemChromium[ mOriginalUrl=http://3g.cib.com.cn/home/00000.html, mUrl=http://3g.cib.com.cn/home/00000.html], WebHistoryItemChromium[ mOriginalUrl=https://mobile.cib.com.cn/netbank/cn/index.html, mUrl=https://mobile.cib.com.cn/netbank/cn/index.html]]]
- 使用默認(rèn)處理 return false 方式
WebHistoryItemChromium[ mOriginalUrl=http://3g.cib.com.cn/home/00000.html, mUrl=https://mobile.cib.com.cn/netbank/cn/index.html]]]
可以看到谦絮,前者生成了2條記錄须误,后者只有1條記錄,這樣使用webview.goBack就不會(huì)跳到重定向頁(yè)面了京痢。另外考慮到類似tel:xxx
的url,webview無(wú)法識(shí)別的問(wèn)題臭家,需要對(duì)鏈接做一次過(guò)濾:
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (TextUtil.isEmpty(url)) {
return true;
}
if (url.startsWith("http://") || url.startsWith("https://")) {
return false;
} else {
//todo 自行處理
return true;
}
}
二方淤、通過(guò)一個(gè)頁(yè)面重復(fù)多次進(jìn)行攔截返回的頁(yè)面
問(wèn)題描述:例如https://3g.cib.com.cn/app/00282.html
這個(gè)頁(yè)面携茂,webview在跳轉(zhuǎn)到這個(gè)頁(yè)面時(shí),其實(shí)連續(xù)跳轉(zhuǎn)了2次讳苦,這個(gè)導(dǎo)致返回的會(huì)到前面一個(gè)相同的頁(yè)面壳繁,而之后又會(huì)相同的頁(yè)面產(chǎn)生棋凳,導(dǎo)致返回不了子寓。
解決:這個(gè)問(wèn)題解決其實(shí)很簡(jiǎn)單,webview跳轉(zhuǎn)返回除了goBack之外還有一個(gè)goBackOrForward方法
/**
* Goes to the history item that is the number of steps away from
* the current item. Steps is negative if backward and positive
* if forward.
*
* @param steps the number of steps to take back or forward in the back
* forward list
*/
public void goBackOrForward(int steps) {
checkThread();
mProvider.goBackOrForward(steps);
}
這個(gè)方法可以直接前進(jìn)或者返回多級(jí)袜爪,于是我們只要在返回時(shí)檢測(cè)歷史隊(duì)列中的相同url,直接跳過(guò)相同的url穗慕,返回2級(jí)就可以了goBackOrForward(-2)
三、onPageFinished監(jiān)聽(tīng)不到url跳轉(zhuǎn)
問(wèn)題描述:某些情況下怀各,webview在處理頁(yè)面一些內(nèi)部跳轉(zhuǎn)時(shí)onPageFinished沒(méi)有調(diào)用
解決:在onLoadResource監(jiān)聽(tīng),onLoadResource是資源加載寿酌,只要頁(yè)面資源變化,這個(gè)方法就會(huì)執(zhí)行
四硕蛹、webview銷毀
問(wèn)題描述:webview資源不銷毀會(huì)引起內(nèi)存泄露法焰,相關(guān)部分可以查看更加具體的文章 鏈接
解決:
if (webView != null) {
//webView.removeJavascriptInterface("android"); //刪除jsbridge
webView.setWebChromeClient(null);
webView.setWebViewClient(null);
webView.getSettings().setJavaScriptEnabled(false);
webView.clearCache(true);
webView.removeAllViews();
if (webView.getParent() instanceof ViewGroup) {
((ViewGroup) webView.getParent()).removeView(webView);
}
webView.destroy();
}
五埃仪、支持加載Https和Http混合模式
問(wèn)題描述:在Android5.0以下卵蛉,默認(rèn)是采用的MIXED_CONTENT_ALWAYS_ALLOW模式傻丝,即總是允許WebView同時(shí)加載Https和Http;而從Android5.0開(kāi)始,默認(rèn)用MIXED_CONTENT_NEVER_ALLOW模式幌氮,即總是不允許WebView同時(shí)加載Https和Http。
解決:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
set.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
}
六韭畸、js對(duì)象注入漏洞
問(wèn)題描述:4.2以前胰丁,通過(guò)JavaScript锦庸,可以訪問(wèn)當(dāng)前設(shè)備的SD卡上面的任何東西蒲祈,甚至是聯(lián)系人信息,短信等扬卷。可以看相關(guān)報(bào)道:烏云
六咱枉、js 方法的混淆
問(wèn)題描述:webview與js交互的時(shí)候徒恋,需要使用自定義方法入挣,這個(gè)方法名是不能被混淆的
解決:
為了解決上述js漏洞問(wèn)題,原則上所有定義的js方法都應(yīng)該加上@JavascriptInterface 风皿,而這些被加了@JavascriptInterface 的方法keep起來(lái)就好了
-keepattributes *Annotation*
-keepattributes *JavascriptInterface*
-keep public class org.mq.study.webview.DemoJavaScriptInterface{
public <methods>;
}