Skip to content

About

Android 16 本地记账 App:Jetpack Compose + Room,支持微信/支付宝支付通知自动记账

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

记账本 Ledger

一个跑在 Android 16 上的本地记账 App,付完钱自动帮你记一笔。

Kotlin · Jetpack Compose · Room · 纯本地存储 · 无需服务器 · 无需 root

Kotlin Jetpack Compose Android Room License


它解决什么问题

记账这件事真正的门槛不是"记",而是**"坚持记"**。手动记账 App 死于第三天——付完钱要掏手机、点开 App、输金额、选分类,太麻烦了。

这个 App 的做法是:你正常用微信/支付宝付款,它自己把流水记下来。 支付完成几秒后,一条带「自动」标签的记录就出现在列表里,金额、商户、收支方向都填好了。

数据全程存在你手机本地的 SQLite 里,不联网、不上传、不需要注册账号。


截图

首页 · 月度流水 记一笔 自动记账设置
首页 记一笔 自动记账设置
保存后回到列表 通知使用权已授权
保存后 已授权

截图摄于 vivo V2452A(Android 16,API 36,1260×2800)。


功能

基础记账

  • 月度视图:顶部左右箭头切月,汇总卡显示本月收入 / 支出 / 结余
  • 按日分组:今天 / 昨天 / 具体日期,每天带当日收支小计
  • 记一笔:支出 / 收入分段切换 → 自定义数字键盘 → 分类九宫格 → 备注 → 日期 → 保存
  • 编辑与删除:点列表项进编辑页改任意字段;列表长按或编辑页垃圾桶删除,均有二次确认

自动记账(v1.1.0 核心特性)

  • 监听微信支付、支付宝的支付通知,自动解析金额、方向、商户并入库
  • 三个开关:总开关 + 微信 + 支付宝,可单独关掉某一个
  • 按通知 key 去重:同一条通知重复推送只记一次
  • 商户关键词推断分类:美团→餐饮、滴滴→交通、京东→购物,猜不到落「其他」,随时可改
  • 记账后提醒(可选):弹一条系统通知,点进去直接改这笔
  • 列表里带「自动」标签,一眼区分手动录入和自动抓取

已处理的工程细节

  • 金额全程用 Long「分」 存储,只在展示时格式化,没有浮点误差
  • 数据库 Room v2,带 1→2 迁移脚本(自动记账字段为增量升级,老数据不丢)
  • 解析逻辑有 10 个 JUnit 单元测试覆盖金额/方向/商户的边界情况

下载

前往 Releases 页面下载 APK:

文件 大小 说明
ledger-v1.1.0-release.apk 11 MB 正式签名包,装这个(zipalign + v2/v3 签名)
ledger-v1.1.0-debug.apk 17 MB 调试包,仅开发用

安装方式:

adb install -r ledger-v1.1.0-release.apk

或直接把 APK 传到手机点开安装(Android 16 需给文件管理器授权「允许来自此来源的应用」)。


自动记账是怎么实现的

先说清楚约束:微信和支付宝都没有开放个人账单 API,第三方 App 拿不到交易记录。Android 上唯一不用 root 的路径是 NotificationListenerService——系统把通知文本转交给本 App,App 做解析。

流程:

微信/支付宝推送通知
        ↓
系统 NotificationListenerService 回调
        ↓
PaymentNotificationParser  正则抠金额 + 判方向 + 抽商户
        ↓
AutoCategoryRules          商户关键词 → 分类
        ↓
Room 插入(notifKey 唯一索引,重复自动忽略)
        ↓
LedgerNotifier 可选提醒 → 点通知进编辑页

解析规则

项 规则
金额 ¥12.50 / 12.50元 / 付款12.50 三种模式按优先级匹配,BigDecimal 精确转分
收支方向 命中 退款 / 收款 / 收钱 / 入账 / 转入 → 收入,否则支出
分类 商户关键词表匹配,未命中落「其他」
去重 同一 StatusBarNotification.key 只记一次(IGNORE 插入策略)
兜底 来源关键词和金额必须同时命中才入库——宁可漏记,绝不记错

⚠️ 一个踩过的坑:方向判断词里不能放「支付」,因为「支付宝」三个字本身包含它,会让所有支付宝通知都被误判为支出。这条已写进单元测试锁住。

开启步骤

  1. 首页右上角 ⚙ → 自动记账
  2. 点「去系统设置授权」,在系统页给记账本打开通知使用权(Android 不允许 App 自己开)
  3. 打开「启用自动记账」,按需勾选微信 / 支付宝
  4. 想要提醒就再给一下通知权限(Android 13+)

也可以用 adb 一条命令授权:

adb shell cmd notification allow_listener com.qaq.ledger/com.qaq.ledger.autotrack.LedgerNotificationListener

