mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
Fix LSPosed when opened "只有模块classloader可以使用Xposed API" not founded the API's bug And add more feature function
This commit is contained in:
@@ -37,7 +37,7 @@ import com.google.devtools.ksp.symbol.KSClassDeclaration
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* 这是 YukiHookAPI 的自动生成处理类 - 核心基于 KSP
|
||||
* 这是 [YukiHookAPI] 的自动生成处理类 - 核心基于 KSP
|
||||
*
|
||||
* 可以帮你快速生成 Xposed 入口类和包名
|
||||
*
|
||||
|
@@ -36,22 +36,21 @@ import com.highcapable.yukihookapi.YukiHookAPI.encase
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseField
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.hasClass
|
||||
import com.highcapable.yukihookapi.hook.factory.processName
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.log.*
|
||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||
import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||
|
||||
/**
|
||||
* YukiHookAPI 的装载调用类
|
||||
* [YukiHookAPI] 的装载调用类
|
||||
*
|
||||
* 可以实现作为模块装载和自定义 Hook 装载两种方式
|
||||
*
|
||||
* 模块装载方式已经自动对接 Xposed API - 可直接调用 [encase] 完成操作
|
||||
*
|
||||
* 你可以调用 [configs] 对 YukiHookAPI 进行配置
|
||||
* 你可以调用 [configs] 对 [YukiHookAPI] 进行配置
|
||||
*/
|
||||
object YukiHookAPI {
|
||||
|
||||
@@ -97,10 +96,21 @@ object YukiHookAPI {
|
||||
* 请过滤 [debugTag] 即可找到每条日志
|
||||
*/
|
||||
var isDebug = true
|
||||
|
||||
/**
|
||||
* 是否启用调试日志的输出功能
|
||||
*
|
||||
* - ❗关闭后将会停用 [YukiHookAPI] 对全部日志的输出
|
||||
*
|
||||
* 但是不影响当你手动调用下面这些方法输出日志
|
||||
*
|
||||
* [loggerD]、[loggerI]、[loggerW]、[loggerE]
|
||||
*/
|
||||
var isAllowPrintingLogs = true
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置 YukiHookAPI 相关参数
|
||||
* 配置 [YukiHookAPI] 相关参数
|
||||
*
|
||||
* 详情请参考 [configs 方法](https://github.com/fankes/YukiHookAPI/wiki/API-%E5%9F%BA%E6%9C%AC%E9%85%8D%E7%BD%AE#configs-%E6%96%B9%E6%B3%95)
|
||||
* @param initiate 方法体
|
||||
@@ -207,7 +217,7 @@ object YukiHookAPI {
|
||||
}
|
||||
|
||||
/** 输出找不到 [XposedBridge] 的错误日志 */
|
||||
private fun printNoXposedBridge() = loggerE(msg = "Could not found XposedBridge in current space! Aborted")
|
||||
private fun printNoXposedBridge() = yLoggerE(msg = "Could not found XposedBridge in current space! Aborted")
|
||||
|
||||
/**
|
||||
* 通过 baseContext 创建 Hook 入口类
|
||||
@@ -220,5 +230,9 @@ object YukiHookAPI {
|
||||
* 是否存在 [XposedBridge]
|
||||
* @return [Boolean]
|
||||
*/
|
||||
internal val hasXposedBridge get() = ("de.robv.android.xposed.XposedBridge").hasClass
|
||||
internal val hasXposedBridge
|
||||
get() = runCatching {
|
||||
if (Configs.isDebug) yLoggerI(msg = "YukiHookAPI is running on Xposed API ${XposedBridge.getXposedVersion()}")
|
||||
true
|
||||
}.getOrNull() ?: false
|
||||
}
|
@@ -29,10 +29,11 @@
|
||||
|
||||
package com.highcapable.yukihookapi.annotation.xposed
|
||||
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
||||
|
||||
/**
|
||||
* 标识 YukiHookAPI 注入 Xposed 入口的类注释
|
||||
* 标识 [YukiHookAPI] 注入 Xposed 入口的类注释
|
||||
*
|
||||
* - 你的项目 source 目录默认为 "src/main/" 可在 [sourcePath] 中进行自定义 - 自动处理程序将只检查 ..app/[sourcePath]/java.. 中间部分
|
||||
*
|
||||
|
@@ -36,8 +36,8 @@ import com.highcapable.yukihookapi.hook.bean.HookClass
|
||||
import com.highcapable.yukihookapi.hook.core.finder.ConstructorFinder
|
||||
import com.highcapable.yukihookapi.hook.core.finder.FieldFinder
|
||||
import com.highcapable.yukihookapi.hook.core.finder.MethodFinder
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.log.loggerI
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerI
|
||||
import com.highcapable.yukihookapi.hook.param.HookParam
|
||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||
import com.highcapable.yukihookapi.hook.param.wrapper.HookParamWrapper
|
||||
@@ -48,7 +48,7 @@ import java.lang.reflect.Field
|
||||
import java.lang.reflect.Member
|
||||
|
||||
/**
|
||||
* YukiHookAPI 核心 Hook 实现类
|
||||
* [YukiHookAPI] 核心 Hook 实现类
|
||||
*
|
||||
* 这是一个 API 对接类 - 实现原生对接 [XposedBridge]
|
||||
* @param packageParam 需要传入 [PackageParam] 实现方法调用
|
||||
@@ -103,7 +103,7 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
else Thread {
|
||||
SystemClock.sleep(10)
|
||||
if (onHookClassNotFoundFailureCallback == null)
|
||||
loggerE(msg = "HookClass [${hookClass.name}] not found", e = hookClass.throwable)
|
||||
yLoggerE(msg = "HookClass [${hookClass.name}] not found", e = hookClass.throwable)
|
||||
else onHookClassNotFoundFailureCallback?.invoke(hookClass.throwable ?: Throwable("[${hookClass.name}] not found"))
|
||||
}.start()
|
||||
return Result()
|
||||
@@ -427,7 +427,7 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
onHookingFailureCallback?.invoke(it)
|
||||
onAllFailureCallback?.invoke(it)
|
||||
if (isNotIgnoredHookingFailure)
|
||||
loggerE(
|
||||
yLoggerE(
|
||||
msg = if (isHookMemberSetup)
|
||||
"Hooked Member with a finding error by $hookClass [$tag]"
|
||||
else "Hooked Member cannot be non-null by $hookClass [$tag]",
|
||||
@@ -448,7 +448,7 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
}
|
||||
}.onFailure {
|
||||
onAllFailureCallback?.invoke(it)
|
||||
if (isNotIgnoredHookingFailure) loggerE(msg = "Hooked All Members with an error in Class [$hookClass] [$tag]")
|
||||
if (isNotIgnoredHookingFailure) yLoggerE(msg = "Hooked All Members with an error in Class [$hookClass] [$tag]")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -457,7 +457,7 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
* @param msg 调试日志内容
|
||||
*/
|
||||
private fun onHookLogMsg(msg: String) {
|
||||
if (YukiHookAPI.Configs.isDebug) loggerI(msg = msg)
|
||||
if (YukiHookAPI.Configs.isDebug) yLoggerI(msg = msg)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,7 +465,7 @@ class YukiHookCreater(private val packageParam: PackageParam, private val hookCl
|
||||
* @param throwable 异常信息
|
||||
*/
|
||||
private fun onHookFailureMsg(throwable: Throwable) =
|
||||
loggerE(msg = "Try to hook ${hookClass.instance ?: hookClass.name}[$member] got an Exception [$tag]", e = throwable)
|
||||
yLoggerE(msg = "Try to hook ${hookClass.instance ?: hookClass.name}[$member] got an Exception [$tag]", e = throwable)
|
||||
|
||||
/**
|
||||
* 判断是否没有设置 Hook 过程中的任何异常拦截
|
||||
|
@@ -32,7 +32,7 @@ package com.highcapable.yukihookapi.hook.core.finder
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerW
|
||||
import com.highcapable.yukihookapi.hook.utils.ReflectionUtils
|
||||
import com.highcapable.yukihookapi.hook.utils.runBlocking
|
||||
import java.lang.reflect.Constructor
|
||||
@@ -177,7 +177,7 @@ class ConstructorFinder(
|
||||
)
|
||||
remedyPlans.clear()
|
||||
}
|
||||
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookTag}]")
|
||||
} else yLoggerW(msg = "RemedyPlan is empty,forgot it? [${hookTag}]")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -33,7 +33,7 @@ import android.os.SystemClock
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
||||
import com.highcapable.yukihookapi.hook.utils.ReflectionUtils
|
||||
import com.highcapable.yukihookapi.hook.utils.runBlocking
|
||||
import java.lang.reflect.Field
|
||||
@@ -75,7 +75,7 @@ class FieldFinder(
|
||||
@DoNotUseMethod
|
||||
override fun build(isBind: Boolean) = when {
|
||||
name.isBlank() -> {
|
||||
loggerE(msg = "Field name cannot be empty in Class [$classSet] [${hookTag}]")
|
||||
yLoggerE(msg = "Field name cannot be empty in Class [$classSet] [${hookTag}]")
|
||||
Result(isNoSuch = true)
|
||||
}
|
||||
else -> try {
|
||||
@@ -91,7 +91,7 @@ class FieldFinder(
|
||||
} catch (e: Throwable) {
|
||||
Thread {
|
||||
SystemClock.sleep(10)
|
||||
if (isNotIgnoredHookingFailure) loggerE(msg = "NoSuchField happend in [$classSet] [${hookTag}]", e = e)
|
||||
if (isNotIgnoredHookingFailure) yLoggerE(msg = "NoSuchField happend in [$classSet] [${hookTag}]", e = e)
|
||||
}.start()
|
||||
Result(isNoSuch = true, e)
|
||||
}
|
||||
|
@@ -32,8 +32,8 @@ package com.highcapable.yukihookapi.hook.core.finder
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.core.finder.base.BaseFinder
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.log.loggerW
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerW
|
||||
import com.highcapable.yukihookapi.hook.utils.ReflectionUtils
|
||||
import com.highcapable.yukihookapi.hook.utils.runBlocking
|
||||
import java.lang.reflect.Method
|
||||
@@ -117,7 +117,7 @@ class MethodFinder(
|
||||
@DoNotUseMethod
|
||||
override fun build(isBind: Boolean) = when {
|
||||
name.isBlank() -> {
|
||||
loggerE(msg = "Method name cannot be empty in Class [$classSet] [${hookTag}]")
|
||||
yLoggerE(msg = "Method name cannot be empty in Class [$classSet] [${hookTag}]")
|
||||
Result(isNoSuch = true)
|
||||
}
|
||||
else -> try {
|
||||
@@ -201,7 +201,7 @@ class MethodFinder(
|
||||
)
|
||||
remedyPlans.clear()
|
||||
}
|
||||
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookTag}]")
|
||||
} else yLoggerW(msg = "RemedyPlan is empty,forgot it? [${hookTag}]")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -31,8 +31,8 @@ import android.os.SystemClock
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||
import com.highcapable.yukihookapi.hook.core.YukiHookCreater
|
||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||
import com.highcapable.yukihookapi.hook.log.loggerI
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerE
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerI
|
||||
import java.lang.reflect.Member
|
||||
|
||||
/**
|
||||
@@ -75,7 +75,7 @@ abstract class BaseFinder(
|
||||
* @param isAlwaysPrint 忽略条件每次都打印错误
|
||||
*/
|
||||
internal fun onFailureMsg(msg: String = "", throwable: Throwable? = null, isAlwaysPrint: Boolean = false) {
|
||||
fun print() = loggerE(msg = "NoSuch$tag happend in [$classSet] $msg [${hookTag}]", e = throwable)
|
||||
fun print() = yLoggerE(msg = "NoSuch$tag happend in [$classSet] $msg [${hookTag}]", e = throwable)
|
||||
if (isAlwaysPrint) print()
|
||||
else Thread {
|
||||
SystemClock.sleep(10)
|
||||
@@ -88,7 +88,7 @@ abstract class BaseFinder(
|
||||
* @param msg 调试日志内容
|
||||
*/
|
||||
internal fun onHookLogMsg(msg: String) {
|
||||
if (YukiHookAPI.Configs.isDebug) loggerI(msg = msg)
|
||||
if (YukiHookAPI.Configs.isDebug) yLoggerI(msg = msg)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -34,7 +34,7 @@ import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
||||
|
||||
/**
|
||||
* YukiHookAPI 的子类 Hooker 实现
|
||||
* [YukiHookAPI] 的子类 Hooker 实现
|
||||
*
|
||||
* 也许你的 Module 中存在多个 Hooker - 继承此类可以方便帮你管理每个 Hooker
|
||||
*
|
||||
|
@@ -78,6 +78,22 @@ fun String.hasClass(loader: ClassLoader?) = try {
|
||||
false
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找变量是否存在
|
||||
* @param name 名称
|
||||
* @param type 类型 - 不填默认模糊
|
||||
* @return [Boolean] 是否存在
|
||||
*/
|
||||
fun Class<*>.hasField(name: String, type: Class<*>? = null): Boolean =
|
||||
try {
|
||||
if (type != null)
|
||||
ReflectionUtils.findFieldIfExists(this, type.name, name)
|
||||
else getDeclaredField(name).apply { isAccessible = true }
|
||||
true
|
||||
} catch (_: Throwable) {
|
||||
false
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找方法是否存在
|
||||
* @param name 名称
|
||||
|
@@ -33,6 +33,47 @@ import android.util.Log
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import de.robv.android.xposed.XposedBridge
|
||||
|
||||
/**
|
||||
* [YukiHookAPI] 向控制台和 [XposedBridge] 打印日志 - D
|
||||
*
|
||||
* - ❗此方法为私有功能性 API - 你不应该手动调用此方法
|
||||
* @param msg 日志打印的内容
|
||||
*/
|
||||
internal fun yLoggerD(msg: String) {
|
||||
if (YukiHookAPI.Configs.isAllowPrintingLogs) loggerD(msg = msg)
|
||||
}
|
||||
|
||||
/**
|
||||
* [YukiHookAPI] 向控制台和 [XposedBridge] 打印日志 - I
|
||||
*
|
||||
* - ❗此方法为私有功能性 API - 你不应该手动调用此方法
|
||||
* @param msg 日志打印的内容
|
||||
*/
|
||||
internal fun yLoggerI(msg: String) {
|
||||
if (YukiHookAPI.Configs.isAllowPrintingLogs) loggerI(msg = msg)
|
||||
}
|
||||
|
||||
/**
|
||||
* [YukiHookAPI] 向控制台和 [XposedBridge] 打印日志 - W
|
||||
*
|
||||
* - ❗此方法为私有功能性 API - 你不应该手动调用此方法
|
||||
* @param msg 日志打印的内容
|
||||
*/
|
||||
internal fun yLoggerW(msg: String) {
|
||||
if (YukiHookAPI.Configs.isAllowPrintingLogs) loggerW(msg = msg)
|
||||
}
|
||||
|
||||
/**
|
||||
* [YukiHookAPI] 向控制台和 [XposedBridge] 打印日志 - E
|
||||
*
|
||||
* - ❗此方法为私有功能性 API - 你不应该手动调用此方法
|
||||
* @param msg 日志打印的内容
|
||||
* @param e 可填入异常堆栈信息 - 将自动完整打印到控制台
|
||||
*/
|
||||
internal fun yLoggerE(msg: String, e: Throwable? = null) {
|
||||
if (YukiHookAPI.Configs.isAllowPrintingLogs) loggerE(msg = msg, e = e)
|
||||
}
|
||||
|
||||
/**
|
||||
* 向控制台和 [XposedBridge] 打印日志 - D
|
||||
*
|
||||
|
@@ -28,7 +28,7 @@
|
||||
package com.highcapable.yukihookapi.hook.xposed
|
||||
|
||||
import androidx.annotation.Keep
|
||||
import com.highcapable.yukihookapi.hook.log.loggerI
|
||||
import com.highcapable.yukihookapi.hook.log.yLoggerI
|
||||
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus.isActive
|
||||
|
||||
/**
|
||||
@@ -47,7 +47,7 @@ object YukiHookModuleStatus {
|
||||
*/
|
||||
@Keep
|
||||
fun isActive(): Boolean {
|
||||
loggerI(msg = "This Module is not actived")
|
||||
yLoggerI(msg = "This Module is not actived")
|
||||
return false
|
||||
}
|
||||
}
|
@@ -49,7 +49,7 @@ import java.io.File
|
||||
*
|
||||
* - 使用 LSPosed 环境请在 AndroidManifests.xml 中将 "xposedminversion" 最低设置为 93
|
||||
*
|
||||
* - 未使用 LSPosed 环境请将你的模块 API 降至 26 以下 - YukiHookAPI 将会尝试使用 [makeWorldReadable] 但仍有可能不成功
|
||||
* - 未使用 LSPosed 环境请将你的模块 API 降至 26 以下 - [YukiHookAPI] 将会尝试使用 [makeWorldReadable] 但仍有可能不成功
|
||||
*
|
||||
* - ❗当你在模块中存取数据的时候 [context] 必须不能是空的
|
||||
*
|
||||
|
@@ -34,7 +34,7 @@ import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
||||
import com.highcapable.yukihookapi.hook.factory.encase
|
||||
|
||||
/**
|
||||
* YukiHookAPI 的 Xposed 装载 API 调用接口
|
||||
* [YukiHookAPI] 的 Xposed 装载 API 调用接口
|
||||
*
|
||||
* - ❗请在此类上添加注释 [InjectYukiHookWithXposed] 标记模块 Hook 入口
|
||||
*
|
||||
|
Reference in New Issue
Block a user