Integrating SIP in Flutter Applications: A Comprehensive Guide #2
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:
- 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.