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

@@ -78,3 +78,11 @@ val instance: Any
emptyParameters()
}.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

@@ -74,3 +74,9 @@ val instance: Any
emptyParameters()
}.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 成功时回调 */
private var onHookedCallback: ((Member) -> Unit)? = null
/** 重复 Hook 时回调 */
private var onAlreadyHookedCallback: ((Member) -> Unit)? = null
/** 找不到 [members] 出现错误回调 */
private var onNoSuchMemberFailureCallback: ((Throwable) -> Unit)? = null
@@ -447,8 +444,6 @@ class YukiMemberHookCreator internal constructor(private val packageParam: Packa
member.hook().also {
when {
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 -> {
hookedMembers.add(it.hookedMember)
onHookedCallback?.invoke(it.hookedMember.member!!)
@@ -847,14 +842,13 @@ class YukiMemberHookCreator internal constructor(private val packageParam: Packa
/**
* 监听 [members] 重复 Hook 的回调方法
*
* - 同一个 [hookClass] 中的同一个 [members] 不会被 API 重复 Hook - 若由于各种原因重复 Hook 会回调此方法
* @param result 回调被重复 Hook 的 [Member]
* - 此方法及功能已被移除 - 在之后的版本中将直接被删除
*
* - 不再限制重复 Hook 操作
* @return [Result] 可继续向下监听
*/
fun onAlreadyHooked(result: (Member) -> Unit): Result {
onAlreadyHookedCallback = result
return this
}
@Deprecated(message = "此方法及功能已被移除,请删除此方法")
fun onAlreadyHooked(result: (Member) -> Unit) = this
/**
* 监听 [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.YukiMemberHook
import com.highcapable.yukihookapi.hook.core.api.proxy.YukiMemberReplacement
import com.highcapable.yukihookapi.hook.core.api.store.YukiHookCacheStore
import java.lang.reflect.Member
/**
@@ -43,7 +42,6 @@ internal object YukiHookCallbackDelegate {
override val member get() = member()
override fun remove() {
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.proxy.YukiHookCallback
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 java.lang.reflect.Member
@@ -50,27 +49,8 @@ internal object YukiHookHelper {
* @param callback 回调
* @return [YukiHookResult]
*/
internal fun hookMember(member: Member?, callback: YukiHookCallback): YukiHookResult {
runCatching {
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() }
}
internal fun hookMember(member: Member?, callback: YukiHookCallback) =
YukiHookResult(hookedMember = HookCompatHelper.hookMember(member, callback))
/**
* 执行原始 [Member]
@@ -81,13 +61,12 @@ internal object YukiHookHelper {
* @return [Any] or null
* @throws IllegalStateException 如果 [Member] 参数个数不正确
*/
internal fun invokeOriginalMember(member: Member?, instance: Any?, args: Array<out Any?>?) =
if (isMemberHooked(member)) member?.let {
runCatching { HookCompatHelper.invokeOriginalMember(member, instance, args) }.onFailure {
if (it.message?.lowercase()?.contains("wrong number of arguments") == true) error(it.message ?: it.toString())
YLog.innerE("Invoke original Member [$member] failed", it)
}.getOrNull()
} else null
internal fun invokeOriginalMember(member: Member?, instance: Any?, args: Array<out Any?>?) = member?.let {
runCatching { HookCompatHelper.invokeOriginalMember(member, instance, args) }.onFailure {
if (it.message?.lowercase()?.contains("wrong number of arguments") == true) error(it.message ?: it.toString())
YLog.innerE("Invoke original Member [$member] failed", it)
}.getOrNull()
}
/**
* 使用当前 Hook API 自带的日志功能打印日志

View File

@@ -25,7 +25,6 @@ import com.highcapable.yukihookapi.hook.core.api.proxy.YukiMemberHook
/**
* Hook 结果实现类
* @param isAlreadyHooked 是否已经被 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.core.YukiMemberHookCreator
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.MemberBaseFinder
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.ObjectConditions
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.log.YLog
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
*/
private fun baseCall(vararg args: Any?) =
if (isCallOriginal && YukiHookHelper.isMemberHooked(method))
if (isCallOriginal)
YukiHookHelper.invokeOriginalMember(method, instance, args)
else method?.invoke(instance, *args)