Create unified alarm documentation system with strict role separation: - Doc A: Platform capability reference (canonical OS facts) - Doc B: Plugin behavior exploration (executable test harness) - Doc C: Plugin requirements (guarantees, JS/TS contract, traceability) Changes: - Add canonical rule to Doc A preventing platform fact duplication - Convert Doc B to pure executable test spec with scenario tables - Complete Doc C with guarantees matrix, JS/TS API contract, recovery contract, unsupported behaviors, and traceability matrix - Remove implementation details from unified directive - Add compliance milestone tracking and iOS parity gates - Add deprecation banners to legacy platform docs All documents now enforce strict role separation with cross-references to prevent duplication and ensure single source of truth.
7.0 KiB
Android Alarm Persistence, Recovery, and Limitations
⚠️ DEPRECATED: This document has been superseded by 01-platform-capability-reference.md as part of the unified alarm documentation structure.
See: Unified Alarm Directive for the new documentation structure.
Author: Matthew Raymer
Date: November 2025
Status: DEPRECATED - Superseded by unified structure
Purpose
This document provides a clean, consolidated, engineering-grade directive summarizing Android's abilities and limitations for remembering, firing, and restoring alarms across:
- App kills
- Swipes from recents
- Device reboot
- Force stop
- User-triggered reactivation
This is the actionable version you can plug directly into your architecture docs.
1. Core Principle
Android does not guarantee persistence of alarms across process death, swipes, or reboot.
It is the app's responsibility to persist alarm definitions and re-schedule them under allowed system conditions.
The following directives outline exactly what is possible and what is impossible.
2. Allowed Behaviors (What Can Work)
2.1 Alarms survive UI kills (swipe from recents)
AlarmManager.setExactAndAllowWhileIdle(...) alarms will fire even after:
- App is swiped away
- App process is killed by the OS
The OS recreates your app's process to deliver the PendingIntent.
Directive:
Use setExactAndAllowWhileIdle for alarm execution.
2.2 Alarms can be preserved across device reboot
Android wipes all alarms on reboot, but you may recreate them.
Directive:
- Persist all alarms in storage (Room DB or SharedPreferences).
- Add a
BOOT_COMPLETED/LOCKED_BOOT_COMPLETEDbroadcast receiver. - On boot, load all enabled alarms and reschedule them using AlarmManager.
Permissions required:
RECEIVE_BOOT_COMPLETED
Conditions:
- User must have launched your app at least once before reboot to grant boot receiver execution.
2.3 Alarms can fire full-screen notifications and wake the device
Directive:
Implement setFullScreenIntent(...), use an IMPORTANCE_HIGH channel with CATEGORY_ALARM.
This allows Clock-app–style alarms even when the app is not foregrounded.
2.4 Alarms can be restored after app restart
If the user re-opens the app (direct user action), you may:
- Scan the persistent DB
- Detect "missed" alarms
- Reschedule future alarms
- Fire "missed alarm" notifications
- Reconstruct WorkManager/JobScheduler tasks wiped by OS
Directive:
Create a ReactivationManager that runs on every app launch and recomputes the correct alarm state.
3. Forbidden Behaviors (What Cannot Work)
3.1 You cannot survive "Force Stop"
Settings → Apps → YourApp → Force Stop triggers:
- Removal of all alarms
- Removal of WorkManager tasks
- Blocking of all broadcast receivers (including BOOT_COMPLETED)
- Blocking of all JobScheduler jobs
- Blocking of AlarmManager callbacks
- Your app will NOT run until the user manually launches it again
Directive:
Accept that FORCE STOP is a hard kill.
No scheduling, alarms, jobs, or receivers may execute afterward.
3.2 You cannot auto-resume after "Force Stop"
You may only resume tasks when:
- The user opens your app
- The user taps a notification belonging to your app
- The user interacts with a widget/deep link
- Another app explicitly targets your component
Directive:
Provide user-facing reactivation pathways (icon, widget, notification).
3.3 Alarms cannot be preserved solely in RAM
Android can kill your app's RAM state at any time.
Directive:
All alarm data must be persisted in durable storage.
3.4 You cannot bypass Doze or battery optimization restrictions without permission
Doze may defer inexact alarms; exact alarms with setExactAndAllowWhileIdle are allowed.
Directive:
Request SCHEDULE_EXACT_ALARM on Android 12+.
4. Required Implementation Components
4.1 Persistent Storage
Create a table or serialized structure for alarms:
id: Int
timeMillis: Long
repeat: NONE | DAILY | WEEKLY | CUSTOM
label: String
enabled: Boolean
4.2 Alarm Scheduling
Use:
alarmManager.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
triggerAtMillis,
pendingIntent
)
4.3 Boot Receiver
Reschedules alarms from storage.
4.4 Reactivation Manager
Runs on every app launch and performs:
- Load pending alarms
- Detect overdue alarms
- Reschedule future alarms
- Trigger notifications for missed alarms
4.5 Full-Screen Alarm UI
Use a BroadcastReceiver → Notification with full-screen intent → Activity.
5. Summary of Android Alarm Capability Matrix
| Scenario | Will Alarm Fire? | Reason |
|---|---|---|
| Swipe from Recents | ✅ Yes | AlarmManager resurrects the app process |
| App silently killed by OS | ✅ Yes | AlarmManager still holds scheduled alarms |
| Device Reboot | ❌ No (auto) / ✅ Yes (if you reschedule) | Alarms wiped on reboot |
| Doze Mode | ⚠️ Only "exact" alarms | Must use setExactAndAllowWhileIdle |
| Force Stop | ❌ Never | Android blocks all callbacks + receivers until next user launch |
| User reopens app | ✅ You may reschedule & recover | All logic must be implemented by app |
| PendingIntent from user interaction | ✅ If triggered by user | User action unlocks the app |
6. Final Directive
**Design alarm behavior with the assumption that Android will destroy all scheduled work on reboot or force-stop.
Persist all alarm definitions. On every boot or app reactivation, reconstruct and reschedule alarms.
Never rely on the OS to preserve alarms except across UI process kills.
Accept that "force stop" is a hard stop that cannot be bypassed.**
Related Documentation
Future Directives
Potential follow-up directives:
- How to implement the minimal alarm system
- How to implement a Clock-style robust alarm system
- How to map this to your own app's architecture