Repository navigation
Releases: yigenhuobah/cloudmusictool
Releases · yigenhuobah/cloudmusictool
Release list
2.4.9
修复
- UI-04 顶部频道过滤导致「我的 → 最近」闪退(issue #5):
MusicTabLayout.addTab兜底原先按「不在保留清单里」删 tab,但该类被「我的音乐 / 最近播放」等页面复用;误删后 TabLayout 子 View 数与 PagerAdapter 页数不一致,populateFromPagerAdapter抛IndexOutOfBoundsException: index=2 count=1。现在兜底只作用于首页 tab 容器实例,并且只移除本次数据层真正过滤掉的标题。 - 新增
TopTabHooksTest回归用例:记录删除标题、非首页MusicTabLayout一律放行。
2.4.8
诊断轮(内置诊断 + 对齐,27 项工作项全修)。明细见仓库 CHANGELOG 对应条目与提交记录。
新增
- 崩溃自动捕获:模块安装时包装宿主未捕获异常处理器(透传原 handler,不影响应用自有上报),最近 3 条崩溃(时间/线程/异常类+前 2 帧)随诊断回传,诊断页新增「最近崩溃」卡片——报障不再需要 adb。
- 导出诊断包:诊断页新增分享按钮,一键聚合模块版本/系统/框架 API/目标版本/功能状态/最近命中/最近崩溃,走系统分享面板。
修复
- 「我的页」自定义页补
onDestroy清理(WriteGate + 在途刷新作废)。
说明
- crash 通道为 HookState JSON 根级
crashes数组;QB/QM/TB 为crash0/1/2平铺键——载体差异源于回传协议不同,语义同构(最近 3 条、240 字符截断、空串清残留)。
2.4.7
四模块深度审查修复轮(130 项发现,本模块 53 项中 52 项修复、1 项经实跑证伪豁免)。全量明细见仓库 CHANGELOG 对应条目与提交记录。
修复
- 9.6.15 版本门控失配(high):
BottomTabHooks/MineBackgroundHooks不再用versionCode == 9006013判等,9.6.15 恢复 UI-05 底栏过滤与 EN-01 全屏链路;TargetProfile.findMethodSpec修正改名后挂载点的 critical 判定。 - 会话协议:session 改为身份比较(带进程随机后缀),时钟回拨不再整批丢弃回传;未来时间戳超过 5 分钟判过期。
- 诊断口径:installer 异常计入 failed/criticalFailed,失败横幅不再漏报整体失效;DexKit native 加载与扫描失败增加负缓存,未适配版本不再主线程全盘扫描。
- hook 语义:
chain.proceed()恢复单次调用(移出 try,禁止 catch 内二次 proceed);配置写回补 generation 回滚;hit 限流键收敛、hookNull 返回类型校验。 - 其余:JSON 过滤支持对象级 blockCode、搜索广告卡隐藏、启动延迟重复投递修复,以及测试质量与死代码清理。
2.4.6
UI-03 首页定制新增两个可勾选项。
新增
- 首页定制新增「搜索频道入口」「为你专属推荐(更多推荐)」两个可勾选项:
对应网易云 9.6.13 首页 scan 日志中的PAGE_RECOMMEND_SEARCH_CHANNEL_ENTRY
与PAGE_RECOMMEND_MORE_RCMD两个 block code,追加在选项列表末尾,
不影响旧选项索引;新增对应纯 JVM 单测锁定匹配行为。
注意
- 这两个 block 只在宿主下发对应 AB / 推荐流时存在。部分账号的首页数据流中
不含它们(9.6.15 真机实测UI-03 cache scan ... no-match),勾选后可能
没有可观察效果;选项只影响 UI-03 的过滤清单,不会误伤其他 block。
验证
- 单测 257 个用例通过(0 失败 / 0 跳过);lint 0 error。
- 真机(25102RKBEC / 网易云 9.6.15):2.4.6 覆盖安装后状态卡
「目标版本 9.6.15 · 已注入目标应用」,profile mounts=145、
runtime hooks installed 4/4;两个新选项可勾选并持久化;
当前账号首页数据流不含这两个 block,端到端 filtered 不可构造;
AD-01、UI-02、EN-01、PV-01~06 回归通过,无 FATAL/ANR。
2.4.5
深度代码评审第 4 轮(Phase 2–5):调度、配置写入、首页/背景热路径与诊断链路
加固,并新增网易云 9.6.15 兼容。
新增
- 配置写入结果与异步提交(Phase 3):
ConfigStore引入WriteResult
(SAVED/REJECTED/UNAVAILABLE/FAILED),开关与多选写入改为
后台单线程队列 + 异步commit,真实结果回主线程。框架未连接时设置页、
首页定制的开关置灰并提示;远端拒绝时开关/多选回滚并提示「保存失败,
设置未生效」。设置页、实验页、首页定制的 remote prefs 读取与桌面图标
组件状态读写全部移出主线程;桌面图标开关失败时回滚并提示。 - 首页 block token 缓存(Phase 4):
HomeBlockHooks按 block 身份
(WeakHashMap弱键)缓存已提取的 positionCode / moduleKey,滚动时不再
重复反射与正则;只有 String、org.json、Map/Collection 才序列化,任意
宿主对象不再调用不可控的toString。 - 「我的」页背景源指纹(Phase 4):共享目录不可读、走 Provider 兜底时,
通过StatusProvider.query读取内部图片 length / lastModified 指纹,
换图或清除后能及时让缓存失效。 - 运行时 ClassLoader 校验(Phase 4):
RuntimeHookBootstrap在安装运行时
UI hook 前用 3 个宿主类探测 ClassLoader;Tinker 中间态或异常 loader 不执行
installer 并重置标志,等后续 Activity 重试,避免 hook 挂在无效 loader 上。 - 诊断会话与新鲜度(Phase 5):回传新增
session(目标进程启动时刻);
模块侧丢弃迟到的旧会话整包回写;超过 10 分钟没有新回写时诊断页标记
「数据已过期」,不再把旧快照当成健康数据。 - 工具链:
check-mounts.sh记录 APK 路径/大小/mtime/SHA-256,同路径
替换 APK 时丢弃旧临时结果;release.sh在未安装gh时跳过官方仓资产
SHA-256 校验并明确告警。
修复
- 冷启动首报 context 未就绪:目标进程 context 未就绪时,
TargetProcessPublisher原先直接丢弃本次状态快照,诊断页在无后续事件时
可能长期为空。现改为按 1s/2s/4s 有界重试最多 3 次,同一通道只保留一条
重试链;成功、短路或重试耗尽都会取消在途任务。快照幂等,重复发送不会
产生副作用,仅修复回传时机。 - Profile 映射签名校验:
HookKit使用 Profile 映射方法前校验参数与返回
类型;不匹配时输出 warn 并回退常规查找,避免挂到同名的错误重载方法。 - DexKit 弱缓存:bridge 与 class 缓存的值改为
WeakReference。此前
WeakHashMap的弱键被强 value 反向引用,Tinker 热修 ClassLoader 无法回收。 - 重试取消与单调时钟(Phase 2):
TargetProcessPublisher在发送成功、
短路或重试耗尽时取消已排队的重试任务,避免状态已回传后迟到任务再次发送;
PublishThrottle的窗口判定改为synchronized,消除「关窗消费 pending」
与并发 decide 的竞争;生产时钟改用nanoTime单调毫秒,墙钟回拨不再吞
事件、向前跳变不再重复发送。 - ExperimentState 超长条目(Phase 2):key / group / source 任一超过协议
上限(256 字符)时整条跳过并只告警一次。StatusProvider 对超长字符串是整包
拒绝,跳过单条可保留其它 experiments 数据。 - 「我的」页背景共享 Bitmap:清除背景时不再主动
recycle进程级共享
位图,只清引用交给 GC,修复其它页面继续绘制时的
Canvas: trying to use a recycled bitmap崩溃。 - 失败横幅误报(Phase 5):
failedFeatureCount只统计主进程、TTL 内、
已启用且「expected > 0 且 installed <= 0」或criticalFailed > 0的功能;
普通lastFailure只作诊断。expected=0的功能(如实验面板)不再计入。 - 设置页旧快照覆盖(Phase 3):后台读取结果用 generation 丢弃过期快照;
用户刚修改的开关/多选不会被更早的读取结果回写覆盖。
诊断
- 诊断页数据来源新增「数据已过期:超过 10 分钟未收到目标进程回写」。
- 回传 payload 根键白名单新增
session;迟到的旧会话回写记录
status report ignored: stale session。 - Profile 映射签名不匹配、运行时 loader 不可用、experiments 条目超长均输出
明确的 warn 日志,便于定位适配问题。 - 异常横幅只认 critical 挂载失败,可选挂载点改名不再把整个功能判死。
兼容
- 网易云 9.6.15:9.6.15(versionCode 9006015)复用 9.6.13 的挂载点集合;
2026-10-29 对 9.6.15 base.apk 全量体检 145/145 OK。版本门禁与「关于」页
展示 9.6.08 / 9.6.13 / 9.6.15;未适配版本仍 fail-open。
已知限制
- 底栏保留清单无法去掉「首页」Tab(9.6.13/9.6.15 主页面初始化依赖首页,
强行删除会导致启动卡死)。 - UI-03 的隐藏清单基于旧版 block code;9.6.13/9.6.15 首页新增的
PAGE_RECOMMEND_SEARCH_TOP_BANNER/SEARCH_CHANNEL_ENTRY/MORE_RCMD
等 code 需要在新版首页定制里勾选对应项才会隐藏。 - 「我的页背景」清除后宿主侧
validType=4注入不会回滚(与 2.4.2 一致),
清除后如仍显示背景可重启网易云。 - 9.6.15 复用 9.6.13 Profile,目前只完成挂载点静态体检,未做 9.6.15 单独
真机验收;如 9.6.15 后续小版本改动类/方法坐标,需要重新体检。 - 诊断数据 TTL 为 10 分钟且不发送心跳:目标进程空闲超过 10 分钟会显示
「数据已过期」,这是设计内的「未知」状态,不是故障。 - 异常横幅只统计 critical 挂载失败;非 critical 子项失败仅出现在诊断页,
不会触发横幅。
验证
:app:testDebugUnitTest:252 个用例通过;:app:lintDebug、
:app:assembleRelease通过。- 9.6.15 挂载体检 145/145 OK(
profile9613.json+--allow-version,
RESULT: OK=145 GONE=0 ERROR=0)。 tools/verify-apk.shPASS:versionCode=15 / versionName=2.4.5,签名证书
SHA-256eea85cac2aee030a28a2fe1e6f5b4e3e3c9448b674e53ec5bf88c3ea09d08925,
R8 keep 与 Xposed 元数据全部通过。- APK:
app/build/outputs/apk/release/cloudmusictool-2.4.5.apk,
4,253,165 字节(约 4.06 MiB),SHA-256
7184566341875033ad704208459624a9a7dd817ced708564cb5edd430b6ad62e。
2.4.4
网易云 9.6.13 三项适配(UI-03 / UI-05 / EN-01 第二层)。三项均已在真机
25102RKBEC / Android 17 / LSPosed 2.2.1 / 网易云 9.6.13 验证。
修复
- 9.6.13 UI-03 首页模块净化:
MixContainerData.getResources()的元素是
com.netease.luna.cm.container.Block,旧逻辑只认DslBlock#getDslWrapperModel,
对 9.6.13 首页混排的NativeBlock/RnBlock完全不命中。现主匹配改为
Block.getPositionCode(),DslBlock保留 originData 正则兜底,NativeBlock
补充nativeData/originServerData兜底;隐藏清单新增 9.6.13 的 6 个
block code(PAGE_RECOMMEND_BANNER_0/GREETING/NOTE/
PODCAST_NARROW_SCENE/SEARCH_TOP_BANNER/SECONDARY_TAB)。
getBlockCodeOrderList()同步按隐藏清单过滤(只影响下一次分页请求)。
真机验证:配置的旧 30 项 code 命中时首页顶部对应卡片消失
(resources filtered 9/9)。 - 9.6.13 UI-05 底部导航精简:9.6.13 底栏列表构建点是
tf0.o$a#y(List<BottomTabInfoVO>, Z);旧的rh0.c.c返回的是
List<Drawable>(drawable 工厂),过滤它只会让图标错位、不能删 tab。
现改挂tf0.o$a#y过滤入参,state 与 drawable 同源缩短;tf0.o$a为
9.6.13 专属挂载点,按 Profile 门控(9.6.08 不查找,避免诊断误报)。
首页 Tab 始终保留:网易云主页面以首页为初始 tab,把首页从底栏删掉会让
导航初始化卡住、启动页一直不消失(真机复现并修复)。保留清单不再包含首页时
结果为「首页 + 保留清单」。
真机验证:保留{搜索, 关注}时底栏为「首页 / 搜索 / 关注」
(filtered from 4 to 3 tabs),正常进入首页。 - 9.6.13 EN-01 我的页自定义背景(第二层调度点):
MyMusicProxyFragment
类并未消失——9.6.08 的oc()Z(RN 门禁)在 9.6.13 改名为kc()Z,
而同名的oc()V只负责启动协程,旧 hook 对它返回 false 完全无效。
现改为 hookkc()Z返回 false 强制原生页(9.6.08 仍回退oc()Z),
并新增只读探针记录sg.s()结果与hc()最终创建的 Fragment。
修复 9.6.13 已失配的反射(pe()→pe(Activity);删除 9.6.13 不存在的
W1(boolean)/kd(String)分支,9.6.08 保留原路径)。
真机验证:kc=false强制原生页、sg.s=true、
hc fragment=MyMusicFragmentV4、本地背景贴图与内容区 scrim 全部生效。 - 共享基础设施(三项共用):9.6.13 运行时使用 Tinker
DelegateLastClassLoader(tinker_classN.apk),模块启动时的 ClassLoader
与运行时不同。现提供RuntimeHookBootstrap在首个Activity#onCreate
用运行时 ClassLoader 统一安装 UI-03 / UI-05 / EN-01(UI-04 已在 2.4.3
使用同机制);MountResolver缓存按 ClassLoader 隔离;HookState新增
entry(入口调用)计数并区分 hit(过滤生效)计数,运行时安装后重算
unavailable。 - 诊断:
getBlockCodeOrderList/getResources/getBlockList/
底栏列表构建入口均记录 entry;getResources无命中时按 10 秒限流打印
block 运行时类型与 positionCode 样本,便于后续版本适配。
已知限制
- 底栏保留清单无法去掉「首页」Tab(9.6.13 主页面初始化依赖首页,
强行删除会导致启动卡死);首页定制页新增的「云村 (social)」「发布
(publish)」按 tabCode 匹配 9.6.13 新增 tab。 - UI-03 的隐藏清单基于 9.6.08 的 30 个 block code;9.6.13 首页出现了
PAGE_RECOMMEND_SEARCH_TOP_BANNER/SEARCH_CHANNEL_ENTRY/
MORE_RCMD等新 code,需要在新版首页定制里勾选对应项才会隐藏。 - 「我的页背景」清除后宿主侧
validType=4注入不会回滚(与 2.4.2 一致),
清除后如仍显示背景可重启网易云。
验证
:app:testDebugUnitTest:195 个用例通过(新增 MountResolver ClassLoader
隔离、HookState entry/unavailable、UI-03 block 匹配、UI-05 过滤与
Profile 门控、EN-01 调度点选择);:app:lintDebug通过。- 9.6.13 挂载体检 145/145 OK;9.6.08 挂载体检 142/142 OK。
- 真机 25102RKBEC:冷启动
runtime hooks installed: 4/4,UI-03 / UI-05 /
EN-01 hook 链路全部命中,无 FATAL / ANR / hook failed。
2.4.3
修复
- Issue #4:9.6.13 顶部频道管理(UI-04)不生效:网易云运行时使用 Tinker
热修 ClassLoader,模块启动时挂载的是 base 副本,导致 UI-04 钩子全部
“registered 但零命中”。现改为在首个Activity#onCreate用运行时
ClassLoader 安装 UI-04 钩子,并补充ArkFragmentV2/arkview.ArkFragment
数据链路覆盖。真机 9.6.13 验证:保留「心动/推荐」时顶部只剩这两个频道。 - EN-01 9.6.13 入口适配(第一层):
fullScreen注入入口整包改名
pc2.*→nb2.*,新增BgInfoParser/BgStore覆盖,避免 9.6.13 上
EN-01 类定位失败。9.6.08 不受影响。
已知问题(本次未修复)
- 9.6.13 上 UI-03 发现页推荐卡片隐藏仍不生效,首页卡片未按配置过滤。
- 9.6.13 上 UI-05 底部导航保留仍不生效,底栏 tab 未按配置裁剪。
- 9.6.13 上 EN-01 我的页自定义背景仍不显示:
MyMusicProxyFragment
类已消失(只剩 MyMusicFragmentV3/V4),页面架构变化,第二层调度点待
重新逆向;9.6.08 不受影响。 - 以上三项已记录,下一版继续处理;如急需可在 Issue 中补充诊断页截图和
网易云版本号。
验证
:app:testDebugUnitTest:166 个用例通过;:app:lintDebug、
:app:assembleRelease通过。- 9.6.13 挂载体检 142/142 OK;真机 25102RKBEC 冷启动验证:保留
「心动/推荐」时顶部只剩这两个频道,清空后恢复全部 6 个。
2.4.2
深度代码评审第三轮:调度/管线重构与热路径性能;附带 Issue #1 修复。
修复
- 「我的」页自定义背景整页透出(Issue #1):根因是宿主
gd()要求背景
图经官方加载器真实加载完成才给内容区设半透明遮罩,模块贴图的本地路径
走不通该链路。现于背景贴图后主动应用官方同款 scrim(0x1AFFFFFF),
清除背景时回调宿主恢复;gd()双签名兼容 9.6.08/9.6.13。已知限制:
网易云 9.6.13 起「我的」页架构调整,EN-01 整条链待下一版适配
(9.6.08 不受影响)。 - 诊断回传改领先+尾沿调度并收敛为共享管线:
TargetProcessPublisher统一
HookState 与 ExperimentState 两套回传(共享执行器/Context 反射缓存/authority),
窗口内状态变化不再丢失,最后一次变化必随尾沿上报——冷启动后诊断页
数分钟级延迟的问题根治;实验通道首事件改为立即发送。 - AbTest 定位并入 HookKit 主管线(获得 Profile 参数消歧/旧名映射;DexKit
兜底待锚点补充后自动生效);EN-01 全部类定位改走 HookKit,失败进入
诊断页(原仅 logcat 可见)。
变更
- HookKit 返回类型校验收紧:skipVoid 现要求精确 void 返回(全仓 26 个
skipVoid 站点已逐一审计确认为 void 后收紧),9 个文件的逐处样板检查
收敛为installVoidByName/installConstFalse中心助手。 - 「我的」页 hook 的反射样板与 sampleSize 手工副本删除;set 型配置与
强开映射解析收敛为PrefsSetCodec/ForceMapCodec单一实现;目标包名
常量收敛到Config.TARGET_PACKAGE。
性能
- MMKV 读取 hook 零分配快路径:mmapID 按实例缓存(每读 1 次反射→0)、
相关性判定改首字符预筛+regionMatches(最坏 240B/读分配→0)、黑名单为空
时连查表都不进。基准前后对照见评审产物。 - hit 限流键与 detail 解耦:被限流的命中不再拼字符串/进锁;限流表
超 512 条自动清空重建,消除长会话无界增长。
验证
:app:testDebugUnitTest:165 个用例通过(2.4.1 为 140);两波七组经
全站点审计门、补丁回放与基准复测验收;Issue #1 附带 3 个新用例。
2.4.1
深度代码评审第二轮修复(协议/并发/性能)。
修复
- 回传协议边界真强制:
StatusProvider落盘前对两种通道按结构白名单整体校验
(根键 / Feature 名 / 字段集 / 条数 ≤800 / 字符串 ≤256 / 总量 ≤64KB),不合拒绝;
退役与真实协议脱节的 reg./hit./skip. 白名单死抽象。 - 「我的」页背景三连修:external 共享副本写入改 tmp+rename 原子替换;
clear()/syncExternal()与导入共用单线程队列 FIFO 串行,消除「清除被在途
导入撤销」「导入报成功但文件已清空」等交错终态;目标进程位图缓存按源文件
指纹失效,换图/清除后即时生效,不再需要强杀网易云。 - PV-03 启动任务黑名单套用核心任务保护名单(与 EX-02 共享同一来源),
用户配错黑名单不会误杀受保护启动任务。 - AbTest 挂载失败进入诊断页(原仅 logcat 可见);删除 EN-01 无消费死坐标。
- JsonFilter 零删除快路径:延迟序列化 + 零删除原引用返回 + 嵌套串廉价预门;
实测 500KB 零命中 18.8ms → 0.19ms(≈98×),过滤语义不变。 - 死代码清理:
VersionGate.shouldProceed(恒真)、DexKitAnchors.of、
ProfileRegistry.clearActive、HookState.markNotFound旧重载、
MineBackgroundStore.calculateInSampleSize包装。
变更
ExperimentFragment改用StatusProvider.readExperiments单一读取入口。
验证
:app:testDebugUnitTest:140 个用例通过(2.4.0 为 123);七组修复经
变异验证、补丁回放与独立基准复测验收。- 真机(网易云音乐 9.6.13 / versionCode 9006013,KernelSU + LSPosed,与第三方模块
共存环境)冷启动验证:136 挂载全部注册、进程稳定无 FATAL、回传协议零拒绝。
注:x86_64 模拟器上宿主防篡改库(libpoison.so)有启动崩溃复现,与本版改动的
关联未证实(真机不重现),待模拟器环境恢复后复查。
2.4.0
底栏导航回归 + 适配网易云音乐 9.6.13(fail-open 版本门禁,versionCode 10)。
新增
- 底栏 4 tab 导航:设置 / 实验 / 诊断 / 关于四个顶层 tab 常驻底栏,切换用
hide/show 保留各 tab 滚动位置;「首页定制」保留为二级页(从设置页进入,
带返回箭头,进入时隐藏底栏,返回后恢复)。首页定制页移除冗余的
「仅本机可见」说明(功能表已有同一描述)。 - 适配网易云音乐 9.6.13(versionCode 9006013):新增
Profile9613挂载点总表,
与Profile9608双档案并存,ProfileRegistry按目标 versionCode 自动选择;
相对 9.6.08 的混淆漂移共 34 个挂载点重定位(按 mount id 的 overrides 表 +
hint 第三参等分片级差异),并新增 Profile 感知的方法名映射(hook 文件写死的
9.6.08 混淆名按活动 Profile 换算成实际方法名)。9.6.08 仍受支持。 - fail-open 版本门禁:未适配/未知版本不再因版本不匹配整体跳过 hook:
active Profile 置空后回退硬编码挂载点 best-effort 安装(与 QuietBox 语义一致),
状态卡/异常横幅提示未适配;移除allow_unsupported_version开关。
变更
- 工程整备:新增
tools/release.sh(一键发版:预检 → 构建 → 校验 → 归档 →
可选 tag / Release / 官方仓同步)、tools/verify-apk.sh(Xposed 元数据 / scope /
R8 keep / Manifest / 版本号 / 签名证书校验)、tools/preflight.sh(JDK 21 + SDK +
单测 + lint 预检)、CI(test + lint);接入 JaCoCo 覆盖率报告;新增 prefs/Feature
一致性与 Hook 注册表等单测;appcompat 1.8.0 / material 1.14.0;构建基线 JDK 21
(Java 字节码仍 17)。 - 移除未使用的
compileOnly io.github.libxposed:annotation:1.0.0依赖:
全部源码零引用,compileOnly 不进入 APK,删除不影响功能与产物。 tools/check-mounts.sh支持双档案:期望 versionCode 取自所选 profile JSON
(9608 / 9613 各自携带),不再硬编码单一版本号。
修复
StatusProvider上报 type 只认 mounts/experiments,未知 type 一律拒绝,
防止绕过 mounts 通道的主进程门禁覆盖主进程快照。- EX-02 启动任务编排改用 installOne 传入的会话级 config 快照,不二次
Config.load。 ConfigStore读取 Set 时空串视为未设置回退默认值,与Config.loadSet一致。- 主界面 tab 切换的刷新挂在事务
runOnCommit之后,落在真正切到的新 tab 上。
验证
:app:testDebugUnitTest:123 个用例通过;:app:lintDebug、
:app:assembleRelease、bash tools/preflight.sh、bash tools/verify-apk.sh通过。- 模拟器(网易云 9.6.13 / versionCode 9006013)运行时:115 registered / 0 skip /
10 mapped,无 FATAL。
APK: cloudmusictool-2.4.0.apk
versionCode: 10
大小: 4,231,517 字节
SHA-256: a378b3eeb5658f12d2d39efc3a1017ea926d345f33ddf865366bcdd27209e7de