Example React Native webRTC

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.