记录webView接入h5界面时,调起相册、文件、相机无效的解决办法。

在开发项目时,接入一个h5界面。使用webview时,发现界面显示正常,但是按钮不论怎么点都无效,但是m站和ios都正常。后来上网查了相关资料,才发现原来这块是需要Android这边自己在webview这边开发的。需要重写WebChromeClient。

这里有一个需要区分的概念就是WebChromeClient和WebViewClient,因时间和精力关系只做简单的学习和介绍。

WebViewClient只和影响view有关系的事件到来时,会通过WebViewClient内的方法回调通知开发者。

WebChromeClient则是和浏览器有关的事件进行回调。

一句话区分就是WebViewClient只和显示有关系,而WebChromeClient则是和js交互有关(如弹窗等)。

WebChromeClient

想要实现和js的打开相册、相机等交互,必须重写两个方法,分别适配4.1~5.0以及5.0以上版本。

//For Android 4.1  - 5.0
public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType,String capture) {
}//For 5.0+
@Override
public boolean onShowFileChooser(WebView webView,ValueCallback<Uri[]> filePathCallback,WebChromeClient.FileChooserParams fileChooserParams) {return true;
}

在了解这个方法前,可以先简单了解一下h5界面是如何调用本地的相册以及其他功能。如下所示

<input type=“file” accept=“video/*;capture=camcorder”>
<input type=“file” accept=“audio/*;capture=microphone”>
<input type=“file” accept=“image/*;capture=camera”>

accept 和capture分别对应openFileChooser的acceptType和capture,因此我们只需要和h5约定好accept的值就可以做相对应的处理了,uploadMsg则是这个方法的回调。

也许你会奇怪onShowFileChooser中并没有这样acceptType和capture,但实际上有一个fileChooserParams。可以通过fileChooserParams.getAcceptTypes()[0]的方式获取到acceptType。

比如我们可以和h5约定accepty="image/*"是打开相册、accepty=“camera/*”是打开相机。然后分别在webview中处理就可以了。

来简单实现一下。

第一步,设置WebChromeClient。

        customWebview.setWebChromeClient(new WebChromeClient() {//For Android 4.1  - 5.0public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType,String capture) {//这是一个全局变量filePathCallback = uploadMsg;if (acceptType != null) {openCustomServiceProcess(acceptType);}}//For 5.0+@Overridepublic boolean onShowFileChooser(WebView webView,ValueCallback<Uri[]> filePathCallback,WebChromeClient.FileChooserParams fileChooserParams) {//这是一个全局变量filesPathCallback = filePathCallback;if (fileChooserParams != null&& fileChooserParams.getAcceptTypes() != null) {openCustomServiceProcess(fileChooserParams.getAcceptTypes()[0]);}return true;}});

openCustomServiceProcess是根据acceptType分别处理调用相册或者相机等功能。

/*** 根据actionType判断是打开相册、打开文件、还是打开相机** @param type h5 actionType*/
private void openCustomServiceProcess(String type) {Intent intent = new Intent(Intent.ACTION_GET_CONTENT);if (!TextUtils.isEmpty(type)) {intent.setType(type);//如果是打开图片if (type.equals("image/*")) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {intent.addCategory(Intent.CATEGORY_OPENABLE);}} else if (type.equals("camera/*")) {//如果是打开相机 REQUEST_CODE_CAMERA是自定义的requestCode 只需要是唯一常数即可sendCameraIntent(REQUEST_CODE_CAMERA);return;}} else {//如果是打开所有文件intent.setType("*/*");}//调用起文件查看器,根据是否设置Intent.CATEGORY_OPENABLE判断打开的分类是图片库还是所有文件this.startActivityForResult(Intent.createChooser(intent, "请选择文件"), REQUEST_CODE_FILE);
}
/*** 调起相机*/
private void sendCameraIntent(int requestCode) {if (mCameraFile == null) {mCameraFile = new File(AppUtils.getCameraImagePath(CustomWebViewActivity.this));}mCameraFile.getParentFile().mkdirs();Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {imageUri = FileProvider.getUriForFile(CustomWebViewActivity.this,getApplicationContext().getPackageName() + ".fileprovider",mCameraFile);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);} else {imageUri = Uri.fromFile(mCameraFile);}if (requestCode == REQUEST_CODE_CAMERA_KF) {intent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);}intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);startActivityForResult(intent, requestCode);}

到这一步基本上就已经可以调用起相册或者相机了,但是很快就会发现有一个问题,只能调用一次。原来是每次使用回调以后,必须都有一个返回值,通过mUploadMsg或者filesPathCallback的onReceiveValue方法,切记一定要返回值,即使data为空也需要传null回去。

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);if (resultCode == Activity.RESULT_OK) {switch (requestCode) {case REQUEST_CODE_FILE:case REQUEST_CODE_CAMERA:if (filePathCallback != null) {Uri result = data == null ? null : data.getData();if (result != null) {filePathCallback.onReceiveValue(result);} else {filePathCallback.onReceiveValue(Uri.EMPTY);}filePathCallback = null;}//将文件回传给h5if (filesPathCallback != null) {Uri[] result = null;if (data != null) {String dataString = data.getDataString();ClipData clipData = data.getClipData();if (clipData != null) {int itemCount = clipData.getItemCount();result = new Uri[itemCount];for (int i = 0; i < itemCount; i++) {ClipData.Item item = clipData.getItemAt(i);result[i] = item.getUri();}}if (dataString != null) {result = new Uri[] { Uri.parse(dataString) };}} else if (requestCode == REQUEST_CODE_CAMERA) {result = new Uri[] { imageUri };}if (result == null) {filesPathCallback.onReceiveValue(new Uri[] {});} else {filesPathCallback.onReceiveValue(result);}filesPathCallback = null;}break;default:break;}} else {switch (requestCode) {//如果返回为空时,返回nullcase REQUEST_CODE_FILE:case REQUEST_CODE_CAMERA_KF:if (filePathCallback != null) {filePathCallback.onReceiveValue(Uri.EMPTY);filePathCallback = null;}if (filesPathCallback != null) {filesPathCallback.onReceiveValue(new Uri[] {});filesPathCallback = null;}break;default:com.gaotu100.superclass.base.logger.MyLogger.d("1");break;}}
}

至此算是完成了app内嵌h5调用相册和相机的功能。

记录webView接入h5界面时,调起相册、文件、相机无效的解决办法相关推荐

  1. iCoud-MaciCoud上传文件时卡住-卡死-iCoud文件无法上传解决办法

    平时iCoud我都是存一些文本文件,最近iCoud总是显示"正在上传", 总大小才几kb,不可能上传的那么慢.并且长期处于这种状态,由于我不经常使用iCoud就没搭理它. 今天需要 ...

  2. 服务器执行sh文件或目录,将window的shell脚本通过ftp传输到Linux服务器后, shell脚本中执行时提示“没有那个文件或目录”的解决办法...

    出现bad interpreter:No such file or directory的原因,是文件格式的问题.这个文件是在Windows下编写的.换行的方式与Unix不一样,但是在vim下面如果不S ...

  3. android h5控制锁屏,WebView播放H5课件时,锁屏解锁后,页面重新绘制的问题

    难题描述:H5页面播放 ,锁屏,解锁后,重新加载了页面,三星不会出现(onpause onstop ,onresume),但在小米.魅族会调用 onpause onstop ondestroy,onr ...

  4. 解决vue在ios或android中用webview打开H5链接时#号后面的参数被忽略问题angular同样适用

    解决vue在ios或android中用webview打开H5链接时#号后面的参数被忽略问题angular同样适用 参考文章: (1)解决vue在ios或android中用webview打开H5链接时# ...

  5. Win10系统在运行界面cmd出现ipconfig命令无法使用的情况的解决办法!!

    Win10系统在运行界面cmd出现ipconfig命令无法使用的情况的解决办法!! 问题描述 解决方案(完整步骤) Hello!从今天开始笔者决定把自己的学习过程记录下来,因为自己的方向以后会是车联网 ...

  6. sqlplus登录时遇到的ORA-12560: TNS: 协议适配器错误解决办法

    sqlplus登录时遇到的ORA-12560: TNS: 协议适配器错误解决办法 在windows下使用lsnrctl start启动监听之后,然后使用sqlplus登录的时候遇到了ORA-12560 ...

  7. 暗黑地牢dlc文件夹或mods文件夹中某个mod在初始界面开新档不显示/不加载的解决办法

    暗黑地牢 Darkest Dungeon dlc文件夹或mods文件夹中某个mod在初始界面开新档不显示/不加载的解决办法 (记录博文) 相关提示 检查mod完整性(参考正确的mod文件结构进行判断) ...

  8. 本地计算机无法启动wireless,win7系统使用无线时提示:“windows无法启动wireless”的解决办法...

    此文约为506字,阅读需要3分钟 如果在连接无线网络时连接不上,而系统提示了"Windows无法启动Wireless PAN DHCP Server服务(位于本地计算机上).错误1067:进 ...

  9. linux服务器黑屏_IBM服务器安装、进入Linux系统时显示花屏、黑屏的解决办法

    IBM服务器安装.进入Linux系统时显示花屏.黑屏的解决办法 在Linux安装时不能正确识别或者装上显卡驱动,导致在安装或者启动时显示黑屏.花屏,这时我们可以使用VESA模式进入Linux的图形话界 ...

最新文章

  1. 火狐产品主管称:不值得开发Windows RT浏览器
  2. 代码变油画,精细到毛发,这个前端小姐姐只用HTML+CSS,让美术设计也惊叹丨GitHub热榜...
  3. Openfiler的配置
  4. 转载:2016前端开发技术巡礼
  5. 神经网络的输出有方向吗?
  6. 「后端小伙伴来学前端了」Vue中利用全局事件总线实现组件之间通信
  7. 使用SWig出现调用异常的情况
  8. 从【银行销冠】化身测试工程师,小哥这样实现了人生的逆转
  9. vue3初探-工程化项目架构-笔记
  10. 蔚蓝网上书店项目js/jQuery部分
  11. 大数据平台有哪些基础服务
  12. Windows2003企业版 + SQL2008R2 使用大内存
  13. 【Java微信公众平台开发模式+自定义按钮源码】
  14. win7怎么不能无线连接网络连接服务器,win7网络连接不上|windows7无线网络连接不上怎么办?...
  15. 数据库关系代数练习题
  16. linux中giep命令作用,Linux查看硬件信息以及驱动设备的命令
  17. 计算机毕业设计Java居家养老系统(源码+系统+mysql数据库+lw文档)
  18. wpf 语音通话_WPF+WCF一步一步打造音频聊天室(二):文字聊天和白板共享
  19. 软考计算机硬件设计师被取消,软考证书取消登记,一起来看看软考证书的前世今生...
  20. 51单片机Proteus仿真+Keil工程-实验6-单片机扩展RAM6264实验

热门文章

  1. 图像处理之道路行道线检测
  2. Access数据库有什么用?该数据库有什么功能?
  3. mysql5.5.57 漏洞_DEDECMS(织梦程序)5.5-5.7通杀GetShell漏洞
  4. SPOJ Problem 3410:Feynman
  5. JS逆向之浏览器补环境详解
  6. 【职坐标】 java基础内容汇总
  7. Unsatisfied dependency expressed through field
  8. C# 获取当前桌面路径
  9. office 2010 ppt幻灯片自动播放
  10. windows下C与C++执行cmd命令并实时获取输出