Integration of SendBird SDK Chat into Mobile Application
SendBird is not just "connect and it works." SDK is heavy: iOS version adds ~15 MB to binary, Android — about 10 MB AAR. Plus WebSocket connection that needs proper initialization, reconnection on network change, and correct teardown in background. Let's break down where integration usually fails and how to do it right.
Initialization and Authentication
iOS
SendbirdChat.initialize(params: InitParams(applicationId: "APP_ID")) called once in application(_:didFinishLaunchingWithOptions:). Connection:
SendbirdChat.connect(userId: userId, accessToken: token) { user, error in
guard let user else { return }
// Connection established
}
Get token from your backend — don't hardcode it in client. SendBird issues session token with TTL; upon expiration SDK calls SessionDelegate.sessionTokenDidRequireRefresh, there you request new token from your API and return via completionHandler.
On Android similarly: SendbirdChat.init(InitParams(applicationId, context, useCaching = true)). useCaching = true enables local cache on Room — messages available offline without extra code.
Typical Initialization Error
Calling connect before initialize completes. SDK works asynchronously; if calling connect synchronously right after initialize — you get SendbirdError.initializationNotFinished. Need to wait for completion block of initialization or, on Android, CompletionHandler.
Channels and Messages
SendBird operates two channel types: GroupChannel (private, by invitation) and OpenChannel (public, like IRC). For most messengers need GroupChannel.
Creating or getting 1-to-1 channel:
let params = GroupChannelCreateParams()
params.userIds = [currentUserId, targetUserId]
params.isDistinct = true // important: doesn't create duplicate if channel exists
GroupChannel.createChannel(params: params) { channel, error in ... }
isDistinct = true — key parameter. Without it each call creates new channel between same users.
Getting History and Realtime
channel.getMessagesByTimestamp(timestamp, params) — pagination back from timestamp. For realtime subscribe via addChannelDelegate:
SendbirdChat.addChannelDelegate(self, identifier: "ChatVC")
// In delegate:
func channel(_ sender: BaseChannel, didReceive message: BaseMessage) {
// Add to dataSource, update collectionView
}
On Android — addChannelHandler. Important: removeChannelDelegate / removeChannelHandler when destroying screen, otherwise — memory leak and event duplication.
Push Notifications
iOS
Register APNs token in SendBird:
SendbirdChat.registerDevicePushToken(deviceToken, unique: true) { status, error in ... }
unique: true replaces previous device token — needed on reinstall. In AppDelegate.application(_:didReceiveRemoteNotification:) check SendbirdChat.isHandledRemoteNotification(userInfo) — if true, SDK decodes payload itself.
Android
Via FCM: in FirebaseMessagingService.onNewToken call SendbirdChat.registerPushToken(token, unique = true). In onMessageReceived — SendbirdChat.handleRemoteMessageData(remoteMessage.data) for SendBird notification handling.
Common problem: notifications arrive when app is closed but not when open — because you forgot to remove SendbirdChat.setAutoBackgroundDetection(false) in needed scenarios or didn't handle foreground-case.
UI Customization vs UIKit SDK
SendBird offers ready UIKit (SwiftUI/Compose components) — quick start but limited customization. If design is non-standard — work with Core SDK directly, build UI ourselves. Practice: UIKit suits MVP in 1-2 days, custom UI — 3-5 extra days.
Offline and Reconnection
On iOS subscribe to NetworkObserver or NWPathMonitor; on connection restore call SendbirdChat.connect again. SDK syncs missed messages via MessageCollection — if using MessageCollectionDelegate, new message highlighting happens automatically.
On Android useCaching = true + MessageCollection do the same without manual management.
Workflow
SendBird app setup in console → SDK integration (CocoaPods/SPM on iOS, Gradle on Android) → authentication with your backend → channels and messages implementation → push notifications → testing reconnects and edge cases.
Timeline
Basic integration with ready UIKit — 2-3 days. Custom UI on Core SDK — 5-7 days. Cost calculated individually after requirement analysis.







