Перейти к содержимому
Все записи

Live Updates в Android 16: таймер фокусировки Mintly теперь на экране блокировки

Практическое руководство по уведомлениям Android 16, ориентированным на прогресс — сегменты ProgressStyle, продвинутые постоянные уведомления и что они дают работающему таймеру Pomodoro.

MFKAPPS 4 мин чтения

Таймер, который живёт только внутри приложения, — это таймер, который никто не проверяет. Весь смысл сессии Pomodoro в том, чтобы перестать за ней следить — вы бросаете взгляд на экран блокировки, когда отвлекаетесь от работы, видите, сколько времени фокуса осталось, и возвращаетесь к делу. Android 16 наконец даёт постоянным уведомлениям настоящий ответ на этот взгляд: Live Updates — тип продвинутого уведомления, построенный вокруг ProgressStyle, который получает место на экране блокировки и компактный чип в строке состояния вместо того, чтобы теряться в шторке уведомлений. Вот что это на самом деле делает и как это изменило уведомление, которое Mintly показывает во время сессии.

Что Live Update добавляет к обычному постоянному уведомлению

Постоянное, неотклоняемое уведомление с полосой прогресса работает на Android уже много лет — именно так работало уведомление таймера Mintly до этого. Чего ему не хватало, так это приоритетного размещения. Обычное постоянное уведомление сидит в шторке рядом со всем остальным, и на телефоне с забитым списком уведомлений это одна строка среди множества.

Live Update отличается от того же содержимого буквально одним вызовом Notification.Builder, но система обрабатывает его иначе: оно имеет право показываться на экране блокировки, даже когда остальные уведомления свёрнуты, а на поддерживаемых устройствах может отображаться в виде маленького живого чипа рядом с часами в строке состояния. Систему сама решает, действительно ли предоставить это продвинутое размещение — запрос его не гарантирует, — но для тех типов уведомлений, под которые Android это и проектировал (приближающаяся поездка, доставка в пути, обратный отсчёт таймера), это разница между «пользователю нужно разблокировать телефон и потянуть шторку вниз» и «пользователь читает всё прямо на экране блокировки, ничего не трогая».

Подключение ProgressStyle к уведомлению таймера

Сам стиль — это небольшое дополнение к уведомлению, которое вы уже строите:

val progressStyle = NotificationCompat.ProgressStyle()
    .setProgress(elapsedSeconds)
    .setProgressMax(totalSeconds)
    .setProgressIndeterminate(false)

val notification = NotificationCompat.Builder(context, CHANNEL_FOCUS_SESSION)
    .setContentTitle("Focus session")
    .setContentText(formatRemaining(totalSeconds - elapsedSeconds))
    .setSmallIcon(R.drawable.ic_mintly_timer)
    .setOngoing(true)
    .setOnlyAlertOnce(true)
    .setStyle(progressStyle)
    .setRequestPromotedOngoing(true)
    .build()

Единственная настройка, на которой стоит остановиться, — это setRequestPromotedOngoing(true). Это запрос, а не переключатель — платформа может его отклонить, и он предназначен для уведомлений, которые действительно представляют что-то, чего пользователь сейчас активно ждёт, а не для общего способа пролезть без очереди. Реально работающий таймер этому критерию отвечает. Устаревшее уведомление, оставшееся от сессии, закончившейся десять минут назад, — нет, и собственная эвристика платформы начнёт игнорировать запросы на продвижение от приложения, которое запрашивает их тогда, когда на самом деле ничего не происходит.

Сегменты превращают полосу в настоящую карту сессии

То, что действительно оправдало внедрение этого в Mintly, — не само по себе размещение на экране блокировки, а поддержка сегментов в ProgressStyle. Вместо одной сплошной полосы можно описать прогресс как последовательность цветных диапазонов, что напрямую отражает реальную структуру сессии Pomodoro: блок работы, короткий перерыв, блок работы, длинный перерыв.

val segments = listOf(
    ProgressStyle.Segment(25 * 60).setColor(mintlyFocusColor),
    ProgressStyle.Segment(5 * 60).setColor(mintlyBreakColor),
    ProgressStyle.Segment(25 * 60).setColor(mintlyFocusColor),
    ProgressStyle.Segment(15 * 60).setColor(mintlyLongBreakColor),
)

progressStyle.setProgressSegments(segments)

Одно это изменение отвечает на вопрос, на который старая плоская полоса прогресса никогда не могла ответить: не просто «сколько времени осталось в этой сессии», а «где я нахожусь в цикле и как далеко до следующего настоящего перерыва». Точки — второй базовый элемент, который предлагает ProgressStyle, — небольшие маркеры вдоль полосы, — и они естественно подходят для контрольных точек прерываний, хотя Mintly пока их не использует.

Ошибочный сценарий: относиться к этому как к украшению

Соблазнительно навесить ProgressStyle и запрос продвижения на каждое постоянное уведомление, какое есть у приложения, потому что поверхность API маленькая, а визуальное улучшение реально. Это неверный инстинкт. Live Updates существует для узкой категории — чего-то ограниченного по времени и действительно происходящего прямо сейчас, что важно пользователю именно в этот момент, — и платформа следит за приложениями, которые запрашивают продвижение вне этой категории. Приложение, продвигающее напоминание вида «вы не открывали это 3 дня», замаскированное под полосу прогресса, — это ровно тот случай злоупотребления, который эта функция должна была предотвратить, а повторяющиеся недобросовестные запросы — именно то, из-за чего будущие запросы приложения на продвижение могут тихо понизить в приоритете.

Честная проверка перед добавлением setRequestPromotedOngoing(true) где бы то ни было: стоит ли за этим уведомлением реальный, работающий процесс, который заканчивается в конкретный момент, предсказуемый по самой полосе? Для таймера фокусировки — да, по всем пунктам. Для большинства других типов уведомлений в типичном local-first приложении — нет, и простое уведомление, которое у вас уже есть, — как раз то, что стоит оставить.

Что это не заменяет

Live Updates меняет то, где видно уведомление таймера. Это не меняет того, срабатывает ли оно надёжно в принципе — за это по-прежнему отвечают foreground-сервис и расчёт времени окончания по настенным часам, на которые Mintly уже опирается, чтобы пережить Doze и гибель процесса. ProgressStyle и запрос продвижения лежат поверх этого фундамента; это слой представления, а не замена правильной реализации самого таймера. Сначала постройте надёжную версию. Чип на экране блокировки стоит добавлять, когда это уже вне сомнений, — не раньше.

// По теме

Ещё из журнала

MFKAPPS 4 мин чтения

Типы foreground-сервисов в Android в 2026 году: как выбрать тот, что реально подходит вашей функции

Практическое руководство по ограничениям типов foreground-сервисов Android — dataSync, mediaPlayback, specialUse, shortService — и как выбрать правильный, не получив ни принудительной остановки, ни отказа в проверке.

#android #engineering #kotlin
MFKAPPS 4 мин чтения

Каналы уведомлений Android в 2026 году: как задать уровни важности, которые пользователи не отключат

Практическое руководство по каналам уведомлений Android — уровни важности, группы каналов, почему настройки замораживаются после создания и как мигрировать, не потеряв доверие пользователя.

#android #engineering #notifications
MFKAPPS 4 мин чтения

Разработка Mintly: как удержать точность таймера фокуса, когда Android хочет убить процесс

У работающего таймера Pomodoro проблема с надёжностью сложнее, чем у одноразового напоминания. Вот как Mintly переживает режим Doze, гибель процесса и дрейф при выключенном экране благодаря foreground-сервису и времени окончания по системным часам.

#android #engineering #mobile