最近项目需求是H5调用安卓的方法选择图片或者打开照相机拍照,然后传给H5显示图片,最后由H5上传到服务器。查了一下资料,大概有以下几种方法:
- 利用WebChromeClient的openFileChooser(5.0+是onShowFileChooser)
- JS调用安卓端定义好的接口选择图片或者打开照相机,获取到图片信息(base64)之后,安卓端调用JS方法回调给H5
- JS调用安卓端定义好的接口选择图片或者打开照相机,安卓端上传图片给服务器,服务器返回图片的URL,最后安卓端调用JS方法把图片的URL传给H5
先来比较一下这三种方法:
第一种方法,看上去应该很好用,毕竟是系统原生方法,但是随着安卓系统版本的不断更新,WebChromeClient的openFileChooser方法返回的参数都有所改变,到了5.0+更是换了个名字,这都不是重点,重点是出了4.4这个奇葩,居然不支持openFileChooser,所以这个方法要做适配和解决4.4这个奇葩才可行。嫌麻烦的我怎么可能选这个方法呢(´Д`)解决方案可以参考以下两个链接的内容:
http://stackoverflow.com/questions/5907369/file-upload-in-webview/http://blog.csdn.net/mengzuixilou/article/details/48374971
第二种方法,是我最后采用了的方法,可能是因为我比较二,所以喜欢第二种方法吧。囧rz 主要的问题都是跟H5之间的交互,不过还是遇到部分机型传递不到数据的问题(图片流太大),后面将会详细讲解我最后的方案。
第三种方法,简单粗暴而且可行性很高,因为上传图片到服务器的方法已经很成熟了,所以基本不必担心传不到图片对应的URL给H5,而且传给H5的数据量少。但是,有个缺点就是要展示的图片不一定是要上传到服务器的,而是用户点击了“上传”按钮才会上传到服务器。所以,这个方法看起来有点别扭,最后还是没有用到这个方案。
下面将详细讲解第二种方法 <( ̄ ﹌  ̄)@m
首先,设置WebView使其支持JS调用JAVA方法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
其中OperationPresenter代码如下
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
H5只需要在这样调用即可
- 1
- 2
- 3
- 4
getPhoto就是JS定义的方法,需要安卓端回调使用的,定义如下
- 1
- 2
- 3
- 4
- 5
封装JSONObject并回调
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
大致流程如下:
JS调用了安卓的方法打开图库/照相机–>获取图片–>压缩–>转成base64–>封装成JSONObject–>调用JS方法回传图片数据
至于一些WebView的优化和设置、图片压缩、base64的转换等等可以参考网上的其他资料。
再说明一下为什么不直接传base64字符串,而是将它封装成JSON对象。因为当在部分性能比较差的手机上面(4.0真机、4.2模拟器),把base64这样长的字符串直接传给JS的话会出现像下面这样的问题
- 1
居然是一个我看不懂的JS错误,搜索了一下基本都没有范对应的错(PS:还是我不够细心看问题呢)后来无意间发现了这篇文章
http://blog.csdn.net/waww116529/article/details/52850018
主要原因就是图片流太大,不过作者应该是写错了一点,传JSON对象的时候,应该不用再加单引号或者双引号了,我试过加了是没反应的。像下面这样就可以了。