This module allows you to add voice-over-IP (VoIP) calling into your React Native app using Twilio Programmable Voice.
Supported versions:
- iOS 13+
- Android API 26+
Android call to iOS:
iOS call to Android:
Follow the Twilio Voice iOS SDK Quickstart and Android SDK Quickstart.
Steps 1 and 6 must be skipped.
Now come the easy part :)
npm install react-native-twilio-phone
Run this command to complete installation on iOS:
cd ios/ && pod install
You must also create a Swift file like this one in the /ios
folder. If you don't have such a file, your app won't build.
Use RNTwilioPhone
class to easily receive incoming calls or start outgoing calls.
import * as React from 'react';
import { RNTwilioPhone } from 'react-native-twilio-phone';
// ...
const callKeepOptions = {
};
// Async function that returns Twilio access token
async function fetchAccessToken() {
const response = await fetch(
'https://XXXXXX.ngrok.io/accessToken?identity=alice'
);
const accessToken = await response.text();
return accessToken;
}
// RNTwilioPhone options
const options = {
requestPermissionsOnInit: true, // Default: true - Set to false if you want to request permissions manually
};
export function MyComponent() {
// Initialize once when component did mount
// Execute returned function when component will unmount to avoid memory leaks
React.useEffect(() => {
// This will set up CallKeep and register device for incoming calls
return RNTwilioPhone.initialize(callKeepOptions, fetchAccessToken, options);
// Or use initializeCallKeep if you just want to make outgoing calls
// return RNTwilioPhone.initializeCallKeep(callKeepOptions, fetchAccessToken, options);
}, []);
// Function that starts an outgoing call
async function startCall() {
try {
await RNTwilioPhone.startCall('+00123456789');
} catch (e) {
console.log(e);
}
}
// Call this function to unregister device from incoming calls
// Useful when user signs out for example
async function unregister() {
try {
await RNTwilioPhone.unregister();
} catch (e) {
console.log(e);
}
}
// Display active calls
console.log(RNTwilioPhone.calls);
// ...
}
Use twilioPhoneEmitter
to subscribe to module's events:
import { twilioPhoneEmitter } from 'react-native-twilio-phone';
// ...
React.useEffect(() => {
const subscriptions = [
twilioPhoneEmitter.addListener('CallConnected', (data) => {
console.log(data);
}),
twilioPhoneEmitter.addListener('CallDisconnected', (data) => {
console.log(data);
}),
twilioPhoneEmitter.addListener('CallDisconnectedError', (data) => {
console.log(data);
}),
];
return () => {
subscriptions.map((subscription) => {
subscription.remove();
});
};
}, []);
// ...
Following events are available:
enum EventType {
CallInvite = 'CallInvite',
CancelledCallInvite = 'CancelledCallInvite',
CallRinging = 'CallRinging',
CallConnectFailure = 'CallConnectFailure',
CallConnected = 'CallConnected',
CallReconnecting = 'CallReconnecting',
CallReconnected = 'CallReconnected',
CallDisconnected = 'CallDisconnected',
CallDisconnectedError = 'CallDisconnectedError',
RegistrationSuccess = 'RegistrationSuccess',
RegistrationFailure = 'RegistrationFailure',
UnregistrationSuccess = 'UnregistrationSuccess',
UnregistrationFailure = 'UnregistrationFailure',
}
Use TwilioPhone
class to have more control over calls.
type TwilioPhoneType = {
register(accessToken: string, deviceToken: string): void;
handleMessage(payload: MessagePayload): void;
acceptCallInvite(callSid: string): void;
rejectCallInvite(callSid: string): void;
disconnectCall(callSid: string): void;
endCall(callSid: string): void;
toggleMuteCall(callSid: string, mute: boolean): void;
toggleHoldCall(callSid: string, hold: boolean): void;
toggleSpeaker(speakerOn: boolean): void;
sendDigits(callSid: string, digits: string): void;
startCall(accessToken: string, params: ConnectParams): void;
unregister(accessToken: string, deviceToken: string): void;
activateAudio(): void; // iOS only
deactivateAudio(): void; // iOS only
checkPermissions(callback: (permissions: Permissions) => void): void;
requestPermissioniOS(callback: (permissions: Permissions) => void): void;
};
If you don't want to request permissions on initialization, set requestPermissionsOnInit
option to false
:
// ...
export function MyComponent() {
React.useEffect(() => {
return RNTwilioPhone.initialize(callKeepOptions, fetchAccessToken, {
requestPermissionsOnInit: false,
});
}, []);
}
You can request permissions later by calling checkPermissions
method on TwilioPhone
:
TwilioPhone.checkPermissions((permissions) => {
console.log(permissions); // Display the required permissions and their status
});
To start the example app, first set up Twilio server-side web application.
Then run yarn bootstrap
in the root directory to install the required dependencies for each package:
yarn bootstrap
To run the example app on Android:
yarn example android
To run the example app on iOS:
yarn example ios
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT