Agora SDK Integration for Video Communication in Mobile Application
Agora — one of most common managed services for real-time video and audio. SDK handles WebRTC under hood, own transport network (not public internet), adaptive bitrate and codecs. Integration task — not just add dependency but properly configure lifecycle, tokens, event handling and UI.
Initialization and Tokens
Agora works on App ID + Token model. App ID — public identifier from console. Token — short-lived JWT generated by your backend via Agora Token Builder and passed to client on channel join.
Initialize engine once on app startup:
// iOS
let config = AgoraRtcEngineConfig()
config.appId = "YOUR_APP_ID"
agoraKit = AgoraRtcEngineKit.sharedEngine(with: config, delegate: self)
// Android
val config = RtcEngineConfig()
config.mContext = context
config.mAppId = "YOUR_APP_ID"
config.mEventHandler = handler
rtcEngine = RtcEngine.create(config)
Re-initialization on each call — mistake. sharedEngine — singleton, repeated call with same App ID just returns existing instance. RtcEngine.create() on Android — no: each call creates new instance, previous must be destroyed via RtcEngine.destroy(). Not obvious from docs but native resource leak appears after 3–5 calls.
Channel Join and Video Handling
let option = AgoraRtcChannelMediaOptions()
option.clientRoleType = .broadcaster
option.channelProfile = .communication
agoraKit.joinChannel(
byToken: token,
channelId: channelName,
uid: 0, // 0 = auto-assign
mediaOptions: option
)
uid: 0 — Agora assigns UID. If need binding to system user — pass deterministic numeric ID (not UUID — Agora UID is UInt32).
Render local video via AgoraRtcVideoCanvas with setupLocalVideo(). Remote — via setupRemoteVideo() in delegate method didJoinedOfUid. Important: setupRemoteVideo() must be called on main thread, otherwise EXC_BAD_ACCESS on quick connect/disconnect.
func rtcEngine(_ engine: AgoraRtcEngineKit, didJoinedOfUid uid: UInt, elapsed: Int) {
DispatchQueue.main.async {
let canvas = AgoraRtcVideoCanvas()
canvas.uid = uid
canvas.renderMode = .hidden
canvas.view = self.remoteVideoView
self.agoraKit.setupRemoteVideo(canvas)
}
}
Video Quality Configuration
Agora provides presets (AgoraVideoEncoderConfiguration) and custom parameters:
let config = AgoraVideoEncoderConfiguration(
size: CGSize(width: 640, height: 360),
frameRate: .fps15,
bitrate: AgoraVideoBitrateStandard,
orientationMode: .adaptative,
mirrorMode: .auto
)
agoraKit.setVideoEncoderConfiguration(config)
For mobile 360p/15fps — reasonable quality/battery balance. 720p/30fps — for tablets or when quality critical. AgoraVideoBitrateStandard — automatic bitrate selection per resolution, works better than manual setting in most scenarios.
Interrupt Handling and Lifecycle
On iOS AVAudioSession.routeChangeNotification and AVAudioSession.interruptionNotification — Agora SDK handles auto with correct AgoraAudioScenario setup. Scenario .meeting — optimal for video calls: enables AEC (acoustic echo cancellation), ANS (noise suppression), AGC (gain normalization).
On incoming system call on iOS Agora doesn't pause auto. Implement via CXCallObserver and callObserver(_:callChanged:): on CXCall.hasConnected == true — mute local audio in Agora (muteLocalAudioStream(true)), on termination — unmute.
On Android transition to background without ForegroundService — Android 8+ kills process after 5–10 minutes. Start ForegroundService on call begin with notification. android:foregroundServiceType="camera|microphone" in manifest mandatory from Android 14.
Token Authentication Errors
AgoraErrorCode.tokenExpired (109) and AgoraErrorCode.invalidToken (110) — most common production issues. Token has limited TTL (24 hours to 1 hour depending on settings). Implement handling via tokenPrivilegeWillExpire delegate method — get new token from backend and call renewToken() without breaking connection.
Typical error: token generated with UID 0 on backend but client after joinChannel gets specific UID from Agora — on next renewToken pass token generated for wrong UID. Need to save UID from didJoinChannel and use for new token request.
Timeline
Basic integration (1-to-1 video call with camera management, mute, flip) — 3–5 days. With group support up to 8 participants, token management and background mode — 1–2 weeks. Cost calculated after requirement analysis.







