Open In App

Create a Calling App using React-Native

Last Updated : 05 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Building a Calling App using React-Native allows you to create a cross-platform application that supports voice calling. This tutorial will guide you through the process of integrating voice calling functionality into a React-Native app, enabling users to make and receive calls seamlessly.

Preview of final output: Let us have a look at how the final output will look like

Screenshot-2024-01-16-195011

Prerequisites:

Approach:

The app will utilize the Agora React Native SDK for voice calling. Key functionalities include initializing Agora Engine, joining and leaving channels, and handling user permissions for microphone and camera.

Steps to create the project:

Step 1: Setup a React Native environment for Voice Calling project

npx react-native init VoicecallApp --template react-native-template-typescript

Step 2: Navigate to the Android folder:

  • Open the android folder within your React Native project.
  • Create or Edit “local.properties”.
  • Inside the android folder, look for a file named local.properties. If it doesn’t exist, create a new file and name it local.properties.
  • Add sdk.dir Property:
  • Add the following line, replacing C:\\PATH\\TO\\ANDROID\\SDK with the actual path to your Android SDK (usually found in C:\\Users\\your-username\\AppData\\Local\\Android\\Sdk)
sdk.dir=C:\\PATH\\TO\\ANDROID\\SDK

Screenshot-2024-01-16-195819

Step 3: Navigate to the root folder of your project in the terminal and integrate with either:

npm i --save react-native-agora
  • If your target platform is iOS, use CocoaPods to install Voice Calling:
npx pod-install

Project structure:

Screenshot-2024-01-16-201625

The updated dependencies in package.json file will look like:

"dependencies": {
"react": "18.2.0",
"react-native": "0.73.2",
"react-native-agora": "^4.2.6"
},
"devDependencies": {
"@babel/core": "^7.20.0",
"@babel/preset-env": "^7.20.0",
"@babel/runtime": "^7.20.0",
"@react-native/babel-preset": "0.73.19",
"@react-native/eslint-config": "0.73.2",
"@react-native/metro-config": "0.73.3",
"@react-native/typescript-config": "0.73.1",
"@types/react": "^18.2.6",
"@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.6.3",
"eslint": "^8.19.0",
"jest": "^29.6.3",
"prettier": "2.8.8",
"react-test-renderer": "18.2.0",
"typescript": "5.0.4"
}

Step 4: Add the following code in App.tsx, Replacing the appId, channelName, and token which we will see how ot generate in next step.

Javascript




//App.tsx
 
import React, { useRef, useState, useEffect } from 'react';
import {
    SafeAreaView,
    ScrollView,
    StyleSheet,
    Text,
    View,
    TouchableOpacity,
} from 'react-native';
import { PermissionsAndroid, Platform } from 'react-native';
import {
    ClientRoleType,
    createAgoraRtcEngine,
    IRtcEngine,
    ChannelProfileType,
} from 'react-native-agora';
 
const appId = 'yourappID';
const channelName = 'dhruvicalling';
const token = 'Yourtoken';
const uid = 0;
 
