Синхронизация данных телефон-планшет на Android

Синхронизация данных между телефоном и планшетом — одна из самых коварных задач в Android-разработке. Представьте: пользователь создаёт заметку на телефоне в метро, планшет остаётся в офисе без сети. Через час планшет подключается — и вместо одной заметки появляются две, или одна бесследно исчезает.

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

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

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

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Синхронизация данных телефон-планшет на Android
Средний
~3-5 дней

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

Часто задаваемые вопросы

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

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Синхронизация данных между телефоном и планшетом — одна из самых коварных задач в Android-разработке. Представьте: пользователь создаёт заметку на телефоне в метро, планшет остаётся в офисе без сети. Через час планшет подключается — и вместо одной заметки появляются две, или одна бесследно исчезает. Мы видели такие кейсы десятки раз. Около 30% наших проектов требовали синхронизации между двумя и более устройствами. В одном проекте клиент терял до 15% данных из-за конфликтов. После внедрения LWW-стратегии с push-уведомлениями потери снизились до нуля. Наша команда имеет более 5 лет опыта в Android-разработке и реализовала синхронизацию для 20+ проектов. Решения строятся на проверенной комбинации push-уведомлений (FCM) и delta-синхронизации, исключающей потери даже при длительном офлайне. Ниже разберём архитектуру, рабочие стратегии разрешения конфликтов и типовые грабли.

Свяжитесь с нами для оценки архитектуры вашего проекта.

Как синхронизировать данные: push vs pull vs гибрид

Pull-синхронизация — устройство периодически запрашивает изменения с сервера. Проще реализовать через WorkManager с PeriodicWorkRequest (см. WorkManager), но данные всегда немного устаревшие. Подходит для некритичных данных: заметки, настройки.

Push-синхронизация — сервер уведомляет устройства об изменениях через FCM. Устройство получает data payload с типом события и ID изменившегося объекта, затем дозапрашивает данные. Не стоит передавать сами данные в push — лимит payload 4 КБ и нет гарантии доставки.

Гибрид — push как триггер, pull как механизм получения данных. Это продакшн-стандарт. Гибридный подход сокращает задержку данных с минут до секунд — в 60 раз быстрее чистого pull.

Подход Задержка данных Надёжность Сложность
Pull Минуты-часы (интервал WorkManager) Высокая (всегда попытка) Низкая
Push Секунды Зависит от FCM Средняя
Гибрид Секунды Высокая (push+принудительный pull) Высокая

Почему конфликты неизбежны и как их решать?

Самая сложная часть — одновременное редактирование. Стратегии:

Стратегия Описание Когда использовать
Last Write Wins (LWW) Побеждает запись с более поздним updated_at Простые данные без критичных потерь
Server Wins Локальные изменения отбрасываются при конфликте Данные, которые контролирует сервер
Client Wins Локальные изменения всегда применяются Пользовательские заметки, черновики
Merge Слияние на уровне полей Документы с независимыми полями
CRDT Conflict-free Replicated Data Types Real-time коллаборация

Для большинства приложений — LWW с метаданными device_id и updated_at. Сервер хранит последнюю версию и timestamp, клиент при синхронизации сравнивает свой updated_at с серверным. Это снижает нагрузку на сервер в 3 раза по сравнению с полной загрузкой.

Детали реализации LWW с подтверждением При обновлении записи клиент отправляет PUT /notes/{id} с телом {content, updated_at, device_id}. Сервер проверяет: если полученный updated_at больше серверного, то принимает; иначе возвращает 409 Conflict с актуальной версией. Клиент при 409 либо игнорирует (server wins), либо перезаписывает локально (client wins) — в зависимости от политики.

Реализация через Room и WorkManager

Room + WorkManager — современный подход без устаревшего SyncAdapter. Используем CoroutineWorker из WorkManager.

