21 KiB
Android App Analysis: DailyNotification Plugin Test App
Author: Matthew Raymer
Date: 2025-10-24
Version: 1.0.0
Overview
This document provides a comprehensive analysis of the /android/app portion of the DailyNotification plugin, examining its structure, purpose, and interaction with the /www web assets. This analysis is designed to help understand the plugin's test application architecture and provide context for ChatGPT analysis.
Table of Contents
- Architecture Overview
- Directory Structure
- Key Components
- Web Asset Integration
- Plugin Integration
- Build Configuration
- Runtime Behavior
- Testing Capabilities
Architecture Overview
Purpose
The /android/app directory contains a Capacitor-based Android test application specifically designed to test and demonstrate the DailyNotification plugin functionality. It serves as:
- Plugin Testing Environment: Interactive testing interface for all plugin features
- Development Tool: Real-time debugging and validation of plugin behavior
- Integration Example: Reference implementation for plugin integration
- Documentation: Live demonstration of plugin capabilities
Architecture Pattern
┌─────────────────────────────────────────────────────────────┐
│ Android App Container │
├─────────────────────────────────────────────────────────────┤
│ MainActivity (BridgeActivity) │
│ ├── Capacitor Bridge │
│ ├── Plugin Discovery │
│ └── WebView Container │
├─────────────────────────────────────────────────────────────┤
│ Web Assets (/www) │
│ ├── index.html (Test Interface) │
│ ├── capacitor.js (Capacitor Runtime) │
│ └── plugins/ (Plugin JavaScript) │
├─────────────────────────────────────────────────────────────┤
│ Native Plugin Integration │
│ ├── DailyNotificationPlugin.java │
│ ├── BootReceiver.java │
│ ├── DailyNotificationReceiver.java │
│ └── Supporting Classes (34 files) │
└─────────────────────────────────────────────────────────────┘
Directory Structure
Root Android App Structure
android/app/
├── build.gradle # App build configuration
├── capacitor.build.gradle # Auto-generated Capacitor config
├── proguard-rules.pro # Code obfuscation rules
└── src/
├── main/
│ ├── AndroidManifest.xml # App permissions and components
│ ├── assets/ # Web assets (Capacitor www)
│ │ ├── capacitor.config.json
│ │ ├── capacitor.plugins.json
│ │ └── public/ # Web application files
│ │ ├── index.html # Main test interface
│ │ ├── cordova.js # Capacitor runtime
│ │ ├── cordova_plugins.js
│ │ └── plugins/ # Plugin JavaScript files
│ ├── java/
│ │ └── com/timesafari/dailynotification/
│ │ └── MainActivity.java # Capacitor BridgeActivity
│ └── res/ # Android resources
│ ├── drawable/ # App icons and images
│ ├── layout/ # Android layouts
│ ├── mipmap/ # App launcher icons
│ ├── values/ # Strings, styles, colors
│ └── xml/ # Configuration files
├── androidTest/ # Instrumented tests
└── test/ # Unit tests
Key Components
1. MainActivity.java
Purpose: Entry point extending Capacitor's BridgeActivity
Location: src/main/java/com/timesafari/dailynotification/MainActivity.java
public class MainActivity extends BridgeActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}
Key Features:
- Minimal implementation - Capacitor handles most functionality
- Extends
BridgeActivityfor automatic plugin discovery - Provides WebView container for web assets
- Handles plugin registration and JavaScript bridge
2. AndroidManifest.xml
Purpose: App configuration, permissions, and component declarations
Location: src/main/AndroidManifest.xml
Key Declarations:
<!-- App Configuration -->
<application android:name="com.timesafari.dailynotification">
<activity android:name=".MainActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Plugin Components -->
<receiver android:name="com.timesafari.dailynotification.DailyNotificationReceiver" />
<receiver android:name="com.timesafari.dailynotification.BootReceiver" />
</application>
<!-- Required Permissions -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
Critical Permissions:
POST_NOTIFICATIONS: Required for Android 13+ notification postingSCHEDULE_EXACT_ALARM: Required for precise notification timingWAKE_LOCK: Required for background processingINTERNET: Required for content fetchingRECEIVE_BOOT_COMPLETED: Required for reboot recovery
3. Capacitor Configuration Files
capacitor.config.json
Purpose: Capacitor runtime configuration
{
"appId": "com.timesafari.dailynotification",
"appName": "DailyNotification Test App",
"webDir": "www",
"server": {
"androidScheme": "https"
},
"plugins": {
"DailyNotification": {
"fetchUrl": "https://api.example.com/daily-content",
"scheduleTime": "09:00",
"enableNotifications": true,
"debugMode": true
}
}
}
capacitor.plugins.json
Purpose: Plugin discovery and registration
[
{
"name": "DailyNotification",
"classpath": "com.timesafari.dailynotification.DailyNotificationPlugin"
}
]
Web Asset Integration
/www Directory Structure
The /www directory (mapped to assets/public/) contains the web application that runs inside the Capacitor WebView:
assets/public/
├── index.html # Main test interface (549 lines)
├── capacitor.js # Capacitor runtime
├── capacitor_plugins.js # Plugin JavaScript bridge
└── plugins/ # Plugin JavaScript files
index.html Analysis
Purpose: Interactive test interface for plugin functionality Size: 549 lines of HTML, CSS, and JavaScript Features:
1. User Interface
- Modern Design: Gradient background, responsive layout
- Interactive Buttons: 12 test functions with visual feedback
- Status Display: Real-time feedback with color-coded results
- Mobile-Optimized: Touch-friendly interface
2. Test Categories
// Plugin Testing
- testPlugin() // Basic plugin availability
- configurePlugin() // Plugin configuration
- checkStatus() // Plugin status check
// Notification Testing
- testNotification() // Immediate notification test
- scheduleNotification() // Scheduled notification test
- showReminder() // Daily reminder test
// Permission Management
- checkPermissions() // Permission status check
- requestPermissions() // Permission request
- openExactAlarmSettings() // Settings navigation
// Channel Management
- checkChannelStatus() // Notification channel status
- openChannelSettings() // Channel settings navigation
- checkComprehensiveStatus() // Complete status check
3. Plugin Integration
// Plugin Access Pattern
window.DailyNotification = window.Capacitor.Plugins.DailyNotification;
// Example Usage
window.DailyNotification.scheduleDailyNotification({
time: "09:00",
title: "Test Notification",
body: "This is a test notification!",
sound: true,
priority: "high"
});
4. Error Handling
- Visual Feedback: Color-coded status indicators
- Error Messages: Detailed error reporting
- Graceful Degradation: Fallback behavior for missing features
Plugin Integration
Plugin Discovery Process
- Capacitor Startup: Loads
capacitor.plugins.json - Plugin Registration: Discovers
DailyNotificationPluginclass - JavaScript Bridge: Creates
window.Capacitor.Plugins.DailyNotification - Method Exposure: Exposes
@PluginMethodannotated methods
Plugin Class Structure
Location: android/plugin/src/main/java/com/timesafari/dailynotification/DailyNotificationPlugin.java
Key Methods (from @PluginMethod annotations):
@PluginMethod
public void configure(PluginCall call) { ... }
@PluginMethod
public void scheduleDailyNotification(PluginCall call) { ... }
@PluginMethod
public void scheduleDailyReminder(PluginCall call) { ... }
@PluginMethod
public void getNotificationStatus(PluginCall call) { ... }
@PluginMethod
public void checkPermissionStatus(PluginCall call) { ... }
@PluginMethod
public void requestNotificationPermissions(PluginCall call) { ... }
@PluginMethod
public void checkStatus(PluginCall call) { ... }
@PluginMethod
public void isChannelEnabled(PluginCall call) { ... }
@PluginMethod
public void openChannelSettings(PluginCall call) { ... }
@PluginMethod
public void openExactAlarmSettings(PluginCall call) { ... }
Supporting Classes (34 files)
The plugin includes a comprehensive set of supporting classes:
Core Components:
BootReceiver.java- Handles system boot eventsDailyNotificationReceiver.java- Handles notification eventsDailyNotificationScheduler.java- Manages notification schedulingDailyNotificationFetcher.java- Handles content fetching
Storage & Database:
DailyNotificationStorage.java- Storage abstractionDailyNotificationStorageRoom.java- Room database implementationDailyNotificationDatabase.java- Database definitiondao/- Data Access Objects (3 files)entities/- Database entities (3 files)
Management & Utilities:
PermissionManager.java- Permission handlingChannelManager.java- Notification channel managementDailyNotificationExactAlarmManager.java- Exact alarm managementDailyNotificationErrorHandler.java- Error handlingDailyNotificationPerformanceOptimizer.java- Performance optimization
Workers & Background Tasks:
DailyNotificationWorker.java- Main background workerDailyNotificationFetchWorker.java- Content fetching workerDailyNotificationMaintenanceWorker.java- Maintenance tasksDozeFallbackWorker.java- Doze mode handlingSoftRefetchWorker.java- Soft refresh handling
Build Configuration
app/build.gradle
Purpose: App-level build configuration and dependencies
Key Dependencies:
dependencies {
// Capacitor Core
implementation project(':capacitor-android')
implementation project(':plugin') // DailyNotification plugin
// AndroidX Libraries
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
// Plugin-Specific Dependencies
implementation "androidx.room:room-runtime:2.6.1"
implementation "androidx.work:work-runtime-ktx:2.9.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
// Cordova Compatibility
implementation project(':capacitor-cordova-android-plugins')
}
Build Configuration:
android {
namespace "com.timesafari.dailynotification"
compileSdkVersion rootProject.ext.compileSdkVersion
defaultConfig {
applicationId "com.timesafari.dailynotification"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
}
}
capacitor.build.gradle
Purpose: Auto-generated Capacitor configuration
Note: Regenerated on each npx cap sync - should not be manually edited
Runtime Behavior
App Startup Sequence
- Android System: Launches
MainActivity - Capacitor Initialization: Loads Capacitor runtime
- Plugin Discovery: Scans
capacitor.plugins.jsonfor plugins - Plugin Registration: Instantiates
DailyNotificationPlugin - WebView Loading: Loads
index.htmlfrom assets - JavaScript Bridge: Establishes communication between web and native
- Plugin Availability:
window.Capacitor.Plugins.DailyNotificationbecomes available
Plugin Method Execution Flow
JavaScript Call
↓
Capacitor Bridge
↓
Plugin Method (@PluginMethod)
↓
Native Implementation
↓
Response (JSObject)
↓
JavaScript Promise Resolution
Background Processing
- WorkManager: Handles background content fetching
- AlarmManager: Manages notification scheduling
- BootReceiver: Reschedules notifications after reboot
- Doze Mode: Handles Android's battery optimization
Testing Capabilities
Interactive Testing Features
The test app provides comprehensive testing capabilities:
1. Plugin Availability Testing
- Basic Detection: Verify plugin is loaded and accessible
- Method Availability: Check if specific methods are callable
- Error Handling: Test error conditions and edge cases
2. Notification Testing
- Immediate Notifications: Test instant notification display
- Scheduled Notifications: Test time-based notification scheduling
- Reminder Testing: Test daily reminder functionality
- Content Testing: Test with different notification content
3. Permission Management
- Permission Status: Check current permission state
- Permission Requests: Test permission request flow
- Settings Navigation: Test opening system settings
- Permission Validation: Verify permission changes
4. Channel Management
- Channel Status: Check notification channel state
- Channel Settings: Test channel configuration
- Importance Levels: Test different importance settings
- Channel Creation: Test channel creation and management
5. Comprehensive Status Checking
- Overall Status: Complete system status check
- Issue Detection: Identify configuration problems
- Readiness Check: Verify system is ready for notifications
- Troubleshooting: Help identify and resolve issues
Debugging Features
- Console Logging: Detailed console output for debugging
- Visual Feedback: Color-coded status indicators
- Error Reporting: Detailed error messages and stack traces
- Real-time Updates: Live status updates during testing
Integration Patterns
Plugin Integration Pattern
// 1. Check Plugin Availability
if (!window.DailyNotification) {
console.error('Plugin not available');
return;
}
// 2. Call Plugin Method
window.DailyNotification.scheduleDailyNotification({
time: "09:00",
title: "Daily Notification",
body: "Your daily content is ready!",
sound: true,
priority: "high"
})
.then(() => {
console.log('Notification scheduled successfully');
})
.catch(error => {
console.error('Scheduling failed:', error);
});
Error Handling Pattern
try {
const result = await window.DailyNotification.checkStatus();
// Handle success
} catch (error) {
// Handle error
console.error('Status check failed:', error.message);
}
Permission Management Pattern
// Check permissions first
const permissions = await window.DailyNotification.checkPermissionStatus();
if (!permissions.allPermissionsGranted) {
// Request permissions
await window.DailyNotification.requestNotificationPermissions();
}
Key Insights
Strengths
- Comprehensive Testing: Covers all plugin functionality
- Interactive Interface: Easy-to-use testing interface
- Real-time Feedback: Immediate visual feedback
- Error Handling: Robust error handling and reporting
- Permission Management: Complete permission testing
- Documentation: Self-documenting through interface
Architecture Benefits
- Separation of Concerns: Clear separation between web and native
- Plugin Isolation: Plugin functionality is isolated and testable
- Capacitor Integration: Leverages Capacitor's plugin system
- Cross-Platform: Web interface works across platforms
- Maintainable: Easy to update and maintain
Use Cases
- Plugin Development: Test new plugin features
- Integration Testing: Verify plugin integration
- Debugging: Debug plugin issues
- Documentation: Demonstrate plugin capabilities
- Quality Assurance: Validate plugin functionality
Conclusion
The /android/app portion of the DailyNotification plugin represents a well-architected test application that provides comprehensive testing capabilities for the plugin. It demonstrates best practices for Capacitor plugin integration, including proper permission handling, error management, and user interface design.
The integration between the web assets (/www) and native Android code through Capacitor's bridge system creates a seamless testing environment that allows developers to validate plugin functionality in real-time while providing an intuitive interface for non-technical users to test and understand the plugin's capabilities.
This architecture serves as both a practical testing tool and a reference implementation for integrating the DailyNotification plugin into other applications.
Assumptions & Versions
| Topic | Value | Notes |
|---|---|---|
| Android min/target SDK | 24 / 35 | Align with compileSdkVersion/targetSdkVersion. |
| Capacitor | v5.x | Confirm web asset naming (capacitor.js vs Cordova shims). |
| WorkManager | 2.9.0 | Matches Gradle deps listed. |
| Room | 2.6.1 | Matches Gradle deps listed. |
| Exact Alarms | Tiramisu+ | Requires user grant on many OEMs. |
Bridge Surface (Summary)
scheduleDailyNotification(req: {time, title, body, sound, priority}) -> {success, scheduledAt?, error?}checkPermissionStatus() -> {postNotificationsGranted, exactAlarmGranted, batteryOptIgnored, channelEnabled, ...}openChannelSettings() -> {opened: boolean}openExactAlarmSettings() -> {opened: boolean}requestNotificationPermissions() -> {granted: boolean, permissions: {...}}getNotificationStatus() -> {isEnabled, isScheduled, nextNotificationTime, ...}
Permission & Settings Truth Table
| Symptom | Likely Cause | Action |
|---|---|---|
| No notification posts | POST_NOTIFICATIONS denied |
Call requestNotificationPermissions() |
| Fires late/misses | No exact alarm grant / Doze | openExactAlarmSettings() or fallback to WorkManager |
| Silent notifications | Channel disabled/low importance | openChannelSettings() then retest |
| Battery optimization kills | App not whitelisted | Guide user to battery optimization settings |
| Boot reschedule fails | RECEIVE_BOOT_COMPLETED denied |
Check manifest receiver registration |
Runtime Flow Diagram
graph TD
A[JavaScript Call] --> B[Capacitor Bridge]
B --> C[@PluginMethod]
C --> D[Use Case Handler]
D --> E{Alarm vs WorkManager}
E -->|Exact Alarm| F[AlarmManager]
E -->|Fallback| G[WorkManager]
F --> H[BootReceiver]
G --> H
H --> I[NotificationReceiver]
I --> J[UI Update]
Cordova vs Capacitor Assets – Accuracy Note
Note: If using pure Capacitor v5, the web runtime is
capacitor.js. If Cordova compatibility is enabled,cordova.js/cordova_plugins.jswill appear; otherwise remove those references here for accuracy.