Suggestions

close search

Getting started with Stringee Call2 API using Android SDK

Step 1: Prepare

Before you use Stringee Call2 API to make or receive a call:

  1. Sign up for a Stringee account free here: https://developer.stringee.com/account/register
  2. Create a project on Stringee Dashboard.

Stringee create project

  1. Buy a number (Option): 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

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

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

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

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

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) When building an application, you should use your own answer_url. The best way to learn how to use Stringee Call2 API is to follow these steps:

Step 2: Creating a new project

Stringee SDK is designed to be used with Android Studio

1. Open Android Studio and select New Project from the File menu.
2. Set the minimum SDK for the app to be API 16 (Android 4.1 Jelly Bean).
3. Click through the wizard, ensuring that Empty Activity is selected. Leave the Activity Name set to MainActivity, and leave the Layout Name set to activity_main.

Step 3: Adding the Stringee SDK

Stringee Android SDK is distributed as an AAR and can be added to your project by referencing the AAR remotely with Maven.

  1. Navigate to your build.gradle at the project level and include the following:

    buildscript {
        repositories {
            ...
            mavenCentral()
        }
    }
    ...
    allprojects {
        repositories {
            ...
            mavenCentral()
        }
    }
  2. Navigate to your build.gradle at the app level and include the following:

    android {
        ...
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
    dependencies {    
        ...
        implementation 'com.stringee.sdk.android:stringee-android-sdk:1.7.8'
        implementation 'com.android.volley:volley:1.2.0'
    }

Step 4: Permissions and proguard

The Stringee Android SDK requires some permissions from your app's AndroidManifest.xml file:

<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" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.BLUETOOTH" />

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

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

Step 5: Setting up authentication

To connect to Stringee Server, you will need access to the authentication credential: access_token. In application building, the access_token should be generated by your server described here: Client authentication, sample code generates access token here: https://github.com/stringeecom/server-samples/tree/master/access_token.

To save time, we will just hard code the value:

  1. In the MainActivity class, declare a variable to store the access_token.

    public class MainActivity extends AppCompatActivity {
    
    private String token;
  2. Adjust the code by hard coding the value for the token: To do this, go to Dashboard -> Tools -> Generate Access token and generates an access_token.

Step 6: Connecting

Next, we will connect to the Stringee Server. You must do this before you can make or answer a call.

  1. Add a StringeeClient property to the MainActivity class.

    private StringeeClient client;
  2. Instantiate the StringeeClient object and register a connection listener to interact with Stringee server:

    client = new StringeeClient(this);
    client.setConnectionListener(new StringeeConnectionListener() {
        @Override
        public void onConnectionConnected(final StringeeClient stringeeClient, boolean isReconnecting) {
        }
        @Override
        public void onConnectionDisconnected(StringeeClient stringeeClient, boolean isReconnecting) {
        }
        @Override
        public void onIncomingCall(final StringeeCall stringeeCall) {
        }
        @Override
        public void onIncomingCall2(StringeeCall2 stringeeCall2) {
        }
        @Override
        public void onConnectionError(StringeeClient stringeeClient, final StringeeError stringeeError) {
        }
        @Override
        public void onRequestNewToken(StringeeClient stringeeClient) {
        // Get new token here and connect to Stringe server
        }
        @Override
        public void onCustomMessage(String s, JSONObject jsonObject) {
        }
        @Override
        public void onTopicMessage(String s, JSONObject jsonObject) {
        }
    });        
    • When the client connects to Stringee Server, the onConnectionConnected(StringeeClient stringeeClient, boolean isReconnecting) method is called.
    • When the client disconnects to Stringee Server, the onConnectionDisconnected(StringeeClient stringeeClient, boolean isReconnecting) method is called
    • When the client fails to connect to Stringee Server, the onConnectionError(StringeeClient stringeeClient, StringeeError stringeeError) method is called.
    • When the token is expired, the onRequestNewToken(StringeeClient stringeeClient) is called. You will need re-generate a new token and connect again.
    • When the client have an incoming call, the onIncomingCall2(StringeeCall2 stringeeCall2) method is called.
  3. If you use On-Premise server, you can follow the code below to connect:

    import com.stringee.common.SocketAddress;
    import java.util.ArrayList;
    import java.util.List;
    ...
    List<SocketAddress> socketAddressList = new ArrayList<>();
    socketAddressList.add(new SocketAddress("ip", port));
    client.setHost(socketAddressList);

Note: You need to setHost before connect.

  1. Connect Stringee server with an access token generated in Step 5:
    client.connect(token);

Step 7: Making a call

After connecting to the Stringee Server, you have to follow these steps to make a call:

  1. Create OutgoingCallActivity class to display the outgoing call screen.
    1. Add a stringeeCall2 property to the OutgoingCallActivity class:
      private StringeeCall2 stringeeCall2;
      private StringeeAudioManager audioManager;
    2. Modify the implementation of the onCreate method in OutgoingCallActivity class to include code to make a call:
      stringeeCall2 = new StringeeCall2(MainActivity.this, client, from, to);
      // Initialize audio manager to manage the audio routing
      audioManager = StringeeAudioManager.create(this);
      audioManager.start(new StringeeAudioManager.AudioManagerEvents() {
      @Override
      public void onAudioDeviceChanged(StringeeAudioManager.AudioDevice selectedAudioDevice, Set<StringeeAudioManager.AudioDevice> availableAudioDevices) {
          // All change of audio devices will receive in here
      }
      });
      audioManager.setSpeakerphoneOn(isVideoCall); // false: Audio Call, true: Video Call
      // Make a call
      stringeeCall2.setVideoCall(isVideoCall); // false: Audio Call, true: Video Call
      stringeeCall2.makeCall();
  1. Handle the call type

    Your Server uses the project's answer_url to determine the type of outgoing call (app-to-app or app-to-phone). Hence, you should be able to complete it independently. However, we offer an easy method for you to implement quickly:

    stringeeCall2.setCustom(custom);

    'custom' is a customizable text that be sent to Your Server via the project's answer_url. You can set it as: {'type': 'app-to-app'}, {'type':'app-to-phone'} or any other texts you want. Your Server will check this text to determine whether the call is app-to-app or app-to-phone.

  2. Implement the StringeeCall.StringeeCallListener interface to interact with the call:

    stringeeCall2.setCallListener(new StringeeCall2.StringeeCallListener() {
        @Override
        public void onSignalingStateChange(final StringeeCall2 stringeeCall, final StringeeCall2.SignalingState signalingState, String reason, int sipCode, String sipReason) {
        }
    
        @Override
        public void onError(StringeeCall2 stringeeCall2, int code, String description) {
        }
    
        @Override
        public void onHandledOnAnotherDevice(StringeeCall2 stringeeCall2, StringeeCall2.SignalingState signalingState, String description) {
        }
    
        @Override
        public void onMediaStateChange(StringeeCall2 stringeeCall2, StringeeCall2.MediaState mediaState) {
        }
    
        @Override
        public void onLocalStream(final StringeeCall2 stringeeCall2) {
        }
    
        @Override
        public void onRemoteStream(final StringeeCall2 stringeeCall2) {
        }
    
        @Override
        public void onVideoTrackAdded(StringeeVideoTrack stringeeVideoTrack) {
        }
    
        @Override
        public void onVideoTrackRemoved(StringeeVideoTrack stringeeVideoTrack) {
        }
    
        @Override
        public void onCallInfo(StringeeCall2 stringeeCall2, final JSONObject callInfo) {
        }
    });
    • When the client fails to make a call, the onError(StringeeCall stringeeCall, int code, String description) method is invoked.
    • When the client makes a call successfully, the call will walk through a lot of states such as: calling, ringing, answered, ended, busy... Each time the call's state, the onSignalingStateChange(final StringeeCall call, final StringeeCall.SignalingState signalingState, String reason, int sipCode, String sipReason) method is invoked.
    • When the call's media stream is connected or disconnected, the onMediaStateChange(StringeeCall stringeeCall, StringeeCall.MediaState mediaState) method is invoked.
    • When the call is handled on another device, the onHandledOnAnotherDevice(StringeeCall stringeeCall, StringeeCall.SignalingState signalingState, String description) method is invoked. A call is actually established when it's answered and the media's state is MediaState.CONNECTED.

Step 8: Answering a call

For clients to be able to answer an incoming call:

  1. Create IncomingCallActivity class to display the incoming call screen.
  2. Modify the implementation of the onIncomingCall(StringeeCall stringeeCall) method and include code to navigate to the IncomingCallActivity.
    @Override
    public void onIncomingCall2(StringeeCall2 stringeeCall2) {
        callsMap.put(stringeeCall2.getCallId(), stringeeCall2);
        Intent intent = new Intent(MainActivity.this, IncomingCallActivity.class);
        intent.putExtra("call_id", stringeeCall2.getCallId());
        startActivity(intent);
    }

    Pass the call id to the IncomingCallActivity class.

  3. Add a stringeeCall2 property to the IncomingCallActivity class:
    private StringeeCall2 stringeeCall2;
    private StringeeAudioManager audioManager;
  4. Get StringeeCall2 from calls map:
    String callId = getIntent().getStringExtra("call_id");
    stringeeCall2 = callsMap.get(callId);
  5. Initialize the answer and send a ringing signal:
    // Initialize audio manager to manage the audio routing
    audioManager = StringeeAudioManager.create(this);
    audioManager.start(new StringeeAudioManager.AudioManagerEvents() {
        @Override
        public void onAudioDeviceChanged(StringeeAudioManager.AudioDevice selectedAudioDevice, Set<StringeeAudioManager.AudioDevice> availableAudioDevices) {
        }
    });
    audioManager.setSpeakerphoneOn(isVideoCall); // false: Audio Call, true: Video Call
    stringeeCall2.ringing(new StatusListener() {
        @Override
        public void onSuccess() {
        }
    });
  6. Answer and start the conversation:
    stringeeCall2.answer();

Step 9: Displaying video

The Stringee Android SDK exposes videos of caller and callee as View objects. You can add these as children of ViewGroup objects in your app. This sample app will use FrameLayout objects (which extend ViewGroup) as containers for the caller and callee views:

  1. Open the app/res/layout/activity_outgoing_call.xml file and include the following:

    <FrameLayout
        android:id="@+id/v_remote"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    
    <FrameLayout
        android:id="@+id/v_local"
        android:layout_width="80dp"
        android:layout_height="120dp"
        android:layout_alignParentRight="true"        
        android:layout_margin="10dp" />
    
  2. Declare mLocalViewContainer and mRemoteViewcontainer as properties of OutgoingCallActivity class.

    private FrameLayout mLocalViewContainer;
    private FrameLayout mRemoteViewContainer;
  3. Initialize these layout view objects.

    mLocalViewContainer = (FrameLayout) findViewById(R.id.v_local);
    mRemoteViewContainer = (FrameLayout) findViewById(R.id.v_remote);
  4. Register the StringeeCall2.StringeeCallListener interface as described in 7.4

  5. Modify the implementation code of the onLocalStream(final StringeeCall2 stringeeCall2) method to display caller's video (local media stream):

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            if (stringeeCall2.isVideoCall()) {
                mLocalViewContainer.addView(stringeeCall2.getLocalView());
                stringeeCall2.renderLocalView(true);
            }
        }
    });

    onLocalStream(final StringeeCall2 stringeeCall2) method runs in background thread. So in order to interact with UI components from this method, your code must run in UI thread.

  6. Modify the implementation code of the onRemoteStream(StringeeCall2 stringeeCall2) method to display callee's video (remote media stream):

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            if (stringeeCall2.isVideoCall()) {
                mRemoteViewContainer.addView(stringeeCall2.getRemoteView());
                stringeeCall2.renderRemoteView(false);
            }
        }
    });

