Files
daily-notification-plugin/docs/android-alarm-persistence-directive.md
Matthew Raymer 35babb3126 docs(alarms): unify and enhance alarm directive documentation stack
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.
2025-11-25 10:09:46 +00:00

7.0 KiB
Raw Blame History

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:

  1. Persist all alarms in storage (Room DB or SharedPreferences).
  2. Add a BOOT_COMPLETED / LOCKED_BOOT_COMPLETED broadcast receiver.
  3. 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-appstyle 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.**



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