Agora & Sendbird SDK Integration in iOS Application
Technostacks
With smartphones, chat capabilities have become common for mobile apps, and messaging apps are all the rage. The engagement that comes with chat features will unarguably push your users to spend more and more time on the app. Modern chat apps support not only text messages but also multimedia elements like images, videos, GIFs, and audio calls & video calling.
While implementing chat features, you can write everything by yourself or use some scaffolding from others to make the development faster.
Below is the list of available 3rd party SDKs (Software Development Kits) for integrating chat audio & video calling functionality into iOS applications.
Here are some popular and most used SDK options:
- Sendbird
- Firebase Real-time Database and Firebase Cloud Messaging
- Twilio
- Agora
- Zendesk Chat SDK
- PubNub
We have implemented all the above SDKs in our various areas of iOS applications.
We will discuss here the Agora & SendBird SDK implementation and the key features of both SDKs.
Agora SDK (Chat & Video Calling With Streaming Video Content)
Agora SDK (Software Development Kit) is a bundle of tools, libraries, and APIs provided by Agora, Inc. to developers with the sole aim of enabling them to infix their functions for real-time audio, video, and interactive broadcasting into their own apps. The foremost Agora SDK is used to aid in the integration of mechanisms through which applications can provide users with real-time communication, collaboration, and interaction.
Key Features Of The Agora SDK
Voice and Video Communication
The Agora SDK allows the developers to build the user interface of voice and video calling in the application. In other words, with the Agora SDK, as an example from our side, a user is able to make a one-to-one call or make a group call.
Interactive Broadcasting
The use of the Agora SDK can be by developers in making interactive broadcasting applications where one or more hosts may broadcast themselves to a large audience but at the same time enable the audience to interact via chat, likes, and many others.
Real-Time Messaging
The SDK makes not only voice calls but also video calls and empowers real-time text messaging and chat functionalities for conversation amongst users in the time of voice or video calls and standalone message applications.
Screen Sharing
Developers can also enable screen sharing in their apps, whereby the user is able to share their screens with other users during a call.
Cross-Platform Support
Agora SDK is versatile since it is compatible with iOS and Android devices, web browsers, and desktop applications making developers enjoy uniform experiences on various devices.
High Quality and Low Latency
Agora has emphasized in high audio and video quality as well as good latency to make the communication experience all smooth and immersive.
Customization and Integration
The SDK offers customization options fitting the branding and user experience of the host application. It also provides, then the APIs to integrate the real-time communication features seamlessly into the UI of the app.
You can Integrate the Agora SDK in various applications, such as video conferencing apps, social networking platforms, e-learning platforms, and virtual events, among others.
Read More:- Localization in SwiftUI – String Catalogs with Xcode 15
Agora SDK Implementation Guide for iOS Applications
Prerequisites
Xcode (latest version)
- A valid Agora account (sign up at [Agora Developer Portal](https://www.agora.io/en/)
- An iOS device or simulator running iOS 9.0 or later.
SDK Installation
- Using CocoaPods
- Open your project’s `Podfile`.
- Add the following line to your `Podfile`:
- Manual Integration
- Initializing the Agora SDK
pod ‘AgoraRtcKit’
– Run the command `pod install` in your project directory.
– Open the `.xcworkspace` file generated by CocoaPods.
– Download the Agora SDK from the [Agora Developer Portal](https://www.agora.io/en/).
– Drag and drop the `AgoraRtcKit.framework` file into your Xcode project.
– In your project’s target settings, under “General,” add the `AgoraRtcKit.framework` to the “Frameworks, Libraries, and Embedded Content” section.
– Replace `”APP_ID”` with your Agora App ID.
import AgoraRtcKit func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { AgoraRtcEngineKit.sharedEngine(withAppId: "YOUR_APP_ID", delegate: nil) return true
– To implement the user interface, create two views for the display of local and remote videos.
// The video feed for the local user is displayed here var localView: UIView! // The video feed for the remote user is displayed here var remoteView: UIView! remoteView.frame = CGRect() localView.frame = CGRect() func initViews() { // Initializes the remote video view. This view displays video when a remote host joins the channel. remoteView = UIView() self.view.addSubview(remoteView) // Initializes the local video window. This view displays video when the local user is a host. localView = UIView() self.view.addSubview(localView) }
– First, we need to get permission for the camera and microphone, for that add these two permission keys to the info.Plist file.
NSCameraUsageDescription $(PRODUCT_NAME) uses the camera for video call Privacy - Microphone Usage Description $(PRODUCT_NAME) uses the microphone for video call
– Here is the Apple native AVCaptureDevice class to ask for permission before starting the camera.
func requestCameraAccess() -> Bool { var hasCameraPermission = false let semaphore = DispatchSemaphore(value: 0) switch AVCaptureDevice.authorizationStatus(for: .video) { case .notDetermined: AVCaptureDevice.requestAccess(for: .video, completionHandler: { granted in hasCameraPermission = granted semaphore.signal() }) semaphore.wait() return hasCameraPermission case .restricted: AVCaptureDevice.requestAccess(for: .video, completionHandler: { granted in hasCameraPermission = granted semaphore.signal() }) semaphore.wait() return hasCameraPermission case .denied: return false case .authorized: return true @unknown default: AVCaptureDevice.requestAccess(for: .video, completionHandler: { granted in hasCameraPermission = granted semaphore.signal() }) semaphore.wait() return hasCameraPermission } }
– Also, need to request audio permission using the same AVCaptureDevice class.
func requestAudioAccess() -> Bool { var hasAudioPermission = false let semaphore = DispatchSemaphore(value: 0) AVCaptureDevice.requestAccess(for: .audio, completionHandler: { granted in hasAudioPermission = granted semaphore.signal() }) semaphore.wait() return hasAudioPermission }
In our case, we have generated a unique channel using the random alphanumeric string function and get a video token and streaming token from the backend API.
func init() { if checkForPermissions() { if userType == .userHost { self.getStreamingTokenAndJoinCall() } else { // if a user is not hosting this video call, we get this channel name, a token from firebase notification passed by the host user self.userId = UInt("logged user-id") self.agoraManager.channelName = channelName ?? "" self.agoraManager.videotoken = token ?? "" self.agoraManager.streamingToken = token ?? "" self.joinChannel() } } }
var userId:UInt = 0 var playerId:Int = 1001 var channelName = "" var videocallChanneltoken = "" var streamingChanneltoken = "" var videoURL:String? func randomAlphaNumericString(length: Int) -> String { let allowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" let allowedCharsCount = UInt32(allowedChars.count) var randomString = "" for _ in 0 ..< length { let randomNum = Int(arc4random_uniform(allowedCharsCount)) let randomIndex = allowedChars.index(allowedChars.startIndex, offsetBy: randomNum) let newCharacter = allowedChars[randomIndex] randomString += String(newCharacter) } return randomString } func getStreamingTokenAndJoinCall() { let channelName = randomAlphaNumericString(length: 5) DispatchQueue.main.sync { self.userId = UInt("logged user id") self.agoraManager.channelName = channelName ?? "" self.agoraManager.videotoken = videocallChanneltoken ?? "" self.agoraManager.streamingToken = streamingChanneltoken ?? "" self.playerId = playerID ?? 1001 self.joinChannel() } }
To join a channel for real-time communication, We can use the channel ID.
agoraKit.joinChannel(byToken: nil, channelId: "yourChannelId", info: nil, uid: 0, joinSuccess: nil)
To publish your own audio and video stream, you'll need to configure the local media settings and then start publishing.
agoraKit.enableVideo() // Enable video agoraKit.enableAudio() // Enable audio // Setup local video view let localVideoView = UIView() agoraKit.setupLocalVideo(localVideoView) // Start publishing agoraKit.startPreview() agoraKit.startPublishing()
As a host user, you can also publish media streams in video calls using the Agora mediakit player.
// push video url in agora mediakit player self.agoraManager.mediaPlayerKit.open(videoURL ?? "00", startPos: 0) self.agoraManager.publishStream(channelName: agoraManager.channelName, UId: playerId)
- Callback called when a new host joins the channel.
extension ViewController: AgoraRtcEngineDelegate { func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) { let videoCanvas = AgoraRtcVideoCanvas() videoCanvas.uid = uid videoCanvas.renderMode = .hidden videoCanvas.view = remoteView agoraEngine.setupRemoteVideo(videoCanvas) } }
- To subscribe to other users' audio and video streams, you'll need to set up remote video views and then subscribe to the streams.
// Your remote video view let remoteVideoView = UIView() agoraKit.setupRemoteVideo(remoteVideoView, forUid: remoteUid) agoraKit.subscribeRemoteVideoStream(remoteUid, type: .video, streamType: .high, subscribeSuccess: nil)
- You should manage user interface elements that allow users to start/stop publishing and subscribing, as well as UI elements for displaying video views.
- Leave Channel
- When the user wants to end the communication session, make sure to leave the channel and release resources.
agoraKit.leaveChannel(nil) agoraKit.stopPreview() agoraKit.setupLocalVideo(nil) agoraKit.setupRemoteVideo(nil, forUid: remoteUid)
- Implement UI controls for actions like muting audio, disabling video, switching cameras, etc. Use Agora SDK methods to manage these interactions.
Sendbird SDK (In-App Chat API And SDK Platform)
Sendbird SDK makes it easy for retailers to connect buyers and sellers within the mobile app for increased conversions and engagement for better retention all with a superior support edge. Increase community growth at the same time reducing churn. Essential moderation tools to keep the conversation safe.
Read More:- Placing 3D Objects In Real-World With SwiftUI
Key Features Of The Sendbird SDK
1. Group channels
A feature to enable a chat among up to 100 users in a channel, public and private. In the group channel, it would take place through an invitation for a 1-on-1 or 1-to-N private chat for users while a public chat without permission would involve various users.
2. Push notifications
Ability to send a push notification for the user's devices in case of a new message.
3. Typing indicators
Indication of whether the other users in the channel are typing a message.
4. Read receipts
Allowing the user to be aware that their messages have been read by the other users in the channel.
5. Smart throttling
A feature to customize the number of messages displayed in a large group chat by adjusting the message loading speed.
6. Message Search
First, a feature that is to be added is a search specific to messages of the channel. Developers and users will be able to find messages by title in the desired channel.
7. Message metadata
Feature that allows developers to add extra data to the messages being sent.
8. Image auto-moderation
A feature that would allow automatic filtering of explicit image inventory messages or inappropriate image URLs.
9. TLS-based message encryption
A feature that enables the Sendbird server and client apps to have messages that are encrypted as required by the protection against eavesdropping, tampering, and message forgery demands of the Transport Layer Security (TLS).
10. Advanced analytics
A feature that allows user behavior analysis through nine different metrics occurring on channels, messages, and users.
These features enable instant communication, collaborative discussions happen, the ability to track messages, monitor content in forums, share multilingual experiences, there is seamless integration and a piece of cake. Do note that in the latest SDK versions, there might be additional features too.
Read More:- Create a 3D Floor Plan of an Interior Room Using RoomPlan
For implementing chat, there are 2 options available:
- SendBird Chat SDK
- SendBird UIKit
On the other hand, the Chat SDK is more low-level and flexible and you have more control over how you want to implement and customize the chat experience inside your app.
The SendBird UIKit SDK is a high-level library that essentially comes built on top of the Chat SDK. It provides pre-built UI components and ready-to-use user interface elements which through easy integration get to be added to your app.
Sendbird SDK Implementation Guide for iOS Applications
Beforehand, one has to create a SendBird application either through the SendBird Dashboard before integrating the SendBird Chat SDK. This application consists of all the fundamental elements of chat service including the user's profiles, exchanging messages, and communication channels. To get started with Chat SDK, you will need a unique Application ID of your SendBird application acquired from the dashboard.
The minimum requirements for Chat SDK for iOS are the following.
- macOS
- Xcode 14.1 and later
- At least one device running iOS 11.0 and later
- Swift 5.0 and later or Objective-C
Install SendBird chat SDK with either Swift Packages Or CocoaPods Or Carthage. If you don’t want to write all code on your own you can use the available open source code of SendBird UIKit and do modifications as per requirements.
You see the Sources folder in the source code of UIKit. To your existing project, you could add that folder and accordingly update the color themes and styles. You should add a NotificationService folder under Sample to add the things related to notifications.
Every time the connection state of your iOS app changes, the Chat SDK has to be awoken to respond in properly. In waking up the Chat SDK, you will want to start it up. Starting the Chat SDK calls for your Sendbird application's special APP_ID which is available on the Sendbird Dashboard.
This ID helps the SDK work smoothly with your app. In AppDelegate file, you need to import chat SDK like below:
import SendbirdChatSDK func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let APP_ID = "APP_ID" //Specify your SendBird application ID SendbirdUI.initialize(applicationId: APP_ID) { // This is the origin. // Initialization of SendbirdUIKit has started. // Show a loading indicator. } migrationHandler: { // DB migration has started. } completionHandler: { error in // If DB migration is successful, proceed to the next step. // If DB migration fails, an error exists. // Hide the loading indicator. } }
Then set the current user. User information can be found on the dashboard.
//Case 1: user_id only SBUGlobals.currentUser = SBUUser(userId: "USER_ID") //Case 2: Specify all fields SBUGlobals.currentUser = SBUUser(userId: "USER_ID", nickname: "(Optional)NICK_NAME", profileURL: "(Optional)PROFILE_URL")
In our project, we create the user from the backend when user signup from the website and get the user_id or any other information related to the sendbird on Login and save a relevant data in UserDefault.
With the object instantiated with "SBUGroupChannelListViewController", you can present or push the object whatever you want to get the channel list. When you send some of these messages to any user, it will create a channel with 2 members if there is one-to-one communication or with more than 2 users if there is a group. The "distinct" property works as a toggle that will decide, each and every time that the same person would like to commence a conversation with the same people, whether to re-open an already existing chat channel or create one afresh. For one-to-one discussions, you should set the "distinct" property to true.
This way, you keep using the same channel for ongoing conversations, which is usually what you want. This is the code for presenting ViewController like this. You can also push the ViewController if you are already in the Navigation Controller.
let mainVC = SBUGroupChannelListViewController() let naviVC = UINavigationController(rootViewController: self.mainVC) naviVC.modalPresentationStyle = .fullScreen naviVC.modalTransitionStyle = .crossDissolve self.present(naviVC, animated: true)
If you want to know more about Channel you can get it from their website.
https://sendbird.com/docs/chat/sdk/v4/ios/channel/overview-channel
To share the images, videos, or any other file you first have to add Privacy permission in Info. plist file.
Almost every user interface content can be customized including view layouts, list styles, and themes. This could be done by modifying the code that is placed inside the "Source" folder. This way it lets you control the visual look as well as the behavior of your app's interface altogether. The provided code is implemented according to MVVM architecture. You have the flexibility to change the titles and labels displayed on the screen as well. Customize the text that appears on buttons, headers, and labels to match your app's desired language, tone, or branding.
We added search particular channel in a search bar below the navigation bar. We changed the color theme and some headers and label text. You can see we have changed the left button of the navigation bar like this:
self.mainVC.headerComponent?.leftBarButton = self.createHighlightedBackButton() //function for custom back button func createHighlightedBackButton() -> UIBarButtonItem { let backButton = UIButton(type: .custom) backButton.frame = .init(x: 0, y: 0, width: 40, height: 40) backButton.setImage(UIImage(named: "fi_menu"), for: .normal) backButton.tintColor = UIColor.appSecondaryColor backButton.addTarget(self, action: #selector(onClickBack), for: .touchUpInside) let backBarButton = UIBarButtonItem(customView: backButton) return backBarButton }
If you wish to receive notifications even when your phone is in sleep mode or your app is running in the background, you can achieve this by taking the following steps:
Step 1: Obtain the Necessary Files
Before diving into the technical steps, make sure you have the required files ready:
- APNs Authentication Key (.p8): If you're using Apple's Push Notification Service (APNs), generate an authentication key (.p8) from the Apple Developer account. This key will be used to securely send push notifications to iOS devices.
- SendBird Dashboard Access: Log in to your SendBird Dashboard account, where you'll set up push notifications for your SendBird application.
Step 2: Configure Push Notifications in SendBird Dashboard
- Log in to your SendBird Dashboard account.
- Navigate to your SendBird application.
- Under the "Settings" section, locate the "Push Notifications" tab.
- Upload the APNs authentication key (.p8) file that you generated earlier.
Step 3: Integrate Push Notifications in Your App
- In your iOS app project, add the APNs authentication key (.p8) file.
- Implement the necessary code to handle push notifications:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { //Register a device token to SendBird server SendbirdUI.registerPush(deviceToken: deviceToken) { success in } func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let userInfo = response.notification.request.content.userInfo guard let payload: NSDictionary = userInfo["sendbird"] as? NSDictionary else { return } let havePresentedVC = UIApplication.shared.currentWindow?.rootViewController?.presentedViewController != nil let isSignedIn = UserDefaultHelper.isLoggedIn ?? false let needToPedning = !(isSignedIn || havePresentedVC) if needToPedning { self.pendingNotificationPayload = payload } else { guard let channel: NSDictionary = payload["channel"] as? NSDictionary, let channelURL: String = channel["channel_url"] as? String else { return } let sceneDelegate = UIApplication.shared.connectedScenes .first!.delegate as! SceneDelegate if havePresentedVC { SendbirdUI.moveToChannel(channelURL: channelURL, basedOnChannelList: true) sceneDelegate.drawerController.setDrawerState(.closed, animated: true) } else { sceneDelegate.hightLightedRow = 2 sceneDelegate.channelUrl = channelURL sceneDelegate.setNV(navId: .MessagesNV) sceneDelegate.drawerController.setDrawerState(.closed, animated: true) } } completionHandler() }
If you want to remove push notification then you need to write below code. This code we have added in the logout function.
SendbirdUI.unregisterPushToken { success in SendbirdUI.disconnect { [weak self] in print("SendbirdUIKit.disconnect") } }
If you want to add an audio/video call service, then it is also available in the sendbird call package.
There are many other features and functions that you will be able to handle when implementing SendBird. The above is just but an example of a short and fast implementation process for you to quickly know how to integrate SendBird into your application.
Conclusion
Here we have discussed how you can implement SendBird and Agora SDK in your iOS applications. We have also discussed the features and implementation guide of both the SDKs.
Technostacks is a leading mobile app development company, successfully accomplished projects in multiple sectors while considering the specific needs of their customers. With an experience of 10+ years, the team of professionals creates each project with a vision oriented towards the offering of solutions. We provide the services of developing chat, voice, and video calling apps for all industries that enable businesses to enhance their app’s user experience.
If you want to integrate video and chat functionalities or have a requirement for something related then you can contact us. Our dedicated developers have vast experience in creating mobile applications with ease and are able to meet your requirements.