Android Dev

Methods to Add Video Calling to a React Native App

By Krissanawat

Video calling has change into a necessary daily exercise through the COVID-19 pandemic. By utilizing options resembling chat apps, audio calling, and video calling, we have now been in a position to keep related with our family and friends.

Now, let’s create our personal React Native app that may allow us to make video calls.

On this tutorial, we’re going to learn to implement a video calling characteristic within the React Native app utilizing the Twilio programmable video name API.

The method is fairly simple. We’ll merely create a video convention room and invite others to affix that room. To do that, we’re going to want entry to the digicam and microphone. So we’ll want to make use of an actual smartphone machine for testing functions.

The principle package deal we’re going to use to entry the Twilio API is the react-native-twilio-video-webrtc package deal.

Necessities

Let’s get began!

Methods to Get Your Twilio API Key

As a way to get your Twilio API key, you’re going to want a Twilio account. For that, go to this URL. After organising your account, you want to go to the placement directed by the screenshot under:

Image

Methods to Setup the Server to Deal with Fetching the Entry Token

To fetch the entry token, we have to create a brand new Node server venture. For that, we have to set up the required packages by operating the next command:

yarn add dotenv specific ngrok nodemon twilio

Subsequent, we have to add Twilio credentials within the atmosphere variables file – .env, as proven within the code snippet under:

PORT=3000
ACCOUNT_SID=AC5ceb0847c50c91b143ce07
API_KEY_SID=SKa173c10de99a26fd86969b
API_KEY_SECRET=Czv7IjNIZJis8s7jb5FePi

Now we have to create an API endpoint. First, we have to import the required packages and create object situations to acquire the entry token as directed within the code snippet under:

import 'dotenv/config';
import specific from 'specific';

import twilio from 'twilio';
import ngrok from 'ngrok';
const AccessToken = twilio.jwt.AccessToken;
const VideoGrant = AccessToken.VideoGrant;

const app = specific();

Right here, we’re going to create an API endpoint to get the entry token. By utilizing the get technique supplied by the Specific occasion, we have to create an endpoint operate that responds with the entry token.

Contained in the operate, we have to create a brand new occasion with Twillio credentials. Then, we have to add the username that we acquired from the register display screen on the cellular machine as an id attribute.

Lastly, we’ll grant entry to the person to allow them to use the video after which return the JWT token again to the machine. Here is the code to do all this within the snippet under:

app.get('/getToken', (req, res) => {
  if (!req.question || !req.question.userName) {
    return res.standing(400).ship('Username parameter is required');
  }
  const accessToken = new AccessToken(
    course of.env.ACCOUNT_SID,
    course of.env.API_KEY_SID,
    course of.env.API_KEY_SECRET,
  );

  
  accessToken.id = req.question.userName;

  
  var grant = new VideoGrant();
  accessToken.addGrant(grant);

  
  var jwt = accessToken.toJwt();
  return res.ship(jwt);
});

We additionally expose the endpoint API we created to the web for the east entry. For that, we will use the code from the next code snippet:

app.pay attention(course of.env.PORT, () =>
  console.log(`Server listening on port ${course of.env.PORT}!`),
);

ngrok.join(course of.env.PORT).then((url) => {
  console.log(`Server forwarded to public url ${url}`);
});

Lastly, we have to run the server as proven within the screenshot under:

Image

Right here, we have now efficiently created an API endpoint to return the entry token.

Methods to Configure Our React Native Venture

In our React Native venture, we have to arrange the packages manually in addition to configure permissions to entry the digicam and microphone for each Android and iOS platforms.

However first, we have to set up the required packages, that are react-navigation and react-native-twilio-video-webrtc, by operating the next command in our venture terminal:

yarn add @react-navigation/native @react-navigation/stack react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view react-native-dotenv react-native-permissions <https://github.com/blackuy/react-native-twilio-video-webrtc>

Setup for iOS

For iOS, we have to arrange the package deal manually. First, we have to increment the IOS goal to 11 on the Podfile. That is needed as a result of Twilio’s Native Video SDK only has support for iOS 11.0+:

platform :ios, '11.0'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

In Podfile, we have to setup a permission request as directed within the code snippet under:

permissions_path = '../node_modules/react-native-permissions/ios'
  pod 'Permission-Digital camera', :path => "#{permissions_path}/Digital camera.podspec"
  pod 'Permission-Microphone', :path => "#{permissions_path}/Microphone.podspec"

