React Native:Webview getUserMedia无法正常工作(onPermissionRequest是否被覆盖?) [英] React Native: Webview getUserMedia not working (onPermissionRequest override?)

查看:111
本文介绍了React Native:Webview getUserMedia无法正常工作(onPermissionRequest是否被覆盖?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用React Native开发用于 iOS,Android和Windows 的应用程序,其中需要通过WebView显示网页.该网页访问设备的相机,因此它使用MediaDevices.getUserMedia() Javascript函数.

I'm developing an application for iOS, Android and Windows with React Native in which I need to show a webpage through a WebView. That webpage accesses the camera of the device, so it uses MediaDevices.getUserMedia() Javascript function.

它可以在台式机上正常运行,即使在智能手机上的Chrome应用程序中.但是,当我通过React Native <WebView />调用网页时,出现了PermissionDenied错误.问题是未显示任何请求,让我接受该权限.它只是拒绝请求而没有询问.

It works without problems in desktop, even in the Chrome app on the smartphone. However, when I call the webpage via the React Native <WebView />, I get a PermissionDenied error. The problem is that no request is shown to let me accept that permission. It justs denies the request without asking.

以下是我的WebView元素的示例:

Here is a sample of my WebView element:

    <WebView 
        style={{flex: 1}}
        mediaPlaybackRequiresUserAction={false}
        domStorageEnabled={true}
        allowsInlineMediaPlayback={true}
        source={{uri: 'https://myurltomyapp.com/index.html'}} 
        startInLoadingState={true}
        allowUniversalAccessFromFileURLs={true}
    />

我已经在AndroidManifest.xml上设置了所有必要的权限(甚至为了测试不需要一些权限):

I've got all necessary permissions set on AndroidManifest.xml (and even some not needed for the sake of testing):

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CAPTURE_AUDIO_OUTPUT" />
    <uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />
    <uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
    <uses-permission android:name="android.permission.RECORD_AUDIO"/>
    <uses-permission android:name="android.permission.RECORD_VIDEO"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />

是的,该网站的托管URL经过SSL认证,因此它通过HTTPS.它可以在Chrome应用程序上运行,因此也可以在WebView上运行.

And yes, the URL where is hosted the website is SSL certified, so it goes through HTTPS. It works on Chrome app, so it should work on WebView, too.

我一直在网上阅读,这似乎是因为React Native WebView缺少onPermissionRequest()实现,所以它默默地失败了(并拒绝了它).

I've been reading through the net, and it seems that's because React Native WebView lacks of a onPermissionRequest() implementation, so it fails silently (and denies it).

有没有一种方法可以在React Native中实现覆盖本机WebView ?如果可能,我必须编辑哪些文件?是否有任何第三方模块(最新的)已实现(无法找到任何模块)?

Is there a way to implement it overriding the native WebView in React Native? Which files do I have to edit, if possible? Is there any third-party module (up to date) which has this implemented (haven't been able to find any)?

谢谢.

推荐答案

最后,我不得不在本机Android中实现自己的WebView组件.问题是onPermissionRequest()函数未在本机WebView中实现.您必须创建自己的并覆盖该功能.就我而言,我必须添加以下代码(所有文件都在路径[react-native-project]/android/app/src/main/java/com/listproject/permissionwebview/下):

Finally I had to implement an own WebView component in native Android. The problem is the onPermissionRequest() function that it's not implemented in the native WebView. You have to create your own and override that function. In my case, I had to add the following code (all files are under path [react-native-project]/android/app/src/main/java/com/listproject/permissionwebview/):

PermissionWebviewPackage.java中:

In PermissionWebviewPackage.java:

package com.listproject.permissionwebview;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.Arrays;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;

/**
 * Add this package to getPackages() method in MainActivity.
 */

public class PermissionWebviewPackage implements ReactPackage {

    @Override
    public List<ViewManager> createViewManagers(
            ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(
            new PermissionWebviewViewManager()
          );
    }

    @Override
    public List<NativeModule> createNativeModules(
            ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

PermissionWebviewView.java中:

In PermissionWebviewView.java:

package com.listproject.permissionwebview;
import android.content.Context;
import android.widget.LinearLayout;
import android.os.Bundle;
import android.widget.Toast;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.PermissionRequest;
import android.webkit.WebSettings;
import android.net.http.SslCertificate;
import android.net.http.SslError;
import android.webkit.SslErrorHandler;
import android.support.v4.app.ActivityCompat;
import android.app.LocalActivityManager;
import android.view.ViewGroup;
import android.Manifest;
import android.app.Activity;
import com.listproject.MainActivity;
import com.listproject.R;

public class PermissionWebviewView extends WebView{

    private Context context;

    public PermissionWebviewView(Context context) {
        super(context);
        this.context = context;

        this.setWebViewClient(new WebViewClient());

        WebSettings webSettings = this.getSettings();
        webSettings.setJavaScriptEnabled(true);
        webSettings.setAllowFileAccessFromFileURLs(true);
        webSettings.setAllowUniversalAccessFromFileURLs(true);
        webSettings.setMediaPlaybackRequiresUserGesture(false);
        webSettings.setUseWideViewPort(true);
        webSettings.setDomStorageEnabled(true);

        this.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onPermissionRequest(final PermissionRequest request) {
                request.grant(request.getResources());
            }
        });
    }
}

PermissionWebviewViewManager.java中:

In PermissionWebviewViewManager.java:

package com.listproject.permissionwebview;

import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.uimanager.annotations.ReactProp;

public class PermissionWebviewViewManager extends SimpleViewManager<PermissionWebviewView> {

    public static final String REACT_CLASS = "PermissionWebviewViewManager";
    private String source;

    @Override
    public String getName() {
        return REACT_CLASS;
    }

    @Override
    public PermissionWebviewView createViewInstance(ThemedReactContext context) {
        return new PermissionWebviewView(context); //If your customview has more constructor parameters pass it from here.
    }

    @ReactProp(name = "sourceUri")
    public void setSource(PermissionWebviewView view, String source) {
        view.loadUrl(source);
    }
}

最后,更新您的MainApplication.java文件,并将您的软件包添加到getPackages()函数中:

Finally, update your MainApplication.java file, and add your package into getPackages() function:

@Override
protected List<ReactPackage> getPackages() {
  return Arrays.<ReactPackage>asList(
      new MainReactPackage(),
        [...],
        new PermissionWebviewPackage()
  );
}

请记住,只要在文件的命名空间和程序包引用中更改listprojectpermissionwebview等名称,即可将其更改为所需的名称.

Keep in mind that the names of listproject, permissionwebview, and so on can be changed to whatever you need to, as long as you change them in the namespaces of the files and in the package references.

一旦拥有了所有这些,您只需创建ReactNative组件导出([react-native-project]/app/components/PermissionWebView/index.android.js):

Once you have all this, all you have to create is the ReactNative component export ([react-native-project]/app/components/PermissionWebView/index.android.js):

import PropTypes from 'prop-types';
import {requireNativeComponent, ViewPropTypes} from 'react-native';

// The 'name' property is not important, the important one is below
var mcs = {
  name: 'PermissionWebview',
  propTypes: {
    sourceUri: PropTypes.string,
      ...ViewPropTypes
  }
};

module.exports = requireNativeComponent('PermissionWebviewViewManager', mcs);

请注意,我们将索引的名称设置为index.android.js,因为该组件是为Android制作的,因此仅包含在Android平台中.

Note we set the name of index to index.android.js because this component is made for Android, so it's included only in Android platform.

使用此功能,一切正常,并且WebView组件在使用时应征得许可.

With this, everything should work and the WebView component should ask for permission when it's used.

我已将代码上传到我的 Github存储库.我只更改了一些名称,但核心代码没有做任何更改以确保它仍然可以工作(我无法对其进行测试,因此最好不要进行很多更改).

I've uploaded the code to my Github repository. I've only changed some names, but the core code has not changed a bit to make sure it still works (I cannot test it, so better not to change lots of things).

希望它对某人有帮助!

这篇关于React Native:Webview getUserMedia无法正常工作(onPermissionRequest是否被覆盖?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