移除验证码解析功能,简化为纯短信转发
- 删除 VerificationCodeParser 及相关测试,短信捕获和推送不再解析验证码 - 飞书推送改为只发送短信原文,时间戳格式化为可读日期 - 移除主界面"只推送验证码"开关和"调试时上传完整短信正文"选项 - 移除"保存轮询间隔"按钮,开启轮询时自动保存间隔(未输入默认1秒) - 按钮文字从"开始1秒轮询验证码"改为"开始短信轮询" - 删除"打印最近30条短信"功能及相关 SmsInboxReader.logRecentMessages - SmsInboxReader 用 RecentSmsResult 替换 RecentCodeResult - FeishuWebhookConfigStore.Config 移除 filterVerificationCode/sendFullBodyDebug - 修复代码缩进不一致问题
This commit is contained in:
@@ -86,7 +86,7 @@ Android 侧用 `JSONObject` / `JSONArray` 构造,避免手写 JSON 字符串
|
||||
`BroadcastReceiver.onReceive` 生命周期短,不能同步执行网络请求。后续实现应采用:
|
||||
|
||||
- `FeishuWebhookClient.pushMarkdownAsync(...)` 提交到后台 `ExecutorService`。
|
||||
- `SmsReceiver` 在验证码解析成功、保存本地结果后,只触发异步推送,不等待网络结果。
|
||||
- `SmsReceiver` 在短信原文读取成功、保存本地结果后,只触发异步推送,不等待网络结果。
|
||||
- 推送结果写入 `SharedPreferences` 或轻量状态 store,并通过本地广播刷新 UI。
|
||||
- 若未来需要保证进程退出后仍发送,可另起 change 引入 WorkManager;本轮不做。
|
||||
|
||||
@@ -97,7 +97,6 @@ Android 侧用 `JSONObject` / `JSONArray` 构造,避免手写 JSON 字符串
|
||||
- `webhook_id`
|
||||
- `secret`
|
||||
- `enabled`
|
||||
- `sendFullSmsBodyForDebug`,默认 false
|
||||
- 最近一次推送状态、时间、错误类型和错误摘要
|
||||
|
||||
飞书 webhook 配置保存到 `/sdcard/Android/data/{applicationId}/config/feishu.json`。如果 `feishu.json` 不存在,app 生成默认模板 `/sdcard/Android/data/{applicationId}/config/def_config_feishu.json`,但不把模板当作生效配置。这样调试时可以直接改 `feishu.json`,不需要重新编译 Android 代码。
|
||||
@@ -106,13 +105,13 @@ Android 侧用 `JSONObject` / `JSONArray` 构造,避免手写 JSON 字符串
|
||||
|
||||
### 6. 推送内容策略
|
||||
|
||||
验证码解析成功时,默认 markdown 内容建议包含:
|
||||
短信原文读取成功时,默认 markdown 内容建议包含:
|
||||
|
||||
- 验证码:解析出的 code。
|
||||
- 短信原文。
|
||||
- 来源:`system_sms_broadcast` / `sms_inbox_*`。
|
||||
- 发送方:掩码后的 sender。
|
||||
- 时间:本地格式化时间。
|
||||
- 解析策略和置信度:便于诊断。
|
||||
- 如存在读取异常,附带失败摘要。
|
||||
|
||||
默认包含完整短信原文,便于远端调试确认。仍不建议在 logcat 打印完整正文。
|
||||
|
||||
@@ -143,11 +142,11 @@ Android 侧用 `JSONObject` / `JSONArray` 构造,避免手写 JSON 字符串
|
||||
|
||||
## Privacy Boundaries
|
||||
|
||||
- 默认仅上传验证码和必要诊断摘要。
|
||||
- 飞书推送默认包含完整短信正文;开启推送即表示允许验证码短信离开设备。
|
||||
- 默认上传短信原文和必要诊断摘要。
|
||||
- 飞书推送默认包含完整短信正文;开启推送即表示允许短信内容离开设备。
|
||||
- 不上传联系人通讯录、短信历史或设备标识。
|
||||
- 本地保存 secret 时使用 `SharedPreferences` 只满足个人调试场景;如需更严格保护,应另起 change 使用 Android Keystore 加密。
|
||||
- 推送到飞书意味着验证码会离开设备,UI 应让用户明确知道远端推送已开启。
|
||||
- 推送到飞书意味着短信内容会离开设备,UI 应让用户明确知道远端推送已开启。
|
||||
|
||||
## Test Strategy
|
||||
|
||||
@@ -168,7 +167,7 @@ Android 侧用 `JSONObject` / `JSONArray` 构造,避免手写 JSON 字符串
|
||||
- 使用真实飞书机器人确认收到 markdown 卡片。
|
||||
- 故意填错 secret,确认 UI 显示飞书业务错误而不是短信接收失败。
|
||||
- 断网或飞行模式下测试 `network_error`/`timeout`。
|
||||
- 收到真实验证码短信后,确认本地结果先保存,远端推送状态独立更新。
|
||||
- 收到真实短信后,确认本地结果先保存,远端推送状态独立更新。
|
||||
|
||||
## Rollout Plan
|
||||
|
||||
@@ -177,12 +176,12 @@ Android 侧用 `JSONObject` / `JSONArray` 构造,避免手写 JSON 字符串
|
||||
3. 实现签名、请求体构造、响应解析和异步发送模块。
|
||||
4. 增加 JSON 配置 store 和最近推送状态。
|
||||
5. 在 `MainActivity` 增加配置、测试发送和状态展示。
|
||||
6. 将验证码解析成功后的推送接入异步链路。
|
||||
6. 将短信原文读取成功后的推送接入异步链路。
|
||||
7. 增加聚焦单元测试,不要求本轮编译。
|
||||
|
||||
## Open Questions
|
||||
|
||||
- webhook id 和 secret 是否只用于本机调试,还是需要后续提供导入/导出配置。
|
||||
- 默认推送内容是否只发验证码,还是需要包含发送方掩码和解析策略。
|
||||
- 是否需要推送所有收到的字符串,还是只在验证码解析成功时推送。
|
||||
- 默认推送内容是否只发短信原文,还是需要包含发送方掩码和来源等诊断摘要。
|
||||
- 是否需要推送所有收到的字符串,还是只在短信原文读取成功时推送。
|
||||
- 如果网络失败,是否需要后续补发;本轮建议不做持久化补发队列。
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Why
|
||||
|
||||
当前 `SmsReceive` 已经具备短信验证码接收、解析、存储和本地诊断能力。新需求是在收到字符串内容后,把它发送到服务器。用户已经给出 Python 参考实现,目标服务器实际是飞书机器人 webhook:构造 interactive markdown 卡片,使用 `timestamp + "\n" + secret` 生成 HmacSHA256 + Base64 签名,然后 POST 到 `https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}`。
|
||||
当前 `SmsReceive` 已经具备短信原文接收、存储和本地诊断能力。新需求是在收到字符串内容后,把它发送到服务器。用户已经给出 Python 参考实现,目标服务器实际是飞书机器人 webhook:构造 interactive markdown 卡片,使用 `timestamp + "\n" + secret` 生成 HmacSHA256 + Base64 签名,然后 POST 到 `https://open.feishu.cn/open-apis/bot/v2/hook/{webhook_id}`。
|
||||
|
||||
这次变更的重点不是重新设计服务端协议,而是把 Python 中已经验证过的请求协议等价迁移到 Android,并与当前短信接收链路解耦。Android 侧应提供一个可测试、可诊断、可复用的发送模块,后续可以由 `SmsReceiver`、手动测试按钮或其它业务入口调用。
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
- 实际配置从 `/sdcard/Android/data/{applicationId}/config/feishu.json` 读取,便于动态调试。
|
||||
- 如果 `feishu.json` 不存在,则生成默认模板 `/sdcard/Android/data/{applicationId}/config/def_config_feishu.json`。
|
||||
- 后续实现可接入当前短信结果:
|
||||
- 成功解析验证码后,可以把验证码摘要、来源、时间和发送方掩码作为 markdown 内容推送。
|
||||
- 按调试需求推送完整短信原文,便于确认服务端收到的内容与本机短信一致。
|
||||
- 成功读取短信原文后,可以把短信内容、来源、时间和发送方掩码作为 markdown 内容推送。
|
||||
- 默认推送完整短信原文,便于确认服务端收到的内容与本机短信一致。
|
||||
|
||||
## Capabilities
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `sms-code-capture`: 后续实现可以在验证码解析成功后触发推送,但短信捕获本身不依赖网络成功。
|
||||
- `sms-code-capture`: 后续实现可以在短信原文读取成功后触发推送,但短信捕获本身不依赖网络成功。
|
||||
- `sms-receiver-delivery-diagnostics`: 后续诊断应区分“短信接收/解析成功”和“远端推送成功/失败”,避免把网络失败误判为短信接收失败。
|
||||
|
||||
## Impact
|
||||
@@ -40,14 +40,14 @@
|
||||
- `app/src/main/AndroidManifest.xml`:新增 `android.permission.INTERNET`。
|
||||
- `app/src/main/java/com/smsreceive/app/`:新增飞书推送相关 Java 类,例如 `FeishuWebhookClient`、`FeishuWebhookConfigStore`、`FeishuWebhookPushResult`。
|
||||
- `MainActivity`:新增 JSON 配置路径展示、配置输入、测试发送和最近推送结果展示。
|
||||
- `SmsReceiver` 或统一结果处理层:在验证码解析成功后触发异步推送。
|
||||
- `SmsReceiver` 或统一结果处理层:在短信原文读取成功后触发异步推送。
|
||||
- 推荐技术选择:
|
||||
- 网络库:OkHttp。
|
||||
- JSON 构造/解析:优先使用 Android 自带 `org.json`,降低依赖数量。
|
||||
- 签名:`javax.crypto.Mac` + `SecretKeySpec` + `android.util.Base64.NO_WRAP`。
|
||||
- 异步执行:小型 `ExecutorService` 或现有轻量后台执行器,不引入协程/RxJava。
|
||||
- 隐私影响:
|
||||
- 默认推送验证码摘要、来源、发送方掩码、时间和短信原文。
|
||||
- 默认推送短信原文、来源、发送方掩码和时间。
|
||||
- 不在 logcat 打印 secret、sign、完整 webhook URL 或完整短信正文。
|
||||
|
||||
## Validation
|
||||
|
||||
@@ -33,7 +33,7 @@ The app SHALL send markdown content to the Feishu bot webhook using the same req
|
||||
The app SHALL avoid blocking UI and SMS broadcast handling while sending webhook requests.
|
||||
|
||||
#### Scenario: SMS receiver triggers a push
|
||||
- **WHEN** a verification code is parsed successfully in `SmsReceiver`
|
||||
- **WHEN** a new SMS capture result is stored successfully in `SmsReceiver`
|
||||
- **THEN** the app MUST save the local capture result first
|
||||
- **AND** it MUST dispatch the webhook push asynchronously
|
||||
- **AND** it MUST NOT wait for the network request before returning from broadcast handling
|
||||
@@ -85,12 +85,11 @@ The app SHALL avoid exposing webhook secrets while sending complete SMS content
|
||||
- **THEN** it MUST mask the secret
|
||||
- **AND** it MUST NOT log the generated signature or full webhook URL
|
||||
|
||||
#### Scenario: Verification code push content is built
|
||||
- **WHEN** the app builds markdown content from a parsed SMS result
|
||||
- **THEN** it MUST include the verification code and minimal diagnostics such as source, masked sender, time, strategy, and confidence
|
||||
- **AND** it MUST include the full original SMS body
|
||||
#### Scenario: SMS push content is built
|
||||
- **WHEN** the app builds markdown content from an SMS capture result
|
||||
- **THEN** it MUST include the full original SMS body and minimal diagnostics such as source, masked sender, time, and any structured failure reason when present
|
||||
|
||||
#### Scenario: Webhook push is disabled
|
||||
- **WHEN** a verification code is parsed while push is disabled
|
||||
- **WHEN** an SMS is captured while push is disabled
|
||||
- **THEN** the app MUST keep local SMS capture behavior unchanged
|
||||
- **AND** it MUST record or report that remote push was skipped because it is disabled
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
## 5. Config And State
|
||||
|
||||
- [x] 5.1 新增 `FeishuWebhookConfigStore`,通过 `/sdcard/Android/data/{applicationId}/config/feishu.json` 保存 enabled、webhook id、secret 和 debug 上传开关
|
||||
- [x] 5.1 新增 `FeishuWebhookConfigStore`,通过 `/sdcard/Android/data/{applicationId}/config/feishu.json` 保存 enabled、webhook id 和 secret
|
||||
- [x] 5.2 新增最近推送状态,包含时间、成功状态、错误类型和错误摘要
|
||||
- [x] 5.3 UI 展示 secret 时使用掩码
|
||||
- [x] 5.4 默认推送完整短信原文,便于远端调试
|
||||
@@ -46,10 +46,10 @@
|
||||
|
||||
## 7. SMS Flow Integration
|
||||
|
||||
- [x] 7.1 验证码解析成功后构造默认 markdown 摘要
|
||||
- [x] 7.1 短信原文读取成功后构造默认 markdown 摘要
|
||||
- [x] 7.2 `SmsReceiver` 保存本地结果后触发异步推送
|
||||
- [x] 7.3 推送失败不影响本地短信捕获、解析和 UI 刷新
|
||||
- [x] 7.4 默认推送内容包含验证码、来源、发送方掩码、时间、解析摘要和短信原文
|
||||
- [x] 7.4 默认推送内容包含短信原文、来源、发送方掩码和时间
|
||||
|
||||
## 8. Tests
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Context
|
||||
|
||||
当前 app 已有短信验证码接收实现:Manifest 声明了 `RECEIVE_SMS`、`READ_SMS`,静态 `SmsReceiver` 监听 `android.provider.Telephony.SMS_RECEIVED`,`MainActivity` 提供权限申请、最近结果展示、`READ_SMS` 最新短信读取、ContentObserver 和短时轮询诊断。用户反馈“逻辑试过了能用”,但不确定为什么某些场景 `onReceive` 收不到。
|
||||
当前 app 已有短信原文接收实现:Manifest 声明了 `RECEIVE_SMS`、`READ_SMS`,静态 `SmsReceiver` 监听 `android.provider.Telephony.SMS_RECEIVED`,`MainActivity` 提供权限申请、最近结果展示、`READ_SMS` 最新短信读取、ContentObserver 和短时轮询诊断。用户反馈“逻辑试过了能用”,但不确定为什么某些场景 `onReceive` 收不到。
|
||||
|
||||
目标设备是小米 12S、澎湃 OS 3、Android 15。根据 Android 官方文档,`RECEIVE_SMS` 允许应用接收 SMS,但它是 dangerous 且 hard restricted 权限,是否能真正持有可能受安装来源/安装器 allowlist 影响。Android 15 又新增了 `BOOT_COMPLETED` 启动部分前台服务类型的限制;Doze/App Standby 白名单也不是无限制后台执行。小米官方支持文档说明 HyperOS/小米系统存在“Background autostart”用户开关,路径为 Settings > Apps > Permissions > Background autostart。
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
### 1. 系统短信广播仍是主路径
|
||||
|
||||
短信进入设备时,主路径仍是 `SMS_RECEIVED_ACTION`。这是最直接的验证码捕获路径,但它依赖:
|
||||
短信进入设备时,主路径仍是 `SMS_RECEIVED_ACTION`。这是最直接的短信原文捕获路径,但它依赖:
|
||||
|
||||
- 应用真正持有 `RECEIVE_SMS`。
|
||||
- 应用未被用户 force-stop。
|
||||
@@ -129,7 +129,7 @@ Android 标准能力:
|
||||
2. 发送短信时抓 logcat `SmsReceive`。
|
||||
3. 如果 receiver 无日志,点“读取最新短信”确认短信是否入库。
|
||||
4. 如果短信已入库但 receiver 无日志,重点排查权限、force-stop、HyperOS 自启动和省电。
|
||||
5. 如果 receiver 有日志但无验证码,排查 PDU/body/parser。
|
||||
5. 如果 receiver 有日志但无短信结果,排查 PDU/body/读取链路。
|
||||
|
||||
## Data Model
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Why
|
||||
|
||||
当前 `SmsReceive` 已经能在部分场景接收并解析验证码短信,但目标设备是小米 12S、澎湃 OS 3、Android 15,后台策略比标准 Android 更激进。仅靠 `SMS_RECEIVED_ACTION` 静态广播不够,需要补齐“开机后自动恢复监听、后台运行可见、系统设置可引导、失败可诊断”的完整方案。
|
||||
当前 `SmsReceive` 已经能在部分场景接收并展示短信原文,但目标设备是小米 12S、澎湃 OS 3、Android 15,后台策略比标准 Android 更激进。仅靠 `SMS_RECEIVED_ACTION` 静态广播不够,需要补齐“开机后自动恢复监听、后台运行可见、系统设置可引导、失败可诊断”的完整方案。
|
||||
|
||||
这次需求的重点不是规避系统限制,而是在个人自用 sideload/debug app 的边界内,把 Android 官方后台机制、HyperOS 人工设置、短信广播兜底路径和可验证诊断组合起来。用户也会手动在小米设置中开启“自启动”和“省电策略-无限制”,因此方案应显式利用这个前提。
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
- [x] 6.1 记录最近一次 `system_sms_broadcast` 到达时间
|
||||
- [x] 6.2 记录最近一次 `sms_inbox_observer`、`sms_inbox_manual`、`sms_inbox_polling` 命中时间
|
||||
- [x] 6.3 当收件箱兜底发现新验证码但广播未到达时,展示“疑似短信广播未投递”
|
||||
- [x] 6.3 当收件箱兜底发现新短信但广播未到达时,展示“疑似短信广播未投递”
|
||||
- [x] 6.4 在 UI 中列出 `onReceive` 不触发的排查清单
|
||||
- [x] 6.5 增加 logcat 输出,区分权限缺失、body 为空、parser 失败、广播未到达
|
||||
|
||||
@@ -62,15 +62,15 @@
|
||||
- [ ] 8.1 为 `KeepAliveStateStore` 增加状态读写测试
|
||||
- [ ] 8.2 为 Boot action 处理逻辑增加单元测试
|
||||
- [ ] 8.3 为设置 intent fallback 增加测试或可验证日志
|
||||
- [x] 8.4 保持现有验证码解析测试通过
|
||||
- [x] 8.4 保持现有短信接收与结果展示测试通过
|
||||
- [x] 8.5 不要求本轮编译;代码完成后再按用户要求通知
|
||||
|
||||
## 9. Xiaomi 12S / HyperOS 3 Device Validation
|
||||
|
||||
- [ ] 9.1 手动开启小米自启动
|
||||
- [ ] 9.2 手动设置省电策略为无限制
|
||||
- [ ] 9.3 开启常驻通知,后台 30 分钟后发送验证码短信
|
||||
- [ ] 9.4 锁屏 30 分钟后发送验证码短信
|
||||
- [ ] 9.3 开启常驻通知,后台 30 分钟后发送测试短信
|
||||
- [ ] 9.4 锁屏 30 分钟后发送测试短信
|
||||
- [ ] 9.5 重启手机,确认保活服务是否自动恢复
|
||||
- [ ] 9.6 重启后未打开 app 直接发送第一条短信,记录广播是否到达
|
||||
- [ ] 9.7 手动 force-stop 后发送短信,确认不承诺接收,并记录诊断表现
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
|
||||
当前 `SmsReceive` 目录几乎为空,只有 macOS 生成的 `.DS_Store`,没有 Android 工程和既有 OpenSpec 目录。用户要求先生成完整 spec 方案,再开始编码;同时明确 Android Studio、Gradle、JDK 等环境不在本次方案范围内,后续实现要参考 `Weather reference project` 的构建环境。
|
||||
|
||||
目标设备是小米 12S、澎湃 OS 3、Android 15。需求本质是个人自用工具:收到手机短信验证码后,应用读取短信正文、提取验证码并展示。由于不是 Play Store 上架应用,方案可以直接使用短信权限,但仍要面对 Android 运行时权限、Android 15 受限权限策略、厂商后台管理和短信广播分发行为。
|
||||
目标设备是小米 12S、澎湃 OS 3、Android 15。需求本质是个人自用工具:收到手机短信后,应用读取短信原文并展示。由于不是 Play Store 上架应用,方案可以直接使用短信权限,但仍要面对 Android 运行时权限、Android 15 受限权限策略、厂商后台管理和短信广播分发行为。
|
||||
|
||||
官方 API 判断如下:
|
||||
|
||||
- Android `Telephony.Sms.Intents.SMS_RECEIVED_ACTION` 是收到文本短信的系统广播,需要 `RECEIVE_SMS` 权限。它是读取任意短信验证码最直接的路径。
|
||||
- Google `SMS Retriever API` 不需要 `READ_SMS` 或 `RECEIVE_SMS`,但短信必须包含 app hash,适合服务端短信模板可控的手机号验证,不适合读取所有第三方验证码。
|
||||
- Google `SMS User Consent API` 可以请求用户授权读取单条包含验证码的短信,不要求 app hash,但需要弹出用户确认,适合作为受限权限或广播异常时的对比验证路径。
|
||||
- Android `Telephony.Sms.Intents.SMS_RECEIVED_ACTION` 是收到文本短信的系统广播,需要 `RECEIVE_SMS` 权限。它是读取任意短信原文最直接的路径。
|
||||
- Google `SMS Retriever API` 不需要 `READ_SMS` 或 `RECEIVE_SMS`,但短信必须包含 app hash,适合服务端短信模板可控的场景,不适合读取所有第三方短信。
|
||||
- Google `SMS User Consent API` 可以请求用户授权读取单条短信,不要求 app hash,但需要弹出用户确认,适合作为受限权限或广播异常时的对比验证路径。
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- 先形成可执行 spec,不直接写业务代码。
|
||||
- 建立 Android 15 上读取验证码短信的主路径和备选路径。
|
||||
- 明确验证码解析、权限状态、诊断状态和真机验证标准。
|
||||
- 建立 Android 15 上读取短信原文的主路径和备选路径。
|
||||
- 明确短信原文展示、权限状态、诊断状态和真机验证标准。
|
||||
- 后续实现应保持最小化:一个主界面、一个接收链路、一组诊断信息,不做复杂产品化。
|
||||
- 保持短信内容本地处理,默认只展示验证码、来源、时间和短诊断摘要。
|
||||
- 保持短信内容本地处理,默认展示短信原文、来源、时间和短诊断摘要。
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
@@ -26,13 +26,13 @@
|
||||
- 不实现发送短信、删除短信、读取历史短信库或同步短信到云端。
|
||||
- 不处理 Android Studio、Gradle、JDK 的重新安装和环境拉取。
|
||||
- 不以 Google Play 上架合规作为约束目标。
|
||||
- 不保证所有银行、平台、运营商验证码都能被无条件读取;必须通过真机验证确认。
|
||||
- 不保证所有银行、平台、运营商短信都能被无条件读取;必须通过真机验证确认。
|
||||
|
||||
## Decisions
|
||||
|
||||
### Decision 1: 主路径使用 `SMS_RECEIVED_ACTION` + `RECEIVE_SMS`
|
||||
|
||||
主路径选择系统短信广播。原因是目标是读取“我自己的手机收到的验证码”,短信来源不可控,很多验证码短信不会带当前 app 的 hash,`SMS Retriever API` 无法覆盖任意验证码。系统广播能拿到完整 PDU,再通过 `Telephony.Sms.Intents.getMessagesFromIntent(Intent)` 合并为正文,是最符合目标的能力。
|
||||
主路径选择系统短信广播。原因是目标是读取“我自己的手机收到的短信原文”,短信来源不可控,很多短信不会带当前 app 的 hash,`SMS Retriever API` 无法覆盖任意短信。系统广播能拿到完整 PDU,再通过 `Telephony.Sms.Intents.getMessagesFromIntent(Intent)` 合并为正文,是最符合目标的能力。
|
||||
|
||||
实现要求:
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
- 对 Android 6.0+ 执行运行时权限申请。
|
||||
- 注册接收 `android.provider.Telephony.SMS_RECEIVED` 的 receiver。
|
||||
- receiver 内只做轻量解析和状态分发,避免长耗时。
|
||||
- 记录最近一次接收时间、sender、body 摘要、提取结果和失败原因。
|
||||
- 记录最近一次接收时间、sender、body 摘要、读取结果和失败原因。
|
||||
|
||||
备选方案:
|
||||
|
||||
- `READ_SMS` 可读取短信数据库,但需求是监听新验证码,不需要读取历史短信;默认不纳入主路径。
|
||||
- `READ_SMS` 可读取短信数据库,但需求是监听新短信,不需要读取历史短信;默认不纳入主路径。
|
||||
- 默认短信应用角色权限更强,但目标不是做短信客户端;不作为一期要求。
|
||||
|
||||
### Decision 2: 备选验证路径引入 `SMS User Consent API`
|
||||
@@ -52,29 +52,28 @@
|
||||
`SMS User Consent API` 用于验证两类问题:
|
||||
|
||||
- 当系统广播路径在 HyperOS 上被后台策略影响时,前台触发 consent flow 是否能拿到单条短信。
|
||||
- 当用户不愿或系统不允许直接授予短信权限时,是否仍能通过一次性确认读取验证码。
|
||||
- 当用户不愿或系统不允许直接授予短信权限时,是否仍能通过一次性确认读取短信原文。
|
||||
|
||||
限制:
|
||||
|
||||
- 它不是静默读取,需要用户确认。
|
||||
- 它适合前台验证流程,不适合后台长期监听所有验证码。
|
||||
- 它适合前台验证流程,不适合后台长期监听所有短信。
|
||||
- 它依赖 Google Play services;国内 ROM 环境下需要确认设备实际可用性。
|
||||
|
||||
### Decision 3: `SMS Retriever API` 只作为受控短信模板能力
|
||||
|
||||
`SMS Retriever API` 的优点是无需短信权限,体验干净;但它要求短信包含 app hash,且通常需要服务端发送符合格式的短信。对于读取第三方平台验证码,它大概率不适用。因此一期只实现或预留为“自发测试短信/未来自控服务端验证码”的能力,不作为读取任意验证码的主线。
|
||||
`SMS Retriever API` 的优点是无需短信权限,体验干净;但它要求短信包含 app hash,且通常需要服务端发送符合格式的短信。对于读取第三方平台短信,它大概率不适用。因此一期只实现或预留为“自发测试短信/未来自控服务端短信”的能力,不作为读取任意短信的主线。
|
||||
|
||||
### Decision 4: 验证码解析采用多阶段规则
|
||||
### Decision 4: 最近结果直接以短信原文为主
|
||||
|
||||
解析规则必须保守,避免把手机号、金额、日期误识别为验证码。
|
||||
当前目标不再是从短信中提取结构化业务字段,而是直接保留收到的短信原文。因此最近结果与诊断数据应围绕“是否成功读取到完整短信正文”展开,而不是围绕解析命中策略。
|
||||
|
||||
建议顺序:
|
||||
|
||||
1. 优先匹配包含关键词的模式:`验证码`、`校验码`、`动态码`、`code`、`verification`、`OTP` 附近的 4-8 位数字或字母数字。
|
||||
2. 次级匹配短信中独立出现的 4-8 位数字,排除明显日期、手机号片段、金额和订单号。
|
||||
3. 对带空格或短横线的验证码做归一化,例如 `12 34 56`、`123-456`。
|
||||
4. 若多个候选值并存,选择距离关键词最近、长度在 4-6 位优先、出现位置更靠前的候选。
|
||||
5. 解析失败时保留失败原因,不展示完整正文。
|
||||
1. 优先保证 PDU 合并后的短信正文完整。
|
||||
2. 记录 sender、timestamp、source 和 body 摘要。
|
||||
3. 读取失败时保留失败原因,例如无权限、未收到广播、正文为空。
|
||||
4. 默认展示最近一条短信原文,不额外推断正文中的业务字段。
|
||||
|
||||
### Decision 5: UI 首版只做诊断型工具界面
|
||||
|
||||
@@ -83,17 +82,16 @@
|
||||
- 当前短信权限状态。
|
||||
- 主路径 receiver 状态。
|
||||
- Google Play services / SMS User Consent 可用性。
|
||||
- 最近一次收到短信的时间、发送方、验证码、解析策略命中类型。
|
||||
- 最近失败原因,例如无权限、未收到广播、正文为空、未找到验证码、API timeout。
|
||||
- 最近一次收到短信的时间、发送方、来源和短信原文。
|
||||
- 最近失败原因,例如无权限、未收到广播、正文为空、API timeout。
|
||||
- 手动清空最近结果按钮。
|
||||
|
||||
### Decision 6: 本地隐私边界
|
||||
|
||||
即使是自用 app,也不应默认保存完整短信正文。建议:
|
||||
即使是自用 app,也应尽量控制短信内容扩散。建议:
|
||||
|
||||
- 内存中可短暂保留最近一条完整正文用于调试开关。
|
||||
- 默认持久化只保存验证码、时间、sender 摘要和解析状态。
|
||||
- 不做网络上传。
|
||||
- 默认只持久化最近一条短信原文、时间、sender 摘要和读取状态。
|
||||
- 核心能力不以网络上传为前提。
|
||||
- 日志避免输出完整短信正文;debug 模式如需输出,必须集中开关控制。
|
||||
|
||||
## Android 15 And HyperOS Risk Analysis
|
||||
@@ -117,7 +115,7 @@
|
||||
2. 参考 Weather 项目创建或复制最小 Android 构建骨架。
|
||||
3. 实现权限和诊断 UI。
|
||||
4. 实现系统短信广播主路径。
|
||||
5. 实现验证码解析器和单元测试。
|
||||
5. 实现短信读取结果存储和展示逻辑。
|
||||
6. 在小米 12S 上跑真机验证。
|
||||
7. 根据真机结果决定是否补 `SMS User Consent API` 或后台稳定性处理。
|
||||
|
||||
@@ -136,14 +134,14 @@ Rollback 策略:
|
||||
|
||||
代码验证:
|
||||
|
||||
- 验证码解析器单元测试覆盖中文、英文、空格、短横线、多候选、无验证码样本。
|
||||
- 短信读取与结果存储测试覆盖多段短信、正文为空、权限缺失和最近结果刷新样本。
|
||||
- receiver 解析逻辑可通过构造 Intent/PDU 或抽象 message input 测试核心逻辑。
|
||||
- 权限状态和诊断状态可通过 ViewModel/unit test 验证。
|
||||
|
||||
真机验证:
|
||||
|
||||
- 前台打开应用后,向目标号码发送测试短信:`【测试】验证码 123456,5 分钟内有效。`
|
||||
- 应用退到后台后,重复发送不同验证码。
|
||||
- 前台打开应用后,向目标号码发送测试短信:`【测试】这是一条短信原文样本。`
|
||||
- 应用退到后台后,重复发送不同短信正文。
|
||||
- 锁屏状态下发送短信,解锁后检查最近结果。
|
||||
- 若可以控制短信格式,发送带 app hash 的 SMS Retriever 测试短信。
|
||||
- 若广播路径失败,打开前台 consent flow 再发送短信,观察是否弹出授权并读取正文。
|
||||
@@ -152,5 +150,5 @@ Rollback 策略:
|
||||
|
||||
- 目标小米 12S 当前是否安装并启用了 Google Play services。
|
||||
- 用户是否接受为了后台稳定性关闭 HyperOS 对该 app 的省电限制。
|
||||
- 首版是否需要常驻通知显示最近验证码,还是只在 app 内展示。
|
||||
- 是否需要支持验证码自动复制到剪贴板;这会带来额外隐私和系统提示问题,建议先不做。
|
||||
- 首版是否需要常驻通知显示最近短信结果,还是只在 app 内展示。
|
||||
- 是否需要支持短信原文快捷复制;这会带来额外隐私和系统提示问题,建议先不做。
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
## Why
|
||||
|
||||
你想做的不是完整短信客户端,而是一个只服务自己手机的验证码接收工具:在小米 12S、澎湃 OS 3、Android 15 上尽可能可靠地读取新收到短信里的验证码,并把关键结果快速展示出来。
|
||||
你想做的不是完整短信客户端,而是一个只服务自己手机的短信接收工具:在小米 12S、澎湃 OS 3、Android 15 上尽可能可靠地读取新收到短信的原文,并把关键结果快速展示出来。
|
||||
|
||||
这类需求的关键不在 UI,而在 Android 15 与厂商系统对短信权限、广播分发、后台限制和验证码短信格式的真实行为。因此必须先把可用 API、兜底路径和真机验证方案写清楚,再进入编码。
|
||||
这类需求的关键不在 UI,而在 Android 15 与厂商系统对短信权限、广播分发、后台限制和短信原文读取链路的真实行为。因此必须先把可用 API、兜底路径和真机验证方案写清楚,再进入编码。
|
||||
|
||||
## What Changes
|
||||
|
||||
- 新建一个 Android App 规格方案,目标能力限定为“接收短信验证码、解析验证码、展示最近结果、输出诊断状态”。
|
||||
- 新建一个 Android App 规格方案,目标能力限定为“接收短信原文、展示最近结果、输出诊断状态”。
|
||||
- 明确三条可用 SMS 获取路径,并按优先级落地:
|
||||
- `Telephony.Sms.Intents.SMS_RECEIVED_ACTION` + `RECEIVE_SMS`:主路径,适合个人自用、非 Play 上架场景,直接读取收到短信内容。
|
||||
- `SMS User Consent API`:备选路径,不要求短信带 app hash,但需要用户对单条短信授权,适合验证系统广播被限制时的可行性。
|
||||
- `SMS Retriever API`:受控格式路径,不需要短信权限,但要求验证码短信包含当前 app 的 hash,更适合服务端可控验证码,不适合作为读取任意平台验证码的主路径。
|
||||
- `SMS Retriever API`:受控格式路径,不需要短信权限,但要求测试短信包含当前 app 的 hash,更适合服务端可控短信模板,不适合作为读取任意平台短信的主路径。
|
||||
- 明确不把 Android Studio、Gradle、JDK 环境初始化纳入本次工作,后续实现时参考已有 `Weather` 项目的构建环境。
|
||||
- 设计验证码解析策略,支持常见 4-8 位数字码、中文验证码文案、带空格/短横线的验证码,以及短信多段 PDU 合并后的正文。
|
||||
- 设计短信原文处理和展示策略,支持短信多段 PDU 合并后的完整正文展示、最近结果存储和诊断摘要。
|
||||
- 设计真机验证路径,重点验证 Android 15 + HyperOS 3 上:
|
||||
- 运行时申请 `RECEIVE_SMS` 是否成功。
|
||||
- 应用在前台/后台时 `SMS_RECEIVED_ACTION` 是否触发。
|
||||
- 短信正文是否能被解析为完整 message body。
|
||||
- 常见短信验证码是否能稳定提取。
|
||||
- 建立诊断能力,暴露权限状态、API 路径状态、最近一次广播时间、最近一次解析结果和失败原因。
|
||||
- 常见短信原文是否能稳定读取。
|
||||
- 建立诊断能力,暴露权限状态、API 路径状态、最近一次广播时间、最近一次读取结果和失败原因。
|
||||
|
||||
## Capabilities
|
||||
|
||||
### New Capabilities
|
||||
|
||||
- `sms-code-capture`: 定义应用通过系统短信广播、Google SMS 验证 API 备选路径接收短信正文并抽取验证码的行为要求。
|
||||
- `sms-code-capture`: 定义应用通过系统短信广播、Google SMS 验证 API 备选路径接收短信正文并保留原始内容的行为要求。
|
||||
- `sms-permission-diagnostics`: 定义应用对短信权限、接收状态、API 可用性和解析失败原因的诊断展示要求。
|
||||
- `sms-code-validation-workflow`: 定义在小米 12S、澎湃 OS 3、Android 15 真机上的验证流程和测试通过标准。
|
||||
- `sms-code-validation-workflow`: 定义在小米 12S、澎湃 OS 3、Android 15 真机上的短信原文读取验证流程和测试通过标准。
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
@@ -35,14 +35,14 @@
|
||||
## Impact
|
||||
|
||||
- 预期后续会创建一个最小 Android 工程或复用 Weather 工程环境生成同类 Android 工程配置。
|
||||
- 预期会影响 Android Manifest、运行时权限申请、BroadcastReceiver、短信 PDU 解析、验证码正则解析、前台诊断 UI 和测试用例。
|
||||
- 预期会影响 Android Manifest、运行时权限申请、BroadcastReceiver、短信 PDU 解析、最近结果展示、前台诊断 UI 和测试用例。
|
||||
- 需要引入或使用的主要 Android/Google API:
|
||||
- `android.provider.Telephony.Sms.Intents.SMS_RECEIVED_ACTION`
|
||||
- `android.permission.RECEIVE_SMS`
|
||||
- `Telephony.Sms.Intents.getMessagesFromIntent(Intent)`
|
||||
- `com.google.android.gms.auth.api.phone.SmsRetriever`
|
||||
- `SMS User Consent API`
|
||||
- 不以 Play Store 上架合规为目标,因此可以使用短信权限;但实现仍必须本地化处理短信内容,不上传、不持久化完整短信正文,减少隐私风险。
|
||||
- 不以 Play Store 上架合规为目标,因此可以使用短信权限;但实现仍必须以本地读取、展示和诊断为主线,减少不必要的短信内容扩散。
|
||||
|
||||
## Validation
|
||||
|
||||
@@ -50,4 +50,4 @@
|
||||
- API 方案必须明确主路径、备选路径、适用条件和限制,不写成泛泛而谈的短信读取方案。
|
||||
- 设计必须说明 Android 15、HyperOS 3、个人自用 sideload/debug 场景下的权限与后台行为风险。
|
||||
- 后续实现前必须能从任务列表直接进入编码,不再需要重新讨论核心架构。
|
||||
- 后续实现完成后,必须在目标真机上完成至少一轮短信接收、解析和诊断验证。
|
||||
- 后续实现完成后,必须在目标真机上完成至少一轮短信接收、展示和诊断验证。
|
||||
|
||||
@@ -11,46 +11,42 @@ The app SHALL use Android's new SMS received broadcast path as the primary mecha
|
||||
- **WHEN** the app does not have `RECEIVE_SMS` permission
|
||||
- **THEN** the app MUST report that the primary SMS capture path is blocked by missing permission
|
||||
|
||||
### Requirement: Parse complete SMS message bodies
|
||||
The app SHALL parse SMS bodies using Android SMS message APIs rather than ad hoc PDU handling in business logic.
|
||||
### Requirement: Preserve complete SMS message bodies
|
||||
The app SHALL preserve SMS bodies using Android SMS message APIs rather than ad hoc PDU handling in business logic.
|
||||
|
||||
#### Scenario: Multi-part SMS is received
|
||||
- **WHEN** the received intent contains multiple SMS message segments
|
||||
- **THEN** the app MUST combine the message bodies in received order before verification code extraction
|
||||
- **THEN** the app MUST combine the message bodies in received order before saving or displaying the capture result
|
||||
|
||||
#### Scenario: Sender and timestamp are available
|
||||
- **WHEN** Android exposes sender address or timestamp for the SMS message
|
||||
- **THEN** the app MUST attach those values to the capture result for diagnostics and display
|
||||
|
||||
### Requirement: Extract verification code candidates
|
||||
The app SHALL extract verification code candidates from SMS bodies with a conservative parser optimized for common Chinese and English verification messages.
|
||||
### Requirement: Surface the original SMS content as the primary result
|
||||
The app SHALL use the original SMS body as the primary display and diagnostic result.
|
||||
|
||||
#### Scenario: Chinese verification keyword is present
|
||||
- **WHEN** the SMS body contains a keyword such as `验证码`、`校验码` or `动态码` near a 4-8 character code
|
||||
- **THEN** the app MUST extract the nearby code as the preferred verification code candidate
|
||||
#### Scenario: SMS body is available
|
||||
- **WHEN** the app reads an SMS body successfully
|
||||
- **THEN** the app MUST retain the original SMS body for local display and diagnostics
|
||||
|
||||
#### Scenario: English verification keyword is present
|
||||
- **WHEN** the SMS body contains a keyword such as `code`, `verification` or `OTP` near a 4-8 character code
|
||||
- **THEN** the app MUST extract the nearby code as the preferred verification code candidate
|
||||
#### Scenario: SMS body is empty
|
||||
- **WHEN** the app reads an SMS message but the body is empty
|
||||
- **THEN** the app MUST return a structured failure instead of inventing a display value
|
||||
|
||||
#### Scenario: Code contains spaces or hyphens
|
||||
- **WHEN** the SMS body contains a verification code formatted with spaces or hyphens
|
||||
- **THEN** the app MUST normalize the code before displaying it
|
||||
|
||||
#### Scenario: No reliable code candidate exists
|
||||
- **WHEN** the SMS body does not contain a reliable verification code candidate
|
||||
- **THEN** the app MUST return a structured parse failure instead of displaying a guessed code
|
||||
#### Scenario: Capture result is displayed
|
||||
- **WHEN** the app shows the latest SMS capture result
|
||||
- **THEN** it MUST display the original SMS content, sender summary, source, timestamp, and any structured failure reason
|
||||
|
||||
### Requirement: Support optional Google SMS verification APIs
|
||||
The app SHALL support Google SMS verification APIs only as optional paths and MUST NOT depend on them for the primary capture behavior.
|
||||
|
||||
#### Scenario: SMS User Consent path is available
|
||||
- **WHEN** Google Play services supports SMS User Consent and the user authorizes reading a single SMS
|
||||
- **THEN** the app MUST parse that SMS body through the same verification code parser used by the primary path
|
||||
- **THEN** the app MUST feed that SMS body through the same body-preservation path used by the primary path
|
||||
|
||||
#### Scenario: SMS Retriever path is used with app hash
|
||||
- **WHEN** a controlled test SMS includes the app hash required by SMS Retriever
|
||||
- **THEN** the app MUST accept the retrieved message and parse the verification code
|
||||
- **THEN** the app MUST accept the retrieved message and preserve the original SMS body
|
||||
|
||||
#### Scenario: Google SMS API is unavailable
|
||||
- **WHEN** Google Play services is missing, disabled, incompatible, times out, or the user declines consent
|
||||
|
||||
+11
-11
@@ -4,27 +4,27 @@
|
||||
The app SHALL be validated on the user's Xiaomi 12S running HyperOS 3 and Android 15 before the SMS capture behavior is considered complete.
|
||||
|
||||
#### Scenario: Foreground validation
|
||||
- **WHEN** the app is open in the foreground and a test SMS containing `验证码 123456` is received
|
||||
- **THEN** the app MUST show `123456` as the latest parsed verification code
|
||||
- **WHEN** the app is open in the foreground and a test SMS containing `这是一条短信原文样本` is received
|
||||
- **THEN** the app MUST show that SMS body as the latest received SMS content
|
||||
|
||||
#### Scenario: Background validation
|
||||
- **WHEN** the app has been moved to the background and a test SMS containing a new verification code is received
|
||||
- **THEN** the app MUST either show the new code after returning to the app or report that background delivery was blocked
|
||||
- **WHEN** the app has been moved to the background and a test SMS containing new SMS content is received
|
||||
- **THEN** the app MUST either show that new SMS body after returning to the app or report that background delivery was blocked
|
||||
|
||||
#### Scenario: Lock screen validation
|
||||
- **WHEN** the device is locked and a test SMS is received
|
||||
- **THEN** the app MUST show the received result after unlock or report that delivery was blocked under lock screen conditions
|
||||
|
||||
### Requirement: Validate parser behavior with representative samples
|
||||
The verification parser SHALL be validated with representative verification SMS examples and negative examples.
|
||||
### Requirement: Validate SMS body handling with representative samples
|
||||
The SMS body handling logic SHALL be validated with representative SMS examples and failure examples.
|
||||
|
||||
#### Scenario: Common valid samples
|
||||
- **WHEN** parser tests include Chinese verification codes, English OTP messages, space-separated codes, hyphen-separated codes, and multiple candidates
|
||||
- **THEN** all expected verification codes MUST be extracted with the correct normalized value
|
||||
- **WHEN** tests include Chinese notices, English notification-like messages, multi-part messages, and regular promotional text
|
||||
- **THEN** all expected SMS bodies MUST be preserved with the correct original content
|
||||
|
||||
#### Scenario: Negative samples
|
||||
- **WHEN** parser tests include messages with phone numbers, dates, money amounts, tracking numbers, or no verification code
|
||||
- **THEN** the parser MUST avoid returning a false verification code unless a stronger keyword-nearby rule applies
|
||||
#### Scenario: Failure samples
|
||||
- **WHEN** tests include empty bodies, unreadable message input, or missing permission states
|
||||
- **THEN** the app MUST return a structured failure instead of a fabricated SMS result
|
||||
|
||||
### Requirement: Validate optional API assumptions separately
|
||||
The app SHALL validate Google SMS APIs independently from the primary system broadcast path.
|
||||
|
||||
+11
-11
@@ -15,12 +15,12 @@ The app SHALL display whether the SMS receive permission is granted, denied, or
|
||||
The app SHALL expose diagnostic state for each supported SMS capture path.
|
||||
|
||||
#### Scenario: Primary path receives an SMS
|
||||
- **WHEN** the system broadcast path receives and parses an SMS
|
||||
- **THEN** the app MUST show the latest receive time, source path, sender summary, parsed code, and parse strategy
|
||||
- **WHEN** the system broadcast path receives and processes an SMS
|
||||
- **THEN** the app MUST show the latest receive time, source path, sender summary, and SMS body or body summary
|
||||
|
||||
#### Scenario: Primary path fails before parsing
|
||||
- **WHEN** the app cannot receive or parse an SMS through the primary path
|
||||
- **THEN** the app MUST show a specific reason such as missing permission, no broadcast received, empty body, or parser failure
|
||||
#### Scenario: Primary path fails before body capture completes
|
||||
- **WHEN** the app cannot receive or process an SMS through the primary path
|
||||
- **THEN** the app MUST show a specific reason such as missing permission, no broadcast received, empty body, or body-read failure
|
||||
|
||||
#### Scenario: Optional Google API path fails
|
||||
- **WHEN** SMS User Consent or SMS Retriever cannot complete
|
||||
@@ -29,13 +29,13 @@ The app SHALL expose diagnostic state for each supported SMS capture path.
|
||||
### Requirement: Avoid unnecessary SMS content retention
|
||||
The app SHALL minimize retention and logging of full SMS content.
|
||||
|
||||
#### Scenario: Verification code is parsed successfully
|
||||
- **WHEN** the app extracts a verification code from an SMS
|
||||
- **THEN** the app MUST display or retain the code, sender summary, timestamp, and parse metadata without requiring persistent storage of the full SMS body
|
||||
#### Scenario: Recent SMS result is stored for display
|
||||
- **WHEN** the app stores the latest SMS capture result
|
||||
- **THEN** the app MUST keep retention limited to the recent result, sender summary, timestamp, source, and the SMS body needed for local display or diagnostics
|
||||
|
||||
#### Scenario: Debug body visibility is enabled
|
||||
- **WHEN** a debug-only setting enables full body visibility
|
||||
- **THEN** the app MUST keep that behavior local to the device and clearly separate it from normal display state
|
||||
#### Scenario: Full body visibility is shown in diagnostics
|
||||
- **WHEN** the app shows full SMS content for local diagnostics
|
||||
- **THEN** the app MUST keep that behavior local to the device and clearly separate it from broader logging or export behavior
|
||||
|
||||
### Requirement: Provide recovery actions for permission problems
|
||||
The app SHALL provide a clear recovery path when Android or HyperOS blocks SMS capture permissions.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
- [x] 2.1 基于 Weather 项目环境建立最小 Android app 工程骨架
|
||||
- [x] 2.2 设置包名、minSdk、targetSdk、compileSdk,并保持与现有可用环境兼容
|
||||
- [x] 2.3 创建单 Activity 工具型界面,用于权限申请、状态展示和最近验证码展示
|
||||
- [x] 2.3 创建单 Activity 工具型界面,用于权限申请、状态展示和最近短信原文展示
|
||||
- [x] 2.4 建立基础日志标签和 debug 开关
|
||||
|
||||
## 3. Permission And Diagnostics
|
||||
@@ -27,15 +27,15 @@
|
||||
- [x] 4.2 使用 `Telephony.Sms.Intents.getMessagesFromIntent(Intent)` 解析短信消息
|
||||
- [x] 4.3 处理多段短信 body 合并、sender、timestamp 和 subscription id
|
||||
- [x] 4.4 将 receiver 结果分发到应用状态层,避免在 receiver 内执行重任务
|
||||
- [x] 4.5 在无权限、body 为空、解析失败时输出结构化失败原因
|
||||
- [x] 4.5 在无权限、body 为空、读取失败时输出结构化失败原因
|
||||
|
||||
## 5. Verification Code Parser
|
||||
## 5. SMS Content Result Handling
|
||||
|
||||
- [x] 5.1 实现关键词邻近匹配,支持验证码、校验码、动态码、code、verification、OTP
|
||||
- [x] 5.2 实现 4-8 位数字或字母数字候选提取
|
||||
- [x] 5.3 支持空格和短横线归一化,例如 `12 34 56` 和 `123-456`
|
||||
- [x] 5.4 增加误判排除规则,降低手机号、日期、金额、订单号误识别概率
|
||||
- [x] 5.5 为多候选短信输出命中策略和置信度
|
||||
- [x] 5.1 保存最近一次短信原文、时间、sender 摘要和来源
|
||||
- [x] 5.2 支持多段短信 body 合并后的完整结果展示
|
||||
- [x] 5.3 对最近结果提供失败原因和正文摘要
|
||||
- [x] 5.4 保持手动读取、收件箱兜底和系统广播路径的结果结构一致
|
||||
- [x] 5.5 不对短信原文额外做业务字段推断
|
||||
|
||||
## 6. Optional Google SMS APIs
|
||||
|
||||
@@ -47,10 +47,10 @@
|
||||
|
||||
## 7. Tests
|
||||
|
||||
- [x] 7.1 为验证码解析器添加中文验证码样本测试
|
||||
- [x] 7.2 为验证码解析器添加英文 OTP/code 样本测试
|
||||
- [x] 7.3 为验证码解析器添加空格、短横线、多候选样本测试
|
||||
- [x] 7.4 为验证码解析器添加无验证码、手机号、日期、金额误判样本测试
|
||||
- [x] 7.1 为短信读取状态层添加最近结果存储测试
|
||||
- [x] 7.2 为短信广播读取链路添加多段正文样本测试
|
||||
- [x] 7.3 为收件箱路径添加最近短信读取样本测试
|
||||
- [x] 7.4 为正文为空、权限缺失和失败原因添加样本测试
|
||||
- [ ] 7.5 为短信接收状态层添加权限状态和失败原因测试
|
||||
|
||||
## 8. Xiaomi 12S / HyperOS 3 Device Validation
|
||||
@@ -67,5 +67,5 @@
|
||||
- [x] 9.1 相关上下文逻辑分析通过
|
||||
- [x] 9.2 OpenSpec validate 通过
|
||||
- [x] 9.3 单元测试通过
|
||||
- [ ] 9.4 目标真机至少完成一条验证码短信接收和解析
|
||||
- [x] 9.5 诊断 UI 能解释无权限、未收到广播、未解析到验证码三类失败
|
||||
- [ ] 9.4 目标真机至少完成一条短信原文接收和展示
|
||||
- [x] 9.5 诊断 UI 能解释无权限、未收到广播、未读取到短信正文三类失败
|
||||
|
||||
Reference in New Issue
Block a user