React Native:Webview getUserMedia无法正常工作(onPermissionRequest覆盖?)

Una*_*dra 8 android webview android-webview getusermedia react-native

我正在使用React Native 为iOS,Android和Windows开发应用程序,我需要在其中显示一个网页WebView.该网页访问设备的摄像头,因此它使用MediaDevices.getUserMedia()Javascript功能.

即使在智能手机上的Chrome应用中,它也可以在桌面上正常运行.但是,当我通过React Native调用网页时<WebView />,出现PermissionDenied错误.问题是没有显示任何请求让我接受该许可.它只是在不问的情况下否认了这个请求.

这是我的WebView元素的示例:

    <WebView 
        style={{flex: 1}}
        mediaPlaybackRequiresUserAction={false}
        domStorageEnabled={true}
        allowsInlineMediaPlayback={true}
        source={{uri: 'https://myurltomyapp.com/index.html'}} 
        startInLoadingState={true}
        allowUniversalAccessFromFileURLs={true}
    />
Run Code Online (Sandbox Code Playgroud)

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

    <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" />
Run Code Online (Sandbox Code Playgroud)

是的,托管网站的URL是SSL认证的,所以它通过HTTPS.它适用于Chrome应用,因此它也可以使用WebView.

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

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

谢谢.

Una*_*dra 12

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

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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());
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

记住的名字listproject,permissionwebview等可以被任何你需要改变的,只要你改变他们在文件中的名称空间和包的引用.

完成所有这些后,您需要创建的只是ReactNative组件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);
Run Code Online (Sandbox Code Playgroud)

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

有了这个,一切都应该工作,WebView组件应该在使用时请求权限.

编辑:

我已将代码上传到我的Github存储库.我只更改了一些名称,但核心代码没有改变,以确保它仍然有效(我无法测试它,所以最好不要改变很多东西).

希望它可以帮到某人!