- Update Android manifest, Java imports, and capacitor.plugins.json to use org.timesafari.dailynotification (receivers, intent action, plugin classpath) - Update iOS Info.plist BGTaskSchedulerPermittedIdentifiers to org.timesafari.* - Bump @timesafari/daily-notification-plugin 1.3.3 → 2.0.0 (package-lock, Podfile.lock) - Update docs and test-notification-receiver.sh to reference new package/action names - Lockfile: minor bumps for @expo/cli, @expo/fingerprint, @expo/router-server, babel-preset-expo
5.9 KiB
5.9 KiB
Daily Notification Plugin: Alignment Outline
Purpose: Checklist of changes/additions needed in this app to align with the test app (daily-notification-plugin/test-apps/daily-notification-test) so that:
- Rollover recovery (and rollover itself) works.
- Notifications show when the app is in the foreground (not only background/closed).
- Plugin loads at app launch so recovery runs after reboot without the user opening notification UI.
Reference: Test app at
/Users/aardimus/Sites/trentlarson/daily-notification-plugin_test/daily-notification-plugin/test-apps/daily-notification-test
1. iOS AppDelegate
File: ios/App/App/AppDelegate.swift
1.1 Add imports
import UserNotifications- Import the Daily Notification plugin framework (Swift module name: TimesafariDailyNotificationPlugin per this app’s Podfile; test app uses DailyNotificationPlugin)
1.2 Conform to UNUserNotificationCenterDelegate
- Add
, UNUserNotificationCenterDelegateto the class declaration:
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate
1.3 Force-load plugin at launch
- In
application(_:didFinishLaunchingWithOptions:), before other setup, add logic to force-load the plugin class (e.g._ = DailyNotificationPlugin.selfor the class exposed by the TimesafariDailyNotificationPlugin pod) so that the plugin’sload()(and thusperformRecovery()) runs at app launch, not only when JS first calls the plugin.
1.4 Set notification center delegate
- In
didFinishLaunchingWithOptions, set:
UNUserNotificationCenter.current().delegate = self - In
applicationDidBecomeActive, re-set the same delegate (in case Capacitor or another component clears it).
1.5 Implement userNotificationCenter(_:willPresent:withCompletionHandler:)
- When a notification is delivered (including in foreground), read
notification_idandscheduled_timefromnotification.request.content.userInfo. - Post rollover event:
NotificationCenter.default.post(name: NSNotification.Name("DailyNotificationDelivered"), object: nil, userInfo: ["notification_id": id, "scheduled_time": scheduledTime]) - Call completion handler with presentation options so the notification is shown in foreground, e.g.
completionHandler([.banner, .sound, .badge])(use.alerton iOS 13 if needed).
1.6 Implement userNotificationCenter(_:didReceive:withCompletionHandler:)
- Handle notification tap/interaction; call
completionHandler()when done.
2. Android Manifest
File: android/app/src/main/AndroidManifest.xml
2.1 Fix receiver placement
- Move the two
<receiver>elements (DailyNotificationReceiver and BootReceiver) inside the<application>block (e.g. after<activity>...</activity>and before<provider>...</provider>). - Remove the stray second
</application>so there is a single<application>...</application>containing activity, receivers, and provider.
2.2 (Optional) Add NotifyReceiver
- If the plugin’s Android integration expects NotifyReceiver for alarm-based delivery, add a
<receiver>fororg.timesafari.dailynotification.NotifyReceiverinside<application>(see test app manifest for exact declaration).
2.3 (Optional) BootReceiver options
- Consider aligning with test app: add
android:directBootAware="true",android:exported="true", and intent-filter actionsLOCKED_BOOT_COMPLETED,MY_PACKAGE_REPLACED,PACKAGE_REPLACEDif you need the same boot/update behavior.
3. Capacitor / JS startup (optional but recommended)
File: src/main.capacitor.ts (or the main entry used for native builds)
3.1 Load plugin at startup
- Add a top-level import or an early call that touches the Daily Notification plugin so the JS side loads it at app startup (e.g.
import "@timesafari/daily-notification-plugin"or a small init that callsgetRebootRecoveryStatus()orconfigure()).
This ensures the plugin is loaded as soon as the app runs; together with the iOS force-load in AppDelegate, recovery runs at launch.
4. Plugin configuration (optional)
- If you use the native fetcher or need plugin config (db path, storage, etc.), call
DailyNotification.configure()and/orconfigureNativeFetcher()when appropriate (e.g. after login or when notification UI is first used), similar to the test app’sconfigureNativeFetcher()in HomeView.
5. Summary table
| Area | Change / addition |
|---|---|
| iOS AppDelegate | Conform to UNUserNotificationCenterDelegate; set delegate; force-load plugin; implement willPresent (post DailyNotificationDelivered + show in foreground) and didReceive. |
| Android manifest | Move DailyNotificationReceiver and BootReceiver inside <application>; remove duplicate </application>; optionally add NotifyReceiver and BootReceiver options. |
| main.capacitor.ts | Optionally import or call plugin at startup so it (and recovery) load at launch. |
| Plugin config | Optionally call configure() / configureNativeFetcher() where appropriate. |
6. Verification
After making the changes:
- iOS: Build and run; trigger a daily notification and confirm it appears when the app is in the foreground.
- iOS: Confirm rollover (next day’s schedule) still occurs after a notification fires (check logs for
DNP-ROLLOVER/DailyNotificationDelivered). - iOS: Restart the app (or reboot) and confirm recovery runs without opening the notification settings screen (e.g. logs show plugin load and recovery).
- Android: Build and run; confirm receivers are registered (no manifest errors) and that notifications and boot recovery behave as expected.