EzResources

宿主资源替换。借 ResourcesLoader 把模块 apk 挂进宿主 Resources,再 hook Resources / TypedArray 的 getter 按「包名 + 类型 + 名称」拦截取值。不依赖 framework 提供资源接口,思路来自 HyperCeiler 的 ResourcesTool

EzResources.setResReplacement("com.miui.home", "drawable", "ic_launcher", R.drawable.my_icon)
EzResources.setObjectReplacement("com.miui.home", "color", "bg", Color.RED)
EzResources.setDensityReplacement("com.miui.home", "dimen", "bar_height", 8f)

包名传 "*" 表示不限宿主,精确匹配优先。hook 按需装、进程级、带稳定 reloadKey,模块不需要持有或摘除。 替换规则按名字存、取值时才对当前挂着的 apk 解析 id,所以 102 热重载换 apk 不会串资源;loader 由新一代先挂新再摘旧。

Functions

Link copied to clipboard

清掉全部替换规则。已经装上的 hook 不摘 —— 它们此后只是空转。

Link copied to clipboard

生成一个不与宿主冲突的虚拟资源 ID,用于宿主里本来没有的资源。

Link copied to clipboard
fun inject(context: Context, onMainLooper: Boolean = false): Boolean

inject 的 Context 形式。

fun inject(resources: Resources, onMainLooper: Boolean = false): Boolean

把模块 apk 挂进 resources,之后宿主能解析模块的 R.xxx。R 及以上走 ResourcesLoader,否则回退 AssetManager.addAssetPath。重复调用同一个 resources 是安全的。

Link copied to clipboard
fun setDensityReplacement(pkg: String, type: String, name: String, value: Float)

数值 x 屏幕密度,即 dp 语义。用于 dimen

Link copied to clipboard
fun setObjectReplacement(pkg: String, type: String, name: String, value: Any)

直接给一个值。类型要和取值方法对得上(getText 需要 CharSequence,数值类接受任意 Number), 对不上会记一条 warn 并放行原值。

Link copied to clipboard
fun setResReplacement(pkg: String, type: String, name: String, moduleResId: Int)

用模块里的资源顶掉宿主资源。