Suggestions

close search

Getting started with Stringee Call API using Flutter Plugin

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)

  4. 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

  5. Configure answer_url

    For more information about 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

    • Configure Project's answer_url: To make an app-to-app, app-to-phone call, configure your Project's answer_url

      Stringee Project answer_url

    If you do not have answer_url, you can use the following Project's answer_url to accelerate the process:

    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: https://github.com/stringeecom/server-samples/blob/master/answer_url/php/project_answer_url.php)

    When building an application, you should use your own answer_url.

    • Configure Number's answer_url: To receive a phone-to-app call, configure your Number's answer_url

    Stringee Number answer_url

    If you do not have answer_url, you can use the following Number's answer_url to accelerate the process:

    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: https://github.com/stringeecom/server-samples/blob/master/answer_url/php/number_answer_url.php)

Step 2: Install stringee-flutter-plugin

  1. Download stringee-flutter-plugin here: https://github.com/stringeecom/stringee_flutter_plugin

  2. Put stringee-flutter-plugin into the same directory of your project them add the following to your pubspec.yaml file

    dependencies:
        stringee_flutter_plugin:
            git:
                url: https://github.com/stringeecom/stringee_flutter_plugin.git
  3. Install the plugin by running the following command from the project root:

    $ flutter pub get

Step 3: Setup

