This commit is contained in:
2022-02-07 02:12:29 +08:00
parent 108c792ab8
commit 73108a44a6
16 changed files with 144 additions and 89 deletions

View File

@@ -32,11 +32,11 @@ package com.highcapable.yukihookapi
import android.content.pm.ApplicationInfo
import androidx.annotation.Keep
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.param.CustomParam
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
import de.robv.android.xposed.callbacks.XC_LoadPackage
/**
@@ -49,37 +49,52 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage
@Keep
object YukiHookAPI {
/**
* 这是一个调试日志的全局标识
*
* 默认文案为 YukiHookAPI
*
* 你可以修改为你自己的文案
*/
var debugTag = "YukiHookAPI"
/**
* 是否开启调试模式 - 默认启用
*
* 启用后将交由日志输出管理器打印详细 Hook 日志到控制台
*
* 关闭后将只输出 Error 级别的日志
*
* 请过滤 [debugTag] 即可找到每条日志
*/
var isDebug = true
/**
* Xposed Hook API 绑定的模块包名 - 未写将自动生成
* - 你不应该设置此变量的名称 - 请使用 [encase] 装载模块包名
*/
@DoNotUseField
@Keep
var modulePackageName = ""
/** Xposed Hook API 方法体回调 */
private var packageParamCallback: (PackageParam.() -> Unit)? = null
/**
* 配置 YukiHook
*/
object Configs {
/**
* 这是一个调试日志的全局标识
*
* 默认文案为 YukiHookAPI
*
* 你可以修改为你自己的文案
*/
var debugTag = "YukiHookAPI"
/**
* 是否开启调试模式 - 默认启用
*
* 启用后将交由日志输出管理器打印详细 Hook 日志到控制台
*
* 关闭后将只输出 Error 级别的日志
*
* 请过滤 [debugTag] 即可找到每条日志
*/
var isDebug = true
/**
* Xposed Hook API 绑定的模块包名
*
* - 用于 [YukiHookModuleStatus] 判断模块激活状态
*
* 未写将自动生成
*/
@Keep
var modulePackageName = ""
}
/**
* 配置 YukiHook 相关参数
* @param initiate 方法体
* @return [Configs]
*/
fun configs(initiate: Configs.() -> Unit) = Configs.apply(initiate)
/**
* 装载 Xposed API 回调
*
@@ -92,22 +107,18 @@ object YukiHookAPI {
/**
* 作为模块装载调用入口方法 - Xposed API
* @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成
* @param initiate Hook 方法体
*/
fun encase(moduleName: String = "", initiate: PackageParam.() -> Unit) {
modulePackageName = moduleName
fun encase(initiate: PackageParam.() -> Unit) {
packageParamCallback = initiate
}
/**
* 作为模块装载调用入口方法 - Xposed API
* @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成
* @param hooker Hook 子类数组 - 必填不能为空
* @throws IllegalStateException 如果 [hooker] 是空的
*/
fun encase(moduleName: String = "", vararg hooker: YukiBaseHooker) {
modulePackageName = moduleName
fun encase(vararg hooker: YukiBaseHooker) {
packageParamCallback = {
if (hooker.isNotEmpty())
hooker.forEach { it.assignInstance(packageParam = this) }

View File

@@ -48,7 +48,7 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
*
* - 你的模块包名将被这样识别:|com.example.module|.hook...
*
* - 若你不喜欢这样创建类 - 没问题 - 请在 [YukiHookAPI.encase] 中自行指定模块包名即可 - 但不按照规则定义包名你将会收到编译警告
* - 若你不喜欢这样创建类 - 没问题 - 请在 [YukiHookAPI.Configs.modulePackageName] 填写模块包名即可 - 但不按照规则定义包名你将会收到编译警告
*
* 例子YukiHookAPI.encase(moduleName = "com.example.module", ...)
*

View File

@@ -133,6 +133,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
*
* 你只能使用一次 [method] 或 [constructor] 方法 - 否则结果会被替换
* @param initiate 方法体
* @return [ConstructorFinder.Result]
*/
fun constructor(initiate: ConstructorFinder.() -> Unit): ConstructorFinder.Result {
isHookMemberSetup = true
@@ -327,11 +328,11 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
}
/**
* Hook 过程中开启了 [YukiHookAPI.isDebug] 输出调试信息
* Hook 过程中开启了 [YukiHookAPI.Configs.isDebug] 输出调试信息
* @param msg 调试日志内容
*/
internal fun onHookLogMsg(msg: String) {
if (YukiHookAPI.isDebug) loggerI(msg = msg)
if (YukiHookAPI.Configs.isDebug) loggerI(msg = msg)
}
/**
@@ -368,7 +369,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
}
/**
* 忽略 Hook 进行过程中发生错误
* 忽略 Hook 进行过程中发生错误
* @return [Result] 可继续向下监听
*/
fun ignoredConductFailure() = onConductFailure { _, _ -> }

View File

@@ -104,7 +104,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
inner class RemedyPlan {
/** 失败尝试次数数组 */
private val remedyPlan = HashSet<ConstructorFinder>()
private val remedyPlans = HashSet<ConstructorFinder>()
/**
* 创建需要重新查找的 [Constructor]
@@ -115,7 +115,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
* @param initiate 方法体
*/
fun constructor(initiate: ConstructorFinder.() -> Unit) =
remedyPlan.add(ConstructorFinder(hookInstance, hookClass).apply(initiate))
remedyPlans.add(ConstructorFinder(hookInstance, hookClass).apply(initiate))
/**
* 开始重查找
@@ -123,10 +123,10 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
*/
@DoNotUseMethod
internal fun build() {
if (remedyPlan.isNotEmpty()) run {
if (remedyPlans.isNotEmpty()) run {
var isFindSuccess = false
var lastError: Throwable? = null
remedyPlan.forEachIndexed { p, it ->
remedyPlans.forEachIndexed { p, it ->
runCatching {
runBlocking {
hookInstance.member = it.result
@@ -143,10 +143,10 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
}
if (!isFindSuccess) {
onFailureMsg(
msg = "trying ${remedyPlan.size} times and all failure by RemedyPlan",
msg = "trying ${remedyPlans.size} times and all failure by RemedyPlan",
throwable = lastError
)
remedyPlan.clear()
remedyPlans.clear()
}
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookInstance.tag}]")
}

View File

@@ -37,9 +37,9 @@ import com.highcapable.yukihookapi.hook.utils.runBlocking
import java.lang.reflect.Field
/**
* Field 查找结果实现
* Field 查找类
*
* 可在这里处理找到的 [fieldInstance]
* 可通过执行类型查找指定变量
* @param hookInstance 当前 Hook 实例
* @param hookClass 当前被 Hook 的 [Class]
*/

View File

@@ -111,7 +111,7 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
inner class RemedyPlan {
/** 失败尝试次数数组 */
private val remedyPlan = HashSet<MethodFinder>()
private val remedyPlans = HashSet<MethodFinder>()
/**
* 创建需要重新查找的 [Method]
@@ -121,7 +121,8 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
* 若最后依然失败 - 将停止查找并输出错误日志
* @param initiate 方法体
*/
fun method(initiate: MethodFinder.() -> Unit) = remedyPlan.add(MethodFinder(hookInstance, hookClass).apply(initiate))
fun method(initiate: MethodFinder.() -> Unit) =
remedyPlans.add(MethodFinder(hookInstance, hookClass).apply(initiate))
/**
* 开始重查找
@@ -129,10 +130,10 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
*/
@DoNotUseMethod
internal fun build() {
if (remedyPlan.isNotEmpty()) run {
if (remedyPlans.isNotEmpty()) run {
var isFindSuccess = false
var lastError: Throwable? = null
remedyPlan.forEachIndexed { p, it ->
remedyPlans.forEachIndexed { p, it ->
runCatching {
runBlocking {
hookInstance.member = it.result
@@ -149,10 +150,10 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
}
if (!isFindSuccess) {
onFailureMsg(
msg = "trying ${remedyPlan.size} times and all failure by RemedyPlan",
msg = "trying ${remedyPlans.size} times and all failure by RemedyPlan",
throwable = lastError
)
remedyPlan.clear()
remedyPlans.clear()
}
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookInstance.tag}]")
}

View File

@@ -40,13 +40,11 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
*
* 你可以继续继承此类进行自定义 Hooker 相关参数
*
* 你可以在 [YukiHookXposedInitProxy] 的 [YukiHookXposedInitProxy.onHook] 中实现如下用法
* 你可以在 [YukiHookXposedInitProxy] 的 [YukiHookXposedInitProxy.onHook] 中实现如下用法
*
* 第一种方式:调用 [YukiHookAPI.encase] encase(MainHooker(), SecondHooker(), ThirdHooker() ...)
* 1.调用 [YukiHookAPI.encase] encase(MainHooker(), SecondHooker(), ThirdHooker() ...)
*
* 第二种方式:调用 [YukiHookAPI.encase] encase(moduleName = "模块包名", MainHooker(), SecondHooker(), ThirdHooker() ...)
*
* 调用 [PackageParam.loadHooker] loadHooker(hooker = CustomHooker())
* 2.调用 [PackageParam.loadHooker] loadHooker(hooker = CustomHooker())
*
* 更多请参考 [InjectYukiHookWithXposed] 中的注释内容
*

View File

@@ -40,11 +40,9 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
/**
* 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI]
* @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成
* @param initiate Hook 方法体
*/
fun YukiHookXposedInitProxy.encase(moduleName: String = "", initiate: PackageParam.() -> Unit) =
YukiHookAPI.encase(moduleName, initiate)
fun YukiHookXposedInitProxy.encase(initiate: PackageParam.() -> Unit) = YukiHookAPI.encase(initiate)
/**
* 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI]
@@ -53,15 +51,6 @@ fun YukiHookXposedInitProxy.encase(moduleName: String = "", initiate: PackagePar
*/
fun YukiHookXposedInitProxy.encase(vararg hooker: YukiBaseHooker) = YukiHookAPI.encase(hooker = hooker)
/**
* 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI]
* @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成
* @param hooker Hook 子类数组 - 必填不能为空
* @throws IllegalStateException 如果 [hooker] 是空的
*/
fun YukiHookXposedInitProxy.encase(moduleName: String, vararg hooker: YukiBaseHooker) =
YukiHookAPI.encase(moduleName, *hooker)
/**
* 判断模块是否在太极、无极中激活
* @return [Boolean] 是否激活

View File

@@ -37,10 +37,10 @@ import de.robv.android.xposed.XposedBridge
* 向控制台和 [XposedBridge] 打印日志 - D
*
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.debugTag]
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag]
* @param msg 日志打印的内容
*/
fun loggerD(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
fun loggerD(tag: String = YukiHookAPI.Configs.debugTag, msg: String) = runCatching {
Log.d(tag, msg)
XposedBridge.log("[$tag][D]--> $msg")
}
@@ -49,10 +49,10 @@ fun loggerD(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
* 向控制台和 [XposedBridge] 打印日志 - I
*
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.debugTag]
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag]
* @param msg 日志打印的内容
*/
fun loggerI(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
fun loggerI(tag: String = YukiHookAPI.Configs.debugTag, msg: String) = runCatching {
Log.i(tag, msg)
XposedBridge.log("[$tag][I]--> $msg")
}
@@ -61,10 +61,10 @@ fun loggerI(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
* 向控制台和 [XposedBridge] 打印日志 - W
*
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.debugTag]
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag]
* @param msg 日志打印的内容
*/
fun loggerW(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
fun loggerW(tag: String = YukiHookAPI.Configs.debugTag, msg: String) = runCatching {
Log.w(tag, msg)
XposedBridge.log("[$tag][W]--> $msg")
}
@@ -73,11 +73,11 @@ fun loggerW(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
* 向控制台和 [XposedBridge] 打印日志 - E
*
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.debugTag]
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag]
* @param msg 日志打印的内容
* @param e 可填入异常堆栈信息 - 将自动完整打印到控制台
*/
fun loggerE(tag: String = YukiHookAPI.debugTag, msg: String, e: Throwable? = null) = runCatching {
fun loggerE(tag: String = YukiHookAPI.Configs.debugTag, msg: String, e: Throwable? = null) = runCatching {
Log.e(tag, msg, e)
XposedBridge.log("[$tag][E]--> $msg")
e?.also { XposedBridge.log(it) }

View File

@@ -35,13 +35,13 @@ import java.io.Serializable
* 获得 [Any] 类型
* @return [Class]
*/
val AnyType get() = Any::class.javaPrimitiveType
val AnyType get() = Any::class.java
/**
* 获得 [Unit] 类型
* @return [Class]
*/
val UnitType get() = Unit::class.javaPrimitiveType
val UnitType get() = Void.TYPE ?: Unit::class.java
/**
* 获得 [Boolean] 类型

View File

@@ -41,13 +41,31 @@ import com.highcapable.yukihookapi.hook.factory.encase
*
* Hook 开始时将自动调用 [onHook] 方法
*
* 你可以对 [YukiHookAPI] 进行配置
*
* 调用 [YukiHookAPI.configs] 进行配置
*
* ....
*
* YukiHookApi.configs {
*
* ....debugTag = "自定义 TAG"
*
* ....modulePackageName = "模块包名/可选"
*
* ....isDebug = true
*
* }
*
* ....
*
* 请在 [onHook] 中调用 [YukiHookAPI.encase] 或直接调用 [encase]
*
* 可写作如下形式:
*
* ....
*
* override fun onHook() = YukiHookAPI.encase(moduleName = "模块包名/可选") {
* override fun onHook() = YukiHookAPI.encase {
*
* ....// Your code here.
*
@@ -59,7 +77,7 @@ import com.highcapable.yukihookapi.hook.factory.encase
*
* ....
*
* override fun onHook() = encase(moduleName = "模块包名/可选") {
* override fun onHook() = encase {
*
* ....// Your code here.
*
@@ -71,7 +89,7 @@ import com.highcapable.yukihookapi.hook.factory.encase
*
* ......
*
* override fun onHook() = encase(moduleName = "模块包名", MainHooker(), SecondHooker(), ThirdHooker() ...)
* override fun onHook() = encase(MainHooker(), SecondHooker(), ThirdHooker() ...)
*
* ......
*
@@ -80,7 +98,13 @@ import com.highcapable.yukihookapi.hook.factory.encase
@Keep
interface YukiHookXposedInitProxy {
/** 模块装载调用入口方法 - Xposed API */
/**
* 模块装载调用入口方法
*
* Xposed API
*
* 调用 [YukiHookAPI.encase] 或直接调用 [encase] 开始 Hook
*/
@Keep
fun onHook()
}