Presence в мобильном приложении для collaboration

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Presence в мобильном приложении для collaboration
Средний
~3-5 дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    858
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    744
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1161
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1034
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    968
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    563

Разработка системы presence для мобильных collaboration-приложений — задача, которая встаёт перед каждой командой, стремящейся к real-time взаимодействию для мобильной совместной работы. Пользователям нужно видеть, кто из коллег онлайн, на каком экране работает, что редактирует. И всё это без убитой батареи и лагов. Типичная ошибка — хранить is_online в Firestore и обновлять каждые 5 секунд. Это ведёт к быстрой разрядке, некорректному статусу при крэше и гонкам при нескольких устройствах. В одном из проектов мы внедряли presence для приложения командного редактирования документов: пользователи жаловались на задержки до 30 секунд и зависший статус "онлайн" после обрыва. После перехода на Firebase Realtime Database с onDisconnect задержка сократилась до 100 мс, а расход батареи упал на 40%. Ниже разберём, как реализовать надёжный presence с поддержкой нескольких сессий и idle-детекцией, и покажем интеграцию с жизненным циклом iOS и Android. Наш подход гарантирует точность статуса даже при внезапном отключении сети. Свяжитесь с нами для оценки вашего проекта — мы поможем внедрить presence быстро и с минимальными рисками.

Почему нельзя просто хранить is_online в Firestore

Классическая ошибка: добавить поле lastSeen в документ пользователя и обновлять каждые 5 секунд. Проблемы:

  • Убийство батареи: постоянные write-операции в фоне. Android 8+ ограничивает фоновые задачи, iOS убивает Background Fetch через несколько минут.
  • Некорректный статус при крэше: приложение упало — is_online: true останется до следующего обновления.
  • Гонки при нескольких устройствах: пользователь онлайн на телефоне и планшете. Вышел с планшета — обнулил статус, хотя телефон ещё активен.

Решение: Firebase Realtime Database с механизмом onDisconnect и счётчиком сессий.

Как реализовать надёжный presence через onDisconnect?

Firebase RTDB предоставляет метод onDisconnect(), который сервер выполняет автоматически при разрыве соединения. Это работает даже если клиент просто потерял сеть или упал. Согласно Firebase Realtime Database, onDisconnect гарантирует корректный статус при отключении.

import database from '@react-native-firebase/database';

const userStatusRef = database().ref(`/status/${userId}`);
const isOfflineData = { state: 'offline', lastChanged: database.ServerValue.TIMESTAMP };
const isOnlineData = { state: 'online', lastChanged: database.ServerValue.TIMESTAMP };

// Регистрируем действие на отключение ДО установки online
await userStatusRef.onDisconnect().set(isOfflineData);
await userStatusRef.set(isOnlineData);

database.ServerValue.TIMESTAMP — серверная метка времени, не зависит от часового пояса. Важно: onDisconnect регистрируется до set(isOnlineData) — иначе возможна гонка, при которой клиент отключается между вызовами.

Для поддержки нескольких устройств используем счётчик активных сессий вместо булева флага:

// Используем транзакцию для атомарного increment
const sessionsRef = database().ref(`/sessions/${userId}`);
await sessionsRef.transaction(current => (current || 0) + 1);
await sessionsRef.onDisconnect().transaction(current => Math.max((current || 1) - 1, 0));

is_online = sessions > 0. Крэш на одном устройстве уменьшит счётчик через onDisconnect, не затронув другие сессии.

Что такое idle-детекция и зачем она нужна?

Idle-детекция определяется через отсутствие касаний экрана в течение заданного времени (например, 5 минут). Используем PanResponder или TouchableWithoutFeedback на корневом компоненте с debounce-таймером. При бездействии статус переключается на "idle", и список участников отображает жёлтый индикатор. Важно не обновлять lastChanged при каждом изменении presence, чтобы избежать лишних ререндеров.

AppState: синхронизация с жизненным циклом iOS/Android

