Files
YukiHookAPI/docs/guide/move-to-new-api.md

255 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 从 Xposed API 迁移
> 若你熟悉 Xposed API你可以参考下方的相同点将自己的 API 快速迁移到 `YukiHookAPI`。
## 迁移 Hook 入口点
> 从 `XC_LoadPackage.LoadPackageParam` 迁移至 `PackageParam`。
`YukiHookAPI``PackageParam` 实现了 `lambda` 方法体 `this` 用法,在 `encase` 方法体内即可全局得到 `PackageParam` 对象。
> API 功能差异对比如下
<!-- tabs:start -->
#### **Yuki Hook API**
```kotlin
override fun onHook() = encase {
// 得到当前 Hook 的包名
packageName
// 得到当前 Hook 的 ApplicationInfo
appInfo
// 得到宿主 Application 生命周期
appContext
// Hook 指定的 APP
loadApp(name = "com.demo.test") {
// Class Hook
findClass("com.demo.test.TestClass").hook {
injectMember {
method {
name = "test"
param(BooleanType)
}
afterHook {
// ...
}
}
}
// Resources Hook (固定用法)
resources().hook {
injectResource {
conditions {
name = "ic_launcher"
mipmap()
}
replaceToModuleResource(R.mipmap.ic_launcher)
}
}
}
}
```
#### **Xposed API**
```kotlin
private lateinit var moduleResources: XModuleResources
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
// 得到当前 Hook 的包名
lpparam.packageName
// 得到当前 Hook 的 ApplicationInfo
lpparam.applicationInfo
// 得到宿主 Application 生命周期
AndroidAppHelper.currentApplication()
// Class Hook
if(lpparam.packageName == "com.demo.test")
XposedHelpers.findAndHookMethod("com.demo.test.TestClass", lpparam.classLoader, "test", Boolean::class.java, object : XC_MethodHook() {
override fun afterHookedMethod(param: MethodHookParam) {
// ...
}
})
}
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
// 得到当前 Hook 的包名
resparam.packageName
// 创建 Hook
resparam.res.setReplacement("com.demo.test", "mipmap", "ic_launcher", moduleResources.fwd(R.mipmap.ic_launcher))
}
```
<!-- tabs:end -->
## 迁移 Hook 方法体
> 从 `XC_MethodHook.MethodHookParam` 迁移至 `HookParam`。
### Before/After Hook
`YukiHookAPI` 同样对 `HookParam` 实现了 `lambda` 方法体 `this` 用法,在 `beforeHook``afterHook` 等方法体内即可全局得到 `HookParam` 对象。
> API 功能差异对比如下
<!-- tabs:start -->
#### **Yuki Hook API**
```kotlin
afterHook {
// 得到当前 Hook 的实例
instance
// 得到当前 Hook 的 Class 实例
instanceClass
// 得到并 cast 当前 Hook 的实例为指定类型 T
instance<T>()
// 得到方法参数数组
args
// 得到方法参数的第一位 T
args().first().cast<T>()
// 得到方法参数的最后一位 T
args().last().cast<T>()
// 得到方法参数的任意下标 T这里用 2 举例
args(index = 2).cast<T>()
// 设置方法参数的任意下标,这里用 2 举例
args(index = 2).set(...)
// 得到返回值
result
// 得到返回值并 cast 为 T
result<T>()
// 修改返回值内容
result = ...
// 删除返回值内容
resultNull()
// 向 Hook APP 抛出异常
Throwable("Fatal").throwToApp()
// 执行未经 Hook 的原始方法
method.invokeOriginal(...)
}
```
#### **Xposed API**
```kotlin
override fun afterHookedMethod(param: MethodHookParam) {
// 得到当前 Hook 的实例
param.thisObject
// 得到当前 Hook 的 Class 实例
param.thisObject.javaClass
// 得到并 cast 当前 Hook 的实例为指定类型 T
param.thisObject as T
// 得到方法参数数组
param.args
// 得到方法参数的第一位 T
param.args[0] as T
// 得到方法参数的最后一位 T
param.args[param.args.lastIndex] as T
// 得到方法参数的任意下标 T这里用 2 举例
param.args[2] as T
// 设置方法参数的任意下标,这里用 2 举例
param.args[2] = ...
// 得到返回值
param.result
// 得到返回值并 cast 为 T
param.result as T
// 修改返回值内容
param.result = ...
// 删除返回值内容
param.result = null
// 向 Hook APP 抛出异常
param.throwable = Throwable("Fatal")
// 执行未经 Hook 的原始方法
XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
}
```
<!-- tabs:end -->
### Replace Hook
`replaceHook` 方法比较特殊,`YukiHookAPI` 为它做出了多种形式以供选择。
> API 功能差异对比如下
<!-- tabs:start -->
#### **Yuki Hook API**
无返回值的方法 `void`
```kotlin
replaceUnit {
// 直接在这里实现被替换的逻辑
}
```
有返回值的方法。
```kotlin
replaceAny {
// 在这里实现被替换的逻辑
// ...
// 需要返回方法对应的返回值,无需写 return只需将参数放到最后一位
// 假设这个方法的返回值是 Int我们只需要保证最后一位是我们需要的返回值即可
0
}
```
有些方法我们只需替换其返回值,则有如下实现。
```kotlin
// 替换为你需要的返回值
replaceTo(...)
// 替换为 Boolean 类型的返回值
replaceToTrue()
// 拦截返回值
intercept()
```
!> 直接替换返回值的方法传入的参数是固定不变的,若想实现动态替换返回值请使用 `replaceAny` 方法体。
#### **Xposed API**
无返回值的方法 `void`
```kotlin
override fun replaceHookedMethod(param: MethodHookParam): Any? {
// 直接在这里实现被替换的逻辑
return null
}
```
有返回值的方法。
```kotlin
override fun replaceHookedMethod(param: MethodHookParam): Int {
// 在这里实现被替换的逻辑
// ...
// 假设这个方法的返回值是 Int
return 0
}
```
有些方法我们只需替换其返回值,则有如下实现。
```kotlin
// 替换为你需要的返回值
override fun replaceHookedMethod(param: MethodHookParam) = ...
// 替换为 Boolean 类型的返回值
override fun replaceHookedMethod(param: MethodHookParam) = true
// 拦截返回值
override fun replaceHookedMethod(param: MethodHookParam) = null
```
<!-- tabs:end -->
## 迁移其它功能
`YukiHookAPI` 对 Xposed API 进行了完全重写,你可以参考 [API 文档](api/home) 以及 [特色功能](guide/special-feature) 来决定一些功能性的迁移和使用。
<br/><br/>
[浏览下一篇 &nbsp;➡️](config/api-example.md)