Android

  1. Permissions

    The Stringee Android SDK requires some permissions from your AndroidManifest

    • Open up android/app/src/main/AndroidManifest.xml
    • Add the following lines:
    // for internet access
    <uses-permission android:name="android.permission.INTERNET" />
    // 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" />
    // for bluetooth
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  2. Proguard

    If your project uses ProGuard, you may have to add the following settings to the ProGuard configuration file to make sure Stringee builds correctly:

    • Create file proguard-rules.pro in your app/ dir and insert inside:
    #Flutter Wrapper
    -dontwarn org.webrtc.**
    -keep class org.webrtc.** { *; }
    -keep class com.stringee.** { *; }
    • Add the following lines to /app/buidl.gradle :
    android {
        buildTypes {
            release {
                useProguard true
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
    }
  3. Add volley library

    In your file build.gradle add this line:

    dependencies {
        implementation 'com.android.volley:volley:1.2.1'
    }

iOS

  1. From the command line run following command:

    pod install --repo-update
  2. After run cocoapods command, open project file .xcworkspace

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

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

  5. Right-click the information property list file (Info.plist) and select Open As -> Source Code. Then 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>
  6. In the "Build Settings" tab -> "Allow Non-modular includes in Framework Modules" select "YES"

Step 4: 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. Initialize StringeeClient:

    import 'package:stringee_flutter_plugin/stringee_flutter_plugin.dart';
    ...
    StringeeClient _stringeeClient = StringeeClient();
  2. Register the client's events in your State

    /// Listen for the StringeeClient event
    _stringeeClient.registerEvent(StringeeClientListener(
      /// Invoked when the StringeeClient is connected
      onConnect: (stringeeClient, userId) {
         debugPrint('onConnect: $userId');
      },
      /// Invoked when the StringeeClient is disconnected
      onDisconnect: (stringeeClient) {
         debugPrint('onDisconnect');
      },
      /// Invoked when StringeeClient connect false
      onFailWithError: (stringeeClient, code, message) {
         debugPrint('onFailWithError: code - $code - message - $message');
      },
      /// Invoked when your token is expired
      onRequestAccessToken: (stringeeClient) {
         debugPrint('onRequestAccessToken');
      },
      /// Invoked when receive an incoming of StringeeCall
      onIncomingCall: (stringeeClient, stringeeCall) {
         debugPrint('onIncomingCall: callId - ${stringeeCall.id}');
      },
      /// Invoked when receive an incoming of StringeeCall2
      onIncomingCall2: (stringeeClient, stringeeCall2) {
         debugPrint('onIncomingCall2: callId - ${stringeeCall2.id}');
      },
    ));
  3. Connect

    ...
    String token = 'PUT YOUR TOKEN HERE'
    ...
    _stringeeClient.connect(token);

Step 5: Make a call

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

  1. Initialize StringeeCall

    import 'package:stringee_flutter_plugin/stringee_flutter_plugin.dart';
    ...
    StringeeCall _stringeeCall = StringeeCall(
      _stringeeClient, /// stringeeClient using to connect
      'caller_userId', /// caller id
      'callee_userId', /// callee id
    );
  2. Register the call's events in your State

    _stringeeCall.registerEvent(StringeeCallListener(
      /// Invoked when the call's signaling state changes
      onChangeSignalingState: (stringeeCall, signalingState) {
         debugPrint('onChangeSignalingState: signalingState - $signalingState');
      },
      /// Invoked when the call's media state changes
      onChangeMediaState: (stringeeCall, mediaState) {
         debugPrint('onChangeMediaState: mediaState - $mediaState');
      },
      /// Invoked when receive call info
      onReceiveCallInfo: (stringeeCall, callInfo) {
         debugPrint('onReceiveCallInfo: callInfo - $callInfo');
      },
      /// Invoked when an incoming call is handle on another device
      onHandleOnAnotherDevice: (stringeeCall, signalingState) {
         debugPrint('onHandleOnAnotherDevice: signalingState - $signalingState');
      },
      /// Invoked when local stream in video call is ready to play
      onReceiveLocalStream: (stringeeCall) {
         debugPrint('onReceiveLocalStream');
      },
      /// Invoked when remote stream in video call is ready to play
      onReceiveRemoteStream: (stringeeCall) {
         debugPrint('onReceiveLocalStream');
      },
      /// Invoked when the current audio device changes in android
      onChangeAudioDevice: (stringeeCall, selectedAudioDevice, availableAudioDevices) {
         debugPrint('onChangeAudioDevice: selectedAudioDevice - selectedAudioDevice');
      },
    ));
  3. Make a call

    _stringeeCall.makeCall(params).then((result) {
      debugPrint('makeCall: ${result['message']} - callId - ${_call.id} - from - ${_call.from} - to - ${_call.to}');
    });

Step 6: Answer a call

When the client receives an incoming call from onIncomingCall(), initialize a StringeeCall as described in 4.1, 4.2. Then follow these steps:

  1. Initialize the answer

    _stringeeCall.initAnswer().then((event) {
        debugPrint('initAnswer: ${result['message']}');
    });
  2. Answer

    _stringeeCall.answer().then((result) {
        debugPrint('answer: ${result['message']}');
    });

Step 7: Make a video call

  1. A Stringee call is a voice call by default. If you want to make a video call, you must set property isVideoCall of StringeeCall to true.
  2. Receive and display the local video and the remote video

    Using our StringeeVideoView to display the video

    Widget? localScreen = null;
    Widget? remoteScreen = null;
    ...
    _stringeeCall.registerEvent(StringeeCallListener(
      ...
      /// Invoked when local stream in video call is ready to play
      onReceiveLocalStream: (stringeeCall) {
         debugPrint('onReceiveLocalStream');
         setState(() {
            localScreen = new StringeeVideoView(
               stringeeCall.id!, /// callId of StringeeCall
               true, /// true - local video, false - remote video
               alignment: Alignment.topRight,
               margin: EdgeInsets.only(top: 25.0, right: 25.0),
               height: 150.0,
               width: 100.0,
            );
         });
      },
      /// Invoked when remote stream in video call is ready to play
      onReceiveRemoteStream: (stringeeCall) {
         debugPrint('onReceiveLocalStream');
         setState(() {
            remoteScreen = new StringeeVideoView(
               stringeeCall.id!, /// callId of StringeeCall
               false, /// true - local video, false - remote video
            );
         });
      },
      ...
    ));
    ...
    return new Scaffold(
      ...
      body: new Stack(
         children: <Widget>[
            remoteScreen != null ? remoteScreen! : Placeholder(color: Colors.transparent),
            localScreen != null ? localScreen!: Placeholder(color: Colors.transparent),
            ...
         ],
      ),
    );

Step 8: Hang up

Hang up a call:

_stringeeCall.hangup().then((result) {
   debugPrint('hangup: ${result['message']}');
});

Step 9: Reject

Reject a call:

_stringeeCall.reject().then((result) {
   debugPrint('reject: ${result['message']}');
});

Step 10: Mute

Mute the local sound:

bool mute = true; // true: mute, false: unmute
_stringeeCall.mute(mute).then((result) {
   debugPrint('mute: ${result['message']}');
});

Step 11: Switch speaker or bluetooth device

Switch to speakerphone or earpiece:

bool isSpeaker = true; // true: speakerphone, false: earpiece
_stringeeCall.setSpeakerphoneOn(isSpeaker).then((result) {
   debugPrint('setSpeakerphoneOn: ${result['message']}');
});

Switch to bluetooth device or device speaker:

bool bluetoothScoOn = true; // true: bluetooth device, false: device speaker
_stringeeCall.setBluetoothScoOn(bluetoothScoOn).then((result) {
   debugPrint('setBluetoothScoOn: ${result['message']}');
});

Step 12: Switch camera

Switch the local camera:

_stringeeCall.switchCamera().then((result) {
   debugPrint('switchCamera: ${result['message']}');
});

Step 13: Turn on/off video

Turn on/off video:

bool enableVideo = true; // true: turn on, false: turn off
_stringeeCall.enableVideo(enableVideo).then((result) {
   debugPrint('enableVideo: ${result['message']}');
});

Sample

You can view a full version of this sample app on GitHub: https://github.com/stringeecom/flutter-samples/tree/master/call_sample