草庐IT

React Native Webview 中input type=file accept=“image/*“ 无法调起相机问题排查及解决

lizhen_software 2023-04-03 原文

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

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

<input
          type="file"
          ref={inputRef}
          accept="image/*"
          capture={'camera' as any}
          id="uploadImage"
          onChange={handleUploadChange}
        />

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

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

<uses-permission android:name="android.permission.CAMERA" />

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

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

  • 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这个了。

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

有关React Native Webview 中input type=file accept=“image/*“ 无法调起相机问题排查及解决的更多相关文章

  1. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  2. ruby - 在 64 位 Snow Leopard 上使用 rvm、postgres 9.0、ruby 1.9.2-p136 安装 pg gem 时出现问题 - 2

    我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po

  3. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  4. ruby-on-rails - 无法使用 Rails 3.2 创建插件? - 2

    我对最新版本的Rails有疑问。我创建了一个新应用程序(railsnewMyProject),但我没有脚本/生成,只有脚本/rails,当我输入ruby./script/railsgeneratepluginmy_plugin"Couldnotfindgeneratorplugin.".你知道如何生成插件模板吗?没有这个命令可以创建插件吗?PS:我正在使用Rails3.2.1和ruby​​1.8.7[universal-darwin11.0] 最佳答案 随着Rails3.2.0的发布,插件生成器已经被移除。查看变更日志here.现在

  5. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  6. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  7. ruby - 无法让 RSpec 工作—— 'require' : cannot load such file - 2

    我花了三天的时间用头撞墙,试图弄清楚为什么简单的“rake”不能通过我的规范文件。如果您遇到这种情况:任何文件夹路径中都不要有空格!。严重地。事实上,从现在开始,您命名的任何内容都没有空格。这是我的控制台输出:(在/Users/*****/Desktop/LearningRuby/learn_ruby)$rake/Users/*******/Desktop/LearningRuby/learn_ruby/00_hello/hello_spec.rb:116:in`require':cannotloadsuchfile--hello(LoadError) 最佳

  8. ruby - 通过 RVM (OSX Mountain Lion) 安装 Ruby 2.0.0-p247 时遇到问题 - 2

    我的最终目标是安装当前版本的RubyonRails。我在OSXMountainLion上运行。到目前为止,这是我的过程:已安装的RVM$\curl-Lhttps://get.rvm.io|bash-sstable检查已知(我假设已批准)安装$rvmlistknown我看到当前的稳定版本可用[ruby-]2.0.0[-p247]输入命令安装$rvminstall2.0.0-p247注意:我也试过这些安装命令$rvminstallruby-2.0.0-p247$rvminstallruby=2.0.0-p247我很快就无处可去了。结果:$rvminstall2.0.0-p247Search

  9. ruby - Fast-stemmer 安装问题 - 2

    由于fast-stemmer的问题,我很难安装我想要的任何ruby​​gem。我把我得到的错误放在下面。Buildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingfast-stemmer:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcreatingMakefilemake"DESTDIR="cleanmake"DESTDIR=

  10. ruby - 无法覆盖 irb 中的 to_s - 2

    我在pry中定义了一个函数:to_s,但我无法调用它。这个方法去哪里了,怎么调用?pry(main)>defto_spry(main)*'hello'pry(main)*endpry(main)>to_s=>"main"我的ruby版本是2.1.2看了一些答案和搜索后,我认为我得到了正确的答案:这个方法用在什么地方?在irb或pry中定义方法时,会转到Object.instance_methods[1]pry(main)>defto_s[1]pry(main)*'hello'[1]pry(main)*end=>:to_s[2]pry(main)>defhello[2]pry(main)

随机推荐