Docs

User Guide

Introduction

The Sinch SDK is a product that makes adding voice calling and/or instant messaging to mobile apps easy. It handles all the complexity of signaling and audio management while providing you the freedom to create a stunning user interface.

This document provides an overview for developers integrating with Sinch SDK for the first time. It outlines the prerequisites and guides you through the process of setting up and answering calls as well as sending and receiving instant messages.

Please see the Reference Documentation for a comprehensive description of all the classes.

First time setup

Below is a step-by-step guide on setting up the Sinch SDK for the first time.

Register an Application

  1. Register a Sinch Developer account at http://www.sinch.com/signup.
  2. Setup a new Application using the Dashboard where you can then obtain an Application Key and an Application Secret.

Download

The Sinch SDK can be downloaded at www.sinch.com/download/. It contains: the library binary, this user guide, reference documentation, and sample apps for calling and instant messaging.

Add the Sinch library - Eclipse

  1. Confirm that the latest version of the Android Development Tools are being used.
  2. Copy the entire libs folder from the Sinch SDK archive into the project’s root directory.

Add the Sinch library - Android Studio/IntelliJ

  1. Copy the entire libs folder to your project’s root directory.
  2. Right-click the jar-files and choose ‘Add As Library’.
  3. Create a new folder under src/main and name it jniLibs.
  4. Move the armeabi and armeabi-v7a folders into the newly created jniLibs folder.

Permissions

A minimum set of permissions are needed for the app to use the Sinch SDK. These are specified in the AndroidManifest.xml file. If the calling functionality will be used, all five permissions listed here are needed. However, if the calling functionality isn’t used, the last three (RECORD_AUDIO, MODIFY_AUDIO_SETTINGS and READ_PHONE_STATE) can be omitted.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

Note: By default, the Sinch SDK hangs up any Sinch call if the regular phone app has an active call. This functionality requires the permission READ_PHONE_STATE. However, if this default functionality isn’t wanted, turn it off by calling sinchClient.getCallClient().setRespectNativeCalls(false); and the permission READ_PHONE_STATE is not needed.

Verify manifest in runtime during development

To verify that the manifest has the necessary permissions the sinchClient.checkManifest() method can be used. This method should be called before starting the client and will throw an exception if the manifest isn’t setup correctly. sinchClient.checkManifest() should only be called during development. When the application is ready for release the method call can safely be removed.

Note: This method takes into consideration which features the app supports (for example, calling, instant messaging, respecting native calls, and so on). Call sinchClient.checkManifest() after the setup but before the start of the SinchClient.

Sinch client

The SinchClient is the Sinch SDK entry point. It is used to configure the user’s and device’s capabilities, as well as to provide access to feature classes such as the CallClient, MessageClient and AudioController.

Create a SinchClient

// Instantiate a SinchClient using the SinchClientBuilder.
android.content.Context context = this.getApplicationContext();
SinchClient sinchClient = Sinch.getSinchClientBuilder().context(context)
                                                  .applicationKey("<application key>")
                                                  .applicationSecret("<application secret>")
                                                  .environmentHost("sandbox.sinch.com")
                                                  .userId("<user id>")
                                                  .build();

The Application Key and Application Secret are obtained from the Sinch Developer Dashboard. See Production and Sandbox Environments for valid values for environmentHost. The User ID should uniquely identify the user on the particular device.

Note: All listener callbacks emitted from the Sinch SDK are invoked on the same thread that the call to SinchClientBuilder.build is made on. If the invoking thread is not the main-thread, it needs to have an associated Looper.

Specify capabilities

The SinchClient can be configured to enable or disable certain functionality. Please see the Reference for a comprehensive description of each capability.

The following example shows how to setup the client with both voice calling and instant messaging enabled.

// Specify the client capabilities. 
// At least one of the messaging or calling capabilities should be enabled.
sinchClient.setSupportMessaging(true);
sinchClient.setSupportCalling(true);
sinchClient.setSupportActiveConnectionInBackground(true);
sinchClient.setSupportPushNotifications(true);
sinchClient.startListeningOnActiveConnection()

Calling startListeningOnActiveConnection allows your application to receive incoming calls and messages.

