Mesibo Voice and Video Call APIs - Secure and end-to-end encrypted calling

Estimated reading time: 22 minutes

Mesibo provides a set of powerful voice and video call APIs to add secure & end-to-end encrypted voice and video calling into your apps. The mesibo call APIs are easy to use, and in just a few lines of code, your app will be able to make and receive secure voice and video calls. Mesibo calls are secure and end-to-end encrypted. Mesibo also provides ready to use and open-source user-interface (UI) with all the features you can find in any commercial app so that you can add voice and video calling in your app without any coding.

Quick Start with Mesibo Video and Voice Call APIs

If you do not plan to modify the default user interface, you can copy the following two lines of the code and stop reading further. It’s that easy! You only need to initialize once which will automatically handle incoming calls. For outgoing calls, invoke call API as required. Note that, mesibo maintains the same API signatures across all the supported platforms as far as possible which makes it easy for you to write code on one platform and then port it on another.

Java (Android)

To initialize in Java

MesiboCall.getInstance().init(context);
MesiboCall.getInstance().setDefaultUiTitle('your app name');

To make a call in Java

MesiboCall.getInstance().callUi(this, address, true);

Kotlin (Android)

Similarly, initialization In Kotlin

MesiboCall.getInstance().init(applicationContext)
MesiboCall.getInstance().setDefaultUiTitle('mesibo first app')

To make a call in Kotlin

MesiboCall.getInstance().callUi(this, address, true)

Objective-C (iOS)

Initialization in Objective-C

[MesiboCall startWith:nil name:@"mesibo first App" icon:nil callKit:YES];

To make a call in Objective-C

 [MesiboCallInstance callUi:self address:mRemoteUser video:YES];

Swift (iOS)

Initialization in Swift

MesiboCall.start(with: nil, name: "mesibo first app", icon: nil, callKit: true)

To make a call in Swift

MesiboCall.getInstance().callUi(self, address:mRemoteUser, video:true)

Source code and the Sample code

We recommend looking at Android, iOS, and Javascript sample code to quickly get started with Mesibo Calls and other APIs. Refer to the Download page for download instructions for your platform.

However, if you plan to customize the user interface, the entire source code is available on GitHub that you can modify to suit your needs. You should continue reading this document before you modify the source code.

Understanding Mesibo Call Architecture in Detail

There are two key components to the Mesibo Call architecture:

  • Mesibo Call Processing API: The Call processing API handles the entire call processing, including incoming and outgoing call establishment, reconnection, quality, bitrate control, and other control functionalities like muting audio/video, selecting cameras, filtering/blocking calls, etc. The call processing API runs in the background and does not provide any UI. You can even create a headless application(without any UI) using the Call API. You can control the call behavior (for example, video size, bitrate, etc.) using the call properties.

  • Mesibo Call User Interface (UI): The Call user interface (UI) component uses Mesibo call processing API to control the call and show the call information, for example, local and remote video screens, call ringing, call timer, buttons, etc. The entire Call UI source code is available on GitHub, which you can modify to suit your needs or use it as it is.

Mesibo Call component follows Model-View-Controller (MVC) architecture where call API represents model/controller, and the UI represents the View.

Key components in the Call API

Following are the key components in the Call API:

  • MesiboCall, The Entrance class to the Call API. It provides various functions to initialize call APIs, setting up listeners, creating call objects, etc.
  • IncomingListener, to Handle incoming calls, errors, show call UI, etc. You only need to implement this listener if you plan to customize the default call behavior.
  • CallProperties, to define various call properties and behavior, for example, video size, bitrate, hide on proximity, etc.
  • Call, the core call API.
  • InProgressListener, Handle various call events for an ongoing call, for example, call ringing, answered, declined, hang up, audio device changed, etc. It is optional to implement this listener.

Call API

These components are described in detail in the following subsections.

Initializing the Call API

You can use mesibo call modules with default call handling logic and UI as it is. All you need to do is to intitalize mesibo calls, with a single line of code.

For example, In Android, you can initialize mesibo calls like, similarly for other platforms.

MesiboCall.init(context);

After initializing mesibo calls, you will be able to make outgoing calls and receive incoming calls using various methods in the Call API. In the upcoming sections, you will learn more about using the Call API.

Listening to incoming calls and customizing - IncomingListener

By default, mesibo handles incoming calls for you without any effort from your end. However, if your app requires to alter the call properties (say, video resolution, bandwidth, etc.), OR to launch a custom user interface, your app will need to implement an IncomingListener. We recommend that you implement this listener interface in MainApplication in Android or AppDelegate in iOS. However, you can implement it wherever it suits your application architecture.