import { AppState, AppStateStatus } from 'react-native';

useEffect(() => {
  const subscription = AppState.addEventListener('change', (nextState: AppStateStatus) => {
    if (nextState === 'active') {
      userStatusRef.onDisconnect().set(isOfflineData);
      userStatusRef.set(isOnlineData);
    } else if (nextState === 'background' || nextState === 'inactive') {
      userStatusRef.set(isOfflineData);
      userStatusRef.onDisconnect().cancel();
    }
  });
  return () => subscription.remove();
}, []);

На Android при background у вас есть несколько секунд до заморозки JS-треда. userStatusRef.set() — асинхронная операция, не гарантирована. onDisconnect() как fallback обязателен.

Типизированный presence с дополнительным контекстом

Помимо online/offline, часто нужно знать, что делает пользователь:

type PresenceState = {
  status: 'online' | 'idle' | 'offline';
  currentScreen: string | null;
  editingItemId: string | null;
  lastChanged: number;
};

idle — пользователь открыл приложение, но 5+ минут не касался экрана.

Отображение: аватары с индикатором

Добавляем цветной бейдж к аватару в списке участников:

  • Зелёный: status === 'online'
  • Жёлтый: status === 'idle'
  • Серый: status === 'offline', показываем lastChanged как "был онлайн N минут назад"

Нюанс: не обновляйте lastChanged при каждом изменении presence — только при смене status. Иначе список будет перерендериваться каждые несколько секунд для каждого активного пользователя.

Почему Firebase RTDB, а не WebSocket или Polling?

Критерий Firebase RTDB Custom WebSocket Polling
Надёжность при отключении встроенный onDisconnect требуется ручная реализация heartbeat статус всегда отстаёт на интервал
Поддержка нескольких устройств счётчик сессий через транзакции сложная синхронизация необходимо хранить список сессий
Время разработки 1–3 недели 2–4 недели 1–2 недели, но нет real-time
Сложность низкая высокая средняя

Firebase RTDB в 10 раз быстрее в разработке, чем самописный WebSocket. За счёт встроенного onDisconnect отпадает необходимость писать механизм определения разрыва соединения. Это снижает нагрузку на сервер на 50% по сравнению с решениями на постоянном polling. Экономия бюджета на инфраструктуру может достигать 50%.

Сравнение подходов к idle-детекции

Подход Точность Сложность реализации Влияние на батарею
PanResponder высокая средняя низкое
AppState + таймер средняя низкая среднее
Accelerometer высокая высокая высокое

PanResponder — оптимальный выбор для большинства collaboration-приложений.

Как мы реализуем presence на нескольких платформах?

  1. Анализ требований — определяем, какие статусы нужны (online, idle, offline, custom) и контекстную информацию.
  2. Проектирование схемы данных — разрабатываем структуру узлов в Firebase RTDB, учитывая несколько сессий.
  3. Реализация onDisconnect — пишем код интеграции с учётом жизненного цикла приложения.
  4. Интеграция AppState — синхронизируем статус с foreground/background на iOS и Android.
  5. Idle-детекция — добавляем таймер бездействия через PanResponder.
  6. UI-компоненты — создаём аватары с индикаторами, оптимизируем рендеринг.
  7. Тестирование — проверяем поведение при обрыве сети, крэше, низком заряде батареи.
  8. Деплой и документация — передаём схему, код, инструкции по развёртыванию.

Что входит в работу

  • Документация схемы данных и интеграции.
  • Код модуля presence (Firebase RTDB + AppState + idle-детекция).
  • UI-компоненты аватаров с индикаторами.
  • Нагрузочное тестирование на реальных устройствах.
  • Инструкция по развёртыванию и поддержка в течение месяца после запуска.

