mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-05 18:25:28 +08:00
...
This commit is contained in:
16
README.md
16
README.md
@@ -9,13 +9,27 @@
|
|||||||
|
|
||||||
# Introduce
|
# Introduce
|
||||||
|
|
||||||
|
## 项目介绍
|
||||||
|
|
||||||
- 这是一个使用 Kotlin 重新构建的高效 Xposed Hook API
|
- 这是一个使用 Kotlin 重新构建的高效 Xposed Hook API
|
||||||
- 名称取自 <a href='https://www.bilibili.com/bangumi/play/ss5016/?from=search&seid=313229405371562533&spm_id_from=333.337.0.0'>
|
- 名称取自 <a href='https://www.bilibili.com/bangumi/play/ss5016/?from=search&seid=313229405371562533&spm_id_from=333.337.0.0'>
|
||||||
《ももくり》女主 栗原 雪(Yuki)</a>
|
《ももくり》女主 栗原 雪(Yuki)</a>
|
||||||
- 前身为 [开发学习项目](https://github.com/fankes/TMore) 中使用的 Innocent Xposed API,现在重新命名并开源
|
- 前身为 [开发学习项目](https://github.com/fankes/TMore) 中使用的 Innocent Xposed API,现在重新命名并开源
|
||||||
|
|
||||||
|
# Why YukiHookAPI
|
||||||
|
|
||||||
|
## 它能做什么
|
||||||
|
|
||||||
|
- 1.模块开发:自动构建程序可以帮你快速创建一个 Xposed 模块,完全省去配置入口类和 xposed_init 文件
|
||||||
|
- 2.轻量优雅:拥有一套强大、优雅和人性的 Koltin lambda Hook API,可以帮你快速实现 Method、Constructor、Field 的查找以及 Hook
|
||||||
|
- 3.高效调试:拥有丰富的调试日志功能,细到每个 Hook 方法的名称、所在类以及查找耗时,可进行快速调试和排错
|
||||||
|
- 4.方便移植:原生支持 Xposed API 用法,并原生对接 Xposed API,拥有 Xposed API 的 Hook 框架都能快速对接 YuKiHookAPI
|
||||||
|
- 5.快速上手:简单易用,不需要繁琐的配置,不需要十足的开发经验,搭建环境集成依赖即可立即开始使用
|
||||||
|
|
||||||
# Get Started
|
# Get Started
|
||||||
|
|
||||||
|
## 开始使用
|
||||||
|
|
||||||
- 暂定 1.0 版本
|
- 暂定 1.0 版本
|
||||||
- 可做学习参考但暂时不要 Fork 也不要使用
|
- 可做学习参考但暂时不要 Fork 也不要使用
|
||||||
- 还差 Wiki 没有撰写 Demo 没有写完和 API 未提交至 Maven
|
- 还差 Wiki 没有撰写 Demo 没有写完和 API 未提交至 Maven
|
||||||
@@ -23,6 +37,8 @@
|
|||||||
|
|
||||||
# License
|
# License
|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
- [MIT](https://choosealicense.com/licenses/mit)
|
- [MIT](https://choosealicense.com/licenses/mit)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@@ -5,6 +5,17 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
signingConfigs {
|
||||||
|
debug {
|
||||||
|
storeFile file('../keystore/public')
|
||||||
|
storePassword '123456'
|
||||||
|
keyAlias 'public'
|
||||||
|
keyPassword '123456'
|
||||||
|
v1SigningEnabled true
|
||||||
|
v2SigningEnabled true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
compileSdk 31
|
compileSdk 31
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
@@ -20,6 +31,7 @@ android {
|
|||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled false
|
minifyEnabled false
|
||||||
|
signingConfig signingConfigs.debug
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -50,8 +50,10 @@ class MainInjecter : YukiHookXposedInitProxy {
|
|||||||
|
|
||||||
override fun onHook() {
|
override fun onHook() {
|
||||||
// 设置模式
|
// 设置模式
|
||||||
YukiHookAPI.debugTag = "YukiSuki"
|
YukiHookAPI.configs {
|
||||||
YukiHookAPI.isDebug = true
|
debugTag = "YukiSuki"
|
||||||
|
isDebug = true
|
||||||
|
}
|
||||||
// 方案 1
|
// 方案 1
|
||||||
// encase(MainHooker(), SecondHooker())
|
// encase(MainHooker(), SecondHooker())
|
||||||
// 方案 2
|
// 方案 2
|
||||||
@@ -81,7 +83,7 @@ class MainInjecter : YukiHookXposedInitProxy {
|
|||||||
method {
|
method {
|
||||||
name = "a"
|
name = "a"
|
||||||
param(StringType, StringType)
|
param(StringType, StringType)
|
||||||
returnType = UnitType
|
returnType = StringType
|
||||||
}
|
}
|
||||||
beforeHook {
|
beforeHook {
|
||||||
args(index = 0).set("✌️改了前面的")
|
args(index = 0).set("✌️改了前面的")
|
||||||
|
BIN
keystore/public
Normal file
BIN
keystore/public
Normal file
Binary file not shown.
@@ -153,6 +153,7 @@ class YukiHookXposedProcessor : SymbolProcessorProvider {
|
|||||||
"\n" +
|
"\n" +
|
||||||
"import androidx.annotation.Keep\n" +
|
"import androidx.annotation.Keep\n" +
|
||||||
"import com.highcapable.yukihookapi.YukiHookAPI\n" +
|
"import com.highcapable.yukihookapi.YukiHookAPI\n" +
|
||||||
|
"import com.highcapable.yukihookapi.YukiHookAPI.Configs\n" +
|
||||||
"import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus\n" +
|
"import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus\n" +
|
||||||
"import com.highcapable.yukihookapi.hook.log.loggerE\n" +
|
"import com.highcapable.yukihookapi.hook.log.loggerE\n" +
|
||||||
"import de.robv.android.xposed.IXposedHookLoadPackage\n" +
|
"import de.robv.android.xposed.IXposedHookLoadPackage\n" +
|
||||||
@@ -171,8 +172,8 @@ class YukiHookXposedProcessor : SymbolProcessorProvider {
|
|||||||
" }.onFailure {\n" +
|
" }.onFailure {\n" +
|
||||||
" loggerE(msg = \"Try to load $packageName.$className Failed\", e = it)\n" +
|
" loggerE(msg = \"Try to load $packageName.$className Failed\", e = it)\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" YukiHookAPI.modulePackageName.ifEmpty {\n" +
|
" YukiHookAPI.Configs.modulePackageName.ifEmpty {\n" +
|
||||||
" YukiHookAPI.modulePackageName = \"$realPackageName\"\n" +
|
" YukiHookAPI.Configs.modulePackageName = \"$realPackageName\"\n" +
|
||||||
" \"$realPackageName\"\n" +
|
" \"$realPackageName\"\n" +
|
||||||
" }.also {\n" +
|
" }.also {\n" +
|
||||||
" if (lpparam.packageName == it)\n" +
|
" if (lpparam.packageName == it)\n" +
|
||||||
|
@@ -32,11 +32,11 @@ package com.highcapable.yukihookapi
|
|||||||
import android.content.pm.ApplicationInfo
|
import android.content.pm.ApplicationInfo
|
||||||
import androidx.annotation.Keep
|
import androidx.annotation.Keep
|
||||||
import com.highcapable.yukihookapi.YukiHookAPI.encase
|
import com.highcapable.yukihookapi.YukiHookAPI.encase
|
||||||
import com.highcapable.yukihookapi.annotation.DoNotUseField
|
|
||||||
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
import com.highcapable.yukihookapi.annotation.DoNotUseMethod
|
||||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||||
import com.highcapable.yukihookapi.hook.param.CustomParam
|
import com.highcapable.yukihookapi.hook.param.CustomParam
|
||||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
|
||||||
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
import de.robv.android.xposed.callbacks.XC_LoadPackage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,37 +49,52 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage
|
|||||||
@Keep
|
@Keep
|
||||||
object YukiHookAPI {
|
object YukiHookAPI {
|
||||||
|
|
||||||
/**
|
|
||||||
* 这是一个调试日志的全局标识
|
|
||||||
*
|
|
||||||
* 默认文案为 YukiHookAPI
|
|
||||||
*
|
|
||||||
* 你可以修改为你自己的文案
|
|
||||||
*/
|
|
||||||
var debugTag = "YukiHookAPI"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启调试模式 - 默认启用
|
|
||||||
*
|
|
||||||
* 启用后将交由日志输出管理器打印详细 Hook 日志到控制台
|
|
||||||
*
|
|
||||||
* 关闭后将只输出 Error 级别的日志
|
|
||||||
*
|
|
||||||
* 请过滤 [debugTag] 即可找到每条日志
|
|
||||||
*/
|
|
||||||
var isDebug = true
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Xposed Hook API 绑定的模块包名 - 未写将自动生成
|
|
||||||
* - 你不应该设置此变量的名称 - 请使用 [encase] 装载模块包名
|
|
||||||
*/
|
|
||||||
@DoNotUseField
|
|
||||||
@Keep
|
|
||||||
var modulePackageName = ""
|
|
||||||
|
|
||||||
/** Xposed Hook API 方法体回调 */
|
/** Xposed Hook API 方法体回调 */
|
||||||
private var packageParamCallback: (PackageParam.() -> Unit)? = null
|
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 回调
|
* 装载 Xposed API 回调
|
||||||
*
|
*
|
||||||
@@ -92,22 +107,18 @@ object YukiHookAPI {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 作为模块装载调用入口方法 - Xposed API
|
* 作为模块装载调用入口方法 - Xposed API
|
||||||
* @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成
|
|
||||||
* @param initiate Hook 方法体
|
* @param initiate Hook 方法体
|
||||||
*/
|
*/
|
||||||
fun encase(moduleName: String = "", initiate: PackageParam.() -> Unit) {
|
fun encase(initiate: PackageParam.() -> Unit) {
|
||||||
modulePackageName = moduleName
|
|
||||||
packageParamCallback = initiate
|
packageParamCallback = initiate
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 作为模块装载调用入口方法 - Xposed API
|
* 作为模块装载调用入口方法 - Xposed API
|
||||||
* @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成
|
|
||||||
* @param hooker Hook 子类数组 - 必填不能为空
|
* @param hooker Hook 子类数组 - 必填不能为空
|
||||||
* @throws IllegalStateException 如果 [hooker] 是空的
|
* @throws IllegalStateException 如果 [hooker] 是空的
|
||||||
*/
|
*/
|
||||||
fun encase(moduleName: String = "", vararg hooker: YukiBaseHooker) {
|
fun encase(vararg hooker: YukiBaseHooker) {
|
||||||
modulePackageName = moduleName
|
|
||||||
packageParamCallback = {
|
packageParamCallback = {
|
||||||
if (hooker.isNotEmpty())
|
if (hooker.isNotEmpty())
|
||||||
hooker.forEach { it.assignInstance(packageParam = this) }
|
hooker.forEach { it.assignInstance(packageParam = this) }
|
||||||
|
@@ -48,7 +48,7 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
|||||||
*
|
*
|
||||||
* - 你的模块包名将被这样识别:|com.example.module|.hook...
|
* - 你的模块包名将被这样识别:|com.example.module|.hook...
|
||||||
*
|
*
|
||||||
* - 若你不喜欢这样创建类 - 没问题 - 请在 [YukiHookAPI.encase] 中自行指定模块包名即可 - 但不按照规则定义包名你将会收到编译警告
|
* - 若你不喜欢这样创建类 - 没问题 - 请在 [YukiHookAPI.Configs.modulePackageName] 填写模块包名即可 - 但不按照规则定义包名你将会收到编译警告
|
||||||
*
|
*
|
||||||
* 例子:YukiHookAPI.encase(moduleName = "com.example.module", ...)
|
* 例子:YukiHookAPI.encase(moduleName = "com.example.module", ...)
|
||||||
*
|
*
|
||||||
|
@@ -133,6 +133,7 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
|
|||||||
*
|
*
|
||||||
* 你只能使用一次 [method] 或 [constructor] 方法 - 否则结果会被替换
|
* 你只能使用一次 [method] 或 [constructor] 方法 - 否则结果会被替换
|
||||||
* @param initiate 方法体
|
* @param initiate 方法体
|
||||||
|
* @return [ConstructorFinder.Result]
|
||||||
*/
|
*/
|
||||||
fun constructor(initiate: ConstructorFinder.() -> Unit): ConstructorFinder.Result {
|
fun constructor(initiate: ConstructorFinder.() -> Unit): ConstructorFinder.Result {
|
||||||
isHookMemberSetup = true
|
isHookMemberSetup = true
|
||||||
@@ -327,11 +328,11 @@ class YukiHookCreater(private val packageParam: PackageParam, val hookClass: Cla
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook 过程中开启了 [YukiHookAPI.isDebug] 输出调试信息
|
* Hook 过程中开启了 [YukiHookAPI.Configs.isDebug] 输出调试信息
|
||||||
* @param msg 调试日志内容
|
* @param msg 调试日志内容
|
||||||
*/
|
*/
|
||||||
internal fun onHookLogMsg(msg: String) {
|
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] 可继续向下监听
|
* @return [Result] 可继续向下监听
|
||||||
*/
|
*/
|
||||||
fun ignoredConductFailure() = onConductFailure { _, _ -> }
|
fun ignoredConductFailure() = onConductFailure { _, _ -> }
|
||||||
|
@@ -104,7 +104,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
|||||||
inner class RemedyPlan {
|
inner class RemedyPlan {
|
||||||
|
|
||||||
/** 失败尝试次数数组 */
|
/** 失败尝试次数数组 */
|
||||||
private val remedyPlan = HashSet<ConstructorFinder>()
|
private val remedyPlans = HashSet<ConstructorFinder>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建需要重新查找的 [Constructor]
|
* 创建需要重新查找的 [Constructor]
|
||||||
@@ -115,7 +115,7 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
|||||||
* @param initiate 方法体
|
* @param initiate 方法体
|
||||||
*/
|
*/
|
||||||
fun constructor(initiate: ConstructorFinder.() -> Unit) =
|
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
|
@DoNotUseMethod
|
||||||
internal fun build() {
|
internal fun build() {
|
||||||
if (remedyPlan.isNotEmpty()) run {
|
if (remedyPlans.isNotEmpty()) run {
|
||||||
var isFindSuccess = false
|
var isFindSuccess = false
|
||||||
var lastError: Throwable? = null
|
var lastError: Throwable? = null
|
||||||
remedyPlan.forEachIndexed { p, it ->
|
remedyPlans.forEachIndexed { p, it ->
|
||||||
runCatching {
|
runCatching {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
hookInstance.member = it.result
|
hookInstance.member = it.result
|
||||||
@@ -143,10 +143,10 @@ class ConstructorFinder(private val hookInstance: YukiHookCreater.MemberHookCrea
|
|||||||
}
|
}
|
||||||
if (!isFindSuccess) {
|
if (!isFindSuccess) {
|
||||||
onFailureMsg(
|
onFailureMsg(
|
||||||
msg = "trying ${remedyPlan.size} times and all failure by RemedyPlan",
|
msg = "trying ${remedyPlans.size} times and all failure by RemedyPlan",
|
||||||
throwable = lastError
|
throwable = lastError
|
||||||
)
|
)
|
||||||
remedyPlan.clear()
|
remedyPlans.clear()
|
||||||
}
|
}
|
||||||
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookInstance.tag}]")
|
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookInstance.tag}]")
|
||||||
}
|
}
|
||||||
|
@@ -37,9 +37,9 @@ import com.highcapable.yukihookapi.hook.utils.runBlocking
|
|||||||
import java.lang.reflect.Field
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Field 查找结果实现类
|
* Field 查找类
|
||||||
*
|
*
|
||||||
* 可在这里处理找到的 [fieldInstance]
|
* 可通过执行类型查找指定变量
|
||||||
* @param hookInstance 当前 Hook 实例
|
* @param hookInstance 当前 Hook 实例
|
||||||
* @param hookClass 当前被 Hook 的 [Class]
|
* @param hookClass 当前被 Hook 的 [Class]
|
||||||
*/
|
*/
|
||||||
|
@@ -111,7 +111,7 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
|||||||
inner class RemedyPlan {
|
inner class RemedyPlan {
|
||||||
|
|
||||||
/** 失败尝试次数数组 */
|
/** 失败尝试次数数组 */
|
||||||
private val remedyPlan = HashSet<MethodFinder>()
|
private val remedyPlans = HashSet<MethodFinder>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建需要重新查找的 [Method]
|
* 创建需要重新查找的 [Method]
|
||||||
@@ -121,7 +121,8 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
|||||||
* 若最后依然失败 - 将停止查找并输出错误日志
|
* 若最后依然失败 - 将停止查找并输出错误日志
|
||||||
* @param initiate 方法体
|
* @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
|
@DoNotUseMethod
|
||||||
internal fun build() {
|
internal fun build() {
|
||||||
if (remedyPlan.isNotEmpty()) run {
|
if (remedyPlans.isNotEmpty()) run {
|
||||||
var isFindSuccess = false
|
var isFindSuccess = false
|
||||||
var lastError: Throwable? = null
|
var lastError: Throwable? = null
|
||||||
remedyPlan.forEachIndexed { p, it ->
|
remedyPlans.forEachIndexed { p, it ->
|
||||||
runCatching {
|
runCatching {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
hookInstance.member = it.result
|
hookInstance.member = it.result
|
||||||
@@ -149,10 +150,10 @@ class MethodFinder(private val hookInstance: YukiHookCreater.MemberHookCreater,
|
|||||||
}
|
}
|
||||||
if (!isFindSuccess) {
|
if (!isFindSuccess) {
|
||||||
onFailureMsg(
|
onFailureMsg(
|
||||||
msg = "trying ${remedyPlan.size} times and all failure by RemedyPlan",
|
msg = "trying ${remedyPlans.size} times and all failure by RemedyPlan",
|
||||||
throwable = lastError
|
throwable = lastError
|
||||||
)
|
)
|
||||||
remedyPlan.clear()
|
remedyPlans.clear()
|
||||||
}
|
}
|
||||||
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookInstance.tag}]")
|
} else loggerW(msg = "RemedyPlan is empty,forgot it? [${hookInstance.tag}]")
|
||||||
}
|
}
|
||||||
|
@@ -40,13 +40,11 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
|||||||
*
|
*
|
||||||
* 你可以继续继承此类进行自定义 Hooker 相关参数
|
* 你可以继续继承此类进行自定义 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() ...)
|
* 2.调用 [PackageParam.loadHooker] loadHooker(hooker = CustomHooker())
|
||||||
*
|
|
||||||
* 调用 [PackageParam.loadHooker] loadHooker(hooker = CustomHooker())
|
|
||||||
*
|
*
|
||||||
* 更多请参考 [InjectYukiHookWithXposed] 中的注释内容
|
* 更多请参考 [InjectYukiHookWithXposed] 中的注释内容
|
||||||
*
|
*
|
||||||
|
@@ -40,11 +40,9 @@ import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI]
|
* 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI]
|
||||||
* @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成
|
|
||||||
* @param initiate Hook 方法体
|
* @param initiate Hook 方法体
|
||||||
*/
|
*/
|
||||||
fun YukiHookXposedInitProxy.encase(moduleName: String = "", initiate: PackageParam.() -> Unit) =
|
fun YukiHookXposedInitProxy.encase(initiate: PackageParam.() -> Unit) = YukiHookAPI.encase(initiate)
|
||||||
YukiHookAPI.encase(moduleName, initiate)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI]
|
* 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI]
|
||||||
@@ -53,15 +51,6 @@ fun YukiHookXposedInitProxy.encase(moduleName: String = "", initiate: PackagePar
|
|||||||
*/
|
*/
|
||||||
fun YukiHookXposedInitProxy.encase(vararg hooker: YukiBaseHooker) = YukiHookAPI.encase(hooker = hooker)
|
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] 是否激活
|
* @return [Boolean] 是否激活
|
||||||
|
@@ -37,10 +37,10 @@ import de.robv.android.xposed.XposedBridge
|
|||||||
* 向控制台和 [XposedBridge] 打印日志 - D
|
* 向控制台和 [XposedBridge] 打印日志 - D
|
||||||
*
|
*
|
||||||
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
|
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
|
||||||
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.debugTag]
|
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag]
|
||||||
* @param msg 日志打印的内容
|
* @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)
|
Log.d(tag, msg)
|
||||||
XposedBridge.log("[$tag][D]--> $msg")
|
XposedBridge.log("[$tag][D]--> $msg")
|
||||||
}
|
}
|
||||||
@@ -49,10 +49,10 @@ fun loggerD(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
|
|||||||
* 向控制台和 [XposedBridge] 打印日志 - I
|
* 向控制台和 [XposedBridge] 打印日志 - I
|
||||||
*
|
*
|
||||||
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
|
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
|
||||||
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.debugTag]
|
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag]
|
||||||
* @param msg 日志打印的内容
|
* @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)
|
Log.i(tag, msg)
|
||||||
XposedBridge.log("[$tag][I]--> $msg")
|
XposedBridge.log("[$tag][I]--> $msg")
|
||||||
}
|
}
|
||||||
@@ -61,10 +61,10 @@ fun loggerI(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
|
|||||||
* 向控制台和 [XposedBridge] 打印日志 - W
|
* 向控制台和 [XposedBridge] 打印日志 - W
|
||||||
*
|
*
|
||||||
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
|
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
|
||||||
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.debugTag]
|
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag]
|
||||||
* @param msg 日志打印的内容
|
* @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)
|
Log.w(tag, msg)
|
||||||
XposedBridge.log("[$tag][W]--> $msg")
|
XposedBridge.log("[$tag][W]--> $msg")
|
||||||
}
|
}
|
||||||
@@ -73,11 +73,11 @@ fun loggerW(tag: String = YukiHookAPI.debugTag, msg: String) = runCatching {
|
|||||||
* 向控制台和 [XposedBridge] 打印日志 - E
|
* 向控制台和 [XposedBridge] 打印日志 - E
|
||||||
*
|
*
|
||||||
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
|
* [XposedBridge] 中的日志打印风格为 [[tag]]「类型」--> [msg]
|
||||||
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.debugTag]
|
* @param tag 日志打印的标签 - 建议和自己的模块名称设置成一样的 - 默认为 [YukiHookAPI.Configs.debugTag]
|
||||||
* @param msg 日志打印的内容
|
* @param msg 日志打印的内容
|
||||||
* @param e 可填入异常堆栈信息 - 将自动完整打印到控制台
|
* @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)
|
Log.e(tag, msg, e)
|
||||||
XposedBridge.log("[$tag][E]--> $msg")
|
XposedBridge.log("[$tag][E]--> $msg")
|
||||||
e?.also { XposedBridge.log(it) }
|
e?.also { XposedBridge.log(it) }
|
||||||
|
@@ -35,13 +35,13 @@ import java.io.Serializable
|
|||||||
* 获得 [Any] 类型
|
* 获得 [Any] 类型
|
||||||
* @return [Class]
|
* @return [Class]
|
||||||
*/
|
*/
|
||||||
val AnyType get() = Any::class.javaPrimitiveType
|
val AnyType get() = Any::class.java
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得 [Unit] 类型
|
* 获得 [Unit] 类型
|
||||||
* @return [Class]
|
* @return [Class]
|
||||||
*/
|
*/
|
||||||
val UnitType get() = Unit::class.javaPrimitiveType
|
val UnitType get() = Void.TYPE ?: Unit::class.java
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获得 [Boolean] 类型
|
* 获得 [Boolean] 类型
|
||||||
|
@@ -41,13 +41,31 @@ import com.highcapable.yukihookapi.hook.factory.encase
|
|||||||
*
|
*
|
||||||
* Hook 开始时将自动调用 [onHook] 方法
|
* Hook 开始时将自动调用 [onHook] 方法
|
||||||
*
|
*
|
||||||
|
* 你可以对 [YukiHookAPI] 进行配置
|
||||||
|
*
|
||||||
|
* 调用 [YukiHookAPI.configs] 进行配置
|
||||||
|
*
|
||||||
|
* ....
|
||||||
|
*
|
||||||
|
* YukiHookApi.configs {
|
||||||
|
*
|
||||||
|
* ....debugTag = "自定义 TAG"
|
||||||
|
*
|
||||||
|
* ....modulePackageName = "模块包名/可选"
|
||||||
|
*
|
||||||
|
* ....isDebug = true
|
||||||
|
*
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* ....
|
||||||
|
*
|
||||||
* 请在 [onHook] 中调用 [YukiHookAPI.encase] 或直接调用 [encase]
|
* 请在 [onHook] 中调用 [YukiHookAPI.encase] 或直接调用 [encase]
|
||||||
*
|
*
|
||||||
* 可写作如下形式:
|
* 可写作如下形式:
|
||||||
*
|
*
|
||||||
* ....
|
* ....
|
||||||
*
|
*
|
||||||
* override fun onHook() = YukiHookAPI.encase(moduleName = "模块包名/可选") {
|
* override fun onHook() = YukiHookAPI.encase {
|
||||||
*
|
*
|
||||||
* ....// Your code here.
|
* ....// 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.
|
* ....// 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
|
@Keep
|
||||||
interface YukiHookXposedInitProxy {
|
interface YukiHookXposedInitProxy {
|
||||||
|
|
||||||
/** 模块装载调用入口方法 - Xposed API */
|
/**
|
||||||
|
* 模块装载调用入口方法
|
||||||
|
*
|
||||||
|
* Xposed API
|
||||||
|
*
|
||||||
|
* 调用 [YukiHookAPI.encase] 或直接调用 [encase] 开始 Hook
|
||||||
|
*/
|
||||||
@Keep
|
@Keep
|
||||||
fun onHook()
|
fun onHook()
|
||||||
}
|
}
|
Reference in New Issue
Block a user