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