Почему silent push не доходит: кейсы из практики
Silent push — мощный инструмент фоновой синхронизации, но реализация полна подводных камней. По статистике, неправильная настройка silent push приводит к 40% недополученных уведомлений на Android и до 60% на iOS в сложных сценариях. Один из наших клиентов, сервис доставки на 500 000 пользователей, столкнулся с тем, что после обновления на Android 13 фоновые уведомления перестали пробуждать приложение — Doze Mode с новыми ограничениями блокировал high-priority сообщения из-за отсутствия вызова setForegroundAsync в expedited worker. Мы перенастроили обработку и добавили вызов — проблема решилась. В этой статье разберём, как гарантированно настроить фоновую синхронизацию без участия пользователя, и покажем, как избежать типовых ошибок. Наш опыт — 10+ лет в мобильной разработке, 50+ проектов с push-инфраструктурой.
Silent Push на iOS: технические нюансы
На iOS silent push требует флага content-available: 1 в payload и включённой Background Mode «Remote notifications» в Xcode Capabilities.
Payload APNs:
{
"aps": {
"content-available": 1
},
"sync_type": "messages",
"last_known_id": "msg_8823"
}
Без alert, без sound — чистый фоновый вызов. Обработка в AppDelegate:
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
guard let syncType = userInfo["sync_type"] as? String else {
completionHandler(.noData)
return
}
Task {
do {
let hasNewData = try await SyncManager.shared.sync(type: syncType)
completionHandler(hasNewData ? .newData : .noData)
} catch {
completionHandler(.failed)
}
}
}
Критический момент: iOS даёт около 30 секунд на выполнение. Если completionHandler не вызван — принудительное завершение. Также iOS не гарантирует доставку при низком заряде батареи (Low Power Mode) и после принудительного закрытия приложения. Force quit полностью блокирует silent push до ручного запуска — это документированное поведение iOS, обойти нельзя. Подробнее в официальной документации Apple.
Silent Push на Android: FCM Data Message и WorkManager
На Android роль silent push выполняет FCM Data Message — он попадает в FirebaseMessagingService.onMessageReceived независимо от состояния приложения (если не убит системой Doze).
class AppFirebaseMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
val syncType = message.data["sync_type"] ?: return
val workRequest = OneTimeWorkRequestBuilder<SyncWorker>()
.setInputData(workDataOf("sync_type" to syncType))
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build()
WorkManager.getInstance(applicationContext).enqueue(workRequest)
}
}
setExpedited() запрашивает немедленное выполнение. На Android 12+ внутри expedited worker нужно вызвать setForegroundAsync(), иначе при долгой операции возможен ANR.
Doze Mode ограничивает фоновую активность. FCM high-priority сообщения обходят Doze, если в payload указать android.priority: "HIGH":
{
"message": {
"token": "device_fcm_token",
"android": {
"priority": "HIGH"
},
"data": {
"sync_type": "messages",
"payload": "{...}"
}
}
}
Дополнительно о Doze Mode
Doze Mode активируется, когда устройство неактивно и не подключено к зарядке. High-priority сообщения обходят его, но при очень частых запросах система может начать игнорировать их — соблюдайте интервалы не менее 10 минут между silent push.
Как обновить badge без уведомления пользователя?
Популярный кейс — обновить цифру на иконке без показа уведомления. На iOS через silent push:
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
if let badge = userInfo["badge"] as? Int {
UNUserNotificationCenter.current().setBadgeCount(badge) { _ in }
}
completionHandler(.newData)
}
На Android единого API нет — используйте библиотеку ShortcutBadger или NotificationManagerCompat.setNumber(), но поддержка зависит от лончера (Samsung, Xiaomi, Huawei).
Ограничения и квоты
iOS 13+ ввёл BGTaskScheduler и background processing quota. Если приложение слишком часто запрашивает фоновое выполнение без пользы для пользователя, система начинает throttle-ить вызовы. Вызов completionHandler(.noData) при отсутствии новых данных критичен для корректной работы системы квот. На Android аналогичный механизм — WorkManager сжимает частые задачи. Соблюдайте интервалы и используйте экспоненциальную задержку при ошибках.
Сравнение платформ
| Характеристика |
iOS |
Android |
| Механизм |
Silent Push (content-available) |
FCM Data Message |
| Фоновое выполнение |
Background Modes + 30с лимит |
WorkManager + expedited |
| Force quit |
Не доставляется |
Доставляется (если не убит системой) |
| Doze Mode |
Throttling по квоте |
High priority обходит Doze |
| Badge обновление |
UNUserNotificationCenter.setBadgeCount |
ShortcutBadger / лончер-специфично |
Типичные ошибки и решения
| Ошибка |
Решение |
| Silent push не доставляется на iOS после force quit |
Объясните пользователю, что приложение нужно запускать вручную |
| FCM Data Message не пробуждает на Android 12+ |
Добавьте setForegroundAsync() в expedited worker |
| Badge не обновляется на Android Xiaomi |
Используйте ShortcutBadger с явной поддержкой Xiaomi |
| Превышение квоты фонового выполнения на iOS |
Уменьшите частоту silent push до 1 раза в 5-10 минут |
Что входит в настройку silent push под ключ
При заказе нашей услуги вы получаете:
- Проектирование архитектуры push-инфраструктуры (APNs + FCM)
- Реализацию обработчиков на iOS и Android с учётом граничных случаев
- Конфигурацию Background Modes, WorkManager, high-priority топиков
- Интеграцию обновления badge counter на обеих платформах
- Документацию и обучение вашей команды
- Поддержку после запуска (1 месяц)
Почему стоит доверить настройку нам?
Мы специализируемся на мобильной разработке с 10+ летним опытом. За это время реализовали более 50 проектов с push-инфраструктурой, включая высоконагруженные приложения с миллионами пользователей. Наши решения проходят App Store Review и Google Play Console без замечаний. Используем актуальные версии Swift, Kotlin, Flutter — стек подбирается под ваш проект.
Сроки и стоимость
Настройка silent push для одной платформы (iOS или Android) занимает 3–5 рабочих дней. Комплексное решение под обе платформы — от 5 до 9 дней. Стоимость рассчитывается индивидуально в зависимости от сложности интеграции и необходимого стека. Оценим ваш проект бесплатно — просто свяжитесь с нами.
Получите консультацию — пишите на почту или через форму на сайте. Поможем настроить silent push так, чтобы данные обновлялись даже в самых жёстких условиях.
Push-уведомления в мобильном приложении: APNs, FCM, сегментация, rich push
Мы внедрили push-уведомления в мобильном приложении для 50+ проектов — от стартапов до enterprise с аудиторией 10M+ пользователей. Нерелевантное или технически сломанное уведомление хуже его отсутствия: пользователь отключает push или удаляет приложение. Согласно отчёту Localytics, отказ от push-разрешений на iOS достигает 40% в первую неделю — причина почти всегда в нерелевантности, а не в механике. Уже через 2 недели после внедрения качественной сегментации конверсия открытия вырастает на 25–30%. Свяжитесь с нами для аудита текущей реализации — мы оценим проект и предложим оптимальный стек за один день.
Как работает инфраструктура: APNs и FCM
APNs — единственный канал доставки на iOS. Всё остальное (OneSignal, Braze, Airship) — обёртки поверх него. APNs принимает запрос по HTTP/2, аутентификация через JWT-токен (p8-ключ) или сертификат. JWT предпочтительнее: один ключ для всех приложений в аккаунте, не истекает ежегодно в отличие от сертификата. Подробнее — на Wikipedia.
Критический момент: APNs различает apns-push-type — alert, background, voip, complication, fileprovider, mdm. Неправильно указанный тип на iOS 13+ приводит к тому, что background-уведомление не разбудит приложение. Видели проекты, где content-available: 1 отправляли без apns-push-type: background — приложение не получало silent push на части устройств, и команда месяц искала «баг в приложении».
FCM на Android работает через Google Play Services. Для устройств без GMS (Huawei, часть китайского рынка) нужен Huawei Push Kit или прямой WebSocket — отдельная задача. FCM поддерживает data-сообщения (обрабатываются в onMessageReceived) и notification-сообщения (система отображает автоматически, если приложение в фоне). Смешивать их нужно осторожно: если в notification-блоке есть click_action, а deep link в приложении не зарегистрирован, тап по уведомлению просто откроет главный экран без навигации.
| Характеристика |
APNs |
FCM |
| Аутентификация |
JWT-токен или сертификат |
Сервис-аккаунт Firebase |
| Типы сообщений |
alert, background, voip, etc. |
notification, data |
| Silent push |
content-available + apns-push-type: background |
data-сообщение с приоритетом high |
| Ограничения по payload |
4 КБ |
4 КБ (верхний), до 2 КБ для notification |
| Работа без Google Play |
Н/П (только iOS) |
Нет, нужен альтернативный провайдер |
Почему сегментация — основа эффективных push-уведомлений?
Отправлять всем подряд — значит быстро исчерпать лояльность пользователей. Персонализированные сообщения кликают в 3 раза чаще массовых, а правильная сегментация снижает отток на 25% (на одном из проектов это принесло дополнительный доход 3 млн рублей за квартал). Стоимость настройки сегментации в OneSignal или кастомном бэкенде составляет от 100 000 до 250 000 рублей в зависимости от сложности фильтров.
Нормальная сегментация строится на нескольких уровнях.
| Тип сегментации |
Инструмент |
Пример |
| По топикам |
FCM topics / APNs push-to-topic |
Уведомления о статусе заказа |
| По атрибутам |
OneSignal, Braze |
last_active < 7_days + plan = premium |
| Персонализированные |
Кастомный бэкенд |
По device_token с привязкой к профилю |
Топики — для широких категорий: «новые акции», «обновления статуса заказа». Пользователь подписывается через FirebaseMessaging.getInstance().subscribeToTopic("orders"). Просто, но нет гибкой фильтрации.
Сегменты по атрибутам — через OneSignal, Braze или кастомный бэкенд. Храним в профиле пользователя: язык, тип устройства, последняя активность, LTV-сегмент. Уведомление уходит только тем, у кого last_active < 7_days и plan = premium. OneSignal позволяет строить такие фильтры в интерфейсе без кода.
Персонализированные — по конкретному device_token. Важно хранить токены правильно: токен обновляется при переустановке приложения, при восстановлении из бэкапа на новый телефон, при сбросе настроек. На iOS используем UNUserNotificationCenter + didRegisterForRemoteNotificationsWithDeviceToken, сохраняем на бэкенд при каждом запуске, не только при первом. Иначе через 3 месяца 30% токенов в базе устаревшие.
Что такое rich push и как он повышает конверсию?
Стандартное уведомление с заголовком и текстом кликают реже, чем rich push с картинкой и кнопками действий — в 3 раза. Но реализация rich push — отдельная работа на каждой платформе.
На iOS rich content требует UNNotificationServiceExtension (для модификации payload) и UNNotificationContentExtension (кастомный UI). Расширение запускается в отдельном процессе с ограниченным временем и памятью. Если расширение падает или превышает таймаут, система показывает оригинальный payload без медиа. Типичная ошибка — пытаться загрузить изображение по HTTP (не HTTPS): ATS заблокирует запрос, расширение молча завершится, пользователь увидит уведомление без картинки.
На Android с API 26+ уведомления привязаны к NotificationChannel. Если канал создан с IMPORTANCE_LOW, звук и вибрация недоступны. Разные типы уведомлений (транзакционные, маркетинговые) должны быть в разных каналах, чтобы пользователь мог отключить маркетинг, не теряя уведомлений о заказах. BigPictureStyle, MessagingStyle, InboxStyle — шаблоны для расширенных уведомлений. MessagingStyle с Person и аватарками — лучший выбор для чатов.
| Платформа |
Компонент |
Особенности |
| iOS |
UNNotificationServiceExtension |
Время выполнения ~30 с, память ~50 МБ, обязательный HTTPS |
| iOS |
UNNotificationContentExtension |
Кастомный UI, кнопки действий |
| Android |
NotificationChannel |
Уровень важности, звук, вибрация — настраиваются пользователем |
| Android |
BigPictureStyle / MessagingStyle |
Расширенный контент, группировка сообщений |
Как отследить доставку и конверсию push-уведомлений?
Отправить уведомление — полдела. Важно знать: доставлено ли оно, открыто ли, привело ли к целевому действию.
FCM отдаёт MessageId при отправке, но не гарантирует коллбэк о доставке — это by design. Для tracking открытий нужна кастомная логика: при тапе на уведомление в onMessageReceived или через getInitialNotification() / onNotificationOpenedApp (OneSignal SDK) отправляем событие в аналитику с notification_id.
OneSignal предоставляет встроенную аналитику доставки и CTR. Для более детального анализа — интегрируем с Amplitude или Mixpanel через webhook на событие открытия. Бюджет такого дашборда составляет от 50 000 до 150 000 рублей в зависимости от объёма событий.
Как мы внедряем push-уведомления: типовой процесс
-
Аудит текущей реализации — проверяем хранение токенов, обработку обновлений, типы уведомлений.
-
Проектирование архитектуры — выбираем транспорт (FCM + APNs), слой сегментации (OneSignal/Braze/кастом), способ персонализации.
-
Реализация — пишем код регистрации, обработки входящих, rich push, deep linking.
-
Тестирование — отправляем тестовые кампании, проверяем доставку на разных устройствах, симуляторах, регионах.
-
Мониторинг и аналитика — настраиваем дашборд, события открытия и конверсий.
-
Документация и обучение — передаём команде материалы по эксплуатации.
Типичный стек: FCM + APNs на транспортном уровне, OneSignal или Firebase Notifications Composer для сегментации, кастомный бэкенд для персонализированных событийных уведомлений. Для крупных приложений с >1M пользователей OneSignal имеет ценовые ограничения — тогда используем Braze или собственную реализацию на AWS SNS.
Типичные ошибки при настройке push-уведомлений
- Не хранить обновлённые
device_token при каждом запуске — через 3 месяца 30% токенов устаревают.
- Путать
apns-push-type — background-уведомления не пробуждают приложение.
- Создавать один
NotificationChannel для всех типов уведомлений — пользователь не сможет отключить маркетинг, не потеряв транзакции.
- Загружать медиа в rich push по HTTP — ATS блокирует запрос на iOS.
- Не проверять deep link в таргетинге — переходы идут на главный экран.
Сроки зависят от сложности: базовая интеграция FCM+APNs с транзакционными уведомлениями — 1–2 недели. Полноценная система с сегментацией, rich push, аналитикой и A/B-тестированием контента — 4–8 недель. Закажите аудит текущей push-инфраструктуры или получите консультацию по внедрению push-уведомлений в мобильном приложении — мы свяжемся с вами в течение дня и предоставим точную оценку.