Android WebView基礎(chǔ)應(yīng)用詳解
附GitHub源碼:WebViewExplore
一、WebView的基礎(chǔ)配置
WebSettings ws = getSettings(); ws.setBuiltInZoomControls(true);// 隱藏縮放按鈕 ws.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);// 排版適應(yīng)屏幕 ws.setUseWideViewPort(true);// 可任意比例縮放 ws.setLoadWithOverviewMode(true);// setUseWideViewPort方法設(shè)置webview推薦使用的窗口。setLoadWithOverviewMode方法是設(shè)置webview加載的頁(yè)面的模式。 ws.setSaveFormData(true);// 保存表單數(shù)據(jù) ws.setJavaScriptEnabled(true); // 是否能與JS交互【如果業(yè)務(wù)中無(wú)JS交互,建議將此項(xiàng)關(guān)閉】 ws.setGeolocationEnabled(true);// 啟用地理定位【如果業(yè)務(wù)中無(wú)此業(yè)務(wù),建議將此項(xiàng)關(guān)閉】 ws.setDomStorageEnabled(true); ws.setJavaScriptCanOpenWindowsAutomatically(true);//允許JS Alert對(duì)話框等打開(kāi)【如果業(yè)務(wù)中無(wú)此業(yè)務(wù),建議將此項(xiàng)關(guān)閉】 ws.setSupportMultipleWindows(true);// 新加
二、WebView支持播放音樂(lè)
//是否支持播放音樂(lè) ws.setPluginState(WebSettings.PluginState.ON); ws.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); //是否需要用戶點(diǎn)擊才播放 ws.setMediaPlaybackRequiresUserGesture(true);
三、WebView支持視頻播放
四、WebChromeClient
/** * WebChromeClient是輔助WebView處理Javascript的對(duì)話框,網(wǎng)站圖標(biāo),網(wǎng)站title,加載進(jìn)度等 */ setWebChromeClient(new XWebChromeClient());
其具體覆蓋方法如下:?
public static class XWebChromeClient extends WebChromeClient {
/**
* 獲取網(wǎng)頁(yè)加載進(jìn)度
* @param view
* @param newProgress
*/
@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
Log.d(TAG, "onProgressChanged---> newProgress:" + newProgress);
}
/**
* 獲取網(wǎng)站標(biāo)題 (Android 6.0 以下通過(guò)title獲取【捕捉HTTP ERROR】)
*
* @param view
* @param title
*/
@Override
public void onReceivedTitle(WebView view, String title) {
super.onReceivedTitle(view, title);
Log.d(TAG, "onReceivedTitle---> title:" + title);
if (webTitleCallBack != null) {
webTitleCallBack.onReceived(title);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (title.contains("404") || title.contains("500") || title.contains("Error")) {
view.loadUrl("about:blank"); // 避免出現(xiàn)默認(rèn)的錯(cuò)誤界面
// 在這里可以考慮顯示自定義錯(cuò)誤頁(yè)
// showErrorPage();
}
}
}
/**
* 網(wǎng)站圖標(biāo)
*
* @param view
* @param icon
*/
@Override
public void onReceivedIcon(WebView view, Bitmap icon) {
super.onReceivedIcon(view, icon);
Log.d(TAG, "icon:" + icon);
}
/**
* 攔截Alert彈框
*
* @param view
* @param url
* @param message
* @param result
* @return
*/
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
Log.d(TAG, "onJsAlert");
return super.onJsAlert(view, url, message, result);
}
/**
* 攔截 confirm彈框
*
* @param view
* @param url
* @param message
* @param result
* @return
*/
@Override
public boolean onJsConfirm(WebView view, String url, String message, JsResult result) {
Log.d(TAG, "onJsConfirm");
return super.onJsConfirm(view, url, message, result);
}
/**
* 打印console信息
*
* @param consoleMessage
* @return
*/
@Override
public boolean onConsoleMessage(ConsoleMessage consoleMessage) {
Log.d(TAG, "onConsoleMessage");
return super.onConsoleMessage(consoleMessage);
}
/**
* 該方法在web頁(yè)面請(qǐng)求某個(gè)尚未被允許或拒絕的權(quán)限時(shí)回調(diào)
*
* @param request
*/
@Override
public void onPermissionRequest(PermissionRequest request) {
super.onPermissionRequest(request);
Log.d(TAG, "onPermissionRequest---> request:" + request);
}
}
五、WebViewClient
/** * WebViewClient就是幫助WebView處理各種通知、請(qǐng)求事件的 */ setWebViewClient(new XWebViewClient());
其具體覆蓋方法如下:?
public class XWebViewClient extends WebViewClient {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
Log.d(TAG, "onPageStarted---> url:" + url);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
Log.d(TAG, "onPageFinished---> url:" + url);
}
/**
* WEB頁(yè)面加載錯(cuò)誤時(shí)回調(diào),這些錯(cuò)誤通常都是由無(wú)法與服務(wù)器正常連接引起的。
*
* @param view
* @param errorCode
* @param description
* @param failingUrl
*/
//Android6.0之前的方法 【在新版本中也可能被調(diào)用,所以加上一個(gè)判斷,防止重復(fù)顯示】
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
super.onReceivedError(view, errorCode, description, failingUrl);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// 斷網(wǎng)或者網(wǎng)絡(luò)連接超時(shí)
showReceivedErrorPage(view, errorCode, description, failingUrl);
}
}
/**
* 當(dāng)服務(wù)器返回錯(cuò)誤碼時(shí)回調(diào)
*
* @param view
* @param request
* @param errorResponse
*/
//6.0新增方法
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
super.onReceivedHttpError(view, request, errorResponse);
// 這個(gè)方法在6.0才出現(xiàn)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
int statusCode = 0;
if (errorResponse != null) {
statusCode = errorResponse.getStatusCode();
}
Log.d(TAG, "onReceivedHttpError---> code = " + statusCode);
if (404 == statusCode || 500 == statusCode) {
view.loadUrl("about:blank");// 避免出現(xiàn)默認(rèn)的錯(cuò)誤界面
// 在這里可以考慮顯示自定義錯(cuò)誤頁(yè)
// showErrorPage();
}
}
}
}
還有如下方法,在使用時(shí)尤其要注意:
1、重定向問(wèn)題
在 shouldOverrideUrlLoading 方法可進(jìn)行重定向的判斷跟處理:
/**
* 重定向分析:
*
* @param view
* @param request
* @return true: 表示當(dāng)前url已經(jīng)加載完成,即使url還會(huì)重定向都不會(huì)再進(jìn)行加載
* false: 表示此url默認(rèn)由系統(tǒng)處理,該重定向還是重定向,直到加載完成
*/
//Android7.0之后的方法
@RequiresApi(api = Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
Log.d(TAG, "shouldOverrideUrlLoading new---> url:" + request.getUrl());
analysisRequest(request);
String url = (request.getUrl()).toString();
boolean hasGesture = request.hasGesture();
boolean isRedirect = request.isRedirect();
return shouldOverride(view, url);
}
其WebView重定向需要考慮的case如下:
1、是最普通的http url【不含.doc .apk等下載url】
2、下載的http url【如.doc .apk等】
3、非http或https自定義url 【如 "weixin:// alipays://等】
【deprecated】如果期望打開(kāi)web頁(yè)時(shí)不自動(dòng)喚起app,可通過(guò) request.hasGesture()【是否】點(diǎn)擊來(lái)判斷,如果是true才喚起第三方app。(此種方案有時(shí)不太準(zhǔn)確,故可采用下面方案)
【recommend】定義一個(gè)boolean值如:isClickWeb = false,在onTouchEvent DOWN方法中,將其賦值為true。在必要位置添加判斷即可【具體可參考代碼】
/**
* 自定義重定向處理方法
* @param view
* @param url
* @return
*/
private boolean shouldOverride(WebView view, final String url) {
//業(yè)務(wù)需要可做處理
redirectionJudge(view, url);
if (SchemeUtil.isHttpProtocol(url) && !SchemeUtil.isDownloadFile(url)) {
return false;
}
if (SchemeUtil.isHttpProtocol(url) && SchemeUtil.isDownloadFile(url)) {
if (isClickWeb) {
openDialog(url);
return true;
}
}
if (!SchemeUtil.isHttpProtocol(url)) {
boolean isValid = SchemeUtil.isSchemeValid(context, url);
if (isValid && isClickWeb) {
openDialog(url);
} else {
Log.d(TAG, "此scheme無(wú)效[比如手機(jī)中未安裝該app]");
}
return true;
}
return false;
}
2、實(shí)現(xiàn)預(yù)加載
在 shouldInterceptRequest 方法中可實(shí)現(xiàn)資源預(yù)加載:
/**
* 【實(shí)現(xiàn)預(yù)加載】
* 有時(shí)候一個(gè)頁(yè)面資源比較多,圖片,CSS,js比較多,還引用了JQuery這種龐然巨獸,
* 從加載到頁(yè)面渲染完成需要比較長(zhǎng)的時(shí)間,有一個(gè)解決方案是將這些資源打包進(jìn)APK里面,
* 然后當(dāng)頁(yè)面加載這些資源的時(shí)候讓它從本地獲取,這樣可以提升加載速度也能減少服務(wù)器壓力。
*/
@Nullable
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
if (request == null) {
return null;
}
String url = request.getUrl().toString();
Log.d(TAG, "shouldInterceptRequest---> " + url);
return getWebResourceResponse(url);
}
protected WebResourceResponse getWebResourceResponse(String url) {
//此處[tag]等需要跟服務(wù)端協(xié)商好,再處理
if (url.contains("[tag]")) {
try {
String localPath = url.replaceFirst("^http.*[tag]\\]", "");
InputStream is = getContext().getAssets().open(localPath);
Log.d(TAG, "shouldInterceptRequest: localPath " + localPath);
String mimeType = "text/javascript";
if (localPath.endsWith("css")) {
mimeType = "text/css";
}
return new WebResourceResponse(mimeType, "UTF-8", is);
} catch (IOException e) {
e.printStackTrace();
return null;
}
} else {
return null;
}
}
3、增加錯(cuò)誤頁(yè)面展示限制
在onReceivedError方法中,通過(guò) request.isForMainFrame() || url.equals(getUrl() 判斷來(lái)盡可能少的減少錯(cuò)誤頁(yè)面的展示。即當(dāng)錯(cuò)誤頁(yè)面是主頁(yè)面時(shí)才展示錯(cuò)誤頁(yè),避免整個(gè)頁(yè)面中如某個(gè)icon等展示錯(cuò)誤,導(dǎo)致影響整個(gè)頁(yè)面的情況【如網(wǎng)易音樂(lè)的某些URL,就曾有出現(xiàn)這種情況,通過(guò)這種方式可以避免錯(cuò)誤頁(yè)面展示】。
/**
* 此方法中加載錯(cuò)誤頁(yè)面的時(shí)候,需要判斷下 isForMainFrame 是否為true 亦或者 當(dāng)前url跟加載的url是否為同一個(gè)url。
*
* @param view
* @param request
* @param error
*/
//Android6.0之后的方法
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
super.onReceivedError(view, request, error);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String url = request.getUrl().toString();
int errorCode = error.getErrorCode();
String description = error.getDescription().toString();
Log.d(TAG, "onReceivedError---> " + " url:" + url + "errorCode:" + errorCode + " description:" + description + " failingUrl:" + url + " request.isForMainFrame():" + request.isForMainFrame());
// 如果當(dāng)前網(wǎng)絡(luò)請(qǐng)求是為main frame創(chuàng)建的,則顯示錯(cuò)誤頁(yè)
if (request.isForMainFrame() || url.equals(getUrl())) {
showReceivedErrorPage(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString());
}
}
}
4、解決頁(yè)面白屏問(wèn)題
當(dāng)SSL證書(shū)無(wú)效時(shí),會(huì)導(dǎo)致白屏問(wèn)題,可在 onReceivedSslError 方法中添加 handler.proceed();
可解決白屏問(wèn)題:?
/**
* 【解決白屏問(wèn)題】
* 如SSL證書(shū)無(wú)效時(shí)調(diào)用
*
* @param view
* @param handler
* @param error
*/
@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
//此處處理可避免SSL證書(shū)無(wú)效的頁(yè)面白屏
handler.proceed();
super.onReceivedSslError(view, handler, error);
Log.d(TAG, "onReceivedSslError---> error = " + error);
}
以上就是Android WebView基礎(chǔ)應(yīng)用詳解的詳細(xì)內(nèi)容,更多關(guān)于Android WebView的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- Android WebView輸入框被檔問(wèn)題升級(jí)解析
- 淺談Android開(kāi)發(fā)Webview的Loading使用效果
- Android?webView加載數(shù)據(jù)時(shí)內(nèi)存溢出問(wèn)題及解決
- Android?WebView預(yù)渲染介紹
- Android?WebView軟鍵盤(pán)遮擋輸入框方案詳解
- Android WebView如何判斷是否滾動(dòng)到底部
- Android WebView控件基本使用示例
- Android WebView實(shí)現(xiàn)全屏播放視頻
- Android?WebView緩存機(jī)制優(yōu)化加載慢問(wèn)題
相關(guān)文章
Android Gridview布局出現(xiàn)滾動(dòng)條或組件沖突解決方法
這篇文章主要介紹了Android Gridview布局出現(xiàn)滾動(dòng)條或組件沖突解決方法,GridView是一個(gè)在二維可滾動(dòng)的網(wǎng)格中展示內(nèi)容的控件。網(wǎng)格中的內(nèi)容通過(guò)使用adapter自動(dòng)插入到布局中2022-07-07
Android實(shí)現(xiàn)上拉加載更多ListView(PulmListView)
這篇文章主要介紹了Android實(shí)現(xiàn)上拉加載更多ListView:PulmListView,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
Android實(shí)現(xiàn)短信驗(yàn)證碼輸入框
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)短信驗(yàn)證碼輸入框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
Android Studio OkHttpClient使用教程詳解
這篇文章主要介紹了Android Studio OkHttpClient使用教程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Android EditText輸入框?qū)崿F(xiàn)下拉且保存最近5個(gè)歷史記錄思路詳解
今天給大家介紹Android EditText輸入框?qū)崿F(xiàn)下拉且保存最近5個(gè)歷史記錄功能,android實(shí)現(xiàn)文本框下拉利用sharedpreferences來(lái)保存每次app啟動(dòng)和關(guān)閉時(shí)已經(jīng)填寫(xiě)的數(shù)值,具體代碼跟隨小編一起看看吧2021-07-07
android的消息處理機(jī)制(圖文+源碼分析)—Looper/Handler/Message
這篇文章寫(xiě)的非常好,深入淺出;android的消息處理機(jī)制(圖+源碼分析)—Looper,Handler,Message是一位大三學(xué)生自己剖析的心得,感興趣的朋友可以了解下哦,希望對(duì)你有所幫助2013-01-01
Android?手寫(xiě)RecyclerView實(shí)現(xiàn)列表加載
這篇文章主要介紹了Android?手寫(xiě)RecyclerView實(shí)現(xiàn)列表加載,涉及到列表的需求,肯定第一時(shí)間想到RecyclerView,即便是自定義View,那么RecyclerView也會(huì)是首選,為什么會(huì)選擇RecyclerView而不是ListView,主要就是RecyclerView的內(nèi)存復(fù)用機(jī)制,這也是RecyclerView的核心?2022-08-08
Android模糊處理實(shí)現(xiàn)圖片毛玻璃效果
這篇文章主要介紹了Android模糊處理實(shí)現(xiàn)圖片毛玻璃效果,需要的朋友可以參考下2016-02-02
Android編程實(shí)現(xiàn)根據(jù)不同日期計(jì)算天數(shù)差的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)根據(jù)不同日期計(jì)算天數(shù)差的方法,涉及Android調(diào)用日期類Calendar實(shí)現(xiàn)時(shí)間運(yùn)算的相關(guān)技巧,需要的朋友可以參考下2016-03-03

