一个纯本地、无后端、无账号的 Android 习惯打卡应用,用 Jetpack Compose 从零构建。
🔒 本地优先(Local-first):所有数据只存在你手机本机的 Room 数据库里,App 不申请任何网络权限,不上传、不登录、不追踪。备份靠导出 JSON 文件,数据完全由你掌控。
DAKA 是一个自用优先、现在开源的习惯打卡工具。它不联网、不上云,目标就是把"今天该做哪几件事、连续做了几天"这件事做得简单又顺手:
- 分类随你建,想加"运动""读书""副业"随手就建,零迁移;
- 中国法定工作日 / 节假日内置,提醒不会在休息日乱响;
- 数据导出一个 JSON 就能备份、换机、分享。
| 能力 | 说明 |
|---|---|
| 习惯打卡 | 今日完成度、连续打卡天数(streak)、历史打卡记录 |
| 分类管理 | 内置 生活 / 工作 / 学习 / 健康,且可自定义任意分类(提交即建,零迁移) |
| 拖拽排序 | 长按拖动调整顺序、跨分类移动、置顶,带弹簧让位动画,跟手不卡顿 |
| 多提醒时间 | 一个习惯可设多条提醒(主提醒之外任意加),每条独立时间与重复规则,各自排期触发 |
| 跳过当天 | 长按卡片 → 跳过今天:不算完成也不算断签,连击自动穿过跳过日,随时可反悔 |
| CSV 导出 | 全部打卡记录导出 CSV(习惯、分类、日期),Excel / WPS 直接打开,带 BOM 中文不乱码 |
| 日历视图 | 月视图 + 当日提醒清单 + 系统日历双向同步 |
| 中国法定节假日 | 工作日判断内置 2026 官方安排(含调休),表外年份退化为普通周末判断 |
| 数据备份 / 恢复 | 导出 JSON(可分享),恢复前先预览再导入 |
| 交互音效 | 清脆可关 |
| 多语言(i18n) | 中文 / English 可切换(设置 → 语言),也跟随系统 |
| 主题 | 跟随系统 / 浅色 / 深色三选一(设置 → 主题),清新薄荷青绿配色底座,所有界面卡片重绘不闪屏 |
| 外观自定义 | 强调色无极取色(HSV 调色盘 + 8 色预设,即时重染全局主色系)+ 主页布局三选一(列表 / 网格 / 紧凑) |
| 今日进度环 | 首页顶部环形进度(CircularProgressIndicator)+ 随完成度变化的鼓励语,一眼看出今日完成比例 |
| 新手引导 | 首次启动三步引导,最后一步可选「不再显示」 |
| 统计页 | 周/月/年趋势图、年日历热力图、月历每日完成率着色、最佳连击等,原生 Canvas 绘制,无第三方图表库 |
| 检查更新 | 设置页显示当前 / 最新版本号,有新版红点提醒,1 小时缓存,不弹窗,自行决定是否更新 |
| 桌面快捷方式 | 长按图标:新建习惯 / 查看统计 / 一键打卡(批量补打今天所有未打卡活跃习惯) |
| 习惯备注 | 每个习惯可填备注(任意文本),随习惯存库;新建页草稿停手 400ms 自动保存,返回再进不丢 |
| 自适应图标 | 清新的绿色渐变圆角方 + 白色对勾 |
K40 真机截图(已裁掉顶部通知栏),共 6 张覆盖四个核心页面的浅/深主题:
| 首页(浅色) | 首页(深色) |
|---|---|
![]() |
![]() |
| 新建习惯 | 提醒日历 |
|---|---|
![]() |
![]() |
| 设置(浅色) | 设置(深色) |
|---|---|
![]() |
![]() |
每张习惯卡片底部都自带一行小字提示「◀ 左滑编辑 · 右滑置顶 ▶」, 配合首页底部的「左滑编辑 · 右滑置顶 · 长按拖动排序」,滑动手势不用猜就知道。 主题切换在「设置 → 主题」里,跟随系统 / 浅色 / 深色三选一,立即生效不闪屏。
| 类别 | 选型 |
|---|---|
| 语言 | Kotlin 2.2.10 |
| UI | Jetpack Compose (Material3) |
| 构建 | Android Gradle Plugin 9.3.2 / Gradle 9.5.0 |
| 最低 / 目标 / 编译 | minSdk 26 / targetSdk 37 / compileSdk 37 |
| 本地数据库 | Room 2.8.4(KSP 生成代码) |
| 键值存储 | DataStore (Preferences) |
| 导航 | Navigation Compose |
| JSON | kotlinx.serialization |
架构:UI(Compose)← ViewModel(StateFlow)← 数据层(Room DAO / Repository)。 数据库变更一律走 Room Migration,绝不丢老用户数据。
当前数据库版本 v7(含
reminders/habit_skips表,habits表含note列),迁移脚本集中在HabitDatabase.kt。
前置条件
- Android SDK(compileSdk 37)
- JDK 17
- 一台 Android 8.0+ 设备(或模拟器)
./gradlew assembleDebug # 调试包,可直接 adb install
./gradlew assembleRelease # 发布包(需配置签名,见下)默认
settings.gradle.kts使用阿里云 Maven 镜像加速国内依赖下载; 如需纯官方源,把镜像块注释掉即可(会自动回落官方源,不会"某个依赖突然拉不到")。
安装到已连接的设备:
adb install -r app/build/outputs/apk/debug/app-debug.apkrelease 构建默认不签名。生成你自己的密钥库后,在 local.properties
(已被 .gitignore 忽略,绝不提交)追加:
RELEASE_STORE_FILE=../daka-release.keystore
RELEASE_STORE_PASSWORD=你的密钥库密码
RELEASE_KEY_ALIAS=daka
RELEASE_KEY_PASSWORD=你的密钥密码生成密钥库:
keytool -genkeypair -v -keystore daka-release.keystore \
-alias daka -keyalg RSA -keysize 2048 -validity 10000app/build.gradle.kts 会在 local.properties 存在上述字段时自动启用 release 签名。
设置页 → 备份(导出 JSON 到共享存储,可分享给网盘 / 微信); 恢复时先预览(习惯数 / 记录数 / 导出日期)再导入。
⚠️ 数据库位于应用私有目录,卸载 App 会清除数据,请先备份。
长按桌面上的 DAKA 图标,弹出三个快捷操作(静态快捷方式,无需进 App):
| 快捷方式 | 行为 |
|---|---|
| 新建习惯 | 直接打开应用内「新建习惯」页 |
| 查看统计 | 直接打开「统计」页 |
| 一键打卡 | 一次性补打今天所有还没打卡的活跃习惯(已打卡的不重复打) |
一键打卡适合"睡前一键补完今天漏掉的"场景;若今天已全部打完,则提示"今天没有待打卡的习惯"。 显示前提是桌面启动器支持静态快捷方式(MIUI / 原生启动器 / 多数第三方启动器均支持)。
新建习惯页里的备注输入框为可选:随便写什么都行,返回时(停手 400ms)自动存草稿, 下次再进自动恢复,不会因误返回而清空。保存后备注随习惯一起存库,编辑页也能改。
从下拉通知栏的「编辑快捷开关」面板里,把 DAKA 磁贴拖进你的快捷区(第三方 App 的磁贴都需手动添加,无法自动塞进通知栏)。
添加后:
| 操作 | 行为 |
|---|---|
| 单击(点一下) | 直接打开「新建习惯」页 |
| 长按 | 进入 App 主界面(首页) |
单击走系统磁贴直达,比先解锁、再点图标、再点「+」更快一步。 长按的目标页面由 Manifest 里 MainActivity 的
ACTION_QS_TILE_PREFERENCES决定(API 34+); 旧系统上由Tile.setActivity实现,逻辑见app/.../quicktile/NewHabitTileService.kt。
新建 / 编辑习惯时,分类区提供内置 chip + 一个「自定义分类(可选)」输入框; 输入任意名称并保存,即自动创建该分类,首页自动把它当成一个新分组显示。
分类本质是 Habit.category 字符串字段,没有独立分类表,因此自建零成本。
app/src/main/java/com/marvin/daka/
├── model/ # 数据模型(Habit / 打卡记录 / 分类)
├── data/ # Room 数据库、DAO、Repository、Migration
├── ui/
│ ├── home/ # 首页(分组列表、拖拽排序、ViewModel)
│ ├── create/ # 新建 / 编辑习惯(含自定义分类输入框)
│ ├── calendar/ # 日历视图 + 系统日历同步
│ └── settings/ # 设置、备份 / 恢复
- 周 / 月打卡统计图表(统计页,原生 Canvas 绘制)
- 习惯模板库(一键导入常用习惯)
- 桌面快捷方式(新建 / 统计 / 一键打卡)+ 习惯备注草稿
- 多语言(i18n)
- 主题切换(跟随系统 / 浅色 / 深色)
- 每张卡片加侧滑操作提示
- 月历每日完成率热力着色(日历页每天按完成率深浅上色 + 图例)
- 统计页「最佳连击」(历史最长连续打卡天数)
- 多提醒时间 + 跳过当天(附加提醒表 + 跳过表,数据库 v7)
- CSV 导出(Excel 可开)
- 外观自定义(强调色无极取色 + 主页布局三选一)
- 迁移到新设备指引(导出分享 → 新机恢复)
- 自动化测试补齐
- 网格 / 紧凑布局补回分类分组显示:每个分类顶部显示分类名 + 今日完成度(x/total),与列表风格一致。
- 网格 / 紧凑布局补回滑动快捷操作:网格磁贴、紧凑行卡片支持「左滑编辑 / 右滑置顶」(与列表一致),带操作音效。
- 无障碍补齐:网格卡 / 紧凑行新增读屏自定义动作(置顶 / 编辑 / 移动 / 删除)。
- 底层:
SwipeableHabitCard改造为通用滑动包裹层(content 槽),三套卡片复用同一套滑动逻辑;按分类遍历渲染,删除原先拍平丢失分类的实现。 - 升级
versionName 1.4.0、versionCode 18。
- 强调色无极取色:设置 → 通用「强调色」由固定 8 色板升级为 HSV 无极取色盘(双 Canvas:饱和度×明度面板 + 彩虹色相条,可取任意颜色),保留 8 色预设快捷;重染 primary 系,深浅模式各自适配 tonal 关系。改完即时重组生效。
- 移除圆角风格:删去「标准 / 方正 / 圆润」三档圆角设置,回归 Material 3 默认中等圆角;同步删除仅为其服务的
ShapesCompat.java桥接。 - 今日进度更好看:首页顶部「今日进度」由朴素进度条改为环形进度(CircularProgressIndicator)+ 随完成度变化的鼓励语,一眼看出今日完成比例。
- 主页布局三选一:设置 → 通用新增「主页布局」——列表(默认,可拖动排序)/ 网格(两列磁贴)/ 紧凑(单行清单),三种风格在首页即时切换。
- 升级
versionName 1.3.9、versionCode 17。
- 多提醒时间:一个习惯可设多条提醒。主提醒留在习惯上,附加提醒存新的
reminders表(数据库 v6),调度器为每条提醒独立排期(requestCode 区分 habitId + reminderId),接收器按条触发、独立计数。新建/编辑页可增删改附加提醒,设置页提醒行显示附加数量。 - 跳过当天:操作面板新增「跳过今天」(已打卡不显示)。跳过日存
habit_skips表(数据库 v7):不算完成、不算断签——连续天数算法自动穿过跳过日,calcStreak/calcBestStreak均已支持;可随时取消跳过。 - CSV 导出:设置 → 备份区新增「导出 CSV」。打卡明细(习惯、分类、日期)按日期升序输出,UTF-8 带 BOM(Excel 中文不乱码),字段含逗号/引号/换行时按 RFC 4180 转义,导完可一键分享。
- 外观自定义:设置 → 通用新增「强调色」(8 色色板,重染 primary 系,深浅模式各自适配 tonal 关系)与「圆角风格」(标准 / 方正 / 圆润三档,整包替换全局 Shapes)。偏好存 DataStore,改完即时生效。
- 迁移到新设备:备份区新增「迁移到新设备」三步指引(老机备份分享 → 新机安装 → 新机恢复),备份格式升级 v2(新增 reminders / skips 数据,v1 旧备份完全兼容)。
- 兼容性:数据库 v5 → v7 走正式迁移(
MIGRATION_5_6/MIGRATION_6_7),老数据原样保留;Habit实现统一的ReminderLike接口,提醒引擎只认接口不认具体存储。 - 工程备注:material3 1.4.0 把
Shapes的 Kotlin 构造/copy 全部锁死(internal / HIDDEN),新增ShapesCompat.java桥接(Java 只认 JVM 可见性)为「圆角风格」留出生成入口。 - 升级
versionName 1.3.8、versionCode 16。
- 月历热力图:日历页每个月格按「当天完成率」着色(5 档深浅,与统计页年热力图同色系),并加图例。一眼看出哪天全勤、哪天划水。
- 统计页最佳连击:概览新增第 4 张卡「最佳连击」= 所有习惯里各自历史最长连续打卡天数的最大值,比「当前连击」更能体现长期毅力。
- 注:习惯「分组/标签/拖拽」早在 v1.3.x 已实现(首页按分类分组 + 跨分类拖动),本次未重复开发。
- 升级
versionName 1.3.7、versionCode 15。
- 取消桌面小组件功能:移除 2×2 / 4×3 / 1×4 三种 Glance 组件及其 Receiver、
res/xmlprovider、res/layout占位、Glance 依赖、WidgetColors、新手引导第 4 步。 - 原因:在 MIUI(Redmi K40)上,系统会在后台限流 / 丢弃 AppWidget 的更新调用,导致小组件长期显示旧数据、组件内点击无法即时反映。刷新代码本身正确、每次写入后都会调用,但 ROM 层限流无法在应用层彻底修复。按用户决定整体移除,消除「点了没反应 / 显示旧数据」的体感问题。
- 新手引导改为 3 步(去掉「桌面小组件」一步)。
- 升级
versionName 1.3.6、versionCode 14。
- 4×3 大组件由 Glance
LazyColumn改为固定Column(参考 Google Keep 清单不滚动范式),修复内部项点击不生效;组件读库改 suspend 直读。 - 回退 v1.3.4 的「电池优化豁免」入口(实测与小组件即时响应无关)。
- 后续确认小组件在 MIUI 后台刷新被 ROM 限流,最终于 v1.3.6 整体移除。
- 修复小组件「不实时」:
refreshHabitWidgets改为模块级非取消协程作用域,用户切走/杀后台后刷新广播仍会发出,不再依赖调用方ViewModelScope。 - MIUI 电池优化豁免入口:设置页新增「电池优化」项,显示当前是否已豁免;未豁免时一键跳系统对话框,把 DAKA 加入白名单,避免 MIUI / 国产 ROM 杀后台导致小组件刷新延迟几秒。
- 升级
versionName 1.3.4、versionCode 12。
- 桌面长按图标快捷方式(3 条):新建习惯(跳应用内新建页)、查看统计(跳统计页)、一键打卡(批量补打今天所有未打卡活跃习惯)。
- 习惯备注:新建 / 编辑习惯支持填备注(任意文本),随习惯存库。
- 备注草稿自动保存:新建页停手 400ms 自动落盘(DataStore),返回再进自动恢复,不丢失。
- 图标选择精简:图标推荐 3 行 → 2 行、颜色推荐 2 行 → 1 行,一屏多看更好选。
- 代码精简(功能不变):抽取
Habit.withReminder()统一三处提醒字段映射;HabitRecordDao新增exists(),提醒接收器与桌面小组件切换打卡免全表加载;数据库升至 v5(habits.note列,含 v4→v5 迁移,旧数据保留)。 - 真机(Redmi K40)复验:一键打卡正确补打缺失记录,无崩溃;Release APK v2 签名验证通过。
- 设置页新增「检查更新」:显示当前 / 最新版本号,有新版红点提醒,1 小时缓存,不弹窗,用户自行决定是否更新。
- 文案区分「当前已是最新版本」与真实失败提示。
- 配色底座换成清新薄荷青绿,去掉 Material You 动态取色,避免与 40 色习惯色板打架; 桌面小组件同步统一到同一族墨绿/青绿(之前是紫灰暗色调)。
- 设置 → 主题:跟随系统 / 浅色 / 深色三选一,Compose 换 colorScheme 即时重绘,不重建 Activity、不闪屏。
- 每张习惯卡片底部加一行侧滑操作提示「◀ 左滑编辑 · 右滑置顶 ▶」, 极淡 labelSmall 50% 透明,不抢打卡状态/7 天格子的视觉焦点; 首页底部那条全局提示保留,给长按拖动一起讲清楚。
- 桌面小组件和设置页加了对应的深色截图(README 截图区从 4 张扩到 6 张)。
- 全量字符串外置(中文/English),设置页可切换;日期/星期按应用语言本地化。
- 首启动 4 步引导,末步可勾「不再显示」。
- 桌面小组件从 1×1 / 4×3 双尺寸扩到 2×2 / 4×3 / 1×4 三尺寸(Keep 清单风格)。
- 保留左右滑提示,操作面板悬浮化;修复组件"点了不刷新"(用 DAO 直查替代 Flow 缓存)。
- 习惯打卡、分类管理、拖拽排序、每习惯独立提醒、日历视图(系统日历双向同步)、 法定节假日、JSON 备份/恢复、清脆音效、Keep 风格桌面小组件(2×2)。
欢迎在 Issue 里提建议或认领。
欢迎 Issue / PR。见 CONTRIBUTING.md。 请保持"纯本地、无后端"的产品定位——本仓库不接受引入网络同步 / 账号体系的改动。
MIT © 2026 Marvin
Marvin · 个人习惯打卡工具,自用起步,开源共享。





