Android|Android WebView基础应用详解

目录

  • 一、WebView的基础配置
  • 二、WebView支持播放音乐
  • 三、WebView支持视频播放
  • 四、WebChromeClient
  • 五、WebViewClient
    • 1、重定向问题
    • 2、实现预加载
    • 3、增加错误页面展示限制
    • 4、解决页面白屏问题
附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*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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*/@Overridepublic boolean onConsoleMessage(ConsoleMessage consoleMessage) {Log.d(TAG, "onConsoleMessage"); return super.onConsoleMessage(consoleMessage); } /*** 该方法在web页面请求某个尚未被允许或拒绝的权限时回调** @param request*/@Overridepublic void onPermissionRequest(PermissionRequest request) {super.onPermissionRequest(request); Log.d(TAG, "onPermissionRequest---> request:" + request); }}


五、WebViewClient
/** * WebViewClient就是帮助WebView处理各种通知、请求事件的 */setWebViewClient(new XWebViewClient());

其具体覆盖方法如下:
public class XWebViewClient extends WebViewClient { @Overridepublic void onPageStarted(WebView view, String url, Bitmap favicon) {super.onPageStarted(view, url, favicon); Log.d(TAG, "onPageStarted---> url:" + url); } @Overridepublic 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之前的方法 【在新版本中也可能被调用,所以加上一个判断,防止重复显示】@Overridepublic 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)@Overridepublic 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)@Overridepublic 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@Overridepublic 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)@Overridepublic 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*/@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {//此处处理可避免SSL证书无效的页面白屏handler.proceed(); super.onReceivedSslError(view, handler, error); Log.d(TAG, "onReceivedSslError---> error = " + error); }

【Android|Android WebView基础应用详解】以上就是Android WebView基础应用详解的详细内容,更多关于Android WebView的资料请关注脚本之家其它相关文章!

    推荐阅读