Note: If the application is meant to only make outgoing calls but not receive incoming calls, don’t call startListeningOnActiveConnection. Outgoing calls can be made after calling the start method.

Start the Sinch client

Before starting the client, add a client listener (see Reference documentation):

sinchClient.addSinchClientListener(new SinchClientListener() {

    public void onClientStarted(SinchClient client) { }

    public void onClientStopped(SinchClient client) { }

    public void onClientFailed(SinchClient client, SinchError error) { }

    public void onRegistrationCredentialsRequired(SinchClient client, ClientRegistration registrationCallback) { }

    public void onLogMessage(int level, String area, String message) { }
});

sinchClient.start();

Terminate the Sinch client

When the app is done using the SinchClient, it should be stopped. If the client is currently listening for incoming events, it needs to stop listening as well. After terminate is called, any object that you retrieved directly from the client object (that is, CallClient, MessageClient, and AudioController) are considered invalid.

Terminating the client:

sinchClient.stopListeningOnActiveConnection();
sinchClient.terminate();

Calling

The Sinch SDK supports two types of calls: app-to-app calls and app-to-phone calls. The CallClient is the entry point for the calling functionality of the Sinch SDK.

Calls are placed through the CallClient and events are received using the CallClientListener. The call client is owned by the SinchClient and accessed using sinchClient.getCallClient(). Calling is not enabled by default.

Enable calling with the following method before starting the SinchClient:

sinchClient.setSupportCalling(true);

Set up an app-to-app call

Use the CallClient to start the call (the callUser method). Pass the user identifier of the callee (the user receiving the call) to the call method, so that Sinch services can connect the call to the callee.

CallClient callClient = sinchClient.getCallClient();
Call call = callClient.callUser("<remote user id>");
call.addCallListener(...); 

A call object is returned, containing details about the participants in the call, call details such as start time, call state, possible errors, and so on.

Assuming the callee’s device is available, the method onCallProgressing is called on the CallListener. It notifies the application that the outgoing call is progressing. If a progress tone should be played, this is where it should be started.

When the other party answers, the onCallEstablished method is called. Now, the users can start talking. If a progress tone was previously played, it should be stopped now.

Set up an app-to-phone call

