mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
Modify auto matched Class<*> instance in PackageParam and changed some function
This commit is contained in:
@@ -1,13 +1,17 @@
|
||||
## HookClass [class]
|
||||
|
||||
```kotlin
|
||||
class HookClass internal constructor(var instance: Class<*>?, var name: String, var throwable: Throwable?)
|
||||
class HookClass internal constructor(internal var instance: Class<*>?, internal var name: String, internal var throwable: Throwable?)
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.93` `修改`
|
||||
|
||||
`HookClass` 相关功能不再对外开放
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 创建一个当前 Hook 的 `Class` 接管类。
|
||||
|
@@ -402,6 +402,8 @@ val VariousClass.clazz: Class<*>
|
||||
|
||||
> 字符串、`VariousClass` 转换为实体类。
|
||||
|
||||
使用当前 `appClassLoader` 装载目标 `Class`。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以轻松地将 `String` 类型的 `Class` 包名转为 `Class` 实例。
|
||||
@@ -459,11 +461,11 @@ if("com.example.demo.DemoClass".hasClass) {
|
||||
### findClass [method]
|
||||
|
||||
```kotlin
|
||||
fun findClass(name: String): HookClass
|
||||
fun findClass(name: String, loader: ClassLoader?): HookClass
|
||||
```
|
||||
|
||||
```kotlin
|
||||
fun findClass(vararg name: String): VariousClass
|
||||
fun findClass(vararg name: String, loader: ClassLoader?): VariousClass
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
@@ -474,10 +476,16 @@ fun findClass(vararg name: String): VariousClass
|
||||
|
||||
移除了 ~~`findClass(various: VariousClass)`~~ 方法
|
||||
|
||||
`v1.0.93` `修改`
|
||||
|
||||
新增 `loader` 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过完整包名+名称查找需要被 Hook 的 `Class`。
|
||||
|
||||
!> 使用此方法会得到一个 `HookClass` 仅用于 Hook,若想查找 `Class` 请使用 `classOf`、`clazz` 功能。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以使用三种方式查找你需要 Hook 的目标 `Class`。
|
||||
@@ -506,22 +514,40 @@ findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.exa
|
||||
val variousClass = VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
|
||||
```
|
||||
|
||||
若你当前需要查找的 `Class` 不属于 `appClassLoader`,你可以使用 `loader` 参数指定你要装载的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
|
||||
findClass(name = "com.example.demo.OutsideClass", loader = outsideLoader)
|
||||
```
|
||||
|
||||
同样地,在不确定多个版本的 `Class` 以及不同名称时,也可以使用 `loader` 参数指定你要装载的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
|
||||
findClass("com.example.demo.OutsideClass1", "com.example.demo.OutsideClass2", "com.example.demo.OutsideClass3", loader = outsideLoader)
|
||||
```
|
||||
|
||||
### hook [method]
|
||||
|
||||
```kotlin
|
||||
inline fun String.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||
inline fun String.hook(initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||
```
|
||||
|
||||
```kotlin
|
||||
inline fun Class<*>.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||
inline fun Class<*>.hook(initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||
```
|
||||
|
||||
```kotlin
|
||||
inline fun VariousClass.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||
inline fun VariousClass.hook(initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||
```
|
||||
|
||||
```kotlin
|
||||
inline fun HookClass.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||
inline fun HookClass.hook(initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||
```
|
||||
|
||||
**变更记录**
|
||||
@@ -548,6 +574,10 @@ inline fun HookClass.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHook
|
||||
|
||||
将方法体进行 inline
|
||||
|
||||
`v1.0.93` `修改`
|
||||
|
||||
移除了 ~~`isUseAppClassLoader`~~ 参数
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 这是一切 Hook 的入口创建方法,Hook 方法、构造方法。
|
||||
@@ -578,10 +608,12 @@ findClass(name = "com.example.demo.DemoClass").hook {
|
||||
|
||||
使用 `stub` 或直接拿到 `Class` 实例进行创建。
|
||||
|
||||
默认情况下 API 会将 `Class` 实例转换为类名并绑定到 `appClassLoader`,若失败,则会使用原始 `Class` 实例直接进行 Hook。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
Activity::class.java.hook {
|
||||
Stub::class.java.hook {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
@@ -606,23 +638,6 @@ findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
|
||||
}
|
||||
```
|
||||
|
||||
!> 以下是关于 Hook 目标 Class 的一个特殊情况说明。
|
||||
|
||||
若你 Hook 的 `Class` 实例的 `ClassLoader` 并不是当前的 `appClassLoader`,那么你需要做一下小的调整。
|
||||
|
||||
在 `hook` 方法中加入 `isUseAppClassLoader = false`,这样,你的 `Class` 就不会被重新绑定到 `appClassLoader` 了。
|
||||
|
||||
此方案适用于目标 `Class` 无法在当前 `appClassLoader` 中被得到但可以得到 `Class` 实例的情况。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
// 这里的做法标识了 hook 不会再将 YourClass 重新与当前 appClassLoader 绑定
|
||||
YourClass.hook(isUseAppClassLoader = false) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
### hook [method]
|
||||
|
||||
```kotlin
|
||||
|
@@ -8,61 +8,35 @@
|
||||
|
||||
> 这是自定义 `Member` 和 `Class` 相关功能的查找匹配以及 `invoke` 的封装类。
|
||||
|
||||
### hookClass [field]
|
||||
|
||||
```kotlin
|
||||
val Class<*>.hookClass: HookClass
|
||||
```
|
||||
### ~~hookClass [field]~~ <!-- {docsify-ignore} -->
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
`v1.0.93` `移除`
|
||||
|
||||
> 将 `Class` 转换为 `HookClass`。
|
||||
`HookClass` 相关功能不再对外开放
|
||||
|
||||
### normalClass [field]
|
||||
|
||||
```kotlin
|
||||
val HookClass.normalClass: Class<*>?
|
||||
```
|
||||
### ~~normalClass [field]~~ <!-- {docsify-ignore} -->
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
`v1.0.93` `移除`
|
||||
|
||||
> 将 `HookClass` 转换为 `Class`。
|
||||
`HookClass` 相关功能不再对外开放
|
||||
|
||||
### hasClass [field]
|
||||
|
||||
```kotlin
|
||||
val String.hasClass: Boolean
|
||||
```
|
||||
### ~~hasClass [field]~~ <!-- {docsify-ignore} -->
|
||||
|
||||
**变更记录**
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
**功能描述**
|
||||
`v1.0.93` `移除`
|
||||
|
||||
> 通过字符串查找类是否存在。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以轻松的使用此方法判断字符串中的类是否存在。
|
||||
|
||||
!> 此查找仅限使用当前的 `ClassLoader`,若要指定 `ClassLoader` 请使用下方的 `hasClass` 同名方法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
if("com.example.demo.DemoClass".hasClass) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
请直接使用 `hasClass()` 无参方法
|
||||
|
||||
### hasExtends [field]
|
||||
|
||||
@@ -120,10 +94,37 @@ fun String.hasClass(loader: ClassLoader?): Boolean
|
||||
|
||||
`v1.0` `添加`
|
||||
|
||||
`v1.0.93` `修改`
|
||||
|
||||
支持直接使用空参数方法使用默认 `ClassLoader` 进行判断
|
||||
|
||||
**功能描述**
|
||||
|
||||
> 通过字符串使用指定的 `ClassLoader` 查找类是否存在。
|
||||
|
||||
**功能示例**
|
||||
|
||||
你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 `Class.forName`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
if("com.example.demo.DemoClass".hasClass()) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
填入方法中的 `loader` 参数可判断指定的 `ClassLoader` 中的 `Class` 是否存在。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
if("com.example.demo.DemoClass".hasClass(customClassloader)) {
|
||||
// Your code here.
|
||||
}
|
||||
```
|
||||
|
||||
### hasField [method]
|
||||
|
||||
```kotlin
|
||||
|
@@ -682,6 +682,29 @@ VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
|
||||
}.get().call()
|
||||
```
|
||||
|
||||
若当前 `Class` 在指定的 `ClassLoader` 中存在,你可以在 `get` 中填入你的 `ClassLoader`。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
|
||||
VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
|
||||
name = "doTask"
|
||||
emptyParam()
|
||||
}.get().call()
|
||||
```
|
||||
|
||||
若你正在 `PackageParam` 中操作 (Xposed) 宿主环境的 `Class`,可以直接使用 `clazz` 进行设置。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
VariousClass("com.demo.ATest", "com.demo.BTest").clazz.method {
|
||||
name = "doTask"
|
||||
emptyParam()
|
||||
}.get().call()
|
||||
```
|
||||
|
||||
更多用法可参考 [VariousClass](api/document?id=variousclass-class)。
|
||||
|
||||
若在创建 Hook 的时候使用,可以更加方便,还可以自动拦截找不到 `Class` 的异常。
|
||||
|
@@ -33,7 +33,11 @@ package com.highcapable.yukihookapi.hook.bean
|
||||
* @param name 完整名称
|
||||
* @param throwable 异常
|
||||
*/
|
||||
class HookClass internal constructor(var instance: Class<*>? = null, var name: String, var throwable: Throwable? = null) {
|
||||
class HookClass internal constructor(
|
||||
@PublishedApi internal var instance: Class<*>? = null,
|
||||
@PublishedApi internal var name: String,
|
||||
@PublishedApi internal var throwable: Throwable? = null
|
||||
) {
|
||||
|
||||
override fun toString() = "[class] $name [throwable] $throwable [instance] $instance"
|
||||
}
|
@@ -30,7 +30,6 @@
|
||||
package com.highcapable.yukihookapi.hook.factory
|
||||
|
||||
import com.highcapable.yukihookapi.hook.bean.CurrentClass
|
||||
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
|
||||
@@ -43,26 +42,6 @@ import java.lang.reflect.Field
|
||||
import java.lang.reflect.Member
|
||||
import java.lang.reflect.Method
|
||||
|
||||
/**
|
||||
* [Class] 转换为 [HookClass]
|
||||
* @return [HookClass]
|
||||
*/
|
||||
val Class<*>.hookClass get() = HookClass(instance = this, name)
|
||||
|
||||
/**
|
||||
* [HookClass] 转换为 [Class]
|
||||
* @return [Class] or null
|
||||
*/
|
||||
val HookClass.normalClass get() = instance
|
||||
|
||||
/**
|
||||
* 通过字符串查找类是否存在
|
||||
*
|
||||
* - ❗仅限使用当前的 [ClassLoader]
|
||||
* @return [Boolean] 是否存在
|
||||
*/
|
||||
val String.hasClass get() = hasClass(loader = null)
|
||||
|
||||
/**
|
||||
* 当前 [Class] 是否有继承关系 - 父类是 [Any] 将被认为没有继承关系
|
||||
* @return [Boolean]
|
||||
@@ -94,10 +73,10 @@ fun classOf(name: String, loader: ClassLoader? = null): Class<*> {
|
||||
|
||||
/**
|
||||
* 通过字符串查找类是否存在
|
||||
* @param loader [Class] 所在的 [ClassLoader]
|
||||
* @param loader [Class] 所在的 [ClassLoader] - 不填使用默认 [ClassLoader]
|
||||
* @return [Boolean] 是否存在
|
||||
*/
|
||||
fun String.hasClass(loader: ClassLoader?) = try {
|
||||
fun String.hasClass(loader: ClassLoader? = null) = try {
|
||||
classOf(name = this, loader)
|
||||
true
|
||||
} catch (_: Throwable) {
|
||||
|
@@ -45,7 +45,6 @@ import com.highcapable.yukihookapi.hook.core.YukiResourcesHookCreater
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||
import com.highcapable.yukihookapi.hook.factory.hasClass
|
||||
import com.highcapable.yukihookapi.hook.factory.hookClass
|
||||
import com.highcapable.yukihookapi.hook.param.type.HookEntryType
|
||||
import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper
|
||||
import com.highcapable.yukihookapi.hook.utils.value
|
||||
@@ -318,68 +317,76 @@ open class PackageParam internal constructor(@PublishedApi internal var wrapper:
|
||||
/**
|
||||
* 通过字符串查找类是否存在
|
||||
*
|
||||
* - 默认使用当前 [appClassLoader] 装载目标 [Class]
|
||||
* - 使用当前 [appClassLoader] 装载目标 [Class]
|
||||
* @return [Boolean] 是否存在
|
||||
*/
|
||||
val String.hasClass get() = hasClass(appClassLoader)
|
||||
|
||||
/**
|
||||
* 默认使用当前 [appClassLoader] 查询并装载 [Class]
|
||||
* 查找并装载 [Class]
|
||||
*
|
||||
* - ❗使用此方法会得到一个 [HookClass] 仅用于 Hook - 若想查找 [Class] 请使用 [classOf]、[clazz] 功能
|
||||
* @param name 类名
|
||||
* @param loader 当前 [ClassLoader] - 默认使用 [appClassLoader] - 设为 null 使用默认 [ClassLoader]
|
||||
* @return [HookClass]
|
||||
*/
|
||||
fun findClass(name: String) = try {
|
||||
name.clazz.hookClass
|
||||
fun findClass(name: String, loader: ClassLoader? = appClassLoader) = try {
|
||||
classOf(name, loader).hookClass
|
||||
} catch (e: Throwable) {
|
||||
HookClass(name = name, throwable = e)
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认使用当前 [appClassLoader] 查询并装载 [Class]
|
||||
* 查找并装载 [Class]
|
||||
*
|
||||
* 使用此方法查询将会取 [name] 其中命中存在的第一个 [Class] 作为结果
|
||||
* 使用此方法查找将会取 [name] 其中命中存在的第一个 [Class] 作为结果
|
||||
*
|
||||
* - ❗使用此方法会得到一个 [HookClass] 仅用于 Hook - 若想查找 [Class] 请使用 [classOf]、[clazz] 功能
|
||||
* @param name 可填入多个类名 - 自动匹配
|
||||
* @return [VariousClass]
|
||||
* @param loader 当前 [ClassLoader] - 默认使用 [appClassLoader] - 设为 null 使用默认 [ClassLoader]
|
||||
* @return [HookClass]
|
||||
*/
|
||||
fun findClass(vararg name: String) = VariousClass(*name)
|
||||
fun findClass(vararg name: String, loader: ClassLoader? = appClassLoader) = VariousClass(*name).hookClass(loader)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造方法
|
||||
*
|
||||
* - 使用当前 [appClassLoader] 装载目标 [Class]
|
||||
*
|
||||
* - ❗为防止任何字符串都被当做 [Class] 进行 Hook - 推荐优先使用 [findClass]
|
||||
* @param isUseAppClassLoader 是否使用 [appClassLoader] 重新绑定当前 [Class] - 默认启用
|
||||
* @param initiate 方法体
|
||||
* @return [YukiMemberHookCreater.Result]
|
||||
*/
|
||||
inline fun String.hook(isUseAppClassLoader: Boolean = true, initiate: YukiMemberHookCreater.() -> Unit) =
|
||||
findClass(name = this).hook(isUseAppClassLoader, initiate)
|
||||
inline fun String.hook(initiate: YukiMemberHookCreater.() -> Unit) = findClass(name = this).hook(initiate)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造方法
|
||||
* @param isUseAppClassLoader 是否使用 [appClassLoader] 重新绑定当前 [Class] - 默认启用
|
||||
*
|
||||
* - 自动选择与当前 [Class] 相匹配的 [ClassLoader] - 优先使用 [appClassLoader]
|
||||
* @param initiate 方法体
|
||||
* @return [YukiMemberHookCreater.Result]
|
||||
*/
|
||||
inline fun Class<*>.hook(isUseAppClassLoader: Boolean = true, initiate: YukiMemberHookCreater.() -> Unit) =
|
||||
hookClass.hook(isUseAppClassLoader, initiate)
|
||||
inline fun Class<*>.hook(initiate: YukiMemberHookCreater.() -> Unit) = when {
|
||||
name.hasClass(appClassLoader) -> findClass(name)
|
||||
else -> hookClass
|
||||
}.hook(initiate)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造方法
|
||||
* @param isUseAppClassLoader 是否使用 [appClassLoader] 重新绑定当前 [Class] - 默认启用
|
||||
*
|
||||
* - 使用当前 [appClassLoader] 装载目标 [Class]
|
||||
* @param initiate 方法体
|
||||
* @return [YukiMemberHookCreater.Result]
|
||||
*/
|
||||
inline fun VariousClass.hook(isUseAppClassLoader: Boolean = true, initiate: YukiMemberHookCreater.() -> Unit) =
|
||||
hookClass(if (isUseAppClassLoader) appClassLoader else null).hook(isUseAppClassLoader, initiate)
|
||||
inline fun VariousClass.hook(initiate: YukiMemberHookCreater.() -> Unit) = hookClass(appClassLoader).hook(initiate)
|
||||
|
||||
/**
|
||||
* Hook 方法、构造方法
|
||||
* @param isUseAppClassLoader 是否使用 [appClassLoader] 重新绑定当前 [Class] - 默认启用
|
||||
* @param initiate 方法体
|
||||
* @return [YukiMemberHookCreater.Result]
|
||||
*/
|
||||
inline fun HookClass.hook(isUseAppClassLoader: Boolean = true, initiate: YukiMemberHookCreater.() -> Unit) =
|
||||
YukiMemberHookCreater(packageParam = this@PackageParam, hookClass = if (isUseAppClassLoader) bind() else this).apply(initiate).hook()
|
||||
inline fun HookClass.hook(initiate: YukiMemberHookCreater.() -> Unit) =
|
||||
YukiMemberHookCreater(packageParam = this@PackageParam, hookClass = this).apply(initiate).hook()
|
||||
|
||||
/**
|
||||
* Hook APP 的 Resources
|
||||
@@ -391,7 +398,7 @@ open class PackageParam internal constructor(@PublishedApi internal var wrapper:
|
||||
YukiResourcesHookCreater(packageParam = this@PackageParam, hookResources = this).apply(initiate).hook()
|
||||
|
||||
/**
|
||||
* [VariousClass] 转换为 [HookClass] 并绑定到 [appClassLoader]
|
||||
* [VariousClass] 转换为 [HookClass]
|
||||
* @param loader 当前 [ClassLoader] - 若留空使用默认 [ClassLoader]
|
||||
* @return [HookClass]
|
||||
*/
|
||||
@@ -403,17 +410,12 @@ open class PackageParam internal constructor(@PublishedApi internal var wrapper:
|
||||
}
|
||||
|
||||
/**
|
||||
* 将目标 [Class] 绑定到 [appClassLoader]
|
||||
*
|
||||
* - ❗请注意未绑定到 [appClassLoader] 的 [Class] 是不安全的 - 调用 [hook] 方法会根据设定自动绑定
|
||||
* [Class] 转换为 [HookClass]
|
||||
* @return [HookClass]
|
||||
*/
|
||||
@PublishedApi
|
||||
internal fun HookClass.bind() = try {
|
||||
name.clazz.hookClass
|
||||
} catch (e: Throwable) {
|
||||
HookClass(name = name, throwable = throwable ?: e)
|
||||
}
|
||||
internal val Class<*>.hookClass
|
||||
get() = HookClass(instance = this, name)
|
||||
|
||||
/**
|
||||
* 当前 Hook APP 的生命周期实例处理类
|
||||
|
@@ -180,7 +180,7 @@ object YukiHookBridge {
|
||||
* @return [Boolean] 是否存在
|
||||
*/
|
||||
private fun isMiuiCatcherPatch(packageName: String?) =
|
||||
(packageName == "com.miui.contentcatcher" || packageName == "com.miui.catcherpatch") && ("android.miui.R").hasClass
|
||||
(packageName == "com.miui.contentcatcher" || packageName == "com.miui.catcherpatch") && ("android.miui.R").hasClass()
|
||||
|
||||
/**
|
||||
* 当前包名是否已在指定的 [HookEntryType] 被装载
|
||||
|
Reference in New Issue
Block a user