Then, we have to open information.plist and add code to request permission for digicam and microphone entry as directed within the code snippet under:

  <key>UIViewControllerBasedStatusBarAppearance</key>
    <false/>
  <key>NSCameraUsageDescription</key>
  <string>We require your permission to entry the digicam whereas in a video name</string>
  <key>NSMicrophoneUsageDescription</key>
  <string>We require your permission to entry the microphone whereas in a video name</string>

Now we’re executed with our iOS setup.

Setup for Android

Firstly, we have to add the next line of code to the ./android/settings.gradle file:

venture(':react-native-twilio-video-webrtc').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-twilio-video-webrtc/android')

Additionally, we have to add package deal implementation code to the ./android/app/construct.gradle file:

implementation venture(':react-native-twilio-video-webrtc')

Lastly, we have to import this to the MainApplication.java file as nicely:

import com.twiliorn.library.TwilioPackage;

Then, we have to activate the package deal through the use of the next piece of code:

@Override
protected Checklist getPackages() {
  @SuppressWarnings("UnnecessaryLocalVariable")
  Checklist packages = new PackageList(this).getPackages();
  
  packages.add(new TwilioPackage());
  return packages;
}

Methods to Construct the Register Room Display screen

Right here, we’re going to create a display screen known as “Register Room” which goes to permit us to register to a room in our video calling React Native app.

First, we have to import the required packages as proven within the code snippet under:

import React, {useState, useRef, useEffect, useContext} from 'react';
import {
  StyleSheet,
  View,
  Textual content,
  StatusBar,
  TouchableOpacity,
  TextInput,
  Alert,
  KeyboardAvoidingView,
  Platform,
  ScrollView,
  Dimensions,
} from 'react-native';

import {
  TwilioVideoLocalView,
  TwilioVideoParticipantView,
  TwilioVideo,
} from 'react-native-twilio-video-webrtc';

import {NavigationContainer} from '@react-navigation/native';
import {createStackNavigator} from '@react-navigation/stack';
  • react-navigation: To deal with the navigation of the register display screen and video name display screen.
  • react-native: This packages permits us to deal with permissions to entry the digicam and microphone.
  • react-native-twilio-video-webrtc: this permits us to entry Twilio’s Video name programmable API.

Methods to Initialize Cases and Variables

First, we’re going to create an occasion for react-navigation. Then, we’re going to initialize the states in addition to context variables to distribute states as proven within the code snippet under:

const Stack = createStackNavigator();
const initialState = {
  isAudioEnabled: true,
  standing: 'disconnected',
  contributors: new Map(),
  videoTracks: new Map(),
  userName: '',
  roomName: '',
  token: '',
};

const AppContext = React.createContext(initialState);

const dimensions = Dimensions.get('window');

Bootstrap Navigation

Within the App.js file, we’re going to create a navigation container stack. Utilizing the Stack element we’re going to distribute state to each display screen utilizing context as directed within the code snippet under:

export default () => {
  const [props, setProps] = useState(initialState);

  return (
    <>
      <StatusBar barStyle="dark-content" />
      <AppContext.Supplier worth={{props, setProps}}>
        <NavigationContainer>
          <Stack.Navigator>
            <Stack.Display screen title="House" element={HomeScreen} />
            <Stack.Display screen title="Video Name" element={VideoCallScreen} />
          </Stack.Navigator>
        </NavigationContainer>
      </AppContext.Supplier>
    </>
  );
};

Methods to Create the Register Display screen

The Register display screen could have a modal dialog to get the person’s credentials and permit customers to affix the video name room.

First, we have to fetch the props from the context to the register.js file as proven within the code snippet under:

import React, {useState, useRef, useEffect, useContext} from 'react';
import {
  checkMultiple,
  request,
  requestMultiple,
  PERMISSIONS,
  RESULTS,
} from 'react-native-permissions';

