作者简介 原创微信公众号郭霖 WeChat ID: guolin_blog
又到了周五啦,提前祝大家周末愉快!
本篇来自钊林的投稿,分享了一个解决WebView文件上传无法重复选择问题的方案,希望能够帮助到大家。
钊林的博客地址:
http://teachcourse.cn
正文
Android 开发使用WebView控件加载包含表单的 H5 网页,点击上传文件按钮,弹出对话框,选择从相册获取照片、拍照或打开手机文件管理器,从 Android 手机选取一张图片或一个文件,然后通过ValueCallback接口传递,在 WebView 加载的 H5网页 显示。
这里有一个问题,点击“取消”或返回按钮,无法重复回调onShowFileChooser或openFileChooser方法,控制台打印:
Attempted to finish an input event but the input event receiver has already been disposed
一、深入理解onShowFileChooser或openFileChooser
WebChromeClient各个方法这里不再赘述,特殊说明关于 WebChromeClient,它既不是接口也不是抽象类,但声明的方法很多方法体都是空的,这是让钊林感到疑惑之一。查看 WebView 源码,setWebChromeClient()传入WebChromeClient对象,然后使用传入的对象,调用 WebChromeClient 声明的方法,再将一些参数传递返回 WebChromeClient 空方法体。在 WebView 源码里面代码也很简单,详细的处理处理逻辑看不到,这是让钊林感到疑惑之二,感觉像一个黑箱子。
然后就一直想,那么重写 WebChromeClient 的方法有什么作用呢?先看一下onShowFileChooser,如下:
该方法的作用,告诉当前APP,打开一个文件选择器,比如:打开相册、启动拍照或打开本地文件管理器,实际上更好的理解,WebView加载包含上传文件的表单按钮,HTML 定义了 input 标签,同时 input 的 type 类型为 file,手指点击该按钮,回调onShowFileChooser这个方法,在这个重写的方法里面打开相册、启动照片或打开本地文件管理器,甚至做其他任何的逻辑处理,点击一次回调一次的前提是请求被取消,而取消该请求回调的方法:给ValueCallback接口的onReceiveValue抽象方法传入null,同时 onShowFileChooser 方法返回true;
ValueCallback的抽象方法被回调onShowFileChooser方法返回true;反之返回false;再来看一下 openFileChooser 的源码,如下:
在所有发布的SDK版本中,openFileChooser是一个隐藏的方法,使用onShowFileChooser代替,但是最好同时重写showFileChooser和openFileChooser方法,Android 4.4.X以上的系统回调onShowFileChooser方法,低于或等于 Android 4.4.X的系统回调openFileChooser方法,只重写onShowFileChooser或openFileChooser造成在有的系统可以正常回调,在有的系统点击没有反应。
仔细分析onShowFileChooser和openFileChooser回调方法,这两个方法之间的区别:
第一个区别:前者ValueCallback接口回传一个Uri数组,后者回传一个Uri对象,在onActivityResult回调方法中调用ValueCallback接口方法onReceiveValue传入参数特别注意。
第二个区别:前者 将 后者的 acceptType、capture 封装成 FileChooserParams 抽象类
二、实例展示onShowFileChooser或openFileChooser处理过程
这是实例运行的效果图,H5表单写入两个上传文件的按钮,点击其中一个从底部弹出对话框,选择相册文件或拍照,点击“取消”按钮,再次点击“上传文件”按钮能够再次回调onShowFileChooser或openFileChooser方法。
在之前的理解中,误解onShowFileChooser或openFileChooser只能打开相册或启动相机拍照,其实不仅仅是这样,onShowFileChooser或openFileChooser既然是一个回调的方法,可以重复执行各种逻辑代码,比如:启动另一个Activity、弹窗对话框、录制视频或录音等
在上面的例子中,执行弹窗操作,将弹窗的处理代码放置onShowFileChooser或openFileChooser方法体,如下:
点击弹窗取消按钮、点击打开相册取消操作或取消拍照,可能无法再次回调onShowFileChooser或openFileChooser方法,如果你没有在点击弹窗取消方法中或onActivityResult回调方法resultCode==RESULT_CANCELED处理,再次点击上传按钮,打印出 log:
Attempted to finish an input event but the input event receiver has already been disposed
同时,点击没有效果。解决方案:
在不期待回调 mFilePathCallback 的 onReceiveValue 方法时,调用 cancelFilePathCallback(),解决点击上传按钮无法重复回调的问题。
完。。。。。。。。。。。。。。。。。。。。。
文章原创作者GuoLin 书籍推荐
郭林大神原创android 书籍:《第一行代码 android》