Every time there is a new incoming call, mesibo will call MesiboCall_OnIncoming. Depending on your app logic, you can decide to allow the incoming call or filter it. For example, perform call filtering at the application level to reject callers who are blocked/identified as spam, etc. If you decide to allow the call, you need to create a CallProperties object and return it. In the CallProperties object, you can set the video resolution, video/audio bitrate, etc. Mesibo sets the default values for the call properties, but you can override it as required by your app. To reject an incoming call, return null.

For example, in Android,

@Override
public MesiboCall.CallProperties MesiboCall_OnIncoming(Mesibo.UserProfile profile, boolean video){
	// In this example, we use video as a filter to accept video calls only
	if(!video)
		return null; //Accept video calls only
	
	if(profile.address == null || profile.address.isEmpty())
		return null;

	// your app specific function to check if the caller is allowed
	if(isInBlockedList(profile.address)){
		// Check if the caller is part of the blocked list. 
		// You can block spam callers this way.
		return null; // reject the call by returning null
	}
	
	// Define call properties 
	MesiboCall.CallProperties cp = MesiboCall.getInstance().createCallProperties(true);
	
	// Define optional parameters
	cp.video.bitrate = 2000; //bitrate in kbps

	return cp;
}

Similarly for other platforms. Refer to MesiboCall_OnIncoming in the API Reference.

If the call is accepted, mesibo prepares the call API object and invokes MesiboCall_OnShowUserInterface listener to show the user-interface. Your application should return true to show your custom user-interface or return false to show the mesibo default call user-interface.

For example, in Android,

boolean MesiboCall_OnShowUserInterface(Call call, CallProperties properties)
{
	// Show call screen
	return false;
}

Refer MesiboCall_OnShowUserInterface.

You also need to implement MesiboCall_OnError which will be called if any error occurs during a call and #mesibocall_onnotify which you can use to display call notifications for missed calls, etc.

Refer to IncomingListener in the API reference.

Call Properties - CallProperties

CallProperties defines various aspects of a call such as,

  • Voice or Video Call
  • The initial video source, for example, front camera, back camera, screen capture
  • The initial audio device, for example, speaker
  • Video resolution
  • Audio / Video bitrates
  • Call behaviors, for example, automatically mute camera when app goes to background, handling proximity sensor, etc.
  • and more...

There are default values for various call properties. However, you can modify them to suit your needs.

You need to create a CallProperties object for outgoing calls and pass it to the method MesiboCall.call(). If the outgoing call is successful, it will return a Call object( which you can use in your Activity/Fragment or View Controller).

For example, in Android,

MesiboCall.Call mCall = MesiboCall.getInstance().getActiveCall();
if(mCall == null){
	
	...

	// Create Call Properties
	MesiboCall.CallProperties cp = MesiboCall.getInstance().createCallProperties(true);
	cp.video.enabled = true; //create a Video call
	cp.user = new Mesibo.UserProfile();
	
	mCall = MesiboCall.getInstance().call(cc);
	if(mCall == null){
		//Call failed
	}

}

In case of an incoming call, MesiboCall_OnIncoming will be called. Here, you should create and return a CallProperties object. If your app does not implement IncomingListener, mesibo will create CallProperties object with the default values.

For example, in Android,

@Override
public MesiboCall.CallProperties MesiboCall_OnIncoming(MesiboCall.Call call, Mesibo.UserProfile profile, boolean video) {
	// call object will created by mesibo for you
	
	// Initialize call properties
	cp = MesiboCall.getInstance().createCallProperties(true);
	
	// use default values

	return cp;
}

Refer to CallProperties in the API reference.

Creating the core Call API object - Call

The Call class is the most important class that handles the entire call processing for your app. To manage any call (incoming or outgoing), you need a Call object.

There is no Call constructor available. Instead, you need to call a factory method MesiboCall.call() to create an instance of the Call object. Using this factory method ensures that no call object is created if another call is in progress.

In case of an outgoing call, you need to create a CallProperties object, and pass it to MesiboCall.call(). If the outgoing call is placed successfully, MesiboCall.call() will return a Call object.

In case of an incoming call, mesibo will create a Call object and pass it to you in the MesiboCall_OnShowUserInterface callback.

You can access the Call object anytime, by calling getActiveCall(). Before you make an outgoing call, it is recommended that you use isCallInProgress() or getActiveCall() to check if there is an ongoing call. If there is no ongoing call, getActiveCall() will return null.

