refactor: remove repeated hook feature in YukiMemberHookCreator

This commit is contained in:
2025-06-16 18:20:47 +08:00
parent d36a6a10e0
commit beb7b431f8
8 changed files with 32 additions and 83 deletions

View File

@@ -77,4 +77,12 @@ val instance: Any
name = "test" name = "test"
emptyParameters() emptyParameters()
}.of(instance).invokeOriginal() }.of(instance).invokeOriginal()
``` ```
## Repeat Hook Restricted Deprecated
`YukiHookAPI` has deprecated the restriction of duplicate Hook since the `1.3.0` version.
Now, `YukiHookAPI` no longer limits duplicate Hooks to the same method, you can hook multiple times on the same method.
`YukiHookAPI` also deprecated the `onAlreadyHooked` method of `hook { ... }`.
Now this method will be useless and will not be called back. If necessary, please manually handle the relevant logic of duplicate Hooks.

View File

@@ -73,4 +73,10 @@ val instance: Any
name = "test" name = "test"
emptyParameters() emptyParameters()
}.of(instance).invokeOriginal() }.of(instance).invokeOriginal()
``` ```
## 重复 Hook 限制弃用
`YukiHookAPI``1.3.0` 版本开始弃用了重复 Hook 的限制,现在,`YukiHookAPI` 不再限制重复 Hook 同一个方法,你可以在同一个方法上多次 Hook。
`YukiHookAPI` 同时弃用了 `hook { ... }``onAlreadyHooked` 方法,现在此方法将无作用且不会被回调,如有需要,请手动处理重复 Hook 的相关逻辑。

View File

