Локальное уведомление — это сообщение, которое приложение отправляет пользователю без участия удалённого сервера. Все данные обрабатываются и отображаются непосредственно на устройстве получателя. Такой механизм подходит для напоминаний, таймеров и будильников, когда приложение находится в фоне или закрыто. По данным Apple Developer Documentation, UNUserNotificationCenter обеспечивает централизованное управление локальными уведомлениями на iOS.
Главное
Локальное уведомление — это триггерное сообщение, которое генерируется и отображается операционной системой на том же устройстве, где установлено приложение. В отличие от push-уведомлений, локальные не проходят через внешний сервер — вся логика планирования выполняется на клиенте.
Такие уведомления работают независимо от состояния приложения: активное оно, свёрнутое или полностью закрытое. Операционная система берёт на себя доставку в назначенное время, а разработчик задаёт только контент и триггер.
Система гарантирует доставку локального уведомления даже при отсутствии сети. Это ключевое преимущество перед push-уведомлениями, которые требуют стабильного интернет-соединения и рабочего сервера.
Каждое локальное уведомление состоит из трёх частей: контент (заголовок, тело, звук), триггер (временной или гео-условие) и идентификатор запроса. Идентификатор позволяет отменить или обновить уведомление до его доставки.
Разработчик может задать до 64 локальных уведомлений на одно приложение в iOS и неограниченное количество в Android. Разница связана с архитектурными ограничениями операционных систем.
Обе платформы предоставляют собственные API для работы с локальными уведомлениями. На iOS центральный элемент — UNUserNotificationCenter, на Android — NotificationManager. Несмотря на разные интерфейсы, логика совпадает: приложение создаёт запрос, регистрирует его в системе, и ОС доставляет уведомление в заданный момент.
iOS использует UNCalendarNotificationTrigger для календарных событий, UNTimeIntervalNotificationTrigger для интервалов и UNLocationNotificationTrigger для геопозиции. Android предлагает AlarmManager, WorkManager и точное планирование через setExact.
С версии Android 12 — SCHEDULE_EXACT_ALARM требует специального разрешения от пользователя. На iOS разрешение запрашивается один раз через UNUserNotificationCenter.requestAuthorization, и пользователь выбирает уровень доступа: баннеры, звуки, значки.
Локальные уведомления классифицируются по типу триггера, а не по содержимому. Каждый тип определяет, когда и при каких условиях уведомление будет показано пользователю.
На iOS и Android типы триггеров реализованы по-разному, хотя логическая классификация совпадает. iOS использует UNCalendarNotificationTrigger для дат, UNTimeIntervalNotificationTrigger для интервалов и UNLocationNotificationTrigger для геопозиции. Android предлагает AlarmManager с setExact и setRepeating, а также WorkManager для отложенных задач.
| Тип триггера | Описание | Пример |
|---|---|---|
| Временной интервал | Уведомление через N секунд после запуска | Таймер обратного отсчёта |
| Календарная дата | Уведомление в конкретное время и дату | Напоминание о встрече |
| Геопозиция | Уведомление при входе/выходе из региона | Напоминание у магазина |
| Безусловное | Немедленная доставка при вызове API | Уведомление о загрузке |
На iOS также доступен UNNotificationAttachment — вложение изображения, аудио или видео в тело уведомления. Android поддерживает кастомные шаблоны с кнопками и большими изображениями через NotificationCompat.Style.
Выбор триггера зависит от сценария: календарные напоминания лучше всего работают через календарный триггер, а гео-напоминания — через геопозицию. Интервальные триггеры подходят для регулярных событий с фиксированным периодом.
На iOS локальные уведомления доставляются системой даже при закрытом приложении — UNUserNotificationCenter управляет очередью самостоятельно. На Android доставка зависит от выбранного механизма: AlarmManager срабатывает даже при выключенном экране, а WorkManager — с учётом энергосбережения.
Локальные уведомления решают задачи, где внешняя инфраструктура избыточна или недоступна. Основные сценарии: напоминания, таймеры, обучающие подсказки и отложенные действия.
Исследования Localytics показывают, что приложения, использующие локальные напоминания, удерживают на 35% больше пользователей в первую неделю после установки. Это делает локальные уведомления мощным инструментом онбординга.
Важно не злоупотреблять частотой — система сама группирует уведомления от одного приложения, а пользователь может отключить все локальные уведомления, если они надоедают. Оптимальная частота — не более 2–3 уведомлений в день для не-критичных событий.
Для планирования локального уведомления на Android используйте NotificationManager в паре с AlarmManager. С Android 8+ необходимо сначала создать канал уведомлений, иначе уведомление не отобразится.
val channelId = "reminder_channel"
val notificationId = "task_reminder_42"
val channel = NotificationChannel(
channelId,
"Напоминания",
NotificationManager.IMPORTANCE_HIGH
).apply {
description = "Канал для напоминаний о задачах"
}
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(channel)
val intent = Intent(this, ReminderReceiver::class.java).apply {
putExtra("notification_id", notificationId)
putExtra("channel_id", channelId)
}
val pendingIntent = PendingIntent.getBroadcast(
this, notificationId.hashCode(),
intent, PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManager = getSystemService(AlarmManager::class.java)
alarmManager.setExact(
AlarmManager.RTC_WAKEUP,
triggerTimeMillis,
pendingIntent
)
На Android 12+ проверьте разрешение SCHEDULE_EXACT_ALARM перед вызовом setExact. Если разрешение не выдано — используйте setWindow, который гарантирует доставку в пределах временного окна.
При срабатывании AlarmManager система отправляет широковещательный Intent, который принимает BroadcastReceiver. Внутри него необходимо создать и показать уведомление через NotificationManager. Убедитесь, что PendingIntent использует FLAG_UPDATE_CURRENT, иначе при изменении данных старые уведомления продолжат использовать устаревший Intent.
На iOS локальные уведомления создаются через UNUserNotificationCenter с помощью UNMutableNotificationContent и одного из триггеров. Перед планированием необходимо запросить разрешение у пользователя.
import UserNotifications
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in
guard granted else { return }
}
let content = UNMutableNotificationContent()
content.title = "Напоминание о задаче"
content.body = "Не забудьте завершить отчёт до 18:00"
content.sound = .default
content.userInfo = ["task_id": "42"]
let trigger = UNTimeIntervalNotificationTrigger(
timeInterval: 3600,
repeats: false
)
let request = UNNotificationRequest(
identifier: "task_reminder_42",
content: content,
trigger: trigger
)
center.add(request)
iOS поддерживает до 64 одновременных запросов на локальные уведомления. Если лимит превышен — система отклоняет новые запросы до тех пор, пока активные не будут доставлены или отменены. Используйте getPendingNotificationRequests для проверки текущей очереди.
Когда пользователь взаимодействует с локальным уведомлением iOS, вызывается метод userNotificationCenter:didReceive response делегата UNUserNotificationCenterDelegate. В этом методе доступны идентификатор запроса, actionIdentifier (какая кнопка нажата) и кастомные userInfo. Это позволяет различать простое открытие уведомления и нажатие на конкретную кнопку действия.
Чтобы локальные уведомления приносили пользу, а не раздражали пользователя, соблюдайте несколько ключевых правил. Первое: контролируйте частоту — не более 2–3 уведомлений в день для не-критичных событий, иначе пользователь отключит все уведомления приложения.
Второе: давайте пользователю выбор. Добавьте в интерфейс возможность отключить определённые типы локальных уведомлений. На Android для этого удобно использовать отдельный NotificationChannel с низким importance, на iOS — отдельную категорию в настройках приложения.
Третье: контекстная релевантность — уведомление должно появляться, когда оно необходимо пользователю. Гео-триггеры идеальны для напоминаний о делах рядом с домом, календарные — для встреч, интервальные — для регулярных действий вроде питья воды или разминки. Не смешивайте типы без необходимости.
Четвёртое: тестируйте на реальных устройствах. Симулятор iOS не эмулирует все сценарии доставки локальных уведомлений, особенно в фоне. На Android используйте adb shell dumpsys notification для проверки очереди запланированных уведомлений и их параметров. Пятое: всегда предоставляйте пользователю возможность отключить уведомления через интерфейс приложения — это обязательное требование UX и App Store Review Guidelines.
Часто задаваемые вопросы
Локальное уведомление планируется и доставляется устройством без участия сервера. Push-уведомление требует внешнего сервиса (FCM, APNS) и интернет-соединения. Локальные работают офлайн, push — только при наличии сети.
iOS ограничивает до 64 одновременно запланированных запросов. Android не имеет строгого лимита, но свыше 500 уведомлений может снизить производительность системы и повлиять на время доставки.
Да, на iOS используйте removePendingNotificationRequests с идентификатором запроса. На Android вызовите NotificationManager.cancel или отмените PendingIntent через AlarmManager. Уникальный идентификатор обязателен для отмены.
На iOS разрешение запрашивается обязательно через requestAuthorization. На Android 13+ (Tiramisu) также требуется разрешение POST_NOTIFICATIONS. Более старые версии Android не требуют явного разрешения для локальных уведомлений.
На iOS создайте UNNotificationAction и добавьте в UNNotificationCategory. На Android используйте NotificationCompat.Builder.addAction с PendingIntent на BroadcastReceiver. Каждая кнопка запускает отдельное действие в приложении.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также