An app-to-phone call is a call that is made to a phone on the regular telephone network. Setting up an app-to-phone call is not much different than setting up an app-to-app call. Instead of invoking the callUser method, invoke the callPhoneNumber method on the CallClient object. Sufficient funds must be available on the Sinch account and a valid phone number specified for the call to connect successfully. The phone number should be specified according to the E.164 number formatting (http://en.wikipedia.org/wiki/E.164) recommendation and should be prefixed with a ‘+’. E.g. to call the US phone number 415 555 0101, the phone number should be specified as “+14155550101”. The ‘+’ is the required prefix and the US country code ‘1’ prepended to the local subscriber number.

Placing an app-to-phone call requires a developer account with credits. Topping up credits can be done on the Account page. Credits are used each time an app-to-phone call is placed and the balance history is updated after each call.

App-to-phone calls can be tested by calling the following test number: +46000000000. When placing a call to this number, you will hear a voice prompt stating that the call has been connected, and shortly after that the call will automatically be ended.

Handle incoming calls

To answer calls, the application must be notified when the user receives an incoming call.

Add a CallClientListener to the CallClient to act on the incoming calls. The CallClientListener is notified using onIncomingCall as calls come in to the device.

CallClient callClient = sinchClient.getCallClient();
callClient.addCallClientListener(...);

When the incoming call method is executed, the call can either be connected automatically without any user action, or it can wait for the user to press the answer or the hangup button. If the call is set up to wait for a user response, we recommended that a ringtone is played to notify the user that there is an incoming call.

@Override
public void onIncomingCall(CallClient callClient, Call call) {
    // Start playing ringing tone
    ... 

    // Add call listener
    call.addCallListener(...);          
}       

To get events related to the call, add a call listener. The call object contains details about participants, start time, potential error codes, and error messages.

Answer incoming call

To answer the call, use the answer method on the call to accept it. If a ringtone was previously played, it should be stopped now.

User presses the answer button:

// User answers the call
call.answer();

// Stop playing ringing tone
...     

Now, the clients on both ends establish the connection. When the call is established and the voice streams are running in both directions, the onCallEstablished listener method is called.

Decline incoming call

If the call should not be answered, use the hangup method on the call to decline. The caller is notified that the incoming call was denied. If a ringtone was previously played, it should be stopped now.

User presses the hangup button:

// User does not want to answer
call.hangup();

// Stop playing ringing tone
...     

Disconnecting a Call

When the user wants to disconnect an ongoing call, use the hangup method. Either user taking part in a call can disconnect it.

Hanging up a call:

call.hangup();

When either party disconnects a call, the application is notified using the call listener method onCallEnded. This allows the user interface to be updated, an alert tone to be played, or similar actions to occur.

A call can be disconnected before it has been completely established.

Hanging up a connecting call:

// Starting a call
Call call = callClient.callUser("<remote user id>");

// User changed his/her mind, let’s hangup
call.hangup();

Volume control

To make sure that the volume of the call can be modified by the hardware volume controls, setVolumeControlStream(AudioManager.STREAM_VOICE_CALL) must be called on the Activity where the call is handled. Make sure that volumeControlStream is reset to a suitable value when the call has ended.

For example, after creating a call (using CallClient.callUser) or when answering a call (using Call.answer()) you should call setVolumeControlStream(AudioManager.STREAM_VOICE_CALL);.

When the call ends, set the volume control stream back to it’s previous value. For example in your implementation of CallListener:

    @Override
    public void onCallEnded(Call call) {
        setVolumeControlStream(AudioManager.USE_DEFAULT_STREAM_TYPE);
    }

Instant messaging

The MessageClient is the entry point to Instant Messaging functionality in the Sinch SDK.

Messages are sent through the MessageClient and events are received using the MessageClientListener. The message client is owned by the SinchClient and accessed using SinchClient.getMessageClient(). Instant messaging is not enabled by default. To enable instant messaging, SinchClient.setSupportMessaging(true) must be set.

sinchClient.setSupportMessaging(true);
sinchClient.start();

...

MessageClient messageClient = sinchClient.getMessageClient();
messageClient.addMessageListener(...);

Send a message

Sending a message with the Sinch SDK is easy. Get hold of a MessageClient as described earlier and pass it a WritableMessage.

// Create a WritableMessage
WritableMessage message = new WritableMessage(
        "someRecipientUserId",
        "Hello someRecipientUserId! How are you?"); 

// Send it
messageClient.send(message);

Message delivery success

When a message to a recipient is successfully sent, there is an event on the MessageClientListener, onMessageSent.

@Override
public void onMessageSent(MessageClient client, Message message) {
    // Persist message
    // Update UI
}

Updating the UI from the onMessageSent callback is especially convenient when a user is logged in into more than one device simultaneously. The onMessageSent callback is fired on each device. This aids in keeping the UI consistent across devices.

When the system has confirmed the messages were delivered the listener is notified using the onMessageDeliveredmethod. Inspecting the MessageDeliveryInfo parameter passed to the callback reveals more details on the specific event.

@Override
public void onMessageDelivered(MessageClient client, MessageDeliveryInfo deliveryInfo) {
  Log.d(TAG, "The message with id "+deliveryInfo.getMessageId()
    +" was delivered to the recipient with id"+ deliveryInfo.getRecipientId());
}

Message delivery failures

Delivering a message to a recipient can fail for various reasons: there might not be a network available, the recipient does not have instant messaging support and so on. When a message failed to reach its destination the listener is notified using the onMessageFailed callback. The reason for failing to deliver a message is propagated back as an MessageFailureInfo instance.

@Override
public void onMessageFailed(MessageClient client, Message message, MessageFailureInfo failureInfo) {
        Log.d(TAG, "Failed to send to user: "+info.getRecipientId()
                    +" because: "+failureInfo.getSinchError().getMessage());
}

Note: Messages are persisted internally in the SDK. In case the message was not sent successfully it will be retried automatically at a later point in time. The message will be retried for 12 hours and then fail permanently firing the failure callback.

Note: Messages are stored in the backend for 30 days before being removed. If the recipient has not started the app and downloaded the message history within this time frame, the message will be lost and no notification will be received.

Note: A message should be retried only in case of network unavailability (use messageFailureInfo.getSinchError().getErrorType().equals(ErrorType.NETWORK)). In this case create a new WritableMessage (using new WritableMessage(message)) and send that instance because the previous message is considered stale.

Receive a message

Incoming messages (Message) are delivered using the method onIncomingMessage on the MessageClientListener.

@Override
public void onIncomingMessage(MessageClient client, Message message) {
    // Persist message
    // Update UI
}

Send a message to multiple recipients

To send a message to multiple recipients, create the message with the WriteableMessage(List<String> recipientUserIds, String textBody) constructor.

// Create a WritableMessage and send to multiple recipients
WritableMessage message = new WritableMessage(
        {"recipient user id 1", "recipient user id 2"},
        "Hello recipients! How are you?");  

// Send it
messageClient.send(message);

Receiving recipient status updates for multi-recipient messages

The recipient’s state transitions for the message are communicated back using the MessageClientListener listener the same as in the single recipient case. The listener’s callbacks are triggered for every recipient.

Push notifications

An application is considered offline in the following scenarios:

  • When the application is not running
  • When background mode has been disabled for the Sinch client, and the application is not in the foreground

For these two scenarios, push notifications must be implemented in the application to be able to receive incoming calls and instant messages. The following sections cover how to support receiving calls and messages via push notifications.

The Sinch client relies on a push service to launch the application if it is not currently listening for incoming calls or messages due to the application being offline. Which push service to use is up to the developer, but for Android applications, the typical choice is to use Google Cloud Messaging (GCM). The examples that follow assume that Google Cloud Messaging is used to deliver push messages.

When offline, the recipient of a call or message receives a push notification containing a Sinch-specific payload that enables the Sinch Client to connect the incoming call or message. Acting on the push notification brings the application to the foreground allowing the user to answer the call or view the message.

Figure 2. Push notification sequence.
Figure 2. Push notification sequence.

Figure 2 describes the following sequence of events: Both users start their applications and Sinch clients. When A (the caller) calls B (the callee), B’s application is in a state where it is not considered online (that is reachable using an active socket connection). Sinch notices that B is not online, and tells A to send a push notification to B so that B can answer the call.

When the Sinch client on the caller’s (or sender’s) side observes that the destination client is offline, it notifies the application that it needs to trigger the sending of a push notification to the recipient device.

Push notification data

On startup, each instance of the application is expected to register a device identifier. The identifier is referred to as push notification data and should be provided to the Sinch client using the method registerPushNotificationData.

Push notifications can be addressed to that identifier in the event that the application goes offline.

The push notification data can be any byte sequence; it is up to you to define its structure and what it contains. However, the push notification data must not exceed 1024 bytes. It should contain enough information to allow a push service to send a push notification to a particular user of the application on a particular device. For example, an Android exclusive application would likely use the GCM registration id as its push notification data.

Multi-platform applications may use a mix of different push services. For instance, in an application running on both iOS and Android, the platform identifier in the push notification data can be used by the push server to determine whether APNS or GCM should be used.

The device-specific push notification data should be registered on start up of the application, or as soon as it’s available. If user B then turns off the application, and user A calls B, user A’s application would get the callback CallListener.onShouldSendPushNotification. One of the parameters in this callback, is a list of PushPairs that contain a payload and a push notification data. Each element in this list corresponds to each of B’s registered push notification data identifiers (a user can have multiple devices).

The push notification data can also be unregistered by calling the SinchClient.unregisterPushNotificationData method. This effectively disables incoming calls or messages using push notifications for the particular device.

Enable push notifications

The following sections assumes that GCM is used, but the use pattern for other push services is similar.

The easiest way to enable offline calls or messages using GCM is to first call SinchClient.setSupportPushNotifications(true) and then register the device specific push notification data with SinchClient.registerPushNotificationData. In a simple example we can use the registration id received from Google when registering to GCM.

// Register with the GCM service to get a device specific registrationId
// Should be done in a background job
GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(context);
String regId = gcm.register("Your-Sender-ID");

...

sinchClient.setSupportPushNotifications(true);
sinchClient.start();
sinchClient.registerPushNotificationData(regId);

Please refer to Google’s Google Cloud Messaging for Android for more information on how to use the GCM service.

Note: As described in the Push Data Notification section, the data that you register with the registerPushNotificationData method is defined by you. If using GCM, it must at a minimum include the registrationId from Google (so a GCM server can push to a particular device).

Send and receive push notifications

To send push messages the application developer must have a server that is configured for sending push notifications to the Google Cloud Messaging Service. Please see the Sinch REST API User Guide for details on how to handle feedback from Google Cloud Messaging Service.

Also refer to Google’s Google Cloud Messaging for Android for detailed information on how GCM works.

On the caller side

When the recipient’s application is offline and the app needs to notify the user using a push notification, the caller’s or sender’s application is notified using the callback method CallListener.onShouldSendPushNotification.

The callback includes a List of PushPairs. The pairs contain a payload that is Sinch- and call-specific. Moreover the pairs contain a push data byte array. The Sinch specific payload should be embedded in the push notification sent to the recipient’s device(s). The push data is the same push data that the recipient’s application registered earlier. There might be multiple registered devices for the recipient user (for example, the same user is using the application on both a phone and a tablet), which is why the callback includes a List of Push Pairs.

public void onShouldSendPushNotification(Call call, List<PushPair> pushPairs) {
    // Send payload and push data to application server
    // which should communicate with GCM Service to send push notifications.
}

A push notification should be sent to each device, where each entry in the parameter pushPairs list corresponds to one device. Each push notification should include the Sinch-specific payload so it can be forwarded to the Sinch client running on the destination device.

The Sinch-specific payload should be embedded as custom payload data in the GCM Payload.

{
  "registration_ids" : ["APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...", ...],
  "data" : {
    "Sinch" : <payload>,
  },
}

Please refer to Google’s Google Cloud Messaging for Android for more information.

On the callee side

As a prerequisite, offline calling and messaging must be enabled on the receiver’s side (see Push Notifications).

When the application receives a push notification from the Google Cloud Messaging Service, the application should extract the Sinch-specific payload from the push notification, and forwarding it to the Sinch client using the method relayRemotePushNotificationPayload.

protected void onMessage(final Context context, final Intent intent) {
    String sinchPayload = intent.getStringExtra("Sinch");

    sinchClient.relayRemotePushNotificationPayload(sinchPayload);
}

Application authentication

A user identity must be provided when initiating a Sinch client. The first time the application instance and the Sinch client are running on behalf of a particular user, they are required to register against the Sinch service. This is mostly handled transparently by the Sinch SDK, but it works slightly differently depending on which authentication scheme you choose to use.

The step of registering a user identity against the Sinch service requires the application instance to be authenticated and authorized to perform the user registration. Once the application instance has successfully registered the user identity, it will also have obtained the necessary credentials to perform further authorized requests for that specific user, for example, calling.

Two different authentication schemes are available: authentication by client access to application secret and authentication supported by application server.

Authentication by client access to Application Secret

This application authentication scheme is based on giving the application direct access to the Application Secret, which enables the Sinch Client SDK in the application to self-sign an authorized request to perform user registration. Choosing this authentication scheme corresponds to initiating the Sinch client by using the factory method that takes both an Application Key and an Application Secret.

Using this authentication scheme is the quickest way to get started as the client application instances can directly perform authorized requests against the Sinch service.

Caution: It is not recommended to have the application secret in plain text in the source code in the release version of the application.

Authentication supported by application server

This application authentication scheme is based on the client application instance not having direct access to the Application Secret. Instead, when the Sinch client needs to perform an authorized request to register a user identity against the Sinch service, it needs to be provided with an authentication signature and a registration sequence to perform the registration. This should be provided by the application’s backend service, for example, by using a HTTP request over an SSL connection.

This scheme has the benefit of the application secret never being directly accessible by the client applications and provides a better level of security as well as flexibility.

Note: The need for the Sinch client to request an authentication signature and registration sequence is only required once per user and device–not on every application launch.

Figure 4. Authentication Supported by Application Server
Figure 4. Authentication Supported by Application Server

Generating the signature

The Application Server is responsible for generating a valid signature for each registration request that it accepts as a valid user registration. The sequence is a cryptographic nonce, and must be a monotonically increasing value. The signature is then generated as as follows (pseudogrammar):

string userId;
string applicationKey; // E.g. "196087a1-e815-4bc4-8984-60d8d8a43f1d"
string applicationSecret; // E.g. "oYdgGRXoxEuJhGDY2KQ/HQ=="
uint64 sequence = previous_sequence + 1; // E.g. previous_sequence = 0

string stringToSign = userId + applicationKey + sequence + applicationSecret;

// Use a Base64-encoder that don't introduce line-breaks, 
// or trim the output signature afterwards.
string signature = Base64.encode(SHA1.digest(stringToSign));

For example, in Java:

    // Generating the Signature - Java
    // import java.security.MessageDigest;
    // import org.apache.commons.codec.binary.Base64;

    String userId; 
    String applicationKey; // E.g. "196087a1-e815-4bc4-8984-60d8d8a43f1d";
    String applicationSecret; // E.g. "oYdgGRXoxEuJhGDY2KQ/HQ==";
    long sequence; // fetch and increment last used sequence

    String toSign = userId + applicationKey + sequence + applicationSecret;

    MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
    byte[] hash = messageDigest.digest(toSign.getBytes("UTF-8"));

    String signature = Base64.encodeBase64String(hash).trim();

Set up the Sinch client and provide authorization credentials for user registration

// Instantiate a SinchClient using the SinchClientBuilder,
// and don't specify the application secret, only the application key.
android.content.Context context = this.getApplicationContext();
SinchClient sinchClient = Sinch.getSinchClientBuilder().context(context)
                                                  .applicationKey("<application key>")
                                                  .environmentHost("sandbox.sinch.com")
                                                  .userId("<user id>")
                                                  .build();

sinchClient.addSinchClientListener(...);

// SinchClientListener implementation
public void onRegistrationCredentialsRequired(SinchClient client, 
                                              ClientRegistration registrationCallback) {
    // This will on the first run for this user call onRegistrationCredentialsRequired on the client listener.
    // Perform API request to server which keeps the Application Secret.
    myApiService.getAuthorizedSignatureForUser("<user id>", new OnCompletedCallback() {
        public void onCompleted(String signature, long sequence) {
            // pass the signature and sequence back to the Sinch SDK
            // via the ClientRegistration interface.
            registrationCallback.register(signature, sequence);
        }
    });
}

Miscellaneous

Minimum requirements

You must have Android version 2.3 (Gingerbread) or later to use the Sinch SDK.

Production and Sandbox environments

Sinch provides two environments:

  • Production - Used for applications deployed in production.
  • Sandbox - Used during development and testing.

The environment is passed as the parameter environmentHost when instantiating the Sinch client.

Environment EnvironmentHost parameter
Production clientapi.sinch.com
Sandbox sandbox.sinch.com

Restrictions on User IDs

User IDs can only contain characters in the printable ASCII character set. That is:

!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~

User IDs must not be longer than 64 characters.

Encryption export regulations and Google Play

Please check the Summary of U.S. Export Controls Applicable to Commercial Encryption Products and ensure that the application is registered for the Encryption Regulations, if applicable. It can be found under this link.

Statistics

The Sinch SDK client uploads statistics to the Sinch servers at the end of a call, a call failure, or similar event. The statistics are used for monitoring of network status, call quality, and other aspects regarding the general quality of the service.

Some of the information is not anonymous and may be associated with the User ID call participants.

The statistics upload is done by the client in the background.

Glossary

This glossary defines some of the domain specific terms used throughout this document.

Term Explanation
Application The mobile application running on iOS and/or Android. A partner can have more than one application.
Application Instance One installation of the application on a single device.
Application Key A key generated by Sinch. The key is unique to the application. A key looks like 196087a1-e815-4bc4-8984-60d8d8a43f1d (lowercase hexadecimal formatted GUID).
Application Secret A string generated by Sinch. The secret is used to verify the application. A secret looks like oYdgGRXoxEuJhGDY2KQ/HQ== (Base64-encoded string representation).
Callee The person receiving a call.
Caller The person making a call.
User A user of the mobile application. The actual person holding the mobile device.
User Identity Identity of a user in the application domain. Can be any string, for instance a user name, user id, phone number or email address.
Active Connection A socket connection for signaling purposes where incoming calls are received.

Third party libraries and copyright notices

All Third Party Libraries and Copyright notices can be found under this link.