Navbar
Logo icon Name

Relay SDK for React Native

Getting Started

The Relay React Native SDK allows you to integrate Relay into React Native applications, enabling developers to directly make audio and video calls to phone numbers, SIP endpoints, browsers and other Apps. Using the React Native SDK you can add immersive, scalable communication - from video conferences and softphones to mobile gaming - all available right in your own App.

SignalWire's simple and powerful authentication system, using JWT, allows you to set granular permissions, enabling some of your users to only join conference calls, while others could list on-going calls and jump in to assist from a support dashboard... the possibilities are endless.

Latest Version:

Source Code: signalwire/signalwire-react-native

Support: SignalWire Community Slack Channel

Installation

The Relay SDK for React Native is easy to use and only takes a few minute to setup and get running.

npm install @signalwire/react-native

During the installation process the SDK will try to automatically install and link these React Native libraries for you:

iOS Setup

Make sure to add the permissions into the Info.plist file to access microphone and webcam:

<key>NSCameraUsageDescription</key>
<string>Enter here the message to display to the user to ask access to the Camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>Enter here the message to display to the user to ask access to the Microphone</string>

To troubleshoot any build errors, follow the steps for each native library:

Android Setup

Make sure to add the permissions in android/app/src/main/AndroidManifest.xml:

<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus"/>

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

To troubleshoot any build errors, follow the steps for each native library:

Push Notifications

The Relay React Native SDK opens a persistent network connection with SignalWire but when the App goes in background mode, both iOS and Android have mechanisms to avoid draining battery and consuming network data.

We are working to support Push Notifications to GCM/FCM and APNS to allow you to reach your users even when the App is closed or in background.

Stay tuned...

Using the SDK

First step to using the SDK is to setup authentication.

To avoid packaging and releasing the private Project Token into your own App, the React Native SDK uses JSON Web Tokens (JWT) to authenticate with SignalWire and apply fine grained permissions to the end-user.

Your server uses your Project ID and Project Token to make a request to generate a JWT with your specific requirements, such as expiration time, permissions, resource name, and give the resulting JWT Token to the App. The JWT is safe to expose to the end user, it is signed and cannot be edited. The App can then log into SignalWire using the Project ID and the JWT.

To learn more about generating and using JWT, including all the options available to you, visit Authentication for React Native SDK Documentation.

Generate a JWT

To generate a JWT, make a server-side POST request to the JWT endpoint on the Relay REST API.

curl https://your-space.signalwire.com/api/relay/rest/jwt \
  -X POST \
  -u 'YourProjectID:YourProjectToken' \
  -H 'Content-Type: application/json'

Will result in a JSON response like:

{
    "jwt_token": "a_long_jwt_token",
    "refresh_token": "a_long_jwt_refresh_token"
}

For more information and examples on generating JSON Web Tokens, visit Authentication for React Native SDK Documentation

Connect using JWT

Using the JWT you received in the previous step, you can connect to Relay using your Project ID and the JWT.

const client = new Relay({
  project: 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX',
  token: 'a_long_jwt_token'
})

You can then use client to make Relay requests.

Refresh JWT Token

All tokens have an expiration, so that a user cannot stay logged in forever. You can use the refresh token you received in Generate a JWT to refresh a token you already generated.

To refresh a JWT, make a server-side PUT request to the JWT endpoint with the refresh token:

curl https://your-space.signalwire.com/api/relay/rest/jwt \
  -X PUT \
  -u 'YourProjectID:YourProjectToken' \
  -H 'Content-Type: application/json' \
  -d '{
        "refresh_token": "a_long_jwt_token"
      }'

Will result in a JSON response like:

{
    "jwt_token": "a_new_jwt_token",
    "refresh_token": "a_new_jwt_refresh_token"
}

For more information about automatically refreshing JWT as they're about to expire, see refreshToken Event Documentation

API Reference

Relay

Relay client is the basic connection to Relay, allowing you send commands to Relay and setup handlers for inbound events.

Constructor

Constructs a client object to interact with Relay.

Parameters

project string required Project ID from your SignalWire Space
token string required Json Web Token retrieved using Rest API. See Generate a JWT for more information.

Examples

Create a Client to interact with the Relay API.

const client = new Relay({
  project: 'my-project-id',
  token: 'my-jwt',
})

client.on('signalwire.ready', (client) => {
  // You are connected with Relay!
})

client.connect()

Properties

connected boolean true if the client has connected to Relay.
expired boolean true if the JWT has expired.

Devices and Media Constraints

You can configure the devices your client will use by default with these properties and methods:

devices
getter
object All devices recognized by the client keyed by kind: videoinput, audioinput and audiooutput.
videoDevices
getter
object Video devices recognized by the client.
audioInDevices
getter
object Audio input devices recognized by the client.
audioOutDevices
getter
object Audio output devices recognized by the client.
mediaConstraints
getter
object Current audio/video constraints used by the client.
speaker
getter
string Audio output device used by the client.
speaker
setter
string Set the audio output device to use for the subsequent calls.

PRO TIP: videoDevices, audioInDevices, audioOutDevices objects have deviceId as a key.
If you want an array instead, use .toArray() method on them. See the example below.

 

Examples

Retrieve video devices as object and then as array.

const asObject = client.videoDevices
// {
//   "0a294ce2885d06ffb17e86e184e357bc970730d4116526c6e2": {
//     "deviceId": "0a294ce2885d06ffb17e86e184e357bc970730d4116526c6e2",
//     "kind": "videoinput",
//     "label": "GENERAL WEBCAM",
//     "groupId": "e425504b346c1c9d7fbda3c035862ea4373420bfa1d23210d6"
//   }
// }

const asArray = client.videoDevices.toArray()
// [
//   {
//     "deviceId": "0a294ce2885d06ffb17e86e184e357bc970730d4116526c6e2",
//     "kind": "videoinput",
//     "label": "GENERAL WEBCAM",
//     "groupId": "e425504b346c1c9d7fbda3c035862ea4373420bfa1d23210d6"
//   }
// ]

If present, use the first audio output device as default speaker.

const speakerList = client.audioOutDevices.toArray()
if (speakerList.length) {
  client.speaker = speakerList[0].deviceId
}

STUN/TURN Servers

Through the iceServers you can set/retrieve the default ICE server configuration for all subsequent calls.

iceServers getter RTCIceServers Current ICE servers used by the client.
iceServers setter RTCIceServers[] or Boolean array of ICE servers, true to use the default ones or false to not use STUN/TURN at all.

Methods

checkPermissions

The first time your App will try to access microphone or webcam, the OS will display a notification to the user. Use this method if you want to request the permissions to access them.

Available In:

Parameters

audio boolean optional Whether to check permissions for the microphone.
Default to true
video boolean optional Whether to check permissions for the webcam.
Default to true

Returns

Promise<boolean> - A Promise object resolved with a boolean value.

Examples

Check both audio and video permissions.

// within an async function ..
const success = await client.checkPermissions()
if (success) {
  // The user has given permission..
} else {
  // The user has not given permission!
}

connect

Activates the connection to Relay. Make sure you have attached the listeners you need before connecting the client, or you might miss some events.

Available In:

Returns

Promise<void>

Examples

await client.connect()

disconnect

Disconnect the client from Relay.

Available In:

Returns

void

Examples

client.disconnect()

disableMicrophone

Disable the use of the microphone for the subsequent calls.

Available In:

disableWebcam

Disable the use of the webcam for the subsequent calls.

Available In:

enableMicrophone

Enable the use of the microphone for the subsequent calls.

Available In:

enableWebcam

Enable the use of the webcam for the subsequent calls.

Available In:

newCall

Make a new outbound call.

Parameters

options object required Object with the following properties:
destinationNumber string required Extension to dial.
id string optional The identifier of the Call.
localStream string optional If set, the Call will use this stream instead of retrieving a new one.
iceServers RTCIceServers[] optional Overrides client's default iceServers.
audio boolean optional Overrides client's default audio constraints.
video boolean optional Overrides client's default video constraints.
useStereo boolean optional Use stereo audio instead of mono.
onNotification string optional Overrides client's default signalwire.notification handler for this Call.

Returns

Promise<Call> - A Promise fulfilled with the new outbound Call object or rejected with the error.

Examples

Make an outbound call to the conference 35123 using default values from the Client.

// within an async function ..
const options = { destinationNumber: '35123' }
const call = await client.newCall(options).catch(console.error)

on

Attach an event handler for a specific type of event.

Available In:

Parameters

event string required Event name. Full list of events Relay Events
handler function required Function to call when the event comes.

Returns

Relay - The client object itself.

Examples

Subscribe to the signalwire.ready and signalwire.error events.

client.on('signalwire.ready', (client) => {
  // Your client is ready!
}).on('signalwire.error', (error) => {
  // Got an error...
})

off

Remove an event handler that were attached with .on(). If no handler parameter is passed, all listeners for that event will be removed.

Parameters

event string required Event name. Full list of events Relay Events
handler function optional Function to remove.
Note: handler will be removed from the stack by reference so make sure to use the same reference in both .on() and .off() methods.

Returns

Relay - The client object itself.

Examples

Subscribe to the signalwire.error and then, remove the event handler.

const errorHandler = (error) => {
  // Log the error..
}

client.on('signalwire.error', errorHandler)

// .. later
client.off('signalwire.error', errorHandler)

refreshToken

When the JWT is going to expire, the Client dispatch a notification with type refreshToken that allows you to refresh the token and keep your session alive.

Available In:

Parameters

token string required New JWT to keep your session alive.

Returns

Promise<void>

Examples

Listen for all notifications and, on refreshToken, fetch a new JWT from your backend and update the token on the client.

client.on('signalwire.notification', function(notification) {
  switch (notification.type) {

    case 'refreshToken':
      // Take a new token from your server...
      xhrRequestToRefreshYourJWT().then(async (newToken) => {
        await client.refreshToken(newToken).catch(console.error)
      })
    break

  }
})

Events

All available events you can attach a listener on.

signalwire.ready The session has been established and all other methods can now be used.
signalwire.error There is an error dispatch at the session level.
signalwire.notification A notification from SignalWire. Notifications can refer to calls or session updates.
signalwire.socket.open The websocket is open. However, you have not yet been authenticated.
signalwire.socket.error The websocket gave an error.
signalwire.socket.message The client has received a message from the websocket.
signalwire.socket.close The websocket is closing.

Call

A Call represents a one-to-one call with another browser, a SIP endpoint, or even a phone number. The Call object supports both audio and video.

Properties

id string The identifier of the call.
direction string The direction of the call. Can be either inbound or outbound.
state string The state of the call. See below for all the possible call states.
prevState string The previous state of the call. See below for all the possible call states.
localStream MediaStream The local stream of the call. This can be used in a video/audio element to play the local media.
remoteStream MediaStream The remote stream of the call. This can be used in a video/audio element to play the remote media.

State

The state and prevState properties of a Call have the following values:

Value Description
new New Call has been created in the client.
trying You are attempting to call someone.
requesting Your outbound call is being sent to the server.
recovering Your previous call is recovering after the page refresh. If you refresh the page during a call, you will automatically be joined with the latest call.
ringing Someone is attempting to call you.
answering You are attempting to answer the inbound Call.
early You received the media before the Call has been answered.
active Call has become active.
held Call has been held.
hangup Call has ended.
destroy Call has been destroyed.
purge Call has been purged.

Methods

answer

Start the process to answer the incoming Call.

Available In:

Parameters

None

Returns

None

Example

call.answer()

deaf

Turn off the audio input track.

Available In:

Example

call.deaf()

dtmf

Send a Dual Tone Multi Frequency (DTMF) string to Relay.

Available In:

Parameters

string string required DTMF to send.

Returns

None

Examples

call.dtmf('0')

hangup

Hangs up the call.

Available In:

Parameters

None

Returns

None

Examples

call.hangup()

hold

Holds the call.

Available In:

Parameters

None

Returns

None

Examples

call.hold()

muteAudio

Turn off the audio output track.

Available In:

Example

call.muteAudio()

muteVideo

Turn off the video output track.

Available In:

Example

call.muteAudio()

setSpeakerPhone

By default the library route the audio to earpiece if the call has not a video track, otherwise route to the speakerphone. Using setSpeakerPhone() you can change the behaviour while in call.

Available In:

Parameters

flag boolean required true/false to route audio to speakerphone or not.

Returns

None

Example

call.setSpeakerPhone(true)

switchCamera

Switch the camera currently used by the Call.

Note: in recent devices with more then 1 rear camera the switch method will try to use all the available devices.

Available In:

Example

call.switchCamera()

toggleAudioMute

Toggle the audio output track.

Available In:

Example

call.toggleAudioMute()

toggleDeaf

Toggle the audio input track.

Available In:

Example

call.toggleDeaf()

toggleHold

Toggles the hold state of the call.

Available In:

Parameters

None

Returns

None

Examples

call.toggleHold()

toggleVideoMute

Toggle the video output track.

Available In:

Example

call.toggleVideoMute()

undeaf

Turn on the audio input track.

Available In:

Example

call.undeaf()

unhold

Un-holds the call.

Available In:

Parameters

None

Returns

None

Examples

call.unhold()

unmuteAudio

Turn on the audio output track.

Available In:

Example

call.unmuteAudio()

unmuteVideo

Turn on the video output track.

Available In:

Example

call.unmuteVideo()

Notification

A notification is an event that SignalWire dispatches to notify the Client about different cases. A notification can refer to the JWT expiration, Call changes or Conference updates.

Types

Every notification has a property type that identify the case and the structure of the data.
The available type are:

Value Description
refreshToken The JWT is going to expire. Refresh it or your session will be disconnected.
callUpdate A Call's state has been changed. Update the UI accordingly.
participantData New participant’s data (i.e. name, number) to update the UI.
userMediaError The user has not given the permission to access media devices. Check the audio and video constraints you are using.

refreshToken

Your JWT is going to expire. Refresh it or your session will be disconnected.

Anatomy of a refreshToken notification.

{
  type: 'refreshToken',
  session: RelayInstance
}

callUpdate

A Call's state has been changed. It is useful to update the UI of your application.s

Anatomy of a callUpdate notification.

{
  type: 'callUpdate',
  call: CallObject
}

participantData

This notification contains the participant data for the current Call. This is useful when updating the UI.

Anatomy of a participantData notification.

{
  type: 'participantData',
  call: CallObject,
  displayName: 'David Roe',
  displayNumber: '1777888800'
  displayDirection: 'inbound'
}

userMediaError

The user has not given the permission to access media devices. You can ask the user to set the proper permission for your App in the OS settings.

Anatomy of a userMediaError notification.

{
  type: 'userMediaError',
  error: error
}

Examples

Checkout our examples in Github to help you get started quickly.

Visit https://github.com/signalwire/signalwire-node/tree/master/packages/react-native/examples for our latest list of example implementations using the React Native SDK.