Suggestions

close search

Getting started with the React Native wrapper for Stringee Call SDK

Step 1: Prepare

  1. Before using Stringee Call API for the first time, you must have a Stringee account If you do not have a Stringee account, sign up for free here: https://developer.stringee.com/account/register

  2. Create a Project on Stringee Dashboard Stringee create Project

  3. Buy a Number (optional) For app-to-phone, phone-to-app calling, buy a Number from Dashboard. If you only need app-to-app calling, skip this step. Stringee buy Number

  4. Configure answer_url

For more information on answer_url, read Stringee Call API Overview. You can view answer_url sample code here: https://github.com/stringeecom/server-samples/tree/master/answer_url

Stringee Project answer_url

If you do not have a answer_url, to speed things up you can use the following Project's answer_url:

Project's answer_url for App-to-App call:

https://developer.stringee.com/scco_helper/simple_project_answer_url?record=false&appToPhone=false

Project's answer_url for App-to-Phone call:

https://developer.stringee.com/scco_helper/simple_project_answer_url?record=false&appToPhone=true

(Source code here: https://github.com/stringeecom/server-samples/blob/master/answer_url/php/project_answer_url.php)

But in a production application, you should use your own answer_url.

Stringee Number answer_url

If you do not have a answer_url, to speed things up you can use the following Number's answer_url:

Number's answer_url for Phone-to-App call (The call is routed to Your App which authenticated by USER_ID):

https://developer.stringee.com/scco_helper/simple_number_answer_url?record=true&phoneToPhone=false&to_number=USER_ID

Number's answer_url for Phone-to-Phone call (The call is routed to TO_NUMBER):

https://developer.stringee.com/scco_helper/simple_number_answer_url?record=true&phoneToPhone=true&stringeeNumber=STRINGEE_NUMBER&to_number=TO_NUMBER

(Source code here: https://github.com/stringeecom/server-samples/blob/master/answer_url/php/number_answer_url.php)

But in a production application, you should use your own answer_url.

Step 2: Install stringee-react-rative package

  1. In your terminal (Command Prompt in Windows), change into your React Native project's directory

  2. In your terminal (Command Prompt in Windows), run $ npm install stringee-react-native --save

iOS

Note Please make sure to have CocoaPods on your computer.

  1. In you terminal, change into your ios directory.

  2. Create a pod file by running: pod init.

  3. Add the following to your pod file:

    pod 'RNStringee', path: "../node_modules/stringee-react-native/ios"
  1. Now run, pod install

  2. Open XCode

  3. Open <YourProjectName>.xcworkspace file in XCode. This file can be found in the ios folder of your React Native project.

  4. In the "Build Settings" tab -> "Other linker flags" add "$(inherited)" flag.

  5. In the "Build Settings" tab -> "Enable bitcode" select "NO".

  6. Right-click the information property list file (Info.plist) and select Open As -> Source Code.

  7. Insert the following XML snippet into the body of your file just before the final element:

  <key>NSCameraUsageDescription</key>
  <string>$(PRODUCT_NAME) uses Camera</string>
  <key>NSMicrophoneUsageDescription</key>
  <string>$(PRODUCT_NAME) uses Microphone</string>

Android

Proguard

Open up android/app/proguard-rules.pro and add following lines:

-dontwarn org.webrtc.**
-keep class org.webrtc.** { *; }
-keep class com.stringee.** { *; }

Permissions

The Stringee Android SDK requires some permissions from your AndroidManifest

  1. Open up android/app/src/main/AndroidManifest.xml
  2. Add the following lines:
    // for internet access
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    // for audio access
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    // for camera access
    <uses-permission android:name="android.permission.CAMERA" />

Step 3: Connect to Stringee Server

In order to connect to Stringee Server, 3-parties authentication is required as described here: Client authentication

For testing purpose, go to Dashboard -> Tools -> Generate Access token and generates an access_token. In production, the access_token should be generated by your server, sample code generates access token here: https://github.com/stringeecom/server-samples/tree/master/access_token

  1. Import StringeeClient:
import {
  StringeeClient
} from "stringee-react-native";
  1. Initialize StringeeClient
render () {
  return (
    <View>
      ...    
      <StringeeClient
        ref="client"
        eventHandlers = {this.clientEventHandlers}
      />
      ...
    </View>
  )
}
  1. Register the client's events
class App extends Component {
  constructor(props) {
    super(props);

    this.clientEventHandlers = {
      onConnect: this._clientDidConnect,
      onDisConnect: this._clientDidDisConnect,
      onFailWithError: this._clientDidFailWithError,
      onRequestAccessToken: this._clientRequestAccessToken,
      onIncomingCall: this._callIncomingCall,
      onIncomingCall2: this._callIncomingCall2,
      onCustomMessage: this._clientReceiveCustomMessage,
    };
  }

  // The client connects to Stringee server
  _clientDidConnect = ({userId}) => {
    console.log('_clientDidConnect: ' + userId);
  }

  // The client disconnects from Stringee server
  _clientDidDisConnect = () => {
    console.log('_clientDidDisConnect');
  }

  // The client fails to connects to Stringee server
  _clientDidFailWithError = () => {
    console.log('_clientDidFailWithError');
  }

  // Access token is expired. A new access token is required to connect to Stringee server
  _clientRequestAccessToken = () => {
    console.log("_clientRequestAccessToken");
    // this.refs.client.connect('NEW_YOUR_ACCESS_TOKEN');
  }

   // IncomingCall event
  _callIncomingCall = ({callId, from, to, fromAlias, toAlias, callType, isVideoCall}) => {
    console.log('_callIncomingCall: ' + callId);
  }

  // IncomingCall2 event
  _callIncomingCall2 = ({callId, from, to, fromAlias, toAlias, callType, isVideoCall}) => {
    console.log('_callIncomingCall2: ' + callId);
  }

  // Receive custom message
  _clientReceiveCustomMessage = ({data}) => {
    console.log('_clientReceiveCustomMessage: ' + data);
  };

  render() {
    return (
      <View>
        ...
        <StringeeClient
          ref="client"
          eventHandlers = {this.clientEventHandlers}
         /> 
        ...
      </View>
    );
  }
}
  1. Connect
  async componentDidMount() {
    await this.refs.client.connect('YOUR_ACCESS_TOKEN');
  }

Step 4: Make a call

After the client connects to Stirngee server, follows these steps to make a call:

  1. Import StringeeCall:
import {
  StringeeCall
} from "stringee-react-native";
  1. Initialize StringeeCall
async componentDidMount() {
    await this.refs.stringeeClient.connect(token);
    this.setState({clientId: this.refs.stringeeClient.getId()});
  }
...
render () {
  return (
    <View>
      ...
      {this.state.clientId !== null && this.state.isStringeeCall && (
            <StringeeCall
              ref="stringeeCall"
              clientId={this.state.clientId}
            />
          )}
      ...
    </View>
  );
}
  1. Register the call's events
class App extends Component {
  constructor(props) {
    super(props);

    this.callEventHandlers = {
      onChangeSignalingState: this._callDidChangeSignalingState,
      onChangeMediaState: this._callDidChangeMediaState,
      onReceiveLocalStream: this._callDidReceiveLocalStream,
      onReceiveRemoteStream: this._callDidReceiveRemoteStream,
      onReceiveDtmfDigit: this._didReceiveDtmfDigit,
      onReceiveCallInfo: this._didReceiveCallInfo,
      onHandleOnAnotherDevice: this._didHandleOnAnotherDevice,
      onAudioDeviceChange: this._didAudioDeviceChange, ///only available on android
    };
  }

    // Invoked when the call signaling state changes
  _callDidChangeSignalingState = ({callId, code, reason, sipCode, sipReason}) => {
    console.log('_callDidChangeSignalingState: ' + code);
  }

  // Invoked when the call media state changes
  _callDidChangeMediaState = ({callId, code, description}) => {
    console.log('_callDidChangeMediaState: ' + code);
  }

  // Invoked when the local stream is available    
  _callDidReceiveLocalStream = ({callId}) => {
    console.log('_callDidReceiveLocalStream: ' + callId);
  }
  // Invoked when the remote stream is available
  _callDidReceiveRemoteStream = ({callId}) => {
    console.log('_callDidReceiveRemoteStream: ' + callId);
  }

  // Invoked when receives a DMTF
  _didReceiveDtmfDigit = ({callId, dtmf}) => {
    console.log('_didReceiveDtmfDigit');
  }

  // Invoked when receives info from other clients
  _didReceiveCallInfo = ({callId, data}) => {
    console.log('_didReceiveCallInfo: ' + data);
  }

  // Invoked when the call is handled on another device
  _didHandleOnAnotherDevice = ({callId, code, description}) => {
    console.log('_didHandleOnAnotherDevice: ' + code);
  }

  // Invoked when audio device has change
  _didAudioDeviceChange = ({selectedAudioDevice, availableAudioDevices}) => {
    console.log(
      '_didHandleOnAnotherDevice: selectedAudioDevice - ' +
        selectedAudioDevice +
        ' availableAudioDevices - ' +
        availableAudioDevices,
    );
  };

  render() {
    return (
      <View style={styles.container}>
        ...    
        {this.state.clientId !== null && this.state.isStringeeCall && (
            <StringeeCall
              ref="stringeeCall"
              clientId={this.state.clientId}
              eventHandlers={this.callEventHandlers}
            />
        )}
      ...
      </View>
    );
  }
}
  1. Make a call
  const myObj = {
    from: 'caller_userId', // caller
    to: 'callee_userId', // callee
    isVideoCall: false, // Cuộc gọi là video call hoặc voice call 
    videoResolution: 'NORMAL' // chất lượng hình ảnh 'NORMAL' hoặc 'HD'. Mặc định là 'NORMAL'.
  };

  const parameters = JSON.stringify(myObj);

  this.refs.stringeeCall.makeCall(parameters, (status, code, message, callId) => {
    console.log('status-' + status + ' code-' + code + ' message-' + message + 'callId-' + callId);
    if (status) {
      // Sucess
    } else {
      // Fail
    }
  })

Step 5: Answer a call

When the client receives an incoming call with callId

   // IncomingCall event
  _callIncomingCall = ({callId, from, to, fromAlias, toAlias, callType, isVideoCall}) => {
    console.log('IncomingCallId: ' + callId);
  }

Initialize a StringeeCall as described in 4.1, 4.2, 4.3. Then follow these steps:

  1. Initialize the answer
  this.refs.stringeeCall.initAnswer(callId, (status, code, message) => {
    console.log(message);
    if (status) {
      // Sucess
    } else {
      // Fail
    }
  });
  1. Answer
  this.refs.stringeeCall.answer(callId, (status, code, message) => {
    console.log(message);
    if (status) {
      // Sucess
    } else {
      // Fail
    }
  });

Step 6: Hang up

When the client wants to hang up:

  this.refs.stringeeCall.hangup(callId, (status, code, message) => {
    console.log(message);
    if (status) {
      // Sucess
    } else {
      // Fail
    }
  });

Step 7: Reject a call

When the client wants to reject a call:

  this.refs.stringeeCall.reject(callId, (status, code, message) => {
    console.log(message);
    if (status) {
      // Sucess
    } else {
      // Fail
    }
  });

Step 8: Make a video call

  1. A Stringee call is a voice call by default. If you want to make a video call, you must assign:
  const myObj = {
    from: 'caller_userId', // caller
    to: 'callee_userId', // callee
    isVideoCall: true, // Must be true
    videoResolution: 'NORMAL' // Set video resolution: 'NORMAL', 'HD'
  };

  const parameters = JSON.stringify(myObj);

  this.refs.stringeeCall.makeCall(parameters, (status, code, message, callId) => {
    console.log('status-' + status + ' code-' + code + ' message-' + message + 'callId-' + callId);
    if (status) {
      // Sucess
    } else {
      // Fail
    }
  })
  1. Display the local video
  _callDidReceiveLocalStream = ({callId}) => {
    console.log('_callDidReceiveLocalStream ' + callId);
    this.setState({hasReceivedLocalStream:true});
  }

  render () {
    return (
      <View>
        ...
        {this.props.isVideoCall &&
          this.props.hasLocalStream &&
          this.props.stringeeCallId != '' && (
            <StringeeVideoView
              style={styles.localView}
              callId={this.props.stringeeCallId}
              local={true}
              overlay={true}
            />
          )}
        ...
        <StringeeCall
            ref="stringeeCall"
            clientId={this.state.clientId}
            eventHandlers={this.callEventHandlers}
        />
        ...
      </View>
    );
  }
}
  1. Receive and display the remote video
  _callDidReceiveRemoteStream = ({callId}) => {
    console.log('_callDidReceiveRemoteStream ' + callId);
    this.setState({hasReceivedRemoteStream:true});
  }

  render () {
    return (
      <View>
        ...
        {this.props.isVideoCall &&
            this.props.hasRemoteStream &&
            this.props.stringeeCallId != '' && (
              <StringeeVideoView
                style={{flex: 1}}
                callId={this.props.stringeeCallId}
                local={false}
              />
            )}
        ...
        <StringeeCall
            ref="stringeeCall"
            clientId={this.state.clientId}
            eventHandlers={this.callEventHandlers}
        />
        ...
      </View>
    );
  }
}

Sample

You can view a completed version of this sample app on GitHub: https://github.com/stringeecom/react-native-samples