Step 10: Hanging up

Terminate a call and release resources:

```
stringeeCall2.hangup();
// Stop audio manager to restore the previous audio settings before making a call
audioManager.stop();
```

Step 11: Reject

Reject a call:

```
stringeeCall2.reject();
// Stop audio manager to restore the previous audio settings before making a call
audioManager.stop();
```

Step 12: Mute

Mute the local sound:

```
bool mute = true // true: mute, false: unmute
stringeeCall2.mute(true);
```

Step 13: Switch speaker

Switch to speakerphone or internal speaker:

```
bool isSpeaker = true // true: speakerphone, false: internal speaker
audioManager.setSpeakerphoneOn(isSpeaker);
```    

Step 14: Switch camera

Switch the local camera:

```
stringeeCall2.switchCamera(new StatusListener() {
    @Override
    public void onSuccess() {
    }
});
``` 

Step 15: Turn on/off video

Turn on/off video:

```
bool enableVideo = true // true: turn on, false: turn off
stringeeCall2.enableVideo(enableVideo);
``` 

Step 16: Share the screen (require android API >= 21)

  1. Initialize StringeeScreenCapture and start capture:

    We have 2 approaches to start sharing the screen

    • Using AppCompatActivity

      • Initialize StringeeScreenCapture:

        import com.stringee.video.StringeeScreenCapture;
        ...
        StringeeScreenCapture screenCapture = new StringeeScreenCapture.Builder().buildWithAppCompatActivity(this)
      • Start capture screen: Before start capture screen, you need to create and start a Foreground service with foregroundServiceType is mediaProjection.

        stringeeCall2.startCaptureScreen(screenCapture, new StatusListener() {
            @Override
            public void onSuccess() {}
            });
    • Using Activity

      • Initialize StringeeScreenCapture:

        import com.stringee.video.StringeeScreenCapture;
        ...
        StringeeScreenCapture screenCapture = new StringeeScreenCapture.Builder().buildWithActivity(this)
        ...
        // Register receive activityResult
        @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
        }
      • Start capture screen: Before start capture screen, you need to create and start a Foreground service with foregroundServiceType is mediaProjection.

        int REQUEST_CODE = YOUR_REQUEST_CODE;
        stringeeCall2.startCaptureScreen(screenCapture, REQUEST_CODE, new StatusListener() {
            @Override
            public void onSuccess() {}
            });
        ...
        // After start capture, you will receive capture data onActivityResult then you need to create capture  
        @Override
        protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if(requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK){
                screenCapture.createCapture(data);
            }
        }
  2. Display capture video:

    After successfully capturing the screen, you will receive a StringeeVideoTrack which is your capture screen track or other screen tracks from onVideoTrackAdded:

    @Override
    public void onVideoTrackAdded(StringeeVideoTrack stringeeVideoTrack) {
        runOnUiThread(() -> {
            // Add view of this track to your view to display
            yourView.removeAllViews();
            yourView.addView(stringeeVideoTrack.getView(YourActivity.this));
            stringeeVideoTrack.renderView(true);
        });
    }
  3. Stop capture screen:

    stringeeCall2.stopCaptureScreen(new StatusListener() {
        @Override
        public void onSuccess() {}
        });
    ...
    //After stopCaptureScreen success, you will receive event onVideoTrackRemoved, then you can remove this track view in your view
    @Override
    public void onVideoTrackRemoved(StringeeVideoTrack stringeeVideoTrack) {
        runOnUiThread(() -> {
            yourView.removeAllViews();
        });
    }

Step 17: Running the app

The now complete code allows you to run the app with your device. You can view the full version of this sample app on GitHub: https://github.com/stringeecom/android-sdk-samples/tree/master/OneToOneCallSample