web-dev-qa-db-ja.com

Reactネイティブ:Webview getUserMediaが機能していません(onPermissionRequestオーバーライド?)

iOS、Android and Windows with React Nativeで、ウェブページを表示する必要があるアプリケーションを開発しています。 WebView。そのWebページカメラにアクセスデバイスのため、MediaDevices.getUserMedia()Javascript関数を使用します。

デスクトップでは問題なく動作しますスマートフォンのChromeアプリでも)==。ただし、React)経由でウェブページを呼び出すと=ネイティブ_<WebView />_、PermissionDeniedエラーが発生します。問題はリクエストが表示されないその権限を受け入れさせることです。質問せずにリクエストを拒否するだけです。

これが私のWebView要素のサンプルです:

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

_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" />
_

はい、ウェブサイトがホストされているURLはSSL認定を受けているため、HTTPSを経由します。 Chromeアプリで動作するため、WebViewでも動作するはずです。

私はネットを読んでいますが、React Native WebViewにはonPermissionRequest()実装がないため、黙って失敗する(そして拒否する)ためだと思われますそれ)。

それを実装する方法はありますかネイティブWebViewをオーバーライドします in React Native?可能であれば、どのファイルを編集する必要がありますか?サードパーティのモジュールはありますか?最新)これは実装されていますか(何も見つかりませんでした)?

ありがとうございました。

10
Unapedra

最後に、ネイティブAndroidに独自のWebViewコンポーネントを実装する必要がありました。問題は、ネイティブWebViewに実装されていないonPermissionRequest()関数です。独自に作成し、その関数をオーバーライドする必要があります。私の場合、次のコードを追加する必要がありました(すべてのファイルはパス_[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();
    }
}
_

_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_:

_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()関数に追加します。

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

listprojectpermissionwebviewなどの名前は、ファイルの名前空間とパッケージ参照で変更する限り、必要に応じて変更できることに注意してください。 。

これらがすべて揃ったら、作成する必要があるのはReactNativeコンポーネントのエクスポート(_[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);
_

このコンポーネントはAndroid向けに作成されているため、インデックスの名前を_index.Android.js_に設定していることに注意してください。これは、Androidプラットフォームにのみ含まれています。

これにより、すべてが機能し、WebViewコンポーネントが使用されるときに許可を求める必要があります。

編集:

コードを Githubリポジトリ にアップロードしました。一部の名前を変更しただけですが、コアコードは、それがまだ機能することを確認するために少し変更されていません(テストできないため、多くのことを変更しない方がよいでしょう)。

それが誰かを助けることを願っています!

13
Unapedra