const RegisterScreen = ({navigation}) => {
  const {props, setProps} = useContext(AppContext);

Subsequent, we have to create a operate to deal with the digicam and microphone permissions. The code for the operate is supplied within the code snippet under:

const _checkPermissions = (callback) => {
    const iosPermissions = [PERMISSIONS.IOS.CAMERA, PERMISSIONS.IOS.MICROPHONE];
    const androidPermissions = [
      PERMISSIONS.ANDROID.CAMERA,
      PERMISSIONS.ANDROID.RECORD_AUDIO,
    ];
    checkMultiple(
      Platform.OS === 'ios' ? iosPermissions : androidPermissions,
    ).then((statuses) => {
      const [CAMERA, AUDIO] =
        Platform.OS === 'ios' ? iosPermissions : androidPermissions;
      if (
        statuses[CAMERA] === RESULTS.UNAVAILABLE ||
        statuses[AUDIO] === RESULTS.UNAVAILABLE
      ) {
        Alert.alert(
          'Error',
          '{Hardware} to help video calls isn't obtainable',
        );
      } else if (
        statuses[CAMERA] === RESULTS.BLOCKED ||
        statuses[AUDIO] === RESULTS.BLOCKED
      ) {
        Alert.alert(
          'Error',
          'Permission to entry {hardware} was blocked, please grant manually',
        );
      } else {
        if (
          statuses[CAMERA] === RESULTS.DENIED &&
          statuses[AUDIO] === RESULTS.DENIED
        ) {
          requestMultiple(
            Platform.OS === 'ios' ? iosPermissions : androidPermissions,
          ).then((newStatuses) => {
            if (
              newStatuses[CAMERA] === RESULTS.GRANTED &&
              newStatuses[AUDIO] === RESULTS.GRANTED
            ) {
              callback && callback();
            } else {
              Alert.alert('Error', 'One of many permissions was not granted');
            }
          });
        } else if (
          statuses[CAMERA] === RESULTS.DENIED ||
          statuses[AUDIO] === RESULTS.DENIED
        ) {
          request(statuses[CAMERA] === RESULTS.DENIED ? CAMERA : AUDIO).then(
            (outcome) => {
              if (outcome === RESULTS.GRANTED) {
                callback && callback();
              } else {
                Alert.alert('Error', 'Permission not granted');
              }
            },
          );
        } else if (
          statuses[CAMERA] === RESULTS.GRANTED ||
          statuses[AUDIO] === RESULTS.GRANTED
        ) {
          callback && callback();
        }
      }
    });
  };

Then, we have to name this permission-checking operate each time the app begins. For that, we have to name the operate contained in the useEffect hook as directed within the code snippet under:

useEffect(() => {
    _checkPermissions();
  }, []);

Lastly, we have to create a easy kind with two inputs that settle for room title and person title. Then, we have to ship the inputs to the server to register on the Twilio API. The code for that is supplied within the code snippet under:

return (
    <KeyboardAvoidingView
      habits={Platform.OS === 'ios' ? 'padding' : 'peak'}
      fashion={types.container}>
      <ScrollView contentContainerStyle={types.container}>
        <View fashion={types.kind}>
          <View fashion={types.formGroup}>
            <Textual content fashion={types.textual content}>Person Title</Textual content>
            <TextInput
              fashion={types.textInput}
              autoCapitalize="none"
              worth={props.userName}
              onChangeText={(textual content) => setProps({...props, userName: textual content})}
            />
          </View>
          <View fashion={types.formGroup}>
            <Textual content fashion={types.textual content}>Room Title</Textual content>
            <TextInput
              fashion={types.textInput}
              autoCapitalize="none"
              worth={props.roomName}
              onChangeText={(textual content) => setProps({...props, roomName: textual content})}
            />
          </View>
          <View fashion={types.formGroup}>
            <TouchableOpacity
              disabled={false}
              fashion={types.button}
              onPress={() => {
                _checkPermissions(() => {
                  fetch(`https://ae7a722dc260.ngrok.io/getToken?userName=${props.userName}`)
                    .then((response) => {
                      if (response.okay) {
                        response.textual content().then((jwt) => {
                          setProps({...props, token: jwt});
                          navigation.navigate('Video Name');
                          return true;
                        });
                      } else {
                        response.textual content().then((error) => {
                          Alert.alert(error);
                        });
                      }
                    })
                    .catch((error) => {
                      console.log('error', error);
                      Alert.alert('API not obtainable');
                    });
                });
              }}>
              <Textual content fashion={types.buttonText}>Hook up with Video Name</Textual content>
            </TouchableOpacity>
          </View>
        </View>
      </ScrollView>
    </KeyboardAvoidingView>
  );

We’ll get the outcome as proven within the emulator screenshot under:

Image

Right here, we will discover our Register Room display screen with a modal kind the place we will enter the room title and person title as a way to register to the Twilio API operating on the server.

Methods to Construct the Video Name Display screen

Within the Video Name Display screen, we’re going to have two home windows – one to show our personal digicam’s view, and the opposite to show the recipient’s digicam’s view.

First, we have to initialize the context to simply accept the states. Then we’ll create a reference variable utilizing the useRef hook to entry the states as directed within the code snippet under:

const VideoCallScreen = ({navigation}) => {
  const twilioVideo = useRef(null);
  const {props, setProps} = useContext(AppContext);

Subsequent, we have to initialize the connection utilizing the join technique from the twilioVideo object, offering the room title and entry token as directed within the code snippet under:

useEffect(() => {
    twilioVideo.present.join({
      roomName: props.roomName,
      accessToken: props.token,
    });
    setProps({...props, standing: 'connecting'});
    return () => {
      _onEndButtonPress();
    };
  }, []);

Now, we have to create the principle physique template for the Video Name Display screen. Right here, we present the participant’s digicam view solely when the connection is established and streaming utilizing conditional rendering. The general code for that is supplied within the code snippet under:

{(props.standing === 'related' || props.standing === 'connecting') && (
        <View fashion={types.callWrapper}>
          {props.standing === 'related' && (
            <View fashion={types.grid}>
              {Array.from(props.videoTracks, ([trackSid, trackIdentifier]) => (
                <TwilioVideoParticipantView
                  fashion={types.remoteVideo}
                  key={trackSid}
                  trackIdentifier={trackIdentifier}
                />
              ))}
            </View>
          )}
        </View>
      )}

Subsequent, we have to create capabilities to regulate the in-video options resembling finish name, mute, and switching back and front digicam. The coding implementation of the required capabilities are supplied within the code snippet under:

const _onEndButtonPress = () => {
    twilioVideo.present.disconnect();
    setProps(initialState);
  };

  const _onMuteButtonPress = () => {
    twilioVideo.present
      .setLocalAudioEnabled(!props.isAudioEnabled)
      .then((isEnabled) => setProps({...props, isAudioEnabled: isEnabled}));
  };

  const _onFlipButtonPress = () => {
    twilioVideo.present.flipCamera();
  };

Right here, we used the disconnect, setLocalAudioEnabled and flipCamera strategies supplied by twilioVideo occasion to set off the required in-video options.

Now we have to render out some buttons to set off the capabilities. For that, we have to use the code from the next code snippet:

       <View fashion={types.optionsContainer}>
        <TouchableOpacity fashion={types.button} onPress={_onEndButtonPress}>
          <Textual content fashion={types.buttonText}>Finish</Textual content>
        </TouchableOpacity>
        <TouchableOpacity fashion={types.button} onPress={_onMuteButtonPress}>
          <Textual content fashion={types.buttonText}>
            {props.isAudioEnabled ? 'Mute' : 'Unmute'}
          </Textual content>
        </TouchableOpacity>
        <TouchableOpacity fashion={types.button} onPress={_onFlipButtonPress}>
          <Textual content fashion={types.buttonText}>Flip</Textual content>
        </TouchableOpacity>
      </View>

The final step is so as to add the TwilioVideo element that’s configured to deal with and observe all of the video calling occasions. The general configured TwilioVideo element is supplied within the code snippet under:

      <TwilioVideo
        ref={twilioVideo}
        onRoomDidConnect={() => {
          setProps({...props, standing: 'related'});
        }}
        onRoomDidDisconnect={() => {
          setProps({...props, standing: 'disconnected'});
          navigation.goBack();
        }}
        onRoomDidFailToConnect={(error) => {
          Alert.alert('Error', error.error);
          setProps({...props, standing: 'disconnected'});
          navigation.goBack();
        }}
        onParticipantAddedVideoTrack={({participant, observe}) => {
          if (observe.enabled) {
            setProps({
              ...props,
              videoTracks: new Map([
                ...props.videoTracks,
                [
                  track.trackSid,
                  {
                    participantSid: participant.sid,
                    videoTrackSid: track.trackSid,
                  },
                ],
              ]),
            });
          }
        }}
        onParticipantRemovedVideoTrack={({observe}) => {
          const videoTracks = props.videoTracks;
          videoTracks.delete(observe.trackSid);
          setProps({...props, videoTracks});
        }}
      />

We’ll get the next outcome if we’re in a position to set up the right connection between customers in a room:

Image

The screenshots above show video calling between two contributors in a room.

With this, we have now efficiently carried out the Video Calling characteristic in our React Native app.

Conclusion

This tutorial aimed to ship a beginner-level studying useful resource on tips on how to setup Video Calling in a React Native app. We did this through the use of Twilio’s programmable video name API.

We not solely coated the React Native half but in addition the general API implementation in a separate Node server venture.

Now, the following step may be so as to add superior options resembling beginning an nameless name or a number of participant video calling rooms.

For characteristic inspiration and a correct video calling app, you possibly can try instamobile.io that gives state of a Video Chat app with highly effective options.

See ya subsequent time people, Pleased Coding!

Source link

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button

Adblock Detected

Please consider supporting us by disabling your ad blocker