Add Video Calling in Xamarin apps using 📱

Sid Sharma
May 23, 2018 · 9 min read

The Xamarin SDK is an open source project that enables developers to build cross platforms apps in C#. After requests from many developers, we have officially adopted the Xamarin binding and open sourced it to help others easily bring real time communications to their mobile apps.

Open sourced projects are something that we can all get behind, so we want YOU to interact with this! Jump in and make pull requests, fork this, translate it or just help other developers by improving our documentation.

For the remainder of this article, I will help you get started with your first video call using the Xamarin SDK. Let’s get to it! 🤓


Step 1. Account

If you haven’t already, create an developer account. Once you finish the sign up process, you will be redirected to the Dashboard. Open the Projects tab on the left hand nav to see your default project’s App ID.

Step 2. Integrate the Agora SDK

Create a new Blank Native app Solution.

Step 3. Add Agora Nuget packages to iOS project

For AgoraTutorial.iOS project add package Xamarin.Agora.Full.iOS

Step 4. Privacy settings for camera and mic access

In the Info.plist file, make sure to add the Privacy Settings for both the camera and the microphone in order for the device to access them. Also check that minimum iOS version is 9.3. And verify the project properties build target is Armv7 + AMD64, the library does not support Armv7s as a target.

Step 5. Adding views

First, download the assets provided in this tutorial. These assets are icons for the different buttons added throughout this tutorial. Rename the file from ViewController.cs to VideoCallViewController.cs for a more relevant file name as this will be the view controller we set up for the video call. Next, add a new view to the project (SetChannelViewController.cs) in order to allow the user to choose which channel to join. We will go ahead and dive into the code for each of these files after we set up the storyboard.

Next, open the Main.storyboard file and in the identity inspector, set the custom class to VideoCallViewController to update the storyboard VC link with the renamed cs file. Set Storyboard Id to VideoCallView.

Next, drag in a View component for the remote video feed. Inside the remote view, add another view which will be used for the local video feed. This view sits on the top right corner in most video chat applications. Using the same height/width & x/y values, create an image view and assign it the cameramute.png asset. This image will be used to overlay the remote video feed when the user pauses their video feed. Afterwards, drag an image view to the center of the local video image view and assign it the cameraoff_mainVideo.png image. Add another image view with the same cameraoff_mainVideo.png image and center it in the middle of the remote view. On the bottom of the screen, create a view which encapsulates four buttons: Pause Video, Audio Mute, Switch Camera, and Hang Up. Use the appropriate assets for each button and refer to the image above for placement.

Next, drag a View Controller in the Main.storyboard file. Add a text field for the user-inputted channel name and a button to start the video call. In the identity inspector, set the custom class to SetChannelViewController in order to link the storyboard VC with the file.

Step 6. Add Agora Functionality

Initialize Agora Native SDK

AgoraRtcEngineKit is the basic interface class of Agora Native SDK. The AgoraRtcEngineKit object enables the use of Agora Native SDK's communication functionality. Create a variable that is an AgoraRtcEngineKit object make it an implicitly unwrapped optional. Next add interface (IAgoraRtcEngineDelegate) to your controller. Next, create a method (InitializeAgoraEngine()) that will initialize the AgoraRtcEngineKit class as a singleton instance to initialize the service before we use it. In the method call, supply two parameters: AppId and delegate. Provide your App ID as a String and pass in self for the delegate providing the current View Controller (the View Controller controlling the call). The Agora Native SDK uses delegates to inform the application on the engine runtime events (joining/leaving a channel, new participants, etc). Call the InitializeAgoraEngine() method inside the ViewDidLoad() method. Lastly, add a String optional (channel) for the channel name that will be supplied by the user in a different View Controller that will be built later in this tutorial.

Enable Video Mode

Create a method (SetupVideo()) and enable video mode within the method. In this tutorial, we are enabling video mode before entering a channel so the end user will start in video mode. If it is enabled during a call, it switches from audio to video mode. Next, set the video encoding profile to 360p and set the swapWidthAndHeight parameter to false. Passing true would result in the swapping of the width and height of the stream. Each profile includes a set of parameters such as: resolution, frame rate, bitrate, etc. When the device's camera does not support the specified resolution, the SDK automatically chooses a suitable camera resolution, but the encoder resolution still uses the one specified by SetVideoProfile. Afterwards, call SetupVideo() in the ViewDidLoad() method.

Join Channel

At this time, create a method (JoinChannel()) to let a user join a specific channel. Call the agoraKit.JoinChannelByToken() method and supply null for the token and info parameters. For the channel name, supply any string (ex: "demoChannel1") and pass in 0 for the UID to allow Agora to chose a random UID for the channel ID.

Disable the UI Application’s Idle Timer and enable the speakerphone using the Agora Kit. Users in the same channel can talk to each other, however users using different App IDs cannot call each other (even if they join the same channel). Once this method is called successfully, the SDK will trigger the callbacks. We will not be implementing them in this tutorial, but they will be a part of our future tutorial series. Lastly, call JoinChannel() in the ViewDidLoad() method.

Setup Local Video

