Repository navigation
Releases: IamCanincan/HardCrop
Release list
v1.0.9 — 修复第三方应用闪退 + 手动运维按钮 + 界面整理
修复:第三方应用闪退
现象:某些第三方应用冷启动时直接闪退、反复崩溃,清图标缓存也没用。
报错:
android.content.res.Resources$NotFoundException: Resource ID #0x6e08013b
at android.content.Context.getDrawable
at com.android.internal.widget.ActionBarView.setIcon
at android.app.Activity.initWindowDecorActionBar
at ...MainActivity.onCreate
根因:模块给应用图标的资源 ID 打标记(0x7f… → 0x6e…),好在图标加载出口认出它并裁成圆形。但打标记发生在 system_server(PMS)里,这些对象随后会经 Binder 传给任意应用进程。接收方不在本模块作用域内(没有还原逻辑)时,拿到的伪造 ID 在它自己的资源表里根本不存在,一解析就抛异常 —— 而调用点就在 Activity.onCreate 里,于是直接把应用带崩。
修复:在 writeToParcel(Binder 序列化出口)统一把标记还原成合法的 0x7f…,彻底掐断跨进程泄漏。已注入的进程(桌面 / 设置 / 状态栏等)收到后仍会重新打标记,裁圆功能不受影响。
修复:桌面图标的「全出血」开关从未生效
与同类模块逐条对齐排查时发现:IconOptions.drawFullBleed 是装箱的 java.lang.Boolean,而代码里写的是 Field.setBoolean() —— 它只接受基本类型 boolean,对装箱字段会抛 IllegalArgumentException。
模块跑在保护模式下,这个异常被整个吞掉:既不崩溃、也不留任何日志。结果是这个开关从加入那天起就没起过作用,真机日志里累计抛出了 9994 次。
已改为 Field.set()(自动拆箱,基本类型与装箱类型都成立)。修好后桌面图标不会再带多余的黑色方角,而且每次生成图标都少一次异常开销。
真机验证:清缓存全量重建后裁圆 40/40;新进程之后该异常 0 次。
新增:手动运维按钮(界面「运维操作」一栏)
- 清除缓存并重启桌面 —— 删掉桌面的
app_icons.db并重启桌面,图标按当前逻辑重新生成 - 重启 SystemUI
- 重启其他进程(设置 / 设置建议 / 意图解析器 / 权限控制器)
这几个动作全部由模块在目标进程内部完成(删自己的缓存、重启自己),不需要 root,也不会执行任何 shell 命令。
同时按反馈移除了自动清缓存:什么时候清由你决定,模块不再自作主张删除桌面的数据库。
界面整理
- 加了顶部应用栏(随列表滚动收起),右上角可直接打开仓库。
- 分区标题与卡片重新分组,一眼能看出标题领着哪张卡。
- 作用域列表默认只展开「必选 + 推荐」,5 条「可选」折叠起来,页面短了近一半。
- 验证命令改成整块点击复制(原来只有右侧一个小图标能按);按钮圆角统一。
真机验证
- 华为应用市场冷启动不再崩溃,进程正常存活(修复前连续两次
FATAL EXCEPTION)。 - 另测 Kimi / TapTap / Mihon 三个不在作用域的第三方应用,均无崩溃。
- 桌面清缓存后重建:裁圆调用 40/40(日志预算打满),覆盖自适应图标与位图图标,无回归。
- 三个运维按钮均实测生效(桌面 29273→29395 并重建图标、SystemUI 29918→30239、设置进程被杀后重新注入)。
- 界面在真机逐项确认:顶栏、作用域展开/收起、三个运维按钮均渲染正常,滚动与切换无崩溃。
assembleRelease+lintDebug均 0 error 0 warning。
说明
- 不需要额外权限,也不需要 root。
- 若你之前因为闪退在 LSPosed 里取消勾选了某些应用,升级后可以重新勾选。
HardCrop v1.0.8
(问题:模块给图标资源 ID 打的标记会跨进程泄漏到未注入的应用,解析时抛异常并直接带崩应用。)
变更
- 模块更新 / 启用后自动清理 launcher3 图标缓存:升级后桌面不会再显示上一版渲染的方形图标,无需手动操作(每个模块版本只清一次)
- 强制圆形裁切现已覆盖全部界面:桌面 / 抽屉、最近任务、设置应用列表、分享页、冷启动开屏、状态栏、权限弹窗、数字健康、电池用量页、主题图标(动态取色)
- 覆盖进程(作用域不写死,可在 LSPosed 管理器自行勾选):system_server、systemui、launcher3(含 Pixel Launcher)、settings、分享页、权限控制器、数字健康等 10 个
- 自适应图标同样强制裁圆,并透传 monochrome 层以支持 Android 13+ 主题图标染色
校验
- SHA256:
8fa0fed3d1ae4930d275c3869a212ba34258fcb105e12394e2489072c3a39b3b - 包名
com.iamcanincan.hardcrop,versionCode 8 / versionName 1.0.8
HardCrop v1.0.4
变更
- 修复应用列表不裁切:图标内容改放在 background 层,
RoundedIconDrawable用 DST_IN 自裁正圆(不再依赖系统 mask,解决 Settings 应用列表等直绘页面仍是方形的问题)。 - 对齐参考项目通道:覆盖
global-icon-pack-android的全部图标加载通道(严格超集),并保留双 ThreadLocal 防重入(marking + replacing),避免同一条调用链上圆套圆 / 尺寸重复缩放。 - 新增裁圆专属通道:
Settings.Utils.getAdaptiveIcon(deoptimize)、电池用量页、冷启动 splash、APM.getDrawable / getApplicationIcon 等直接 Drawable 出口。 - 去除临时诊断探针,行为稳定。
适用
LSPosed / LibXposed(API 102)。把非自适应图标强制裁成圆形。
HardCrop v1.0.3
修复
-
修点击桌面图标导致桌面崩溃(v1.0.2 的严重 bug,装了 1.0.2 请尽快升级)
点击桌面 / 抽屉里任意非自适应图标的 app,会让桌面(launcher)整个进程崩溃闪退。
根因:CircleIconDrawable.getConstantState()返回了 null,而 Launcher3 的
FloatingIconView会直接icon.getConstantState().newDrawable()—— 拿到 null 就是 NPE。
现在包装类与其内层都实现了getConstantState()且永不返回 null。 -
适配 Pixel Launcher(
com.google.android.apps.nexuslauncher)
Pixel / Nexus 的桌面进程包名跟类原生 ROM 用的com.android.launcher3不一样,
之前模块不会作用于它。现在作用域列表、内部类(BaseIconFactory / IconOptions)
查找、以及应用内的作用域清单都同时兼容这两个包名。
已知限制
- 设置页 / 分享菜单里的应用列表项,走的是
system_server里 PMS 缓存的 Bitmap,
而system_server在开机时往往早于 LSPosed daemon 启动、未被注入,这一处看到的
仍是原图。重启一次设备可让system_server也进入注入。 - 点击图标时桌面的浮起过渡动画,其图标外框由 launcher 自己绘制,本模块不介入。
- 快捷设置磁贴画的是小尺寸单色图形,通知栏小图标走别的资源,均不受影响。
校验
SHA256 ad14dc0916dda1034444408a97d71445acb9d674734b8dae6401763ecbb48d78
size 1076927 bytes
HardCrop v1.0.2
把非自适应图标强制裁成圆形 —— 只做这一件事。已经是自适应图标的应用不会被改动。
安装
- 需要 root + LSPosed(或其兼容框架,libxposed API 100+)。
- 装好下面的 APK,在 LSPosed 里启用模块。
- 重启设备 —— 模块不支持热加载。
作用域已经用 staticScope 固定为 6 个进程,管理器里只能勾这些,勾别的会被框架拒绝:
android 系统服务,解析应用信息
com.android.launcher3 桌面与应用抽屉(效果最直观)
com.android.systemui 状态栏与最近任务
com.android.settings 设置里的应用列表
com.android.intentresolver 分享与打开方式的选择列表
com.android.permissioncontroller 权限弹窗里的应用图标
至少勾选 com.android.launcher3 才能在桌面看到效果。
验证
adb logcat -s HardCrop
看到 onPackageReady 与 Hooked 就说明模块已注入该进程。
本次包含的改动
1.0.2 是本仓库的第一个 Release,包含了自 1.0 以来的全部改动:
- 包名统一为
com.iamcanincan.hardcrop,并补上应用界面(作用域清单、启用步骤、
验证命令、检查更新)。之前纯后台模块没有桌面图标,只能去设置的应用列表里找。 - 静态作用域:
scope.list只留模块真正 hook 的 6 个进程。 - 模块描述:改用
android:description(管理器读的是ApplicationInfo.descriptionRes;
写在module.prop的description=是 API ≤ 93 的旧写法,LibXposed 不读)。 - 检查更新:应用内唯一联网行为,且只在点了按钮之后才发起。先直连 GitHub,
连不上时退到公共加速镜像。没有统计也没有上报。 - Android 16+:额外关掉 Pixel Launcher 自带的白色圆形背景板
(IconOptions.drawFullBleed = false),图标按原样铺满圆形。
已知取舍
- 快捷设置磁贴画的是单色小图形,被排除在外。
- 旧版 Android(< 16)的桌面会保留 launcher 自带的背景板,模块只能保证 Drawable 本身是圆形。
- 应用列表(Settings)走 PMS 的 Bitmap 缓存,重启后才会刷新;桌面与应用抽屉即时生效。
校验
SHA256 d30ae06dd3c084d0afaca048f99da2032e83fd9326e80569ed1b0cd459e75da3
MIT 许可。