您的位置:首页 > 移动开发 > Android开发

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方法

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的方法请留言发链接,小弟不胜感激!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android webview