Android WebView基礎應用詳解
附GitHub源碼:WebViewExplore
一、WebView的基礎配置
WebSettings ws = getSettings(); ws.setBuiltInZoomControls(true);// 隱藏縮放按鈕 ws.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);// 排版適應屏幕 ws.setUseWideViewPort(true);// 可任意比例縮放 ws.setLoadWithOverviewMode(true);// setUseWideViewPort方法設置webview推薦使用的窗口。setLoadWithOverviewMode方法是設置webview加載的頁面的模式。 ws.setSaveFormData(true);// 保存表單數據 ws.setJavaScriptEnabled(true); // 是否能與JS交互【如果業務中無JS交互,建議將此項關閉】 ws.setGeolocationEnabled(true);// 啟用地理定位【如果業務中無此業務,建議將此項關閉】 ws.setDomStorageEnabled(true); ws.setJavaScriptCanOpenWindowsAutomatically(true);//允許JS Alert對話框等打開【如果業務中無此業務,建議將此項關閉】 ws.setSupportMultipleWindows(true);// 新加
二、WebView支持播放音樂
//是否支持播放音樂 ws.setPluginState(WebSettings.PluginState.ON); ws.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); //是否需要用戶點擊才播放 ws.setMediaPlaybackRequiresUserGesture(true);
三、WebView支持視頻播放
Android WebView播放視頻(包括全屏播放)
四、WebChromeClient
/** * WebChromeClient是輔助WebView處理Javascript的對話框,網站圖標,網站title,加載進度等 */ setWebChromeClient(new XWebChromeClient());
其具體覆蓋方法如下:
public static class XWebChromeClient extends WebChromeClient { /** * 獲取網頁加載進度 * @param view * @param newProgress */ @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); Log.d(TAG, "onProgressChanged---> newProgress:" + newProgress); } /** * 獲取網站標題 (Android 6.0 以下通過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"); // 避免出現默認的錯誤界面 // 在這裡可以考慮顯示自定義錯誤頁 // showErrorPage(); } } } /** * 網站圖標 * * @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頁面請求某個尚未被允許或拒絕的權限時回調 * * @param request */ @Override public void onPermissionRequest(PermissionRequest request) { super.onPermissionRequest(request); Log.d(TAG, "onPermissionRequest---> request:" + request); } }
五、WebViewClient
/** * WebViewClient就是幫助WebView處理各種通知、請求事件的 */ 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頁面加載錯誤時回調,這些錯誤通常都是由無法與服務器正常連接引起的。 * * @param view * @param errorCode * @param description * @param failingUrl */ //Android6.0之前的方法 【在新版本中也可能被調用,所以加上一個判斷,防止重復顯示】 @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) { // 斷網或者網絡連接超時 showReceivedErrorPage(view, errorCode, description, failingUrl); } } /** * 當服務器返回錯誤碼時回調 * * @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); // 這個方法在6.0才出現 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");// 避免出現默認的錯誤界面 // 在這裡可以考慮顯示自定義錯誤頁 // showErrorPage(); } } } }
還有如下方法,在使用時尤其要註意:
1、重定向問題
在 shouldOverrideUrlLoading 方法可進行重定向的判斷跟處理:
/** * 重定向分析: * * @param view * @param request * @return true: 表示當前url已經加載完成,即使url還會重定向都不會再進行加載 * false: 表示此url默認由系統處理,該重定向還是重定向,直到加載完成 */ //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】如果期望打開web頁時不自動喚起app,可通過 request.hasGesture()【是否】點擊來判斷,如果是true才喚起第三方app。(此種方案有時不太準確,故可采用下面方案)
【recommend】定義一個boolean值如:isClickWeb = false,在onTouchEvent DOWN方法中,將其賦值為true。在必要位置添加判斷即可【具體可參考代碼】
/** * 自定義重定向處理方法 * @param view * @param url * @return */ private boolean shouldOverride(WebView view, final String url) { //業務需要可做處理 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無效[比如手機中未安裝該app]"); } return true; } return false; }
2、實現預加載
在 shouldInterceptRequest 方法中可實現資源預加載:
/** * 【實現預加載】 * 有時候一個頁面資源比較多,圖片,CSS,js比較多,還引用瞭JQuery這種龐然巨獸, * 從加載到頁面渲染完成需要比較長的時間,有一個解決方案是將這些資源打包進APK裡面, * 然後當頁面加載這些資源的時候讓它從本地獲取,這樣可以提升加載速度也能減少服務器壓力。 */ @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]等需要跟服務端協商好,再處理 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、增加錯誤頁面展示限制
在onReceivedError方法中,通過 request.isForMainFrame() || url.equals(getUrl() 判斷來盡可能少的減少錯誤頁面的展示。即當錯誤頁面是主頁面時才展示錯誤頁,避免整個頁面中如某個icon等展示錯誤,導致影響整個頁面的情況【如網易音樂的某些URL,就曾有出現這種情況,通過這種方式可以避免錯誤頁面展示】。
/** * 此方法中加載錯誤頁面的時候,需要判斷下 isForMainFrame 是否為true 亦或者 當前url跟加載的url是否為同一個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()); // 如果當前網絡請求是為main frame創建的,則顯示錯誤頁 if (request.isForMainFrame() || url.equals(getUrl())) { showReceivedErrorPage(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); } } }
4、解決頁面白屏問題
當SSL證書無效時,會導致白屏問題,可在 onReceivedSslError 方法中添加 handler.proceed();
可解決白屏問題:
/** * 【解決白屏問題】 * 如SSL證書無效時調用 * * @param view * @param handler * @param error */ @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { //此處處理可避免SSL證書無效的頁面白屏 handler.proceed(); super.onReceivedSslError(view, handler, error); Log.d(TAG, "onReceivedSslError---> error = " + error); }
以上就是Android WebView基礎應用詳解的詳細內容,更多關於Android WebView的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- Android WebView開發之WebView與Native交互
- Android 中 WebView 的基本用法詳解
- Android WebView開發之自定義WebView工具框
- Android開發使用WebView打造web app示例代碼
- Android webview加載H5方法詳細介紹