Integrating SIP in Flutter Applications: A Comprehensive Guide #2

Vinayak
YavarTechWorks
Published in
3 min readAug 20, 2024

In our previous article, we introduced the concept of integrating SIP (Session Initiation Protocol) into Flutter applications. We covered the basics of SIP and WebRTC, explaining how these technologies enable voice and video calls, messaging, and real-time communication over the internet.

We then explored the sip_ua plugin, a powerful tool maintained by the flutter-webrtc team, which allows for seamless SIP integration across mobile, desktop, and web platforms using pure Dart. To kickstart the development, we set up a local Asterisk server using Docker, providing an easy-to-configure environment. Finally, we walked through the process of connecting to the SIP server by configuring the necessary settings in the UaSettings class and using the SIPUAHelper class to establish the connection. This laid the groundwork for enabling your Flutter app to handle voice and video calls.

In this article, we’ll build on that foundation by diving into how to implement audio and video calling functionality within your Flutter application.

Setting Up Audio and Video Calls

To make calls in our application, we’ll be using the call method in SIPUAHelper. But first, we need to capture the user’s media, such as audio and video, to include in the call. Here’s how to do it:

final Map<String, dynamic> mediaConstraints = <String, dynamic>{
"video": true,
"audio": true,
};
final MediaStream mediaStream =
await navigator.mediaDevices.getUserMedia(mediaConstraints);
await sipuaHelper.call(target, mediaStream: mediaStream);

Breaking Down the Code:

  1. Media Constraints Definition:
final Map<String, dynamic> mediaConstraints = <String, dynamic>{
"video": true,
"audio": true,
};

This Map defines the types of media you want to access from the user’s device. Both video and audio are set to true, meaning you want to capture both. If you only want to make an audio call, you can set "video” to false.

2. Accessing the User’s Media Stream:

final MediaStream mediaStream =
await navigator.mediaDevices.getUserMedia(mediaConstraints);

The getUserMedia method requests access to the user’s media devices (camera and microphone) based on the specified constraints. It returns a MediaStream object that contains the audio and video tracks from the user’s device.

3. Making a SIP Call with Media Stream:

await sipuaHelper.call(target, mediaStream: mediaStream);

The call method initiates a SIP call to the specified target. By passing the mediaStrea as a parameter, you’re ensuring that the call will include the user’s audio and video streams, enabling a full video call experience.

Answering and Ending Calls

Answering a Call

When you receive an incoming SIP call, you can answer it using the answer method provided by the Call class:

call.answer(sipuaHelper.buildCallOptions(!call.remote_has_video));

Explanation:
- call.answer(): This method accepts the incoming call.
- sipuaHelper.buildCallOptions(...): This constructs and returns a set of options for the call, such as whether to enable video.
- !call.remote_has_video: This checks if the remote party (the caller) has video enabled. The ! operator negates the value, so if the caller has video, you won’t force the local video, and if not, you might enable the local video by default.

Ending a Call

To end or terminate a call, use the hangup method:

call.hangup();

This will immediately terminate the ongoing call.

What’s Next?

In this article, we’ve covered how to make audio and video calls, answer incoming calls, and terminate them using the sip_ua plugin. However, simply making calls isn’t enough — we also need to update the UI to reflect the call status, such as when a call is incoming or outgoing. Additionally, features like muting the microphone or holding/unholding a call need to be handled.

In our next article, we’ll explore how to update the UI in response to call events and how to implement advanced features like toggling the microphone and handling call hold/unhold states.

Stay tuned!

Thanks for reading this article ❤

If I got something wrong? Let me know in the comments. I would love to improve.

Until then Bye-Bye.

--

--