Files
daily-notification-plugin/docs/platform-capability-reference.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

14 KiB
Raw Permalink Blame History

Platform Capability Reference: Android & iOS Alarm/Notification Behavior

⚠️ 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 pure OS-level facts about alarm and notification capabilities on Android and iOS. It contains no plugin-specific logic—only platform mechanics that affect plugin design.

This is a reference document to be consulted when designing plugin behavior, not an implementation guide.


1. Core Principles

Android

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.

iOS

iOS does persist scheduled local notifications across app termination and device reboot, but:

  • App code does not run when notifications fire (unless user interacts)
  • Background execution is severely limited
  • Plugin must persist its own state if it needs to track or recover missed notifications

2. Android Alarm Capability Matrix

Scenario Will Alarm Fire? OS Behavior App Responsibility
Swipe from Recents Yes AlarmManager resurrects the app process None (OS handles)
App silently killed by OS Yes AlarmManager still holds scheduled alarms None (OS handles)
Device Reboot No (auto) / Yes (if you reschedule) All alarms wiped on reboot Must reschedule from persistent storage on boot
Doze Mode ⚠️ Only "exact" alarms Inexact alarms deferred; exact alarms allowed Must use setExactAndAllowWhileIdle
Force Stop Never Android blocks all callbacks + receivers until next user launch Cannot bypass; must detect on app restart
User reopens app You may reschedule & recover App process restarted Must detect missed alarms and reschedule future ones
PendingIntent from user interaction If triggered by user User action unlocks the app None (OS handles)

Android Allowed Behaviors

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.

Required API: setExactAndAllowWhileIdle() or setAlarmClock()

2.2 Alarms can be preserved across device reboot

Android wipes all alarms on reboot, but you may recreate them.

Required Components:

  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

2.3 Alarms can fire full-screen notifications and wake the device

Required API: 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

Required: Create a ReactivationManager that runs on every app launch

Android Forbidden Behaviors

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.

Required Permission: SCHEDULE_EXACT_ALARM on Android 12+ (API 31+)


3. iOS Notification Capability Matrix

Scenario Will Notification Fire? OS Behavior App Responsibility
Swipe from App Switcher Yes UNUserNotificationCenter persists and fires notifications None (OS handles)
App Terminated by System Yes UNUserNotificationCenter persists and fires notifications None (OS handles)
Device Reboot Yes (for calendar/time triggers) iOS persists scheduled local notifications across reboot None for notifications; must persist own state if needed
App Force Quit (swipe away) Yes UNUserNotificationCenter persists and fires notifications None (OS handles)
Background Execution No arbitrary code Only BGTaskScheduler with strict limits Cannot rely on background execution for recovery
Notification Fires Yes Notification displayed; app code does NOT run unless user interacts Must handle missed notifications on next app launch
User Taps Notification Yes App launched; code can run Can detect and handle missed notifications

iOS Allowed Behaviors

3.1 Notifications survive app termination

UNUserNotificationCenter scheduled notifications will fire even after:

  • App is swiped away from app switcher
  • App is terminated by system
  • Device reboots (for calendar/time-based triggers)

Required API: UNUserNotificationCenter.add() with UNCalendarNotificationTrigger or UNTimeIntervalNotificationTrigger

3.2 Notifications persist across device reboot

iOS automatically persists scheduled local notifications across reboot.

No app code required for basic notification persistence.

Limitation: Only calendar and time-based triggers persist. Location-based triggers do not.

3.3 Background tasks for prefetching

Required API: BGTaskScheduler with BGAppRefreshTaskRequest

Limitations:

  • Minimum interval between tasks (system-controlled, typically hours)
  • System decides when to execute (not guaranteed)
  • Cannot rely on background execution for alarm recovery
  • Must schedule next task immediately after current one completes

iOS Forbidden Behaviors

4.1 App code does not run when notification fires

When a scheduled notification fires:

  • Notification is displayed to user
  • No app code executes unless user taps the notification
  • Cannot run arbitrary code at notification time

Workaround: Use notification actions or handle missed notifications on next app launch.

4.2 No repeating background execution

iOS does not provide repeating background execution APIs except:

  • BGTaskScheduler (system-controlled, not guaranteed)
  • Background fetch (deprecated, unreliable)

Directive: Plugin cannot rely on background execution to reconstruct alarms. Must persist state and recover on app launch.

4.3 No arbitrary code on notification trigger

Unlike Android's PendingIntent which can execute code, iOS notifications only:

  • Display to user
  • Launch app if user taps
  • Execute notification action handlers (if configured)

Directive: All recovery logic must run on app launch, not at notification time.

4.4 Background execution limits

BGTaskScheduler Limitations:

  • Minimum intervals between tasks (system-controlled)
  • System may defer or skip tasks
  • Tasks have time budgets (typically 30 seconds)
  • Cannot guarantee execution timing

Directive: Use BGTaskScheduler for prefetching only, not for critical scheduling.


4. Cross-Platform Comparison

Feature Android iOS
Survives swipe/termination Yes (with exact alarms) Yes (automatic)
Survives reboot No (must reschedule) Yes (automatic for calendar/time triggers)
App code runs on trigger Yes (via PendingIntent) No (only if user interacts)
Background execution WorkManager, JobScheduler ⚠️ Limited (BGTaskScheduler only)
Force stop equivalent Force Stop (hard kill) No user-facing equivalent
Boot recovery required Yes (must implement) No (OS handles)
Missed alarm detection Must implement on app launch Must implement on app launch
Exact timing Yes (with permission) ⚠️ ±180s tolerance
Repeating notifications Must reschedule each occurrence Can use repeats: true in trigger

5. Required Platform APIs

Android

Alarm Scheduling:

  • AlarmManager.setExactAndAllowWhileIdle() - Android 6.0+ (API 23+)
  • AlarmManager.setAlarmClock() - Android 5.0+ (API 21+)
  • AlarmManager.setExact() - Android 4.4+ (API 19+)

Permissions:

  • RECEIVE_BOOT_COMPLETED - Boot receiver
  • SCHEDULE_EXACT_ALARM - Android 12+ (API 31+)

Background Work:

  • WorkManager - Deferrable background work
  • JobScheduler - Alternative (API 21+)

iOS

Notification Scheduling:

  • UNUserNotificationCenter.add() - Schedule notifications
  • UNCalendarNotificationTrigger - Calendar-based triggers
  • UNTimeIntervalNotificationTrigger - Time interval triggers

Background Tasks:

  • BGTaskScheduler.submit() - Schedule background tasks
  • BGAppRefreshTaskRequest - Background fetch requests

Permissions:

  • Notification authorization (requested at runtime)

6. Platform-Specific Constraints Summary

Android Constraints

  1. Reboot: All alarms wiped; must reschedule from persistent storage
  2. Force Stop: Hard kill; cannot bypass until user opens app
  3. Doze: Inexact alarms deferred; must use exact alarms
  4. Exact Alarm Permission: Required on Android 12+ for precise timing
  5. Boot Receiver: Must be registered and handle BOOT_COMPLETED

iOS Constraints

  1. Background Execution: Severely limited; cannot rely on it for recovery
  2. Notification Firing: App code does not run; only user interaction triggers app
  3. Timing Tolerance: ±180 seconds for calendar triggers
  4. BGTaskScheduler: System-controlled; not guaranteed execution
  5. State Persistence: Must persist own state if tracking missed notifications


Version History

  • v1.0 (November 2025): Initial platform capability reference
    • Android alarm matrix
    • iOS notification matrix
    • Cross-platform comparison