this is my react native webRTC implementation:
import React, { useState, useEffect } from 'react';
import { View, SafeAreaView, Button, TextInput, KeyboardAvoidingView } from 'react-native';
import { RTCView, mediaDevices, RTCPeerConnection, RTCSessionDescription, RTCIceCandidate } from 'react-native-webrtc';
const HomeScreen = () => {
function send(message) {
conn.send(JSON.stringify(message));
}
const[remoteStream, setRemoteStream] = useState(null);
const[localStream, setLocalStream] = useState(null);
const[webcamStarted, setWebcamStarted] = useState(false);
const configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] };
const peerConnection = new RTCPeerConnection(configuration)
peerConnection.addEventListener('track', async (event) => {
setRemoteStream(event.streams[0]);
console.log(remoteStream)
});
peerConnection.addEventListener('icecandidate', event => {
if (event.candidate) {
send({
event : "candidate",
data : event.candidate
});
}
});
var conn = new WebSocket('ws://your ip address:8080/socket');//change with your ip
conn.onmessage = async (event) => {
console.log("Messaggio ricevuto:", event.data);
// Analizza il messaggio JSON ricevuto
const message = JSON.parse(event.data);
if (message.event === "answer" && message.data) {
const answer = new RTCSessionDescription(message.data);
try {
await peerConnection.setRemoteDescription(answer);
console.log("Descrizione remota impostata con successo.");
} catch (error) {
console.log(answer)
console.error("Errore nell'impostazione della descrizione remota:", error);
}
}
// Controlla se il messaggio contiene un candidato ICE
if (message.event === "candidate" && message.data) {
// Estrai il candidato ICE dal messaggio
const candidate = new RTCIceCandidate(message.data);
// Aggiungi il candidato ICE al tuo peerConnection
peerConnection.addIceCandidate(candidate)
.then(() => {
console.log('ICE candidate aggiunto con successo');
})
.catch(error => {
console.error('Errore nell aggiungere l ICE candidate:', error);
});
}
if (message.event === "offer" && message.data ) {
const offer = new RTCSessionDescription(message.data);
await peerConnection.setRemoteDescription(offer);
try {
const answer = await peerConnection.createAnswer();
console.log('Risposta creata con successo');
console.log(answer)
await send({
event : "answer",
data : answer
});
await peerConnection.setLocalDescription(answer);
} catch (error) {
console.error('Errore durante l invio della risposta al server di segnalazione');
}
}
};
//var dataChannel = peerConnection.createDataChannel("dataChannel", { reliable: true });
//dataChannel.onerror = function(error) {
//console.log("Error:", error);
//};
//dataChannel.onclose = function() {
//console.log("Data channel is closed");
//};
const startWebcam = async () => {
try {
const stream = await mediaDevices.getUserMedia({
video: true,
audio: true,
});
setWebcamStarted(true);
setLocalStream(stream);
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
} catch (error) {
console.error('Errore durante l invio della risposta al server di segnalazione');
}
const offer = await peerConnection.createOffer();
//console.log('offer',offer)
await peerConnection.setLocalDescription(offer);
send({
event: "offer",
data: peerConnection.localDescription
});
}
return (
<KeyboardAvoidingView style={styles.body} behavior="position">
<SafeAreaView>
<RTCView
streamURL={remoteStream?.toURL()}
style={styles.stream}
objectFit="cover"
mirror
/>
<View style={styles.buttons}>
{!webcamStarted && (
<Button title="Start webcam" onPress={startWebcam} />
)}
{webcamStarted && (
<Button title="Stop webcam" onPress={() => setLocalStream(null)} />
)}
</View>
</SafeAreaView>
</KeyboardAvoidingView>
);
}
const styles = {
body: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
stream: {
width: '100%',
height: 300,
},
buttons: {
marginTop: 20,
},
};
export default HomeScreen;
the code works I hope it will help you if you have any advice are welcome below place other code is a react webRTC application for browser not for android as the code above my purpose is to make the android application communicate via video call with the browser application. IMPORTANT: it only works in this sequence both apps must be connected to a websocket server that I created with springboot :https://www.baeldung.com/webrtc, once connected both, so as soon as the variable conn is instantiated with the address of my websocket server I start the stream on the WEB application(not the react-native application I recommend first start the stream on the web application) as you can see the audio video call works even if from errors and has a bug or even if after starting the camera on the browser application I do not start the camera on the React Native application for Android works this is the code for the browser app name of file client.js
const localVideo = document.getElementById('localVideo');
const remoteVideo = document.getElementById('remoteVideo');
const startButton = document.getElementById('startButton');
const hangupButton = document.getElementById('hangupButton');
const configuration = { iceServers: [{ urls: 'stun:stun.l.google.com:19302' }] };
console.log(configuration,"config del server stun");
var conn = new WebSocket('ws://localhost:8080/socket');
const peerConnection = new RTCPeerConnection(configuration);
function send(message) {
conn.send(JSON.stringify(message));
}
conn.onmessage = async (event) => {
//console.log("Messaggio ricevuto:", event.data);
// Analizza il messaggio JSON ricevuto
const message = JSON.parse(event.data);
if (message.event === "answer" && message.data) {
const answer = new RTCSessionDescription(message.data);
try {
await peerConnection.setRemoteDescription(answer);
console.log("Descrizione remota impostata con successo.");
} catch (error) {
console.error("Errore nell'impostazione della descrizione remota:", error);
}
}
// Controlla se il messaggio contiene un candidato ICE
if (message.event === "candidate" && message.data) {
// Estrai il candidato ICE dal messaggio
const candidate = new RTCIceCandidate(message.data);
// Aggiungi il candidato ICE al tuo peerConnection
peerConnection.addIceCandidate(candidate)
.then(() => {
console.log('ICE candidate aggiunto con successo',message.data);
})
.catch(error => {
console.error('Errore nell aggiungere l ICE candidate:', error);
});
}
if (message.event === "offer" && message.data ) {
const offer = new RTCSessionDescription(message.data);
await peerConnection.setRemoteDescription(offer);
try {
const answer = await peerConnection.createAnswer();
console.log('Risposta creata con successo');
send({
event : "answer",
data : answer
});
await peerConnection.setLocalDescription(answer);
} catch (error) {
console.error('Errore durante l invio della risposta al server di segnalazione');
}
}
};
//let localStream;
//let peerConnection;
startButton.addEventListener('click', startVideoChat);
hangupButton.addEventListener('click', hangUp);
async function startVideoChat() {
try {
localStream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true });
localVideo.srcObject = localStream;
localStream.getTracks().forEach(track => peerConnection.addTrack(track, localStream));
//peerConnection.addEventListener('track', async (event) => {
//remoteVideo.srcObject = event.streams[0];
//});
var dataChannel = peerConnection.createDataChannel("dataChannel", { reliable: true });
dataChannel.onerror = function(error) {
console.log("Error:", error);
};
dataChannel.onclose = function() {
console.log("Data channel is closed");
};
const offer = await peerConnection.createOffer();
await peerConnection.setLocalDescription(offer);
send({
event: "offer",
data: offer
});
peerConnection.onicecandidate = handleIceCandidate;
peerConnection.ontrack = handleTrack;
} catch (error) {
console.error('Errore durante l invio della risposta al server di segnalazione');
}
}
function handleIceCandidate(event) {
console.log(event.candidate)
//if (event.candidate) {
// Invia l'ICE candidate al server o all'altro peer
send({
event : "candidate",
data : event.candidate
});
//}
}
function handleTrack(event) {
remoteVideo.srcObject = event.streams[0];
}
function hangUp() {
peerConnection.close();
localStream.getTracks().forEach(track => track.stop());
localVideo.srcObject = null;
remoteVideo.srcObject = null;
}
this is the html fil index.html that use javascript code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebRTC Video Chat</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h1>WebRTC Video Chat</h1>
<div class="video-container">
<video id="localVideo" autoplay muted></video>
<video id="remoteVideo" autoplay></video>
</div>
<div class="controls">
<button id="startButton">Start Video Chat</button>
<button id="hangupButton">Hang Up</button>
</div>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
<script src="client.js"></script>
</body>
</html>
That’s all you have the code to make two applications communicate for questions ask as well for improvements I’m here to learn.