Adds documentation and test harness for Phase 3 (Boot-Time Recovery). Changes: - Update android-implementation-directive-phase3.md with concise boot recovery flow - Add PHASE3-EMULATOR-TESTING.md with detailed test procedures - Add PHASE3-VERIFICATION.md with test matrix and verification template - Add test-phase3.sh automated test harness Test harness features: - 4 test cases: future alarms, past alarms, no schedules, silent recovery - Automatic emulator reboot handling - Log parsing for boot recovery scenario and results - UI prompts for plugin configuration and scheduling - Verifies silent recovery without app launch Related: - Directive: android-implementation-directive-phase3.md - Requirements: docs/alarms/03-plugin-requirements.md §3.1.1 - Testing: docs/alarms/PHASE3-EMULATOR-TESTING.md - Verification: docs/alarms/PHASE3-VERIFICATION.md
5.7 KiB
Android Implementation Directive – Phase 3
Boot-Time Recovery (Device Reboot / System Restart)
Plugin: Daily Notification Plugin
Author: Matthew Raymer
Applies to: Android Plugin (Kotlin), Capacitor Bridge
Related Docs:
03-plugin-requirements.md000-UNIFIED-ALARM-DIRECTIVE.mdandroid-implementation-directive-phase1.mdandroid-implementation-directive-phase2.mdACTIVATION-GUIDE.md
1. Purpose
Phase 3 introduces Boot-Time Recovery, which restores daily notifications after:
- Device reboot
- OS restart
- Update-related restart
- App not opened after reboot (silent recovery)
Android clears all alarms on reboot.
Therefore, if our plugin is not actively rescheduling on boot, the user will miss all daily notifications until they manually launch the app.
Phase 3 ensures:
- Schedules stored in SQLite survive reboot
- Alarms are fully reconstructed
- No duplication / double-scheduling
- Boot behavior avoids unnecessary heavy recovery
- Recovery occurs even if the user does not manually open the app
2. Boot-Time Recovery Flow
Trigger:
BOOT_COMPLETED broadcast received
→ Plugin's Boot Receiver invoked
→ Recovery logic executed with scenario=BOOT
Recovery Steps
-
Load all schedules from SQLite (
NotificationRepository.getAllSchedules()) -
For each schedule:
- Calculate next runtime based on cron expression
- Compare with current time
-
If the next scheduled time is in the future:
- Recreate alarm with
setAlarmClock - Log:
Rescheduled alarm: <id> for <ts>
- Recreate alarm with
-
If schedule was in the past at boot time:
- Mark as missed
- Schedule next run according to cron rules
-
If no schedules found:
- Quiet exit, log only one line:
BOOT: No schedules found
- Quiet exit, log only one line:
-
Safeties:
- Boot recovery must not modify Plugin Settings
- Must not regenerate Fetcher configuration
- Must not overwrite database records
3. Required Android Components
3.1 Boot Receiver
<receiver
android:name=".BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
3.2 Kotlin Class
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent?) {
if (intent?.action != Intent.ACTION_BOOT_COMPLETED) return
ReactivationManager.runBootRecovery(context)
}
}
4. ReactivationManager – Boot Logic
Method Signature
fun runBootRecovery(context: Context)
Required Logging (canonical)
DNP-REACTIVATION: Starting boot recovery
DNP-REACTIVATION: Loaded <N> schedules from DB
DNP-REACTIVATION: Rescheduled alarm: <id> for <ts>
DNP-REACTIVATION: Marked missed notification: <id>
DNP-REACTIVATION: Boot recovery complete: missed=X, rescheduled=Y, errors=Z
Required Fields
scenario=BOOTmissedrescheduledverifiedMUST BE 0 (boot has no verification phase)
5. Constraints & Guardrails
-
No plugin initialization Boot must not require running the app UI.
-
No heavy processing
- limit to 2 seconds
- use the same timeout guard as Phase 2
-
No scheduling duplicates
- Must detect existing AlarmManager entries
- Boot always clears them, so all reschedules should be fresh
-
App does not need to be opened
- Entire recovery must run in background context
-
Idempotency
- Running twice should produce identical logs
6. Implementation Checklist
Mandatory
- BootReceiver included
- Manifest entry added
runBootRecovery()implemented- Scenario logged as
BOOT - All alarms recreated
- Timeout protection
- No modifications to preferences or plugin settings
Optional
- Additional telemetry for analytics
- Optional debug toast for dev builds only
7. Expected Output Examples
Example 1 – Normal Boot (future alarms exist)
DNP-REACTIVATION: Starting boot recovery
DNP-REACTIVATION: Loaded 2 schedules from DB
DNP-REACTIVATION: Rescheduled alarm: daily_1764233911265 for 1764236120000
DNP-REACTIVATION: Rescheduled alarm: daily_1764233465343 for 1764233700000
DNP-REACTIVATION: Boot recovery complete: missed=0, rescheduled=2, errors=0
Example 2 – Schedules present but some in past
Marked missed notification: daily_1764233300000
Rescheduled alarm: daily_1764233300000 for next day
Example 3 – No schedules
DNP-REACTIVATION: BOOT: No schedules found
8. Status
| Item | Status |
|---|---|
| Directive | Complete |
| Implementation | ☐ Pending / ✅ Complete (plugin v1.2+) |
| Emulator Test Script | Ready (test-phase3.sh) |
| Verification Doc | Ready (PHASE3-VERIFICATION.md) |
9. Related Documentation
- Unified Alarm Directive - Master coordination document
- Plugin Requirements - Requirements this phase implements
- Platform Capability Reference - OS-level facts
- Phase 1 - Prerequisite
- Phase 2 - Prerequisite
- Phase 3 Emulator Testing - Test procedures
- Phase 3 Verification - Verification report
Status: Directive complete, ready for implementation
Last Updated: November 2025