Imported from bas080/notification-reminders (
AGENTS.md). Install upstream withnpx skills add bas080/notification-reminders. Copyright stays with the author.
AGENTS.md
Overview
notification-reminders is a Kotlin Android application that monitors incoming device notifications and intelligently matches them against user-defined reminders. When a notification contains words matching an active reminder, the application creates a new notification to surface that reminder.
Tech Stack & Architecture
- Language: Kotlin (
jvmTarget = 11) - Platform: Android (Target SDK 34, Min SDK 24)
- Key Frameworks / Libraries:
NotificationListenerServicefor background notification monitoring- AndroidX Core KTX, AppCompat, Material Components
- Room Database (for persistent reminder storage)
- View Binding
Repository Structure
.
├── .github/
│ └── workflows/
│ └── ci.yml # CI/CD GitHub Actions workflow
├── app/
│ ├── build.gradle.kts # App module dependencies & configuration
│ └── src/
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin/com/bas080/notificationreminders/
│ │ │ ├── NotificationRemindersApplication.kt
│ │ │ ├── MainActivity.kt
│ │ │ └── services/
│ │ │ └── ReminderNotificationListenerService.kt
│ │ │ └── utils/
│ │ │ └── ReminderMatcher.kt
│ │ └── res/ # Layouts, values, and themes
│ └── test/
│ └── kotlin/com/bas080/notificationreminders/
│ └── utils/
│ └── ReminderMatcherTest.kt
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew # Gradle wrapper script
├── build.gradle.kts # Root build script
├── gradle.properties # Gradle build properties
├── release.keystore # Temporary keystore for signed release builds
├── settings.gradle.kts # Included modules setup
└── README.md
Environment & Build Instructions
Gradle Configuration Notes
- AndroidX properties must be enabled in
gradle.properties:android.useAndroidX=true android.enableJetifier=true android.suppressUnsupportedCompileSdk=34
Build & Test Commands
- Run all unit tests:
./gradlew test - Build signed release APK:
./gradlew assembleRelease - Compile Kotlin source files:
./gradlew compileDebugUnitTestKotlin - Clean build directory:
./gradlew clean
Permissions, Services & Crash Reporting
- POST_NOTIFICATIONS Permission: Prompted on first app launch for Android 13+ (API 33+).
- Notification Listener Service (
NotificationListenerService): Check and prompt user to grant permission viaSettings.ACTION_NOTIFICATION_LISTENER_SETTINGS. - Ongoing Status Notification: Opened automatically via
ReminderNotificationListenerServiceas soon as permissions are granted or when service connects. - Process-Level Crash Handling:
NotificationRemindersApplicationregisters a globalThread.setDefaultUncaughtExceptionHandlerat process initialization. Uncaught exceptions from any thread or component are logged toSharedPreferences. On next app startup,MainActivityprompts the user to send a crash report email tobas080@hotmail.com.
Signing & Release Configuration
- Release Keystore:
release.keystorein root directory. - Signing Credentials:
- Store Password:
android - Key Alias:
releaseKey - Key Password:
android
- Store Password:
- Google Play Protect Note: APKs generated by self-signed keystores are flagged by Google Play Protect as "Unrecognized App" during manual sideloading. Users must click "More details" -> "Install anyway" to proceed with installation.
CI/CD Pipeline & GitHub Releases
The GitHub Actions workflow (.github/workflows/ci.yml) automatically runs tests (./gradlew test), builds signed release and debug APK artifacts (./gradlew assemble), uploads build artifacts via actions/upload-artifact@v4, and creates a GitHub Release via softprops/action-gh-release@v2:
- Pull Request Pushes: Creates a pre-release tagged
pr-<PR_NUMBER>-<SHA>named<PR Title> (#<PR Number>)with signed APK binaries attached. - Push to
master: Creates a pre-release taggedmaster-<SHA>named<Commit Title> (<Short Hash>)with signed APK binaries attached. - Version Tag Push (
v*): Creates a full release named<Tag Name>with signed APK binaries attached. - Manual Workflow Trigger (
workflow_dispatch): Accepts a SemVer tag input (e.g.v1.1.0), updatesversionNameinapp/build.gradle.kts, commits and tags the repository, and creates a full release (not a prerelease) named<Tag Name>with signed APK binaries attached.
Key Components & Code Logic
Matching Logic (ReminderMatcher.kt)
- Performs case-insensitive word matching between reminder text and incoming notification content.
- Filters out common stop words (e.g., "the", "a", "is", "in", "to", etc.).
- Matches based on word presence regardless of word order, supporting partial substring matches.
- Tested by
ReminderMatcherTest.kt.
Exception Handling & Try-Catch Guidelines
- Service & System API Calls: Wrap background service starts (e.g.
startForegroundService,startForeground) and Android OS intent/system calls intry-catchblocks to prevent system-level framework exceptions (such asForegroundServiceStartNotAllowedExceptionorSecurityException) from crashing the app process. - Log Errors Safely: When catching non-fatal exceptions in
try-catchblocks, log the error usingAppLoggerso it is captured inapp_logs.txtfor diagnostic purposes without crashing the user interface. - Do Not Silently Swallow Critical Failures: Only catch expected non-fatal system/framework exceptions. Fatal or unrecoverable application state errors should be allowed to propagate to
NotificationRemindersApplication's uncaught exception handler so the crash can be saved and reported. - Privacy & Logging: Do not write sensitive user information (such as email addresses, personal messages, or private reminder content) to application logs.
Minimal Text Interface Design Guidelines
- Typography-Driven UI: The interface uses a clean, minimal text design where hierarchy is established using font weight (
boldvsnormal), letter spacing (letterSpacing="0.1"), text size, and contrast rather than heavy button borders, background shadows, or graphic cards. - System Colors & High Contrast: Uses Android system color attributes (
?android:attr/colorBackground,?android:attr/textColorPrimary,?android:attr/textColorSecondary,@android:color/holo_blue_light, etc.) to guarantee optimal foreground-to-background text contrast and seamless dark/light system theme support. - Single Top Input Architecture: The main Reminders UI features a single create input row fixed at the top of the list (position 0 in
RemindersAdapter). Do not re-add secondary create inputs at the bottom of the list. - Text-Based Actions: Navigation tabs, clear logs controls, and list item actions (e.g.
+create and✕remove) utilize clean text elements with active/muted visual states.
Documentation & README Guidelines
- User-Focused Character of
README.md: TheREADME.mdfile must remain end-user focused, high-level, user-centric, and non-technical. It explains features, installation, and user workflow rather than developer-facing technical details or internal implementation specs.
Code Style & Conventions
- Follow standard Kotlin coding conventions.
- Package naming:
com.bas080.notificationreminders. - Use ViewBinding for layout interactions.
- Avoid committing generated build outputs (
build/,.gradle/). - Any change to the spec requires the adding or updating of tests.