Інтеграція SDK чату Stream у мобільний застосунок
Stream Chat відрізняється від SendBird архітектурно: API побудований на основі event-driven моделі (WebSocket + event-driven state), SDK пропонує готові SwiftUI/Compose-компоненти з можливістю глибокої кастомізації через subclassing та view factories. Розмір бінарника менше, ніж у SendBird, — iOS близько 8 МБ, Android AAR ~6 МБ. Розберемось інтеграцією з нуля без «Hello World» з документації.
Ініціалізація та токени
Stream працює на JWT. Клієнт ніколи не генерує токен самостійно — тільки ваш бекенд:
POST /api/stream/token
{ "user_id": "user_123" }
→ { "token": "eyJ..." }
На бекенді токен створюється через stream_chat.create_token(user_id) (Python/Node SDK). На клієнті:
// iOS
let client = ChatClient(config: ChatClientConfig(apiKeyString: "YOUR_KEY"))
let token = try Token(rawValue: "eyJ...")
client.connectUser(userInfo: .init(id: userId), token: token) { error in ... }
// Android
val client = ChatClient.Builder("YOUR_KEY", context).build()
client.connectUser(User(id = userId), token).enqueue { result -> ... }
Token refresh: Stream SDK викликає TokenProvider коли токен закінчується. Реалізуйте TokenProvider (iOS: closure-based, Android: інтерфейс TokenProvider) — там робіть запит до вашого API та повертайте новий токен. Без цього користувач вилетить з чату по закінченню TTL токена.
Канали: створення та підписка
Stream використовує комбінацію type:id для ідентифікації каналу. Типи — messaging, livestream, team, commerce, gaming — впливають на дефолтні дозволи.
// Отримати або створити канал 1-на-1
let channelId = ChannelId(type: .messaging, id: "user1_user2")
let controller = client.channelController(
createChannelWithId: channelId,
members: [userId, targetId],
isCurrentUserMember: true
)
controller.synchronize { error in ... }
synchronize() — ключовий виклик. Він підтягає історію, підписується на realtime-події та синхронізує локальний стан. Без нього канал створюється, але події не приходять.
На Android:
val channelClient = client.channel(channelType = "messaging", channelId = "user1_user2")
channelClient.create(memberIds = listOf(userId, targetId)).enqueue { result -> ... }
SwiftUI UIComponents vs кастомний UI
Stream пропонує ChatChannelView, MessageListView, MessageComposerView з пакету StreamChatSwiftUI. Кастомізація — через ViewFactory:
class CustomViewFactory: DefaultViewFactory {
func makeMessageAvatarView(for userInfo: UserAvatarData) -> some View {
// Ваш кастомний аватар
CustomAvatarView(imageUrl: userInfo.imageURL)
}
}
// Інжектуємо:
Utils.shared.viewFactory = CustomViewFactory()
Чистіше, ніж повний кастомний UI — 80% поведінки (свайп, реакції, треди) достаються бебплатно, кастомізуємо тільки зовнішний вигляд. Повний кастомний UI має смисл тільки якщо дизайн несумісний з моделлю компонентів Stream.
Для Android аналогічно: MessageListView та MessageComposerView у XML або Compose, кастомізація через AttachmentFactoryManager та MessageListViewModelFactory.
Реакції та треди
Stream підтримує реакції нативно через message.reactionScores та addReaction / deleteReaction endpoint. Треди (відповіді на повідомлення) — через controller.createNewReply. У готових компонентах це працює з коробки; при кастомному UI потрібно реалізувати ThreadController.
Push-уведомлення
Stream використовує власного провайдера уведомлень поверх APNs/FCM. Реєстрація:
// iOS — після отримання APNs токена
chatClient.currentUserController().addDevice(.apns(token: deviceToken))
// Android
FirebaseMessaging.getInstance().token.addOnSuccessListener { token ->
client.addDevice(Device(token = token, pushProvider = PushProvider.FIREBASE)).enqueue()
}
Stream самостійно надсилає уведомлення при нових повідомленнях у каналах, де користувач є учасником. У dashboard налаштовуємо шаблони уведомлень. Deeplink — через обробку CKNNotificationInfo (iOS) або RemoteMessage.data (Android).
Офлайн-кеш
iOS SDK використовує CoreData під капотом, Android — Room. Включається автоматично при isLocalStorageEnabled = true у конфігурації (за замовчуванням — true). При відновленні мережі SDK автоматично синхронізує пропущені події через механізм health check WebSocket.
Етапи роботи
Реєстрація Stream-застосунку та налаштування ключів → реалізація token endpoint на бекенді → інтеграція SDK → вибір між компонентами та кастомним UI → push-уведомлення → тестування reconnect/offline-сценаріїв.
Строки
З готовими компонентами StreamChatSwiftUI / StreamChatUI — 3-4 дня. Повністю кастомний UI на Core SDK — 6-8 днів. Вартість розраховується індивідуально.







