上次笔记记录了一下webview呈现相关的,这次记录一下我开发过程中出现的一些问题及解决。
一、交互:android和js的交互,android调用js很简单,一句话
webView.loadUrl("javascript:webShow(‘ " + msg + "')");//webShow为web端定义的方法,msg为传入的值,注:必须有单引号转义才能传入
js调用android一般来说有三种方式:
1)第一种就是最常见的设计webview支持js操作,然后传给js一个类的参数,然后用这个参数调用这个类下的方法。
需要注意的是这个类下的方法现版本都需要加上@JavascriptInterface,还有一点就是类必须是公共的,另外打包混淆的时候记住千万不要混淆交互方法。
webView.getSettings()setJavaScriptEnabled(true);//webview设置支持js
webView.addJavascriptInterface(new JsAndAndroid(), "JsAndAndroid");//js使用引号内参数调用JsAndAndroid类中方法
public class JsAndAndroid{
@JavascriptInterface
public vioid takeAndroid(){
}
}
2)第一种交互方法是最常用的,但也是webview不太安全的原因。而第二种方法,也算比较常见,主要用在跳转链接时,(注意:只有真正跳转链接了才会调用此方法, 单页面内的跳转此方法不会调用)用shouldOverrideUrlLoading方法拦截链接,做相应处理,这个方法我在笔记一中提过,重写此方法实现链接在自己的webview上呈现,这次我结合一下使用webview常遇到的问题记录一下此方法更高级的用法。
首先此方法的默认返回值为super.shouldOverrideUrlLoading(view, url),这个返回值的意思是不自己处理,效果就是调用手机其他浏览器,我们可以把返回值改为false,这个返回值的含义是webview自己处理,但我们自己写的代码不干涉,效果就是webview呈现链接页面,而有时常遇到的问题就是点击跳转链接无反应,或者跳转页面不是自己所期望的,我们就可以把返回值改为true,意思是我们代码控制加载,在上面加上view.stop();view.loadUrl(url),就可以正常跳转了(PS:现android高版本常常出现webview内部跳转链接出错的问题,此方法能有效解决;)。另外还有一点,android webview内部不可以实现文件浏览,ios是可以的,本地查看需要在线解析服务,Google等免费服务被墙在了外面,无法使用,所以可以在此方法中检测文件链接,返回true自己做处理。
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
//return super.shouldOverrideUrlLoading(view,url);//手机本地浏览器打开,不推荐
//return false;//webview打开并自己处理,不太推荐
return true;//本地打开,自己处理,推荐,尤其现在android新版推行速度愈发快了
}
3)第三种是WebChromeClient类中的方法:onJsAlert,onJsPrompt,onJsConfirm。这三个方法的主要作用是支持web页面弹窗,笔记一中也有提及,webview是不支持web页面中自己的弹窗的,需要重写这三个方法支持不同的弹窗,可以通过这种方法实现接收js传过来的值,在android中判断并执行操作,网上也有一些这方面的库,有兴趣的可以自己去看下,我知道的也全是网上所见,尊重作者,就不copy了。
二、加载监视:我们加载一个链接的时候,往往需要在加载开始,结束或者出错的情况下做出相应处理,这些其实很简单,就是几个方法,可能唯一的就是有一个方法选择上的问题。
加载开始:WebvVewClient类中的onPageStarted(WebView view,String url,Bitmap favicon),链接开始加载,根据需求看着操作吧。
加载出错:WebvVewClient类中的onReceivedError(WebView view,int errorCode,String description,String failingUrl),链接加载出错了,这个一般都会都用,当链接加载出错时往往都有一个错误提示页面,可以在这个方法中跳转进入错误提示页面。
加载完成:WebvVewClient类中的onPageFinished(WebView view,String url),链接加载完成,一般加载链接时会给用户一个反馈,可能就是一个正在加载的简单提示,这个提示什么时候消失呢,可以在这个方法中处理,但一般不在这个方法中处理。
加载进度:WebChromeClient类中的onProgressChanged(WebView view,int newProgress),newProgress表示加载的进度,从0-100,当onPageFinished执行完成后,进度就会到达100,需要注意的是,无论是执行了onPageFinished,还是onProgressChanged方法中进度到达100,页面都不会立即呈现,白屏时间取决与机器的处理速度,这是因为这些方法监测的只是链接加载情况,加载完了具体什么时候能完全呈现是无法监测的,哪怕是强大的鹅场的app,也无法做到进度加载完,页面即刻呈现。
三、拦截所有url网络请求,这个主要就是一个方法,具体需求作用我还没有用到过,但用这个方法检查过错误,也是WebviewClient中的一个方法,shouldInterceptRequest(WebView view,WebResourceRequest request)和shouldInterceptRequest(WebView view,String url),两个方法差不多,点进WebResourceRequest类的源码看也很简单,主要就是连接所有的请求,比如一个web页面,这里面可能会请求很多个图片链接,很多个js等等,当一个请求出错时,我们可以用此方法定位具体出错的链接。
四、web调用android系统应用:这个需求最常见的就是web页面上传头像,调用本地图库相机,这中请求需要在WebChromeClient类中的onShowFileChooser方法中捕获,捕获到请求,再去调用系统图库相机就简单了吧,然后返回图片uri什么的就都好说了(其实我自己这块也不熟练,后续这块内容补上吧。。。。。。)
五、总结:基本结合webview笔记一和二就能写出来一个web app中android的壳子了,一个控件而已,肯定是不算难,但其中一个人踩坑的经历真是痛不欲生,一星期就研究一个效果,真是抓头发啊,目前也有很多优秀的开源方案可以替换webview,其中做的最好的就是crosswalk和鹅厂的TBS,但都要单独集成浏览器内核,TBS还好说,只要你手机有鹅厂产品(微信,手q,qq浏览器等),并打开过一次网页,你手机就已经自动下载了一个几十兆的内核(是不是听起来也挺蛋疼的),而crosswalk就必须加到app中了,就算单集成arm的内核,也得三十多兆,基本一个原生app大小了。TBS的话,最明显的优势就是视频播放比webview爽太多,而且继承了文档浏览功能,不过始终是别人的产品,而且国内免费开源的东西,其文档往往很烂,遇到错误更不知所措。我可以很明确的说,这两个三方使用起来,并不比webview简单,就是效果可能稍强一些。