Android WebView-H5交互上传文件(包括图片)
来源:互联网 发布:移动大数据公司有哪些 编辑:程序博客网 时间:2024/05/21 06:56
WebView 在4.4前后的区别非常大, 比如对URL跳转的格式, 对JS的注入声明等等, 4.4以后的WebView 已经是chromium内核, 有多强大就无需我赘述. 说这些, 其实也是为了说明也因为WebView的前后变化太大了, 所以在低版本和版本上, WebView上传文件的方式都略有不同, 而且在安卓4.4的一些设备上难以保证所有机型都成功。导读->,
- Android HTML打开相册上传照片
- 扩充 webview 防止js注入
- 解决 android webview 在4.4系统上无法使用情况
第一部分:注入JS脚本监听,网页中某个上传图片按钮的事件。
这里以知乎“写文章”功能的上传图片为例子,如图咱们看一下知乎上传图片的网页代码:
(1)废话不多说,知乎上传图片div标签对应的事件HTML代码为:
<input type="file" accept=".jpeg, .jpg, .png" name="upload_file" id="js-title-img-input">
然后我们可以注入我们自己的JS脚本了,来监听事件了,相信你经过前面文章JS交互的介绍对这里内容已经很熟了。JS脚本如下。
String onclick = "onclick";String[] abc = {"a", "b"};String replaceMethd = "obj.zhihuPicclick();return false;";String href = "href";String replaceLink = "javascript:;";jsFuction.append("(function()") .append("{") .append("document.getElementById('").append("js-title-img-input") .append("').href").append("=") .append("'").append(replaceLink) .append("';") .append("document.getElementById('").append("js-title-img-input") .append("').setAttribute('").append(onclick) .append("','").append(replaceMethd) .append("');") .append("})()");
这里我给<input标签注入了onclick事件,跟href的链接。href直接赋值=javascipt:或者javascript:void(0),目的是为了防止<input>标签事件冲突,经过论证onclick事件的优先级高于href。
(2)android中注入,并监听事件
mWebView.addJavascriptInterface(new JavascriptInterface(), "obj");//或放到onPageFinshed方法。
注入以后,我们在 JavascriptInterface中的zhihuPicclick()可以监听到我们点击知乎页面中上传图片的事件,并事件自己的业务逻辑,保证篇幅不废话,下面接着H5上传图片。
第2:Android4.4系统处理
Android 4.4系统的webview 被禁掉了 需要使用js和android接口互调的形式,JS通过接口调用 android native的方法 , 由android 上传图片 ,成功后获取服务器返回的URL地址 (也就是第一部分),再由android webview调用JS接口 将图片的URL 传给JS显示。WebView的webkit中支持openFileChooser. 当WebView加载一个HTML页面, 点击按钮需要模拟form提交的方式去上传文件时, 就会回调如下方法:
openFileChooser(...)
然后在这个方法里接收并处理参数ValueCallback uploadMsg. 里面的 uri 就是所从本地选择的文件路径.
然后通过Intent的startActivityForResult(…) 方法跳转到系统选择文件的界面进行文件选择, 最后在([通用代码onActiviytReslut)
onActivityResult(int requestCode, int resultCode, Intent data)
方法中获取 data中的字符串路径, 并转换成Uri格式, 并传给uploadMsg 即可,也[通用代码onActiviytReslut]部分代码:
mUploadMessage.onReceiveValue(result);
这样, 接下来的上传工作, WebView会自动完成. 当然, 这是顺利的流程, 如果 onActivityResult(…) 中返回的 resultcode 不等于 Activity.RESULT_OK , 也要做一点处理, 不然再去点击第二次上传文件时是没有反应的. 类似这样:
if (resultCode != Activity.RESULT_OK) { if (mUploadMsg != null) { mUploadMsg.onReceiveValue(null); } return;}
传个 null 即可。OK, 上面就是4.4 以前的实现过程,保证篇幅不再多说。
第3:Android5.0以上系统处理
android5.0及以上的sdk变动时, webkit不再支持,但是google给我们提供了一个openFileChooser(...)替代方法。
public boolean onShowFileChooser(WebView webView, ValueCallback<uri[]> filePathCallback, FileChooserParams fileChooserParams) { return false;}
这个方法的参数跟 openFileChooser(…) 方法很像, 其实作用都是类似的, 只是 从 ValueCallback uploadMsg 变成了 ValueCallback filePathCallback, 还多了FileChooserParams类型参数. fileChooserParams 其实是一个属性封装的参数, 里面包含了acceptType, title等这样的文件属性, 名称等信息,并且这里可以上传多张图片,因为是复数的数组了。
所以, onShowFileChooser(…) 的使用方法跟 openFileChooser(…) 是很类似的, 这里看两者的使用区别:
private class MyWebClient extends WebChromeClient { // For Android 5.0+ @Override public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> valueCallback, android.webkit.WebChromeClient.FileChooserParams fileChooserParams) { //打开图库 } // For Android 3.0+ public void openFileChooser(ValueCallback uploadMsg) { //打开图库 } //3.0--版本 public void openFileChooser(ValueCallback uploadMsg, String acceptType) { openFileChooser(uploadMsg); } // For Android 4.1 public void openFileChooser(ValueCallback uploadMsg, String acceptType, String capture) { openFileChooser(uploadMsg); } }
最后我们通过 onActivityResult(…) ,也就是[通用代码onActiviytReslut]把图片显示出来。
@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK) { if (mUploadMsg != null) { mUploadMsg.onReceiveValue(null); } if (mUploadMsgForAndroid5 != null) { // for android 5.0+ mUploadMsgForAndroid5.onReceiveValue(null); } return; } switch (requestCode) { case REQUEST_CODE_IMAGE_CAPTURE: case REQUEST_CODE_PICK_IMAGE: { try { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { if (mUploadMsg == null) { return; } String sourcePath = ImageUtil.retrievePath(this, mSourceIntent, data); if (TextUtils.isEmpty(sourcePath) || !new File(sourcePath).exists()) { Log.e(TAG, "sourcePath empty or not exists."); break; } Uri uri = Uri.fromFile(new File(sourcePath)); mUploadMsg.onReceiveValue(uri); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (mUploadMsgForAndroid5 == null) { // for android 5.0+ return; } String sourcePath = ImageUtil.retrievePath(this, mSourceIntent, data); if (TextUtils.isEmpty(sourcePath) || !new File(sourcePath).exists()) { Log.e(TAG, "sourcePath empty or not exists."); break; } Uri uri = Uri.fromFile(new File(sourcePath)); mUploadMsgForAndroid5.onReceiveValue(new Uri[]{uri}); } } catch (Exception e) { e.printStackTrace(); } break; } }}
在网上了解到,这里需要注意几点内容,当然我并没有遇到。
- 上传的给图片的路径必须是Uri格式,在实际测试中发现,大部分手机能识别file开头的uri,但有少部分手机,如魅族,vivo不识别该种uri格式,只识别content开头的uri,因此,需要做兼容处理,调用的系统图库,默认返回的uri为content开头,兼容较好,自定义图库则为file开头。
- 在onActivityResult 中获取所选图片 uri,回调给 H5,有点小缺陷,图片可能需要压缩处理,因为在H5加载 base64本地图片是耗时操作,要先压缩图片。
4,代码混淆
这个我觉得有些意思啊,混淆后反编译别人APK的时候会给对手增加一些难度,你思考一件事情,如果你去反编译别人apk的时候,用apktools,dex2.dex.jar什么鬼的,但是很不幸,都是abcefgh,那你应该怎么办?留个坑在这里,待填
在混淆文件中添加
-keepclassmembers class * extends android.webkit.WebChromeClient { public void openFileChooser(...);}
Android studio 用户混淆文件: proguard-rules.pro
eclipse 用户混淆文件: proguard-android.txt
原文链接地址,点击查看
- Android WebView-H5交互上传文件(包括图片)
- Android webview h5 图片,拍照,视频上传
- Android webview与js交互上传图片
- Android webview 和H5交互选择图片功能
- webView支持H5上传图片
- webview支持H5上传图片
- Android WebView 支持H5图片上传<input type="file">
- Android WebView上传图片(base64)到H5(JS)
- Android WebView上传图片(base64)到H5(JS)
- android 通过webView上传文件给服务器(包括拍照)
- Android WebView关于图片/文件上传
- android使用webview上传文件(图片)
- Android WebView 上传图片文件有坑
- android webview 弹出图片选择器上传文件
- android webview设置以及与h5交互
- Android的webView和h5+js交互
- Android 嵌套H5 webview 与 js 交互
- Android Webview H5交互之LocalStorage
- 002-js基础笔记
- 批量替换Excel表格中非空的单元格的内容
- 点赞+1效果
- mac 上传文件到 linux
- 系统的学习大数据分布式计算spark技术
- Android WebView-H5交互上传文件(包括图片)
- Nuxt.js小试牛刀
- letcode 答案(Python)
- copy关键字
- 并查集学习
- Java多线程系列--“基础篇”09之 interrupt()和线程终止方式
- 调制hosts文件
- 数学笔记10——拉格朗日中值定理
- css -- 有用的css