MesiboCall.Call mCall = MesiboCall.getInstance().getActiveCall();
if(mCall == null){
	//There is no active call 
	//We can make an outgoing call

	//Create a CallProperties object
	MesiboCall.CallProperties cp = MesiboCall.getInstance().createCallProperties(true);

	// Call Factory method to create a call object
	mCall = MesiboCall.getInstance().call(cp);
	if(mCall == null){
		//Error
	}
}

Refer to Call in the API reference.

Monitoring a Call - InProgressListener

The InProgressListener is invoked by mesibo call API for various events such as - change in call status (ringing, answered, etc.), when remote peer mutes, when the active audio device changes from an earpiece to a speaker, etc. You can implement InProgressListener in your user interface to get continuous feedback on what is happening on the call to update your user interface or take any actions based on this information, for example,

  • If the call is ringing, MesiboCall_OnStatus will be called. You can update your user interface or play a ringing sound or a custom caller tune.
  • When the call is answered, you can start a call timer and update the user interface.
  • When active audio device changes, MesiboCall_OnAudioDeviceChanged will be called. If it is a speaker you may choose to highlight the speaker button.
  • Etc.

Refer to InProgressListener in the API reference for more details.

In the next section, we will discuss some of the fundamental concepts of designing a good calling app.

Essentials of a Calling App

This section will describe the essentials of a call app and how to use mesibo voice and video call APIs to create one such app.

Designing your Call Screens

In a typical call application, the call screen is one of the most important steps in the design flow. Although mesibo allows you to design your user interface as you like, it is essential to remember that users are accustomed to a particular way of handling calls. Hence, it is recommended to follow standard practice when designing call screens.

There are typically two types of call screens.

  1. Incoming Screen, which allows the user to know the caller, type of the call (voice or video), and controls to accept or decline the call.

  2. InProgress Screen, the screen is shown after the incoming call is accepted or for an outgoing call. The Inprogress screen typically has buttons to hangup, change audio devices, muting, hang up, timer, etc. If the call is of type video, it may have additional controls for remote and local video views, camera controls (only for video calls), etc.

Following are some examples of typical Incoming and Inprogress screens:

Incoming Screen

Call Incoming The user is alerted by displaying an incoming call screen - with the caller’s profile and buttons to accept or reject the call. If the user accepts the call, the call continues, and the screen changes to display the call in progress.

Inprogress Screen

