mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-06 10:45:47 +08:00
Merge findMethod/findField/findClass function and hookMember function to self api
This commit is contained in:
@@ -40,7 +40,10 @@ import android.content.res.Configuration
|
|||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import com.highcapable.yukihookapi.YukiHookAPI
|
import com.highcapable.yukihookapi.YukiHookAPI
|
||||||
import com.highcapable.yukihookapi.annotation.YukiGenerateApi
|
import com.highcapable.yukihookapi.annotation.YukiGenerateApi
|
||||||
|
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||||
|
import com.highcapable.yukihookapi.hook.factory.field
|
||||||
import com.highcapable.yukihookapi.hook.factory.hasClass
|
import com.highcapable.yukihookapi.hook.factory.hasClass
|
||||||
|
import com.highcapable.yukihookapi.hook.factory.method
|
||||||
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
||||||
import com.highcapable.yukihookapi.hook.log.yLoggerW
|
import com.highcapable.yukihookapi.hook.log.yLoggerW
|
||||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||||
@@ -144,10 +147,9 @@ object YukiHookBridge {
|
|||||||
* @throws IllegalStateException 如果获取不到系统框架的 [Context]
|
* @throws IllegalStateException 如果获取不到系统框架的 [Context]
|
||||||
*/
|
*/
|
||||||
internal val systemContext
|
internal val systemContext
|
||||||
get() = runCatching {
|
get() = ActivityThreadClass.method { name = "currentActivityThread" }.ignored().get().call()?.let {
|
||||||
YukiHookHelper.findMethod(ActivityThreadClass, name = "getSystemContext")
|
ActivityThreadClass.method { name = "getSystemContext" }.ignored().get(it).invoke<Context?>()
|
||||||
.invoke(YukiHookHelper.findMethod(ActivityThreadClass, name = "currentActivityThread").invoke(null)) as? Context?
|
} ?: error("Failed to got SystemContext")
|
||||||
}.getOrNull() ?: error("Failed to got SystemContext")
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 模块是否装载了 Xposed 回调方法
|
* 模块是否装载了 Xposed 回调方法
|
||||||
@@ -175,7 +177,7 @@ object YukiHookBridge {
|
|||||||
*/
|
*/
|
||||||
internal val executorName
|
internal val executorName
|
||||||
get() = runCatching {
|
get() = runCatching {
|
||||||
(YukiHookHelper.findField(XposedBridge::class.java, name = "TAG").get(null) as? String?)
|
classOf<XposedBridge>().field { name = "TAG" }.ignored().get().string().takeIf { it.isNotBlank() }
|
||||||
?.replace(oldValue = "Bridge", newValue = "")?.replace(oldValue = "-", newValue = "")?.trim() ?: "unknown"
|
?.replace(oldValue = "Bridge", newValue = "")?.replace(oldValue = "-", newValue = "")?.trim() ?: "unknown"
|
||||||
}.getOrNull() ?: "invalid"
|
}.getOrNull() ?: "invalid"
|
||||||
|
|
||||||
@@ -200,10 +202,11 @@ object YukiHookBridge {
|
|||||||
* @param packageName 当前包名
|
* @param packageName 当前包名
|
||||||
* @return [Int]
|
* @return [Int]
|
||||||
*/
|
*/
|
||||||
internal fun findUserId(packageName: String) = runCatching {
|
internal fun findUserId(packageName: String) =
|
||||||
YukiHookHelper.findMethod(UserHandleClass, name = "getUserId", IntType)
|
UserHandleClass.method {
|
||||||
.invoke(null, systemContext.packageManager.getApplicationInfo(packageName, PackageManager.GET_ACTIVITIES).uid) as? Int ?: 0
|
name = "getUserId"
|
||||||
}.getOrNull() ?: 0
|
param(IntType)
|
||||||
|
}.ignored().get().int(systemContext.packageManager.getApplicationInfo(packageName, PackageManager.GET_ACTIVITIES).uid)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自动忽略 MIUI 系统可能出现的日志收集注入实例
|
* 自动忽略 MIUI 系统可能出现的日志收集注入实例
|
||||||
@@ -275,7 +278,7 @@ object YukiHookBridge {
|
|||||||
/** Hook [Application] 装载方法 */
|
/** Hook [Application] 装载方法 */
|
||||||
runCatching {
|
runCatching {
|
||||||
if (AppLifecycleCallback.isCallbackSetUp) {
|
if (AppLifecycleCallback.isCallbackSetUp) {
|
||||||
YukiHookHelper.hookMember(YukiHookHelper.findMethod(ApplicationClass, name = "attach", ContextClass), object : YukiMemberHook() {
|
YukiHookHelper.hook(ApplicationClass.method { name = "attach"; param(ContextClass) }, object : YukiMemberHook() {
|
||||||
override fun beforeHookedMember(wrapper: HookParamWrapper) {
|
override fun beforeHookedMember(wrapper: HookParamWrapper) {
|
||||||
(wrapper.args?.get(0) as? Context?)?.also { AppLifecycleCallback.attachBaseContextCallback?.invoke(it, false) }
|
(wrapper.args?.get(0) as? Context?)?.also { AppLifecycleCallback.attachBaseContextCallback?.invoke(it, false) }
|
||||||
}
|
}
|
||||||
@@ -284,56 +287,51 @@ object YukiHookBridge {
|
|||||||
(wrapper.args?.get(0) as? Context?)?.also { AppLifecycleCallback.attachBaseContextCallback?.invoke(it, true) }
|
(wrapper.args?.get(0) as? Context?)?.also { AppLifecycleCallback.attachBaseContextCallback?.invoke(it, true) }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
YukiHookHelper.hookMember(YukiHookHelper.findMethod(ApplicationClass, name = "onTerminate"), object : YukiMemberHook() {
|
YukiHookHelper.hook(ApplicationClass.method { name = "onTerminate" }, object : YukiMemberHook() {
|
||||||
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
||||||
(wrapper.instance as? Application?)?.also { AppLifecycleCallback.onTerminateCallback?.invoke(it) }
|
(wrapper.instance as? Application?)?.also { AppLifecycleCallback.onTerminateCallback?.invoke(it) }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
YukiHookHelper.hookMember(YukiHookHelper.findMethod(ApplicationClass, name = "onLowMemory"), object : YukiMemberHook() {
|
YukiHookHelper.hook(ApplicationClass.method { name = "onLowMemory" }, object : YukiMemberHook() {
|
||||||
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
||||||
(wrapper.instance as? Application?)?.also { AppLifecycleCallback.onLowMemoryCallback?.invoke(it) }
|
(wrapper.instance as? Application?)?.also { AppLifecycleCallback.onLowMemoryCallback?.invoke(it) }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
YukiHookHelper.hookMember(
|
YukiHookHelper.hook(ApplicationClass.method { name = "onTrimMemory"; param(IntType) }, object : YukiMemberHook() {
|
||||||
YukiHookHelper.findMethod(ApplicationClass, name = "onTrimMemory", IntType),
|
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
||||||
object : YukiMemberHook() {
|
val self = wrapper.instance as? Application? ?: return
|
||||||
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
val type = wrapper.args?.get(0) as? Int? ?: return
|
||||||
val self = wrapper.instance as? Application? ?: return
|
AppLifecycleCallback.onTrimMemoryCallback?.invoke(self, type)
|
||||||
val type = wrapper.args?.get(0) as? Int? ?: return
|
}
|
||||||
AppLifecycleCallback.onTrimMemoryCallback?.invoke(self, type)
|
})
|
||||||
}
|
YukiHookHelper.hook(ApplicationClass.method { name = "onConfigurationChanged" }, object : YukiMemberHook() {
|
||||||
})
|
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
||||||
YukiHookHelper.hookMember(YukiHookHelper.findMethod(ApplicationClass, name = "onConfigurationChanged", ConfigurationClass),
|
val self = wrapper.instance as? Application? ?: return
|
||||||
object : YukiMemberHook() {
|
val config = wrapper.args?.get(0) as? Configuration? ?: return
|
||||||
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
AppLifecycleCallback.onConfigurationChangedCallback?.invoke(self, config)
|
||||||
val self = wrapper.instance as? Application? ?: return
|
}
|
||||||
val config = wrapper.args?.get(0) as? Configuration? ?: return
|
})
|
||||||
AppLifecycleCallback.onConfigurationChangedCallback?.invoke(self, config)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if (YukiHookAPI.Configs.isEnableDataChannel || AppLifecycleCallback.isCallbackSetUp)
|
if (YukiHookAPI.Configs.isEnableDataChannel || AppLifecycleCallback.isCallbackSetUp)
|
||||||
YukiHookHelper.hookMember(
|
YukiHookHelper.hook(InstrumentationClass.method { name = "callApplicationOnCreate" }, object : YukiMemberHook() {
|
||||||
YukiHookHelper.findMethod(InstrumentationClass, name = "callApplicationOnCreate", ApplicationClass),
|
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
||||||
object : YukiMemberHook() {
|
(wrapper.args?.get(0) as? Application?)?.also {
|
||||||
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
hostApplication = it
|
||||||
(wrapper.args?.get(0) as? Application?)?.also {
|
AppLifecycleCallback.onCreateCallback?.invoke(it)
|
||||||
hostApplication = it
|
AppLifecycleCallback.onReceiversCallback.takeIf { e -> e.isNotEmpty() }?.forEach { (_, e) ->
|
||||||
AppLifecycleCallback.onCreateCallback?.invoke(it)
|
if (e.first.isNotEmpty()) it.registerReceiver(object : BroadcastReceiver() {
|
||||||
AppLifecycleCallback.onReceiversCallback.takeIf { e -> e.isNotEmpty() }?.forEach { (_, e) ->
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
if (e.first.isNotEmpty()) it.registerReceiver(object : BroadcastReceiver() {
|
if (context == null || intent == null) return
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
if (e.first.any { e -> e == intent.action }) e.second(context, intent)
|
||||||
if (context == null || intent == null) return
|
}
|
||||||
if (e.first.any { a -> a == intent.action }) e.second(context, intent)
|
}, IntentFilter().apply { e.first.forEach { e -> addAction(e) } })
|
||||||
}
|
|
||||||
}, IntentFilter().apply { e.first.forEach { a -> addAction(a) } })
|
|
||||||
}
|
|
||||||
if (isDataChannelRegister) return
|
|
||||||
isDataChannelRegister = true
|
|
||||||
runCatching { YukiHookDataChannel.instance().register(it, packageName) }
|
|
||||||
}
|
}
|
||||||
|
if (isDataChannelRegister) return
|
||||||
|
isDataChannelRegister = true
|
||||||
|
runCatching { YukiHookDataChannel.instance().register(it, packageName) }
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,12 +341,15 @@ object YukiHookBridge {
|
|||||||
*/
|
*/
|
||||||
internal fun injectModuleAppResources(context: Context) {
|
internal fun injectModuleAppResources(context: Context) {
|
||||||
if (injectedHostContextHashCodes.contains(context.hashCode())) return
|
if (injectedHostContextHashCodes.contains(context.hashCode())) return
|
||||||
|
injectedHostContextHashCodes.add(context.hashCode())
|
||||||
if (hasXposedBridge)
|
if (hasXposedBridge)
|
||||||
runCatching {
|
AssetManagerClass.method {
|
||||||
YukiHookHelper.findMethod(AssetManagerClass, name = "addAssetPath", StringType)
|
name = "addAssetPath"
|
||||||
.invoke(context.resources.assets, moduleAppFilePath)
|
param(StringType)
|
||||||
injectedHostContextHashCodes.add(context.hashCode())
|
}.ignored().onNoSuchMethod {
|
||||||
}.onFailure { yLoggerE(msg = "Failed to inject module resources in context [$context]", e = it) }
|
runCatching { injectedHostContextHashCodes.remove(context.hashCode()) }
|
||||||
|
yLoggerE(msg = "Failed to inject module resources in context [$context]", e = it)
|
||||||
|
}.get(context.resources.assets).call(moduleAppFilePath)
|
||||||
else yLoggerW(msg = "You can only inject module resources in Xposed Environment")
|
else yLoggerW(msg = "You can only inject module resources in Xposed Environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,14 +365,12 @@ object YukiHookBridge {
|
|||||||
*/
|
*/
|
||||||
internal fun hookClassLoader(loader: ClassLoader?, result: (clazz: Class<*>, resolve: Boolean) -> Unit) {
|
internal fun hookClassLoader(loader: ClassLoader?, result: (clazz: Class<*>, resolve: Boolean) -> Unit) {
|
||||||
runCatching {
|
runCatching {
|
||||||
YukiHookHelper.hookMember(
|
YukiHookHelper.hook(JavaClassLoader.method { name = "loadClass"; param(StringType, BooleanType) }, object : YukiMemberHook() {
|
||||||
YukiHookHelper.findMethod(JavaClassLoader, name = "loadClass", StringType, BooleanType),
|
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
||||||
object : YukiMemberHook() {
|
if (wrapper.instance?.javaClass?.name == loader?.javaClass?.name)
|
||||||
override fun afterHookedMember(wrapper: HookParamWrapper) {
|
(wrapper.result as? Class<*>?)?.also { result(it, wrapper.args?.get(1) as? Boolean ?: false) }
|
||||||
if (wrapper.instance?.javaClass?.name == loader?.javaClass?.name)
|
}
|
||||||
(wrapper.result as? Class<*>?)?.also { result(it, wrapper.args?.get(1) as? Boolean ?: false) }
|
})
|
||||||
}
|
|
||||||
})
|
|
||||||
}.onFailure { yLoggerW(msg = "Try to hook ClassLoader failed: $it") }
|
}.onFailure { yLoggerW(msg = "Try to hook ClassLoader failed: $it") }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,27 +383,23 @@ object YukiHookBridge {
|
|||||||
*/
|
*/
|
||||||
@YukiGenerateApi
|
@YukiGenerateApi
|
||||||
fun hookModuleAppStatus(loader: ClassLoader?, isHookResourcesStatus: Boolean = false) {
|
fun hookModuleAppStatus(loader: ClassLoader?, isHookResourcesStatus: Boolean = false) {
|
||||||
if (YukiHookAPI.Configs.isEnableHookModuleStatus)
|
if (YukiHookAPI.Configs.isEnableHookModuleStatus.not()) return
|
||||||
YukiHookHelper.findClass(loader, YukiHookModuleStatus::class.java).also { statusClass ->
|
classOf<YukiHookModuleStatus>(loader).apply {
|
||||||
if (isHookResourcesStatus.not()) {
|
if (isHookResourcesStatus.not()) {
|
||||||
YukiHookHelper.hookMember(YukiHookHelper.findMethod(statusClass, YukiHookModuleStatus.IS_ACTIVE_METHOD_NAME),
|
YukiHookHelper.hook(method { name = YukiHookModuleStatus.IS_ACTIVE_METHOD_NAME }, object : YukiMemberReplacement() {
|
||||||
object : YukiMemberReplacement() {
|
override fun replaceHookedMember(wrapper: HookParamWrapper) = true
|
||||||
override fun replaceHookedMember(wrapper: HookParamWrapper) = true
|
})
|
||||||
})
|
YukiHookHelper.hook(method { name = YukiHookModuleStatus.GET_XPOSED_TAG_METHOD_NAME }, object : YukiMemberReplacement() {
|
||||||
YukiHookHelper.hookMember(YukiHookHelper.findMethod(statusClass, YukiHookModuleStatus.GET_XPOSED_TAG_METHOD_NAME),
|
override fun replaceHookedMember(wrapper: HookParamWrapper) = executorName
|
||||||
object : YukiMemberReplacement() {
|
})
|
||||||
override fun replaceHookedMember(wrapper: HookParamWrapper) = executorName
|
YukiHookHelper.hook(method { name = YukiHookModuleStatus.GET_XPOSED_VERSION_METHOD_NAME }, object : YukiMemberReplacement() {
|
||||||
})
|
override fun replaceHookedMember(wrapper: HookParamWrapper) = executorVersion
|
||||||
YukiHookHelper.hookMember(YukiHookHelper.findMethod(statusClass, YukiHookModuleStatus.GET_XPOSED_VERSION_METHOD_NAME),
|
})
|
||||||
object : YukiMemberReplacement() {
|
} else
|
||||||
override fun replaceHookedMember(wrapper: HookParamWrapper) = executorVersion
|
YukiHookHelper.hook(method { name = YukiHookModuleStatus.HAS_RESOURCES_HOOK_METHOD_NAME }, object : YukiMemberReplacement() {
|
||||||
})
|
override fun replaceHookedMember(wrapper: HookParamWrapper) = true
|
||||||
} else
|
})
|
||||||
YukiHookHelper.hookMember(YukiHookHelper.findMethod(statusClass, YukiHookModuleStatus.HAS_RESOURCES_HOOK_METHOD_NAME),
|
}
|
||||||
object : YukiMemberReplacement() {
|
|
||||||
override fun replaceHookedMember(wrapper: HookParamWrapper) = true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -25,15 +25,19 @@
|
|||||||
*
|
*
|
||||||
* This file is Created by fankes on 2022/7/28.
|
* This file is Created by fankes on 2022/7/28.
|
||||||
*/
|
*/
|
||||||
|
@file:Suppress("NewApi")
|
||||||
|
|
||||||
package com.highcapable.yukihookapi.hook.xposed.bridge.factory
|
package com.highcapable.yukihookapi.hook.xposed.bridge.factory
|
||||||
|
|
||||||
|
import com.highcapable.yukihookapi.hook.core.finder.ConstructorFinder
|
||||||
|
import com.highcapable.yukihookapi.hook.core.finder.MethodFinder
|
||||||
|
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||||
|
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
||||||
import com.highcapable.yukihookapi.hook.param.wrapper.HookParamWrapper
|
import com.highcapable.yukihookapi.hook.param.wrapper.HookParamWrapper
|
||||||
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
|
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge
|
||||||
import de.robv.android.xposed.XC_MethodHook
|
import de.robv.android.xposed.XC_MethodHook
|
||||||
import de.robv.android.xposed.XposedBridge
|
import de.robv.android.xposed.XposedBridge
|
||||||
import java.lang.reflect.Field
|
|
||||||
import java.lang.reflect.Member
|
import java.lang.reflect.Member
|
||||||
import java.lang.reflect.Method
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook 回调优先级配置类
|
* Hook 回调优先级配置类
|
||||||
@@ -67,33 +71,20 @@ internal object YukiHookedMembers {
|
|||||||
internal object YukiHookHelper {
|
internal object YukiHookHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查找 [Class]
|
* Hook [BaseFinder.BaseResult]
|
||||||
* @param loader 当前 [ClassLoader]
|
* @param traction 直接调用 [BaseFinder.BaseResult]
|
||||||
* @param baseClass 当前类
|
* @param callback 回调
|
||||||
* @return [Field]
|
* @return [Pair] - ([YukiMemberHook.Unhook] or null,[Boolean] 是否已经 Hook)
|
||||||
* @throws IllegalStateException 如果 [ClassLoader] 为空
|
|
||||||
*/
|
*/
|
||||||
internal fun findClass(loader: ClassLoader?, baseClass: Class<*>) = loader?.loadClass(baseClass.name) ?: error("ClassLoader is null")
|
internal fun hook(traction: BaseFinder.BaseResult, callback: YukiHookCallback) = runCatching {
|
||||||
|
hookMember(
|
||||||
/**
|
when (traction) {
|
||||||
* 查找 [Field]
|
is MethodFinder.Result -> traction.ignored().give()
|
||||||
* @param baseClass 所在类
|
is ConstructorFinder.Result -> traction.ignored().give()
|
||||||
* @param name 变量名称
|
else -> error("Unexpected BaseFinder result interface type")
|
||||||
* @return [Field]
|
}, callback
|
||||||
* @throws NoSuchFieldError 如果找不到变量
|
)
|
||||||
*/
|
}.onFailure { yLoggerE(msg = "Hooking Process exception occurred", e = it) }.getOrNull() ?: Pair(null, false)
|
||||||
internal fun findField(baseClass: Class<*>, name: String) = baseClass.getDeclaredField(name).apply { isAccessible = true }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查找 [Method]
|
|
||||||
* @param baseClass 所在类
|
|
||||||
* @param name 方法名称
|
|
||||||
* @param paramTypes 方法参数
|
|
||||||
* @return [Method]
|
|
||||||
* @throws NoSuchMethodError 如果找不到方法
|
|
||||||
*/
|
|
||||||
internal fun findMethod(baseClass: Class<*>, name: String, vararg paramTypes: Class<*>) =
|
|
||||||
baseClass.getDeclaredMethod(name, *paramTypes).apply { isAccessible = true }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook [Member]
|
* Hook [Member]
|
||||||
@@ -103,18 +94,21 @@ internal object YukiHookHelper {
|
|||||||
* @param callback 回调
|
* @param callback 回调
|
||||||
* @return [Pair] - ([YukiMemberHook.Unhook] or null,[Boolean] 是否已经 Hook)
|
* @return [Pair] - ([YukiMemberHook.Unhook] or null,[Boolean] 是否已经 Hook)
|
||||||
*/
|
*/
|
||||||
internal fun hookMember(member: Member, callback: YukiHookCallback): Pair<YukiMemberHook.Unhook?, Boolean> {
|
internal fun hookMember(member: Member?, callback: YukiHookCallback): Pair<YukiMemberHook.Unhook?, Boolean> {
|
||||||
runCatching {
|
runCatching {
|
||||||
YukiHookedMembers.hookedMembers.takeIf { it.isNotEmpty() }?.forEach {
|
YukiHookedMembers.hookedMembers.takeIf { it.isNotEmpty() }?.forEach {
|
||||||
if (it.member.toString() == member.toString()) return@runCatching it
|
if (it.member.toString() == member?.toString()) return@runCatching it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return if (YukiHookBridge.hasXposedBridge)
|
return when {
|
||||||
YukiMemberHook.Unhook.wrapper(XposedBridge.hookMethod(member, callback.compat())).let {
|
member == null -> Pair(null, false)
|
||||||
YukiHookedMembers.hookedMembers.add(it)
|
YukiHookBridge.hasXposedBridge ->
|
||||||
Pair(it, false)
|
YukiMemberHook.Unhook.wrapper(XposedBridge.hookMethod(member, callback.compat())).let {
|
||||||
}
|
YukiHookedMembers.hookedMembers.add(it)
|
||||||
else Pair(null, false)
|
Pair(it, false)
|
||||||
|
}
|
||||||
|
else -> Pair(null, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -125,9 +119,9 @@ internal object YukiHookHelper {
|
|||||||
* @param args 参数实例
|
* @param args 参数实例
|
||||||
* @return [Any] or null
|
* @return [Any] or null
|
||||||
*/
|
*/
|
||||||
internal fun invokeOriginalMember(member: Member, instance: Any?, vararg args: Any?) =
|
internal fun invokeOriginalMember(member: Member?, instance: Any?, vararg args: Any?) =
|
||||||
if (YukiHookBridge.hasXposedBridge && YukiHookedMembers.hookedMembers.any { it.member.toString() == member.toString() })
|
if (YukiHookBridge.hasXposedBridge && YukiHookedMembers.hookedMembers.any { it.member.toString() == member.toString() })
|
||||||
XposedBridge.invokeOriginalMethod(member, instance, args)
|
member?.let { XposedBridge.invokeOriginalMethod(it, instance, args) }
|
||||||
else null
|
else null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user