首页 文章

React Native Android Webview Video

提问于
浏览
11

我正在使用React Native创建一个Android / iOS应用程序,并尝试在WebView组件中播放视频 . 视频在iOS上运行正常,但我无法在Android WebView中播放它 .

我遇到过像这样的一些线程(Enabling HTML5 video playback in android WebView?),声称这是Android上相当常见的问题,可以通过导入WebChromeClient并在webview上设置该选项来解决,如下所示:

mainWebView.setWebChromeClient(new WebChromeClient());

但几乎所有这些线程都严格关于构建原生Android应用程序而不使用React Native .

有谁知道如何在React Native中使用它?

1 回答

  • 9

    我指的是article by Yevgen Safronov

    他写道,在里面

    显然,该应用程序中最具挑战性的部分是处理实时视频流,因为它需要根据可用的Internet带宽切换流的视频质量 . 但首先要做的是 - 我需要一个RN原生组件来显示任何视频流 . RN有一个流行的视频组件,但它仅支持iOS . 我决定在Vitamio播放器周围编写自己的RN组件包装器 . 它是众所周知的开源项目,并支持我们用于移动应用程序的RTMP协议 . 我以前没有编写本机RN组件的经验,所以我直接去了RN文档,了解如何创建一个 . 我所指的指南称为Native UI Components,iOS也有类似指南 . 声明有几个必要部分:实现自定义ViewManager(Android部分)注册ViewManager(Android部分)实现JavaScript模块注册模块(Android部分)实现自定义ViewManager参考声明VideoView for Vitamio的例子这是如何实质的VideoView声明看起来像:

    public class VideoViewDemo extends Activity {
     @Override public void onCreate(Bundle icicle) {
       super.onCreate(icicle);
       if (!LibsChecker.checkVitamioLibs(this))
         return;
       setContentView(R.layout.videoview);
       mEditText = (EditText) findViewById(R.id.url);
       mVideoView = (VideoView) findViewById(R.id.surface_view);
       if (path == "") { return; }
       mVideoView.setVideoPath(path);
       mVideoView.setMediaController(new MediaController(this));
       mVideoView.requestFocus();
     }
    ...
    }
    

    代码看起来非常简单 . 除了将对Activity的引用传递给LibsChecker之外,VideoView还需要一条路径来访问视频流和MediaController的实例 .

    public class VitamioViewManager extends SimpleViewManager<VideoView>{ 
     public static final String REACT_CLASS = “RCTVitamioView”;
     @Override
     public String getName() {
       return REACT_CLASS;
     }
    

    使用ReactProp公开setStreamUrl setter:

    @ReactProp(name = "streamUrl")
    public void setStreamUrl(VideoView view, @Nullable String streamUrl) {
       if (!LibsChecker.checkVitamioLibs(mActivity))
          return;
    
       view.setVideoPath(streamUrl);       
       view.setMediaController(new MediaController(mContext));
       view.requestFocus();       
    }
    

    添加createViewInstance实现:

    private ThemedReactContext mContext = null;
    private Activity mActivity = null;
    @Override
    public VideoView createViewInstance(ThemedReactContext context){
      mContext = context;   
      return new VideoView(context);
    }
    One note about the code. Because LibsChecker requires an instance of Activity we will receive it via constructor, it will reference root activity used for RN application;
    public VitamioViewManager(Activity activity) {
      mActivity = activity;
    }
    

    注册ViewManager最后的Java步骤是将ViewManager注册到应用程序,这通过应用程序包成员函数createViewManagers发生:...

    public class VitamioViewPackage implements ReactPackage {
    
      private Activity mActivity = null;
    
      public VitamioViewPackage(Activity activity) {
          mActivity = activity;
      }
    
    
      @Override    
      public List<NativeModule>
      createNativeModules(ReactApplicationContext reactContext) {
         return Collections.emptyList();
      }  
      @Override
      public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
      }     
      @Override
      public List<ViewManager>
      createViewManagers(ReactApplicationContext reactContext) {
        return Arrays.<ViewManager>asList(
          new VitamioViewManager(mActivity)
        );    
      }
    }
    

    实现JavaScript模块为了在JavaScript中公开自定义UI组件,必须调用特殊的requireNativeComponent函数:

    var { requireNativeComponent, PropTypes } = require('react-native');
    
    var iface = {
      name: 'VideoView',
      propTypes: {
        streamUrl: PropTypes.string
      }
    };
    
    module.exports = requireNativeComponent('RCTVitamioView', iface);
    

    注册模块虽然在官方文档中没有提到必要的步骤,但我们需要它,因为参考了根活动:package com.vitamio_demo;

    import com.facebook.react.ReactActivity;
    import com.facebook.react.ReactPackage;
    import com.facebook.react.shell.MainReactPackage;
    
    import java.util.Arrays;
    import java.util.List;
    
    import com.sejoker.VitamView.VitamioViewPackage; // <--- import
    
    public class MainActivity extends ReactActivity {
    
        /**
         * Returns the name of the main component registered from JavaScript.
         * This is used to schedule rendering of the component.
         */
        @Override
        protected String getMainComponentName() {
            return "vitamio_demo";
        }
    
        /**
         * Returns whether dev mode should be enabled.
         * This enables e.g. the dev menu.
         */
        @Override
        protected boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }
    
       /**
       * A list of packages used by the app. If the app uses additional views
       * or modules besides the default ones, add more packages here.
       */
        @Override
        protected List<ReactPackage> getPackages() {
          return Arrays.<ReactPackage>asList(
            new MainReactPackage(),
            new VitamioViewPackage(this)          // <------ add here
          );
        }
    }
    

    用法示例在项目中安装包:

    npm i react-native-android-vitamio --save
    

    DeclareVideoView:

    var VitamioView = require('react-native-android-vitamio');
    
    class VideoScreen extends React.Component {
      render() {
        return (
          <View>
            <VitamioView style={styles.video} streamUrl="rtmp://fms.12E5.edgecastcdn.net/0012E5/mp4:videos/8Juv1MVa-485.mp4"/>
          </View>
        );
      }
    }
    
    
    var styles = StyleSheet.create({
      video: {
          flex: 1,
          flexDirection: 'row',
          height: 400,
        }
    })
    
    module.exports = VideoScreen;
    

    希望这是有帮助的,文章中给出了他自己的参考文献列表 .

相关问题