Call Outgoing The app displays an outgoing call screen with the destinations’ profile and a button to hang up the call. You may play a ringing sound or caller tune until the call is answered(See playInCallSound. If the destination answers the call, the call continues.

Mesibo makes it easy for you to design a calling screen by invoking necessary callbacks as the call progresses. For example, MesiboCall_OnUpdateUserInterface will be called depending on the call status, which you can use to change UI on the fly as the call progresses, MesiboCall_OnMute is called when the remote user mutes the video or voice, etc.

Request Microphone and Camera Permissions

Mesibo Call API requires a microphone and camera (only for video calls) access to make and receive calls. Hence, your app should have permission to access the microphone and the camera. Both Android and iOS requires you to prompt the user for necessary permissions at run-time, microphone for voice calls, and microphone+camera for video calls.

You can use Android or iOS API calls to request necessary permissions, OR you can use the mesibo helper function checkPermissions, which simplifies the handling of required permissions.

checkPermissions

Mesibo provides checkPermissions, a function that you can use to request and check for permissions. It takes the following parameter:

  • video, Set to true if requesting permissions for a video call, false otherwise

Returns:

  • 0 if the user granted all permissions
  • 1 if the app is prompting the user for permissions
  • A negative value if the user declines the permissions.

For example, in Android,

//Request permissions necessary for a video call
int res = checkPermissions(true);

if(res < 0) {
/* permissions were declined */
}

if(0 == res) {
/* all permissions granted */
}

In the upcoming sections, we will describe how to make outgoing calls and receive calls. We will explain how mesibo handles outgoing and incoming calls. We will then explain how your app should handle outgoing and incoming calls with the Call API’s help.

How Mesibo handles an Outgoing Call

Outgoing Call

Mesibo handles an outgoing call as follows:

  1. The App invokes MesiboCall.call() to place an outgoing call.
  2. Mesibo checks if there is any call in progress (an active call on the application or the phone).
  3. If there is any call in progress, the outgoing call fails. If there are no other active calls, mesibo returns a call object.
  4. The app initiates an outgoing call by calling MesiboCall.start().
  5. If the destination answers the call, the call continues.
  6. If either of the parties on the call hangs up, the call is completed and MesiboCall_OnHangup will be called.

How the app should initiate an Outgoing Call

In a typical application flow, the user presses a button to place an outgoing call. The app then displays a screen showing an outgoing call and other information like the destination’s profile, the phone number or address, etc.

However, before the app launches a call screen, it should check if there is no call is in progress.

Check for any active calls

Before making an outgoing call, we need to be sure that there are no other ongoing calls. If getActiveCall() returns null then we are free to make a new call by creating a Call object.

MesiboCall.Call mCall = MesiboCall.getInstance().getActiveCall();
if(mCall == null){
	//There is no active call 
	//We can make an outgoing call
}

Once the app launches the call screen, the app can create a call object and initiate the outgoing call.

Initialize CallProperties

To make an outgoing call, the app needs to create a CallProperties object. See CallProperties for a complete list of properties that you can set for a call.

Then pass the CallProperties to MesiboCall.call() method, which will then return a Call object. Invoke start() on the call object to initiate the call.

For example, in Android,

MesiboCall.Call mCall = MesiboCall.getInstance().getActiveCall();
if(mCall == null){
	//There is no active call 
	//We can make an outgoing call
	
	MesiboCall.CallProperties cp = MesiboCall.getInstance().createCallProperties(false);
	
	// When using an Activity
	cp.parent = this;
	cp.activity = this;
	cp.video.enabled = true; //make a video call

	cp.user = profile;

	mCall = MesiboCall.getInstance().call(cp);
	if(mCall == null){
		//Alert user about the error. 
	}
}
else {	
	// Alert user that another call is ongoing or show UI for that call
}

After initiating an outgoing call, we display the Inprogress screen. The call screen can then update the UI based on various callbacks in the InProgressListener.

How Mesibo handles an incoming call

Incoming Call Mesibo handles an incoming call as follows:

  1. The mesibo user logged in on the application receives an incoming call from another mesibo user.
  2. Mesibo checks if there is any call in progress (a call active on the application or the phone).
  3. If there is any call in progress, a busy status is sent to the caller. If there are no other active calls, MesiboCall_OnIncoming will be called with the profile of the caller(contains the caller’s address, photo, etc).
  4. The application should create, initialize, and return a CallProperties object from MesiboCall_OnIncoming. To reject the call, MesiboCall_OnIncoming should return null.
  5. If CallProperties is initialized, Mesibo creates a Call object.
  6. MesiboCall_OnShowUserInterface is called with the Call object and the CallProperties object, initialized in the previous step as parameters.
  7. The application should now show the incoming call UI. Display the Call screen with the Answer and Hangup button. See How app should handle an incoming call.
  8. If the user accepts the call, mesibo will continue the call. If the user declines the call, the call ends, and mesibo informs the caller that the user is busy.
  9. As the call progresses, listeners in InProgressListener will be invoked for various events.
  10. If either of the parties on the call hangs up, the call is completed, and mesibo calls MesiboCall_OnHangup.

How the app should handle an incoming call

Incoming Call

Follow the steps below to handle an incoming call:

  1. Implement MesiboCall_OnIncoming. It will be called whenever there is an incoming call.
  2. Initialize and return CallProperties in MesiboCall_OnIncoming.
  3. Implement MesiboCall_OnShowUserInterface. When this listener is called, launch the incoming call screen.
  4. The user can then accept or decline the incoming call. If the user accepts the call, the call continues. Display the call in progress screen.
  5. Implement listeners in InProgressListener and update the Call UI for events.

Initialize CallProperties in MesiboCall_OnIncoming

Mesibo provides MesiboCall_OnIncoming as part of the listener interface, MesiboCall.IncomingListener. If you implement MesiboCall_OnIncoming, it will be called whenever there is an incoming call.

To handle the incoming call, you need to return a CallProperties object from MesiboCall_OnIncoming. The CallProperties can define various aspects of the call, such as the call title, video width, bitrate, etc., that you can modify as per your needs. Refer to CallProperties for a complete list of the various properties that you can set.

For example, in Android,

@Override
CallProperties MesiboCall_OnIncoming(Mesibo.UserProfile profile, boolean video){
	MesiboCall.CallProperties cc;
	cp = MesiboCall.getInstance().createCallProperties(video);
	
	cp.video.enable = true;  // Video call 
	cp.video.bitrate = 1800; // Set Maximum video bitrate
	cp.video.codec = MesiboCall.MESIBOCALL_CODEC_H265;
	return cc;
}

After you return a valid CallProperties object, Mesibo will invoke MesiboCall_OnShowUserInterface with the Call object and CallProperties object as parameters.

For example, in Android,

@Override
boolean MesiboCall_OnShowUserInterface(MesiboCall.Call call, MesiboCall.CallProperties properties){ 
	//launch Call Screen
}
call, voice, video