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支持视频播放
四、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的资料请关注其它相关文章!
推荐阅读
-
Android开发笔记之:AsyncTask的应用详解
-
详解Android Webview加载网页时发送HTTP头信息
-
Android之PreferenceActivity应用详解
-
Android 动画之ScaleAnimation应用详解
-
Android 动画之RotateAnimation应用详解
-
Android 动画之TranslateAnimation应用详解
-
Android之PreferenceActivity应用详解(2)
-
Android 动画之AlphaAnimation应用详解
-
Android的webview支持HTML5的离线应用功能详细配置
-
Android Naive与WebView的互相调用详解