# Platform Capability Reference: Android & iOS Alarm/Notification Behavior

**⚠️ DEPRECATED**: This document has been superseded by [01-platform-capability-reference.md](../alarms/01-platform-capability-reference.md) as part of the unified alarm documentation structure.

**See**: [Unified Alarm Directive](../alarms/000-UNIFIED-ALARM-DIRECTIVE.md) 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-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

**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

---

## Related Documentation

- [Plugin Behavior Exploration Template](./plugin-behavior-exploration-template.md) - Uses this reference
- [Plugin Requirements & Implementation](./plugin-requirements-implementation.md) - Implementation based on this reference
- [Android Alarm Persistence Directive](./android-alarm-persistence-directive.md) - Original Android reference
- [Improve Alarm Directives](./improve-alarm-directives.md) - Improvement directive

---

## Version History

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

