简介
本文将解决以下一些问题(如有错误,可指正,谢谢):
- 解决在webview中input标签type="file"不能使用的问题;
- 解决上传文件的多选问题;
- 解决Android获取input标签中accept属性,从而实现动态选择文件类型的问题;
碰到的问题
PS:以下都是搜索各种博客得来的信息;
HTML中input标签type="file"无法使用
默认的情况下在HTML中 写< input type=“file” />的时候回弹出选择文件的窗口,但实际上在webview中默认的是不弹出窗口的,不能打开android资源管理器。
是因为 android webview 由于考虑安全原因屏蔽了 < input type=“file”/> 这个功能 。
不过 Android 还是为我们预留出一些 api 来,我们可以进行一定的扩展和自由发挥。
但是这样的 api 又有版本的变化,适配变得比较麻烦了。
重写webview 的WebChromeClient
步骤:
-
重载文件选择按钮被点击后的方法,即onShowFileChooser()方法(Android>5.0)。
-
在onShowFileChooser()方法中声明一个意图,打开文件选择相对应的Activity,即FILE_CHOOSER_RESULT_CODE。
-
重载onActivityResult()方法,在里面接收用户选择的文件的Uri,传给input标签。
文件多选功能无法使用
-
private ValueCallback<Uri[]> uploadMessage; //多选文件回调
-
//此处增加参数 允许多选文件
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true); -
onActivityResult回调方法中配置好接收多选的文件
怎么获取input中accept属性的值
onShowFileChooser方法只提供了一个webview对象,一个ValueCallback回调,以及FileChooserParams。FileChooserParams提供的getAcceptTypes方法能够获取input中accept属性的值,但是它会将属性值通过逗号切割开,返回字符串数组。
intent.setType无法指定浏览本地多种类型的文件
这是正常的访问系统自带的文件管理器。但是setType只支持单个setType一般是以下这种(以只查看图片文件为例):
intent.setType("image/*");
在API>=19之后设置多个类型采用以下方式,setType不再支持多个类型;
需要使用intent.putExtra():
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
//例子:支持图片和pdf的上传
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
intent.putExtra(Intent.EXTRA_MIME_TYPES,
new String[]{"image/*","application/pdf"});
}
并且必须是MIME格式的
MimeType
多用途互联网邮件扩展(MIME,Multipurpose Internet Mail Extensions)是一个互联网标准,它扩展了电子邮件标准,使其能够支持非ASCII字符、二进制格式附件等多种格式的邮件消息。
请参阅 IANA MIME 类型,获得标准 MIME 类型的完整列表。
代码
Android代码
public class WebViewActivity extends AppCompatActivity {
private Context context;
private WebView webView;
private ValueCallback<Uri> uploadMessage;//单选文件回调
public ValueCallback<Uri[]> uploadMessageAboveL; //多选文件回调
private final static int FILE_CHOOSER_RESULT_CODE = 10000;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview_layout);
context = this;
initView();
}
public void initView() {
webView = findViewById(R.id.wView);
自定义 WebChromeClient 辅助WebView处理图片上传操作【<input type=file> 文件上传标签】
webView.setWebChromeClient(new WebChromeClient() {
/*
重写 WebChromeClient中的 openFileChooser() 和 onShowFileChooser()方法,由于在不同安卓版本的方法不大一样,所以要分别进行实现。
通过对比这两个方法可以看出它们的区别,openFileChooser中传入的参数ValueCallback接口回传一个Uri的对象,
而onShowFileChooser回传一个Uri[]数组,因此在onActivityResult回调方法中调用ValueCallback接口方法onReceiveValue传入参数需特别注意对于这两种方法的回调要区别对待。
原文链接:https://blog.csdn.net/teagreen_red/article/details/75579016
*/
// For Android >= 5.0 才支持多选
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
uploadMessageAboveL = filePathCallback;
openImageChooserActivity(fileChooserParams.getAcceptTypes());
return true;
}
});
webView.getSettings().setJavaScriptEnabled(true); //设置WebView属性,运行执行js脚本
webView.getSettings().setDomStorageEnabled(true);//DOM Storage
// 开启DOM缓存,开启LocalStorage存储(html5的本地存储方式)
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setAllowContentAccess(true); // 是否可访问Content Provider的资源,默认值 true
webView.getSettings().setAllowFileAccess(true); // 是否可访问本地文件,默认值 true
webView.loadUrl(Config.domain + "test2"); //调用loadUrl方法为WebView加入链接
}
/**
* 打开文件管理器 选择文件
*/
private void openImageChooserActivity(String[] acceptType) {
Intent i = new Intent(Intent.ACTION_GET_CONTENT); //允许用户选择特殊种类的数据,并返回
//一个布尔型值,声明用户是否可以一次选择多个文件。
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true);
i.addCategory(Intent.CATEGORY_OPENABLE); //增加一个可打开的分类
i.setType("*/*");
//在API>=19之后设置多个类型采用以下方式,setType不再支持多个类型
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
i.putExtra(Intent.EXTRA_MIME_TYPES,
// new String[]{"image/jpeg","image/jpg","image/png","application/pdf"});
acceptType);
}
startActivityForResult(Intent.createChooser(i, "Image Chooser"), FILE_CHOOSER_RESULT_CODE);
}
/*
回调函数?
在onActivityResult里处理获取到的文件
重载onActivityResult()方法,在里面接收用户选择的文件的Uri,传给input标签
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == FILE_CHOOSER_RESULT_CODE) {
if (null == uploadMessage && null == uploadMessageAboveL) return;
Uri result = data == null || resultCode != RESULT_OK ? null : data.getData();
if (uploadMessageAboveL != null) {
onActivityResultAboveL(requestCode, resultCode, data);
} else if (uploadMessage != null) {
uploadMessage.onReceiveValue(result);
uploadMessage = null;
}
}
}
/*
android 5.0
多文件的结果返回处理
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void onActivityResultAboveL(int requestCode, int resultCode, Intent intent) {
Log.d("test1234","onActivityResultAboveL");
if (requestCode != FILE_CHOOSER_RESULT_CODE || uploadMessageAboveL == null)
return;
Uri[] results = null;
if (resultCode == Activity.RESULT_OK) {
if (intent != null) {
String dataString = intent.getDataString();
ClipData clipData = intent.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)};
}
}
uploadMessageAboveL.onReceiveValue(results);
uploadMessageAboveL = null;
}
}
HTML代码
前端H5配置好input标签的accept属性,遵守MIME格式的规则,供Android获取配置;
<input type="file" accept="image/jpeg, image/jpg, image/png,application/pdf"/>
实现效果
![]() |
![]() |
参考
安卓WebView文件上传的实现(解决安卓WebView中<input type=‘file‘/>标签点击没反应)
android下webview实现H5 html标签 input file类型文件多选 multiple 属性的支持
Android webview H5页面input选择文件传递参数
Android开发文档(文件存储-打开特定类型的文件)
android intent.setType指定浏览本地多种类型的文件