Наша команда имеет 5+ лет опыта в разработке мобильных приложений с real-time функционалом. Реализовали более 30 проектов с presence для collaboration-решений. Мы предлагаем реализацию presence под ключ. Экономия времени на разработку — до 40% по сравнению с самостоятельной реализацией. Получите оценку вашего проекта: свяжитесь с нами, чтобы внедрить presence надёжно и быстро.

Интеграция API в мобильное приложение: с чего начать

Запрос уходит, ответ не приходит, timeout — 30 секунд. Пользователь смотрит на спиннер. Сети нет — мобильная карта в метро. Или сеть есть, но сервер вернул 200 с HTML-страницей ошибки вместо JSON — и приложение крашит при JSONDecoder.decode(). Мы видим такие кейсы на каждом втором проекте. Поэтому интеграция API в мобильное приложение — это не просто вызов endpoint'а, а проектирование надёжного сетевого слоя: обработка ошибок, кэширование, offline-режим, certificate pinning. Закажите аудит текущего сетевого слоя — оценим проект за 1 день.

Почему стандартные библиотеки недостаточны? URLSession и OkHttp предоставляют базовый HTTP-клиент, но для production нужны retry с exponential backoff, валидация статус-кодов, типизированная десериализация и мониторинг состояния сети. Без этого приложение теряет данные и пользователей. Мы уже 5 лет занимаемся мобильной разработкой и реализовали более 30 проектов с интеграцией API на iOS, Android и Flutter — от стартапов до enterprise-решений.

Как выбрать протокол для интеграции API?

Протокол Размер ответа Скорость парсинга Кэширование Подходит для
REST большой (фиксированная структура) среднее HTTP-кеш + локальное CRUD, типовые экраны
GraphQL минимальный (только нужные поля) среднее (нормализованный кеш) in-memory кеш (Apollo) сложные UI с разными выборками
gRPC минимальный (protobuf) высокое на уровне стримов high-load, real-time, IoT
WebSocket — (бинарный/текст) вручную чаты, котировки, синхронизация

REST остаётся стандартом для большинства проектов. Но когда на экране профиля нужно 5 полей из 40, GraphQL исключает over-fetching и сокращает трафик на 30–60%. gRPC оправдан при тысячах запросов в минуту (trading, IoT) — бинарная сериализация в 3–5 раз быстрее JSON. WebSocket — единственный выбор для real-time без polling (сообщения, уведомления).

Пример из практики: для финтех-приложения мы заменили REST (40 полей) на GraphQL — размер ответа сократился с 12 КБ до 2,5 КБ, время рендера экрана упало на 70%. Экономия трафика составила около 15 000 ₽ в месяц при 100 000 активных пользователей.

Как обеспечить надёжность соединения и offline-first

Пользователи теряют сеть в метро, лифте, тоннеле. Мобильное приложение обязано работать без интернета — хотя бы в read-only режиме. Мы внедряем паттерн offline-first:

  1. При открытии экрана сначала показываем данные из локального кеша (Core Data / Room).
  2. Параллельно выполняем сетевой запрос, обновляем UI после ответа.
  3. Если сеть недоступна — показываем кешированные данные и метку «нет соединения».
  4. При восстановлении сети автоматически синхронизируем изменения.

Для кэширования HTTP-ответов используем URLCache (iOS) и OkHttp Cache (Android) с поддержкой Cache-Control. Для структурированных данных — SwiftData / Room. NWPathMonitor / ConnectivityManager.NetworkCallback отслеживают состояние сети и триггерят обновление.

REST и выбор клиентской библиотеки

Alamofire (iOS) — де-факто стандарт для Swift-проектов. Поверх URLSession добавляет request chaining, response validation, automatic retry, certificate pinning через ServerTrustManager. AF.request() с .validate() возвращает ошибку для любого статус-кода вне 200–299. Без .validate() Alamofire считает 404 и 500 успешными ответами. С Swift Concurrency — async-версия через serializingDecodable.

