warm_alarm_android 0.1.2
warm_alarm_android: ^0.1.2 copied to clipboard
Android implementation of the warm_alarm plugin
warm_alarm_android #
The Android 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 | POST_NOTIFICATIONS permission required |
| Exact alarm scheduling | ✅ Full | SCHEDULE_EXACT_ALARM / USE_EXACT_ALARM |
| Background audio playback | ⚠️ Limited | Foreground service with mediaPlayback type |
| Full-screen presentation | ✅ Full | setFullScreenIntent; per-alarm via androidFullScreenIntent; runtime-checked with canUseFullScreenIntent() |
| Wake-check | ✅ Full | Follow-up alarm verifies user is awake |
Native implementation #
Scheduling #
Alarms are scheduled via AlarmManager.setExactAndAllowWhileIdle() so they fire even when the
device is in Doze mode. The exact-alarm permission (either USE_EXACT_ALARM for system apps or
SCHEDULE_EXACT_ALARM with user approval) is declared in the manifest and checked at runtime
through getPermissionState().
requestNotificationPermission() requests POST_NOTIFICATIONS on Android 13+.
On Android 12 and earlier there is no runtime notification permission to request, so the call reports unsupported and the caller should open notification settings instead.
openReadinessSettings(reason) opens notification, exact-alarm, or full-screen settings when the reported reason supports it.
The settings action returns when Android accepts the deep link.
Query readiness again after the app resumes.
Alarm delivery #
When the scheduled time arrives WarmAlarmReceiver receives the com.andrew.alarm.ACTION_FIRE
broadcast and starts WarmAlarmForegroundService. The service:
- Plays audio via
MediaPlayer(local file, asset, or system default ringtone) - Applies optional fade-in via a
Handler-driven volume schedule - Posts the alarm notification with configurable Stop/Snooze actions
- Optionally enforces volume if the device is set to silent
Wake-check #
When WarmAlarmWakeCheck is configured, a secondary alarm is scheduled for checkDelay after the
primary alarm fires. If ACTION_WAKE_CHECK_FIRE arrives without the user having dismissed the
primary alarm, the alarm retriggers (up to maxRetriggers times at retriggerDelay intervals).
ACTION_WAKE_CHECK_DISMISS cancels the follow-up chain.
A retrigger and the regular alarm are separate PendingIntents.
AlarmManager matches on request code plus Intent.filterEquals, which ignores extras, so a shared identity let arming a retrigger re-target the pending next occurrence and let a dismiss cancel it.
Only the retrigger carries a warm-alarm://<package>/alarm/<id>/retrigger data Uri; the regular alarm keeps the data-less identity it had before 0.1.2, so an alarm scheduled by an older install stays cancellable after an update.
Finishing a wake check clears a recurring alarm's retrigger count and removes the stored schedule only for a one-shot alarm.
filterEquals cannot be exercised from the JVM unit tests, so verify it on a device: schedule a recurring alarm, let the wake check fire, tap the dismiss action, then confirm the next occurrence is still listed by adb shell dumpsys alarm | grep <package>.
Recurrence #
Weekly recurrence is re-armed on fire: AlarmManager is single-shot, so when a recurring alarm
fires, WarmAlarmReceiver computes the next matching weekday occurrence
(WarmAlarmRecurrence.nextOccurrence, same time-of-day, strictly after now) and re-arms it, updating
the stored scheduledAtMillis. The re-arm runs in the receiver without a Flutter engine, so the
series survives even when the app process is dead. Dismissing an alarm ends only the current
occurrence; cancelAlarm(id) tears down the series.
Boot persistence #
WarmAlarmBootReceiver handles BOOT_COMPLETED and LOCKED_BOOT_COMPLETED broadcasts (via
RECEIVE_BOOT_COMPLETED permission) to reschedule any alarms that were lost when the device
restarted. It is directBootAware, so alarms scheduled before first unlock are restored from
device-protected storage.
Kill warning #
setKillWarning(title, body) posts a persistent, non-dismissible notification to discourage users
from force-quitting the app before an alarm fires. Call clearKillWarning() to remove it.
Required permissions #
The following permissions are declared in the plugin's AndroidManifest.xml and merged
automatically into your app's manifest:
SCHEDULE_EXACT_ALARM — exact alarm scheduling (user-granted on Android 12+)
USE_EXACT_ALARM — exact alarm scheduling (system-granted for alarm-category apps)
RECEIVE_BOOT_COMPLETED — reschedule alarms after device reboot
POST_NOTIFICATIONS — show alarm and kill-warning notifications (Android 13+)
USE_FULL_SCREEN_INTENT — launch the full-screen alarm UI over the lock screen (Android 14+)
VIBRATE — haptic feedback during alarm
FOREGROUND_SERVICE — run WarmAlarmForegroundService
FOREGROUND_SERVICE_MEDIA_PLAYBACK — declare mediaPlayback foreground service type
Pigeon wire layer #
All Dart ↔ Kotlin communication is generated by Pigeon. The schema lives in
pigeons/messages.dart; generated outputs (Messages.g.kt, 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.