- Add platform capability reference (Android & iOS OS-level facts) - Add plugin behavior exploration template (executable test matrices) - Add plugin requirements & implementation directive - Add Android-specific implementation directive with detailed test procedures - Add exploration findings from code inspection - Add improvement directive for refining documentation structure - Add Android alarm persistence directive (OS capabilities) All documents include: - File locations, function references, and line numbers - Detailed test procedures with ADB commands - Cross-platform comparisons - Implementation checklists and code examples
364 lines
16 KiB
Markdown
364 lines
16 KiB
Markdown
# Plugin Behavior Exploration Template
|
|
|
|
**Author**: Matthew Raymer
|
|
**Date**: November 2025
|
|
**Status**: Active Exploration Template
|
|
|
|
## Purpose
|
|
|
|
This document provides an **executable template** for exploring and documenting the current plugin's alarm/schedule/notification behavior on Android and iOS.
|
|
|
|
**Use this template to**:
|
|
1. Test plugin behavior across different scenarios
|
|
2. Document expected vs actual results
|
|
3. Identify gaps between current behavior and platform capabilities
|
|
4. Generate findings for the Plugin Requirements document
|
|
|
|
**Reference**: See [Platform Capability Reference](./platform-capability-reference.md) for OS-level facts.
|
|
|
|
---
|
|
|
|
## 0. Quick Reference: Platform Capabilities
|
|
|
|
**Android**: See [Platform Capability Reference - Android Section](./platform-capability-reference.md#2-android-alarm-capability-matrix)
|
|
|
|
**iOS**: See [Platform Capability Reference - iOS Section](./platform-capability-reference.md#3-ios-notification-capability-matrix)
|
|
|
|
**Key Differences**:
|
|
* Android: Alarms wiped on reboot; must reschedule
|
|
* iOS: Notifications persist across reboot automatically
|
|
* Android: App code runs when alarm fires
|
|
* iOS: App code does NOT run when notification fires (unless user interacts)
|
|
|
|
---
|
|
|
|
## 1. Android Exploration
|
|
|
|
### 1.1 Code-Level Inspection Checklist
|
|
|
|
**Source Locations**:
|
|
- Plugin: `android/src/main/java/com/timesafari/dailynotification/`
|
|
- Test App: `test-apps/android-test-app/`
|
|
- Manifest: `test-apps/android-test-app/app/src/main/AndroidManifest.xml`
|
|
|
|
| Task | File/Function | Line | Status | Notes |
|
|
| ---- | ------------- | ---- | ------ | ----- |
|
|
| Locate main plugin class | `DailyNotificationPlugin.kt` | 1302 | ☐ | `scheduleDailyNotification()` |
|
|
| Identify alarm scheduling | `NotifyReceiver.kt` | 92 | ☐ | `scheduleExactNotification()` |
|
|
| Check AlarmManager usage | `NotifyReceiver.kt` | 219, 223, 231 | ☐ | `setAlarmClock()`, `setExactAndAllowWhileIdle()`, `setExact()` |
|
|
| Check WorkManager usage | `FetchWorker.kt` | 31 | ☐ | `scheduleFetch()` |
|
|
| Check notification display | `DailyNotificationWorker.java` | 200+ | ☐ | `displayNotification()` |
|
|
| Check boot receiver | `BootReceiver.kt` | 24 | ☐ | `onReceive()` handles `BOOT_COMPLETED` |
|
|
| Check persistence | `DailyNotificationPlugin.kt` | 1393+ | ☐ | Room database storage |
|
|
| Check exact alarm permission | `DailyNotificationPlugin.kt` | 1309 | ☐ | `canScheduleExactAlarms()` |
|
|
| Check manifest permissions | `AndroidManifest.xml` | - | ☐ | `RECEIVE_BOOT_COMPLETED`, `SCHEDULE_EXACT_ALARM` |
|
|
|
|
### 1.2 Behavior Testing Matrix
|
|
|
|
#### Test 1: Base Case
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule alarm 2 minutes in future | - | Alarm scheduled | ☐ | |
|
|
| 2 | Leave app in foreground/background | - | - | ☐ | |
|
|
| 3 | Wait for trigger time | Alarm fires | Notification displayed | ☐ | |
|
|
| 4 | Check logs | - | No errors | ☐ | |
|
|
|
|
**Code Reference**: `NotifyReceiver.scheduleExactNotification()` line 92
|
|
|
|
---
|
|
|
|
#### Test 2: Swipe from Recents
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule alarm 2-5 minutes in future | - | Alarm scheduled | ☐ | |
|
|
| 2 | Swipe app away from recents | - | - | ☐ | |
|
|
| 3 | Wait for trigger time | ✅ Alarm fires (OS resurrects process) | ✅ Notification displayed | ☐ | |
|
|
| 4 | Check app state on wake | Cold start | App process recreated | ☐ | |
|
|
| 5 | Check logs | - | No errors | ☐ | |
|
|
|
|
**Code Reference**: `NotifyReceiver.scheduleExactNotification()` uses `setAlarmClock()` line 219
|
|
|
|
**Platform Behavior**: OS-guaranteed (Android AlarmManager)
|
|
|
|
---
|
|
|
|
#### Test 3: OS Kill (Memory Pressure)
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule alarm 2-5 minutes in future | - | Alarm scheduled | ☐ | |
|
|
| 2 | Force kill via `adb shell am kill <package>` | - | - | ☐ | |
|
|
| 3 | Wait for trigger time | ✅ Alarm fires | ✅ Notification displayed | ☐ | |
|
|
| 4 | Check logs | - | No errors | ☐ | |
|
|
|
|
**Platform Behavior**: OS-guaranteed (Android AlarmManager)
|
|
|
|
---
|
|
|
|
#### Test 4: Device Reboot
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule alarm 10 minutes in future | - | Alarm scheduled | ☐ | |
|
|
| 2 | Reboot device | - | - | ☐ | |
|
|
| 3 | Do NOT open app | ❌ Alarm does NOT fire | ❌ No notification | ☐ | |
|
|
| 4 | Wait past scheduled time | ❌ No automatic firing | ❌ No notification | ☐ | |
|
|
| 5 | Open app manually | - | Plugin detects missed alarm | ☐ | |
|
|
| 6 | Check missed alarm handling | - | ✅ Missed alarm detected | ☐ | |
|
|
| 7 | Check rescheduling | - | ✅ Future alarms rescheduled | ☐ | |
|
|
|
|
**Code Reference**:
|
|
- Boot receiver: `BootReceiver.kt` line 24
|
|
- Rescheduling: `BootReceiver.kt` line 38+
|
|
|
|
**Platform Behavior**: Plugin-guaranteed (must implement boot receiver)
|
|
|
|
**Expected Plugin Behavior**: Plugin must reschedule from database on boot
|
|
|
|
---
|
|
|
|
#### Test 5: Android Force Stop
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule alarm | - | Alarm scheduled | ☐ | |
|
|
| 2 | Go to Settings → Apps → [App] → Force Stop | ❌ All alarms removed | ❌ All alarms removed | ☐ | |
|
|
| 3 | Wait for trigger time | ❌ Alarm does NOT fire | ❌ No notification | ☐ | |
|
|
| 4 | Open app again | - | Plugin detects missed alarm | ☐ | |
|
|
| 5 | Check recovery | - | ✅ Missed alarm detected | ☐ | |
|
|
| 6 | Check rescheduling | - | ✅ Future alarms rescheduled | ☐ | |
|
|
|
|
**Platform Behavior**: Not allowed (Android hard kill)
|
|
|
|
**Expected Plugin Behavior**: Plugin must detect and recover on app restart
|
|
|
|
---
|
|
|
|
#### Test 6: Exact Alarm Permission (Android 12+)
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Revoke exact alarm permission | - | - | ☐ | |
|
|
| 2 | Attempt to schedule alarm | - | Plugin requests permission | ☐ | |
|
|
| 3 | Check settings opened | - | ✅ Settings opened | ☐ | |
|
|
| 4 | Grant permission | - | - | ☐ | |
|
|
| 5 | Schedule alarm | - | ✅ Alarm scheduled | ☐ | |
|
|
| 6 | Verify alarm fires | ✅ Alarm fires | ✅ Notification displayed | ☐ | |
|
|
|
|
**Code Reference**: `DailyNotificationPlugin.kt` line 1309, 1314-1324
|
|
|
|
---
|
|
|
|
### 1.3 Persistence Investigation
|
|
|
|
| Item | Expected | Actual | Code Reference | Notes |
|
|
| ---- | -------- | ------ | -------------- | ----- |
|
|
| Alarm ID stored | ✅ Yes | ☐ | `DailyNotificationPlugin.kt` line 1393+ | |
|
|
| Trigger time stored | ✅ Yes | ☐ | Room database | |
|
|
| Repeat rule stored | ✅ Yes | ☐ | Schedule entity | |
|
|
| Channel/priority stored | ✅ Yes | ☐ | NotificationContentEntity | |
|
|
| Payload stored | ✅ Yes | ☐ | ContentCache | |
|
|
| Time created/modified | ✅ Yes | ☐ | Entity timestamps | |
|
|
|
|
**Storage Location**: Room database (`DailyNotificationDatabase`)
|
|
|
|
---
|
|
|
|
### 1.4 Recovery Points Investigation
|
|
|
|
| Recovery Point | Expected Behavior | Actual Behavior | Code Reference | Notes |
|
|
| -------------- | ----------------- | --------------- | -------------- | ----- |
|
|
| Boot event | ✅ Reschedule all alarms | ☐ | `BootReceiver.kt` line 24 | |
|
|
| App cold start | ✅ Detect missed alarms | ☐ | Check plugin initialization | |
|
|
| App warm start | ✅ Verify active alarms | ☐ | Check plugin initialization | |
|
|
| Background fetch return | ⚠️ May reschedule | ☐ | `FetchWorker.kt` | |
|
|
| User taps notification | ✅ Launch app | ☐ | Notification intent | |
|
|
|
|
---
|
|
|
|
## 2. iOS Exploration
|
|
|
|
### 2.1 Code-Level Inspection Checklist
|
|
|
|
**Source Locations**:
|
|
- Plugin: `ios/Plugin/`
|
|
- Test App: `test-apps/ios-test-app/`
|
|
- Alternative: Check `ios-2` branch
|
|
|
|
| Task | File/Function | Line | Status | Notes |
|
|
| ---- | ------------- | ---- | ------ | ----- |
|
|
| Locate main plugin class | `DailyNotificationPlugin.swift` | 506 | ☐ | `scheduleUserNotification()` |
|
|
| Identify notification scheduling | `DailyNotificationScheduler.swift` | 133 | ☐ | `scheduleNotification()` |
|
|
| Check UNUserNotificationCenter usage | `DailyNotificationScheduler.swift` | 185 | ☐ | `notificationCenter.add()` |
|
|
| Check trigger types | `DailyNotificationScheduler.swift` | 172 | ☐ | `UNCalendarNotificationTrigger` |
|
|
| Check BGTaskScheduler usage | `DailyNotificationPlugin.swift` | 495 | ☐ | `scheduleBackgroundFetch()` |
|
|
| Check persistence | `DailyNotificationPlugin.swift` | 35 | ☐ | `storage: DailyNotificationStorage?` |
|
|
| Check app launch recovery | `DailyNotificationPlugin.swift` | 42 | ☐ | `load()` method |
|
|
|
|
### 2.2 Behavior Testing Matrix
|
|
|
|
#### Test 1: Base Case
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule notification 2-5 minutes in future | - | Notification scheduled | ☐ | |
|
|
| 2 | Leave app backgrounded | - | - | ☐ | |
|
|
| 3 | Wait for trigger time | ✅ Notification fires | ✅ Notification displayed | ☐ | |
|
|
| 4 | Check logs | - | No errors | ☐ | |
|
|
|
|
**Code Reference**: `DailyNotificationScheduler.scheduleNotification()` line 133
|
|
|
|
---
|
|
|
|
#### Test 2: Swipe App Away
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule notification 2-5 minutes in future | - | Notification scheduled | ☐ | |
|
|
| 2 | Swipe app away from app switcher | - | - | ☐ | |
|
|
| 3 | Wait for trigger time | ✅ Notification fires (OS handles) | ✅ Notification displayed | ☐ | |
|
|
| 4 | Check app state | App terminated | App not running | ☐ | |
|
|
|
|
**Platform Behavior**: OS-guaranteed (iOS UNUserNotificationCenter)
|
|
|
|
---
|
|
|
|
#### Test 3: Device Reboot
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule notification for future time | - | Notification scheduled | ☐ | |
|
|
| 2 | Reboot device | - | - | ☐ | |
|
|
| 3 | Do NOT open app | ✅ Notification fires (OS persists) | ✅ Notification displayed | ☐ | |
|
|
| 4 | Check notification timing | ✅ On time (±180s tolerance) | ✅ On time | ☐ | |
|
|
|
|
**Platform Behavior**: OS-guaranteed (iOS persists calendar/time triggers)
|
|
|
|
**Note**: Only calendar and time-based triggers persist. Location triggers do not.
|
|
|
|
---
|
|
|
|
#### Test 4: Hard Termination & Relaunch
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule repeating notifications | - | Notifications scheduled | ☐ | |
|
|
| 2 | Terminate app via Xcode/switcher | - | - | ☐ | |
|
|
| 3 | Allow some triggers to occur | ✅ Notifications fire | ✅ Notifications displayed | ☐ | |
|
|
| 4 | Reopen app | - | Plugin checks for missed events | ☐ | |
|
|
| 5 | Check missed event detection | ⚠️ May detect | ☐ | Plugin-specific |
|
|
| 6 | Check state recovery | ⚠️ May recover | ☐ | Plugin-specific |
|
|
|
|
**Platform Behavior**: OS-guaranteed for notifications; Plugin-guaranteed for missed event detection
|
|
|
|
---
|
|
|
|
#### Test 5: Background Execution Limits
|
|
|
|
| Step | Action | Expected (OS) | Expected (Plugin) | Actual Result | Notes |
|
|
| ---- | ------ | ------------- | ------------------ | ------------- | ----- |
|
|
| 1 | Schedule BGTaskScheduler task | - | Task scheduled | ☐ | |
|
|
| 2 | Wait for system to execute | ⚠️ System-controlled | ⚠️ May not execute | ☐ | |
|
|
| 3 | Check execution timing | ⚠️ Not guaranteed | ⚠️ Not guaranteed | ☐ | |
|
|
| 4 | Check time budget | ⚠️ ~30 seconds | ⚠️ Limited time | ☐ | |
|
|
|
|
**Code Reference**: `DailyNotificationPlugin.scheduleBackgroundFetch()` line 495
|
|
|
|
**Platform Behavior**: System-controlled (not guaranteed)
|
|
|
|
---
|
|
|
|
### 2.3 Persistence Investigation
|
|
|
|
| Item | Expected | Actual | Code Reference | Notes |
|
|
| ---- | -------- | ------ | -------------- | ----- |
|
|
| Notification ID stored | ✅ Yes (in UNUserNotificationCenter) | ☐ | `UNNotificationRequest` | |
|
|
| Plugin-side storage | ⚠️ May not exist | ☐ | `DailyNotificationStorage?` | |
|
|
| Trigger time stored | ✅ Yes (in trigger) | ☐ | `UNCalendarNotificationTrigger` | |
|
|
| Repeat rule stored | ✅ Yes (in trigger) | ☐ | `repeats: true/false` | |
|
|
| Payload stored | ✅ Yes (in userInfo) | ☐ | `notificationContent.userInfo` | |
|
|
|
|
**Storage Location**:
|
|
- Primary: UNUserNotificationCenter (OS-managed)
|
|
- Secondary: Plugin storage (if implemented)
|
|
|
|
---
|
|
|
|
### 2.4 Recovery Points Investigation
|
|
|
|
| Recovery Point | Expected Behavior | Actual Behavior | Code Reference | Notes |
|
|
| -------------- | ----------------- | --------------- | -------------- | ----- |
|
|
| Boot event | ✅ Notifications fire automatically | ☐ | OS handles | |
|
|
| App cold start | ⚠️ May detect missed notifications | ☐ | Check `load()` method | |
|
|
| App warm start | ⚠️ May verify pending notifications | ☐ | Check plugin initialization | |
|
|
| Background fetch | ⚠️ May reschedule | ☐ | `BGTaskScheduler` | |
|
|
| User taps notification | ✅ App launched | ☐ | Notification action | |
|
|
|
|
---
|
|
|
|
## 3. Cross-Platform Comparison
|
|
|
|
### 3.1 Observed Behavior Summary
|
|
|
|
| Scenario | Android (Observed) | iOS (Observed) | Platform Difference |
|
|
| -------- | ------------------ | -------------- | ------------------- |
|
|
| Swipe/termination | ☐ | ☐ | Both should work |
|
|
| Reboot | ☐ | ☐ | iOS auto, Android manual |
|
|
| Force stop | ☐ | N/A | Android only |
|
|
| App code on trigger | ☐ | ☐ | Android yes, iOS no |
|
|
| Background execution | ☐ | ☐ | Android more flexible |
|
|
|
|
---
|
|
|
|
## 4. Findings & Gaps
|
|
|
|
### 4.1 Android Gaps
|
|
|
|
| Gap | Severity | Description | Recommendation |
|
|
| --- | -------- | ----------- | -------------- |
|
|
| Boot recovery | ☐ High/Medium/Low | Does plugin reschedule on boot? | Implement if missing |
|
|
| Missed alarm detection | ☐ High/Medium/Low | Does plugin detect missed alarms? | Implement if missing |
|
|
| Force stop recovery | ☐ High/Medium/Low | Does plugin recover after force stop? | Implement if missing |
|
|
| Persistence completeness | ☐ High/Medium/Low | Are all required fields persisted? | Verify and add if missing |
|
|
|
|
### 4.2 iOS Gaps
|
|
|
|
| Gap | Severity | Description | Recommendation |
|
|
| --- | -------- | ----------- | -------------- |
|
|
| Missed notification detection | ☐ High/Medium/Low | Does plugin detect missed notifications? | Implement if missing |
|
|
| Plugin-side persistence | ☐ High/Medium/Low | Does plugin persist state separately? | Consider if needed |
|
|
| Background task reliability | ☐ High/Medium/Low | Can plugin rely on BGTaskScheduler? | Document limitations |
|
|
|
|
---
|
|
|
|
## 5. Deliverables from This Exploration
|
|
|
|
After completing this exploration, generate:
|
|
|
|
1. **ALARMS_BEHAVIOR_MATRIX.md** - Completed test results
|
|
2. **PLUGIN_ALARM_LIMITATIONS.md** - Documented limitations and gaps
|
|
3. **Annotated code pointers** - Code locations with findings
|
|
4. **Open Questions / TODOs** - Unresolved issues
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [Platform Capability Reference](./platform-capability-reference.md) - OS-level facts
|
|
- [Plugin Requirements & Implementation](./plugin-requirements-implementation.md) - Requirements based on findings
|
|
- [Improve Alarm Directives](./improve-alarm-directives.md) - Improvement directive
|
|
|
|
---
|
|
|
|
## Notes for Explorers
|
|
|
|
* Fill in checkboxes (☐) as you complete each test
|
|
* Document actual results in "Actual Result" columns
|
|
* Add notes for any unexpected behavior
|
|
* Reference code locations when documenting findings
|
|
* Update "Findings & Gaps" section as you discover issues
|
|
* Use platform capability reference to understand expected OS behavior
|
|
|