diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt index ea75a3d9..47a426c9 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt @@ -46,6 +46,7 @@ import com.highcapable.yukihookapi.hook.core.finder.classes.DexClassFinder import com.highcapable.yukihookapi.hook.core.finder.tools.ReflectionTool import com.highcapable.yukihookapi.hook.core.finder.type.factory.ClassConditions import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker +import com.highcapable.yukihookapi.hook.log.yLoggerW import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper import com.highcapable.yukihookapi.hook.utils.value import com.highcapable.yukihookapi.hook.xposed.bridge.YukiXposedModule @@ -427,7 +428,21 @@ open class PackageParam internal constructor(@PublishedApi internal var wrapper: * 你可以在 Hooker 中继续装载 Hooker * @param hooker Hook 子类 */ - fun loadHooker(hooker: YukiBaseHooker) = hooker.assignInstance(packageParam = this) + fun loadHooker(hooker: YukiBaseHooker) { + hooker.wrapper?.also { + if (it.packageName.isNotBlank() && it.type != HookEntryType.ZYGOTE) + if (it.packageName == wrapper?.packageName) + hooker.assignInstance(packageParam = this) + else yLoggerW( + msg = "This Hooker \"${hooker::class.java.name}\" is singleton or reused, " + + "but the current process has multiple package name \"${wrapper?.packageName}\", " + + "the original is \"${it.packageName}\"\n" + + "Make sure your Hooker supports multiple instances for this situation\n" + + "The process with package name \"${wrapper?.packageName}\" will be ignored" + ) + else hooker.assignInstance(packageParam = this) + } ?: hooker.assignInstance(packageParam = this) + } /** * 通过 [appClassLoader] 按指定条件查找并得到当前 Hook APP Dex 中的 [Class] diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/wrapper/PackageParamWrapper.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/wrapper/PackageParamWrapper.kt index e4a146e5..c185df2f 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/wrapper/PackageParamWrapper.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/wrapper/PackageParamWrapper.kt @@ -54,6 +54,12 @@ internal class PackageParamWrapper internal constructor( var appResources: YukiResources? = null ) { + /** + * 获取当前包装实例的名称 ID + * @return [String] + */ + internal val wrapperNameId get() = if (type == HookEntryType.ZYGOTE) "android-zygote" else packageName + /** * 获取当前正在进行的 Hook 进程是否正确 * diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiXposedModule.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiXposedModule.kt index 6e04d441..aa813e0f 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiXposedModule.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/bridge/YukiXposedModule.kt @@ -57,8 +57,8 @@ internal object YukiXposedModule : IYukiXposedModuleLifecycle { /** 当前 Hook 进程是否正处于 Zygote */ private var isInitializingZygote = false - /** 当前 [PackageParam] 实例 */ - private val packageParam = PackageParam() + /** 当前 [PackageParam] 实例数组 */ + private val packageParams = HashMap() /** 已在 [PackageParam] 中被装载的 APP 包名 */ private val loadedPackageNames = HashSet() @@ -126,6 +126,14 @@ internal object YukiXposedModule : IYukiXposedModuleLifecycle { return false } + /** + * 实例化当前 [PackageParamWrapper] 到 [PackageParam] + * + * 如果实例不存在将会自动创建一个新实例 + * @return [PackageParam] + */ + private fun PackageParamWrapper.instantiate() = packageParams[wrapperNameId] ?: PackageParam().apply { packageParams[wrapperNameId] = this } + /** * 创建、修改 [PackageParamWrapper] * @@ -206,7 +214,7 @@ internal object YukiXposedModule : IYukiXposedModuleLifecycle { else null }?.also { runCatching { - if (it.isCorrectProcess) packageParamCallback?.invoke(packageParam.assign(it).apply { YukiHookAPI.printSplashInfo() }) + if (it.isCorrectProcess) packageParamCallback?.invoke(it.instantiate().assign(it).apply { YukiHookAPI.printSplashInfo() }) if (it.type != HookEntryType.ZYGOTE && it.packageName == modulePackageName) AppParasitics.hookModuleAppRelated(it.appClassLoader, it.type) if (it.type == HookEntryType.PACKAGE) AppParasitics.registerToAppLifecycle(it.packageName)