Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native Android Webview Video

I'm using React Native to create an Android/iOS app and trying to get a video to play in the WebView component. The video plays fine on iOS, but I'm having trouble getting it to play in the android WebView.

I've come across a few threads like this one (Enabling HTML5 video playback in android WebView?) that claim this is a fairly common problem on Android and can be solved by importing WebChromeClient and setting that option on the webview like so:

mainWebView.setWebChromeClient(new WebChromeClient());

But almost all these threads are strictly about building a native Android app and not using React Native.

Does anyone know how to get this to work in React Native?

like image 786
AndrewTet Avatar asked Jun 15 '16 05:06

AndrewTet


People also ask

How do I play a youtube video in React Native Webview?

/** * Sample React Native App * https://github.com/facebook/react-native * * @format * @flow strict-local */ import React from 'react'; import {View} from 'react-native'; import YoutubePlayer from 'react-native-youtube-iframe'; const App = () => { return ( <View> <YoutubePlayer height={300} play={true} videoId={' ...

How do I embed a Youtube video in React Native?

To achieve playing Youtube videos in React Native, we will be making use of the npm dependency named react-native-youtube-iframe. We will work through using this library by fully integrating it into an app.

Does React Native support Webview?

WebViews offer developers opportunities to render any web components in a React Native application. A web component can be anything from a whole webpage/application or just a simple HTML file. The package react-native-webview makes it super simple to embed WebViews into your React Native apps!


1 Answers

I refer to an article by Yevgen Safronov

In it, he writes

Obviously the most challenging part of the application is handling live video stream, because it requires switching stream’s video quality based on available Internet bandwidth. But first things first — I needed a RN native component to show any video stream. There is a popular video component for RN but it has support for iOS only. I decided to write my own RN component wrapper around Vitamio player. It is well known open-source project and has support of RTMP protocol we use for mobile app.

I had no prior experience with writing native RN components so I went directly to RN documentation on how to create one. A guide I refer to is called Native UI Components, there is similar one for iOS. There are several essential parts to declare:

Implement custom ViewManager (Android part)
Register the ViewManager (Android part)
Implement the JavaScript module
Register the module (Android part)

Implement custom ViewManager Referring to the example of declaring VideoView for Vitamio this is how the essence of VideoView declaration looks like:

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();
 }
...
}

The code looks quite straightforward. Apart from passing a reference to Activity into LibsChecker, VideoView requires a path to a video stream and instance of MediaController.

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

expose setStreamUrl setter using ReactProp:

@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();       
}

add createViewInstance implementation:

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;
}

Register the ViewManager The final Java step is to register the ViewManager to the application, this happens via the applications package member function 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)
    );    
  }
}

Implement the JavaScript module In order to expose custom UI component in JavaScript it is necessary to call special requireNativeComponent function:

var { requireNativeComponent, PropTypes } = require('react-native');

var iface = {
  name: 'VideoView',
  propTypes: {
    streamUrl: PropTypes.string
  }
};

module.exports = requireNativeComponent('RCTVitamioView', iface);

Register the module Although it’s not mentioned as required step in official documentation we need it because of reference to the root activity: 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
      );
    }
}

Example of usage Install the package in a project:

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;

Hope this is of help, A list of his own references is given in the article.

like image 156
Rachel Gallen Avatar answered Oct 12 '22 05:10

Rachel Gallen