必须用完整组件名,短写法 com.qaq.ledger/.autotrack... 在部分 ROM 上会静默失败。


从源码构建

环境要求

  • JDK 21
  • Android SDK:API 36(Android 16) + Build-Tools 36.0.0
  • Android Studio Narwhal 2025.1 或更新(可选,命令行也能出包)

用 Android Studio

  1. File → Open 选择本目录
  2. 点 Sync Now 等依赖下载完(首次约 5–15 分钟)
  3. SDK Manager 勾选 Android 16(API 36) 和 Build-Tools 36
  4. 建一个 API 36 的 AVD(或用真机),点 ▶ Run

纯命令行

export ANDROID_HOME=/path/to/android-sdk
./gradlew assembleDebug      # 调试包
./gradlew assembleRelease    # 未签名正式包(再用 apksigner 签名)
./gradlew test               # 跑解析器单元测试

项目根目录的 local.properties 需写入 sdk.dir=<你的 SDK 路径>,Windows 下冒号要转义:sdk.dir=C\:\\Users\\you\\android-sdk。


项目结构

app/src/main/java/com/qaq/ledger/
├── MainActivity.kt               唯一 Activity,enableEdgeToEdge()
├── LedgerApp.kt                  Application,持有依赖容器
├── autotrack/
│   ├── LedgerNotificationListener.kt   NotificationListenerService 入口
│   ├── PaymentNotificationParser.kt    金额/方向/商户解析(有单测)
│   ├── AutoCategoryRules.kt            商户 → 分类关键词表
│   └── LedgerNotifier.kt               「已自动记账」提醒
├── data/
│   ├── AppContainer.kt           极简 DI(不引 Hilt)
│   ├── SettingsRepository.kt     开关持久化(SharedPreferences + StateFlow)
│   ├── db/AppDatabase.kt         Room 数据库,version 2 + MIGRATION_1_2
│   ├── db/Converters.kt          LocalDate ↔ epochDay
│   ├── dao/TransactionDao.kt     Flow 查询
│   ├── model/                    Transaction / TxType / Category / TxSource
│   └── repository/               仓库与月度汇总逻辑
├── ui/
│   ├── LedgerNavHost.kt          Navigation Compose 路由
│   ├── theme/                    Material3 主题与配色
│   ├── home/                     首页 + HomeViewModel
│   ├── editor/                   记一笔 / 编辑页 + ViewModel
│   ├── settings/                 自动记账设置页
│   └── components/               汇总卡 / 流水行 / 数字键盘 / 日期选择器
└── util/
    ├── Format.kt                 金额与日期格式化
    ├── NotificationAccess.kt     通知使用权检测
    └── ViewModelFactory.kt       简易 ViewModel 工厂

技术栈

依赖 版本
Gradle 8.11.1
Android Gradle Plugin 8.9.1
Kotlin 2.1.20
KSP 2.1.20-1.0.31
Compose BOM 2025.03.01
Room 2.7.0
compileSdk / targetSdk 36
minSdk 26(Android 8.0)

Kotlin 与 KSP 版本必须严格成对,升级 Kotlin 时务必同步改 KSP。

Android 16 适配

  • 边到边显示:targetSdk ≥ 35 强制生效,已调用 enableEdgeToEdge(),键盘区加 navigationBarsPadding()
  • 预测式返回:Manifest 中 android:enableOnBackInvokedCallback="true"
  • 16KB 内存页对齐:AGP 8.5+ 默认处理
  • 备份规则:res/xml/data_extraction_rules.xml 限定云备份范围
  • 自适应图标:矢量 drawable(minSdk 26 起可用,无需多套 PNG)

已知限制

  • 通知文案随微信 / 支付宝版本变化,改版后可能解析不到(此时该笔不记录,不会记错)
  • 收款方向靠关键词推断,好友转账的收款通知也可能判成收入,需人工核对
  • 商户名抽取是尽力而为,抽不到就写「微信支付」「支付宝」
  • 国产 ROM 的电池优化会杀后台:vivo / OriginOS 需在 设置 → 电池 → 后台耗电管理 里允许后台运行,并在权限管理中允许自启动
  • 首版固定浅色主题,未做深色配色
  • isMinifyEnabled = false,开启混淆前需补齐 proguard-rules.pro

路线图

  • 导出 CSV / JSON 备份与导入(优先级最高——纯本地 App 清数据就没了)
  • 统计图表:分类饼图 + 趋势折线
  • 月度预算与超支提醒
  • 自定义分类管理(图标 / 名称 / 颜色)
  • 深色主题

隐私

  • 不联网,无任何网络权限
  • 数据仅存于本机 SQLite(ledger.db)
  • 通知文本解析完即丢弃,不留存、不上传

许可

MIT License — 随便用、随便改。

About

Android 16 本地记账 App:Jetpack Compose + Room,支持微信/支付宝支付通知自动记账

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages