Katharine Osborne
Katharine Osborne

Reputation: 7031

Simple example for accessing the camera via WebRTC in react-native (Android)

I'm trying to adapt an augmented reality app I wrote in JS that only works in Firefox on Android to a react native app that can work in either Android or iOS. Since I need the camera input, I'm using react-native-webrtc (rather than importing the html and js I have been using, since I'm also trying to reduce framerate lag). I've been trying to parse out the demo here:

https://github.com/oney/RCTWebRTCDemo/blob/master/main.js

But the demo app is quite complex since it is a video chatroom (from what I can surmise). I just need to access the camera and keep it as the background of the app. This is what I have so far:

import React, { Component } from 'react';
import {
    AppRegistry,
    View,
} from 'react-native';

import {
   RTCPeerConnection,
   RTCMediaStream,
   RTCIceCandidate,
   RTCSessionDescription,
   RTCView,
   MediaStreamTrack,
   getUserMedia,
 } from 'react-native-webrtc';

 let localStream;

 function getLocalStream(isFront, callback) {
     MediaStreamTrack.getSources(sourceInfos => {
     let videoSourceId;
     for (const i = 0; i < sourceInfos.length; i++) {
         const sourceInfo = sourceInfos[i];
         if(sourceInfo.kind == "video" && sourceInfo.facing == (isFront ? "front" :  "back")) {
             videoSourceId = sourceInfo.id;
         }
     }
     getUserMedia({
         audio: false,
         video: {
             mandatory: {
                 minWidth: 500,
                 minHeight: 300,
                 minFrameRate: 30
             },
             facingMode: (isFront ? "user" : "environment"),
             optional: [{ sourceId: sourceInfos.id}]
         }
     }, function(stream) {
         console.log("dddd", stream);
         callback(stream);
         }, logError);
     });
 }

 function logError(error) {
    console.log("logError: ", error);
 }

 let container;

 var CanvasTest = React.createClass({
     getInitialState: function() {
         return {
         isFront: true,
         selfViewSrc: null};
     },
     componentDidMount: function() {
         container = this;
     },
     render() {
         return (
             <View>
                 <RTCView streamURL={this.state.selfViewSrc} />
                 {console.log("this.state: ", this.state)}
                 {getLocalStream(true, function(stream) {
                     //localStream = stream;
                     //container.setState({selfViewSrc: stream.toURL()});
                 })
               }
             </View>
         );
     }
 });

AppRegistry.registerComponent('CanvasTest', () => CanvasTest);

Everything is okay until I try to call the getLocalStream function. I get an "undefined is not an object" error for that line. (I've commented out the lines inside the callback to see if they are causing the problem, they are not).

This is what I get from the console in Android Studio:

E/ReactNativeJS: undefined is not an object (evaluating 'WebRTCModule.mediaStreamTrackGetSources')
E/EGL_emulation: tid 3106: eglSurfaceAttrib(1165): error 0x3009 (EGL_BAD_MATCH)
W/OpenGLRenderer: Failed to set EGL_SWAP_BEHAVIOR on surface 0xa0899300, error=EGL_BAD_MATCH

I think I'm calling the function in the wrong place. I want the view to load up the camera stream when the app starts. What am I doing wrong?

Is there a simpler example somewhere of using WebRTC in react native?

Upvotes: 1

Views: 10296

Answers (1)

zxcpoiu
zxcpoiu

Reputation: 316

About undefined is not an object It may because of not install it properly.

I'd suggest restart a fresh build again:

  1. remove npm module: rm -rf $YourProject/node_modules/react-native-webrtc
  2. clean npm cache: npm cache clean
  3. clear gradle build intermediate files or
    clear xocde project by Product -> clean
    ( it depends on your env )
  4. npm install react-native-webrtc
  5. follow the documents steps by steps carefully (Android / iOS)

be sure grant all permissions mentions on documents then try again.

Where to execute getLocalStream()

in your case, you can execute it in ComponentDidMount otherwise, in some case, app may warn that you can't setState() in render()

(setState() will trigger render() normally, the warning is to prevent infinite loop.)

Suggestion

I would suggest you to NOT test it on simulators as possible for libraries which needs to access lots of hardware's functionalities.

Upvotes: 3

Related Questions