Skip to content
xiaotuantuanaPublic

About

Local-first Android timeline journal for text, photo, and voice notes, built with Kotlin, Jetpack Compose, Room, and DataStore.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

LifeLog - 个人生活时间线记录工具

定位:不是传统长篇大论的日记,而是一个极其方便的个人生活时间线记录工具。核心目标是让用户用最少的操作快速记录生活中的一件事情。


目录

  1. 项目简介
  2. 技术栈架构
  3. 项目完整结构
  4. 如何编译与运行
  5. 权限用途说明
  6. 数据存储位置与媒体生命周期
  7. 数据库架构设计
  8. 已完成功能列表
  9. 后续规划(尚未完成功能)

项目简介

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               // 复制剪贴板与原生分享扩展

如何编译与运行

1. 环境推荐

  • 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),支持真机与模拟器

2. 通过 Android Studio 打开

  1. 打开 Android Studio,点击 Open;
  2. 选择本工程根目录 LifeLog;
  3. Android Studio 将自动读取 gradle/wrapper/gradle-wrapper.properties,完成 Gradle 与相关依赖同步;
  4. 连接 Android 手机(开启 USB 调试)或启动 Android 模拟器;
  5. 点击工具栏绿色的 Run 'app' 按钮即可安装运行。

3. 命令行编译生成 APK

在终端运行:

# 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,确保重装系统或重启手机后依然可以长期加载:

  1. 图片存储目录:
    • 物理路径:context.filesDir/media/images/
    • 文件命名规则:IMG_{UUID}.jpg
    • 来源:从相册选中的图片或相机拍下的照片,一律由 MediaFileManager 拷贝至本目录并提取原始尺寸。
  2. 音频存储目录:
    • 物理路径:context.filesDir/media/audio/
    • 文件命名规则:AUD_{UUID}.m4a
    • 编码格式:AAC 音频编码、MPEG-4 封装容器,录音结束后自动写入该目录。
  3. 安全共享与预览:
    • 配置了标准 androidx.core.content.FileProvider,用于安全调用系统相机与分享备份包。
  4. 生命周期清理:
    • 在编辑中删除的未入库附件立即销毁;
    • 在废纸篓中执行“永久删除”或“清空废纸篓”时,触发物理文件回收删除,绝不发生存储泄露。

数据库架构设计

采用 Room (Version 2) 建立 5 个核心实体表(包含多对多关联与安全升级 Migration):

1. journal_entries(生活日记主表)

字段 类型 说明
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=回收站,带索引)

2. tags(标签表)

字段 类型 说明
id (PK) TEXT 标签 ID(系统默认:tag_system_diary、tag_system_memo)
name TEXT 标签名称(唯一索引,如“日记”、“备忘”)
createdAt INTEGER (Long) 创建时间戳
isSystem INTEGER (Boolean) 是否为系统内置标签

3. entry_tag_cross_ref(记录与标签多对多交叉表)

字段 类型 说明
entryId (PK, FK) TEXT 关联 journal_entries.id,开启 CASCADE 级联删除
tagId (PK, FK) TEXT 关联 tags.id,开启 CASCADE 级联删除

4. image_attachments(图片附件表)

字段 类型 说明
id (PK) TEXT UUID 图片主键
entryId (FK) TEXT 关联的外键 journal_entries.id,开启 CASCADE 级联删除
filePath TEXT 本地私有存储绝对路径
width / height INTEGER 图片宽高像素尺寸
sortOrder INTEGER 多图展示排序索引
createdAt INTEGER (Long) 添加时间戳

5. audio_attachments(音频附件表)

字段 类型 说明
id (PK) TEXT UUID 音频主键
entryId (FK) TEXT 关联的外键 journal_entries.id,开启 CASCADE 级联删除
filePath TEXT 本地私有存储绝对路径
duration INTEGER (Long) 音频毫秒时长
sortOrder INTEGER 排序索引
createdAt INTEGER (Long) 录制时间戳

6. Room 升级迁移策略 (MIGRATION_1_2)

  • 严格安全升级:禁用破坏性重置 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;
    • 打包数据库所有记录(含新标题与标签关联)、元数据与物理媒体文件;
    • 恢复时自动重构并适配新设备路径,安全可靠。

后续规划(尚未完成功能)

根据第一阶段产品定义,为了保证极致轻便与稳定性,以下特性留待后续迭代:

  1. 自动 30 天清理废纸篓:数据结构已提前支持,后续可通过 WorkManager 定时执行。
  2. 全文搜索扩展:后续可考虑对长文本支持 Room FTS4/FTS5 检索加速。
  3. 标签/分类系统:在不破坏一键快速记录体验的前提下,提供可选的轻量标签筛选。
  4. 生物识别加锁:支持指纹/面容解锁进入 App。

About

Local-first Android timeline journal for text, photo, and voice notes, built with Kotlin, Jetpack Compose, Room, and DataStore.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages