从安卓5.0开始(之前的版本没有测试过,只是从一些资料中得知此信息),webview中<input type=”file“>的打开文件实现已经改变,点击没有任何反应,需要重载WebChromeClient,处理打开文件的操作。
因为版本不断更新迭代,网上的一些实现中会用到deprecated的函数,以下给出“2023/4”我的实现,里面用到registerForActivityResult。相对于startActivityForResult,它更好一些,它使用回调,使得不用在多个函数中配合实现一个功能。
首先,注册一个ActivityResultLauncher,用于打开文件浏览器选择文件:
//解决安卓5及以上版本html<input type="file">无响应问题
private ValueCallback<Uri[]> checkedFile;
private ActivityResultLauncher<String[]> explorer;
//在Activity.onCreate中实现以下内容,实现打开文件浏览器选择文件的功能
protected void onCreate(Bundle savedInstanceState) {
........
explorer = registerForActivityResult(new ActivityResultContracts.OpenDocument(),
result -> {
LOG.debug("Open file `{}`", result);
if(checkedFile != null) {
if(result == null) {
checkedFile.onReceiveValue(null); //result没选择时为null
} else {
checkedFile.onReceiveValue(new Uri[]{result});
}
checkedFile = null;
}
});
........
}
其次,安卓5或以上版本,重载WebChromeClient.onShowFileChoose(老版本需要重载其他函数,可以参照网上其他介绍,我认为5以下没必要兼容了,所以不实现)。
WebChromeClient chromeClient = new WebChromeClient() {
@Override
public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
if (checkedFile != null) {
//防止上一次没选文件,直接退出的情况,导致后面选择无法正常工作
checkedFile.onReceiveValue(null);
}
checkedFile = filePathCallback;
String[] acceptTypes = fileChooserParams.getAcceptTypes();
LOG.debug("fileChooserParams:{},sdk_int:{}", Arrays.stream(acceptTypes).toArray(), Build.VERSION.SDK_INT);
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.N){
explorer.launch(new String[]{"*/*"});
} else {
explorer.launch(acceptTypes);
}
return true;
}
};
........
//设置到webview中
webview.setWebChromeClient(chromeClient);
注意,代码中判断了安卓7及以前版本,不能使用fileChooserParams参数来限制选择的文件类型,否则点击没有响应,也无错误信息,原因未知,所以这里传”*/*”。
一个关键点:在onShowFileChooser中获得checkedFile,这是一个回调。在explorer选中文件后,调用checkedFile.onReceiveValue将结果传递给webview。
在html中的处理与普通web浏览器完全相同,以下是获取图片文件并裁剪的例子,完整内容见此连接serverui/file/settings/home.js · master · 至简网格 / 至简网格企业服务 · GitCode,在startCropLogo函数中。
var file = e.target.files[0];
if (!/.(gif|jpg|jpeg|png|bmp|GIF|JPG|PNG)$/.test(e.target.value)) {
this.$refs.alertDlg.show(this.tags.invalidImg);
return false
}
var reader = new FileReader()
reader.onload = (e) => {
var data
if (typeof e.target.result === 'object') {
// 把Array Buffer转化为blob 如果是base64不需要
data = window.URL.createObjectURL(new Blob([e.target.result]))
} else {
data = e.target.result
}
this.logoOpts.img = data
this.loading=false;
}
// reader.readAsDataURL(file)// 转化为base64
reader.readAsArrayBuffer(file)// 转化为blob
原文地址:https://blog.csdn.net/flyinmind/article/details/130194217
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_24570.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!