立项背景: 日常消费频繁但记账习惯难养成,手动逐笔输入效率低且容易遗漏。大多数人的消费信息已经通过支付宝、微信、银行卡的推送通知触达手机,但这些通知阅后即焚,没有结构化沉淀。记花的核心思路是"被动记账"——监听系统通知,自动识别收付款信息并提取金额、商户、分类,用户只需确认即可完成记账,将记账操作从 30 秒缩短到 3 秒。
核心功能模块:
1. 通知自动记账:Android 端通过系统 NotificationListenerService 监听支付宝、微信、银行等 App 的支付推送,利用正则模板引擎(6 类模板、20+ 条规则覆盖支付宝/微信/银行/美团等场景)自动解析金额、类型(收入/支出)、商户名称,弹窗预填确认。去重机制(5 秒窗口 + 复合 key)避免同条通知重复记账。关键词过滤排除非支付通知(B站推送、充值成功等 20+ 条忽略规则)。
2. 手动记账:支持支出/收入切换,15 个支出分类 + 6 个收入分类(带图标和颜色标识),输入金额、商户、备注即可快速完成,防连点重复插入。
3. 预算管理:支持总预算和分类预算设置,进度条实时展示已用/剩余,达 80% 自动预警、超 100% 标红提醒。预警通知栏推送(每分类每 3 天最多 1 次,避免骚扰)。
4. 周期记账:支持每天/每周/每月/每季度等多种周期,App 打开时自动补记漏掉的历史周期,可单独启用/禁用。
5. 数据可视化:首页展示今日/本月收支卡片(横向滑动切换支出/收入)、分类占比环形图(Skia 自绘)、近 7 天趋势折线图(Victory Native);月度报告页支持历史月份切换,展示环比变化、Top3 支出分类、日均消费、记账天数等。
6. 数据导出导入:支持 CSV(含 BOM 兼容 Excel 中文)和 JSON 格式导出/导入,方便数据迁移和备份。
7. 深色模式与主题:支持亮色/暗色/跟随系统三种主题,全组件自适应配色。
8. 通知与保活:每日记账提醒(默认 21:00)、晚间支出汇总(默认 23:00);适配华为/小米/OPPO/vivo 等厂商的自启动设置引导;前台服务保活、电池优化白名单引导、悬浮窗速记(System Alert Window 权限)。
业务流程:用户安装 → 授权通知监听 → 支付时 App 自动弹窗预填 → 用户确认/编辑 → 记录存入 SQLite → 首页仪表盘/报告页实时刷新 → 月底查看月度报告和预算达成 → 导出数据备份。
项目实现
整体架构: 纯前端移动应用,基于 Expo 57(React Native 0.86 + React 19)开发,TypeScript 全量编写。数据存储使用 expo-sqlite 本地 SQLite 数据库(WAL 模式),状态管理使用 Zustand(3 个 Store:记录、应用设置、主题),路由使用 expo-router(基于文件的路由),图表渲染使用 @shopify/react-native-skia(自绘环形图)和 victory-native(趋势折线图)。通知监听通过自定义 Expo 原生模块实现 Android NotificationListenerService,JS 层通过 EventEmitter 接收事件。
我的负责模块与结果:
1. 通知解析引擎:设计了模板化正则解析器,每条规则定义 appId 匹配、正则表达式、金额捕获组、类型、商户捕获组,可扩展新增支付渠道。实现去重、关键词过滤、置信度评分机制。最终支付宝/微信场景解析准确率约 85%+。
2. 原生通知模块:独立开发 Expo 原生模块 PayRecordNotification,实现 NotificationListenerService 监听、EventEmitter 向 JS 层推送事件、通知权限检测与引导、前台服务保活、每日提醒/汇总 AlarmManager 调度、悬浮窗速记、预算预警通知栏推送。适配了小米/华为/OPPO/vivo 四大厂商的自启动设置 Intent 跳转。
3. 数据层与状态管理:设计 SQLite Schema,实现增量迁移,批量查询优化,Zustand Store 封装 CRUD + 自动刷新仪表盘。环形图数据补全,分页加载。
遇到的难点与解决方案:
1. 通知监听服务重启后丢失绑定:Android 重启后 NotificationListenerService 虽有权限但未绑定,导致监听失效。解决:在 JS 层启动时检测 isNotificationAccessGranted 返回 true 但 isListening 返回 false,主动调用 requestListenerRebind() 重新绑定,问题修复率接近 100%。
2. 支付宝/微信推送格式多变**:同一条消息"微信支付:已支付¥21.12"可能有合并通知"[4条]微信支付:…"、全角¥和半角¥混用等多种变体。解决:正则统一先做 normalize,模板中设置 flags: 's' 支持 DOTALL 模式匹配跨行内容,覆盖 20+ 种变体。
3. Skia 环形图渲染精度:当某个分类占比极小时(< 1%),弧度计算精度丢失导致图形闪烁。解决:对极小占比设置最小弧度阈值(3°),保证视觉稳定。