React Native Webview 中input type=file accept=“image/*“ 无法调起相机问题排查及解决
创始人
2024-02-13 08:56:59
0

最近在写一个react native 项目,其中react-native-webview库一些使用着实遇到了不少问题,耗时比较长,现在和大家分享一下。

图片上传时选择拍照是很常见的功能,写的h5项目一直调用正常。使用方式大概如下:

在H5下这段代码是正常可以使用的,调起相机和图库选择器,但是使用react-native-webview要注意。

首先要在AndroidManifest.xml注入权限,大概是如下三个,这个没很认真调研过,有错误可以提出。

        权限注入了之后,我认为一切都可以了,没想到这才是坑的开始。相机死活调不出来,经过查资料,大概有以下几种说法:

  • 1、原生webview不支持input accept="image",capture="camera"这种方式(原生是真的不支持)。但我使用的是类库react-native-webview,我个人以为是一个问题,然后才被坑下去的。
  • 2、xml权限注入的不对,然后各种尝试+各种查哪些权限是干啥用的。
  • 3、react-native 版本有问题
  • 4、react-native-webview版本有问题

并且在查的过程中还发生一些其他的血案,分享个地址给大家看下:https://github.com/react-native-webview/react-native-webview/issues/2679

官网在介绍如果input调不起相机的话,可以去这个地址看一下:react-native-webview/Guide.md at master · react-native-webview/react-native-webview · GitHub

然后呢?

import { WebView } from "react-native-webview";WebView.isFileUploadSupported().then(res => {if (res === true) {// file upload is supported} else {// not file upload support}
});

         这是代码,然后,就报错了,遇到了issues/2679这个问题,在这个坑里挣扎了半天,看node-modules导入的源码,并没有找到WebView.isFileUploadSupported这个方法,到最后我也没找到,这只不过是其中的一个弯路而已,最后我放弃了这个。

        因为没找到问题,我就找到了另外一篇文章,是教咱怎么在原生种实现webview调起相机的功能的。然后我就打算给react-native-webview原生实现一个选择相机的功能,地址链接:Android WebView支持input file启用相机/选取照片功能 - 腾讯云开发者社区-腾讯云

        开干,然后在这个坑里爬了半天,基本上把 react-native-webview源码扒了个遍(PS:当然我不是安卓开发,不太懂),然后找到了其中一个文件:

这个文件包含了点击input 相关的调用逻辑,不是很复杂,主要代码就这段:

if (!needsCameraPermission()) {if (acceptsImages(acceptTypes)) {Intent photoIntent = getPhotoIntent();if (photoIntent != null) {extraIntents.add(photoIntent);}}if (acceptsVideo(acceptTypes)) {Intent videoIntent = getVideoIntent();if (videoIntent != null) {extraIntents.add(videoIntent);}}}

        这段代码才是下一个坑的开始,因为先入为主的原因,我以为react-native-webview根本就没实现相机的调用,于是我就结合了顶上那篇文章,开始了修改源码的爬坑之旅,由于没有java的经验,折腾了一个多小时后,终于相机出来了😭。

        然后下一个坑出来,还是因为先入为主。点击相机没反应?然后各种查资料,看代码,才发现,getPhotoIntent这个方法:

private Intent getPhotoIntent() {Intent intent = null;try {outputImage = getCapturedFile(MimeType.IMAGE);Uri outputImageUri = getOutputUri(outputImage);intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, outputImageUri);} catch (IOException | IllegalArgumentException e) {Log.e("CREATE FILE", "Error occurred while creating the File", e);e.printStackTrace();}return intent;}

TMD,这不就是添加相机的地方吗?以为是这个方法的问题导致相机没有显示:acceptsImages(acceptType),后来发现发现不是,

  private Boolean acceptsImages(String types) {String mimeType = types;if (types.matches("\\.\\w+")) {mimeType = getMimeTypeFromExtension(types.replace(".", ""));}return mimeType.isEmpty() || mimeType.toLowerCase().contains(MimeType.IMAGE.value);}

然后各种找,先入为主害死人啊!添加相机选项的顶上,还有个needsCameraPermission方法,这个方法是获取权限的,我一直以为权限是有的,然后,打断点,发现,这里并没有获取到想要的权限。并且查看手机系统设置-》应用里面的相机权限是禁用,在设置里面打开权限之后,相机调用也正常了,然后我就EMO了。

很多文章告诉我们,权限并不需要手动获取,只需要加到配置清单中就行了,但实际并不是,相机这种权限还是需要主要跟用户获取的,当然用户同意了之后,以后就不需要再次获取了。

最终解决方案,大家可以看一下这篇文章,因为我的页面是需要相机权限的,所以我一进入这个页面就发起了权限的获取。React-Native之Android(6.0及以上)权限申请详解 - 腾讯云开发者社区-腾讯云

示例代码如下:

//请求多个权限const requestMultiplePermission = async () => {try {const permissions = [PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,PermissionsAndroid.PERMISSIONS.CAMERA,];//返回得是对象类型const granteds = await PermissionsAndroid.requestMultiple(permissions);var data = '是否同意地址权限: ';if (granteds['android.permission.ACCESS_FINE_LOCATION'] === 'granted') {data = data + '是\n';} else {data = data + '否\n';}data = data + '是否同意相机权限: ';if (granteds['android.permission.CAMERA'] === 'granted') {data = data + '是\n';} else {data = data + '否\n';}data = data + '是否同意存储权限: ';if (granteds['android.permission.WRITE_EXTERNAL_STORAGE'] === 'granted') {data = data + '是\n';} else {data = data + '否\n';}} catch (err) {// this.show(err.toString());}};useEffect(() => {requestMultiplePermission();}, []);

这段代码会在用户进入页面时发起一次权限的获取,如果已经有权限了,就不会再次发起了。

说了这么多,react-native-webview是支持相机的。

大家在用react-native 相机的时候注意:

1、先看配置清单是否添加权限

2、看下webview是否支持相机,(在系统设置-》应用-》权限中,如果相机权限已经启用,还是调不起相机的话,就要考虑webview是不是不支持)

3、如果安装APP后,相机权限是禁用的,要调用我上面写的方法,主动发起权限申请,webview可以放一个全局的地方申请。

4、input type=file,只有accept="image/*"的时候才有用,并且我测试过:capture={'camera' as any}不是必须的,新版规范中capture也没有camera选项了,只有

capture?: boolean | 'user' | 'environment' | undefined; 这几个值了,没有camera这个了。

就到这,希望大家可以开发顺利。

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
客厅放八骏马摆件可以吗(家里摆... 今天给各位分享客厅放八骏马摆件可以吗的知识,其中也会对家里摆八骏马摆件好吗进行解释,如果能碰巧解决你...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...