跳转到内容

yukihook-extension-kavaref ​

Maven CentralMaven metadata URLAndroid Min SDK

这是 YukiHook 对 KavaRef 相关功能的扩展依赖。

配置依赖 ​

你可以使用如下方式将此模块添加到你的项目中。

我们推荐你优先参考 yukihook-bom 使用 BOM 统一管理版本。

在你的项目 gradle/libs.versions.toml 中添加依赖。

toml
[versions]
yukihook-extension-kavaref = "<version>"
kavaref-bom = "<kavaref-version>"

[libraries]
yukihook-extension-kavaref = { module = "com.highcapable.yukihookapi:yukihook-extension-kavaref", version.ref = "yukihook-extension-kavaref" }
kavaref-bom = { module = "com.highcapable.kavaref:kavaref-bom", version.ref = "kavaref-bom" }
kavaref-core = { module = "com.highcapable.kavaref:kavaref-core" }
kavaref-android = { module = "com.highcapable.kavaref:kavaref-android" }
kavaref-extension = { module = "com.highcapable.kavaref:kavaref-extension" }

在你的项目 build.gradle.kts 中配置依赖。

kotlin
implementation(libs.yukihook.extension.kavaref)

implementation(platform(libs.kavaref.bom))
implementation(libs.kavaref.core)
implementation(libs.kavaref.android)
implementation(libs.kavaref.extension)

请将 <version> 修改为此文档顶部显示的版本,并将 <kavaref-version> 修改为 这里 的最新版本。

传统方式 ​

在你的项目 build.gradle.kts 中配置依赖。

kotlin
implementation("com.highcapable.yukihookapi:yukihook-extension-kavaref:<version>")

implementation(platform("com.highcapable.kavaref:kavaref-bom:<kavaref-version>"))
implementation("com.highcapable.kavaref:kavaref-core")
implementation("com.highcapable.kavaref:kavaref-android")
implementation("com.highcapable.kavaref:kavaref-extension")

请将 <version> 修改为此文档顶部显示的版本,并将 <kavaref-version> 修改为 这里 的最新版本。

特别注意

此模块不会自动装配 KavaRef 的依赖,请按照上方的方式自行引入 KavaRef。

功能介绍 ​

你可以 点击这里 查看 KDoc。

此模块为 KavaRef 提供了在 PackageParam 中使用的扩展方法,详细的用法请参考 这里,这将跳转到 KavaRef 的文档。

特别注意

这些扩展方法只能在 PackageParam 中使用,由于存在与 KavaRef 同名的扩展,请一定确保导入的是 com.highcapable.yukihookapi.extension.kavaref 下对应的方法。

Hook 用法 ​

你可以直接对 KavaRef 的 MemberResolver 使用 hook、hookAll、intercept 以及 interceptAll。

示例如下

kotlin
loadApp("io.github.myapp") {
    "$packageName.MainActivity".toClass()
        .resolve()
        .firstMethod {
            name = "onCreate"
            parameters(Bundle::class)
        }.hook {
            // Your code here.
        }
}

它们的用法与对 Member 使用时完全一致,详情请参考 Hook 用法。

你还可以使用 deoptimize 与 deoptimizeAll,详情请参考 解除内联化。

小提示

在 模块热重载 → 保留数据 中,由于 MemberResolver 对象强引用模块的 ClassLoader,你不能直接对它进行缓存。

此时你可以取出其中的 self,像下方这样使用。

示例如下

kotlin
// 单个方法
val foo = remember("myapp-foo-v1") {
    "$packageName.Demo".toClass()
        .resolve()
        .optional()
        .firstMethodOrNull {
            name = "foo"
            emptyParameters()
        }?.self
}
// 一组方法
val bar = remember("myapp-bar-v1") {
    "$packageName.Demo".toClass()
        .resolve()
        .optional()
        .method {
            name = "bar"
            parameterCount { it in 0..1 }
        }.map { it.self }
}

foo?.hook {
    // Your code here.
}
bar.hookAll {
    // Your code here.
}

原始与特殊调用 ​

你可以使用 KavaRef 的 MethodResolver 与 ConstructorResolver 调用未经 Hook 的原始方法与构造方法。

示例如下

kotlin
loadApp("io.github.myapp") {
    // 假设这就是 Demo 类的实例
    val instance: Any
    "$packageName.Demo".toClass()
        .resolve()
        .firstMethod {
            name = "foo"
            emptyParameters()
        }.of(instance).invokeOriginal()
}
方法说明
invokeOriginal调用未经 Hook 的原始方法
*invokeSpecial非虚调用方法,需要先使用 of 设置实例
initializeSpecial使用构造方法非虚初始化一个已经存在的实例
*createOriginal使用未经 Hook 的原始构造方法创建实例
*createSpecial使用父类构造方法创建子类实例,子类的构造方法不会被调用

以上方法均提供了带有 Quietly 后缀的版本,它们将忽略调用过程中的异常并返回 null。

特别注意

上述标有 * 的方法需要 yukihook-runtime-libxposed 底座支持。

装载宿主中的类 ​

在 PackageParam 中,下方的同名扩展会默认使用 hostClassLoader 装载 Class。

  • String.toClass()
  • String.toClassOrNull()
  • VariousClass.toClass()
  • VariousClass.toClassOrNull()
  • lazyClass(...)
  • lazyClassOrNull(...)

示例如下

kotlin
val DemoClass by lazyClass("io.github.myapp.Demo")

loadApp("io.github.myapp") {
    "$packageName.Demo".toClass()
    VariousClass("$packageName.Demo", "$packageName.NewDemo").toClass()
}

隐藏 API 绕过解析器 ​

YukiHook 提供了 AndroidHiddenApiBypassResolver,你可以在需要反射系统隐藏 API 的地方使用它。

它复刻自 KavaRef 文档的 AndroidHiddenApiBypassResolver。

示例如下

kotlin
val resolver = AndroidHiddenApiBypassResolver()

"android.app.ActivityThread".toClass()
    .resolve()
    // 设置自定义 Member 解析器
    .processor(resolver)
    .firstMethod {
        name = "currentActivityThread"
        emptyParameters()
    }.invoke()

基于 Apache-2.0 许可发布