feat(android): consolidate databases and add prefetch scheduling

Consolidate Java and Kotlin database implementations into unified
schema, add delayed prefetch scheduling, and fix notification
delivery issues.

Database Consolidation:
- Merge Java DailyNotificationDatabase into Kotlin DatabaseSchema
- Add migration path from v1 to v2 unified schema
- Include all entities: ContentCache, Schedule, Callback, History,
  NotificationContentEntity, NotificationDeliveryEntity,
  NotificationConfigEntity
- Add @JvmStatic getInstance() for Java interoperability
- Update DailyNotificationWorker and DailyNotificationStorageRoom
  to use unified database

Prefetch Functionality:
- Add scheduleDelayedFetch() to FetchWorker for 5-minute prefetch
  before notifications
- Support delayed WorkManager scheduling with initialDelay
- Update scheduleDailyNotification() to optionally schedule prefetch
  when URL is provided

Notification Delivery Fixes:
- Register NotifyReceiver in AndroidManifest.xml (was missing,
  causing notifications not to fire)
- Add safe database initialization with lazy getDatabase() helper
- Prevent PluginLoadException on database init failure

Build Configuration:
- Add kotlin-android and kotlin-kapt plugins
- Configure Room annotation processor (kapt) for Kotlin
- Add Room KTX dependency for coroutines support
- Fix Gradle settings with pluginManagement blocks

Plugin Methods Added:
- checkPermissionStatus() - detailed permission status
- requestNotificationPermissions() - request POST_NOTIFICATIONS
- scheduleDailyNotification() - schedule with AlarmManager
- configureNativeFetcher() - configure native content fetcher
- Various status and configuration methods

Code Cleanup:
- Remove duplicate BootReceiver.java (keep Kotlin version)
- Remove duplicate DailyNotificationPlugin.java (keep Kotlin version)
- Remove old Java database implementation
- Add native fetcher SPI registry (@JvmStatic methods)

The unified database ensures schedule persistence across reboots
and provides a single source of truth for all plugin data.
Prefetch scheduling enables content caching before notifications
fire, improving offline-first reliability.
This commit is contained in:
Matthew Raymer
2025-11-06 06:28:00 +00:00
parent d9bdeb6d02
commit 18106e5ba8
17 changed files with 3310 additions and 3114 deletions

View File

@@ -1,22 +1,25 @@
apply plugin: 'com.android.library'
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:8.13.0'
classpath 'com.android.tools.build:gradle:8.1.0'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.10'
}
}
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'
android {
namespace "com.timesafari.dailynotification.plugin"
compileSdk 35
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
defaultConfig {
minSdk 23
targetSdk 35
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
@@ -38,6 +41,10 @@ android {
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
// Disable test compilation - tests reference deprecated/removed code
// TODO: Rewrite tests to use modern AndroidX testing framework
testOptions {
@@ -73,30 +80,52 @@ repositories {
dependencies {
// Capacitor dependency - provided by consuming app
// When included as a project dependency, use project reference
// When building standalone, this will fail (expected - plugin must be built within a Capacitor app)
// NOTE: Capacitor Android is NOT published to Maven - it must be available as a project dependency
def capacitorProject = project.findProject(':capacitor-android')
if (capacitorProject != null) {
implementation capacitorProject
} else {
// Try to find from node_modules (for syntax checking only)
def capacitorPath = new File(rootProject.projectDir, '../node_modules/@capacitor/android/capacitor')
if (capacitorPath.exists() && new File(capacitorPath, 'build.gradle').exists()) {
// If we're in a Capacitor app context, try to include it
throw new GradleException("Capacitor Android project not found. This plugin must be built within a Capacitor app that includes :capacitor-android.")
} else {
throw new GradleException("Capacitor Android not found. This plugin must be built within a Capacitor app context.")
}
// Capacitor not found - this plugin MUST be built within a Capacitor app context
// Provide clear error message with instructions
def errorMsg = """
╔══════════════════════════════════════════════════════════════════╗
║ ERROR: Capacitor Android project not found ║
╠══════════════════════════════════════════════════════════════════╣
║ This plugin requires Capacitor Android to build. ║
║ Capacitor plugins cannot be built standalone. ║
║ ║
║ To build this plugin: ║
║ 1. Build from test-apps/android-test-app (recommended) ║
║ cd test-apps/android-test-app ║
║ ./gradlew build ║
║ ║
║ 2. Or include this plugin in a Capacitor app: ║
║ - Add to your app's android/settings.gradle: ║
║ include ':daily-notification-plugin' ║
║ project(':daily-notification-plugin').projectDir = ║
║ new File('../daily-notification-plugin/android') ║
║ ║
║ Note: Capacitor Android is only available as a project ║
║ dependency, not from Maven repositories. ║
║ ║
╚══════════════════════════════════════════════════════════════════╝
"""
throw new GradleException(errorMsg)
}
// These dependencies are always available from Maven
implementation "androidx.appcompat:appcompat:1.7.0"
implementation "androidx.room:room-runtime:2.6.1"
implementation "androidx.room:room-ktx:2.6.1"
implementation "androidx.work:work-runtime-ktx:2.9.0"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3"
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.10"
implementation "com.google.code.gson:gson:2.10.1"
implementation "androidx.core:core:1.12.0"
// Room annotation processor - use kapt for Kotlin, annotationProcessor for Java
kapt "androidx.room:room-compiler:2.6.1"
annotationProcessor "androidx.room:room-compiler:2.6.1"
}