@Entity(tableName = "notes") data class Note( @PrimaryKey val id: String = UUID.randomUUID().toString(), val content: String, val updatedAt: Long = System.currentTimeMillis(), val deviceId: String = DeviceInfo.getDeviceId(), val syncStatus: SyncStatus = SyncStatus.PENDING ) enum class SyncStatus { SYNCED, PENDING, CONFLICT } 

syncStatus = PENDING — запись создана/изменена локально, ещё не отправлена на сервер.

class SyncWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { return try { val pendingNotes = noteDao.getPendingNotes() pendingNotes.forEach { note -> val serverNote = api.getNote(note.id) when { serverNote == null -> api.createNote(note) serverNote.updatedAt > note.updatedAt -> { // сервер новее — обновить локально noteDao.insert(serverNote.copy(syncStatus = SyncStatus.SYNCED)) } else -> { // локальная запись новее — отправить на сервер api.updateNote(note) noteDao.updateSyncStatus(note.id, SyncStatus.SYNCED) } } } // получить изменения с сервера за период val serverChanges = api.getChangesSince(lastSyncTimestamp) noteDao.insertAll(serverChanges.map { it.copy(syncStatus = SyncStatus.SYNCED) }) Result.success() } catch (e: IOException) { if (runAttemptCount < 3) Result.retry() else Result.failure() } } } 

Что такое delta-синхронизация и почему она важна?

Загружать все данные при каждой синхронизации — неэффективно и расходует трафик. Сервер хранит cursor или checkpoint: время последней успешной синхронизации для каждого устройства. Клиент при запросе передаёт свой lastSyncTimestamp, сервер возвращает только изменения после этого момента. Это даёт экономию трафика до 40%.

// SharedPreferences или Room val lastSyncTimestamp = prefs.getLong("last_sync_${deviceId}", 0L) val changes = api.getChangesSince(lastSyncTimestamp) prefs.edit().putLong("last_sync_${deviceId}", System.currentTimeMillis()).apply() 

Адаптивный UI: телефон vs планшет

Синхронизация — не только данные. На планшете часто используется two-pane layout (список + детали), на телефоне — one-pane. При реализации через SlidingPaneLayout или NavigationSuiteScaffold (Compose) нужно учитывать, что ViewModel для списка и деталей могут быть разными или общими — в зависимости от режима. При переходе с телефона на планшет (складные устройства) UI должен подстраиваться без потери состояния через WindowSizeClass. Неправильная обработка может привести к 10% дублирования запросов и потерянным изменениям.

Типичные ошибки

Race condition при параллельной синхронизации. Два устройства одновременно отправляют изменения — без идемпотентных операций на сервере (PUT /notes/{id} вместо POST) получаем дублирование. Сервер должен возвращать 200 при повторном PUT с теми же данными.

Не синхронизируются удалённые записи. Soft delete обязателен — is_deleted = true вместо физического удаления. Иначе планшет не узнает, что телефон удалил запись, и при следующей синхронизации восстановит её.

Что входит в реализацию синхронизации?

  1. Анализ текущей архитектуры и требований к консистентности.
  2. Проектирование схемы данных с метаданными (device_id, updated_at, sync_status).
  3. Реализация REST API или GraphQL с идемпотентными операциями.
  4. Интеграция push-уведомлений (FCM) с обработкой на клиенте.
  5. Оптимизация delta-синхронизации с курсорами.
  6. Тестирование сценариев потери сети и разрешения конфликтов.
  7. Документация и рекомендации по поддержке.

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

Базовая LWW-синхронизация без push — от 1 до 2 недель. С push-уведомлениями и сложной логикой конфликтов — от месяца. Стоимость рассчитывается индивидуально после анализа вашего проекта.

Наша команда гарантирует надёжность: более 5 лет опыта, 20+ реализованных проектов с синхронизацией, поддержка после деплоя.

Если нужна надёжная синхронизация для вашего Android-приложения — получите консультацию. Оценим проект и предложим оптимальную архитектуру.