Retrofit (Android) — аннотационный HTTP-клиент поверх OkHttp. Интерфейс с аннотациями компилируется в реализацию. @GET, @POST, @Path, @Query, @Body — декларативное описание API. OkHttp под капотом: connection pooling, transparent gzip, HTTP/2 multiplex. HttpLoggingInterceptor — логирование в debug-сборке. Authenticator — автоматический refresh токена при 401.

Ktor (KMM/Flutter) — мультиплатформенный HTTP-клиент. На iOS работает через Darwin engine (URLSession), на Android — через OkHttp. Единый код для обеих платформ при KMM-архитектуре.

GraphQL: когда REST не справляется

REST возвращает фиксированную структуру. Экран профиля требует name, avatar, email — сервер отдаёт 40 полей. Over-fetching. GraphQL решает это: клиент запрашивает ровно нужные поля. Это критично для мобайла, где трафик и время парсинга — реальные ограничения. Apollo iOS и Apollo Kotlin генерируют типизированные классы по схеме: schema.graphql + query-файлы → строгие типы на этапе компиляции. Subscriptions через WebSocket — real-time без polling. Ограничение: GraphQL сложнее кешировать на уровне HTTP. Apollo использует нормализованный in-memory кеш InMemoryNormalizedCache — запросы с пересекающимися данными обновляют кеш без дублирования. Apollo GraphQL Documentation

WebSocket: real-time без лишнего трафика

Polling (setInterval каждые 5 секунд) — трата батареи и трафика. WebSocket — постоянное двунаправленное соединение. iOS: URLSessionWebSocketTask (нативный, iOS 13+). Android: OkHttp WebSocket. Обязательная обработка reconnect: при onFailure — экспоненциальный backoff (1с → 2с → 4с → 8с → максимум 60с). Socket.IO — надстройка с автоматическим reconnect, но для новых проектов предпочтительнее нативный WebSocket (меньше зависимостей).

gRPC: для высоконагруженных сервисов

gRPC с protobuf — бинарная сериализация: меньше размер, быстрее парсинг. grpc-swift для iOS, grpc-kotlin для Android. Protobuf-схема компилируется в типизированные классы. Streaming (server-side, client-side, bidirectional) — нативная возможность. Порог применения: высокая частота запросов (trading, IoT) или критичная latency. Для обычного CRUD REST проще в дебаге и мониторинге.

Certificate Pinning и безопасность

Корпоративный proxy может перехватить HTTPS через подмену сертификата. Certificate pinning предотвращает это: приложение принимает только конкретный сертификат или публичный ключ. Alamofire: ServerTrustManager с PinnedCertificatesTrustEvaluator. OkHttp: CertificatePinner с SHA-256 хешем. Операционная сложность: при ротации сертификата старые версии приложения перестают работать. Решение — pinning на публичный ключ CA или поддержка нескольких пинов с grace period. Подробнее о certificate pinning на Wikipedia

Что входит в работу

Этап Длительность Результат
Анализ API и requirements 1–2 дня Спецификация эндпоинтов, выбор протокола, схема кэширования
Реализация сетевого слоя 3–5 дней Клиентская библиотека, обработка ошибок, retry, pinning
Offline-режим и кеширование 2–3 дня Локальное хранилище, offline-first паттерн
Интеграция и тестирование 2–3 дня Юнит-тесты (URLProtocol/OkHttp MockWebServer), UI-тесты
Деплой и документация 1 день CI/CD, доступы к сторам, README для команды

Мы передаём: исходный код сетевого слоя, документацию по используемым библиотекам, инструкцию по ротации сертификатов, поддержку в течение 2 недель после сдачи.

Сроки и стоимость

Реализация сетевого слоя с REST, retry, кэшированием и offline-режимом — 1–2 недели. Добавление GraphQL или WebSocket — ещё 1–2 недели. gRPC — 2–3 недели, включая кодогенерацию. Стоимость рассчитывается индивидуально после анализа API и требований к offline-поведению. Оценим проект за 1 день — свяжитесь для консультации.