warm_alarm_ios 0.1.1
warm_alarm_ios: ^0.1.1 copied to clipboard
iOS implementation of the warm_alarm plugin
warm_alarm_ios #
The iOS implementation of warm_alarm.
This package is endorsed, which means you do not add it directly to your
pubspec.yaml. It is automatically included when you depend on warm_alarm.
Platform capabilities #
| Feature | Support | Notes |
|---|---|---|
| Notification scheduling | ✅ Full | UNUserNotificationCenter |
| Exact alarm scheduling | ⚠️ Limited | Notification-based; system may throttle background launch |
| Background audio playback | ⚠️ Limited | AVAudioSession .playback category; Silent mode bypass |
| Full-screen presentation | ❌ None | Full-screen intent is not supported; notification only |
| Wake-check | ❌ None | iOS cannot self-trigger background wakes after dismissal |
⚠️ Limited means the alarm fires via a UNUserNotificationCenter notification. The app is not
guaranteed to launch automatically in the background — audio plays only after the user interacts
with the notification (or if the app is already in the foreground).
Native implementation #
Scheduling #
Alarms are scheduled as UNNotificationRequest objects via UNUserNotificationCenter. The
UNCalendarNotificationTrigger fires at the exact scheduledAt time (subject to the operating
system's throttling policy for background notification delivery).
Audio #
When the notification action is handled, WarmAlarmDelegate starts AVAudioPlayer with the
configured audio source (a local file path or a Flutter asset). If neither is provided, no in-app
audio is played — the notification itself still plays the bundled alarm_ring.caf (or the system
default) sound. The AVAudioSession category is set to .playback (with .mixWithOthers) so the
audio continues even when the device is in Silent mode. An optional fade-in is applied by scheduling
discrete volume steps as DispatchWorkItems (via DispatchQueue.main.asyncAfter), not a periodic
timer.
Recurrence #
Weekly recurrence is delivered natively: one UNCalendarNotificationTrigger(repeats: true) is
registered per selected weekday, matching DateComponents(weekday, hour, minute), keyed
"{id}#{isoWeekday}". The series recurs without any re-arm and survives app termination. ISO
weekdays (1 = Mon … 7 = Sun) are mapped to Apple's Calendar weekdays (1 = Sun … 7 = Sat).
Dismissing an alarm ends only the current occurrence; cancelAlarm(id) removes every per-weekday
request and tears down the series. Note: each recurring alarm consumes up to 7 of iOS's 64
pending-notification slots.
Kill warning #
setKillWarning(title, body) stores a warning message. If the app is backgrounded while an alarm is
ringing, the plugin posts a non-actionable notification warning the user not to force-quit the app.
clearKillWarning() removes the stored message; the pending notification is auto-dismissed when the
app returns to the foreground.
Events emitted #
iOS emits a subset of the full event hierarchy — only events that are achievable within the notification delivery model:
WarmAlarmScheduledWarmAlarmFiredWarmAlarmStoppedWarmAlarmSnoozedWarmAlarmFailed
Wake-check events (WarmAlarmWakeCheckShown, WarmAlarmWakeCheckDismissed,
WarmAlarmWakeCheckExpired, WarmAlarmRetriggered) are not emitted on iOS.
Pigeon wire layer #
All Dart ↔ Swift communication is generated by Pigeon. The schema lives in
pigeons/messages.dart; generated outputs (Messages.g.swift, lib/src/messages.g.dart) are
never hand-edited. Run melos run generate after any schema change.
License #
BSD-3-Clause — Copyright (c) 2026, Dongmin Yu. See LICENSE for details.