Repository navigation
Releases
v1.0.0
这一版是发送链路的一次重构升级:发图热路径、接管批次上下文与兜底队列按新结构重写,跨进程回传协议收口到单一常量源,连发两批、钩子失败、通配规则写歪都不再丢文字或把微信带崩。
遇到问题、想要新功能,到 Issues 反馈 —— 发不出字、丢文件名请附上模块版本号、日志(设置页 → 日志 → 导出日志),卡顿请附 adb shell dumpsys gfxinfo com.tencent.mm framestats。
本版内容
发送 / 稳定性
- 重构 发图热路径不再整份拷贝计数台账:
RepeatCounter原来每张图要读 4 次SharedPreferences.getAll()(每次把 300+ 条台账与 600 条事件全拷成新 map 再取一个键,连发 50 张约 7MB 临时对象),trimEventsIfNeeded还会把 ≤600 条事件无条件解析成Event;现在读写直连getString/getLong/getBoolean(类型写错仍回落原实现),裁剪改成计数短路、每 16 次才真扫一遍。 - 重构 接管批次改成「每批一份入口上下文 + CAS 独占位」:原来入口
Method/this/ 参数存在三个跨批共享的volatile字段里,第二张图并发拦进来会覆盖上一批的入口(重放成别人的图);现在每批建ReplayCtx挂ThreadLocal,抢不到独占位就转兜底队列排队补发,不丢文字。 - 优化 拦截线程不再等跨进程 binder 读配置:3s TTL 到期的重附着改 hop 到
wxpiclabel-poller线程,本次调用继续用旧快照(拿不到就沿用上一次,仍 fail-closed);作用域名单按「附着时间戳 + key」缓存,labelOf去掉每张图一次new File(path).getName(),Uri 解析加 64 项LruCache。 - 修复 单张图静默丢文件名:
step()在锁内 peek 到空队列、却在锁外把draining置回 false,主干看到draining == true不再调度,sendLabel白等 10 秒后按失败收场;现在「空队列 → 关 draining」在同一临界区。 - 修复 钩子可能把微信带崩或永久失效:
on5.f#a从不校验返回值,某版本不是void就让宿主拆箱 NPE;markHooked又全部写在hook()之前,类没找到也照样标记、之后永不再试(相册底栏开关就此消失)。现在非void直接跳过并打日志,标记一律后置到挂载成功之后。 - 修复 连发两批图时兜底队列串批 / 吞文字:
pendingDrafts只有一份全局状态,三处各自整表替换,补发到第 i 格时被换成新批、新批前 i 格被当成「已发过」跳过;现在消费前校验「手里这份还是不是当前表」,新批追加队尾不重置序号,批末不再清别人的队列。 - 修复 随手填的通配规则能卡死微信进程:
*a*a*a*a*b这类形状让正则指数回溯,现在改成双指针 + 回溯点匹配(最坏 O(长度 × 星号数)),文本侧大小写折叠每段只做一次。
桥协议 / 诊断
- 新增 跨进程回传协议收口到
core/BridgeProtocol.kt单一常量源,并加只读探针/status(schema / 模块版本 / features / 两条回传的时间与规模共八列);records 与 friends 载荷统一带v与at,读侧遇到更高v走宽松解析并标unsupported而不是猜结构。好友回传补上退避重试,分片insert返回 null 就整份放弃,末片改按前缀清扫残留分片。 - 修复 日志导出的
StringBuilder并发写:读线程拼一段、调用线程toString(),join(1000)超时后读线程仍在 append,导出内容会被截断;现在读写同一把锁。
界面
- 优化 发送记录页从
verticalScroll + 双层 for换成LazyColumn扁平行:600 条台账原来首帧就把每一行都组合、测量一遍(每行还各挂一个remember锚点 +onGloballyPositioned),现在只组合可见的十几行;组卡横跨多个 item,按「首段圆上两角 / 中段直边 / 末段圆下两角」逐段自绘,与整卡逐像素一致。 - 优化 UI 帧路径减分配:概览卡光场每帧的两次
map+listOf+forEachIndexed换成局部val与直调,卡片滚出屏幕或窗口不在STARTED时不再累加时间、不触发重绘。
文档
- 文档
docs/VERSIONING.md§1.1 补「一句版本定位」口径:标题仍禁止堆功能清单,但大版本可以写成v1.0.0 · 功能重构升级。
需要 root + LSPosed(支持 API 102),微信 8.0.x / Android 8.1+。
安装步骤见 README。
v0.8.2
发完图片上滑、切会话、开相册不再被插件抢帧:常驻轮询、台账回传与反射查找全部搬出微信主线程,功能总开关关着也生效。
遇到问题、想要新功能,到 Issues 反馈 —— 卡顿、掉帧请附上模块版本号、adb shell dumpsys gfxinfo com.tencent.mm framestats 与日志(设置页 → 日志 → 导出日志)。
本版内容
发送 / 性能
- 修复 发完图片向上滑动或使用微信时掉帧(功能总开关出厂默认关闭也会卡):常驻 700ms 兜底轮询原来只判主进程、不读功能开关,每轮 6 个检查 + 两次 SystemProperties 反射 + 3s TTL 跨进程重附着都压在微信主线程;现在轮询跑独立
HandlerThread("wxpiclabel-poller"),只有必须读输入框的补发动作回主线程并用AtomicBooleanCAS 合并,刷新令牌、清空记录、改文件名、自测通道在功能关时仍照常可用。 - 优化 台账回传不再同步写盘:
pushRecords统一 hop 到 worker 线程,本地台账 9 处.commit()改.apply(),跨进程 Provider 末片拼 JSON 的.commit()原样保留;发图后「发送」转圈变久的体感收敛。 - 优化 反射查找按类缓存:
SystemProperties.get、消息getType、Reflect.findMethod/findField全部加进程级 Method/Field 缓存(含查无哨兵),public 签名与返回语义零改动。 - 优化 相册底栏布局监听只挂一个常驻实例:勾「原图」后每次全局布局仍按改前公式重算位移,但默认不再拼 kids 字符串、不再每布局
Log.i,排障日志收进debug.wxpiclabel.uidump开关。 - 优化 输入框查找走 WeakReference 缓存快路径:兜底轮询不再每轮爬整棵 DecorView,缓存失效时的回退表达式与改前逐字等价。
构建 / 文档
- 优化 构建
debug变体默认按「性能」构建(关debuggable+ 开 R8 + 开资源压缩),与 release 同口径;要断点 /run-as时显式退回-Pwx.debuggable=true -Pwx.minifyDebug=false(docs/BUILD.md§2.1)。 - 优化 构建口径同步到
build.cmd与README.md,文档单测命令统一成:app:testReleaseUnitTest。 - 新增
docs/PITFALLS.md§29「现象 → 根因 → 怎么避」,把主线程 16ms 帧预算与真机验收命令写进正本。
需要 root + LSPosed(支持 API 102),微信 8.0.x / Android 8.1+。
安装步骤见 README。
v0.8.1
「构建脚本与 CI 不再被环境里的假 SDK 路径绊倒;README 把近几个版本新增的开关与页面补齐了。」
遇到问题请到 Issues 反馈,附上机型、Android 版本、微信版本与 logcat 片段。
本版内容
构建
- 修复
build.cmd把调用方环境里已失效的ANDROID_SDK_ROOT当成 SDK 用:本机该变量指向安装器留下的空目录,日志一直打印假路径,只靠local.properties兜底才编得过。现在目录不存在就打印一行说明并丢弃,回落到sdk.dir - 修复 CI 的 build job 死在 setup 阶段:
android-actions/setup-android@v3默认安装的tools包已从 SDK 仓库下架。现在直接调 runner 预置的sdkmanager安装platforms;android-37.0与build-tools;35.0.0、36.0.0
文档
- 调整
README.md功能表与当前版本对齐:补「文字过滤」(黑白名单决定哪些图补文字,判定压在重复计数之前)与「发送记录」(可搜索、按时间段分组、改文件名 / 改第几次 / 删条目)两行;把「发送图片文件名」行改回它在设置页里的真名「增加 文件名」,并注明出厂关闭、相册底栏有同款开关;「重复图片计数」改为「重复图片追加次数」并注明只累计设定时段内;「仅勾选的会话生效」注明出厂关闭(关 = 所有会话生效);进度与常亮拆成两个开关单列;新增「从源码构建」一节 - 调整
docs/BUILD.md的 minSdk 由 26 订正为 27,与app/build.gradle.kts一致;AGENTS.md补 release 默认产物路径 - 新增
docs/DESIGN-SYSTEM.md§0.3「组件取用与参考来源」:官方件 / 自绘件的分层取用表(页面骨架、开关、行与箭头、弹层、图标、底栏、文字色七行,逐行写明为什么自绘)、新页面的三个参照顺序(本仓最像的一页 → Miuix 官方渲染 → 宿主 App 界面),以及配置类页面一律以「方案设置」为母版的口径
v0.8.0
「重复图片 +N」现在只在设定时段内累计:时段外发出的图连号都不占,时段用上下滑动的滚轮选。
遇到问题请到 Issues 反馈,附上机型、Android 版本、微信版本与 logcat 片段。
本版内容
发送设置
- 新增 发送设置 → 重复图片 → 追加次数设置:
+N只累计落在设定时段里发出去的图。时段外发出的图不进计数表,所以「今天三点半前发过一次、三点半后再发」仍是第 1 次,不会变成+2;前天时段外发过的同理,压根没被记过。默认状态是全天追加,升级后行为不变 - 新增 一天可以设多段(
15:30-17:30, 20:00-21:00),跨零点也认(23:00-01:00);删空所有段即恢复全天 - 调整 新建时段不再手打文本:弹层里四根上下滑动的滚轮(开始 时/分、结束 时/分),循环滚动,初始值取当前整点起两小时。滚轮给不出非法输入,校验只剩「起止相同」与「与已有段重叠」两条
发送记录
- 新增 时段外发出的图在发送记录里显示「未累计 · 时间」,不再是一条没有去处的空白记录;这类条目仍可查看、改次数、删除
- 修复 从记录里删掉或改掉次数后,计数表按该名字所有事件的最大值重建,不会把时段内已经累计的号一起抹掉
界面
- 新增
TimeRangeDialogSpec:贴底弹层 + 滚轮选值的统一规格,与TextInputDialogSpec同壳;今后凡是有刻度的值(时间、时长)都走它
构建
- 调整
build.cmd默认构建 release 包(R8 已开),debug 包在实机掉帧明显、不再作为交付形态;需要 debuggable 抓日志时用build.cmd debug
v0.7.0
重命名规则页重做:规则一条一行,新建点一行、删除点一下;全 App 的搜索框收成同一种,发送记录页那行排障用的「回传报告」已经拿掉。
遇到问题、想要新功能,到 Issues 反馈 —— 崩溃、开关失灵请附上模块版本号与日志(设置页 → 日志 → 导出日志)。
本版内容
发送设置
- 调整 重命名规则 —— 原来是一整块文本框加一排按钮,规则表长什么样、有几条、哪条写错了全靠自己读;现在一条一行(左原名、右新名),行尾 ✕ 删单条。
- 修复 弹层让位在输入法动画期间上下来回弹(点开输入框后卡片一会儿弹上去、一会儿掉下来):现在等键盘动画停下来再采纳一次高度,并带 8px 死区
- 调整 新建规则 —— 底部「新建规则」点开贴底输入弹层;关键字为空、写成多行、没认出分隔符、跟已有规则重名,四种情况都挡在弹层里不让存。
- 调整 清空规则 —— 走贴底二次确认,确认才清。
- 调整 导入规则 —— 从文件或剪贴板导入改成就地合并:同名规则跳过,并回报「新增 N 条、跳过 M 条」,不再整表覆盖。
- 调整 发送设置入口 —— 重命名规则一行右侧显示当前条数(「N 条规则」,空时「按原文件名发送」)。
界面
-
修复 贴底输入弹层被软键盘遮住 —— 「新建规则」这类弹层一弹开键盘,下半截连同「取消 / 确定」就压在键盘底下点不到;现在整个弹层会自己让到键盘上方(全 App 所有弹层统一生效,键盘收起后自动落回原位)。
-
调整 搜索框 —— 全 App 收成同一种:12dp 圆角、44dp 高、主色光标、右端 ✕ 一键清空、键盘搜索键收起键盘;发送记录页与选择好友与群聊页都换过来了。
-
修复 选择好友与群聊页搜不到时整页空白 —— 补「名单里没有匹配的会话」空态,能分清是名单还没读到还是被搜索筛掉了。
-
移除 发送记录页的「回传报告」诊断行 —— 它是排障期临时加的,正常状态下只是在报「回传了 N 字」,对用户没有信息量;记录读不到时的空态文案已经说明问题,诊断能力保留在 logcat。
文档
- 新增 docs/DESIGN-SYSTEM.md —— 两仓共用的界面设计规范:页面骨架与留白、九种行型、可编辑字段三形态、弹层选型与尺寸、图标几何、副标题模板、空态与 Toast 模板、提交前 20 项自检。
- 新增 docs/IMG-LABEL-RENAME.md —— 重命名规则的格式与分隔符优先级、页面形态、新建校验口径、导入是合并不是替换。
- 调整 docs/UI.md —— 新增第 9 章「输入框与搜索框」,第 7 章补「页内搜索只走 AppSearchField」与「需打字的字段一律行入口 + 弹层输入」两条硬规则。
需要 root + LSPosed(支持 API 102),微信 8.0.x / Android 8.1+。
安装步骤见 README。
风险提示:本模块仅供学习研究,会 Hook 微信,可能违反其用户协议并导致
账号风控或封禁。下载使用前请阅读并同意
免责声明。
v0.6.0
这一版给发送加了「黑白名单」:某些图可以只发图、不带文字,图片照样按顺序发出去。
遇到问题请到 Issues 反馈,附上 Android 版本、微信版本、模块设置截图;行为不对时再附一段 adb logcat -s WxPicLabel 里 filter: 开头的日志。
本版内容
发送
- 新增 「黑白名单」:关键字命中的图片按名单决定要不要把文字一起发出(白名单 = 命中才发文字,黑名单 = 命中只发图),图片本身永远照发
- 新增 判定压在重复计数之前:被筛掉的图不涨
+N、也不进发送记录,下一张同名图不会凭空多算次数 - 新增 白名单空表时放行:刚切到白名单还没写关键字时,不会把整批文字全吞掉
- 新增 关键字支持子串匹配与
*?整段通配;「忽略大小写」「连原文件名一起匹配」两个开关各自可控
发送设置
- 新增 发送设置 → 黑白名单三级页:名单一个开关(关 = 白名单,开 = 黑名单)、匹配方式两个开关、关键字一条一行的列表
- 调整 关键字改成一列:右端 ✕ 删单条,底部「新建关键字」走贴底输入弹层(空值挡在弹层里),「清空关键字」走贴底二次确认;全部即改即存,页面没有保存按钮,反馈统一走 Toast
- 调整 旧配置读到
off时自动写回白名单 —— 行为不变,只是把状态显性化
界面
- 调整 黑白名单页整页重做:只留能点的行,说明语义压进行副标题;卡片内不画分隔线,分层靠分卡与行高
- 调整 行尾 ✕ 换成规范里的细描边叉(40dp 触控区、贴右缘、中性色),新建行的 + 改用同画布同笔画的
PlusThin,两颗图标等大等粗、右缘对齐
文档
- 新增
docs/IMG-LABEL-TEXT-FILTER.md:判定插点、三种模式、关键字写法、失败即放行与空表口径 - 调整
docs/UI.md:补两张图标规范表,新增「同卡并列图标必须同画布同笔画」「卡内不画分隔线」两条硬约束 - 调整
docs/NAMING.md、docs/README.md、CHANGELOG.md同步本次改动
v0.5.2
0.5.2 — 记录页「回传 N 字但 0 条」定位与兜底
修复
- 关掉「桌面图标」后每次覆盖更新又冒出来:状态改存本机独立记录,更新广播与启动各重放一次,不打开模块 App 也保持隐藏。
RecordStore.read三层兜底:严格读 → 别名键/数组元素读(label|name|l、count|n|c、last|t|at,元素支持三元/五元数组)→ 在原文上按{"label":…,"count":…,"last":…}/{"s":…,"t":…,"l":…,"n":…,"b":…}形状正则回捞。分片没拼全、文档被截断、顶层键不对,都能读出能读的那部分,不再整份读成空表。- 刷新中的 6 秒不再藏诊断行:只有一条快照都没有时才显示「正在读取记录…」,否则保留上一次的结构诊断(此前每次进页都退回「0 个文件名 0 条记录」,看着像坏了)。
新增
- 诊断行按
Book新字段(rawRows/rawEvents/topKeys/path)分支到七态,结构不符时直接把顶层键与原始条目数写在页面上:回传 17171 字,但一条都解析不出来(顶层键 fetchedAt,friends;原始 0 / 0 项);靠原文回捞时写明「已按原文回捞 X 个文件名 / Y 条」。
验证
- MuMu(Android 12 / 模块 v0.5.2):合法文档 30 条正常;截断文档 → 「文档不完整:已按原文回捞 2 个文件名 / 5 条」;把好友名单塞进
records_json→ 「一条记录也没有(顶层键 fetchedAt,friends)」;真实文档无回归。 build.cmd releaseBUILD SUCCESSFUL;python tools/check-docs.py门禁通过(17 篇,无断链无孤儿)。
v0.5.1
修复:发送记录读不到新数据
- 推送自愈:模块侧原先只有「批次结束 / 兜底 / 三个令牌变化」四处触发回传,一次失败就永久停在旧快照上。现在
RecordExporter.push返回成功与否,微信进程启动即补推一次,失败按min(60s, 5s × (1+失败次数))退避重试,每次记台账也置脏 —— 不用点刷新,也不用再发一张图。 - 并发保护:批末推送、令牌推送、重试三路并发分片 insert 会把两份快照的片拼成烂 JSON,
pushRecords改为串行。 - 诊断行:记录页概览下面直接说清哪一环断了 ——「回传 2248 字 · 8 个文件名 / 30 条记录」/「微信进程还没回传过记录」/「回传内容解析失败:<异常>」/「回传的是旧版文档」。解析异常不再被静默吞成空表。
装好这个包后重启一次微信让新模块进进程。
v0.5.0
发送记录现在按时间段摊开:点那个时间戳就调出那一堆图,行内随手改名字、改「第几次」、删掉,搜一次就看得见命中。
反馈走 Issues,请带上模块版本(设置 → 关于)、安卓版本、复现步骤与模块日志。
本版内容
发送设置
- 新增 发送记录按时间段分组:同一批发出的图折成一张卡,组头就是那个时间段的时间戳,点一下展开/收起那一堆图;组头时间按同日/跨日两种写法拼(
11-09 14:51–14:51:45/11-09 14:51 – 11-09 16:02) - 新增 记录行原地编辑:改文件名、改「第几次」(1..999 校验,预填当前次数)、删除这条(二次确认,只删记录,微信里已经发出去的图不受影响)
- 新增 搜索与筛选:一个框覆盖文件名、「第几次」、时间片段(
14:51、11-09 14:51),纯数字只按文件名与次数理解;时间范围四档(全部 / 今天 / 近 7 天 / 近 30 天) - 修复 筛选态只展开最新一组导致「搜不到记录」:命中但非最新的组只剩组头、行全折着 —— 筛选态改为全部命中组自动展开,并记住手动收起的组,概览改报「筛出 N 条」
- 修复 旧版记录整段历史挤成一组、看着像「根本没有分组」:迁移条目批次是占位
m,改为按 10 分钟一格兜底分组 - 修复 记录页「正在读取记录…」死等 18 秒像卡住 —— 轮询上限 45 → 15 次(6 秒)自动收
界面
- 调整 弹层按
docs/UI.md§4 选型表收敛:锚定小菜单用ChoiceDialogSpec(必须给anchor)、二次确认用ConfirmDialogSpec(居中)、贴底输入用TextInputDialogSpec - 调整 箭头语义跟着形态走:改名页的保存/复制/粘贴、名单页的刷新去掉「→」(点了就地生效),名单页展开卡改成「˅」
- 优化 底栏拖动不再为每个拖动事件新起协程,左右切页更跟手
文档
- 新增
docs/IMAGE-RECORD.md:记录数据正本、跨进程回传协议、改名/改次数/删除语义、记录页结构与搜索口径 - 调整
docs/UI.md§4 改为五种弹层规格表 + 箭头语义表,docs/ARCHITECTURE.md补记录通道段落
v0.4.0
一组图文从 2.7 秒降到 1.17 秒,发完图再发文字不再转圈;新增发送进度提示、屏幕常亮、重命名规则与发送记录。
遇到问题、想要新功能,到 Issues 反馈 —— 崩溃、开关失灵请附上模块版本号与日志(设置页 → 日志 → 导出日志)。
本版内容
发送
- 新增 发送进度提示 —— 发送期间用系统 Toast 显示「正在发送 3/12」,还剩几张一眼可见;只在主进程弹,子进程各弹一个会把 Toast 队列排死。
- 新增 发送期间屏幕常亮 —— 整批发完自动解除,不用 WakeLock、不需要宿主权限。
- 优化 发图时序 —— 成功事件快照前置、退化模式给固定间隔、批次收尾等在途上传排空;一组图文 2.7 秒 → 1.17 秒,单条文字点击等待 120 ms → 9~13 ms。
- 修复 图越多越慢 —— 一批里两次等不到发送确认后,之后每一批都不再等事件、图片一股脑重放,上传全压在微信发送队列里。
发送设置
- 新增 重命名规则 —— 一行一条
原名 -> 新名(也接受=>/=/ 制表符,#注释),支持从文件导入、导出到文件、复制粘贴。 - 新增 发送记录 —— 查看每个名字发过几次、最后一次什么时候,可一键清空。
- 修复 配置通道 —— 目标进程侧 remote preferences 是附着那一刻的快照,模块 App 改的配置微信进程读不到;改为每 3 秒重附着,配置改动免重启微信。
- 修复 白名单外的会话发图会白涨
+N计数。 - 修复 好友选择页「已选 X 个」点击无反应,改为展开已选名单;名单进页自动刷新。
界面
- 修复 三级页可预测手势返回动画 —— 改为三层 + 两条独立进度,手势只推最上面那一层,不再「退回首页又跳回来」。
- 修复
disclaimer_accepted仍在ALL_KEYS(备份会把它带到另一台机器)。
文档
- 调整 定位 —— README、免责声明与关于页统一按「接管相册批量发送、按选图顺序逐张发」表述。
- 新增 开源鸣谢与第三方组件声明补齐到 7 个项目(含 HyperIsland MIT 全文)。
- 修复 README 两处过期描述 —— minSdk 26 → 27、自测日志关键字。
完整变更见 CHANGELOG.md。