Browse Source

docs: apply precise fixes for correctness, consistency, and sprintability

Analysis doc improvements:
- Unify runtime naming: fix tree diagram cordova.js → capacitor.js
- Make manifest receivers explicit: add exported attributes and intent filters
- Surface exact-alarm user rule: add decision rule for QA/ops reasoning
- Guard Cordova dependency: add note about Cordova shims requirement
- Add error surfacing to runtime flow: show validation and use-case error paths
- Add auto-generated note to capacitor.plugins.json section

Implementation plan improvements:
- Add diagnostics button to Phase 1 DoD
- Add Doze/Idle case to Test Matrix for false negative prevention
- Make unknown field rejection explicit acceptance criterion
- Link receivers export policy to Manifest Hygiene checklist
- Add event ID requirement to PR checklist for grep-able logs

All changes maintain existing structure with surgical precision edits.
master
Matthew Raymer 2 days ago
parent
commit
6eb5d63107
  1. 70
      docs/android-app-analysis.md
  2. 6
      docs/android-app-improvement-plan.md

70
docs/android-app-analysis.md

@ -30,6 +30,7 @@ The `/android/app` directory contains a **Capacitor-based Android test applicati
4. **Documentation**: Live demonstration of plugin capabilities 4. **Documentation**: Live demonstration of plugin capabilities
### Architecture Pattern ### Architecture Pattern
``` ```
┌─────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────┐
│ Android App Container │ │ Android App Container │
@ -55,6 +56,7 @@ The `/android/app` directory contains a **Capacitor-based Android test applicati
## Directory Structure ## Directory Structure
### Root Android App Structure ### Root Android App Structure
``` ```
android/app/ android/app/
├── build.gradle # App build configuration ├── build.gradle # App build configuration
@ -68,8 +70,8 @@ android/app/
│ │ ├── capacitor.plugins.json │ │ ├── capacitor.plugins.json
│ │ └── public/ # Web application files │ │ └── public/ # Web application files
│ │ ├── index.html # Main test interface │ │ ├── index.html # Main test interface
│ │ ├── cordova.js # Capacitor runtime │ │ ├── capacitor.js # Capacitor runtime
│ │ ├── cordova_plugins.js │ │ ├── capacitor_plugins.js
│ │ └── plugins/ # Plugin JavaScript files │ │ └── plugins/ # Plugin JavaScript files
│ ├── java/ │ ├── java/
│ │ └── com/timesafari/dailynotification/ │ │ └── com/timesafari/dailynotification/
@ -87,6 +89,7 @@ android/app/
## Key Components ## Key Components
### 1. MainActivity.java ### 1. MainActivity.java
**Purpose**: Entry point extending Capacitor's BridgeActivity **Purpose**: Entry point extending Capacitor's BridgeActivity
**Location**: `src/main/java/com/timesafari/dailynotification/MainActivity.java` **Location**: `src/main/java/com/timesafari/dailynotification/MainActivity.java`
@ -100,16 +103,19 @@ public class MainActivity extends BridgeActivity {
``` ```
**Key Features**: **Key Features**:
- Minimal implementation - Capacitor handles most functionality - Minimal implementation - Capacitor handles most functionality
- Extends `BridgeActivity` for automatic plugin discovery - Extends `BridgeActivity` for automatic plugin discovery
- Provides WebView container for web assets - Provides WebView container for web assets
- Handles plugin registration and JavaScript bridge - Handles plugin registration and JavaScript bridge
### 2. AndroidManifest.xml ### 2. AndroidManifest.xml
**Purpose**: App configuration, permissions, and component declarations **Purpose**: App configuration, permissions, and component declarations
**Location**: `src/main/AndroidManifest.xml` **Location**: `src/main/AndroidManifest.xml`
**Key Declarations**: **Key Declarations**:
```xml ```xml
<!-- App Configuration --> <!-- App Configuration -->
<application android:name="com.timesafari.dailynotification"> <application android:name="com.timesafari.dailynotification">
@ -121,8 +127,23 @@ public class MainActivity extends BridgeActivity {
</activity> </activity>
<!-- Plugin Components --> <!-- Plugin Components -->
<receiver android:name="com.timesafari.dailynotification.DailyNotificationReceiver" /> <receiver
<receiver android:name="com.timesafari.dailynotification.BootReceiver" /> android:name="com.timesafari.dailynotification.DailyNotificationReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.timesafari.daily.NOTIFICATION" />
</intent-filter>
</receiver>
<receiver
android:name="com.timesafari.dailynotification.BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application> </application>
<!-- Required Permissions --> <!-- Required Permissions -->
@ -134,6 +155,7 @@ public class MainActivity extends BridgeActivity {
``` ```
**Critical Permissions**: **Critical Permissions**:
- `POST_NOTIFICATIONS`: Required for Android 13+ notification posting - `POST_NOTIFICATIONS`: Required for Android 13+ notification posting
- `SCHEDULE_EXACT_ALARM`: Required for precise notification timing - `SCHEDULE_EXACT_ALARM`: Required for precise notification timing
- `WAKE_LOCK`: Required for background processing - `WAKE_LOCK`: Required for background processing
@ -143,7 +165,9 @@ public class MainActivity extends BridgeActivity {
### 3. Capacitor Configuration Files ### 3. Capacitor Configuration Files
#### capacitor.config.json #### capacitor.config.json
**Purpose**: Capacitor runtime configuration **Purpose**: Capacitor runtime configuration
```json ```json
{ {
"appId": "com.timesafari.dailynotification", "appId": "com.timesafari.dailynotification",
@ -164,7 +188,10 @@ public class MainActivity extends BridgeActivity {
``` ```
#### capacitor.plugins.json #### capacitor.plugins.json
**Purpose**: Plugin discovery and registration **Purpose**: Plugin discovery and registration
**Note**: Auto-generated on `npx cap sync` - should not be manually edited
```json ```json
[ [
{ {
@ -177,6 +204,7 @@ public class MainActivity extends BridgeActivity {
## Web Asset Integration ## Web Asset Integration
### /www Directory Structure ### /www Directory Structure
The `/www` directory (mapped to `assets/public/`) contains the web application that runs inside the Capacitor WebView: The `/www` directory (mapped to `assets/public/`) contains the web application that runs inside the Capacitor WebView:
``` ```
@ -196,12 +224,14 @@ assets/public/
**Features**: **Features**:
#### 1. User Interface #### 1. User Interface
- **Modern Design**: Gradient background, responsive layout - **Modern Design**: Gradient background, responsive layout
- **Interactive Buttons**: 12 test functions with visual feedback - **Interactive Buttons**: 12 test functions with visual feedback
- **Status Display**: Real-time feedback with color-coded results - **Status Display**: Real-time feedback with color-coded results
- **Mobile-Optimized**: Touch-friendly interface - **Mobile-Optimized**: Touch-friendly interface
#### 2. Test Categories #### 2. Test Categories
```javascript ```javascript
// Plugin Testing // Plugin Testing
- testPlugin() // Basic plugin availability - testPlugin() // Basic plugin availability
@ -225,6 +255,7 @@ assets/public/
``` ```
#### 3. Plugin Integration #### 3. Plugin Integration
```javascript ```javascript
// Plugin Access Pattern // Plugin Access Pattern
window.DailyNotification = window.Capacitor.Plugins.DailyNotification; window.DailyNotification = window.Capacitor.Plugins.DailyNotification;
@ -240,6 +271,7 @@ window.DailyNotification.scheduleDailyNotification({
``` ```
#### 4. Error Handling #### 4. Error Handling
- **Visual Feedback**: Color-coded status indicators - **Visual Feedback**: Color-coded status indicators
- **Error Messages**: Detailed error reporting - **Error Messages**: Detailed error reporting
- **Graceful Degradation**: Fallback behavior for missing features - **Graceful Degradation**: Fallback behavior for missing features
@ -247,15 +279,18 @@ window.DailyNotification.scheduleDailyNotification({
## Plugin Integration ## Plugin Integration
### Plugin Discovery Process ### Plugin Discovery Process
1. **Capacitor Startup**: Loads `capacitor.plugins.json` 1. **Capacitor Startup**: Loads `capacitor.plugins.json`
2. **Plugin Registration**: Discovers `DailyNotificationPlugin` class 2. **Plugin Registration**: Discovers `DailyNotificationPlugin` class
3. **JavaScript Bridge**: Creates `window.Capacitor.Plugins.DailyNotification` 3. **JavaScript Bridge**: Creates `window.Capacitor.Plugins.DailyNotification`
4. **Method Exposure**: Exposes `@PluginMethod` annotated methods 4. **Method Exposure**: Exposes `@PluginMethod` annotated methods
### Plugin Class Structure ### Plugin Class Structure
**Location**: `android/plugin/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.java` **Location**: `android/plugin/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.java`
**Key Methods** (from `@PluginMethod` annotations): **Key Methods** (from `@PluginMethod` annotations):
```java ```java
@PluginMethod @PluginMethod
public void configure(PluginCall call) { ... } public void configure(PluginCall call) { ... }
@ -289,15 +324,18 @@ public void openExactAlarmSettings(PluginCall call) { ... }
``` ```
### Supporting Classes (34 files) ### Supporting Classes (34 files)
The plugin includes a comprehensive set of supporting classes: The plugin includes a comprehensive set of supporting classes:
**Core Components**: **Core Components**:
- `BootReceiver.java` - Handles system boot events - `BootReceiver.java` - Handles system boot events
- `DailyNotificationReceiver.java` - Handles notification events - `DailyNotificationReceiver.java` - Handles notification events
- `DailyNotificationScheduler.java` - Manages notification scheduling - `DailyNotificationScheduler.java` - Manages notification scheduling
- `DailyNotificationFetcher.java` - Handles content fetching - `DailyNotificationFetcher.java` - Handles content fetching
**Storage & Database**: **Storage & Database**:
- `DailyNotificationStorage.java` - Storage abstraction - `DailyNotificationStorage.java` - Storage abstraction
- `DailyNotificationStorageRoom.java` - Room database implementation - `DailyNotificationStorageRoom.java` - Room database implementation
- `DailyNotificationDatabase.java` - Database definition - `DailyNotificationDatabase.java` - Database definition
@ -305,6 +343,7 @@ The plugin includes a comprehensive set of supporting classes:
- `entities/` - Database entities (3 files) - `entities/` - Database entities (3 files)
**Management & Utilities**: **Management & Utilities**:
- `PermissionManager.java` - Permission handling - `PermissionManager.java` - Permission handling
- `ChannelManager.java` - Notification channel management - `ChannelManager.java` - Notification channel management
- `DailyNotificationExactAlarmManager.java` - Exact alarm management - `DailyNotificationExactAlarmManager.java` - Exact alarm management
@ -312,6 +351,7 @@ The plugin includes a comprehensive set of supporting classes:
- `DailyNotificationPerformanceOptimizer.java` - Performance optimization - `DailyNotificationPerformanceOptimizer.java` - Performance optimization
**Workers & Background Tasks**: **Workers & Background Tasks**:
- `DailyNotificationWorker.java` - Main background worker - `DailyNotificationWorker.java` - Main background worker
- `DailyNotificationFetchWorker.java` - Content fetching worker - `DailyNotificationFetchWorker.java` - Content fetching worker
- `DailyNotificationMaintenanceWorker.java` - Maintenance tasks - `DailyNotificationMaintenanceWorker.java` - Maintenance tasks
@ -321,9 +361,11 @@ The plugin includes a comprehensive set of supporting classes:
## Build Configuration ## Build Configuration
### app/build.gradle ### app/build.gradle
**Purpose**: App-level build configuration and dependencies **Purpose**: App-level build configuration and dependencies
**Key Dependencies**: **Key Dependencies**:
```gradle ```gradle
dependencies { dependencies {
// Capacitor Core // Capacitor Core
@ -340,12 +382,13 @@ dependencies {
implementation "androidx.work:work-runtime-ktx:2.9.0" implementation "androidx.work:work-runtime-ktx:2.9.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
// Cordova Compatibility // Cordova Compatibility (only if shipping Cordova shims)
implementation project(':capacitor-cordova-android-plugins') implementation project(':capacitor-cordova-android-plugins')
} }
``` ```
**Build Configuration**: **Build Configuration**:
```gradle ```gradle
android { android {
namespace "com.timesafari.dailynotification" namespace "com.timesafari.dailynotification"
@ -362,10 +405,12 @@ android {
``` ```
### capacitor.build.gradle ### capacitor.build.gradle
**Purpose**: Auto-generated Capacitor configuration **Purpose**: Auto-generated Capacitor configuration
**Note**: Regenerated on each `npx cap sync` - should not be manually edited **Note**: Regenerated on each `npx cap sync` - should not be manually edited
**Manifest Hygiene (Quick Scan)** **Manifest Hygiene (Quick Scan)**
- [ ] `<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>` - [ ] `<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>`
- [ ] `<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>` (if you truly need exact) - [ ] `<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM"/>` (if you truly need exact)
- [ ] `<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>` - [ ] `<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>`
@ -376,6 +421,7 @@ android {
## Runtime Behavior ## Runtime Behavior
### App Startup Sequence ### App Startup Sequence
1. **Android System**: Launches `MainActivity` 1. **Android System**: Launches `MainActivity`
2. **Capacitor Initialization**: Loads Capacitor runtime 2. **Capacitor Initialization**: Loads Capacitor runtime
3. **Plugin Discovery**: Scans `capacitor.plugins.json` for plugins 3. **Plugin Discovery**: Scans `capacitor.plugins.json` for plugins
@ -385,6 +431,7 @@ android {
7. **Plugin Availability**: `window.Capacitor.Plugins.DailyNotification` becomes available 7. **Plugin Availability**: `window.Capacitor.Plugins.DailyNotification` becomes available
### Plugin Method Execution Flow ### Plugin Method Execution Flow
``` ```
JavaScript Call JavaScript Call
@ -400,6 +447,7 @@ JavaScript Promise Resolution
``` ```
### Background Processing ### Background Processing
- **WorkManager**: Handles background content fetching - **WorkManager**: Handles background content fetching
- **AlarmManager**: Manages notification scheduling - **AlarmManager**: Manages notification scheduling
- **BootReceiver**: Reschedules notifications after reboot - **BootReceiver**: Reschedules notifications after reboot
@ -408,14 +456,17 @@ JavaScript Promise Resolution
## Testing Capabilities ## Testing Capabilities
### Interactive Testing Features ### Interactive Testing Features
The test app provides comprehensive testing capabilities: The test app provides comprehensive testing capabilities:
#### 1. Plugin Availability Testing #### 1. Plugin Availability Testing
- **Basic Detection**: Verify plugin is loaded and accessible - **Basic Detection**: Verify plugin is loaded and accessible
- **Method Availability**: Check if specific methods are callable - **Method Availability**: Check if specific methods are callable
- **Error Handling**: Test error conditions and edge cases - **Error Handling**: Test error conditions and edge cases
#### 2. Notification Testing #### 2. Notification Testing
- **Immediate Notifications**: Test instant notification display - **Immediate Notifications**: Test instant notification display
- **Scheduled Notifications**: Test time-based notification scheduling - **Scheduled Notifications**: Test time-based notification scheduling
- **Reminder Testing**: Test daily reminder functionality - **Reminder Testing**: Test daily reminder functionality
@ -545,6 +596,10 @@ This architecture serves as both a practical testing tool and a reference implem
**Status Matrix MUST include:** `postNotificationsGranted`, `exactAlarmGranted`, `channelEnabled`, `batteryOptimizationsIgnored`, `canScheduleNow`. **Status Matrix MUST include:** `postNotificationsGranted`, `exactAlarmGranted`, `channelEnabled`, `batteryOptimizationsIgnored`, `canScheduleNow`.
### Exact-Alarm Decision Rule (User-Visible)
If `SCHEDULE_EXACT_ALARM` is **granted** → schedule with `setExactAndAllowWhileIdle`.
If **denied or quota-limited** → schedule via WorkManager (exp backoff + jitter) and surface `E_EXACT_ALARM_DENIED` (with "Degraded timing — Doze may delay" hint).
## Permission & Settings Truth Table ## Permission & Settings Truth Table
| Symptom | Likely Cause | Action | | Symptom | Likely Cause | Action |
@ -569,6 +624,11 @@ graph TD
G --> H G --> H
H --> I[NotificationReceiver] H --> I[NotificationReceiver]
I --> J[UI Update] I --> J[UI Update]
%% Error paths
C -->|Validation Error| K[Canonical Error]
D -->|Use-case Error| K
K --> L[JavaScript Promise Rejection]
``` ```
## Cordova vs Capacitor Assets – Accuracy Note ## Cordova vs Capacitor Assets – Accuracy Note

6
docs/android-app-improvement-plan.md

@ -532,7 +532,7 @@ public class SecureNetworkClient {
``` ```
#### Key Features #### Key Features
- **Export Control**: Minimize exported components - **Export Control**: Minimize exported components (see Manifest Hygiene checklist)
- **Permission Requirements**: Require permissions for exported components - **Permission Requirements**: Require permissions for exported components
- **Intent Validation**: Validate incoming intents - **Intent Validation**: Validate incoming intents
- **Security Review**: Regular security audits - **Security Review**: Regular security audits
@ -862,6 +862,7 @@ interface ScheduleResponse {
- [ ] Returns stable error codes with hints - [ ] Returns stable error codes with hints
- [ ] Maps native exceptions to canonical errors - [ ] Maps native exceptions to canonical errors
- [ ] Provides user-friendly error messages - [ ] Provides user-friendly error messages
- [ ] Rejects unknown keys with single joined message
### Reliability ### Reliability
- [ ] Reboot scenarios reliably deliver notifications - [ ] Reboot scenarios reliably deliver notifications
@ -916,6 +917,7 @@ By following this plan, the test app will become more maintainable, reliable, an
- Input schema rejects bad `time`, long `title/body`, wrong `priority`. - Input schema rejects bad `time`, long `title/body`, wrong `priority`.
- Boot reschedule idempotent (no dup rows, migration fence). - Boot reschedule idempotent (no dup rows, migration fence).
- @PluginMethod bodies ≤ 25 LOC, delegate to use-cases. - @PluginMethod bodies ≤ 25 LOC, delegate to use-cases.
- "Copy Diagnostics (JSON)" button functional.
### Phase 2 DoD ### Phase 2 DoD
- Test UI split into modular scenarios with fixtures. - Test UI split into modular scenarios with fixtures.
@ -942,6 +944,7 @@ By following this plan, the test app will become more maintainable, reliable, an
- [ ] Logs include event IDs (start/finish/error) - [ ] Logs include event IDs (start/finish/error)
- [ ] Status Matrix field(s) updated if capability changed - [ ] Status Matrix field(s) updated if capability changed
- [ ] Runbooks section touched if behavior changed - [ ] Runbooks section touched if behavior changed
- [ ] No new events without ID (keeps logs grep-able)
## Test Matrix ## Test Matrix
@ -951,6 +954,7 @@ By following this plan, the test app will become more maintainable, reliable, an
| Channel disabled path | isChannelEnabled/openChannelSettings | Disable channel | Canonical `E_CHANNEL_DISABLED` | | Channel disabled path | isChannelEnabled/openChannelSettings | Disable channel | Canonical `E_CHANNEL_DISABLED` |
| Exact alarm denied path | openExactAlarmSettings | Revoke exact alarm | Fallback path taken; logged `DOZE_FALLBACK` | | Exact alarm denied path | openExactAlarmSettings | Revoke exact alarm | Fallback path taken; logged `DOZE_FALLBACK` |
| Boot reschedule | BootReceiver | Reboot emulator | One (not duplicate) schedule restored | | Boot reschedule | BootReceiver | Reboot emulator | One (not duplicate) schedule restored |
| Doze idle window | scheduleDailyNotification | Device in idle | Fallback path taken; logged `EVT_DOZE_FALLBACK_TAKEN`; no crash |
## Error Codes (canonical) ## Error Codes (canonical)

Loading…
Cancel
Save