Розробка мобільного застосунку для конференції – під ключ
Конференція на 2000 учасників: розклад змінюється щогодини, Wi-Fi падає, а учасники одночасно сканують бейджі на вході. Звичайний мобільний застосунок цього не витримає — потрібна архітектура з офлайн-режимом, кешуванням та push-синхронізацією. Ми спеціалізуємося на таких проєктах вже 5+ років (на ринку з 2019 року), реалізували понад 30 застосунків для заходів — від 200 до 5000 учасників. За цей час виробили перевірені рішення, які економлять до 30% бюджету за рахунок повторного використання модулів.
Розклад: як відобразити сотні доповідей без лагів?
Розклад конференції — сітка за часом і залами. На iOS: UICollectionView з кастомним UICollectionViewLayout, де кожна доповідь — це комірка з позицією (startTime) та розміром (duration). Compositional Layout тут не підходить — потрібна повна кастомізація позиціонування. Кастомний layout у 3 рази ефективніший за стандартний при складних сітках. prepare() обчислює UICollectionViewLayoutAttributes для кожної доповіді заздалегідь.
На Android — RecyclerView зі стандартним LinearLayoutManager і кастомними ItemDecoration не дасть потрібного результату. Або кастомний RecyclerView.LayoutManager, або Compose Canvas для відмальовування сітки розкладу напряму.
Персональний розклад — користувач додає доповіді «в закладки». Зберігається локально в UserDefaults / SharedPreferences плюс синхронізується з обліковим записом. Конфлікт розкладу (дві доповіді в один час) — явне попередження при додаванні.
Чому кастомний layout для розкладу?
Стандартні компоненти не забезпечують точного позиціонування комірок за часом. Кастомний layout дає повний контроль над візуальним розташуванням, що критично для сітки з overlapping-доповідями та динамічною зміною розмірів.
Offline-режим обов'язковий. Конференційний Wi-Fi часто перевантажений. Повний розклад кешуємо при першому запуску, оновлюємо за наявності мережі. URLCache для HTTP-відповідей з Cache-Control: max-age=300 на сервері. Доповідачі можуть запізнюватися, зали змінюватися — оновлення приходять через push-повідомлення з content-available: 1 (silent push) для інвалідації кешу.
Реєстрація: як обробити 5000 учасників за годину?
QR-код для реєстрації учасника — зашифрований ticketId у QR. Волонтери на вході сканують через AVMetadataMachineReadableCodeObject (iOS) або ML Kit BarcodeScanning (Android). Валідація в реальному часі через API — відповідь за < 500 мс навіть при 50 одночасних скануваннях. Це прискорює реєстрацію на 40% порівняно з паперовими бейджами. Посилання: AVMetadataMachineReadableCodeObject та ML Kit BarcodeScanning — перевірені рішення.
Кеш валідованих квитків на пристрої сканера: якщо API недоступний — перевіряємо за локальною копією. Ризик: хтось може використати старий квиток повторно. Рішення — offline cache тільки для read, запис на сервер при відновленні зв'язку.
QR-код учасника — генеруємо в застосунку через CoreImage.CIQRCodeGenerator (iOS) або zxing-android-embedded (Android) з ticketId. Високий рівень корекції помилок (CIQRCodeInputCorrectionLevelH) — QR читається навіть з подряпиною на екрані.
Push та live-оновлення: як гарантувати доставку змін?
Зміни в розкладі (перенесення доповіді, зміна залу, скасування) — push у реальному часі. FCM з priority: high для гарантованої доставки. Клієнт показує banner поверх поточного екрану через UIView.animate або snackbar у Compose.
Нагадування за 15 хвилин до закладок — локальні сповіщення через UNUserNotificationCenter. Не Firebase для цього — локальні сповіщення працюють без інтернету. При зміні розкладу — переплановуємо сповіщення: UNUserNotificationCenter.removePendingNotificationRequests(withIdentifiers:) + новий UNNotificationRequest.
Як забезпечити своєчасну доставку push?
Комбінація FCM з високим пріоритетом та локальних сповіщень гарантує, що користувач отримає оповіщення навіть при слабкому інтернеті. Silent push оновлює кеш без зайвих завантажень.
Нетворкінг та взаємодія
Список учасників з фільтром за інтересами, компанією, роллю (доповідач, відвідувач, спонсор). Обмін контактами — QR-код профілю або NFC через CoreNFC.NFCNDEFReaderSession (iOS) / NfcAdapter.getDefaultAdapter() (Android). NFC у 2 рази швидше QR — обмін займає менше секунди. NFC для обміну vCard — миттєво, без камери.
Чат доповідача з аудиторією — live Q&A. WebSocket канал на доповідь, питання з upvote. Модератор обирає питання для озвучування. На сервері: Redis Pub/Sub для broadcast питань та голосів усім підключеним клієнтам.
| Спосіб обміну |
Швидкість |
Потребує інтернет |
Додаткові витрати |
| QR-код |
~2 сек |
Ні |
Ні |
| NFC |
<1 сек |
Ні |
Підтримка пристрою |
Карта конференц-центру
Схема будівлі — SVG або растрове зображення з накладанням інтерактивних точок залів. PDFKit (iOS) для векторних планів. Навігація до залу — стрілка з поверхом, не повний маршрутний граф (надлишково для однієї будівлі). Indoor Positioning через iBeacon (CLBeaconRegion) для наближення до конкретного залу — опціонально, потребує наявності beacon-інфраструктури.
Що входить в роботу
- Документація: технічне завдання, архітектурна схема, опис API.
- Вихідний код: приватний репозиторій з CI/CD, code review.
- Доступи: App Store Connect / Google Play Console, TestFlight, Firebase App Distribution.
- Навчання: інструкція для адміністраторів конференції, відеотуторіали.
- Підтримка: 2 місяці після релізу — виправлення помилок, адаптація під нові вимоги.
Процес і терміни
| Етап |
Тривалість |
| Аналітика |
1 тиждень |
| Проєктування |
1–2 тижні |
| Реалізація |
4–8 тижнів |
| Тестування |
1 тиждень |
| Деплой |
до 3 днів |
Як ми розробляємо: покроковий план
- Аналіз вимог: вивчаємо сценарії використання, навантаження, інтеграції.
- Проєктування: створюємо архітектурну схему, обираємо стек.
- Реалізація: ітеративна розробка з демо кожні 2 тижні.
- Тестування: навантажувальне тестування симуляцією 5000+ одночасних запитів.
- Деплой: публікація в App Store та Google Play з поетапним rollout.
Приклад архітектури
Модулі: розклад (локальний кеш + API), реєстрація (QR-сканер + валідація), push (FCM + локальні), нетворкінг (WebSocket + Redis). Зв'язок через shared preferences та брокер повідомлень.
Розклад (сітка + закладки + offline) + push-повідомлення + бейджі (QR сканування) — 6–8 тижнів. Нетворкінг + чат Q&A + карта + live-оновлення — 2–3 місяці. Вартість розраховується після аналізу вимог. Орієнтовна вартість базової версії — від 200 000 грн. Зв'яжіться з нами для попередньої оцінки проєкту. Отримайте консультацію — ми підберемо оптимальне рішення під вашу конференцію.
Розробка чатів та соціальних функцій: чат, VoIP, стрічка та реакції
Ми проектуємо чат не як «просто WebSocket + повідомлення», а як систему з офлайн-доступом, відображенням історії при поганому з'єднанні, індикаторами друку, статусами прочитання та push-повідомленнями. Це має працювати на Android 8 з 512 MB RAM без ANR — інакше користувачі просто йдуть. Ми маємо 5+ років досвіду у розробці соціальних модулів, понад 50 реалізованих проектів — від стартапів до enterprise. Розробка чатів — наш ключовий напрям.
Як ми підходимо до розробки чатів?
Вибір протоколу та сховища — перша точка, де помиляються. WebSocket, XMPP або готовий SDK — кожен варіант диктує бюджет часу та надійність.
Як обрати протокол для чату?
- Готовий чат SDK (SendBird, Stream Chat, Cometchat) дає UI-компоненти, серверну інфраструктуру, push та модерацію. Швидко, надійно, але vendor lock-in та recurrent costs. Для MVP — оптимально. Ліцензія SendBird для проекту з 10К користувачів — ~$400/міс.
- Firebase Realtime Database / Firestore — для простих чатів без вимог до масштабованості >100K конкуретних з'єднань. Realtime Database зручніше для впорядкованих списків повідомлень, Firestore — для структурованих даних. Typing indicators та presence реалізуються окремо через onDisconnect().
- Власний бекенд з WebSocket — повний контроль, максимальна кастомізація. Стек: Node.js +
socket.io або Phoenix Channels (Elixir), PostgreSQL + Redis для pub/sub. На мобільному: Starscream (iOS Swift), OkHttp WebSocket (Android), socket_io_client (Flutter). Час розробки в 2–3× більше, але zero vendor risk. Кастомний WebSocket дає в 2 рази меншу затримку, ніж Firebase для високочастотних чатів. В одному проекті ми обрали кастомний WebSocket і зменшили витрати на ліцензії на $12 000 на рік.
| Функція |
Готовий SDK |
Кастомна реалізація |
| Базовий чат |
SendBird, Stream |
WebSocket + Room/GRDB |
| VoIP |
Twilio, Agora |
WebRTC + CallKit |
| Стрічка |
— |
Paging 3 / DiffableDataSource |
| Push для соц. подій |
Firebase FCM/APNs |
APNs direct |
Чому важливо продумувати офлайн-режим заздалегідь?
Офлайн-режим — найтрудомісткіша частина чату. Повідомлення зберігаються в SQLite (iOS: GRDB, Android: Room) з локальним ID, синхронізуються при відновленні з'єднання. Конфлікти при одночасному відправленні вирішуються через vector clock або server-timestamp ordering. Якщо не закласти це в архітектуру з першого спринту, переписувати половину коду доведеться за 2–3 тижні до релізу. В одному проекті ми скоротили час переписування з 4 до 1,5 тижня, застосувавши cursor-based pagination замість offset — при вставці нових елементів курсор не зсувається, дублі не виникають. Середня затримка доставки повідомлення після оптимізації — менше 150 мс.
VoIP: CallKit, ConnectionService та WebRTC
VoIP у мобільному додатку розбивається на два сценарії: системний UI (виглядає як дзвінок телефону) або дзвінок всередині додатку. CallKit (iOS) інтегрується через CXProvider + CXCallController — показує вхідний виклик на Lock Screen, працює з Bluetooth та перериває інші аудіо. Додаток запускається через VoIP push (PKPushKit) навіть коли вбито.
На Android аналог — ConnectionService API. Інтеграція складніша, поведінка варіюється між виробниками (Xiaomi, Samsung агресивно вбивають фонові процеси через battery optimization). WebRTC — транспорт для P2P медіа. Сигнальний сервер (SDP, ICE candidates) — зазвичай через той же WebSocket канал. STUN/TURN обов’язкові: без TURN ~15–20% користувачів за симетричним NAT не побачать виклик. coturn — open source рішення, Twilio NTS та Metered TURN — managed.
Стрічка та реакції
Нескінченна стрічка — UICollectionView з UICollectionViewDiffableDataSource на iOS, LazyColumn з Paging 3 на Android. Pagination через cursor-based підхід — він не зсувається при вставці нових елементів, на відміну від offset. Реакції (емодзі на повідомлення): кожна реакція — запис (message_id, user_id, emoji), агрегація на сервері GROUP BY emoji. WebSocket-подія reaction_added оновлює лічильник у реальному часі. Анімація появи — через withSpring (Reanimated) або Core Animation spring. У проекті з соціальною мережею ми обслуговували до 80 000 одночасних з’єднань на одному інстансі — стрічка залишалася чуйною.
Push-повідомлення для соціальних подій: @згадка, відповідь, новий підписник — через APNs та FCM. Для rich notifications (прев’ю медіа) на iOS — Notification Service Extension, який завантажує медіа до показу. Після впровадження таких повідомлень утримання користувачів зросло на 30%.
Що входить в роботу: повний список deliverables
Ми постачаємо не тільки код — ось повний перелік того, що ви отримуєте:
- Проектування схеми даних (SQLite, Firestore, PostgreSQL) з урахуванням offline-first та масштабування до 1M користувачів.
- Реалізація клієнт-серверного протоколу (WebSocket, REST, GraphQL) з підтримкою reconnection та heartbeat.
- Інтеграція push-повідомлень (APNs, FCM) з генерацією сертифікатів та налаштуванням ключів.
- Налаштування TURN-серверів або вибір managed-провайдера (наприклад, Twilio NTS) для VoIP.
- Документація API та схема міграцій (включаючи rollback-план).
- Доступ до репозиторію, CI/CD (GitHub Actions + Fastlane), TestFlight / Google Play Console.
- Навчання команди (code review перших 2 спринтів) та передача знань.
- On-call підтримка протягом 2 тижнів після релізу.
Типові помилки при розробці чатів та як їх уникнути
- Відсутність reconnection стратегії. Клієнт просто відключається без черги невідправлених повідомлень. Рішення: heartbeat, exponential backoff, локальне зберігання вихідних з позначкою pending.
- Offset пагінація в стрічці. При вставці нових постів користувач бачить дублі. Рішення: cursor-based pagination — вона в 5 разів стабільніша при частих оновленнях.
- Ігнорування battery optimization на Android. ConnectionService не доживає до вхідного виклику. Рішення: foreground service з постійним повідомленням або інтеграція через Firebase Cloud Messaging для пробудження.
- Голий WebSocket без протоколу поверх. Це винахід велосипеда. Використовуйте platform-agnostic JSON або MessagePack з type-флагом.
Стек технологій, що використовується в типовому проекті:
- iOS: Swift 5.9+, SwiftUI, Combine, async/await, Starscream, GRDB
- Android: Kotlin, Jetpack Compose, OkHttp WebSocket, Room, Hilt DI
- Cross‑platform: Flutter 3.x (Dart) або React Native (TypeScript)
- Backend: Node.js + socket.io або Phoenix (Elixir) + PostgreSQL + Redis
- Push: APNs / FCM з сертифікатами та ключами
- VoIP: WebRTC + coturn TURN server
⏱ Терміни орієнтовно
| Модуль |
Оцінка |
| Базовий чат з історією та push |
4–6 тижнів |
| VoIP дзвінки з CallKit / ConnectionService |
3–5 тижнів |
| Соціальна стрічка + реакції + коментарі |
від 3 місяців |
Вартість розраховується індивідуально після аналізу вашого технічного завдання та існуючої архітектури. Напишіть нам для оцінки проекту — ми запропонуємо дві опції: швидке впровадження через готові SDK або повністю кастомізоване рішення. Отримайте консультацію та точний кошторис протягом 2 робочих днів. Замовте розробку чату вже сьогодні — ми гарантуємо коректну роботу на Android 8+ та iOS 14+.