@@ -264,9 +264,6 @@ class YukiMemberHookCreator internal constructor(private val packageParam: Packa
/** Hook 成功时回调 */ /** Hook 成功时回调 */
private var onHookedCallback: ((Member) -> Unit)? = null private var onHookedCallback: ((Member) -> Unit)? = null
/** 重复 Hook 时回调 */
private var onAlreadyHookedCallback: ((Member) -> Unit)? = null
/** 找不到 [members] 出现错误回调 */ /** 找不到 [members] 出现错误回调 */
private var onNoSuchMemberFailureCallback: ((Throwable) -> Unit)? = null private var onNoSuchMemberFailureCallback: ((Throwable) -> Unit)? = null
@@ -447,8 +444,6 @@ class YukiMemberHookCreator internal constructor(private val packageParam: Packa
member.hook().also { member.hook().also {
when { when {
it.hookedMember?.member == null -> error("Hook Member [$member] failed") it.hookedMember?.member == null -> error("Hook Member [$member] failed")
it.isAlreadyHooked -> onAlreadyHookedCallback?.invoke(it.hookedMember.member!!)
?: YLog.innerW("Already Hooked Member [$member], this will be ignored")
else -> { else -> {
hookedMembers.add(it.hookedMember) hookedMembers.add(it.hookedMember)
onHookedCallback?.invoke(it.hookedMember.member!!) onHookedCallback?.invoke(it.hookedMember.member!!)
@@ -847,14 +842,13 @@ class YukiMemberHookCreator internal constructor(private val packageParam: Packa
/** /**
* 监听 [members] 重复 Hook 的回调方法 * 监听 [members] 重复 Hook 的回调方法
* *
* - 同一个 [hookClass] 中的同一个 [members] 不会被 API 重复 Hook - 若由于各种原因重复 Hook 会回调此方法 * - 此方法及功能已被移除 - 在之后的版本中将直接被删除
* @param result 回调被重复 Hook 的 [Member] *
* - 不再限制重复 Hook 操作
* @return [Result] 可继续向下监听 * @return [Result] 可继续向下监听
*/ */
fun onAlreadyHooked(result: (Member) -> Unit): Result { @Deprecated(message = "此方法及功能已被移除,请删除此方法")
onAlreadyHookedCallback = result fun onAlreadyHooked(result: (Member) -> Unit) = this
return this
}
/** /**
* 监听 [members] 不存在发生错误的回调方法 * 监听 [members] 不存在发生错误的回调方法

View File

@@ -24,7 +24,6 @@ package com.highcapable.yukihookapi.hook.core.api.factory
import com.highcapable.yukihookapi.hook.core.api.proxy.YukiHookCallback import com.highcapable.yukihookapi.hook.core.api.proxy.YukiHookCallback
import com.highcapable.yukihookapi.hook.core.api.proxy.YukiMemberHook import com.highcapable.yukihookapi.hook.core.api.proxy.YukiMemberHook
import com.highcapable.yukihookapi.hook.core.api.proxy.YukiMemberReplacement import com.highcapable.yukihookapi.hook.core.api.proxy.YukiMemberReplacement
import com.highcapable.yukihookapi.hook.core.api.store.YukiHookCacheStore
import java.lang.reflect.Member import java.lang.reflect.Member
/** /**
@@ -43,7 +42,6 @@ internal object YukiHookCallbackDelegate {
override val member get() = member() override val member get() = member()
override fun remove() { override fun remove() {
onRemove() onRemove()
runCatching { YukiHookCacheStore.hookedMembers.remove(this) }
} }
} }

View File

@@ -26,7 +26,6 @@ import com.highcapable.yukihookapi.hook.core.api.compat.HookApiCategoryHelper
import com.highcapable.yukihookapi.hook.core.api.compat.HookCompatHelper import com.highcapable.yukihookapi.hook.core.api.compat.HookCompatHelper
import com.highcapable.yukihookapi.hook.core.api.proxy.YukiHookCallback import com.highcapable.yukihookapi.hook.core.api.proxy.YukiHookCallback
import com.highcapable.yukihookapi.hook.core.api.result.YukiHookResult import com.highcapable.yukihookapi.hook.core.api.result.YukiHookResult
import com.highcapable.yukihookapi.hook.core.api.store.YukiHookCacheStore
import com.highcapable.yukihookapi.hook.log.YLog import com.highcapable.yukihookapi.hook.log.YLog
import java.lang.reflect.Member import java.lang.reflect.Member
@@ -50,27 +49,8 @@ internal object YukiHookHelper {
* @param callback 回调 * @param callback 回调
* @return [YukiHookResult] * @return [YukiHookResult]
*/ */
internal fun hookMember(member: Member?, callback: YukiHookCallback): YukiHookResult { internal fun hookMember(member: Member?, callback: YukiHookCallback) =
runCatching { YukiHookResult(hookedMember = HookCompatHelper.hookMember(member, callback))
YukiHookCacheStore.hookedMembers.takeIf { it.isNotEmpty() }?.forEach {
if (it.member.toString() == member?.toString()) return YukiHookResult(isAlreadyHooked = true, it)
}
}
return HookCompatHelper.hookMember(member, callback).let {
if (it != null) YukiHookCacheStore.hookedMembers.add(it)
YukiHookResult(hookedMember = it)
}
}
/**
* 获取当前 [Member] 是否被 Hook
* @param member 实例
* @return [Boolean]
*/
internal fun isMemberHooked(member: Member?): Boolean {
if (member == null) return false
return HookApiCategoryHelper.hasAvailableHookApi && YukiHookCacheStore.hookedMembers.any { it.member.toString() == member.toString() }
}
/** /**
* 执行原始 [Member] * 执行原始 [Member]
@@ -81,13 +61,12 @@ internal object YukiHookHelper {
* @return [Any] or null * @return [Any] or null
* @throws IllegalStateException 如果 [Member] 参数个数不正确 * @throws IllegalStateException 如果 [Member] 参数个数不正确
*/ */
internal fun invokeOriginalMember(member: Member?, instance: Any?, args: Array<out Any?>?) = internal fun invokeOriginalMember(member: Member?, instance: Any?, args: Array<out Any?>?) = member?.let {
if (isMemberHooked(member)) member?.let { runCatching { HookCompatHelper.invokeOriginalMember(member, instance, args) }.onFailure {
runCatching { HookCompatHelper.invokeOriginalMember(member, instance, args) }.onFailure { if (it.message?.lowercase()?.contains("wrong number of arguments") == true) error(it.message ?: it.toString())
if (it.message?.lowercase()?.contains("wrong number of arguments") == true) error(it.message ?: it.toString()) YLog.innerE("Invoke original Member [$member] failed", it)
YLog.innerE("Invoke original Member [$member] failed", it) }.getOrNull()
}.getOrNull() }
} else null
/** /**
* 使用当前 Hook API 自带的日志功能打印日志 * 使用当前 Hook API 自带的日志功能打印日志

View File

@@ -25,7 +25,6 @@ import com.highcapable.yukihookapi.hook.core.api.proxy.YukiMemberHook
/** /**
* Hook 结果实现类 * Hook 结果实现类
* @param isAlreadyHooked 是否已经被 Hook - 默认否
* @param hookedMember 当前 Hook 的实例对象 - 默认空 * @param hookedMember 当前 Hook 的实例对象 - 默认空
*/ */
internal data class YukiHookResult(val isAlreadyHooked: Boolean = false, val hookedMember: YukiMemberHook.HookedMember? = null) internal data class YukiHookResult(val hookedMember: YukiMemberHook.HookedMember? = null)

View File

@@ -1,35 +0,0 @@
/*
* YukiHookAPI - An efficient Hook API and Xposed Module solution built in Kotlin.
* Copyright (C) 2019 HighCapable
* https://github.com/HighCapable/YukiHookAPI
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is created by fankes on 2022/7/28.
* This file is modified by fankes on 2023/1/9.
*/
package com.highcapable.yukihookapi.hook.core.api.store
import com.highcapable.yukihookapi.hook.core.api.proxy.YukiMemberHook
import java.lang.reflect.Member
/**
* Hook 过程的功能缓存实现类
*/
internal object YukiHookCacheStore {
/** 已经 Hook 的 [Member] 数组 */
internal val hookedMembers = mutableSetOf<YukiMemberHook.HookedMember>()
}

View File

@@ -29,6 +29,7 @@ package com.highcapable.yukihookapi.hook.core.finder.members
import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.bean.VariousClass
import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator
import com.highcapable.yukihookapi.hook.core.api.helper.YukiHookHelper import com.highcapable.yukihookapi.hook.core.api.helper.YukiHookHelper
import com.highcapable.yukihookapi.hook.core.finder.ReflectionMigration
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder import com.highcapable.yukihookapi.hook.core.finder.base.MemberBaseFinder
import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData import com.highcapable.yukihookapi.hook.core.finder.members.data.MethodRulesData
@@ -39,7 +40,6 @@ import com.highcapable.yukihookapi.hook.core.finder.type.factory.ModifierConditi
import com.highcapable.yukihookapi.hook.core.finder.type.factory.NameConditions import com.highcapable.yukihookapi.hook.core.finder.type.factory.NameConditions
import com.highcapable.yukihookapi.hook.core.finder.type.factory.ObjectConditions import com.highcapable.yukihookapi.hook.core.finder.type.factory.ObjectConditions
import com.highcapable.yukihookapi.hook.core.finder.type.factory.ObjectsConditions import com.highcapable.yukihookapi.hook.core.finder.type.factory.ObjectsConditions
import com.highcapable.yukihookapi.hook.core.finder.ReflectionMigration
import com.highcapable.yukihookapi.hook.factory.hasExtends import com.highcapable.yukihookapi.hook.factory.hasExtends
import com.highcapable.yukihookapi.hook.log.YLog import com.highcapable.yukihookapi.hook.log.YLog
import com.highcapable.yukihookapi.hook.type.defined.UndefinedType import com.highcapable.yukihookapi.hook.type.defined.UndefinedType
@@ -726,7 +726,7 @@ class MethodFinder internal constructor(override val classSet: Class<*>? = null)
* @return [Any] or null * @return [Any] or null
*/ */
private fun baseCall(vararg args: Any?) = private fun baseCall(vararg args: Any?) =
if (isCallOriginal && YukiHookHelper.isMemberHooked(method)) if (isCallOriginal)
YukiHookHelper.invokeOriginalMember(method, instance, args) YukiHookHelper.invokeOriginalMember(method, instance, args)
else method?.invoke(instance, *args) else method?.invoke(instance, *args)