WebView 上传文件 WebChromeClient之openFileChooser函数
原链接:http://blog.saymagic.cn/2015/11/08/webview-upload.html?utm_source=tuicool&utm_medium=referral
从零开始
我们在xml中写入一个简单的Webview组件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<WebView
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_margin="5dp"></WebView>
</RelativeLayout>
然后在Java代码中使用其加载一个能够提供上传服务的URL:
WebView webview = (WebView) findViewById(R.id.webview);
webview.loadUrl(A_UPLOAD_URL);
之后,要加网络权限:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
如果想让Webview能够访问本地资源,SD卡的读写权限也是避免不了的:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
最后,我们运行,会发现根本不能访问本地资源。Why?
让我们来填补第一个坑:
支持上传文件
Webview执行上传操作的逻辑是这样的:首先准备上传时会回调WebChromeClient
类下的openFileChooser
方法,在这个方法中给我们机会发起Intent来打开支持提供文件的第三方应用,最后在onActivityResult
回调中将第三方应用提供的内容通过一个叫做ValueCallback
的参数返回给Webview(详细点来说:ValueCallback是在openFileChooser
方法里由webview提供给我们的,里面包裹一个Uri,我们在onActivityResult
里将选中的Uri反馈给ValueCallback
,这时候相当于Webview就知道我们选择了什么文件),因此,我们需要为Webview设置一个提供openFileChooser
方法的WebChromeClient
,这个方法在不同版本的Android中参数是不同的,为此我们一般需要写三个重载函数,大致像这个样子:
private ValueCallback<Uri> mUploadMessage;
//设置`WebChromeClient`:
webview.setWebChromeClient(new WebChromeClient(){
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg)");
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MainActivity.this.startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}
public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
Log.d(TAG, "openFileChoose( ValueCallback uploadMsg, String acceptType )");
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MainActivity.this.startActivityForResult(
Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE);
}
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
Log.d(TAG, "openFileChoose(ValueCallback<Uri> uploadMsg, String acceptType, String capture)");
mUploadMessage = uploadMsg;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MainActivity.this.startActivityForResult( Intent.createChooser( i, "File Browser" ), MainActivity.FILECHOOSER_RESULTCODE );
}
});
//onActivityResult回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
}
还有重要的一点:如果这个上传操作涉及到JS操作,别忘记对Webview开启对JS的支持:
WebSettings settings = webview.getSettings();
settings.setJavaScriptEnabled(true);
这样,打个debug包测试看以下,不出意外我们的Webview应该可以支持上传操作了。
别高兴得太早,如果这个时候产品要将release包推向市场,当你把release包交给产品时,你会发现你的Webview又不能上传了,什么情况?
请听Webview上传操作的第二个坑。
支持release版
debug版是好的,为什么release就不行了呢?准确的说,开启了混淆的release包是不可以的,究其原因在于,openFileChooser
方法并不是WebChromeClient
的对外开放的方法,因此这个方法会被混淆,解决办法也比较简单,只需要在混淆文件里控制一下即可:
-keepclassmembers class * extends android.webkit.WebChromeClient{
public void openFileChooser(...);
}
好了,我们的Webview可以作为应用内的一个部分对外发布了,等等,有5.0以上用户反映用不了?纳尼????
别回心,来看看这第三个坑。
支持5.0
在5.0发布后,Android人家说了,这次我们回调的不是openFileChooser
方法,而是onShowFileChooser
方法,并且上文提到的ValueCallback
参数里包裹着不再是Uri,而是Uri数组,因此我们必须为5.0+的机器做适配,大致思路如下:
webview.setWebChromeClient(new WebChromeClient(){
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
...
}
public void openFileChooser( ValueCallback uploadMsg, String acceptType ) {
...
}
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
...
}
// For Android 5.0+
public boolean onShowFileChooser (WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
mUploadCallbackAboveL = filePathCallback;
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("*/*");
MainActivity.this.startActivityForResult(
Intent.createChooser(i, "File Browser"),
FILECHOOSER_RESULTCODE);
return true;
}
});
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==FILECHOOSER_RESULTCODE)
{
if (null == mUploadMessage && null == mUploadCallbackAboveL) return;
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (mUploadCallbackAboveL != null) {
onActivityResultAboveL(requestCode, resultCode, data);
}
else if (mUploadMessage != null) {
mUploadMessage.onReceiveValue(result);
mUploadMessage = null;
}
}
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void onActivityResultAboveL(int requestCode, int resultCode, Intent data) {
if (requestCode != FILECHOOSER_RESULTCODE
|| mUploadCallbackAboveL == null) {
return;
}
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (data == null) {
} else {
String dataString = data.getDataString();
ClipData clipData = data.getClipData();
if (clipData != null) {
results = new Uri[clipData.getItemCount()];
for (int i = 0; i < clipData.getItemCount(); i++) {
ClipData.Item item = clipData.getItemAt(i);
results[i] = item.getUri();
}
}
if (dataString != null)
results = new Uri[]{Uri.parse(dataString)};
}
}
mUploadCallbackAboveL.onReceiveValue(results);
mUploadCallbackAboveL = null;
return;
}
如上,我们的Webview应该就可以适应5.0+的机器了。
WebView 上传文件 WebChromeClient之openFileChooser函数相关推荐
- android 上传html文件大小,浅谈关于Android WebView上传文件的解决方案
我们在开发需求的时候,难免会接入一下第三方的H5页面,有些H5页面是具有上传照片的功能,Android 中的 WebView是不能直接打开文件选择弹框的 接下来我讲简单提供一下解决方案,先说一下思路 ...
- android使用webview上传文件,Android项目中如何在webview页面中上传文件
Android项目中如何在webview页面中上传文件 发布时间:2020-11-26 15:56:27 来源:亿速云 阅读:68 作者:Leah 本篇文章为大家展示了Android项目中如何在web ...
- MIUI(Android)使用Webview上传文件
由于业务需求,需要在Android APP的Webview中上传图片,默认点击网页上的input file没有反应,在网上搜索后发现了一个可用的版本: android使用WebView来打开文件选择器 ...
- vue 上传文件_前后端分离项目,如何优雅实现文件存储!
在上一节中我们讲到了使用MinIO来自建对象存储服务,这次我们来讲下MinIO如何结合SpringBoot和Vue来实现文件存储. 学前准备 学习本文需要一些MinIO的基础知识,还不了解的小伙伴可以 ...
- html中异步上传文件实现示例,HTML_html中异步上传文件实现示例,复制代码代码如下: form actio - phpStudy...
html中异步上传文件实现示例 复制代码代码如下: 复制代码代码如下: 这是html中最常见最简单的表单提交方式,但是这种方式必须会切换页面,也许有些时候我们希望可以在同一个页面与服务器进行交互,并不 ...
- SpringBoot+Vue上传文件
最近在研究SpringBoot+Vue的文件上传,踩了不少坑.现在将正确的文件上传流程分享一下. 一.前端采用ElementUI组件 前端页面完整代码: <template><el- ...
- Angular2使用ng2-file-upload上传文件
Angular2使用ng2-file-upload上传文件 ng2-file-upload是一个功能比较全面的上传文件的支持库 (参考:http://www.jianshu.com/p/0741186 ...
- PHP上传文件函数move_upload,如何使用php中move_uploaded_file函数
我们平时上传的文件保存在临时文件夹中,例如/ tmp,但临时文件夹的内容在一段时间后会被删除,因此为了将来要使用上传文件,需要将内容保存在不太可能被任意删除的专用目录中,这时就需要使用move_upl ...
- php上传文件测试代码,php 文件上传函数的超详细示例
这篇文章主要为大家详细介绍了php 文件上传函数的超详细示例,具有一定的参考价值,可以用来参考一下. 下面跟随512笔记的小编来举个例子吧. 经测试代码如下: /** * 文件上传 * * 返回的数组 ...
最新文章
- spring cloud-zuul的Filter详解
- Chkdsk 工具将自动启动时启动的运行 Windows XP Service Pack 2 计算机扫描磁盘
- 非常经典的正则表达式
- windows10设置开机自启动
- python 东哥 with open_python 连接redis cluster
- 如何清空android ListView控件的内容
- nginx关闭websocket
- 磁盘读写流程和网络读写流程
- 【HTML+CSS网页设计与布局 从入门到精通】第10章-CSS
- python3.7 安装pip3_安装python3.7 pip3.7 去哪里了?
- Tengine新增nginx upstream模块的使用
- byteofpython中文gitbook_GitBook 简明教程
- Silverlight 密码框 Focus
- iPhone 9或于4月3日发布;复制粘贴之父Larry Tesler去世;Android 11开发者预览版来了!| 极客头条...
- php smarty 翻译标签,Smarty自定义block标签
- QA是干什么的?(职责所在????)
- 瑞红淘宝商城旗舰店开张 正式进军B2C市场
- 图片如何抠图换背景?怎样将图片抠成透明底图片?
- bt ct 计算机辅助翻译,计算机辅助翻译报告
- 勾股定理(计算)C++
热门文章
- Python filter() 函数
- python文件打开方式详解
- Windbg调试中遇到的问题
- js 判断是不是数字||判断字符串是不是数字(正则表达式)
- bzoj1875 边点互换+矩乘
- Python中’__main__’模块的作用
- 系统信息命令(uname、dmesg、df、hostname、free)
- HDU 4857 Couple doubi(找循环节)
- 我是买家的前世今生,该到了say goodbye的时候了!
- Halcon_灰度直方图和特征直方图的使用