diff --git a/README.md b/README.md
index 3cc1533d..35735c96 100644
--- a/README.md
+++ b/README.md
@@ -22,9 +22,9 @@
- [点击这里](https://fankes.github.io/YukiHookAPI) 前往文档页面查看更多详细教程和内容。
-> 你或许可能会遇到浏览器缓存造成文档不是最新版本的问题,若已经查看过一次文档,请手动在每个页面上刷新,以获取最新版本或清除浏览器缓存。
+> 你大概率会遇到浏览器缓存造成文档不是最新版本的问题,若已经查看过一次文档,请手动在每个页面上刷新一次以同步最新版本,或清除浏览器缓存。
-最新版本更新时间:2022-04-15 04:57
+最新版本更新时间:2022-04-15 14:56
## Contacts
diff --git a/docs/_coverpage.md b/docs/_coverpage.md
index ceb03768..0cdc9919 100644
--- a/docs/_coverpage.md
+++ b/docs/_coverpage.md
@@ -12,7 +12,7 @@
- 方便移植 快速上手
-`更新时间 2022-04-15 04:57`
+`更新时间 2022-04-15 14:56`
[GitHub](https://github.com/fankes/YukiHookAPI)
[Get Started](#介绍)
diff --git a/docs/_navbar.md b/docs/_navbar.md
index 9127d7c8..8b61fa1f 100644
--- a/docs/_navbar.md
+++ b/docs/_navbar.md
@@ -4,6 +4,7 @@
* [快速开始](guide/quick-start)
* [用法示例](guide/example)
* [特色功能](guide/special-feature)
+ * [从 Xposed API 迁移](guide/move-to-new-api)
* 配置
* [API 基本配置](config/api-example)
diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index 13fdeafa..4d089def 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -4,6 +4,7 @@
* [快速开始](guide/quick-start)
* [用法示例](guide/example)
* [特色功能](guide/special-feature)
+ * [从 Xposed API 迁移](guide/move-to-new-api)
* 配置
* [API 基本配置](config/api-example)
diff --git a/docs/config/api-exception.md b/docs/config/api-exception.md
index de673020..d716f46d 100644
--- a/docs/config/api-exception.md
+++ b/docs/config/api-exception.md
@@ -359,17 +359,38 @@ method {
异常原因
-使用 `ModuleApplication` 时调用了 `appContext` 功能但是 APP 可能已经被销毁或没有正确启动。
+> 第一种情况
+
+在被 Hook 的宿主内调用了 `ModuleApplication` 的 `appContext`。
+
+> 示例如下
+
+```kotlin
+encase {
+ // 调用了此变量
+ ModuleApplication.appContext...
+}
+```
+
+> 第二种情况
+
+使用 `ModuleApplication` 时调用了 `appContext` 但是 APP 可能已经被销毁或没有正确启动。
> 示例如下
```kotlin
// 调用了此变量但是 APP 可能已被销毁或没有正确启动
-ModuleApplication.appContext
+ModuleApplication.appContext...
```
解决方案
+> 第一种情况
+
+你只能在模块内使用 `ModuleApplication` 的 `appContext`,在宿主内请使用 `PackageParam` 中的 `appContext`,请确认你使用的是否正确。
+
+> 第二种情况
+
这种情况基本不存在,由于 `appContext` 是在 `onCreate` 中被赋值的,除非遇到多进程并发启动或 APP 没有启动完成前被反射调用了父类的 `onCreate` 方法。
!> `IllegalStateException` YukiHookModulePrefs not allowed in Custom Hook API
diff --git a/docs/config/r8-proguard.md b/docs/config/r8-proguard.md
index 561f6dfc..d0753c38 100644
--- a/docs/config/r8-proguard.md
+++ b/docs/config/r8-proguard.md
@@ -8,18 +8,18 @@
## Proguard
-> 如果你仍然在使用 `Proguard`,你需要做一些规则配置。
+> ~~如果你仍然在使用 `Proguard`,你需要做一些规则配置。~~
-在 `proguard-rules.pro` 添加如下代码即可。
+~~在 `proguard-rules.pro` 添加如下代码即可。~~
-> 示例如下
+> ~~示例如下~~
```proguard
-keep class com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus {*;}
-keep class 这里填你的 HookEntryClass 入口类完整包名_YukiHookXposedInit {*;}
```
-!> 自从 Android Gradle Plugin 4.2 后,拥有 Android Jetpack 套件最新版本的混淆处理程序默认均为 `R8`,基本可以不需要考虑混淆的问题。
+!> Proguard 规则已被弃用,请不要再使用,自从 Android Gradle Plugin 4.2 后,拥有 Android Jetpack 套件最新版本的混淆处理程序默认均为 `R8`,基本可以不需要考虑混淆的问题。
若要在任何版本下启用 `R8`,请在 `gradle.properties` 文件中加入如下规则,Android Gradle Plugin 7.0 及以上版本无需任何配置。
diff --git a/docs/guide/move-to-new-api.md b/docs/guide/move-to-new-api.md
new file mode 100644
index 00000000..775c3742
--- /dev/null
+++ b/docs/guide/move-to-new-api.md
@@ -0,0 +1,221 @@
+# 从 Xposed API 迁移
+
+> 若你熟悉 Xposed API,你可以参考下方的相同点将自己的 API 快速迁移到 `YukiHookAPI`。
+
+## 迁移 Hook 入口点
+
+> 从 `XC_LoadPackage.LoadPackageParam` 迁移至 `PackageParam`。
+
+`YukiHookAPI` 对 `PackageParam` 实现了 `lambda` 方法体 `this` 用法,在 `encase` 方法体内即可全局得到 `PackageParam` 对象。
+
+> API 功能差异对比如下
+
+
+
+#### **Yuki Hook API**
+
+```kotlin
+override fun onHook() = encase {
+ // 得到当前 Hook 的包名
+ packageName
+ // 得到当前 Hook 的 ApplicationInfo
+ appInfo
+ // 得到宿主 Application 生命周期
+ appContext
+ // 创建 Hook
+ findClass("com.demo.Test").hook {
+ injectMember {
+ method {
+ name = "test"
+ param(BooleanType)
+ }
+ afterHook {
+ // ...
+ }
+ }
+ }
+}
+```
+
+#### **Xposed API**
+
+```kotlin
+override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
+ // 得到当前 Hook 的包名
+ lpparam.packageName
+ // 得到当前 Hook 的 ApplicationInfo
+ lpparam.applicationInfo
+ // 得到宿主 Application 生命周期
+ AndroidAppHelper.currentApplication()
+ // 创建 Hook
+ XposedHelpers.findAndHookMethod("com.demo.Test", lpparam.classLoader, "test", Boolean::class.java, object : XC_MethodHook() {
+ override fun afterHookedMethod(param: MethodHookParam) {
+ // ...
+ }
+ })
+}
+```
+
+
+
+## 迁移 Hook 方法体
+
+> 从 `XC_MethodHook.MethodHookParam` 迁移至 `HookParam`。
+
+### Before/After Hook
+
+`YukiHookAPI` 同样对 `HookParam` 实现了 `lambda` 方法体 `this` 用法,在 `beforeHook`、`afterHook` 等方法体内即可全局得到 `HookParam` 对象。
+
+> API 功能差异对比如下
+
+
+
+#### **Yuki Hook API**
+
+```kotlin
+afterHook {
+ // 得到当前 Hook 的实例
+ instance
+ // 得到当前 Hook 的 Class 实例
+ instanceClass
+ // 得到并 cast 当前 Hook 的实例为指定类型 T
+ instance()
+ // 得到方法参数数组
+ args
+ // 得到方法参数的第一位 T
+ args().first().cast()
+ // 得到方法参数的最后一位 T
+ args().last().cast()
+ // 得到方法参数的任意下标 T,这里用 2 举例
+ args(index = 2).cast()
+ // 设置方法参数的任意下标,这里用 2 举例
+ args(index = 2).set(...)
+ // 得到返回值
+ result
+ // 得到返回值并 cast 为 T
+ result()
+ // 修改返回值内容
+ result = ...
+ // 删除返回值内容
+ resultNull()
+ // 执行未经 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 的原始方法
+ XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
+}
+```
+
+
+
+### Replace Hook
+
+`replaceHook` 方法比较特殊,`YukiHookAPI` 为它做出了多种形式以供选择。
+
+> API 功能差异对比如下
+
+
+
+#### **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
+```
+
+
+
+## 迁移其它功能
+
+`YukiHookAPI` 对 Xposed API 进行了完全重写,你可以参考 [API 文档](api/home) 以及 [特色功能](guide/special-feature) 来决定一些功能性的迁移和使用。
\ No newline at end of file
diff --git a/docs/guide/quick-start.md b/docs/guide/quick-start.md
index 9001a241..c9cc754d 100644
--- a/docs/guide/quick-start.md
+++ b/docs/guide/quick-start.md
@@ -112,6 +112,8 @@ class MainHook : YukiHookXposedInitProxy {
有关作为 Xposed 模块使用的相关配置详细内容,你可以 [点击这里](config/xposed-using) 继续阅读。
+若你目前正在使用 Xposed API,你可以参考 [从 Xposed API 迁移](guide/move-to-new-api)。
+
## 作为 Hook API 使用
### 集成方式