const App = () => {
    const agoraEngineRef = useRef < IRtcEngine > (); // Agora engine instance
    const [isJoined, setIsJoined] = useState(false);
    const [remoteUid, setRemoteUid] = useState(0);
    const [message, setMessage] = useState('');
 
    useEffect(() => {
        // Initialize Agora engine when the app starts
        setupVoiceSDKEngine();
    }, []);
 
    const join = async () => {
        if (isJoined) {
            return;
        }
        try {
            agoraEngineRef.current?.setChannelProfile(
                ChannelProfileType.ChannelProfileCommunication,
            );
            agoraEngineRef.current?.joinChannel(token, channelName, uid, {
                clientRoleType: ClientRoleType.ClientRoleBroadcaster,
            });
        } catch (e) {
            console.log(e);
        }
    };
 
    const setupVoiceSDKEngine = async () => {
        try {
            if (Platform.OS === 'android') {
                await getPermission();
            }
            agoraEngineRef.current = createAgoraRtcEngine();
            const agoraEngine = agoraEngineRef.current;
            agoraEngine.registerEventHandler({
                onJoinChannelSuccess: () => {
                    showMessage('Successfully joined the channel'+ channelName);
                    setIsJoined(true);
                },
                onUserJoined: (_connection, Uid) => {
                    showMessage('Remote user joined with uid ' + Uid);
                    setRemoteUid(Uid);
                },
                onUserOffline: (_connection, Uid) => {
                    showMessage('Remote user left the channel. uid: ' + Uid);
                    setRemoteUid(0);
                },
            });
            agoraEngine.initialize({
                appId: appId,
            });
        } catch (e) {
            console.log(e);
        }
    };
 
    const leave = () => {
        try {
            agoraEngineRef.current?.leaveChannel();
            setRemoteUid(0);
            setIsJoined(false);
            showMessage('You left the channel');
        } catch (e) {
            console.log(e);
        }
    };
 
    function showMessage(msg: string) {
        setMessage(msg);
    }
 
    return (
        <SafeAreaView style={styles.container}>
            <Text style={styles.header}>Calling App</Text>
            <View style={styles.buttonContainer}>
                <TouchableOpacity onPress={join} style={styles.joinButton}>
                    <Text style={styles.buttonText}>Join</Text>
                </TouchableOpacity>
                <TouchableOpacity onPress={leave} style={styles.leaveButton}>
                    <Text style={styles.buttonText}>Leave</Text>
                </TouchableOpacity>
            </View>
            <ScrollView style={styles.scroll}
                        contentContainerStyle={styles.scrollContainer}>
                {isJoined ? (
                    <Text style={styles.infoText}>Local user uid: {uid}</Text>
                ) : (
                    <Text style={styles.infoText}>Join a channel</Text>
                )}
                {isJoined && remoteUid !== 0 ? (
                    <Text style={styles.infoText}>
                        Remote user uid: {remoteUid}
                    </Text>
                ) : (
                    <Text style={styles.infoText}>
                        Waiting for a remote user to join
                    </Text>
                )}
                <Text style={styles.messageText}>{message}</Text>
            </ScrollView>
        </SafeAreaView>
    );
};
 
const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        backgroundColor: '#f0f0f0',
    },
    header: {
        fontSize: 24,
        fontWeight: 'bold',
        marginVertical: 20,
    },
    buttonContainer: {
        flexDirection: 'row',
        justifyContent: 'center',
        marginBottom: 20,
    },
    joinButton: {
        paddingHorizontal: 25,
        paddingVertical: 10,
        borderRadius: 8,
        backgroundColor: '#4CAF50',
        margin: 5,
    },
    leaveButton: {
        paddingHorizontal: 25,
        paddingVertical: 10,
        borderRadius: 8,
        backgroundColor: '#E57373',
        margin: 5,
    },
    buttonText: {
        color: '#ffffff',
        fontWeight: 'bold',
        fontSize: 16,
    },
    scroll: {
        flex: 1,
        backgroundColor: '#ffffff',
        width: '90%',
        padding: 10,
        borderRadius: 8,
    },
    scrollContainer: {
        alignItems: 'center',
    },
    infoText: {
        fontSize: 18,
        marginVertical: 10,
    },
    messageText: {
        fontSize: 16,
        fontStyle: 'italic',
        color: '#555555',
    },
});
 
const getPermission = async () => {
    if (Platform.OS === 'android') {
        await PermissionsAndroid.requestMultiple([
            PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
        ]);
    }
};
 
export default App;


NOTE: MAKE SURE TO REPLACE THE APPID AND TOKEN WITH YOUR GENERATED ONES.

Step 5: Generating appId and token in Agora as we are using Agora SDK for call connection.

  • Open Agora.
  • create account on Agora and log in to your account.
  • Then Agora console will appear and will look like:

imresizer-1705416096651

  • Click on create new project and get the token and appId.

dcwdv_AdobeExpress-ezgifcom-video-to-gif-converter

Steps to run the application:

  • Run the following command:
npx react-native start

Output:

wq-ezgifcom-video-to-gif-converter



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads