定位:不是传统长篇大论的日记,而是一个极其方便的个人生活时间线记录工具。核心目标是让用户用最少的操作快速记录生活中的一件事情。
LifeLog 采用现代化 Android 原生技术栈(Kotlin + Jetpack Compose + Material 3 + Room + Flow + DataStore)开发,完全遵循官方架构规范。
- 极致快速记录:打开 App → 点击
+→ 输入文字 → 保存即可完成。默认自动设置发生时间为当前时间,不强制要求选日期、写标题、选分类或标签。 - 时间线自动分组:记录按实际发生时间(
eventTime)倒序排列,自动按天合并成卡片流,直观展现生活轨迹。 - 多媒体附件一体化:文字、多张图片(PhotoPicker/拍照)、语音录制(AAC)同屏呈现,支持直接播放与拖拽进度。
- 数据长期安全:图片与音频统一由私有目录管理,采用 UUID 命名防冲突;支持软删除(废纸篓恢复/永久清理)与一键导出/导入 Zip 完整备份。
| 模块 / 需求 | 选用技术方案 | 说明 |
|---|---|---|
| 编程语言 | Kotlin 2.0.0 | 全面采用协程与最新 Compose 编译插件 |
| UI 框架 | Jetpack Compose (BOM 2024.06.00) | 声明式响应式界面 |
| 设计系统 | Material Design 3 (M3) | 现代化大圆角、舒适留白、浅色/深色/跟随系统 |
| 架构规范 | MVVM + Repository 单一数据源 | 职责清晰解耦,不进行过度封装 |
| 本地数据库 | Room 2.6.1 + KSP | 强类型外键级联、关联查询、Flow 响应式流 |
| 异步流处理 | Kotlin Coroutines + Flow + StateFlow | 彻底杜绝主线程访问数据库与耗时 I/O |
| 单项偏好配置 | Jetpack DataStore Preferences 1.1.1 | 异步类型安全保存主题外观与上次备份时间 |
| 页面导航 | Navigation Compose 2.8.0 | 类型安全路由跳转与参数传递 |
| 图片加载 | Coil 2.7.0 (io.coil-kt:coil-compose) |
内存/磁盘双重缓存与渐显动画 |
| 音频录制播放 | Android 原生 MediaRecorder + MediaPlayer | 极简高效、无需臃肿三方库、兼容性极佳 |
| 系统兼容目标 | MinSdk 26 (Android 8.0) ~ TargetSdk 35 (Android 15) | 覆盖 95%+ 真实设备 |
LifeLog/
├── build.gradle.kts // 根工程构建脚本 (AGP 8.5.0, Kotlin 2.0.0, KSP)
├── settings.gradle.kts // 工程与仓库管理配置
├── gradle.properties // JVM 内存与 AndroidX 配置
├── gradlew / gradlew.bat // Gradle 跨平台 Wrapper 脚本
├── gradle/
│ └── wrapper/
│ └── gradle-wrapper.properties // Gradle 8.7 发行包配置
├── README.md // 项目文档
└── app/
├── build.gradle.kts // App 模块配置与依赖
├── proguard-rules.pro // 代码混淆规则
└── src/
└── main/
├── AndroidManifest.xml // 权限声明、Application 与 FileProvider 配置
├── res/
│ ├── values/
│ │ ├── strings.xml // 中文文本国际化资源
│ │ ├── colors.xml // 基础调色板
│ │ └── themes.xml // 无ActionBar主题与状态栏沉浸式配置
│ ├── xml/
│ │ ├── file_paths.xml // FileProvider 相机照片安全路径
│ │ └── backup_rules.xml // 云备份过滤规则
│ └── drawable/
└── java/com/lifelog/app/
├── LifeLogApplication.kt // 全局单例初始化(DB/Repo/Managers)
├── MainActivity.kt // 顶层 Activity,动态绑定主题与 NavHost
│
├── data/
│ ├── local/
│ │ ├── database/
│ │ │ ├── LifeLogDatabase.kt // RoomDatabase
│ │ │ ├── dao/
│ │ │ │ ├── JournalEntryDao.kt // 记录增删改查、搜索、日历聚合
│ │ │ │ ├── ImageAttachmentDao.kt // 图片增删与关联
│ │ │ │ └── AudioAttachmentDao.kt // 音频增删与关联
│ │ │ └── entity/
│ │ │ ├── JournalEntryEntity.kt // 核心表实体 (带索引)
│ │ │ ├── ImageAttachmentEntity.kt // 图片外键级联实体
│ │ │ ├── AudioAttachmentEntity.kt // 音频外键级联实体
│ │ │ └── EntryWithAttachments.kt // 一对多级联关系模型
│ │ └── preferences/
│ │ └── UserPreferencesManager.kt // DataStore 主题与元数据
│ └── repository/
│ └── JournalRepository.kt // 领域数据源与物理文件同步
│
├── domain/
│ └── model/
│ ├── JournalEntry.kt // 业务条目模型
│ ├── ImageAttachment.kt // 图片元数据模型
│ ├── AudioAttachment.kt // 音频元数据模型
│ ├── TimelineGroup.kt // 按日自动分组实体模型
│ └── BackupData.kt // 备份元数据模型
│
├── media/
│ ├── MediaFileManager.kt // 统一管理沙盒媒体文件读写、复制与清理
│ ├── audio/
│ │ ├── AudioRecorderManager.kt // 麦克风录音控制与实时计时器
│ │ └── AudioPlayerManager.kt // 播放器状态、Seek与波形进度同步
│ └── backup/
│ └── BackupManager.kt // 备份 Zip 归档打包与解压恢复
│
├── ui/
│ ├── navigation/
│ │ ├── Screen.kt // 路由路径常量定义
│ │ └── LifeLogNavHost.kt // 底部导航栏与界面路由中枢
│ ├── theme/
│ │ ├── Color.kt // 沉稳耐看的浅色/深色主题色
│ │ ├── Type.kt // Material 3 排版阶梯
│ │ └── Theme.kt // 动态主题配色切换
│ ├── components/
│ │ ├── EmptyState.kt // 优雅空状态展示
│ │ ├── CommonDialogs.kt // 二次确认对话框与长按操作底栏
│ │ ├── DateTimePickerBottomSheet.kt // 快捷选择与精准日期时间选择器
│ │ ├── AudioWaveformPlayer.kt // 类似微信样式的语音播放条
│ │ ├── ImageGrid.kt // 单图大图展示、多图规则宫格排列
│ │ └── FullscreenImageViewer.kt// 全屏多图水平滑动预览器
│ ├── timeline/
│ │ ├── TimelineScreen.kt // 首页默认时间线界面
│ │ ├── TimelineViewModel.kt // 时间线数据聚合、筛选与控制
│ │ └── components/
│ │ └── TimelineEntryCard.kt// 时间线单条卡片
│ ├── editor/
│ │ ├── EntryEditorScreen.kt // 新建/编辑记录界面
│ │ ├── EntryEditorViewModel.kt // 编辑状态机与多媒体采集流程
│ │ └── DraftManager.kt // 自动草稿保存机制
│ ├── detail/
│ │ ├── EntryDetailScreen.kt // 详情沉浸式浏览页面
│ │ └── EntryDetailViewModel.kt // 详情页状态管理
│ ├── calendar/
│ │ ├── CalendarScreen.kt // 月历视图与按天筛选展示
│ │ └── CalendarViewModel.kt // 日历打点统计与切换
│ ├── search/
│ │ ├── SearchScreen.kt // 实时关键字防抖搜索界面
│ │ └── SearchViewModel.kt // Debounce 搜索流
│ └── settings/
│ ├── SettingsScreen.kt // 外观设置、数据备份与关于页面
│ ├── SettingsViewModel.kt // 偏好设置及 Zip 导入导出任务
│ └── TrashScreen.kt // 最近删除(恢复与物理粉碎)
│
└── util/
├── DateTimeUtils.kt // 时间格式化与 LocalDate 转换工具
└── Extensions.kt // 复制剪贴板与原生分享扩展
- Android Studio:Android Studio Koala (2024.1.1) / Ladybug (2024.2.1) 或更高版本
- JDK 版本:JDK 17 或 JDK 21(Android Studio 自带的 JBR 即可)
- Gradle 版本:8.7(由 wrapper 自动配置)
- Android SDK:API 35(Compile / Target),支持真机与模拟器
- 打开 Android Studio,点击 Open;
- 选择本工程根目录
LifeLog; - Android Studio 将自动读取
gradle/wrapper/gradle-wrapper.properties,完成 Gradle 与相关依赖同步; - 连接 Android 手机(开启 USB 调试)或启动 Android 模拟器;
- 点击工具栏绿色的 Run 'app' 按钮即可安装运行。
在终端运行:
# Debug APK 构建
./gradlew assembleDebug
# Release APK 构建
./gradlew assembleRelease生成的 APK 文件将保存在:
app/build/outputs/apk/debug/app-debug.apk
| 权限名称 | 触发时机 | 用途说明 |
|---|---|---|
android.permission.RECORD_AUDIO |
点击新建界面的“录音”按钮时请求 | 用于录制用户生活语音日志(AAC/M4A) |
android.permission.CAMERA |
点击“添加图片 → 拍照”时请求 | 调用系统相机拍摄照片保存至日记中 |
android.permission.VIBRATE |
长按记录弹出操作菜单时 | 提供舒适自然的触控震动反馈 |
注:相册图片选择采用 Android 官方推荐的 Photo Picker(
ActivityResultContracts.PickMultipleVisualMedia),在 Android 13+ 无需申请相册读取权限,既保护用户隐私又极其顺畅。
所有媒体文件严禁只保存短期只读 URI,确保重装系统或重启手机后依然可以长期加载:
- 图片存储目录:
- 物理路径:
context.filesDir/media/images/ - 文件命名规则:
IMG_{UUID}.jpg - 来源:从相册选中的图片或相机拍下的照片,一律由
MediaFileManager拷贝至本目录并提取原始尺寸。
- 物理路径:
- 音频存储目录:
- 物理路径:
context.filesDir/media/audio/ - 文件命名规则:
AUD_{UUID}.m4a - 编码格式:AAC 音频编码、MPEG-4 封装容器,录音结束后自动写入该目录。
- 物理路径:
- 安全共享与预览:
- 配置了标准
androidx.core.content.FileProvider,用于安全调用系统相机与分享备份包。
- 配置了标准
- 生命周期清理:
- 在编辑中删除的未入库附件立即销毁;
- 在废纸篓中执行“永久删除”或“清空废纸篓”时,触发物理文件回收删除,绝不发生存储泄露。
采用 Room (Version 2) 建立 5 个核心实体表(包含多对多关联与安全升级 Migration):
| 字段 | 类型 | 说明 |
|---|---|---|
id (PK) |
TEXT | UUID 字符串主键 |
title |
TEXT | 日记标题(默认自动生成 日记 yyyy-MM-dd,用户可修改) |
content |
TEXT | 日记普通多行正文 |
eventTime |
INTEGER (Long) | 事情实际发生的时间戳(核心排序依据,带索引) |
createdAt |
INTEGER (Long) | 记录首次创建的时间戳(带索引) |
updatedAt |
INTEGER (Long) | 记录最后一次修改的时间戳 |
isFavorite |
INTEGER (Boolean) | 是否收藏(0=否,1=是,带索引) |
isDeleted |
INTEGER (Boolean) | 软删除标志(0=正常,1=回收站,带索引) |
| 字段 | 类型 | 说明 |
|---|---|---|
id (PK) |
TEXT | 标签 ID(系统默认:tag_system_diary、tag_system_memo) |
name |
TEXT | 标签名称(唯一索引,如“日记”、“备忘”) |
createdAt |
INTEGER (Long) | 创建时间戳 |
isSystem |
INTEGER (Boolean) | 是否为系统内置标签 |
| 字段 | 类型 | 说明 |
|---|---|---|
entryId (PK, FK) |
TEXT | 关联 journal_entries.id,开启 CASCADE 级联删除 |
tagId (PK, FK) |
TEXT | 关联 tags.id,开启 CASCADE 级联删除 |
| 字段 | 类型 | 说明 |
|---|---|---|
id (PK) |
TEXT | UUID 图片主键 |
entryId (FK) |
TEXT | 关联的外键 journal_entries.id,开启 CASCADE 级联删除 |
filePath |
TEXT | 本地私有存储绝对路径 |
width / height |
INTEGER | 图片宽高像素尺寸 |
sortOrder |
INTEGER | 多图展示排序索引 |
createdAt |
INTEGER (Long) | 添加时间戳 |
| 字段 | 类型 | 说明 |
|---|---|---|
id (PK) |
TEXT | UUID 音频主键 |
entryId (FK) |
TEXT | 关联的外键 journal_entries.id,开启 CASCADE 级联删除 |
filePath |
TEXT | 本地私有存储绝对路径 |
duration |
INTEGER (Long) | 音频毫秒时长 |
sortOrder |
INTEGER | 排序索引 |
createdAt |
INTEGER (Long) | 录制时间戳 |
- 严格安全升级:禁用破坏性重置
fallbackToDestructiveMigration(),确保老版本历史记录、图片和音频附件完整保留。 - 自动标题回填:为老数据统一回填默认标题:
日记 yyyy-MM-dd(按历史记录对应的eventTime计算)。 - 默认关联“日记”标签:自动将历史记录与内置“日记”系统标签建立关联。
- 无缝查看与直接编辑统一流:
- 点击记录直达编辑:在时间线、日历、搜索结果中点击任意已有记录直接打开
EntryEditorScreen(entryId),省去中间详情页与多余的“编辑”按钮; - 新建与修改页面完全统一:
+号新建与已有记录维护同一套 UI,新建生成 UUID,已有记录加载后即可修改; - 轻量顶部状态栏:采用简洁居中布局(
←返回、日记 yyyy-MM-dd标题、轻量渐隐“保存中…/已保存”状态、☆/★收藏星标与删除入口); - 自然非侵入式键盘交互:打开已有记录时不强制弹出软键盘,便于用户安静浏览,仅在点击文字输入区域时呼出输入法;
- 已有记录保护机制:即使已有记录的内容被用户完全删空,退出时依然保留该记录不自动误删,必须通过显式“移入废纸篓”确认操作删除。
- 点击记录直达编辑:在时间线、日历、搜索结果中点击任意已有记录直接打开
- 两层式全自动保存与返回拦截:
- 输入防抖自动入库:文字、标题、图片、语音或标签变更后,800ms Debounce 自动将修改写入 Room 数据库;
- 退出强保与有序返回:点击顶部返回、系统返回键、返回手势或点击“完成”时,严格执行
await saveCurrentEntryImmediate()确保落库完成后再关闭页面,绝不发生异步竞态; - 系统生命周期兜底:监听
ON_STOP事件,应用切到桌面或后台时自动触发脏数据持久化; - 空记录防污染:进入新建页若未输入任何实质内容直接退出,智能判断
hasMeaningfulContent == false,不产生任何空白垃圾日记; - UUID 单一持久化:进入新建页即固定全局唯一 UUID,多次自动保存稳定更新同一记录,不产生重复条目。
- 极简新建流与标题联动:
- 新建记录默认自动生成
日记 yyyy-MM-dd; - 修改发生日期时,未手动改动的默认标题自动同步变化;
- 一旦用户手动修改标题(如“海康面试记录”),后续再改日期绝不覆盖自定义标题;
- 首页时间线卡片层级化显示:时间、Semibold 标题、普通字重正文、图片与语音。
- 新建记录默认自动生成
- 多标签系统:
- 数据库建立合理的
Tag与EntryTagCrossRef多对多关系; - 内置“日记”与“备忘”两大系统标签,新建默认带有“日记”标签;
- 编辑页面提供 Material 3
FilterChip多选,支持单条记录挂载多个标签。
- 数据库建立合理的
- 时间线 FilterChip 数据库级筛选:
- 时间线顶部提供轻量
全部/日记/备忘/收藏快捷筛选; - 筛选直通 Room DAO 与响应式 Flow 查询,彻底杜绝 UI 层低效过滤,即时响应更新。
- 时间线顶部提供轻量
- 全功能多维度搜索:
- 搜索支持跨字段综合匹配:
title(标题)、content(正文)、tag name(标签名); - 搜索页顶部联动
全部/日记/备忘/收藏筛选维度; - 300ms Debounce 防抖机制;
- 空状态贴心展示“输入关键词搜索记录”。
- 搜索支持跨字段综合匹配:
- 时间线卡片流:
- 自动按日期聚合(例如
2026年9月26日 星期六); - 支持单图大缩略图、多图 2~3 列规整 Grid 矩阵布局;
- 完整播放语音卡片(支持暂停、播放、拖拽 Seek);
- 长按弹出底部操作单:编辑、收藏、修改时间、复制文本、系统分享、移入废纸篓。
- 自动按日期聚合(例如
- 快捷时间选择器:
- 弹窗直达:现在、今天、昨天、前天;
- 集成 Material 3 原生
DatePicker与TimePicker; - 排序严格依赖
eventTime,修改时间立即实时重排时间线。
- 文字草稿机制:新建日记过程中后台切走或重启自动保全已录入标题、正文、标签与图片。
- 图片全链路:
- PhotoPicker 多图选择与系统相机拍照;
- 本地沙盒私有存储迁移;
- 编辑器内删除、重新排序;
- 详情页与时间线内点击全屏浏览与左右滑动。
- 语音录制与播放:
- MediaRecorder 实时录音计时器展示与终止写入;
- 类似微信样式的语音气泡条;
- 同一条记录允许挂载多条语音;
- 拖拽进度条实时 Seek 响应。
- 月历视图:
- 阳历月历展示与有记录日期打点高亮;
- 支持点击某一天直接查看当天记录列表;
- 上个月、下个月与一键“返回今天”。
- 收藏与独立管理:
- 收藏作为独立 Boolean 字段,不与 Tag 混淆;
- 一键收藏/取消收藏,在时间线与搜索页随时过滤查看。
- 废纸篓与软删除:
- 删除先进入回收站;
- 支持单条恢复、单条粉碎,或一键清空废纸篓。
- 个性化外观系统:
- DataStore 实时持久化;
- 支持“跟随系统”、“浅色模式”、“深色模式”。
- 完整数据备份与恢复:
- 独立打包成
LifeLog_Backup_YYYY-MM-DD.zip; - 打包数据库所有记录(含新标题与标签关联)、元数据与物理媒体文件;
- 恢复时自动重构并适配新设备路径,安全可靠。
- 独立打包成
根据第一阶段产品定义,为了保证极致轻便与稳定性,以下特性留待后续迭代:
- 自动 30 天清理废纸篓:数据结构已提前支持,后续可通过 WorkManager 定时执行。
- 全文搜索扩展:后续可考虑对长文本支持 Room FTS4/FTS5 检索加速。
- 标签/分类系统:在不破坏一键快速记录体验的前提下,提供可选的轻量标签筛选。
- 生物识别加锁:支持指纹/面容解锁进入 App。