Added injectModuleAppResources on Resources function in YukiHookFactory

This commit is contained in:
2022-08-09 23:56:04 +08:00
parent 3cbe9f8cb6
commit 6d23b85541
3 changed files with 37 additions and 25 deletions

View File

@@ -114,17 +114,21 @@ val Context.processName: String
fun Context.injectModuleAppResources() fun Context.injectModuleAppResources()
``` ```
```kotlin
fun Resources.injectModuleAppResources()
```
**变更记录** **变更记录**
`v1.0.93` `新增` `v1.0.93` `新增`
**功能描述** **功能描述**
> 向 Hook APP (宿主) `Context` 注入当前 Xposed 模块的资源。 > 向 Hook APP (宿主) `Context` 或 `Resources` 注入当前 Xposed 模块的资源。
注入成功后,你就可以直接使用例如 `ImageView.setImageResource``Resources.getString` 装载当前 Xposed 模块的资源 ID。 注入成功后,你就可以直接使用例如 `ImageView.setImageResource``Resources.getString` 装载当前 Xposed 模块的资源 ID。
注入的资源作用域仅限当前 `Context`,你需要在每个用到宿主 `Context` 的地方重复调用此方法进行注入才能使用。 注入的资源作用域仅限当前 `Context``Resources`,你需要在每个用到宿主 `Context``Resources` 的地方重复调用此方法进行注入才能使用。
为防止资源 ID 互相冲突,你需要在当前 Xposed 模块项目的 `build.gradle` 中修改资源 ID。 为防止资源 ID 互相冲突,你需要在当前 Xposed 模块项目的 `build.gradle` 中修改资源 ID。
@@ -158,8 +162,10 @@ injectMember {
} }
afterHook { afterHook {
instance<Activity>().also { instance<Activity>().also {
// 注入模块资源 // <方案1> 通过 Context 注入模块资源
it.injectModuleAppResources() it.injectModuleAppResources()
// <方案2> 直接得到宿主 Resources 注入模块资源
it.resources.injectModuleAppResources()
// 直接使用模块资源 ID // 直接使用模块资源 ID
it.getString(R.id.app_name) it.getString(R.id.app_name)
} }
@@ -175,7 +181,10 @@ injectMember {
onAppLifecycle { onAppLifecycle {
onCreate { onCreate {
// 全局注入模块资源,但仅限于全局生命周期,类似 ImageView.setImageResource 这样的方法在 Activity 中需要单独注入 // 全局注入模块资源,但仅限于全局生命周期,类似 ImageView.setImageResource 这样的方法在 Activity 中需要单独注入
// <方案1> 通过 Context 注入模块资源
injectModuleAppResources() injectModuleAppResources()
// <方案2> 直接得到宿主 Resources 注入模块资源
resources.injectModuleAppResources()
// 直接使用模块资源 ID // 直接使用模块资源 ID
getString(R.id.app_name) getString(R.id.app_name)
} }

View File

@@ -107,21 +107,24 @@ val Context.processName
* *
* 注入的资源作用域仅限当前 [Context] - 你需要在每个用到宿主 [Context] 的地方重复调用此方法进行注入才能使用 * 注入的资源作用域仅限当前 [Context] - 你需要在每个用到宿主 [Context] 的地方重复调用此方法进行注入才能使用
* *
* 为防止资源 ID 互相冲突 - 你需要在当前 Xposed 模块项目的 build.gradle 中修改资源 ID * 详情请参考 [injectModuleAppResources](https://fankes.github.io/YukiHookAPI/#/api/document?id=injectmoduleappresources-method)
*
* - Kotlin Gradle DSL ↓
*
* androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
*
* - Groovy ↓
*
* aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
*
* - ❗提供的示例资源 ID 值仅供参考 - 为了防止当前宿主存在多个 Xposed 模块 - 建议自定义你自己的资源 ID
* *
* - ❗只能在 (Xposed) 宿主环境使用此功能 - 其它环境下使用将不生效且会打印警告信息 * - ❗只能在 (Xposed) 宿主环境使用此功能 - 其它环境下使用将不生效且会打印警告信息
*/ */
fun Context.injectModuleAppResources() = YukiHookBridge.injectModuleAppResources(context = this) fun Context.injectModuleAppResources() = resources?.injectModuleAppResources()
/**
* 向 Hook APP (宿主) 指定 [Resources] 直接注入当前 Xposed 模块的资源
*
* 注入成功后 - 你就可以直接使用例如 [ImageView.setImageResource] 或 [Resources.getString] 装载当前 Xposed 模块的资源 ID
*
* 注入的资源作用域仅限当前 [Resources] - 你需要在每个用到宿主 [Resources] 的地方重复调用此方法进行注入才能使用
*
* 详情请参考 [injectModuleAppResources](https://fankes.github.io/YukiHookAPI/#/api/document?id=injectmoduleappresources-method)
*
* - ❗只能在 (Xposed) 宿主环境使用此功能 - 其它环境下使用将不生效且会打印警告信息
*/
fun Resources.injectModuleAppResources() = YukiHookBridge.injectModuleAppResources(hostResources = this)
/** /**
* 仅判断模块是否在太极、无极中激活 * 仅判断模块是否在太极、无极中激活

View File

@@ -101,8 +101,8 @@ object YukiHookBridge {
/** 当前 [PackageParamWrapper] 实例数组 */ /** 当前 [PackageParamWrapper] 实例数组 */
private val packageParamWrappers = HashMap<String, PackageParamWrapper>() private val packageParamWrappers = HashMap<String, PackageParamWrapper>()
/** 已被注入到宿主 [Context] 中的当前 Xposed 模块资源 HashCode 数组 */ /** 已被注入到宿主 [Resources] 中的当前 Xposed 模块资源 HashCode 数组 */
private val injectedHostContextHashCodes = HashSet<Int>() private val injectedHostResourcesHashCodes = HashSet<Int>()
/** 当前 [PackageParam] 方法体回调 */ /** 当前 [PackageParam] 方法体回调 */
internal var packageParamCallback: (PackageParam.() -> Unit)? = null internal var packageParamCallback: (PackageParam.() -> Unit)? = null
@@ -336,20 +336,20 @@ object YukiHookBridge {
} }
/** /**
* 向 Hook APP (宿主) [Context] 注入当前 Xposed 模块的资源 * 向 Hook APP (宿主) 注入当前 Xposed 模块的资源
* @param context 需要注入的 [Context] * @param hostResources 需要注入的宿主 [Resources]
*/ */
internal fun injectModuleAppResources(context: Context) { internal fun injectModuleAppResources(hostResources: Resources) {
if (injectedHostContextHashCodes.contains(context.hashCode())) return if (injectedHostResourcesHashCodes.contains(hostResources.hashCode())) return
injectedHostContextHashCodes.add(context.hashCode()) injectedHostResourcesHashCodes.add(hostResources.hashCode())
if (hasXposedBridge) if (hasXposedBridge)
AssetManagerClass.method { AssetManagerClass.method {
name = "addAssetPath" name = "addAssetPath"
param(StringType) param(StringType)
}.ignored().onNoSuchMethod { }.ignored().onNoSuchMethod {
runCatching { injectedHostContextHashCodes.remove(context.hashCode()) } runCatching { injectedHostResourcesHashCodes.remove(hostResources.hashCode()) }
yLoggerE(msg = "Failed to inject module resources in context [$context]", e = it) yLoggerE(msg = "Failed to inject module resources into [$hostResources]", e = it)
}.get(context.resources.assets).call(moduleAppFilePath) }.get(hostResources.assets).call(moduleAppFilePath)
else yLoggerW(msg = "You can only inject module resources in Xposed Environment") else yLoggerW(msg = "You can only inject module resources in Xposed Environment")
} }