mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
Added "onAlreadyHooked" method in YukiMemberHookCreater
This commit is contained in:
@@ -565,6 +565,7 @@ injectMember {
|
||||
// Your code here.
|
||||
}.result {
|
||||
onHooked {}
|
||||
onAlreadyHooked {}
|
||||
ignoredConductFailure()
|
||||
onHookingFailure {}
|
||||
// ...
|
||||
@@ -605,6 +606,24 @@ fun onHooked(initiate: (Member) -> Unit): Result
|
||||
|
||||
在首次 Hook 成功后回调。
|
||||
|
||||
在重复 Hook 时会回调 `onAlreadyHooked`。
|
||||
|
||||
##### onAlreadyHooked [method]
|
||||
|
||||
```kotlin
|
||||
fun onAlreadyHooked(initiate: (Member) -> Unit): Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0.89` `新增`
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 监听 `member` 重复 Hook 的回调方法。
|
||||
|
||||
!> 同一个 `hookClass` 中的同一个 `member` 不会被 API 重复 Hook,若由于各种原因重复 Hook 会回调此方法。
|
||||
|
||||
##### onNoSuchMemberFailure [method]
|
||||
|
||||
```kotlin
|
||||
|
@@ -162,6 +162,9 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
/** Hook 成功时回调 */
|
||||
private var onHookedCallback: ((Member) -> Unit)? = null
|
||||
|
||||
/** 重复 Hook 时回调 */
|
||||
private var onAlreadyHookedCallback: ((Member) -> Unit)? = null
|
||||
|
||||
/** 找不到 [member] 出现错误回调 */
|
||||
private var onNoSuchMemberFailureCallback: ((Throwable) -> Unit)? = null
|
||||
|
||||
@@ -502,11 +505,14 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
if (member != null)
|
||||
member.also { member ->
|
||||
runCatching {
|
||||
(if (isReplaceHookMode)
|
||||
YukiHookBridge.Hooker.hookMethod(member, replaceMent)?.also { onHookedCallback?.invoke(it) }
|
||||
?: error("Hook Member [$member] failed")
|
||||
else YukiHookBridge.Hooker.hookMethod(member, beforeAfterHook)?.also { onHookedCallback?.invoke(it) }
|
||||
?: error("Hook Member [$member] failed"))
|
||||
(if (isReplaceHookMode) YukiHookBridge.Hooker.hookMethod(member, replaceMent)
|
||||
else YukiHookBridge.Hooker.hookMethod(member, beforeAfterHook)).also {
|
||||
when {
|
||||
it.first == null -> error("Hook Member [$member] failed")
|
||||
it.second -> onAlreadyHookedCallback?.invoke(it.first!!)
|
||||
else -> onHookedCallback?.invoke(it.first!!)
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
onHookingFailureCallback?.invoke(it)
|
||||
onAllFailureCallback?.invoke(it)
|
||||
@@ -527,24 +533,22 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
else runCatching {
|
||||
when (hookMemberMode) {
|
||||
HookMemberMode.HOOK_ALL_METHODS ->
|
||||
if (isReplaceHookMode)
|
||||
YukiHookBridge.Hooker.hookAllMethods(hookClass.instance, allMethodsName, replaceMent).also {
|
||||
if (it.isEmpty()) throw NoSuchMethodError("No Method name \"$allMethodsName\" matched")
|
||||
else it.forEach { e -> onHookedCallback?.invoke(e) }
|
||||
(if (isReplaceHookMode) YukiHookBridge.Hooker.hookAllMethods(hookClass.instance, allMethodsName, replaceMent)
|
||||
else YukiHookBridge.Hooker.hookAllMethods(hookClass.instance, allMethodsName, beforeAfterHook)).also {
|
||||
when {
|
||||
it.first.isEmpty() -> throw NoSuchMethodError("No Method name \"$allMethodsName\" matched")
|
||||
it.second -> it.first.forEach { e -> onAlreadyHookedCallback?.invoke(e) }
|
||||
else -> it.first.forEach { e -> onHookedCallback?.invoke(e) }
|
||||
}
|
||||
else YukiHookBridge.Hooker.hookAllMethods(hookClass.instance, allMethodsName, beforeAfterHook).also {
|
||||
if (it.isEmpty()) throw NoSuchMethodError("No Method name \"$allMethodsName\" matched")
|
||||
else it.forEach { e -> onHookedCallback?.invoke(e) }
|
||||
}
|
||||
HookMemberMode.HOOK_ALL_CONSTRUCTORS ->
|
||||
if (isReplaceHookMode)
|
||||
YukiHookBridge.Hooker.hookAllConstructors(hookClass.instance, replaceMent).also {
|
||||
if (it.isEmpty()) throw NoSuchMethodError("No Constructor matched")
|
||||
else it.forEach { e -> onHookedCallback?.invoke(e) }
|
||||
(if (isReplaceHookMode) YukiHookBridge.Hooker.hookAllConstructors(hookClass.instance, replaceMent)
|
||||
else YukiHookBridge.Hooker.hookAllConstructors(hookClass.instance, beforeAfterHook)).also {
|
||||
when {
|
||||
it.first.isEmpty() -> throw NoSuchMethodError("No Constructor matched")
|
||||
it.second -> it.first.forEach { e -> onAlreadyHookedCallback?.invoke(e) }
|
||||
else -> it.first.forEach { e -> onHookedCallback?.invoke(e) }
|
||||
}
|
||||
else YukiHookBridge.Hooker.hookAllConstructors(hookClass.instance, beforeAfterHook).also {
|
||||
if (it.isEmpty()) throw NoSuchMethodError("No Constructor matched")
|
||||
else it.forEach { e -> onHookedCallback?.invoke(e) }
|
||||
}
|
||||
else -> error("Hooked got a no error possible")
|
||||
}
|
||||
@@ -618,6 +622,8 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
* 监听 [member] Hook 成功的回调方法
|
||||
*
|
||||
* 在首次 Hook 成功后回调
|
||||
*
|
||||
* 在重复 Hook 时会回调 [onAlreadyHooked]
|
||||
* @param initiate 回调被 Hook 的 [Member]
|
||||
* @return [Result] 可继续向下监听
|
||||
*/
|
||||
@@ -626,6 +632,18 @@ class YukiMemberHookCreater(@PublishedApi internal val packageParam: PackagePara
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听 [member] 重复 Hook 的回调方法
|
||||
*
|
||||
* - ❗同一个 [hookClass] 中的同一个 [member] 不会被 API 重复 Hook - 若由于各种原因重复 Hook 会回调此方法
|
||||
* @param initiate 回调被重复 Hook 的 [Member]
|
||||
* @return [Result] 可继续向下监听
|
||||
*/
|
||||
fun onAlreadyHooked(initiate: (Member) -> Unit): Result {
|
||||
onAlreadyHookedCallback = initiate
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听 [member] 不存在发生错误的回调方法
|
||||
* @param initiate 回调错误
|
||||
|
@@ -477,12 +477,12 @@ object YukiHookBridge {
|
||||
* 对接 [XposedBridge.hookMethod]
|
||||
* @param hookMethod 需要 Hook 的方法、构造方法
|
||||
* @param callback 回调
|
||||
* @return [Member] or null
|
||||
* @return [Pair] - ([Member] or null,[Boolean] 是否已经 Hook)
|
||||
*/
|
||||
internal fun hookMethod(hookMethod: Member?, callback: YukiHookCallback): Member? {
|
||||
if (hookedMembers.contains(hookMethod.toString())) return hookMethod
|
||||
internal fun hookMethod(hookMethod: Member?, callback: YukiHookCallback): Pair<Member?, Boolean> {
|
||||
if (hookedMembers.contains(hookMethod.toString())) return Pair(hookMethod, true)
|
||||
hookedMembers.add(hookMethod.toString())
|
||||
return XposedBridge.hookMethod(hookMethod, compatCallback(callback))?.hookedMethod
|
||||
return Pair(XposedBridge.hookMethod(hookMethod, compatCallback(callback))?.hookedMethod, false)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -492,17 +492,22 @@ object YukiHookBridge {
|
||||
* @param hookClass 当前 Hook 的 [Class]
|
||||
* @param methodName 方法名
|
||||
* @param callback 回调
|
||||
* @return [HashSet] 成功 Hook 的方法数组
|
||||
* @return [Pair] - ([HashSet] 成功 Hook 的方法数组,[Boolean] 是否已经 Hook)
|
||||
*/
|
||||
internal fun hookAllMethods(hookClass: Class<*>?, methodName: String, callback: YukiHookCallback) = HashSet<Member>().also {
|
||||
val allMethodsName = "$hookClass$methodName"
|
||||
if (hookedAllMethods.contains(allMethodsName)) {
|
||||
hookClass?.allMethods { _, method -> if (method.name == methodName) it.add(method) }
|
||||
return@also
|
||||
internal fun hookAllMethods(hookClass: Class<*>?, methodName: String, callback: YukiHookCallback): Pair<HashSet<Member>, Boolean> {
|
||||
var isAlreadyHook = false
|
||||
val hookedMembers = HashSet<Member>().also {
|
||||
val allMethodsName = "$hookClass$methodName"
|
||||
if (hookedAllMethods.contains(allMethodsName)) {
|
||||
isAlreadyHook = true
|
||||
hookClass?.allMethods { _, method -> if (method.name == methodName) it.add(method) }
|
||||
return@also
|
||||
}
|
||||
hookedAllMethods.add(allMethodsName)
|
||||
XposedBridge.hookAllMethods(hookClass, methodName, compatCallback(callback)).takeIf { it.isNotEmpty() }
|
||||
?.forEach { e -> it.add(e.hookedMethod) }
|
||||
}
|
||||
hookedAllMethods.add(allMethodsName)
|
||||
XposedBridge.hookAllMethods(hookClass, methodName, compatCallback(callback)).takeIf { it.isNotEmpty() }
|
||||
?.forEach { e -> it.add(e.hookedMethod) }
|
||||
return Pair(hookedMembers, isAlreadyHook)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -511,17 +516,22 @@ object YukiHookBridge {
|
||||
* 对接 [XposedBridge.hookAllConstructors]
|
||||
* @param hookClass 当前 Hook 的 [Class]
|
||||
* @param callback 回调
|
||||
* @return [HashSet] 成功 Hook 的构造方法数组
|
||||
* @return [Pair] - ([HashSet] 成功 Hook 的构造方法数组,[Boolean] 是否已经 Hook)
|
||||
*/
|
||||
internal fun hookAllConstructors(hookClass: Class<*>?, callback: YukiHookCallback) = HashSet<Member>().also {
|
||||
val allConstructorsName = "$hookClass<init>"
|
||||
if (hookedAllConstructors.contains(allConstructorsName)) {
|
||||
hookClass?.allConstructors { _, constructor -> it.add(constructor) }
|
||||
return@also
|
||||
internal fun hookAllConstructors(hookClass: Class<*>?, callback: YukiHookCallback): Pair<HashSet<Member>, Boolean> {
|
||||
var isAlreadyHook = false
|
||||
val hookedMembers = HashSet<Member>().also {
|
||||
val allConstructorsName = "$hookClass<init>"
|
||||
if (hookedAllConstructors.contains(allConstructorsName)) {
|
||||
isAlreadyHook = true
|
||||
hookClass?.allConstructors { _, constructor -> it.add(constructor) }
|
||||
return@also
|
||||
}
|
||||
hookedAllConstructors.add(allConstructorsName)
|
||||
XposedBridge.hookAllConstructors(hookClass, compatCallback(callback)).takeIf { it.isNotEmpty() }
|
||||
?.forEach { e -> it.add(e.hookedMethod) }
|
||||
}
|
||||
hookedAllConstructors.add(allConstructorsName)
|
||||
XposedBridge.hookAllConstructors(hookClass, compatCallback(callback)).takeIf { it.isNotEmpty() }
|
||||
?.forEach { e -> it.add(e.hookedMethod) }
|
||||
return Pair(hookedMembers, isAlreadyHook)
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user