默认的 Andorid WebView 是不支持 input type="file" 这种标签的用法的,但是我们在平时开发中却又是经常碰见这样的需求的。
在应用内嵌 HTML5 页面是很常见,一般情况下,HTML5 页面比较适合做一些业务说明,介绍或者展示等简单的功能,比较复杂的话,可能需要做一些表单的提交。
表单提交的话,input type=file 算是比较麻烦的。出于安全的问题,webview 默认并不会主动弹出文件选择器,不过 Android 还是为我们预留出一些 api 来,我们可以进行一定的扩展和自由发挥。
但是这样的 api 又有版本的变化,适配变得比较麻烦了。下面简单贴出大概的代码。
下面的代码展示如何接收 file type=file 控件的点击事件。这里唤起的是系统默认的文件选择器,你也完全可以启动自己项目里实现的文件选择器,或者图片选择器之类的。这里的重点是需要重写 WebChromeClient 的几个方法。
webview.setWebChromeClient(new WebChromeClient(){
// For 3.0+ Devices (Start)
// onActivityResult attached before constructor
protected void openFileChooser(ValueCallback uploadMsg, String acceptType){
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
startActivityForResult(Intent.createChooser(i, "File Browser"), FILECHOOSER_RESULTCODE);
}
// For Lollipop 5.0+ Devices
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public boolean onShowFileChooser(WebView mWebView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams){
Intent intent = fileChooserParams.createIntent();
try{
startActivityForResult(intent, REQUEST_SELECT_FILE);
} catch (ActivityNotFoundException e){
return false;
}
return true;
}
//For Android 4.1 only
protected void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType, String capture){
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(Intent.createChooser(intent, "File Browser"), FILECHOOSER_RESULTCODE);
}
protected void openFileChooser(ValueCallback<Uri> uploadMsg){
Intent i = new Intent(Intent.ACTION_GET_CONTENT);
i.addCategory(Intent.CATEGORY_OPENABLE);
i.setType("image/*");
startActivityForResult(Intent.createChooser(i, "File Chooser"), FILECHOOSER_RESULTCODE);
}
});
这里是唤起系统文件选择器后,用来接收 result intent。不同的版本略有不同。如果你唤起的是你自己应用的 Activity,处理也是相似的。不过最终,你都是需要通过一个 ValueCallback
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
if (requestCode == REQUEST_SELECT_FILE){
uploadMessage.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
}
}else if (requestCode == FILECHOOSER_RESULTCODE){
// Use MainActivity.RESULT_OK if you're implementing WebView inside Fragment
// Use RESULT_OK only if you're implementing WebView inside an Activity
Uri result = intent == null || resultCode != MainActivity.RESULT_OK ? null : intent.getData();
mUploadMessage.onReceiveValue(result);
}else{
}
}
这个方式实现,可以让 HTML 具有更高的适配性,可以在其他的浏览器中使用,实现了一次编写,到处部署,到处运行的效果。但是这个方式在混合编程确实还是有一些适配的问题,需要花些经历去解决。
现在也有很成熟的 webview 桥接技术,推荐开发团队可以考虑试用一下。
- EOF -
本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处,尊重他人劳动。
转载请注明:文章转载自 Binkery 技术博客 [https://binkery.com]
本文标题: Android WebView 不支持 H5 input type="file" 解决方法
本文地址: https://binkery.com/archives/112001.html