# LTT-K **Repository Path**: xcdmr/LTT-K ## Basic Information - **Project Name**: LTT-K - **Description**: 手机端及时提醒 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-05-25 - **Last Updated**: 2026-05-25 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LTTK(强提醒) ## 1. 文档入口与 AI Agent 协作约定 本项目文档固定分为两个层级: - **主文档:`README.md`** - 负责项目定位、核心功能、代码结构、系统分层、开发规范、风格规范、强约定清单、数据与接口总览、快速开始、当前实现边界。 - 这是开发者和 AI Agent 的第一入口。任何分析、设计、编码、重构、调试行为开始之前,都必须先完整阅读本文件。 - **细节文档:`IMPLEMENTATION.md`** - 负责实现细节、内部 API、组件使用说明、数据格式、运行与配置细节、前端实现细节、当前实现边界展开说明。 - 当本文件中的总览信息不足以支持实现、排错或扩展时,必须继续查阅 `IMPLEMENTATION.md`。 AI Agent 工作规则: 1. 开始工作前必须先阅读 `README.md`;涉及更细实现时,继续阅读 `IMPLEMENTATION.md`。 2. 不得把未实现的能力写成已实现,不得把计划中的能力写成当前状态。 3. 不得绕过本文档声明的分层、边界、目录职责、接口归属、数据访问约定和前端组织约定。 4. 修改代码后,如果影响功能、接口、数据格式、目录结构、开发规范、风格规范、实现边界或使用方式,必须同步更新文档。 5. 如果某项实现已经变化而文档未更新,应先修正文档,再继续后续开发或交付。 6. 开发日志、开发计划、过程记录、任务流水不写入 `README.md` 和 `IMPLEMENTATION.md`。 7. 代码中要有足量中文注释,至少每个功能块、函数要有一条。 ## 2. 项目定位与简介 LTTK 是一个运行在 Android 平台上的原生 Kotlin 强提醒应用。当前代码实现属于轻量、单模块、无传统数据库、基于 Jetpack Compose 的提醒应用。 当前目标是: - 允许用户创建、编辑单次定时提醒。 - 以 Todo 清单方式管理待办提醒,并通过 Checkbox 标记完成。 - 已完成提醒从主页面移除,并展示在独立的“已完成”页面。 - 在指定时间通过 `AlarmManager` 触发提醒。 - 通过前台服务、持续震动、高优先级通知提升提醒可感知性。 - 支持为提醒设置最长提醒时间,到达设定时长后自动停止震动,但仍保留提醒页与前台通知,直到用户手动关闭。 - 在设备处于锁屏状态时,尝试拉起全屏提醒页面。 本项目还不是生产级强提醒应用。权限闭环、开机恢复、后台兼容、日志体系、测试覆盖仍不完整。 ## 3. 当前实现范围与核心功能 已实现能力: 1. **待办提醒列表** - 主页面仅展示未完成提醒。 - 列表项包含 Checkbox、标题、提醒时间、编辑按钮、删除按钮。 - 待办列表按提醒时间升序排列。 2. **新增提醒** - 通过相对时间或指定日期时间创建提醒。 - 相对时间支持填写 `1-1440` 分钟后或 `1-24` 小时后,并显示预计提醒时间。 - 指定日期时间模式下日期默认今天,时间默认打开弹窗时向上取整到下一分钟。 - 必须填写非空标题。 - UI 会阻止保存不晚于当前时间的提醒。 - 创建后保存到 DataStore,并在启用状态下注册系统闹钟。 3. **编辑提醒** - 支持修改提醒标题,并通过相对时间或指定日期时间重设提醒时间。 - 编辑弹窗默认使用相对时间模式,且不预填相对数值;如只修改标题,需要切换到指定时间模式保留原时间。 - UI 会阻止保存不晚于当前时间的提醒。 - 保存时会更新存储、取消旧闹钟,并在未完成且启用时重新调度。 - 当前编辑保存会把 `isEnabled` 设为 `true`。 4. **完成提醒** - 点击待办项 Checkbox 后将提醒标记为已完成。 - 完成后取消闹钟、记录完成时间、从待办页移除。 - 如果该提醒正在响铃,会广播通知 `ReminderService` 停止当前提醒。 5. **已完成提醒页面** - 展示所有已完成提醒。 - 展示原提醒时间和完成时间。 - 支持删除已完成提醒。 - 已完成列表按完成时间倒序排列,缺少完成时间时按创建时间倒序排列。 6. **删除提醒** - 删除时取消已注册闹钟。 - 从 DataStore 删除提醒。 - 如果该提醒正在响铃,会广播通知 `ReminderService` 停止当前提醒。 7. **系统定时触发** - 使用 `AlarmManager` 调度提醒。 - Android 12+ 且允许精确闹钟时使用 `setAlarmClock()`。 - Android 12+ 不允许精确闹钟时退化为 `set()`。 - Android 12 以下使用 `setAlarmClock()`。 8. **强提醒表现** - 闹钟广播触发后启动 `ReminderService` 前台服务。 - 服务启动持续震动。 - 服务显示高优先级、ongoing 的前台通知。 - 锁屏时尝试拉起 `ReminderActivity`。 - 用户可从通知或提醒页停止提醒。 - 用户可在提醒开始后选择稍后提醒:通知提供“5分钟后”快捷入口,全屏提醒页提供 `3 / 5 / 10 / 30` 分钟后四个选项。 - 稍后提醒会停止当前震动和提醒页,更新同一个提醒的触发时间并重新调度,不会创建重复提醒。 9. **提醒偏好设置** - 设置页面支持配置最长提醒时间。 - 当前 UI 可选 `1 / 3 / 5 / 10 / 15 / 30 / 60` 分钟。 - 默认值为 5 分钟。 - 存储层会将传入值规整到 1-60 分钟。 - 达到设定时长后自动停止震动,但通知与提醒页继续保留,等待手动关闭。 当前未实现或未完善能力: - 周期性提醒。 - 开机重启后自动恢复提醒。 - 铃声播放,目前仅实现震动。 - 完整权限引导与拒绝后的降级策略。 - 完整异常恢复、日志、监控。 - 正式自动化测试覆盖。 ## 4. 技术栈与关键版本 构建与语言: - Kotlin:`1.9.0` - Android Gradle Plugin:`8.2.2` - Gradle Wrapper:`8.2` - Java source / target:`1.8` Android 配置: - `compileSdk`:`34` - `targetSdk`:`34` - `minSdk`:`26` - `applicationId`:`com.xcdmr.lttk` - `namespace`:`com.xcdmr.lttk` 主要依赖: - Jetpack Compose BOM:`2023.08.00` - Material 3:Compose Material 3 - Activity Compose:`1.7.0` - Lifecycle Runtime KTX:`2.6.1` - Lifecycle ViewModel Compose:`2.6.1` - Navigation Compose:`2.7.0`,当前代码尚未使用 NavHost,只用本地枚举状态切换页面。 - DataStore Preferences:`1.0.0` - Gson:`2.10.1` - JUnit / AndroidX Test / Espresso:当前仅模板示例测试。 系统能力: - `AlarmManager` - `BroadcastReceiver` - `Foreground Service` - `NotificationCompat` - `WakeLock` - `Vibrator` / `VibratorManager` ## 5. 代码结构与模块职责 项目是单模块 Android App,根模块名为 `lttk`,当前仅包含 `:app`。 ```text . ├─ build.gradle.kts # 顶层构建配置 ├─ settings.gradle.kts # 仓库与模块声明,仅 include(:app) ├─ gradle.properties # Gradle 属性 ├─ gradle/wrapper/ # Gradle Wrapper ├─ README.md # 主文档,项目总览与 AI 主上下文 ├─ IMPLEMENTATION.md # 细节文档,实现细节与维护规则展开 └─ app/ ├─ build.gradle.kts # App 模块构建配置 ├─ proguard-rules.pro # 混淆配置,当前 release 未启用压缩 └─ src/ ├─ main/ │ ├─ AndroidManifest.xml # 权限、Activity、Receiver、Service 声明 │ ├─ java/com/xcdmr/lttk/ │ │ ├─ MainActivity.kt # 应用入口与页面容器 │ │ ├─ ReminderActivity.kt # 锁屏/全屏提醒页 │ │ ├─ ReminderBroadcastReceiver.kt # 闹钟广播接收器 │ │ ├─ ReminderService.kt # 前台提醒服务 │ │ ├─ ReminderViewModel.kt # UI 层业务编排 │ │ ├─ alarm/AlarmScheduler.kt # 闹钟注册与取消封装 │ │ ├─ data/ReminderRepository.kt # 提醒数据存取仓库 │ │ ├─ data/UserPreferencesRepository.kt # 用户偏好存取仓库 │ │ ├─ model/Reminder.kt # 领域模型与序列化模型 │ │ ├─ ui/components/ # Compose 页面片段与共享组件 │ │ ├─ ui/theme/ # Compose 主题 │ │ └─ util/PermissionUtils.kt # 权限与系统设置辅助 │ └─ res/ # Android 资源文件 ├─ androidTest/ # 仪器测试,当前仅模板示例 └─ test/ # 单元测试,当前仅模板示例 ``` ## 6. 系统分层与核心架构约定 当前架构是简化版 MVVM,边界如下: - **UI 层**:`MainActivity`、`ReminderActivity`、`ui/components/*`。负责 Compose 页面、用户输入、页面状态切换,不直接访问 DataStore 或 AlarmManager。 - **状态与业务编排层**:`ReminderViewModel`。负责连接 UI、Repository、AlarmScheduler、Service 停止广播。 - **数据层**:`ReminderRepository`、`UserPreferencesRepository`。负责 DataStore 读写和数据转换。 - **系统调度层**:`AlarmScheduler`、`ReminderBroadcastReceiver`、`ReminderService`。负责闹钟注册、广播触发、前台服务、通知、震动、锁屏拉起。 - **模型层**:`Reminder`、`ReminderData`。`Reminder` 是业务领域模型,`ReminderData` 是 Gson 持久化模型。 - **工具层**:`PermissionUtils`。负责权限检查与跳转系统设置。 强制约定: - UI 不直接读写 DataStore。 - UI 不直接注册或取消 `AlarmManager`。 - 新增、编辑、完成、删除提醒必须通过 `ReminderViewModel` 进入业务流程。 - 持久化提醒列表只能通过 `ReminderRepository`。 - 持久化用户偏好只能通过 `UserPreferencesRepository`。 - 闹钟调度只能通过 `AlarmScheduler`。 - 提醒触发后的持续行为只能由 `ReminderService` 承载,不得在 `BroadcastReceiver` 中执行长任务。 - 如果新增页面、组件、仓库、系统能力入口,必须同步更新 `README.md` 与必要的 `IMPLEMENTATION.md` 章节。 ## 7. 开发规范 通用规范: - 代码默认使用 Kotlin 与现有 AndroidX/Compose 技术栈,不引入新框架前必须确认必要性。 - 默认保持单模块结构,不新增模块,除非需求明确需要模块化。 - 不把未实现能力写入“已实现”章节。 - 修改业务规则、数据格式、目录结构、权限策略、页面组织、共享组件能力后,必须同步更新文档。 - 开发日志、计划、任务流水不写入 `README.md` 或 `IMPLEMENTATION.md`。 - 中文文档必须描述当前真实代码,不写愿景式功能说明。 代码注释规范: - 新增或重构代码时,功能块和函数至少保留一条中文注释。 - 注释解释业务意图、系统限制或非显然实现原因,不写“给变量赋值”这类低价值注释。 - 修改既有函数时,如果函数缺少必要中文注释,应顺手补齐。 数据与并发规范: - 当前提醒数据使用 DataStore Preferences + JSON 字符串,不使用 Room / SQLite。 - 修改 `ReminderData` 字段含义时,必须同步更新数据格式说明。 - `ReminderRepository` 当前使用 `GlobalScope` 收集 DataStore,这是已知维护风险;不要扩散这种模式到新代码。 - ViewModel 中异步任务使用 `viewModelScope`。 - Service 内部异步任务使用服务自有 `CoroutineScope`,销毁时必须取消。 测试规范: - 当前只有 Android Studio 模板示例测试。 - 新增关键业务逻辑时,应优先补充单元测试或仪器测试。 - 如果暂时无法补测,交付说明中必须明确测试缺口。 ## 8. 前端风格规范 当前前端是 Jetpack Compose + Material 3,保持现有简洁工具型风格。 页面组织: - `MainActivity` 承载待办、已完成、设置三个页面状态。 - 当前未使用 Navigation Compose 的 `NavHost`,页面切换通过 `ReminderAppScreen` 枚举名和 `rememberSaveable` 管理。 - 待办页面、已完成页面、设置页面都由 Compose 组件拼装。 Compose 规范: - 组件命名保持业务语义清晰,例如 `ReminderTodoItem`、`CompletedRemindersScreen`、`ReminderSettingsScreen`。 - 可复用 UI 放在 `ui/components/`。 - 主题相关代码放在 `ui/theme/`。 - 页面状态优先由 ViewModel 的 `StateFlow` 提供,组件内只保留短生命周期 UI 状态。 - 新增页面时必须说明页面入口、状态来源、是否影响 `MainActivity` 页面切换方式。 视觉规范: - 保持 Material 3 组件体系和现有 `LttkTheme`。 - 不引入与现有主题冲突的独立样式体系。 - 错误、权限提醒等状态优先使用 Material 语义颜色。 - 强提醒页可以使用更高对比度,但必须保留停止提醒入口。 ## 9. 开发维护强约定清单 必须遵守: 1. 开始任何代码工作前先读 `README.md`;涉及实现细节继续读 `IMPLEMENTATION.md`。 2. 不得把计划、想法、待办写成当前已实现能力。 3. 不得绕过 `ReminderViewModel` 直接从 UI 操作仓库或闹钟。 4. 不得在 `BroadcastReceiver` 中执行持续震动、长时间 IO 或长生命周期业务。 5. 不得未经说明修改 DataStore key、JSON 字段名或时间转换语义。 6. 修改功能、接口、数据格式、目录结构、风格规范、边界说明后必须更新文档。 7. 新增函数或功能块时必须写足量中文注释。 8. 不得把开发日志、计划、过程流水写入正式文档。 ## 10. 数据与接口总览 持久化总览: - 当前没有传统数据库,没有 Room / SQLite。 - 提醒列表使用 DataStore Preferences,DataStore 名称为 `reminders`。 - 用户偏好使用 DataStore Preferences,DataStore 名称为 `user_preferences`。 - 提醒列表以单个 JSON 字符串整体保存。 核心键: | Key | 类型 | 归属 | 含义 | |---|---|---|---| | `reminders_list` | `String` | `ReminderRepository` | 保存 `List` 的 JSON 字符串 | | `max_reminder_duration_minutes` | `Int` | `UserPreferencesRepository` | 最长提醒时间,默认 5 分钟,规整范围 1-60 分钟 | 核心模型: | 模型 | 用途 | 关键字段 | |---|---|---| | `Reminder` | 业务领域模型 | `id`、`title`、`dateTime`、`isEnabled`、`isCompleted`、`createdAt`、`completedAt` | | `ReminderData` | Gson 存储模型 | `id`、`title`、`dateTimeMillis`、`isEnabled`、`createdAt`、`isCompleted`、`completedAtMillis` | 内部入口总览: | 入口 | 作用 | |---|---| | `ReminderViewModel.addReminder()` | 新增提醒并调度闹钟 | | `ReminderViewModel.updateReminder()` | 更新提醒、取消旧闹钟、按状态重新调度 | | `ReminderViewModel.completeReminder()` | 完成提醒、取消闹钟、停止当前响铃 | | `ReminderViewModel.deleteReminder()` | 删除提醒、取消闹钟、停止当前响铃 | | `AlarmScheduler.scheduleReminder()` | 注册系统闹钟 | | `AlarmScheduler.cancelReminder()` | 取消系统闹钟 | | `ReminderService.ACTION_START_REMINDER` | 启动强提醒服务行为 | | `ReminderService.ACTION_STOP_REMINDER` | 停止强提醒服务行为 | | `ReminderService.ACTION_SNOOZE_REMINDER` | 将当前提醒推迟到稍后再次提醒 | | `ReminderService.ACTION_REQUEST_STOP_ACTIVE_REMINDER` | ViewModel 广播请求停止指定正在响铃的提醒 | 更细字段、Intent extra、通知、权限和组件说明见 `IMPLEMENTATION.md`。 ## 11. 快速开始 环境要求: - Android Studio 较新稳定版本。 - Android SDK 34。 - JDK 17,通常与 AGP 8.x 搭配。 构建 Debug 包: ```bash ./gradlew assembleDebug ``` Windows 命令行: ```bat gradlew.bat assembleDebug ``` 运行后重点检查: 1. Android 13+ 通知权限是否授予。 2. Android 12+ 精确闹钟权限是否允许。 3. 电池优化是否影响后台提醒。 4. 锁屏弹出或全屏提醒是否被系统或 ROM 限制。 5. 国产 ROM 对前台服务、闹钟、锁屏启动的限制。 ## 12. 当前实现边界与维护提醒 关键边界: - 当前只支持单次提醒,不支持周期提醒。 - 设备重启后不会自动恢复已注册闹钟。 - 当前无 Room,无数据库迁移机制。 - `ReminderRepository` 使用 `GlobalScope` 收集 DataStore,是已知工程风险。 - `WakeLock` 在 Receiver 中获取后很快释放,实际兜底时长短于 `acquire(5分钟)` 的直觉含义。 - 全屏意图权限检查不完整,`PermissionUtils.hasFullScreenIntentPermission()` 当前只是占位返回 `true`。 - 忽略电池优化有工具方法和权限声明,但主流程未接入。 - `SYSTEM_ALERT_WINDOW`、`DISABLE_KEYGUARD` 已声明但当前代码未形成完整产品闭环。 - 新增提醒和编辑提醒的 UI 会阻止保存不晚于当前时间的提醒;调度层仍未独立兜底校验过去时间。 - `PendingIntent` requestCode 使用 `reminder.id.hashCode()`,理论上存在 hash 冲突可能。 - 测试几乎为空,仅保留模板示例。 优先维护方向: 1. 补齐开机重启恢复提醒。 2. 在 `ReminderViewModel` 或 `AlarmScheduler` 增加过去时间兜底校验。 3. 完整处理通知权限、精确闹钟权限、全屏意图权限的失败与降级。 4. 增加关键日志,便于排查提醒未触发问题。 5. 替换 `ReminderRepository` 中的 `GlobalScope`。 6. 补充提醒新增、更新、删除、完成、存储转换、调度逻辑测试。 ## 13. 细节文档入口 需要以下信息时阅读 `IMPLEMENTATION.md`: - 具体业务流程步骤。 - 内部 API、函数职责、Intent action、extra 名称。 - DataStore JSON 示例和时间字段转换规则。 - Manifest 权限和 Android 版本行为差异。 - Compose 页面组织、共享组件使用方式。 - 维护时容易混淆的特殊规则。 维护原则:`README.md` 负责项目总览、规则入口、AI 主上下文;`IMPLEMENTATION.md` 负责展开实现、承接细节。两个文件必须分工清晰、内容同步、描述准确,并始终以方便后续维护和方便 AI 理解当前真实实现为第一原则。