mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-10 04:24:21 +08:00
docs: update to new usage
This commit is contained in:
@@ -37,12 +37,11 @@ After the Host App is hooked, we can directly inject the `Context` obtained in t
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
after {
|
||||
instance<Activity>().also {
|
||||
// <Scenario 1> Inject Module App's Resources through Context
|
||||
it.injectModuleAppResources()
|
||||
@@ -91,12 +90,11 @@ After the Host App is hooked, we can directly register the `Activity` proxy of t
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
after {
|
||||
instance<Activity>().registerModuleAppActivities()
|
||||
}
|
||||
}
|
||||
@@ -238,12 +236,11 @@ At this time, we want to use `MaterialAlertDialogBuilder` to create a dialog in
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
after {
|
||||
// Use applyModuleTheme to create a theme resource in the current Module App
|
||||
val appCompatContext = instance<Activity>().applyModuleTheme(R.style.Theme_AppCompat)
|
||||
// Directly use this Context that wraps the Module App's theme to create a dialog
|
||||
@@ -263,12 +260,11 @@ Which requires at least Android 10 and above system version support and the curr
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
after {
|
||||
// Define the theme resource in the current Module App
|
||||
var appCompatContext: ModuleContextThemeWrapper
|
||||
// <Scenario 1> Get the Configuration object directly to set
|
||||
|
@@ -1298,15 +1298,12 @@ Here's how the `getString` method in this `Class` Hooks.
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
Test::class.java.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "getString"
|
||||
emptyParam()
|
||||
returnType = StringClass
|
||||
}
|
||||
replaceTo("Hooked")
|
||||
}
|
||||
Test::class.java.method {
|
||||
name = "getString"
|
||||
emptyParam()
|
||||
returnType = StringClass
|
||||
}.hook {
|
||||
replaceTo("Hooked")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1447,34 +1444,8 @@ Test::class.java.method {
|
||||
}
|
||||
```
|
||||
|
||||
Take the current `Class` as an example, if [Multiple Find](#multiple-find) is used in conjunction with `RemedyPlan` when creating a Hook, you need to change the usage slightly.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "doTask"
|
||||
emptyParam()
|
||||
}.remedys {
|
||||
method {
|
||||
name = "doTask"
|
||||
paramCount(0..1)
|
||||
}
|
||||
method {
|
||||
name = "doTask"
|
||||
paramCount(1..2)
|
||||
}
|
||||
}.all()
|
||||
beforeHook {}
|
||||
afterHook {}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
When creating a Hook, please refer to [MethodFinder.Process.all](../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#all-method), [ConstructorFinder.Process.all]( ../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#all-method) methods.
|
||||
|
||||
For more functions, please refer to [MethodFinder.RemedyPlan](../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#remedyplan-class), [ConstructorFinder.RemedyPlan](../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#remedyplan-class), [FieldFinder.RemedyPlan](../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder#remedyplan-class) .
|
||||
|
||||
:::
|
||||
|
@@ -51,9 +51,12 @@ The `encase` method can be created in the `onHook` method using two schemes.
|
||||
```kotlin
|
||||
YukiHookAPI.encase {
|
||||
loadApp(name = "com.example.demo") {
|
||||
"$packageName.DemoClass".toClass().hook {
|
||||
// Your code here.
|
||||
}
|
||||
"$packageName.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -63,9 +66,12 @@ YukiHookAPI.encase {
|
||||
```kotlin
|
||||
encase {
|
||||
loadApp(name = "com.example.demo") {
|
||||
"$packageName.DemoClass".toClass().hook {
|
||||
// Your code here.
|
||||
}
|
||||
"$packageName.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -120,14 +126,20 @@ object CustomHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
loadApp(name = "com.example.demo1") {
|
||||
"$packageName.DemoClass".toClass().hook {
|
||||
// Your code here.
|
||||
}
|
||||
"$packageName.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
loadApp(name = "com.example.demo2") {
|
||||
"$packageName.CustomClass".toClass().hook {
|
||||
// Your code here.
|
||||
}
|
||||
"$packageName.CustomClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,9 +160,12 @@ object HookEntry : IYukiHookXposedInit {
|
||||
object ChildCustomHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
"$packageName.DemoClass".toClass().hook {
|
||||
// Your code here.
|
||||
}
|
||||
"$packageName.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -163,9 +178,12 @@ You can use the `loadHooker` method to load another Hooker in multiple layers in
|
||||
object FirstHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
"$packageName.DemoClass".toClass().hook {
|
||||
// Your code here.
|
||||
}
|
||||
"$packageName.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
loadHooker(SecondHooker)
|
||||
loadHooker(ThirdHooker)
|
||||
}
|
||||
@@ -235,9 +253,12 @@ In `YukiHookAPI`, these functions **are seamless**.
|
||||
```kotlin
|
||||
encase {
|
||||
loadApp(name = "com.example.demo") {
|
||||
"$packageName.DemoClass".toClass().hook {
|
||||
// Your code here.
|
||||
}
|
||||
"$packageName.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
// Create a Resources Hook (fixed usage)
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
@@ -262,9 +283,12 @@ encase {
|
||||
}
|
||||
}
|
||||
loadApp(name = "com.example.demo") {
|
||||
"$packageName.DemoClass".toClass().hook {
|
||||
// Your code here.
|
||||
}
|
||||
"$packageName.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
// Create a Resources Hook in the app
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
@@ -299,9 +323,12 @@ Below are two **error** examples.
|
||||
```kotlin
|
||||
encase {
|
||||
// Wrong usage, can't start Hook directly
|
||||
"com.example.demo.DemoClass".toClass().hook {
|
||||
// ...
|
||||
}
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
// Wrong usage, can't start Hook directly
|
||||
resources().hook {
|
||||
// ...
|
||||
@@ -329,9 +356,12 @@ object CustomHooker : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
// Wrong method of use
|
||||
// Because there is no judgment object in the outer layer, you cannot start Hook directly
|
||||
"com.example.demo.DemoClass".toClass().hook {
|
||||
// ...
|
||||
}
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -357,9 +387,12 @@ encase {
|
||||
loadApp(/** name parameter optional */) {
|
||||
loadHooker(CustomHooker)
|
||||
// ✅ Correct usage, Hook in app scope
|
||||
"com.example.demo.DemoClass".toClass().hook {
|
||||
// ...
|
||||
}
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
// ✅ Correct usage, Hook in app scope
|
||||
resources().hook {
|
||||
// ...
|
||||
@@ -384,9 +417,12 @@ object CustomHooker : YukiBaseHooker() {
|
||||
// ✅ The correct method of use, since there is no judgment object in the outer layer
|
||||
// it is necessary to judge the scope of the app before performing Hook
|
||||
loadApp(/** name parameter optional */) {
|
||||
"com.example.demo.DemoClass".toClass().hook {
|
||||
// ...
|
||||
}
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -226,7 +226,7 @@ If the problem persists, please bring detailed logs for feedback.
|
||||
|
||||
::: danger loggerE
|
||||
|
||||
Hooked Member with a finding error by **CLASS**
|
||||
Hooked Member with a finding error / by **CLASS**
|
||||
|
||||
:::
|
||||
|
||||
@@ -242,7 +242,7 @@ Please check the previous error log before this error occurs, maybe there is an
|
||||
|
||||
::: danger loggerE
|
||||
|
||||
Hooked Member cannot be non-null by **CLASS**
|
||||
Hooked Member cannot be null / by **CLASS**
|
||||
|
||||
:::
|
||||
|
||||
@@ -255,7 +255,7 @@ After the Hook is executed, the `member` of the Hook is `null` and the target Ho
|
||||
```kotlin
|
||||
injectMember {
|
||||
// There are no search conditions for methods and constructors that require hooks
|
||||
afterHook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -273,7 +273,7 @@ injectMember {
|
||||
method {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -302,13 +302,12 @@ private boolean test()
|
||||
Below is an error case.
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
emptyParam()
|
||||
}
|
||||
method {
|
||||
name = "test"
|
||||
emptyParam()
|
||||
}.hook {
|
||||
// <Scenario 1> Set the wrong type, the original type is Boolean
|
||||
beforeHook {
|
||||
before {
|
||||
result = 0
|
||||
}
|
||||
// <Scenario 2> Return the wrong type, the original type is Boolean
|
||||
@@ -322,7 +321,7 @@ injectMember {
|
||||
|
||||
::: warning
|
||||
|
||||
If the above scenario occurs in **beforeHook** or **afterHook**, it will cause the Host App to throw an exception from **XposedBridge** (which will expose the fact of being Hooked).
|
||||
If the above scenario occurs in **before** or **after**, it will cause the Host App to throw an exception from **XposedBridge** (which will expose the fact of being Hooked).
|
||||
|
||||
:::
|
||||
|
||||
@@ -1515,7 +1514,7 @@ Custom Hooking Members is empty
|
||||
injectMember {
|
||||
// Method parameters in parentheses are left blank
|
||||
members()
|
||||
afterHook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -1542,7 +1541,7 @@ HookParam Method args index must be >= 0
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// Assume param is empty
|
||||
args().last()...
|
||||
// Set an index less than 0
|
||||
@@ -1572,7 +1571,7 @@ An object that calls an `instance` variable or `instance` method in a `HookParam
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// This variable is called
|
||||
instance...
|
||||
// This method is called
|
||||
@@ -1606,7 +1605,7 @@ The `args` variable is called in `HookParam`, but the parameter array of the cur
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// This variable is called
|
||||
args...
|
||||
}
|
||||
@@ -1636,7 +1635,7 @@ Call the `member` variable in `HookParam` but cannot get the method and construc
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// This variable is called
|
||||
member...
|
||||
}
|
||||
@@ -1666,7 +1665,7 @@ Calling the `method` variable in `HookParam` but not getting the method instance
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// This variable is called
|
||||
method...
|
||||
}
|
||||
@@ -1696,7 +1695,7 @@ A method instance for calling a `constructor` variable in a `HookParam` but not
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// This variable is called
|
||||
constructor...
|
||||
}
|
||||
@@ -1726,7 +1725,7 @@ Invoking the `instance` method in a `HookParam` specifies the wrong type.
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// The type is cast to Activity
|
||||
// But assumes the current instance's type is not this type
|
||||
instance<Activity>()...
|
||||
@@ -1757,7 +1756,7 @@ The `ArgsModifyer.set` method is called in `HookParam` but the method parameter
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// This method is called
|
||||
args(...).set(...)
|
||||
}
|
||||
@@ -1785,7 +1784,7 @@ Calling the `ArgsModifyer.set` method in `HookParam` specifies an array number b
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// The subscript starts from 0
|
||||
// Assuming the original parameter subscript is 5, but fill in 6 here
|
||||
args(index = 6).set(...)
|
||||
@@ -1870,6 +1869,54 @@ For details, please refer to [Status Monitor](../guide/example#status-monitor).
|
||||
|
||||
###### exception
|
||||
|
||||
::: danger IllegalStateException
|
||||
|
||||
This hook instance is create by Members, not support any hook class instance
|
||||
|
||||
:::
|
||||
|
||||
**Abnormal**
|
||||
|
||||
Hook instance is created using `Member.hook { ... }` instead of `Class.hook { ... }` and uses `instanceClass`.
|
||||
|
||||
**Solution**
|
||||
|
||||
You can only use `instanceClass` if you created a Hook instance using `Class.hook { ... }`.
|
||||
|
||||
###### exception
|
||||
|
||||
::: danger IllegalStateException
|
||||
|
||||
Use of searchClass { ... }.hook { ... } is an error, please use like searchClass { ... }.get()?.hook { ... }
|
||||
|
||||
:::
|
||||
|
||||
**Abnormal**
|
||||
|
||||
The Hook instance are created directly using the `searchClass { ... }.hook { ... }` method.
|
||||
|
||||
**Solution**
|
||||
|
||||
Please use `searchClass { ... }.get()?.hook { ... }` to create a Hook instance.
|
||||
|
||||
###### exception
|
||||
|
||||
::: danger IllegalStateException
|
||||
|
||||
This type \[**TYPE**\] not support to hook, supported are Constructors and Methods
|
||||
|
||||
:::
|
||||
|
||||
**Abnormal**
|
||||
|
||||
Using `Member.hook { ... }` creates member objects that do not support Hooks, such as `Field`.
|
||||
|
||||
**Solution**
|
||||
|
||||
You can only Hook `Constructor` and `Method`.
|
||||
|
||||
###### exception
|
||||
|
||||
::: danger IllegalStateException
|
||||
|
||||
LayoutInflatedParam View instance got null
|
||||
|
@@ -188,9 +188,40 @@ The **entryClassName** you define must not be the same as the class name in **xp
|
||||
|
||||
#### isUsingResourcesHook Parameter
|
||||
|
||||
`isUsingResourcesHook` determines whether the automatic builder generates relevant code for the Resources Hook, this feature is enabled by default.
|
||||
`isUsingResourcesHook` determines whether the automatic builder generates relevant code for the Resources Hook, This feature is not enabled by default.
|
||||
|
||||
The generated entry class after enabling it will look like the following.
|
||||
By default the generated entry class will look like this.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
|
||||
// ...
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If your current project need to use Resources Hook, you can set `isUsingResourcesHook = true` to enable automatic generation.
|
||||
|
||||
::: warning
|
||||
|
||||
This feature will no longer be enabled by default after version **1.2.0**, please enable it manually if you want to use it.
|
||||
|
||||
:::
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed(isUsingResourcesHook = true)
|
||||
```
|
||||
|
||||
The resulting entry class after enabled will look like the following.
|
||||
|
||||
> The following example
|
||||
|
||||
@@ -211,31 +242,6 @@ class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage, IXpos
|
||||
}
|
||||
```
|
||||
|
||||
If your current project does not need to use Resources Hook, you can set `isUsingResourcesHook = false` to disable automatic generation.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
|
||||
```
|
||||
|
||||
The resulting entry class after closing will look like the following.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
|
||||
// ...
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
Since the Xposed entry class is dynamically generated by **YukiHookAPI**, it will generate the following two files at the same time.
|
||||
|
@@ -33,19 +33,32 @@ Host Environment
|
||||
> The above structure can be written in the following form in code.
|
||||
|
||||
```kotlin
|
||||
TargetClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
// New version
|
||||
TargetClass.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
before {
|
||||
// Your code here.
|
||||
}
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
// Old version
|
||||
TargetClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
// Your code here.
|
||||
}
|
||||
beforeHook {
|
||||
before {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
// Resources Hook (2.x.x will be discontinued)
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
@@ -80,20 +93,17 @@ Add code in the body of the `encase` method.
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
AlertDialog.Builder(instance())
|
||||
.setTitle("Hooked")
|
||||
.setMessage("I am hook!")
|
||||
.setPositiveButton("OK", null)
|
||||
.show()
|
||||
}
|
||||
ActivityClass.method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}.hook {
|
||||
after {
|
||||
AlertDialog.Builder(instance())
|
||||
.setTitle("Hooked")
|
||||
.setMessage("I am hook!")
|
||||
.setPositiveButton("OK", null)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,20 +113,19 @@ At this point, the `onCreate` method will be successfully hooked and this dialog
|
||||
|
||||
So, what should I do if I want to continue the Hook `onStart` method?
|
||||
|
||||
In the code just now, continue to insert an `injectMember` method body.
|
||||
We can use Kotlin's `apply` method on `ActivityClass` to create a call space.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
ActivityClass.apply {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}.hook {
|
||||
after {
|
||||
AlertDialog.Builder(instance())
|
||||
.setTitle("Hooked")
|
||||
.setMessage("I am hook!")
|
||||
@@ -124,13 +133,12 @@ loadApp(name = "com.android.browser") {
|
||||
.show()
|
||||
}
|
||||
}
|
||||
injectMember {
|
||||
method {
|
||||
name = "onStart"
|
||||
emptyParam()
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onStart"
|
||||
emptyParam()
|
||||
returnType = UnitType
|
||||
}.hook {
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
@@ -145,11 +153,12 @@ For example, I want to get `com.example.demo.TestClass`.
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
"com.example.demo.TestClass".toClass().hook {
|
||||
injectMember {
|
||||
"com.example.demo.TestClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If `com.example.demo` is the app you want to hook, then the writing method can be simpler.
|
||||
@@ -157,11 +166,12 @@ If `com.example.demo` is the app you want to hook, then the writing method can b
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
"$packageName.TestClass".toClass().hook {
|
||||
injectMember {
|
||||
"$packageName.TestClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
@@ -182,16 +192,13 @@ Add code in the body of the `encase` method.
|
||||
|
||||
```kotlin
|
||||
loadZygote {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
ActivityClass.method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
returnType = UnitType
|
||||
}.hook {
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,10 +222,14 @@ Add code in the body of the `encase` method.
|
||||
|
||||
```kotlin
|
||||
loadSystem {
|
||||
ApplicationInfoClass.hook {
|
||||
ApplicationInfoClass.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
PackageInfoClass.hook {
|
||||
PackageInfoClass.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
@@ -232,6 +243,12 @@ loadSystem {
|
||||
|
||||
### Hook Resources
|
||||
|
||||
::: warning
|
||||
|
||||
This feature will be discontinued and removed in version 2.x.x.
|
||||
|
||||
:::
|
||||
|
||||
Suppose, we want to replace the content of `app_name` of type `string` in Hook `com.android.browser` with `123`.
|
||||
|
||||
Add code in the body of the `encase` method.
|
||||
@@ -303,15 +320,15 @@ The first way, save the `Result` instance of the current injected object, and ca
|
||||
|
||||
```kotlin
|
||||
// Set a variable to save the current instance
|
||||
val hookResult = injectMember {
|
||||
method {
|
||||
val hookResult =
|
||||
method {
|
||||
name = "test"
|
||||
returnType = UnitType
|
||||
}.hook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
afterHook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
// Call the following method when appropriate
|
||||
hookResult.remove()
|
||||
```
|
||||
@@ -321,12 +338,11 @@ The second method, call `removeSelf` in the Hook callback method to remove itsel
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "test"
|
||||
returnType = UnitType
|
||||
}.hook {
|
||||
after {
|
||||
// Just call the following method directly
|
||||
removeSelf()
|
||||
}
|
||||
@@ -350,7 +366,7 @@ You can handle exceptions that occur during the Hook method.
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
hook {
|
||||
// Your code here.
|
||||
}.result {
|
||||
// Handle the exception at the start of the hook
|
||||
@@ -377,7 +393,7 @@ injectResource {
|
||||
}
|
||||
```
|
||||
|
||||
You can also handle exceptions that occur when the Hook's `Class` does not exist.
|
||||
**(Applicable to older versions)** You can also handle exceptions that occur when the Hook's `Class` does not exist.
|
||||
|
||||
> The following example
|
||||
|
||||
@@ -427,7 +443,7 @@ injectMember {
|
||||
method {
|
||||
throw RuntimeException("Exception Test")
|
||||
}
|
||||
afterHook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}.result {
|
||||
@@ -439,7 +455,7 @@ injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
afterHook {
|
||||
after {
|
||||
throw RuntimeException("Exception Test")
|
||||
}
|
||||
}.result {
|
||||
@@ -457,11 +473,10 @@ If you want to throw an exception directly to the Host App in the Hook callback
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
// ...
|
||||
}.hook {
|
||||
after {
|
||||
RuntimeException("Exception Test").throwToApp()
|
||||
}
|
||||
}
|
||||
@@ -472,11 +487,10 @@ You can also throw exceptions directly in the Hook callback method body, and the
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
// ...
|
||||
}.hook {
|
||||
after {
|
||||
throw RuntimeException("Exception Test")
|
||||
}.onFailureThrowToApp()
|
||||
}
|
||||
@@ -486,7 +500,7 @@ The above two methods can receive an exception at the Host App and cause the Hos
|
||||
|
||||
::: warning
|
||||
|
||||
In order to ensure that the Hook calling domain and the calling domain within the Host App are isolated from each other, exceptions can only be thrown to the Host App in the **beforeHook** and **afterHook** callback method bodies.
|
||||
In order to ensure that the Hook calling domain and the calling domain within the Host App are isolated from each other, exceptions can only be thrown to the Host App in the **before** and **after** callback method bodies.
|
||||
|
||||
:::
|
||||
|
||||
@@ -496,42 +510,6 @@ For more functions, please refer to [Throwable.throwToApp](../api/public/com/hig
|
||||
|
||||
:::
|
||||
|
||||
## Status Monitor
|
||||
|
||||
People who use `XposedHelpers` often print `Unhook` after the Hook to determine whether the Hook is successful.
|
||||
|
||||
In `YukiHookAPI`, you can easily reimplement this functionality with the following methods.
|
||||
|
||||
First we can monitor that the Hook is ready to start.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
YourClass.hook {
|
||||
// Your code here.
|
||||
}.onPrepareHook {
|
||||
loggerD(msg = "$instanceClass hook start")
|
||||
}
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
**instanceClass** is recommended to be used only in **onPrepareHook**, otherwise the Hook's **Class** does not exist and an uninterceptable exception will be thrown, causing the Hook process to "die".
|
||||
|
||||
:::
|
||||
|
||||
Then, we can also monitor the success of the method result of the Hook.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}.onHooked { member ->
|
||||
loggerD(msg = "$member has hooked")
|
||||
}
|
||||
```
|
||||
|
||||
## Expansion Usage
|
||||
|
||||
> You can use the following methods to easily implement various judgments and functions in the Hook process.
|
||||
|
@@ -51,52 +51,28 @@ object HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = encase {
|
||||
loadZygote {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
ActivityClass.method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
before {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "sym_def_app_icon"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
ActivityClass.method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
before {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -108,16 +84,12 @@ object HookEntry : IYukiHookXposedInit {
|
||||
::: code-group-item Rovo89 Xposed API
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
|
||||
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
||||
|
||||
private lateinit var moduleResources: XModuleResources
|
||||
|
||||
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,
|
||||
null, "onCreate",
|
||||
@@ -149,14 +121,6 @@ class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInit
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
@@ -29,18 +29,16 @@ override fun onHook() = encase {
|
||||
appContext
|
||||
// Hook specified app
|
||||
loadApp(name = "com.demo.test") {
|
||||
// Class Hook
|
||||
"com.demo.test.TestClass".toClass().hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
param(BooleanType)
|
||||
}
|
||||
afterHook {
|
||||
// Member Hook
|
||||
"com.demo.test.TestClass".toClass()
|
||||
.method {
|
||||
name = "test"
|
||||
param(BooleanType)
|
||||
}.hook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
// Resources Hook (fixed usage)
|
||||
resources().hook {
|
||||
injectResource {
|
||||
@@ -107,7 +105,7 @@ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPa
|
||||
|
||||
#### Before/After Hook
|
||||
|
||||
`YukiHookAPI` also implements the **lambda** method body `this` usage for `HookParam`, and the `HookParam` object can be obtained globally in the method bodies such as `beforeHook` and `afterHook`.
|
||||
`YukiHookAPI` also implements the **lambda** method body `this` usage for `HookParam`, and the `HookParam` object can be obtained globally in the method bodies such as `before` and `after`.
|
||||
|
||||
> The API function differences are compared as follows
|
||||
|
||||
@@ -115,7 +113,7 @@ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPa
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
afterHook {
|
||||
after {
|
||||
// Get the current Hook instance
|
||||
instance
|
||||
// Get the Class instance of the current Hook
|
||||
|
@@ -29,27 +29,15 @@ footer: MIT License | Copyright (C) 2019-2023 HighCapable
|
||||
|
||||
```kotlin
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
ActivityClass.method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
before {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user