Інтеграція SDK чату Stream Chat у мобільний додаток
Real-time чат без лагів — часта головна біль мобільних команд. Помилки в конфігурації WebSocket, нестабільний reconnect, витік токенів — типові проблеми, які ми бачимо на аудитах. Stream Chat SDK вирішує їх, але потребує правильного налаштування. У нас за плечима 5 років досвіду та 20+ проєктів з чатами, 8 з них на Stream Chat. Гарантуємо стабільність навіть при слабкому з'єднанні. Розберемо інтеграцію з нуля, без «Hello World» з документації.
Stream Chat vs SendBird: чому обирають Stream?
Stream Chat відрізняється від SendBird архітектурно: API побудований на подієвій моделі (WebSocket + event-driven state), SDK надає готові SwiftUI/Compose-компоненти з глибокою кастомізацією через subclassing та view factories. Розмір бінарника менший: iOS близько 8 МБ, Android AAR ~6 МБ. Ми не раз стикалися, що SendBird дає більше свободи, але Stream Chat швидше в інтеграції — до 40% економії часу на первинний запуск.
| Критерій | Stream Chat | SendBird |
|---|---|---|
| Розмір SDK (iOS) | ~8 MB | ~12 MB |
| Модель API | event-driven (WebSocket) | REST + WebSocket |
| Готові UI-компоненти | SwiftUI, Compose, UIKit | UIKit, SwiftUI (не всі) |
| Офлайн-кеш | CoreData / Room (вбудований) | Потребує ручного налаштування |
| Ціна (базовий тариф) | $0.1/міс. за MAU | $0.2/міс. за MAU |
Чому Stream Chat економить до 40% часу розробки?
Готові UI-компоненти покривають 80% поведінки. Решта 20% — кастомізація через ViewFactory. Це швидше, ніж писати свій чат з нуля на UIKit/Compose. Повний кастомний UI має сенс тільки при несумісних дизайн-системах.
Ініціалізація та управління токенами
Stream працює на JWT. Клієнт ніколи не генерує токен самостійно — тільки ваш бекенд через Stream Chat SDK. На бекенді токен створюється за допомогою 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 interface) — там робіть запит до свого API та повертайте новий токен. Без цього користувач вилетить з чату через TTL токена.
Як створити канали та підписатися на події?
Stream використовує комбінацію type:id для ідентифікації каналу. Типи — messaging, livestream, team, commerce, gaming — впливають на дефолтні permissions.
// iOS: отримати або створити канал 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-події та синхронізує локальний state. Без нього канал створюється, але події не приходять. На Android аналогічно через client.channel(channelType, channelId).create(memberIds).
Як налаштувати 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).
Кастомізація 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.
Офлайн-кеш та відновлення з'єднання
iOS SDK використовує CoreData під капотом, Android — Room. Вмикається автоматично при isLocalStorageEnabled = true в конфігурації (за замовчуванням — true). При відновленні мережі SDK автоматично синхронізує пропущені події через механізм health check WebSocket.
Що входить в реалізацію?
Ми документуємо кожен крок і залишаємо вам працюючий код. Нижче — етапи та терміни.
| Етап | Тривалість |
|---|---|
| Реєстрація додатку Stream та налаштування ключів | 1 день |
| Реалізація token endpoint на бекенді | 1 день |
| Інтеграція SDK (iOS/Android/Flutter) | 1–2 дні |
| Вибір між компонентами та кастомним UI | 0.5 дня |
| Налаштування push-сповіщень та deep linking | 1 день |
| Тестування reconnect/offline-сценаріїв | 1 день |
| Передача документації та коду | 0.5 дня |
Етапи та терміни
З готовими компонентами StreamChatSwiftUI / StreamChatUI — 3–4 дні. Повністю кастомний UI на Core SDK — 6–8 днів. Вартість розраховується індивідуально. Зв'яжіться з нами для аудиту поточної реалізації або замовте інтеграцію під ключ — ми гарантуємо стабільність та підтримку після здачі.
Приклади реалізації ViewFactory для iOS
Ви можете кастомізувати не тільки аватар, але й колір повідомлень, шрифти та розташування елементів. Повний список методів ViewFactory описаний в документації Stream.







