Android WebView上传图片(base64)到H5(JS)
2016-12-27 23:58
525 查看
最近项目需求是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方法
其中OperationPresenter代码如下
H5只需要在这样调用即可
getPhoto就是JS定义的方法,需要安卓端回调使用的,定义如下
封装JSONObject并回调
大致流程如下:
JS调用了安卓的方法打开图库/照相机–>获取图片–>压缩–>转成base64–>封装成JSONObject–>调用JS方法回传图片数据
至于一些WebView的优化和设置、图片压缩、base64的转换等等可以参考网上的其他资料。
再说明一下为什么不直接传base64字符串,而是将它封装成JSON对象。因为当在部分性能比较差的手机上面(4.0真机、4.2模拟器),把base64这样长的字符串直接传给JS的话会出现像下面这样的问题
居然是一个我看不懂的JS错误,搜索了一下基本都没有范对应的错(PS:还是我不够细心看问题呢)后来无意间发现了这篇文章
http://blog.csdn.net/waww116529/article/details/52850018
主要原因就是图片流太大,不过作者应该是写错了一点,传JSON对象的时候,应该不用再加单引号或者双引号了,我试过加了是没反应的。像下面这样就可以了。
有更多更好的WebView上传图片到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方法
private OperationPresenter operationPresenter = new OperationPresenter(this); private WebView mWebView; //设置WebView支持JS mWebView.getSettings().setJavaScriptEnabled(true); //添加JS可调用的实例对象,第二个参数为JS可用的对象名 mWebView.addJavascriptInterface(operationPresenter, "operation")
其中OperationPresenter代码如下
public class OperationPresenter { private IOperationView view; private String methodName; public OperationPresenter(IOperationView view) { this.view = view; } /** * 选择图片 * * @param methodName JS方法名 */ @JavascriptInterface public void choosePhoto(String methodName) { this.methodName = methodName; view.onChoosePhoto(); } /** * 打开照相机 * * @param methodName JS方法名 */ @JavascriptInterface public void openCamera(String methodName) { this.methodName = methodName; view.onOpenCamera(); } /** * 部分低端机可能会因为字符串太长而不能直接传base64 * 需要把base64封装到JSON对象中 * * @param base64JSONObject 包含base64的JSON对象 */ public void sendPhoto(WebView webView, JSONObject base64JSONObject) { webView.loadUrl("javascript:" + methodName + "(" + base64JSONObject + ")"); } }
H5只需要在这样调用即可
//选择图片 window.opreation.choosePhoto('getPhoto') //打开照相机 window.opreation.openCamera('getPhoto')
getPhoto就是JS定义的方法,需要安卓端回调使用的,定义如下
function getPhoto(response) { //因为response是JSON对象,所以直接通过key(img)获取value response.img //......后面省略 }
封装JSONObject并回调
//获取Bitmap并用自己封装的工具类解释成base64 String baseData = ImgUtils.bitmap2Base64(bitmap); if (!TextUtils.isEmpty(baseData)) { JSONObject jsonObject = new JSONObject(); try { jsonObject.put("img", "data:image/png;base64," + baseData); operationPresenter.sendPhoto(mWebView, jsonObject); } catch (JSONException e) { //TODO } }
大致流程如下:
JS调用了安卓的方法打开图库/照相机–>获取图片–>压缩–>转成base64–>封装成JSONObject–>调用JS方法回传图片数据
至于一些WebView的优化和设置、图片压缩、base64的转换等等可以参考网上的其他资料。
再说明一下为什么不直接传base64字符串,而是将它封装成JSON对象。因为当在部分性能比较差的手机上面(4.0真机、4.2模拟器),把base64这样长的字符串直接传给JS的话会出现像下面这样的问题
Console: Uncaught SyntaxError: Unexpected token ILLEGAL at null:1
居然是一个我看不懂的JS错误,搜索了一下基本都没有范对应的错(PS:还是我不够细心看问题呢)后来无意间发现了这篇文章
http://blog.csdn.net/waww116529/article/details/52850018
主要原因就是图片流太大,不过作者应该是写错了一点,传JSON对象的时候,应该不用再加单引号或者双引号了,我试过加了是没反应的。像下面这样就可以了。
webView.loadUrl("javascript:" + methodName + "(" + base64JSONObject + ")");
有更多更好的WebView上传图片到H5的方法请留言发链接,小弟不胜感激!
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件