mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 17:55:24 +08:00
Update document file
This commit is contained in:
20
README.md
20
README.md
@@ -11,14 +11,6 @@
|
|||||||
⛱️ An efficient Kotlin version of the Xposed Hook API.
|
⛱️ An efficient Kotlin version of the Xposed Hook API.
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
## Plan is in progress
|
|
||||||
|
|
||||||
> `IXposedHookInitPackageResources` and `IXposedHookZygoteInit` are being adapted recently,let's stay tuned
|
|
||||||
|
|
||||||
**计划进行中**
|
|
||||||
|
|
||||||
> 近期正在适配 `IXposedHookInitPackageResources`、`IXposedHookZygoteInit` 敬请期待
|
|
||||||
|
|
||||||
## What's this
|
## What's this
|
||||||
|
|
||||||
- This is an efficient Xposed Hook API rebuilt in Kotlin
|
- This is an efficient Xposed Hook API rebuilt in Kotlin
|
||||||
@@ -31,6 +23,18 @@
|
|||||||
- 名称取自 [《ももくり》女主 栗原 雪(Yuki)](https://www.bilibili.com/bangumi/play/ss5016)
|
- 名称取自 [《ももくり》女主 栗原 雪(Yuki)](https://www.bilibili.com/bangumi/play/ss5016)
|
||||||
- 前身为 [开发学习项目](https://github.com/fankes/TMore) 中使用的 Innocent Xposed API,现在重新命名并开源
|
- 前身为 [开发学习项目](https://github.com/fankes/TMore) 中使用的 Innocent Xposed API,现在重新命名并开源
|
||||||
|
|
||||||
|
## Supports
|
||||||
|
|
||||||
|
- Standard Hook
|
||||||
|
- Zygote Hook
|
||||||
|
- Resources Hook
|
||||||
|
|
||||||
|
**支持的功能**
|
||||||
|
|
||||||
|
- 标准 Hook
|
||||||
|
- Zygote Hook
|
||||||
|
- 资源钩子(Resources Hook)
|
||||||
|
|
||||||
## Get Started
|
## Get Started
|
||||||
|
|
||||||
- [Click here](https://fankes.github.io/YukiHookAPI) go to the documentation page for more detailed tutorials and content.
|
- [Click here](https://fankes.github.io/YukiHookAPI) go to the documentation page for more detailed tutorials and content.
|
||||||
|
@@ -26,15 +26,7 @@
|
|||||||
|
|
||||||
目前 API 只支持通过自动处理程序绑定到 `xposed_init`,若您不喜欢自动处理程序,一定要自己实现模块装载入口,未来会按照需求人数推出仅有 API 功能的 Lite 版本。
|
目前 API 只支持通过自动处理程序绑定到 `xposed_init`,若您不喜欢自动处理程序,一定要自己实现模块装载入口,未来会按照需求人数推出仅有 API 功能的 Lite 版本。
|
||||||
|
|
||||||
### 支持资源 Hook 和注入系统框架
|
API 已经提供了 Xposed 原生 API 监听接口,你可以 [在这里](config/xposed-using?id=原生-xposed-api-事件) 找到或查看 Demo 的实现方法。
|
||||||
|
|
||||||
**计划状态:近期**
|
|
||||||
|
|
||||||
目前的 API 仅支持 APP 内的功能 Hook,并不支持 `Resource` 的替换以及 Hook 系统框架。
|
|
||||||
|
|
||||||
API 还未实现对 `handleInitPackageResources` 和 `initZygote` 的调用。
|
|
||||||
|
|
||||||
在未来会根据使用和需求人数加上这个功能,如有需求你也可以向我们提交 Pull Request 来贡献你的代码。
|
|
||||||
|
|
||||||
### 支持更多 Hook Framework
|
### 支持更多 Hook Framework
|
||||||
|
|
||||||
|
@@ -22,6 +22,14 @@
|
|||||||
|
|
||||||
[filename](public/ModuleApplication.md ':include')
|
[filename](public/ModuleApplication.md ':include')
|
||||||
|
|
||||||
|
[filename](public/YukiModuleResources.md ':include')
|
||||||
|
|
||||||
|
[filename](public/YukiResources.md ':include')
|
||||||
|
|
||||||
|
[filename](public/YukiResForwarder.md ':include')
|
||||||
|
|
||||||
|
[filename](public/YukiXposedEvent.md ':include')
|
||||||
|
|
||||||
[filename](public/ComponentTypeFactory.md ':include')
|
[filename](public/ComponentTypeFactory.md ':include')
|
||||||
|
|
||||||
[filename](public/GraphicsTypeFactory.md ':include')
|
[filename](public/GraphicsTypeFactory.md ':include')
|
||||||
@@ -38,7 +46,9 @@
|
|||||||
|
|
||||||
[filename](public/YukiBaseHooker.md ':include')
|
[filename](public/YukiBaseHooker.md ':include')
|
||||||
|
|
||||||
[filename](public/YukiHookCreater.md ':include')
|
[filename](public/YukiMemberHookCreater.md ':include')
|
||||||
|
|
||||||
|
[filename](public/YukiResourcesHookCreater.md ':include')
|
||||||
|
|
||||||
[filename](public/MethodFinder.md ':include')
|
[filename](public/MethodFinder.md ':include')
|
||||||
|
|
||||||
@@ -54,4 +64,6 @@
|
|||||||
|
|
||||||
[filename](public/VariousClass.md ':include')
|
[filename](public/VariousClass.md ':include')
|
||||||
|
|
||||||
[filename](public/CurrentClass.md ':include')
|
[filename](public/CurrentClass.md ':include')
|
||||||
|
|
||||||
|
[filename](public/HookResources.md ':include')
|
@@ -1,7 +1,7 @@
|
|||||||
## ConstructorFinder [class]
|
## ConstructorFinder [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class ConstructorFinder(override val hookInstance: YukiHookCreater.MemberHookCreater?, override val classSet: Class<*>) : BaseFinder()
|
class ConstructorFinder(override val hookInstance: YukiMemberHookCreater.MemberHookCreater?, override val classSet: Class<*>) : BaseFinder()
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -112,6 +112,22 @@ fun paramCount(num: Int): IndexTypeCondition
|
|||||||
|
|
||||||
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
|
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
|
||||||
|
|
||||||
|
### superClass [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun superClass(isOnlySuperClass: Boolean)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置在 `classSet` 的所有父类中查找当前 `Constructor`。
|
||||||
|
|
||||||
|
!> 若当前 `classSet` 的父类较多可能会耗时,API 会自动循环到父类继承是 `Any` 前的最后一个类。
|
||||||
|
|
||||||
### RemedyPlan [class]
|
### RemedyPlan [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
## CurrentClass [class]
|
## CurrentClass [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class CurrentClass(private val instance: Class<*>, private val self: Any)
|
class CurrentClass(internal val instance: Class<*>, internal val self: Any)
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -12,10 +12,24 @@ class CurrentClass(private val instance: Class<*>, private val self: Any)
|
|||||||
|
|
||||||
> 当前实例的类操作对象。
|
> 当前实例的类操作对象。
|
||||||
|
|
||||||
|
### superClass [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun superClass(): SuperClass
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 调用父类实例。
|
||||||
|
|
||||||
### field [method]
|
### field [method]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
fun field(initiate: FieldFinder.() -> Unit): FieldFinder.Result.Instance
|
inline fun field(initiate: FieldFinder.() -> Unit): FieldFinder.Result.Instance
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -29,7 +43,7 @@ fun field(initiate: FieldFinder.() -> Unit): FieldFinder.Result.Instance
|
|||||||
### method [method]
|
### method [method]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
fun method(initiate: MethodFinder.() -> Unit): MethodFinder.Result.Instance
|
inline fun method(initiate: MethodFinder.() -> Unit): MethodFinder.Result.Instance
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -38,4 +52,46 @@ fun method(initiate: MethodFinder.() -> Unit): MethodFinder.Result.Instance
|
|||||||
|
|
||||||
**功能描述**
|
**功能描述**
|
||||||
|
|
||||||
> 调用当前实例中的方法。
|
> 调用当前实例中的方法。
|
||||||
|
|
||||||
|
### SuperClass [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inner class SuperClass
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 当前类的父类实例的类操作对象。
|
||||||
|
|
||||||
|
#### field [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun field(initiate: FieldFinder.() -> Unit): FieldFinder.Result.Instance
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 调用父类实例中的变量。
|
||||||
|
|
||||||
|
#### method [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun method(initiate: MethodFinder.() -> Unit): MethodFinder.Result.Instance
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 调用父类实例中的方法。
|
@@ -1,7 +1,7 @@
|
|||||||
## FieldFinder [class]
|
## FieldFinder [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class FieldFinder(override val hookInstance: YukiHookCreater.MemberHookCreater?, override val classSet: Class<*>?) : BaseFinder()
|
class FieldFinder(override val hookInstance: YukiMemberHookCreater.MemberHookCreater?, override val classSet: Class<*>?) : BaseFinder()
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -132,6 +132,22 @@ fun type(value: Any): IndexTypeCondition
|
|||||||
|
|
||||||
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
|
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
|
||||||
|
|
||||||
|
### superClass [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun superClass(isOnlySuperClass: Boolean)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置在 `classSet` 的所有父类中查找当前 `Field`。
|
||||||
|
|
||||||
|
!> 若当前 `classSet` 的父类较多可能会耗时,API 会自动循环到父类继承是 `Any` 前的最后一个类。
|
||||||
|
|
||||||
### Result [class]
|
### Result [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
## HookParam [class]
|
## HookParam [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class HookParam(private val createrInstance: YukiHookCreater, private val wrapper: HookParamWrapper)
|
class HookParam(private val createrInstance: YukiMemberHookCreater, private var wrapper: HookParamWrapper?)
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
|
13
docs/api/public/HookResources.md
Normal file
13
docs/api/public/HookResources.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
## HookResources [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
class HookResources(var instance: YukiResources?)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 创建一个当前 Hook 的 `YukiResources` 接管类。
|
@@ -48,4 +48,42 @@ fun onHook()
|
|||||||
|
|
||||||
**功能描述**
|
**功能描述**
|
||||||
|
|
||||||
> Xposed API 的模块装载调用入口方法。
|
> Xposed API 的模块装载调用入口方法。
|
||||||
|
|
||||||
|
### onXposedEvent [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun onXposedEvent()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 监听 Xposed 原生装载事件。
|
||||||
|
|
||||||
|
若你的 Hook 事件中存在需要兼容的原生 Xposed 功能,可在这里实现。
|
||||||
|
|
||||||
|
请在这里使用 `YukiXposedEvent` 创建回调事件监听。
|
||||||
|
|
||||||
|
可监听的事件如下:
|
||||||
|
|
||||||
|
`YukiXposedEvent.onInitZygote`
|
||||||
|
|
||||||
|
`YukiXposedEvent.onHandleLoadPackage`
|
||||||
|
|
||||||
|
`YukiXposedEvent.onHandleInitPackageResources`
|
||||||
|
|
||||||
|
!> 此接口仅供监听和实现原生 Xposed API 的功能,请不要在这里操作 `YukiHookAPI`。
|
||||||
|
|
||||||
|
## ~~YukiHookXposedInitProxy [interface]~~ <!-- {docsify-ignore} -->
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0` `添加`
|
||||||
|
|
||||||
|
`v1.0.80` `作废`
|
||||||
|
|
||||||
|
请转移到 `IYukiHookXposedInit`
|
@@ -1,7 +1,7 @@
|
|||||||
## MethodFinder [class]
|
## MethodFinder [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class MethodFinder(override val hookInstance: YukiHookCreater.MemberHookCreater?, override val classSet: Class<*>) : BaseFinder()
|
class MethodFinder(override val hookInstance: YukiMemberHookCreater.MemberHookCreater?, override val classSet: Class<*>) : BaseFinder()
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -196,6 +196,22 @@ fun returnType(value: Any): IndexTypeCondition
|
|||||||
|
|
||||||
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
|
!> 存在多个 `IndexTypeCondition` 时除了 `order` 只会生效最后一个。
|
||||||
|
|
||||||
|
### superClass [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun superClass(isOnlySuperClass: Boolean)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置在 `classSet` 的所有父类中查找当前 `Method`。
|
||||||
|
|
||||||
|
!> 若当前 `classSet` 的父类较多可能会耗时,API 会自动循环到父类继承是 `Any` 前的最后一个类。
|
||||||
|
|
||||||
### RemedyPlan [class]
|
### RemedyPlan [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
## PackageParam [class]
|
## PackageParam [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
open class PackageParam(private var wrapper: PackageParamWrapper?)
|
open class PackageParam(internal var wrapper: PackageParamWrapper?)
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -54,6 +54,24 @@ val appContext: Application
|
|||||||
|
|
||||||
> 获取当前 Hook APP 的 `Application`。
|
> 获取当前 Hook APP 的 `Application`。
|
||||||
|
|
||||||
|
!> 首次装载可能是空的,请延迟一段时间再获取。
|
||||||
|
|
||||||
|
### appResources [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val appResources:Resources
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获取当前 Hook APP 的 Resources。
|
||||||
|
|
||||||
|
!> 你只能在 `HookResources.hook` 方法体内或 `appContext` 装载完毕时进行调用。
|
||||||
|
|
||||||
### processName [field]
|
### processName [field]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@@ -112,6 +130,38 @@ val mainProcessName: String
|
|||||||
|
|
||||||
其对应的就是 `packageName`。
|
其对应的就是 `packageName`。
|
||||||
|
|
||||||
|
### moduleAppFilePath [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val moduleAppFilePath: String
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获取当前 Xposed 模块自身 APK 文件路径。
|
||||||
|
|
||||||
|
!> 作为 Hook API 装载时无法使用,会获取到空字符串。
|
||||||
|
|
||||||
|
### moduleAppResources [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val moduleAppResources: YukiModuleResources
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获取当前 Xposed 模块自身 `Resources`。
|
||||||
|
|
||||||
|
!> 作为 Hook API 或不支持的 Hook Framework 装载时无法使用,会抛出异常。
|
||||||
|
|
||||||
### prefs [field]
|
### prefs [field]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@@ -126,6 +176,8 @@ val prefs: YukiHookModulePrefs
|
|||||||
|
|
||||||
> 获得当前使用的存取数据对象缓存实例。
|
> 获得当前使用的存取数据对象缓存实例。
|
||||||
|
|
||||||
|
!> 作为 Hook API 装载时无法使用,会抛出异常。
|
||||||
|
|
||||||
### prefs [method]
|
### prefs [method]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@@ -146,6 +198,24 @@ fun prefs(name: String): YukiHookModulePrefs
|
|||||||
|
|
||||||
你可以通过 `name` 来自定义 Sp 存储的名称。
|
你可以通过 `name` 来自定义 Sp 存储的名称。
|
||||||
|
|
||||||
|
!> 作为 Hook API 装载时无法使用,会抛出异常。
|
||||||
|
|
||||||
|
### resources [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun resources(): HookResources
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获得当前 Hook APP 的 `YukiResources` 对象。
|
||||||
|
|
||||||
|
请调用 `HookResources.hook` 方法开始 Hook。
|
||||||
|
|
||||||
### loadApp [method]
|
### loadApp [method]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@@ -170,6 +240,28 @@ fun loadApp(name: String, hooker: YukiBaseHooker)
|
|||||||
|
|
||||||
`name` 为 APP 的包名,后方的两个参数一个可作为 `lambda` 方法体使用,一个可以直接装载子 Hooker。
|
`name` 为 APP 的包名,后方的两个参数一个可作为 `lambda` 方法体使用,一个可以直接装载子 Hooker。
|
||||||
|
|
||||||
|
装载并 Hook 指定、全部包名的 APP,若要 Hook 系统框架,请使用 `loadZygote`。
|
||||||
|
|
||||||
|
### loadZygote [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun loadZygote(initiate: PackageParam.() -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun loadZygote(hooker: YukiBaseHooker)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 装载并 Hook 系统框架。
|
||||||
|
|
||||||
|
方法中的两个参数一个可作为 `lambda` 方法体使用,一个可以直接装载子 Hooker。
|
||||||
|
|
||||||
### withProcess [method]
|
### withProcess [method]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@@ -331,19 +423,19 @@ val variousClass = VariousClass("com.example.demo.DemoClass1", "com.example.demo
|
|||||||
### hook [method]
|
### hook [method]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
inline fun String.hook(isUseAppClassLoader: Boolean, initiate: YukiHookCreater.() -> Unit): YukiHookCreater.Result
|
inline fun String.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||||
```
|
```
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
inline fun Class<*>.hook(isUseAppClassLoader: Boolean, initiate: YukiHookCreater.() -> Unit): YukiHookCreater.Result
|
inline fun Class<*>.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||||
```
|
```
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
inline fun VariousClass.hook(isUseAppClassLoader: Boolean, initiate: YukiHookCreater.() -> Unit): YukiHookCreater.Result
|
inline fun VariousClass.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||||
```
|
```
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
inline fun HookClass.hook(isUseAppClassLoader: Boolean, initiate: YukiHookCreater.() -> Unit): YukiHookCreater.Result
|
inline fun HookClass.hook(isUseAppClassLoader: Boolean, initiate: YukiMemberHookCreater.() -> Unit): YukiMemberHookCreater.Result
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -360,7 +452,7 @@ inline fun HookClass.hook(isUseAppClassLoader: Boolean, initiate: YukiHookCreate
|
|||||||
|
|
||||||
`v1.0.3` `修改`
|
`v1.0.3` `修改`
|
||||||
|
|
||||||
新增 `YukiHookCreater.Result` 返回值
|
新增 `YukiMemberHookCreater.Result` 返回值
|
||||||
|
|
||||||
`v1.0.70` `修改`
|
`v1.0.70` `修改`
|
||||||
|
|
||||||
@@ -443,4 +535,34 @@ findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
|
|||||||
YourClass.hook(isUseAppClassLoader = false) {
|
YourClass.hook(isUseAppClassLoader = false) {
|
||||||
// Your code here.
|
// Your code here.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### hook [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun HookResources.hook(initiate: YukiResourcesHookCreater.() -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> Hook APP 的 Resources。
|
||||||
|
|
||||||
|
**功能示例**
|
||||||
|
|
||||||
|
Resources Hook 为固定用法,获取 `resources` 对象,然后调用 `hook` 方法开始 Hook。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
resources().hook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
!> 这是固定用法,为了防止发生问题,你不可手动实现任何 `HookResources` 实例执行 `hook` 调用。
|
||||||
|
|
||||||
|
将 Resources 的 Hook 设置为这样是为了与 `findClass(...).hook` 做到统一,使得调用起来逻辑不会混乱。
|
@@ -8,6 +8,34 @@
|
|||||||
|
|
||||||
> 这是自定义 `Member` 和 `Class` 相关功能的查找匹配以及 `invoke` 的封装类。
|
> 这是自定义 `Member` 和 `Class` 相关功能的查找匹配以及 `invoke` 的封装类。
|
||||||
|
|
||||||
|
### hookClass [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val Class<*>.hookClass: HookClass
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0` `添加`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 将 `Class` 转换为 `HookClass`。
|
||||||
|
|
||||||
|
### normalClass [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val HookClass.normalClass: Class<*>?
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0` `添加`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 将 `HookClass` 转换为 `Class`。
|
||||||
|
|
||||||
### hasClass [field]
|
### hasClass [field]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@@ -36,33 +64,19 @@ if("com.example.demo.DemoClass".hasClass) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### hookClass [field]
|
### hasExtends [field]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
val Class<*>.hookClass: HookClass
|
val Class<*>.hasExtends: Boolean
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
|
|
||||||
`v1.0` `添加`
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
**功能描述**
|
**功能描述**
|
||||||
|
|
||||||
> 将 `Class` 转换为 `HookClass`。
|
> 当前 `Class` 是否有继承关系,父类是 `Any` 将被认为没有继承关系。
|
||||||
|
|
||||||
### normalClass [field]
|
|
||||||
|
|
||||||
```kotlin
|
|
||||||
val HookClass.normalClass: Class<*>?
|
|
||||||
```
|
|
||||||
|
|
||||||
**变更记录**
|
|
||||||
|
|
||||||
`v1.0` `添加`
|
|
||||||
|
|
||||||
**功能描述**
|
|
||||||
|
|
||||||
> 将 `HookClass` 转换为 `Class`。
|
|
||||||
|
|
||||||
### classOf [method]
|
### classOf [method]
|
||||||
|
|
||||||
|
@@ -50,7 +50,21 @@ fun IYukiHookXposedInit.encase(vararg hooker: YukiBaseHooker)
|
|||||||
|
|
||||||
**功能描述**
|
**功能描述**
|
||||||
|
|
||||||
> 在 `IYukiHookXposedInit` 中装载 `YukiHookAPI`。
|
> 在 `IYukiHookXposedInit` 中调用 `YukiHookAPI`。
|
||||||
|
|
||||||
|
### resources [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun IYukiHookXposedInit.resources(initiate: ResourcesParam.() -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 在 `IYukiHookXposedInit` 中调用 `YukiHookAPI.resources`。
|
||||||
|
|
||||||
### modulePrefs [field]
|
### modulePrefs [field]
|
||||||
|
|
||||||
@@ -94,6 +108,20 @@ val Context.processName: String
|
|||||||
|
|
||||||
> 获取当前进程名称。
|
> 获取当前进程名称。
|
||||||
|
|
||||||
|
### isSupportResourcesHook [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val Any?.isSupportResourcesHook: Boolean
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 判断当前 Hook Framework 是否支持资源钩子(Resources Hook)。
|
||||||
|
|
||||||
### isModuleActive [field]
|
### isModuleActive [field]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
## YukiHookCreater [class]
|
## YukiMemberHookCreater [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class YukiHookCreater(private val packageParam: PackageParam, internal val hookClass: HookClass)
|
class YukiMemberHookCreater(private val packageParam: PackageParam, internal val hookClass: HookClass)
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -14,7 +14,49 @@ class YukiHookCreater(private val packageParam: PackageParam, internal val hookC
|
|||||||
|
|
||||||
**功能描述**
|
**功能描述**
|
||||||
|
|
||||||
> `YukiHookAPI` 核心 Hook 实现类。
|
> `YukiHookAPI` 的 `Member` 核心 Hook 实现类。
|
||||||
|
|
||||||
|
### PRIORITY_DEFAULT [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val PRIORITY_DEFAULT: Int
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 默认 Hook 回调优先级。
|
||||||
|
|
||||||
|
### PRIORITY_LOWEST [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val PRIORITY_LOWEST: Int
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 延迟回调 Hook 方法结果。
|
||||||
|
|
||||||
|
### PRIORITY_HIGHEST [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val PRIORITY_HIGHEST: Int
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 更快回调 Hook 方法结果。
|
||||||
|
|
||||||
### instanceClass [field]
|
### instanceClass [field]
|
||||||
|
|
||||||
@@ -39,7 +81,7 @@ val instanceClass: Class<*>
|
|||||||
### injectMember [method]
|
### injectMember [method]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
inline fun injectMember(tag: String, initiate: MemberHookCreater.() -> Unit): MemberHookCreater.Result
|
inline fun injectMember(priority: Int, tag: String, initiate: MemberHookCreater.() -> Unit): MemberHookCreater.Result
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
@@ -50,6 +92,8 @@ inline fun injectMember(tag: String, initiate: MemberHookCreater.() -> Unit): Me
|
|||||||
|
|
||||||
将方法体进行 inline
|
将方法体进行 inline
|
||||||
|
|
||||||
|
增加 `priority` Hook 优先级
|
||||||
|
|
||||||
**功能描述**
|
**功能描述**
|
||||||
|
|
||||||
> 注入要 Hook 的方法、构造类。
|
> 注入要 Hook 的方法、构造类。
|
||||||
@@ -76,16 +120,30 @@ injectMember(tag = "KuriharaYuki") {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
你还可以自定义 `priority`,以控制当前 Hook 对象并列执行的优先级速度。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectMember(priority = PRIORITY_HIGHEST) {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### MemberHookCreater [class]
|
### MemberHookCreater [class]
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
inner class MemberHookCreater(var tag: String)
|
inner class MemberHookCreater(private val priority: Int, internal val tag: String)
|
||||||
```
|
```
|
||||||
|
|
||||||
**变更记录**
|
**变更记录**
|
||||||
|
|
||||||
`v1.0` `添加`
|
`v1.0` `添加`
|
||||||
|
|
||||||
|
`v1.0.80` `修改`
|
||||||
|
|
||||||
|
增加 `priority` Hook 优先级
|
||||||
|
|
||||||
**功能描述**
|
**功能描述**
|
||||||
|
|
||||||
> Hook 核心功能实现类,查找和处理需要 Hook 的方法、构造类。
|
> Hook 核心功能实现类,查找和处理需要 Hook 的方法、构造类。
|
29
docs/api/public/YukiModuleResources.md
Normal file
29
docs/api/public/YukiModuleResources.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
## YukiModuleResources [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
class YukiModuleResources(private val baseInstance: XModuleResources) : Resources
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 对接 `XModuleResources` 的中间层实例。
|
||||||
|
|
||||||
|
### fwd [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun fwd(resId: Int): YukiResForwarder
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 对接 `XModuleResources.fwd` 方法。
|
||||||
|
|
||||||
|
创建 `YukiResForwarder` 与 `XResForwarder` 实例。
|
55
docs/api/public/YukiResForwarder.md
Normal file
55
docs/api/public/YukiResForwarder.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
## YukiResForwarder [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
class YukiResForwarder(private val baseInstance: XResForwarder)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 对接 `XResForwarder` 的中间层实例。
|
||||||
|
|
||||||
|
### instance [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val instance: XResForwarder
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获得 `XResForwarder` 实例。
|
||||||
|
|
||||||
|
### id [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val id: Int
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获得当前 APP 的 Resources Id。
|
||||||
|
|
||||||
|
### resources [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val resources: Resources
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获得当前 APP 的 Resources。
|
77
docs/api/public/YukiResources.md
Normal file
77
docs/api/public/YukiResources.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
## YukiResources [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
class YukiResources(private val baseInstance: XResources) : Resources
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 对接 `XResources` 的中间层实例。
|
||||||
|
|
||||||
|
### LayoutInflatedParam [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
class LayoutInflatedParam(internal val baseParam: XC_LayoutInflated.LayoutInflatedParam)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 装载 Hook APP 的目标布局 Resources 实现类。
|
||||||
|
|
||||||
|
#### variantName [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val variantName: String
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获取当前被 Hook 的布局装载目录名称。
|
||||||
|
|
||||||
|
例如:`layout`、`layout-land`、`layout-sw600dp`。
|
||||||
|
|
||||||
|
#### currentView [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
val currentView: View
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 获取当前被 Hook 的布局实例。
|
||||||
|
|
||||||
|
#### findViewByIdentifier [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun <reified T : View> View.findViewByIdentifier(name: String): T?
|
||||||
|
```
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun <reified T : View> findViewByIdentifier(name: String): T?
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 使用 Identifier 查找 Hook APP 指定 Id 的 `View`。
|
||||||
|
|
||||||
|
扩展方法可以使用 Identifier 查找 Hook APP 当前装载布局中指定 Id 的 `View`。
|
569
docs/api/public/YukiResourcesHookCreater.md
Normal file
569
docs/api/public/YukiResourcesHookCreater.md
Normal file
@@ -0,0 +1,569 @@
|
|||||||
|
## YukiResourcesHookCreater [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
class YukiResourcesHookCreater(private val packageParam: PackageParam, internal val hookResources: HookResources)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> `YukiHookAPI` 的 `Resources` 核心 Hook 实现类。
|
||||||
|
|
||||||
|
### injectResource [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun injectResource(tag: String, initiate: ResourceHookCreater.() -> Unit): ResourceHookCreater.Result
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 注入要 Hook 的 Resources。
|
||||||
|
|
||||||
|
**功能示例**
|
||||||
|
|
||||||
|
你可以注入任意 Resources,使用 `injectResource` 即可创建一个 `Hook` 对象。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
你还可以自定义 `tag`,方便你在调试的时候能够区分你的 `Hook` 对象。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource(tag = "KuriharaYuki") {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### ResourcesHookCreater [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inner class ResourcesHookCreater(private val tag: String)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> Hook 核心功能实现类。
|
||||||
|
|
||||||
|
查找和处理需要 Hook 的 Resources。
|
||||||
|
|
||||||
|
#### resourceId [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
var resourceId: Int
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 直接设置需要替换的 Resources Id。
|
||||||
|
|
||||||
|
!> 不建议使用此方法设置目标需要 Hook 的 Resources Id,你可以使用 `conditions` 方法。
|
||||||
|
|
||||||
|
**功能示例**
|
||||||
|
|
||||||
|
你可以直接设置并指定目标 Hook APP 的 Resources Id。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
resourceId = 0x7f060001.toInt()
|
||||||
|
replaceTo(...)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### conditions [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun conditions(initiate: ConditionFinder.() -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 查找条件。
|
||||||
|
|
||||||
|
若你设置了 `resourceId` 则此方法将不会被使用。
|
||||||
|
|
||||||
|
**功能示例**
|
||||||
|
|
||||||
|
你可参考 [ConditionFinder](#conditionfinder-class) 查看详细用法。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "test_string"
|
||||||
|
string()
|
||||||
|
}
|
||||||
|
replaceTo(...)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### replaceTo [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun replaceTo(any: Any)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 替换指定 Resources 为指定的值。
|
||||||
|
|
||||||
|
**功能示例**
|
||||||
|
|
||||||
|
你可以替换找到的 Resources 为你想要的值,可以是 `String`、`Drawable` 等。
|
||||||
|
|
||||||
|
比如我们要替换一个找到的字符串 Resources。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "test_string"
|
||||||
|
string()
|
||||||
|
}
|
||||||
|
replaceTo("replace string")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
或是替换为一个 `Drawable`,你无需对目标 Resources 实现 `fwd` 方法或 `DrawableLoader`。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "test_drawable"
|
||||||
|
drawable()
|
||||||
|
}
|
||||||
|
replaceTo(ColorDrawable(Color.RED))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### replaceToTrue [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun replaceToTrue()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 替换指定 Resources 为 `true`。
|
||||||
|
|
||||||
|
!> 确保目标替换 Resources 的类型为 `Boolean`。
|
||||||
|
|
||||||
|
#### replaceToFalse [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun replaceToFalse()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 替换指定 Resources 为 `false`。
|
||||||
|
|
||||||
|
!> 确保目标替换 Resources 的类型为 `Boolean`。
|
||||||
|
|
||||||
|
#### replaceToModuleResource [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun replaceToModuleResource(resId: Int)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 替换为当前 Xposed 模块的 Resources。
|
||||||
|
|
||||||
|
你可以直接使用模块的 `R.string.xxx`、`R.mipmap.xxx`、`R.drawable.xxx` 替换 Hook APP 的 Resources。
|
||||||
|
|
||||||
|
**功能示例**
|
||||||
|
|
||||||
|
使用此方法可非常方便地使用当前模块的 Resources 去替换目标 Hook APP 的 Resources。
|
||||||
|
|
||||||
|
这个过程你无需对目标 Resources 实现 `fwd` 方法。
|
||||||
|
|
||||||
|
比如我们要替换一个字符串。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "test_string"
|
||||||
|
string()
|
||||||
|
}
|
||||||
|
replaceToModuleResource(R.id.module_string)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
还可以替换一些复杂的 Resources,比如 `xml` 创建的 `drawable`。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "test_drawable"
|
||||||
|
drawable()
|
||||||
|
}
|
||||||
|
replaceToModuleResource(R.drawable.module_drawable)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### injectAsLayout [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun injectAsLayout(initiate: YukiResources.LayoutInflatedParam.() -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 作为装载的布局注入。
|
||||||
|
|
||||||
|
**功能示例**
|
||||||
|
|
||||||
|
你可以直接注入一个布局监听并修改它的内部 `View`。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "activity_main"
|
||||||
|
layout()
|
||||||
|
}
|
||||||
|
injectAsLayout {
|
||||||
|
findViewByIdentifier<View>(name = "test_view")?.isVisible = false
|
||||||
|
findViewByIdentifier<TextView>(name = "test_text_view")?.text = "Hook this"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
你还可以通过 `currentView` 拿到 `Context`。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "activity_main"
|
||||||
|
layout()
|
||||||
|
}
|
||||||
|
injectAsLayout {
|
||||||
|
Toast.makeText(currentView.context, "Hook this", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### ConditionFinder [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inner class ConditionFinder
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> Resources 查找条件实现类。
|
||||||
|
|
||||||
|
##### name [field]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
var name: String
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 名称。
|
||||||
|
|
||||||
|
##### anim [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun anim()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为动画。
|
||||||
|
|
||||||
|
##### animator [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun animator()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为属性动画。
|
||||||
|
|
||||||
|
##### bool [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun bool()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为布朗(Boolean)。
|
||||||
|
|
||||||
|
##### color [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun color()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为颜色(Color)。
|
||||||
|
|
||||||
|
##### dimen [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun dimen()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为尺寸(Dimention)。
|
||||||
|
|
||||||
|
##### drawable [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun drawable()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为 Drawable。
|
||||||
|
|
||||||
|
##### integer [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun integer()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为整型(Integer)。
|
||||||
|
|
||||||
|
##### layout [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun layout()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为布局(Layout)。
|
||||||
|
|
||||||
|
##### plurals [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun plurals()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为 Plurals。
|
||||||
|
|
||||||
|
##### string [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun string()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为字符串(String)。
|
||||||
|
|
||||||
|
##### xml [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun xml()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为 Xml。
|
||||||
|
|
||||||
|
##### mipmap [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun mipmap()
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 Resources 类型为位图(Mipmap)。
|
||||||
|
|
||||||
|
#### Result [class]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inner class Result
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 监听全部 Hook 结果实现类,可在这里处理失败事件监听。
|
||||||
|
|
||||||
|
##### result [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun result(initiate: Result.() -> Unit): Result
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 创建监听事件方法体。
|
||||||
|
|
||||||
|
##### by [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun by(initiate: () -> Boolean): Result
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。
|
||||||
|
|
||||||
|
#### onHookingFailure [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun onHookingFailure(initiate: (Throwable) -> Unit): Result
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 监听 Hook 过程发生错误的回调方法。
|
||||||
|
|
||||||
|
#### ignoredHookingFailure [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun ignoredHookingFailure(): Result
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 忽略 Hook 过程出现的错误。
|
69
docs/api/public/YukiXposedEvent.md
Normal file
69
docs/api/public/YukiXposedEvent.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
## YukiXposedEvent [object]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
object YukiXposedEvent
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `添加`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 实现对原生 Xposed API 的装载事件监听。
|
||||||
|
|
||||||
|
### events [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
inline fun events(initiate: YukiXposedEvent.() -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 对 `YukiXposedEvent` 创建一个方法体。
|
||||||
|
|
||||||
|
### onInitZygote [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun onInitZygote(initiate: (StartupParam) -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 initZygote 事件监听。
|
||||||
|
|
||||||
|
### onHandleLoadPackage [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun onHandleLoadPackage(initiate: (LoadPackageParam) -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 handleLoadPackage 事件监听。
|
||||||
|
|
||||||
|
### onHandleInitPackageResources [method]
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
fun onHandleInitPackageResources(initiate: (InitPackageResourcesParam) -> Unit)
|
||||||
|
```
|
||||||
|
|
||||||
|
**变更记录**
|
||||||
|
|
||||||
|
`v1.0.80` `新增`
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
> 设置 handleInitPackageResources 事件监听。
|
@@ -177,6 +177,57 @@ class HookEntryClass : IYukiHookXposedInit {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 扩展特性
|
||||||
|
|
||||||
|
如果你当前使用的 Hook Framework 支持并启用了资源钩子(Resources Hook)功能,你现在可以直接在 `encase` 中创建 Resources Hook。
|
||||||
|
|
||||||
|
你完全不需要与之前在使用 Xposed API 那样区分 `initZygote`、`handleLoadPackage`、`handleInitPackageResources` 方法来执行不同的功能。
|
||||||
|
|
||||||
|
在 `YukiHookAPI` 中,这些功能**是无缝的**。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
encase {
|
||||||
|
loadApp(name = "com.example.demo") {
|
||||||
|
findClass(name = "$packageName.DemoClass").hook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
// 创建一个 Resources Hook (固定用法)
|
||||||
|
resources().hook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
你还可以同时使用 `loadZygote` 方法来装载系统框架。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
encase {
|
||||||
|
loadZygote {
|
||||||
|
ActivityClass.hook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
// 在 Zygote 中创建 Resources Hook
|
||||||
|
resources().hook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadApp(name = "com.example.demo") {
|
||||||
|
findClass(name = "$packageName.DemoClass").hook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
// 在 APP 中创建 Resources Hook
|
||||||
|
resources().hook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 作为 Hook API 使用需要注意的地方
|
## 作为 Hook API 使用需要注意的地方
|
||||||
|
|
||||||
若你作为 Hook API 使用,那么你只需要在入口处对 `encase` 方法进行区分。
|
若你作为 Hook API 使用,那么你只需要在入口处对 `encase` 方法进行区分。
|
||||||
@@ -196,4 +247,6 @@ fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
|
|||||||
|
|
||||||
此处的 `baseContext` 只需填入你在 `attachBaseContext` 处得到的 `Context` 即可,其它用法与上述内容完全一致。
|
此处的 `baseContext` 只需填入你在 `attachBaseContext` 处得到的 `Context` 即可,其它用法与上述内容完全一致。
|
||||||
|
|
||||||
!> 切勿以 Xposed 方式使用 `encase` 方法而漏掉 `baseContext` 参数,否则你的 Hook 将完全不工作。
|
!> 切勿以 Xposed 方式使用 `encase` 方法而漏掉 `baseContext` 参数,否则你的 Hook 将完全不工作。
|
||||||
|
|
||||||
|
!> Resources Hook 功能不支持作为 Hook API 使用。
|
@@ -16,11 +16,11 @@
|
|||||||
|
|
||||||
请确认你在正确的地方装载了 `YukiHookAPI` 的 `encase` 方法,详情请参考 [作为 Xposed 模块使用的相关配置](config/xposed-using) 以及 [作为 Hook API 使用的相关配置](config/api-using)。
|
请确认你在正确的地方装载了 `YukiHookAPI` 的 `encase` 方法,详情请参考 [作为 Xposed 模块使用的相关配置](config/xposed-using) 以及 [作为 Hook API 使用的相关配置](config/api-using)。
|
||||||
|
|
||||||
!> `loggerE` You cannot load a hooker in "onInit" method! Aborted
|
!> `loggerE` You cannot load a hooker in "onInit" or "onXposedEvent" method! Aborted
|
||||||
|
|
||||||
**异常原因**
|
**异常原因**
|
||||||
|
|
||||||
你尝试在继承 `IYukiHookXposedInit` 的 Hook 入口类的 `onInit` 方法中装载了 `encase` 方法。
|
你尝试在继承 `IYukiHookXposedInit` 的 Hook 入口类的 `onInit` 或 `onXposedEvent` 方法中装载了 `encase` 或 `resources` 方法。
|
||||||
|
|
||||||
> 示例如下
|
> 示例如下
|
||||||
|
|
||||||
@@ -34,6 +34,13 @@ class HookEntry : IYukiHookXposedInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onXposedEvent() {
|
||||||
|
// ❗错误的使用方法
|
||||||
|
YukiHookAPI.encase {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onHook() {
|
override fun onHook() {
|
||||||
// Your code here.
|
// Your code here.
|
||||||
}
|
}
|
||||||
@@ -75,6 +82,16 @@ class HookEntry : IYukiHookXposedInit {
|
|||||||
|
|
||||||
通常情况下这种错误不会轻易发生,若一旦发生此错误,请自行查看控制台打印的日志定位问题,确定并非自己的代码发生的问题后,可提交日志进行反馈。
|
通常情况下这种错误不会轻易发生,若一旦发生此错误,请自行查看控制台打印的日志定位问题,确定并非自己的代码发生的问题后,可提交日志进行反馈。
|
||||||
|
|
||||||
|
!> `loggerE` YukiHookAPI bind initZygote failed
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
`YukiHookAPI` 在尝试装载 Xposed 原生接口 `initZygote` 方法时发生了不能处理的异常。
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
通常情况下这种错误不会轻易发生,若一旦发生此错误,请自行查看控制台打印的日志定位问题,确定并非自己的代码发生的问题后,可提交日志进行反馈。
|
||||||
|
|
||||||
!> `loggerE` HookClass \[**NAME**\] not found
|
!> `loggerE` HookClass \[**NAME**\] not found
|
||||||
|
|
||||||
**异常原因**
|
**异常原因**
|
||||||
@@ -361,6 +378,50 @@ method {
|
|||||||
|
|
||||||
请检查查询条件中 `param` 的 `index` 号下标的 `Class` 是否存在,然后再试一次。
|
请检查查询条件中 `param` 的 `index` 号下标的 `Class` 是否存在,然后再试一次。
|
||||||
|
|
||||||
|
!> `loggerE` Resources Hook condition name/type cannot be empty \[**TAG**\]
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
在查找 Resources 时并未设置任何条件。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// 情况 1
|
||||||
|
conditions {
|
||||||
|
// 这里没有设置任何条件
|
||||||
|
}
|
||||||
|
// 情况 2
|
||||||
|
conditions {
|
||||||
|
name = "test"
|
||||||
|
// 这里缺少了 type 条件
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
Resources 的 Hook 并非类似方法的 Hook,其必须拥有完整的名称和类型描述才能查询成功,请将查询条件补充完整并再试一次。
|
||||||
|
|
||||||
|
!> `loggerE` Resources Hook type is invalid \[**TAG**\]
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
在 Hook Resources 时发生了类型错误的异常。
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
`YukiHookAPI` 会尝试在 `initZygote` 与 `handleInitPackageResources` 中装载 Resources Hook,若全部装载失败可能会发生此异常,当前 Hook Framework 需要支持并启用资源钩子(Resources Hook)功能,请检查后再试一次。
|
||||||
|
|
||||||
|
!> `loggerE` Resources Hook got an Exception \[**TAG**\]
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
在 Hook Resources 时发生了任意的异常。
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
这是一个异常汇总,请自行向下查看日志具体的异常是什么,例如找不到 Resources Id 的问题。
|
||||||
|
|
||||||
## 阻断异常
|
## 阻断异常
|
||||||
|
|
||||||
> 这些异常会直接导致 APP 停止运行(FC),同时会在控制台打印 `E` 级别的日志,还会造成 Hook 进程“死掉”。
|
> 这些异常会直接导致 APP 停止运行(FC),同时会在控制台打印 `E` 级别的日志,还会造成 Hook 进程“死掉”。
|
||||||
@@ -682,6 +743,42 @@ encase {
|
|||||||
|
|
||||||
`appContext` 在宿主环境初始化完成之前有大的概率可能是空的,请延迟获取或在宿主的 Hook 方法回调方法体内再使用此变量。
|
`appContext` 在宿主环境初始化完成之前有大的概率可能是空的,请延迟获取或在宿主的 Hook 方法回调方法体内再使用此变量。
|
||||||
|
|
||||||
|
!> `IllegalStateException` Current Hook Framework not support moduleAppResources
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
在 `PackageParam` 中调用了 `moduleAppResources` 变量但是无法获取到实例对象。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
encase {
|
||||||
|
// 调用了此变量
|
||||||
|
moduleAppResources...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
`moduleAppResources` 需要当前 Hook Framework 支持 `initZygote` 功能,请检查后再试一次。
|
||||||
|
|
||||||
|
!> `IllegalStateException` You cannot call to appResources in this time
|
||||||
|
|
||||||
|
在 `PackageParam` 中调用了 `appResources` 变量但是无法获取到实例对象。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
encase {
|
||||||
|
// 调用了此变量
|
||||||
|
appResources...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
`appResources` 不会在 `initZygote` 中装载,另外,这个功能需要当前 Hook Framework 支持并启用资源钩子(Resources Hook)功能,请检查后再试一次。
|
||||||
|
|
||||||
!> `IllegalStateException` VariousClass match failed of those **CLASSES**
|
!> `IllegalStateException` VariousClass match failed of those **CLASSES**
|
||||||
|
|
||||||
**异常原因**
|
**异常原因**
|
||||||
@@ -713,6 +810,48 @@ TargetClass.hook {
|
|||||||
|
|
||||||
详情请参考 [状态监听](guide/example?id=状态监听)。
|
详情请参考 [状态监听](guide/example?id=状态监听)。
|
||||||
|
|
||||||
|
!> `IllegalStateException` LayoutInflatedParam View instance got null
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
在布局 Hook 回调中调用了 `currentView` 但没取到实例对象。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "activity_main"
|
||||||
|
layout()
|
||||||
|
}
|
||||||
|
injectAsLayout {
|
||||||
|
// 调用了此变量
|
||||||
|
currentView...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
这种情况基本上不存在,除非被 Hook 的宿主当前 `Activity` 已经销毁或 Hook Framework 自身存在问题。
|
||||||
|
|
||||||
|
!> `IllegalStateException` XResForwarder is invalid
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
在 `YukiResForwarder` 中调用了 `resources` 但没取到实例对象。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// 调用了此变量
|
||||||
|
moduleAppResources.fwd(...).resources
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
这种情况基本上不存在,除非 Hook Framework 自身存在问题。
|
||||||
|
|
||||||
!> `IllegalStateException` Hook Members is empty, hook aborted
|
!> `IllegalStateException` Hook Members is empty, hook aborted
|
||||||
|
|
||||||
**异常原因**
|
**异常原因**
|
||||||
@@ -731,6 +870,24 @@ TargetClass.hook {
|
|||||||
|
|
||||||
你必须在 `hook` 方法体内加入至少一个 `injectMember` 方法。
|
你必须在 `hook` 方法体内加入至少一个 `injectMember` 方法。
|
||||||
|
|
||||||
|
!> `IllegalStateException` Hook Resources is empty, hook aborted
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
使用了 `hook` 方法体但其中并没有填写内容。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
resources().hook {
|
||||||
|
// 这里没有填写任何内容
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
你必须在 `hook` 方法体内加入至少一个 `injectResources` 方法。
|
||||||
|
|
||||||
!> `IllegalStateException` paramTypes is empty, please use emptyParam() instead
|
!> `IllegalStateException` paramTypes is empty, please use emptyParam() instead
|
||||||
|
|
||||||
**异常原因**
|
**异常原因**
|
||||||
@@ -771,4 +928,14 @@ method {
|
|||||||
name = "test"
|
name = "test"
|
||||||
paramCount = 0
|
paramCount = 0
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!> `IllegalStateException` Invalid YukiHookCallback type
|
||||||
|
|
||||||
|
**异常原因**
|
||||||
|
|
||||||
|
`YukiHookAPI` 的核心 Hook 功能发生故障。
|
||||||
|
|
||||||
|
**解决方案**
|
||||||
|
|
||||||
|
这种情况基本上不存在,若发生上述问题,确定并非自己的代码发生的问题后,可提交日志进行反馈。
|
@@ -10,16 +10,7 @@
|
|||||||
|
|
||||||
> ~~如果你仍然在使用 `Proguard`,你需要做一些规则配置。~~
|
> ~~如果你仍然在使用 `Proguard`,你需要做一些规则配置。~~
|
||||||
|
|
||||||
~~在 `proguard-rules.pro` 添加如下代码即可。~~
|
!> Proguard 规则已被弃用,请不要再使用,自从 Android Gradle Plugin 4.2 后,拥有 Android Jetpack 套件最新版本的混淆处理程序默认均为 `R8`,不再需要考虑混淆的问题。
|
||||||
|
|
||||||
> ~~示例如下~~
|
|
||||||
|
|
||||||
```proguard
|
|
||||||
-keep class com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus {*;}
|
|
||||||
-keep class 这里填你的 HookEntryClass 入口类完整包名_YukiHookXposedInit {*;}
|
|
||||||
```
|
|
||||||
|
|
||||||
!> Proguard 规则已被弃用,请不要再使用,自从 Android Gradle Plugin 4.2 后,拥有 Android Jetpack 套件最新版本的混淆处理程序默认均为 `R8`,基本可以不需要考虑混淆的问题。
|
|
||||||
|
|
||||||
若要在任何版本下启用 `R8`,请在 `gradle.properties` 文件中加入如下规则,Android Gradle Plugin 7.0 及以上版本无需任何配置。
|
若要在任何版本下启用 `R8`,请在 `gradle.properties` 文件中加入如下规则,Android Gradle Plugin 7.0 及以上版本无需任何配置。
|
||||||
|
|
||||||
|
@@ -96,7 +96,7 @@ Xposed 入口类处理如下。
|
|||||||
> 示例如下
|
> 示例如下
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class HookEntry_YukiHookXposedInit: IXposedHookLoadPackage, ...
|
class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources
|
||||||
```
|
```
|
||||||
|
|
||||||
编译后的类名结构如下。
|
编译后的类名结构如下。
|
||||||
@@ -105,6 +105,7 @@ class HookEntry_YukiHookXposedInit: IXposedHookLoadPackage, ...
|
|||||||
|
|
||||||
```
|
```
|
||||||
...hook.HookEntry ← 你的入口类
|
...hook.HookEntry ← 你的入口类
|
||||||
|
...hook.HookEntry_Impl ← 自动生成的 Impl 类
|
||||||
...hook.HookEntry_YukiHookXposedInit ← 自动生成的 Xposed 入口类
|
...hook.HookEntry_YukiHookXposedInit ← 自动生成的 Xposed 入口类
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -122,7 +123,7 @@ Xposed 入口类处理如下。
|
|||||||
> 示例如下
|
> 示例如下
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class HookXposedEntry: IXposedHookLoadPackage, ...
|
class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources
|
||||||
```
|
```
|
||||||
|
|
||||||
编译后的类名结构如下。
|
编译后的类名结构如下。
|
||||||
@@ -131,6 +132,7 @@ class HookXposedEntry: IXposedHookLoadPackage, ...
|
|||||||
|
|
||||||
```
|
```
|
||||||
...hook.HookEntry ← 你的入口类
|
...hook.HookEntry ← 你的入口类
|
||||||
|
...hook.HookEntry_Impl ← 自动生成的 Impl 类
|
||||||
...hook.HookXposedEntry ← 自动生成的 Xposed 入口类
|
...hook.HookXposedEntry ← 自动生成的 Xposed 入口类
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -138,21 +140,47 @@ class HookXposedEntry: IXposedHookLoadPackage, ...
|
|||||||
|
|
||||||
### IYukiHookXposedInit 接口
|
### IYukiHookXposedInit 接口
|
||||||
|
|
||||||
```kotlin
|
|
||||||
interface IYukiHookXposedInit {
|
|
||||||
|
|
||||||
fun onInit()
|
|
||||||
|
|
||||||
fun onHook()
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`IYukiHookXposedInit` 接口为你的 `HookEntryClass` 必须实现的接口,这是你的模块开始 Hook 的起点。
|
`IYukiHookXposedInit` 接口为你的 `HookEntryClass` 必须实现的接口,这是你的模块开始 Hook 的起点。
|
||||||
|
|
||||||
若要了解更多可 [点击这里](api/document?id=iyukihookxposedinit-interface) 进行查看。
|
若要了解更多可 [点击这里](api/document?id=iyukihookxposedinit-interface) 进行查看。
|
||||||
|
|
||||||
当你的模块被 Xposed 装载后,`onHook` 方法将会被回调,你需要在此方法中开始使用 `YukiHookAPI`。
|
当你的模块被 Xposed 装载后,`onHook` 方法将会被回调,你需要在此方法中开始使用 `YukiHookAPI`。
|
||||||
|
|
||||||
> 基本的调用流程为 `YukiHookInjectXposedInitClass.handleLoadPackage` → `HookEntryClass.onInit` → `HookEntryClass.onHook` → `YukiHookAPI.onXposedLoaded`
|
> 基本的调用流程为 `_YukiHookXposedInit` → `IYukiHookXposedInit.onXposedEvent` → `IYukiHookXposedInit.onInit` → `IYukiHookXposedInit.onHook`
|
||||||
|
|
||||||
详情请参考 [API 基本配置](config/api-example)。
|
详情请参考 [API 基本配置](config/api-example)。
|
||||||
|
|
||||||
|
## 原生 Xposed API 事件
|
||||||
|
|
||||||
|
若你当前的 Xposed 模块使用了第三方的资源,但是短时间内可能无法转移它们,此时,你可以使用 `onXposedEvent` 实现监听原生 Xposed API 的全部装载事件。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
@InjectYukiHookWithXposed
|
||||||
|
class HookEntry: IYukiHookXposedInit {
|
||||||
|
|
||||||
|
override fun onHook() {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onXposedEvent() {
|
||||||
|
// 监听原生 Xposed API 的装载事件
|
||||||
|
YukiXposedEvent.events {
|
||||||
|
onInitZygote {
|
||||||
|
// it 对象即 [StartupParam]
|
||||||
|
}
|
||||||
|
onHandleLoadPackage {
|
||||||
|
// it 对象即 [LoadPackageParam]
|
||||||
|
}
|
||||||
|
onHandleInitPackageResources {
|
||||||
|
// it 对象即 [InitPackageResourcesParam]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`onXposedEvent` 与 `onHook` 方法完全独立存在,互不影响,你可以继续在 `onHook` 方法中使用 `YukiHookAPI`。
|
||||||
|
|
||||||
|
若要了解更多可 [点击这里](api/document?id=onxposedevent-method) 进行查看。
|
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
```
|
```
|
||||||
Host Environment
|
Host Environment
|
||||||
└── YukiHookCreater
|
└── YukiMemberHookCreater
|
||||||
└── Class
|
└── Class
|
||||||
└── MemberHookCreater
|
└── MemberHookCreater
|
||||||
└── Member
|
└── Member
|
||||||
@@ -19,6 +19,15 @@ Host Environment
|
|||||||
├── Before
|
├── Before
|
||||||
└── After
|
└── After
|
||||||
...
|
...
|
||||||
|
YukiResourcesHookCreater
|
||||||
|
└── Resources
|
||||||
|
└── ResourcesHookCreater
|
||||||
|
└── Drawable
|
||||||
|
└── Replace
|
||||||
|
ResourcesHookCreater
|
||||||
|
└── Layout
|
||||||
|
└── Inject
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
> 上方的结构换做代码将可写为如下形式。
|
> 上方的结构换做代码将可写为如下形式。
|
||||||
@@ -37,6 +46,14 @@ TargetClass.hook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resources().hook {
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
replaceTo(...)
|
||||||
|
}
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
@@ -51,6 +68,10 @@ TargetClass.hook {
|
|||||||
|
|
||||||
## 一个简单的 Hook 例子
|
## 一个简单的 Hook 例子
|
||||||
|
|
||||||
|
> 这里给出了 Hook APP、Hook 系统框架与 Hook Resources 的例子,可供参考。
|
||||||
|
|
||||||
|
### Hook APP
|
||||||
|
|
||||||
假设,我们要 Hook `com.android.browser` 中的 `onCreate` 方法并弹出一个对话框。
|
假设,我们要 Hook `com.android.browser` 中的 `onCreate` 方法并弹出一个对话框。
|
||||||
|
|
||||||
在 `encase` 方法体中添加代码。
|
在 `encase` 方法体中添加代码。
|
||||||
@@ -171,6 +192,97 @@ TestClass.hook {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Hook 系统框架
|
||||||
|
|
||||||
|
在 `YukiHookAPI` 中,Hook 系统框架的实现非常简单。
|
||||||
|
|
||||||
|
假设我们要全局 Hook 一个 `Activity` 的 `onCreate` 事件
|
||||||
|
|
||||||
|
在 `encase` 方法体中添加代码。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
loadZygote {
|
||||||
|
ActivityClass.hook {
|
||||||
|
injectMember {
|
||||||
|
method {
|
||||||
|
name = "onCreate"
|
||||||
|
param(BundleClass)
|
||||||
|
returnType = UnitType
|
||||||
|
}
|
||||||
|
afterHook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
这样就实现了上述的 Hook 功能。
|
||||||
|
|
||||||
|
!> `loadZygote` 与 `loadApp(name = "android")` 有直接性区别,`loadZygote` 会在 `initZygote` 中装载,若要 Hook 系统框架,建议使用 `loadZygote`。
|
||||||
|
|
||||||
|
### Hook Resources
|
||||||
|
|
||||||
|
假设,我们要 Hook `com.android.browser` 中 `string` 类型的 `app_name` 内容替换为 `123`。
|
||||||
|
|
||||||
|
在 `encase` 方法体中添加代码。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
loadApp(name = "com.android.browser") {
|
||||||
|
resources().hook {
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "app_name"
|
||||||
|
string()
|
||||||
|
}
|
||||||
|
replaceTo("123")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
若当前 APP 使用 `app_name` 设置了标题栏文本,则它就会变成我们的 `123`。
|
||||||
|
|
||||||
|
你还可以使用当前 Xposed 模块的 Resources 替换 Hook APP 的 Resources。
|
||||||
|
|
||||||
|
假设,我们要继续 Hook `com.android.browser` 中 `mipmap` 类型的 `ic_launcher`。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
loadApp(name = "com.android.browser") {
|
||||||
|
resources().hook {
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "ic_launcher"
|
||||||
|
mipmap()
|
||||||
|
}
|
||||||
|
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
至此目标 APP 的图标将会被替换为我们设置的图标。
|
||||||
|
|
||||||
|
若你想替换系统框架的资源,同样也可以这样实现,只需要把 `loadApp` 换成 `loadZygote` 即可。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
loadZygote {
|
||||||
|
resources().hook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
更多功能请参考 [ResourcesHookCreater](api/document?id=resourceshookcreater-class)。
|
||||||
|
|
||||||
## 异常处理
|
## 异常处理
|
||||||
|
|
||||||
> `YukiHookAPI` 重新设计了对异常的监听,任何异常都不会在 Hook 过程中抛出,避免打断下一个 Hook 流程导致 Hook 进程“死掉”。
|
> `YukiHookAPI` 重新设计了对异常的监听,任何异常都不会在 Hook 过程中抛出,避免打断下一个 Hook 流程导致 Hook 进程“死掉”。
|
||||||
@@ -193,6 +305,20 @@ injectMember {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
在 Resources Hook 时此方法同样适用。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
injectResource {
|
||||||
|
// Your code here.
|
||||||
|
}.result {
|
||||||
|
// 处理 Hook 时的任意异常
|
||||||
|
onHookingFailure {}
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
你还可以处理 Hook 的 `Class` 不存在时发生的异常。
|
你还可以处理 Hook 的 `Class` 不存在时发生的异常。
|
||||||
|
|
||||||
> 示例如下
|
> 示例如下
|
||||||
|
@@ -62,6 +62,8 @@
|
|||||||
|
|
||||||
现在,我们只需要编写少量的代码,一切时间开销和花费交给自动化处理。
|
现在,我们只需要编写少量的代码,一切时间开销和花费交给自动化处理。
|
||||||
|
|
||||||
|
借助 `Kotlin` 优雅的 `lambda` 写法以及 `YukiHookAPI`,可以让你的 Hook 逻辑更加美观清晰。
|
||||||
|
|
||||||
> 示例如下
|
> 示例如下
|
||||||
|
|
||||||
<!-- tabs:start -->
|
<!-- tabs:start -->
|
||||||
@@ -70,9 +72,34 @@
|
|||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@InjectYukiHookWithXposed
|
@InjectYukiHookWithXposed
|
||||||
class MainHook : IYukiHookXposedInit {
|
class HookEntry : IYukiHookXposedInit {
|
||||||
|
|
||||||
override fun onHook() = encase {
|
override fun onHook() = encase {
|
||||||
|
loadZygote {
|
||||||
|
ActivityClass.hook {
|
||||||
|
injectMember {
|
||||||
|
method {
|
||||||
|
name = "onCreate"
|
||||||
|
param(BundleClass)
|
||||||
|
}
|
||||||
|
beforeHook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
afterHook {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resources().hook {
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "sym_def_app_icon"
|
||||||
|
mipmap()
|
||||||
|
}
|
||||||
|
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
loadApp(name = "com.android.browser") {
|
loadApp(name = "com.android.browser") {
|
||||||
ActivityClass.hook {
|
ActivityClass.hook {
|
||||||
injectMember {
|
injectMember {
|
||||||
@@ -88,6 +115,15 @@ class MainHook : IYukiHookXposedInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
resources().hook {
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "ic_launcher"
|
||||||
|
mipmap()
|
||||||
|
}
|
||||||
|
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,14 +132,16 @@ class MainHook : IYukiHookXposedInit {
|
|||||||
#### **Xposed API**
|
#### **Xposed API**
|
||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
class MainHook : IXposedHookLoadPackage {
|
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
|
||||||
|
|
||||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
private lateinit var moduleResources: XModuleResources
|
||||||
if (lpparam.packageName == "com.android.browser")
|
|
||||||
XposedHelpers.findAndHookMethod(
|
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
|
||||||
|
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
|
||||||
|
XResources.setSystemWideReplacement("android", "mipmap", "sym_def_app_icon", moduleResources.fwd(R.mipmap.ic_launcher))
|
||||||
|
XposedHelpers.findAndHookMethod(
|
||||||
Activity::class.java.name,
|
Activity::class.java.name,
|
||||||
lpparam.classLoader,
|
null, "onCreate",
|
||||||
"onCreate",
|
|
||||||
Bundle::class.java,
|
Bundle::class.java,
|
||||||
object : XC_MethodHook() {
|
object : XC_MethodHook() {
|
||||||
override fun beforeHookedMethod(param: MethodHookParam?) {
|
override fun beforeHookedMethod(param: MethodHookParam?) {
|
||||||
@@ -115,14 +153,36 @@ class MainHook : IXposedHookLoadPackage {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||||
|
if (lpparam.packageName == "com.android.browser")
|
||||||
|
XposedHelpers.findAndHookMethod(
|
||||||
|
Activity::class.java.name,
|
||||||
|
lpparam.classLoader, "onCreate",
|
||||||
|
Bundle::class.java,
|
||||||
|
object : XC_MethodHook() {
|
||||||
|
override fun beforeHookedMethod(param: MethodHookParam?) {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterHookedMethod(param: MethodHookParam?) {
|
||||||
|
// Your code here.
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
|
||||||
|
if (resparam.packageName == "com.android.browser")
|
||||||
|
resparam.res.setReplacement("com.android.browser", "mipmap", "ic_launcher", moduleResources.fwd(R.mipmap.ic_launcher))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<!-- tabs:end -->
|
<!-- tabs:end -->
|
||||||
|
|
||||||
是的,你没有看错,仅仅就需要这几行代码,就一切安排妥当。
|
是的,你没有看错,仅仅就需要这些代码,就能完全取代 Xposed API 实现同样的功能。
|
||||||
|
|
||||||
代码量少,逻辑清晰,借助高效强大的 `YukiHookAPI`,你就可以实现一个非常简单的 Xposed 模块。
|
现在,借助高效强大的 `YukiHookAPI`,你就可以实现一个非常简单的 Xposed 模块。
|
||||||
|
|
||||||
## 支持的 Hook 框架
|
## 支持的 Hook 框架
|
||||||
|
|
||||||
@@ -131,7 +191,7 @@ class MainHook : IXposedHookLoadPackage {
|
|||||||
| Hook Framework | ST | Describe |
|
| Hook Framework | ST | Describe |
|
||||||
| --------------------------------------------------------- | --- | ----------------------------------------------------------------------------------------- |
|
| --------------------------------------------------------- | --- | ----------------------------------------------------------------------------------------- |
|
||||||
| [LSPosed](https://github.com/LSPosed/LSPosed) | ✅ | 多场景下稳定使用 |
|
| [LSPosed](https://github.com/LSPosed/LSPosed) | ✅ | 多场景下稳定使用 |
|
||||||
| [EdXposed](https://github.com/ElderDrivers/EdXposed) | ✅ | 部分兼容 |
|
| [EdXposed](https://github.com/ElderDrivers/EdXposed) | ❎ | 已停止维护,不再推荐使用 |
|
||||||
| [Pine](https://github.com/canyie/pine) | ⭕ | 可以使用 |
|
| [Pine](https://github.com/canyie/pine) | ⭕ | 可以使用 |
|
||||||
| [SandHook](https://github.com/asLody/SandHook) | ⭕ | 可以使用 |
|
| [SandHook](https://github.com/asLody/SandHook) | ⭕ | 可以使用 |
|
||||||
| [Whale](https://github.com/asLody/whale) | ⭕ | 需要 [xposed-hook-based-on-whale](https://github.com/WindySha/xposed-hook-based-on-whale) |
|
| [Whale](https://github.com/asLody/whale) | ⭕ | 需要 [xposed-hook-based-on-whale](https://github.com/WindySha/xposed-hook-based-on-whale) |
|
||||||
|
@@ -22,15 +22,28 @@ override fun onHook() = encase {
|
|||||||
appInfo
|
appInfo
|
||||||
// 得到宿主 Application 生命周期
|
// 得到宿主 Application 生命周期
|
||||||
appContext
|
appContext
|
||||||
// 创建 Hook
|
// Hook 指定的 APP
|
||||||
findClass("com.demo.Test").hook {
|
loadApp(name = "com.demo.test") {
|
||||||
injectMember {
|
// Class Hook
|
||||||
method {
|
findClass("com.demo.test.TestClass").hook {
|
||||||
name = "test"
|
injectMember {
|
||||||
param(BooleanType)
|
method {
|
||||||
|
name = "test"
|
||||||
|
param(BooleanType)
|
||||||
|
}
|
||||||
|
afterHook {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
}
|
}
|
||||||
afterHook {
|
}
|
||||||
// ...
|
// Resources Hook (固定用法)
|
||||||
|
resources().hook {
|
||||||
|
injectResource {
|
||||||
|
conditions {
|
||||||
|
name = "ic_launcher"
|
||||||
|
mipmap()
|
||||||
|
}
|
||||||
|
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,6 +53,12 @@ override fun onHook() = encase {
|
|||||||
#### **Xposed API**
|
#### **Xposed API**
|
||||||
|
|
||||||
```kotlin
|
```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) {
|
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||||
// 得到当前 Hook 的包名
|
// 得到当前 Hook 的包名
|
||||||
lpparam.packageName
|
lpparam.packageName
|
||||||
@@ -47,12 +66,20 @@ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
|||||||
lpparam.applicationInfo
|
lpparam.applicationInfo
|
||||||
// 得到宿主 Application 生命周期
|
// 得到宿主 Application 生命周期
|
||||||
AndroidAppHelper.currentApplication()
|
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
|
// 创建 Hook
|
||||||
XposedHelpers.findAndHookMethod("com.demo.Test", lpparam.classLoader, "test", Boolean::class.java, object : XC_MethodHook() {
|
resparam.res.setReplacement("com.demo.test", "mipmap", "ic_launcher", moduleResources.fwd(R.mipmap.ic_launcher))
|
||||||
override fun afterHookedMethod(param: MethodHookParam) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@@ -101,7 +101,7 @@ dependencies {
|
|||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
@InjectYukiHookWithXposed
|
@InjectYukiHookWithXposed
|
||||||
class MainHook : IYukiHookXposedInit {
|
class HookEntry : IYukiHookXposedInit {
|
||||||
|
|
||||||
override fun onHook() = YukiHookAPI.encase {
|
override fun onHook() = YukiHookAPI.encase {
|
||||||
// Your code here.
|
// Your code here.
|
||||||
@@ -153,4 +153,4 @@ override fun attachBaseContext(base: Context?) {
|
|||||||
|
|
||||||
### 特别说明
|
### 特别说明
|
||||||
|
|
||||||
!> 由于你使用了自定义的 Hook 框架而并非模块,~~`YukiHookModuleStatus`~~ ~~`YukiHookModulePrefs`~~ 功能将失效。
|
!> 由于你使用了自定义的 Hook 框架而并非模块,~~`YukiHookModuleStatus`~~ ~~`YukiHookModulePrefs`~~ 以及 Resources Hook 功能将失效。
|
@@ -11,7 +11,26 @@
|
|||||||
```java
|
```java
|
||||||
package com.demo;
|
package com.demo;
|
||||||
|
|
||||||
public class Test {
|
public class BaseTest {
|
||||||
|
|
||||||
|
public BaseTest() {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseTest(boolean isInit) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doBaseTask(String taskName) {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
package com.demo;
|
||||||
|
|
||||||
|
public class Test extends BaseTest {
|
||||||
|
|
||||||
public Test() {
|
public Test() {
|
||||||
// ...
|
// ...
|
||||||
@@ -61,7 +80,7 @@ public class Test {
|
|||||||
|
|
||||||
### 查询与反射调用
|
### 查询与反射调用
|
||||||
|
|
||||||
假设我们要得到 `doTask` 方法并执行,通常情况下,我们可以使用标准的反射 API 去查询这个方法。
|
假设我们要得到 `Test`(以下统称“当前 `Class`”)的 `doTask` 方法并执行,通常情况下,我们可以使用标准的反射 API 去查询这个方法。
|
||||||
|
|
||||||
> 示例如下
|
> 示例如下
|
||||||
|
|
||||||
@@ -178,6 +197,54 @@ Test::class.java.method {
|
|||||||
}.get(instance) // 得到这个方法
|
}.get(instance) // 得到这个方法
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 在父类查询
|
||||||
|
|
||||||
|
你会注意到 `Test` 继承于 `BaseTest`,现在我们想得到 `BaseTest` 的 `doBaseTask` 方法,在不知道父类名称的情况下,要怎么做呢?
|
||||||
|
|
||||||
|
参照上面的查询条件,我们只需要在查询条件中加入一个 `superClass` 即可实现这个功能。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// 假设这就是这个 Class 的实例
|
||||||
|
val instance = Test()
|
||||||
|
// 使用 YukiHookAPI 调用并执行
|
||||||
|
Test::class.java.method {
|
||||||
|
name = "doBaseTask"
|
||||||
|
param(StringType)
|
||||||
|
// 只需要添加这个条件
|
||||||
|
superClass()
|
||||||
|
}.get(instance).call("task_name")
|
||||||
|
```
|
||||||
|
|
||||||
|
这个时候我们就可以在父类中取到这个方法了。
|
||||||
|
|
||||||
|
`superClass` 有一个参数为 `isOnlySuperClass`,设置为 `true` 后,可以跳过当前 `Class` 仅查询当前 `Class` 的父类。
|
||||||
|
|
||||||
|
由于我们现在已知 `doBaseTask` 方法只存在于父类,可以加上这个条件节省查询时间。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// 假设这就是这个 Class 的实例
|
||||||
|
val instance = Test()
|
||||||
|
// 使用 YukiHookAPI 调用并执行
|
||||||
|
Test::class.java.method {
|
||||||
|
name = "doBaseTask"
|
||||||
|
param(StringType)
|
||||||
|
// 加入一个查询条件
|
||||||
|
superClass(isOnlySuperClass = true)
|
||||||
|
}.get(instance).call("task_name")
|
||||||
|
```
|
||||||
|
|
||||||
|
这个时候我们同样可以得到父类中的这个方法。
|
||||||
|
|
||||||
|
`superClass` 一旦设置就会自动循环向后查找全部继承的父类中是否有这个方法,直到查询到目标没有父类(继承关系为 `java.lang.Object`)为止。
|
||||||
|
|
||||||
|
更多用法可参考 [superClass 方法](api/document?id=superclass-method)。
|
||||||
|
|
||||||
|
!> 当前查询的 `Method` 除非指定 `superClass` 条件,否则只能查询到当前 `Class` 的 `Method`。
|
||||||
|
|
||||||
### 静态字节码
|
### 静态字节码
|
||||||
|
|
||||||
有些方法和变量在 `Class` 中是静态的实现,这个时候,我们不需要传入实例就可以调用它们。
|
有些方法和变量在 `Class` 中是静态的实现,这个时候,我们不需要传入实例就可以调用它们。
|
||||||
@@ -347,6 +414,23 @@ instance.current {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
我们还可以用 `superClass` 调用当前 `Class` 父类的方法。
|
||||||
|
|
||||||
|
> 示例如下
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// 假设这就是这个 Class 的实例
|
||||||
|
val instance = Test()
|
||||||
|
// 假设这个 Class 是不能被直接得到的
|
||||||
|
instance.current {
|
||||||
|
// 执行父类的 doBaseTask 方法
|
||||||
|
superClass().method {
|
||||||
|
name = "doBaseTask"
|
||||||
|
param(StringType)
|
||||||
|
}.call("task_name")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
问题又来了,我想使用反射的方式创建如下的实例并调用其中的方法,该怎么做呢?
|
问题又来了,我想使用反射的方式创建如下的实例并调用其中的方法,该怎么做呢?
|
||||||
|
|
||||||
> 示例如下
|
> 示例如下
|
||||||
@@ -768,9 +852,9 @@ loggerE(msg = "This is an error")
|
|||||||
|
|
||||||
```kotlin
|
```kotlin
|
||||||
// 假设这就是被抛出的异常
|
// 假设这就是被抛出的异常
|
||||||
val e = Throwable(...)
|
val throwable = Throwable(...)
|
||||||
// 打印日志
|
// 打印日志
|
||||||
loggerE(msg = "This is an error", e = e)
|
loggerE(msg = "This is an error", e = throwable)
|
||||||
```
|
```
|
||||||
|
|
||||||
打印的结果为如下所示。
|
打印的结果为如下所示。
|
||||||
|
@@ -44,7 +44,7 @@
|
|||||||
coverpage: true,
|
coverpage: true,
|
||||||
loadNavbar: true,
|
loadNavbar: true,
|
||||||
loadSidebar: true,
|
loadSidebar: true,
|
||||||
subMaxLevel: 3,
|
subMaxLevel: 4,
|
||||||
auto2top: true,
|
auto2top: true,
|
||||||
mergeNavbar: false,
|
mergeNavbar: false,
|
||||||
notFoundPage: '_404.md',
|
notFoundPage: '_404.md',
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
],
|
],
|
||||||
placeholder: '搜索文档',
|
placeholder: '搜索文档',
|
||||||
noData: '噫,什么都没找到~',
|
noData: '噫,什么都没找到~',
|
||||||
depth: 5,
|
depth: 7,
|
||||||
hideOtherSidebarContent: true
|
hideOtherSidebarContent: true
|
||||||
},
|
},
|
||||||
tabs: {
|
tabs: {
|
||||||
|
@@ -31,13 +31,16 @@ import java.text.SimpleDateFormat
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代码文件注入器
|
* 代码文件注入模板类
|
||||||
*/
|
*/
|
||||||
object CodeSourceFileTemplate {
|
object CodeSourceFileTemplate {
|
||||||
|
|
||||||
/** 定义 Jvm 方法名 */
|
/** 定义 Jvm 方法名 */
|
||||||
private const val IS_ACTIVE_METHOD_NAME = "__--"
|
private const val IS_ACTIVE_METHOD_NAME = "__--"
|
||||||
|
|
||||||
|
/** 定义 Jvm 方法名 */
|
||||||
|
private const val HAS_RESOURCES_HOOK_METHOD_NAME = "_--_"
|
||||||
|
|
||||||
/** 定义 Jvm 方法名 */
|
/** 定义 Jvm 方法名 */
|
||||||
private const val GET_XPOSED_VERSION_METHOD_NAME = "--__"
|
private const val GET_XPOSED_VERSION_METHOD_NAME = "--__"
|
||||||
|
|
||||||
@@ -92,80 +95,150 @@ object CodeSourceFileTemplate {
|
|||||||
/**
|
/**
|
||||||
* 获得 xposed_init 注入文件
|
* 获得 xposed_init 注入文件
|
||||||
* @param packageName 包名
|
* @param packageName 包名
|
||||||
* @param modulePackageName 模块包名
|
|
||||||
* @param entryClassName 入口类名
|
* @param entryClassName 入口类名
|
||||||
* @param xInitClassName xposed_init 入口类名
|
* @param xInitClassName xposed_init 入口类名
|
||||||
* @return [ByteArray]
|
* @return [ByteArray]
|
||||||
*/
|
*/
|
||||||
fun getXposedInitFileByteArray(packageName: String, modulePackageName: String, entryClassName: String, xInitClassName: String) =
|
fun getXposedInitFileByteArray(packageName: String, entryClassName: String, xInitClassName: String) =
|
||||||
("package $packageName\n" +
|
("@file:Suppress(\"ClassName\")\n" +
|
||||||
|
"\n" +
|
||||||
|
"package $packageName\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"import androidx.annotation.Keep\n" +
|
"import androidx.annotation.Keep\n" +
|
||||||
"import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookXposedBridge\n" +
|
"import com.highcapable.yukihookapi.hook.xposed.bridge.event.YukiXposedEvent\n" +
|
||||||
"import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus\n" +
|
|
||||||
"import com.highcapable.yukihookapi.hook.log.loggerE\n" +
|
|
||||||
"import de.robv.android.xposed.IXposedHookLoadPackage\n" +
|
|
||||||
"import de.robv.android.xposed.XC_MethodReplacement\n" +
|
|
||||||
"import de.robv.android.xposed.XposedHelpers\n" +
|
|
||||||
"import de.robv.android.xposed.XposedBridge\n" +
|
|
||||||
"import de.robv.android.xposed.callbacks.XC_LoadPackage\n" +
|
|
||||||
"import com.highcapable.yukihookapi.annotation.YukiGenerateApi\n" +
|
"import com.highcapable.yukihookapi.annotation.YukiGenerateApi\n" +
|
||||||
"import $packageName.$entryClassName\n" +
|
"import de.robv.android.xposed.IXposedHookInitPackageResources\n" +
|
||||||
|
"import de.robv.android.xposed.IXposedHookLoadPackage\n" +
|
||||||
|
"import de.robv.android.xposed.IXposedHookZygoteInit\n" +
|
||||||
|
"import de.robv.android.xposed.callbacks.XC_InitPackageResources\n" +
|
||||||
|
"import de.robv.android.xposed.callbacks.XC_LoadPackage\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
getCommentContent(entryClassName, currrentClassTag = "XposedInit") +
|
getCommentContent(entryClassName, currrentClassTag = "Xposed Init") +
|
||||||
"@Keep\n" +
|
"@Keep\n" +
|
||||||
"@YukiGenerateApi\n" +
|
"@YukiGenerateApi\n" +
|
||||||
"class $xInitClassName : IXposedHookLoadPackage {\n" +
|
"class $xInitClassName : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {\n" +
|
||||||
|
"\n" +
|
||||||
|
" override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {\n" +
|
||||||
|
" ${entryClassName}_Impl.callInitZygote(sparam)\n" +
|
||||||
|
" YukiXposedEvent.EventHandler.callInitZygote(sparam)\n" +
|
||||||
|
" }\n" +
|
||||||
"\n" +
|
"\n" +
|
||||||
" override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" +
|
" override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" +
|
||||||
" if (lpparam == null) return\n" +
|
" ${entryClassName}_Impl.callHandleLoadPackage(lpparam)\n" +
|
||||||
" try {\n" +
|
" YukiXposedEvent.EventHandler.callHandleLoadPackage(lpparam)\n" +
|
||||||
" $entryClassName().apply {\n" +
|
" }\n" +
|
||||||
" onInit()\n" +
|
"\n" +
|
||||||
" if (YukiHookXposedBridge.isXposedCallbackSetUp) {\n" +
|
" override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {\n" +
|
||||||
" loggerE(tag = \"YukiHookAPI\", msg = \"You cannot loading a hooker in \\\"onInit\\\" method! Aborted\")\n" +
|
" ${entryClassName}_Impl.callHandleInitPackageResources(resparam)\n" +
|
||||||
" return\n" +
|
" YukiXposedEvent.EventHandler.callHandleInitPackageResources(resparam)\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" onHook()\n" +
|
"}").toByteArray()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得 xposed_init_Impl 注入文件
|
||||||
|
* @param packageName 包名
|
||||||
|
* @param modulePackageName 模块包名
|
||||||
|
* @param entryClassName 入口类名
|
||||||
|
* @return [ByteArray]
|
||||||
|
*/
|
||||||
|
fun getXposedInitImplFileByteArray(packageName: String, modulePackageName: String, entryClassName: String) =
|
||||||
|
("@file:Suppress(\"ClassName\")\n" +
|
||||||
|
"\n" +
|
||||||
|
"package $packageName\n" +
|
||||||
|
"\n" +
|
||||||
|
"import com.highcapable.yukihookapi.annotation.YukiGenerateApi\n" +
|
||||||
|
"import com.highcapable.yukihookapi.hook.log.loggerE\n" +
|
||||||
|
"import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus\n" +
|
||||||
|
"import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge\n" +
|
||||||
|
"import de.robv.android.xposed.IXposedHookZygoteInit\n" +
|
||||||
|
"import de.robv.android.xposed.XC_MethodReplacement\n" +
|
||||||
|
"import de.robv.android.xposed.XposedHelpers\n" +
|
||||||
|
"import de.robv.android.xposed.callbacks.XC_InitPackageResources\n" +
|
||||||
|
"import de.robv.android.xposed.callbacks.XC_LoadPackage\n" +
|
||||||
|
"\n" +
|
||||||
|
getCommentContent(entryClassName, currrentClassTag = "Xposed Init Impl") +
|
||||||
|
"@YukiGenerateApi\n" +
|
||||||
|
"object ${entryClassName}_Impl {\n" +
|
||||||
|
"\n" +
|
||||||
|
" private const val modulePackageName = \"$modulePackageName\"\n" +
|
||||||
|
" private val hookEntry = $entryClassName()\n" +
|
||||||
|
" private var isZygoteBinded = false\n" +
|
||||||
|
" private var lpparam: XC_LoadPackage.LoadPackageParam? = null\n" +
|
||||||
|
"\n" +
|
||||||
|
" private fun callXposedLoaded(\n" +
|
||||||
|
" isZygoteLoaded: Boolean = false,\n" +
|
||||||
|
" lpparam: XC_LoadPackage.LoadPackageParam? = null,\n" +
|
||||||
|
" resparam: XC_InitPackageResources.InitPackageResourcesParam? = null\n" +
|
||||||
|
" ) {\n" +
|
||||||
|
" if (isZygoteBinded.not()) runCatching {\n" +
|
||||||
|
" hookEntry.onXposedEvent()\n" +
|
||||||
|
" hookEntry.onInit()\n" +
|
||||||
|
" if (YukiHookBridge.isXposedCallbackSetUp) {\n" +
|
||||||
|
" loggerE(tag = \"YukiHookAPI\", msg = \"You cannot load a hooker in \\\"onInit\\\" or \\\"onXposedEvent\\\" method! Aborted\")\n" +
|
||||||
|
" return\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" YukiHookXposedBridge.callXposedInitialized()\n" +
|
" hookEntry.onHook()\n" +
|
||||||
" } catch (e: Throwable) {\n" +
|
" YukiHookBridge.callXposedInitialized()\n" +
|
||||||
" loggerE(tag = \"YukiHookAPI\", msg = \"YukiHookAPI try to load HookEntryClass failed\", e = e)\n" +
|
" YukiHookBridge.modulePackageName = modulePackageName\n" +
|
||||||
" }\n" +
|
" }.onFailure { loggerE(tag = \"YukiHookAPI\", msg = \"YukiHookAPI try to load HookEntryClass failed\", e = it) }\n" +
|
||||||
" if (lpparam.packageName == \"$modulePackageName\") {\n" +
|
" YukiHookBridge.callXposedLoaded(isZygoteLoaded, lpparam, resparam)\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" private fun hookModuleAppStatus(lpparam: XC_LoadPackage.LoadPackageParam? = this.lpparam, isHookResourcesStatus: Boolean = false) {\n" +
|
||||||
|
" lpparam?.let { this.lpparam = it }\n" +
|
||||||
|
" if (isHookResourcesStatus.not()) {\n" +
|
||||||
" XposedHelpers.findAndHookMethod(\n" +
|
" XposedHelpers.findAndHookMethod(\n" +
|
||||||
" YukiHookModuleStatus::class.java.name,\n" +
|
" YukiHookModuleStatus::class.java.name,\n" +
|
||||||
" lpparam.classLoader,\n" +
|
" this.lpparam?.classLoader,\n" +
|
||||||
" \"$IS_ACTIVE_METHOD_NAME\",\n" +
|
" \"$IS_ACTIVE_METHOD_NAME\",\n" +
|
||||||
" object : XC_MethodReplacement() {\n" +
|
" object : XC_MethodReplacement() {\n" +
|
||||||
" override fun replaceHookedMethod(param: MethodHookParam?) = true\n" +
|
" override fun replaceHookedMethod(param: MethodHookParam?) = true\n" +
|
||||||
" })\n" +
|
" })\n" +
|
||||||
" XposedHelpers.findAndHookMethod(\n" +
|
" XposedHelpers.findAndHookMethod(\n" +
|
||||||
" YukiHookModuleStatus::class.java.name,\n" +
|
" YukiHookModuleStatus::class.java.name,\n" +
|
||||||
" lpparam.classLoader,\n" +
|
" this.lpparam?.classLoader,\n" +
|
||||||
" \"$GET_XPOSED_TAG_METHOD_NAME\",\n" +
|
" \"$GET_XPOSED_TAG_METHOD_NAME\",\n" +
|
||||||
" object : XC_MethodReplacement() {\n" +
|
" object : XC_MethodReplacement() {\n" +
|
||||||
" override fun replaceHookedMethod(param: MethodHookParam?) = try {\n" +
|
" override fun replaceHookedMethod(param: MethodHookParam?) = YukiHookBridge.executorName\n" +
|
||||||
" XposedBridge::class.java.getDeclaredField(\"TAG\").apply { isAccessible = true }.get(null) as String\n" +
|
|
||||||
" } catch (_: Throwable) {\n" +
|
|
||||||
" \"invalid\"\n" +
|
|
||||||
" }\n" +
|
|
||||||
" })\n" +
|
" })\n" +
|
||||||
" XposedHelpers.findAndHookMethod(\n" +
|
" XposedHelpers.findAndHookMethod(\n" +
|
||||||
" YukiHookModuleStatus::class.java.name,\n" +
|
" YukiHookModuleStatus::class.java.name,\n" +
|
||||||
" lpparam.classLoader,\n" +
|
" this.lpparam?.classLoader,\n" +
|
||||||
" \"$GET_XPOSED_VERSION_METHOD_NAME\",\n" +
|
" \"$GET_XPOSED_VERSION_METHOD_NAME\",\n" +
|
||||||
" object : XC_MethodReplacement() {\n" +
|
" object : XC_MethodReplacement() {\n" +
|
||||||
" override fun replaceHookedMethod(param: MethodHookParam?) = try {\n" +
|
" override fun replaceHookedMethod(param: MethodHookParam?) = YukiHookBridge.executorVersion\n" +
|
||||||
" XposedBridge.getXposedVersion()\n" +
|
|
||||||
" } catch (_: Throwable) {\n" +
|
|
||||||
" -1\n" +
|
|
||||||
" }\n" +
|
|
||||||
" })\n" +
|
" })\n" +
|
||||||
" YukiHookXposedBridge.isModulePackageXposedEnv = true\n" +
|
" } else XposedHelpers.findAndHookMethod(\n" +
|
||||||
" }\n" +
|
" YukiHookModuleStatus::class.java.name,\n" +
|
||||||
" YukiHookXposedBridge.modulePackageName = \"$modulePackageName\"\n" +
|
" this.lpparam?.classLoader,\n" +
|
||||||
" YukiHookXposedBridge.callXposedLoaded(lpparam)\n" +
|
" \"$HAS_RESOURCES_HOOK_METHOD_NAME\",\n" +
|
||||||
|
" object : XC_MethodReplacement() {\n" +
|
||||||
|
" override fun replaceHookedMethod(param: MethodHookParam?) = true\n" +
|
||||||
|
" })\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" @YukiGenerateApi\n" +
|
||||||
|
" fun callInitZygote(sparam: IXposedHookZygoteInit.StartupParam?) {\n" +
|
||||||
|
" if (sparam == null) return\n" +
|
||||||
|
" runCatching {\n" +
|
||||||
|
" YukiHookBridge.callXposedZygoteLoaded(sparam)\n" +
|
||||||
|
" }.onFailure { loggerE(tag = \"YukiHookAPI\", msg = \"YukiHookAPI bind initZygote failed\", e = it) }\n" +
|
||||||
|
" callXposedLoaded(isZygoteLoaded = true)\n" +
|
||||||
|
" isZygoteBinded = true\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" @YukiGenerateApi\n" +
|
||||||
|
" fun callHandleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" +
|
||||||
|
" if (lpparam == null) return\n" +
|
||||||
|
" if (lpparam.packageName == modulePackageName) hookModuleAppStatus(lpparam)\n" +
|
||||||
|
" callXposedLoaded(lpparam = lpparam)\n" +
|
||||||
|
" }\n" +
|
||||||
|
"\n" +
|
||||||
|
" @YukiGenerateApi\n" +
|
||||||
|
" fun callHandleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {\n" +
|
||||||
|
" if (resparam == null) return\n" +
|
||||||
|
" if (resparam.packageName == modulePackageName) hookModuleAppStatus(isHookResourcesStatus = true)\n" +
|
||||||
|
" callXposedLoaded(resparam = resparam)\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
"}").toByteArray()
|
"}").toByteArray()
|
||||||
}
|
}
|
Reference in New Issue
Block a user