Now it’s time to create the view for local video feed. Create a method (SetupLocalVideo()) to initialize the AgoraRtcVideoCanvas object, used for the video stream. There are a few object properties that need to be properly setup. Set the Uid property to 0 to allow Agora to chose a random UID for the stream feed. The View property should be set to the recently added UIView (localVideo). The RenderMode property should be set to VideoRenderMode.Fit to ensure that if the video size is different than that of the display window, the video is resized proportionally to fit the window.

Then, call agoraKit.SetupLocalVideo(videoCanvas) passing in the AgoraRtcVideoCanvas object that was just created. Lastly, call SetupLocalVideo() in the ViewDidLoad() method.

Delegate Methods

Now it’s time to create the view for remote video feed. As before, within the interface builder, add a UIView to the View Controller in Main.storyboard and create an outlet to it within the corresponding View Controller. Once completed, create an extention for the ViewController which extends the IAgoraRtcEngineDelegate. Add the FirstRemoteVideoDecodedOfUid delegate method with the parameters shown above (AgoraRtcEngineKit engine, nuint uid, CoreGraphics.CGSize size, nint elapsed). This callback is hit when another user is connected and the first remote video frame is received and decoded. Inside this method, show the remoteVideo if it's hidden.

Next, initialize the AgoraRtcVideoCanvas object and set the object properties as we did above. Set the Uid property to 0 to allow Agora to chose a random UID for the stream feed. The View property should be set to the recently added UIView (remoteVideo). The RenderMode property should be set to VideoRenderMode.Adaptive to once again ensure that a video size that's different than the display window is proportionally resized to fit the window.

Then, call agoraKit.SetupRemoteVideo(videoCanvas) passing in the AgoraRtcVideoCanvas object that was just created. Next, implement the next DidOfflineOfUid delegate method with the parameters (AgoraRtcEngineKit engine, nuint uid, UserOfflineReason reason), called when another user leaves the channel. Within that method, set the remoteVideo view to be hidden when a user leaves the call. Lastly, implement the last DidVideoMuted delegate method (AgoraRtcEngineKit engine, bool muted, nuint uid), called when a remote user pauses their stream.

Step 7. Adding Other Functionality

Adding Channel Choice

In order to allow the user to choose which room they wish to join, you added a simple UI layout consisting of a text field for the channel name input and a button to start the call. Open the Main.storyboard file and set SetChannelViewController as an Initial View Controller. Now, just add the text field and button as an outlet and action, respectively. If the text field's text property is not empty, show VideoCallViewController within the IBAction function for the button. If the text field's text property is empty, prompt the user to enter some text for the channel name. Lastly, pass the user inputted channel name to the VideoCallViewController.

Update your JoinChannel method in VideoCallViewController to use Channel field recieved from channel input screen.

Video Chat Controls

Create a view (controlButtons) that sits on the bottom of the remote view. This view will contain the Hang Up button, Audio Mute button, Video Pause button, and the Switch Camera button.

Hang Up / End Call

Create a method LeaveChannel() which will enables the user to leave the current video call (channel). Inside the method, call the agoraKit.LeaveChannel passing in null as the parameter. Next, hide the view (controlButtons) containing the bottom buttons. Afterwards, programatically remove both the local & remote video views and set the agoraKit to be null to end the instance of the AgoraRtcEngineKit object. Inside the IBAction for the Hang-Up button, call the LeaveChannel() method we just created. Lastly, create a method HideControlButtons() which hides the view which contains the different buttons.

Audio Mute

Now it’s time to add the mute functionality for the local audio feed. In the IBAction for the Mute button, call the agoraKit.MuteLocalAudioStream() method passing in button.Selected as the sole parameter.

Video Pause

Sometimes, you’re sitting in your Barney PJs and you don’t want to show your video feed to the rest of your co-workers. Add the ability to the IBAction for the Video button by calling agoraKit.MuteLocalVideoStream() method passing in button.Selected as the sole parameter.

Switch Camera

Next, enable the user to choose between the front and rear cameras. Inside the IBAction for the camera switch button, call the agoraKit.SwitchCamera() method to add the camera switch functionality.

Hide Muted Images

Create a method HideVideoMuted() to hide all the image views that are meant to appear when either the remote or local video feeds are paused. Call this method in the ViewDidLoad() method to ensure the images are hidden on app startup.

Setup Buttons

To keep the UX in mind, we will be hiding/showing the buttons (more so the view that contains the buttons) when user clicked on View. Create a method (SetupButtons) and inside it create a tap gesture recognizer (of type: UITapGestureRecognizer) which performs the action of calling the ViewTapped() method. Add the tap gesture recognizer to the view and enable user interaction for the view.


There you have it! It just took a few steps to get a video calling app up and running. If you have any questions, please feel free to reach out via e-mail.

Agora delivers cutting edge APIs for developers.

Sid Sharma

Written by

Born and raised in the Bay Area #Cali ☀️ I speak Swift & C#. Sometimes English. GS Warriors | Dallas Cowboys | Chi Cubs DevRel | @Nexmo | @CodinGame |

Agora delivers cutting edge APIs for developers. Our blog covers the world of technology.

Sid Sharma

Written by

Born and raised in the Bay Area #Cali ☀️ I speak Swift & C#. Sometimes English. GS Warriors | Dallas Cowboys | Chi Cubs DevRel | @Nexmo | @CodinGame |

Agora delivers cutting edge APIs for developers. Our blog covers the world of technology.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store