Hi all, I am working on a react native application with peer to peer video service. I have added webRTC dependency and I have written the complete flow for peer to peer video call. The local and remote description is getting set. But after that for some reason onicecandidate is not firing.
I have tried different ways and looked at multiple forums, but I am still unable to resolve this. Any help on this would be much appreciated.
Here is my code snippet
import React from 'react';
import { Text, View, Button } from 'react-native';
import {
mediaDevices,
RTCView,
RTCPeerConnection,
RTCSessionDescription,
MediaStream,
} from 'react-native-webrtc';
import DeviceInfo from 'react-native-device-info';
const serverUrl = 'ws://192.168.0.5:8080/socket';
const configuration = { iceServers: [{ url: 'stun:stun.l.google.com:19302' }] };
class DummyScreen extends React.Component {
constructor(props) {
super(props);
this.socket = new WebSocket(serverUrl);
this.uniqueId = DeviceInfo.getUniqueId();
this.peerConnection = new RTCPeerConnection(configuration);
this.state = {
localStream: new MediaStream(),
remoteStream: new MediaStream(),
error: null,
};
}
componentDidMount() {
this.socket.onopen = () => {
this.socket.send('Connected to server');
};
// streaming local camera output
const constraints = {
video: true,
};
mediaDevices
.getUserMedia(constraints)
.then((stream) => this.gotLocalStream(stream))
.catch((e) => this.setState({ error: e }));
// setting up listeners
this.peerConnection.onicecandidate = (event) => {
console.log('event-----------------------', event);
if (event.candidate) {
console.log(
`${this.uniqueId} recieved local ice candidate: ${event.candidate}`
);
this.socket.send(JSON.stringify({ iceCandidate: event.candidate }));
console.log(
`${this.uniqueId} send local ice candidate: ${event.candidate} `
);
}
};
this.peerConnection.onconnectionstatechange = (event) => {
console.log(
this.uniqueId + ' Connection state changed: ',
event,
this.peerConnection
);
};
this.peerConnection.onaddstream = (event) => {
console.log(`${this.uniqueId} recieved remote stream: ${event} `);
this.state.remoteStream.addTrack(event.track, this.state.remoteStream);
};
this.socket.onmessage = async (m) => {
try {
let message;
try {
message = JSON.parse(m.data);
} catch (ex) {
// console.log(ex);
message = {};
}
// console.log(message);
if (message.offer) {
console.log(`${this.uniqueId} recieved offer: ${message.offer} `);
await this.peerConnection.setRemoteDescription(
new RTCSessionDescription(message.offer)
);
const answer = await this.peerConnection.createAnswer();
await this.peerConnection.setLocalDescription(answer);
this.socket.send(JSON.stringify({ answer: answer }));
console.log(`${this.uniqueId} sent answer: ${answer} `);
} else if (message.answer) {
console.log(`${this.uniqueId} recieved answer: ${message.answer} `);
await this.peerConnection.setRemoteDescription(
new RTCSessionDescription(message.answer) // accepting the answer
);
} else if (message.iceCandidate) {
try {
console.log(
`${this.uniqueId} add icecandidate: ${message.iceCandidate} `
);
await this.peerConnection.addIceCandidate(message.iceCandidate);
} catch (e) {
console.error(
this.uniqueId + ' Error adding received ice candidate',
e
);
}
} else {
console.log('message--');
console.log(message);
console.log('--message');
}
} catch (e) {
console.log(this.uniqueId + e);
}
};
}
gotLocalStream(stream) {
this.setState({ localStream: stream });
this.state.localStream.getTracks().forEach((track) => {
this.peerConnection.addTrack(track, this.state.localStream);
});
}
async makeCall() {
console.log(this.uniqueId + ' Making a call...');
const offer = await this.peerConnection.createOffer();
await this.peerConnection.setLocalDescription(offer); // I am calling
this.socket.send(JSON.stringify({ offer: offer }));
console.log(`${this.uniqueId} sent offer: ${offer} `);
}
render() {
return (
<View style={{ flex: 1 }}>
<Button
title="Switch Camera"
onPress={() => this.handleSwitchCamera()}
/>
{this.state.localStream ? (
<>
<Text>Local: </Text>
<RTCView
mirror={true}
streamURL={this.state.localStream.toURL()}
style={{ flex: 1 }}
/>
<Text>Remote: </Text>
<RTCView
mirror={true}
streamURL={this.state.remoteStream.toURL()}
style={{ flex: 1 }}
/>
<Button
title="Make a call"
color="red"
onPress={() => this.makeCall()}
/>
</>
) : (
<Text>
{this.state.error
? `An error occured: ${this.state.error}`
: 'Loading...'}
</Text>
)}
</View>
);
}
handleSwitchCamera() {
const { localStream } = this.state;
localStream.getVideoTracks().forEach((track) => {
track._switchCamera();
});
}
}
export default DummyScreen;