mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-01 08:15:37 +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.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -35,12 +35,11 @@ android {
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
after {
|
||||
instance<Activity>().also {
|
||||
// <方案1> 通过 Context 注入模块资源
|
||||
it.injectModuleAppResources()
|
||||
@@ -87,12 +86,11 @@ onAppLifecycle {
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
after {
|
||||
instance<Activity>().registerModuleAppActivities()
|
||||
}
|
||||
}
|
||||
@@ -229,12 +227,11 @@ The style on this component requires your app theme to be Theme.AppCompat (or a
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
after {
|
||||
// 使用 applyModuleTheme 创建一个当前模块中的主题资源
|
||||
val appCompatContext = instance<Activity>().applyModuleTheme(R.style.Theme_AppCompat)
|
||||
// 直接使用这个包装了模块主题后的 Context 创建对话框
|
||||
@@ -252,12 +249,11 @@ injectMember {
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}.hook {
|
||||
after {
|
||||
// 定义当前模块中的主题资源
|
||||
var appCompatContext: ModuleContextThemeWrapper
|
||||
// <方案1> 直接得到 Configuration 对象进行设置
|
||||
|
@@ -1245,15 +1245,12 @@ public class Test {
|
||||
> 示例如下
|
||||
|
||||
```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")
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1394,34 +1391,8 @@ Test::class.java.method {
|
||||
}
|
||||
```
|
||||
|
||||
以当前 `Class` 举例,若 [多重查找](#多重查找) 结合 `RemedyPlan` 在创建 Hook 的时候使用,你需要稍微改变一下用法。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "doTask"
|
||||
emptyParam()
|
||||
}.remedys {
|
||||
method {
|
||||
name = "doTask"
|
||||
paramCount(0..1)
|
||||
}
|
||||
method {
|
||||
name = "doTask"
|
||||
paramCount(1..2)
|
||||
}
|
||||
}.all()
|
||||
beforeHook {}
|
||||
afterHook {}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
在创建 Hook 的时候使用可参考 [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) 方法。
|
||||
|
||||
更多功能请参考 [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 @@ fun encase(initiate: PackageParam.() -> Unit)
|
||||
```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 @@ object ChildCustomHooker : YukiBaseHooker() {
|
||||
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)
|
||||
}
|
||||
@@ -233,9 +251,12 @@ 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.
|
||||
}
|
||||
// 创建一个 Resources Hook (固定用法)
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
@@ -260,9 +281,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.
|
||||
}
|
||||
// 在 APP 中创建 Resources Hook
|
||||
resources().hook {
|
||||
// Your code here.
|
||||
@@ -296,9 +320,12 @@ encase {
|
||||
```kotlin
|
||||
encase {
|
||||
// 错误的使用方法,不能直接开始 Hook
|
||||
"com.example.demo.DemoClass".toClass().hook {
|
||||
// ...
|
||||
}
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
// 错误的使用方法,不能直接开始 Hook
|
||||
resources().hook {
|
||||
// ...
|
||||
@@ -325,9 +352,12 @@ object CustomHooker : YukiBaseHooker() {
|
||||
|
||||
override fun onHook() {
|
||||
// 错误的使用方法,由于外层没有任何判断对象,不能直接开始 Hook
|
||||
"com.example.demo.DemoClass".toClass().hook {
|
||||
// ...
|
||||
}
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -353,9 +383,12 @@ encase {
|
||||
loadApp(/** name 参数可选 */) {
|
||||
loadHooker(CustomHooker)
|
||||
// ✅ 正确的使用方法,在 APP 作用域内 Hook
|
||||
"com.example.demo.DemoClass".toClass().hook {
|
||||
// ...
|
||||
}
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
// ✅ 正确的使用方法,在 APP 作用域内 Hook
|
||||
resources().hook {
|
||||
// ...
|
||||
@@ -379,9 +412,12 @@ object CustomHooker : YukiBaseHooker() {
|
||||
override fun onHook() {
|
||||
// ✅ 正确的使用方法,由于外层没有任何判断对象,需要判断 APP 作用域后再进行 Hook
|
||||
loadApp(/** name 参数可选 */) {
|
||||
"com.example.demo.DemoClass".toClass().hook {
|
||||
// ...
|
||||
}
|
||||
"com.example.demo.DemoClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -210,7 +210,7 @@ Hook 目标方法、构造方法时发生错误。
|
||||
|
||||
::: danger loggerE
|
||||
|
||||
Hooked Member with a finding error by **CLASS**
|
||||
Hooked Member with a finding error / by **CLASS**
|
||||
|
||||
:::
|
||||
|
||||
@@ -226,7 +226,7 @@ Hooked Member with a finding error by **CLASS**
|
||||
|
||||
::: danger loggerE
|
||||
|
||||
Hooked Member cannot be non-null by **CLASS**
|
||||
Hooked Member cannot be null / by **CLASS**
|
||||
|
||||
:::
|
||||
|
||||
@@ -239,7 +239,7 @@ Hooked Member cannot be non-null by **CLASS**
|
||||
```kotlin
|
||||
injectMember {
|
||||
// 这里并没有设置需要 Hook 的方法、构造方法的查找条件
|
||||
afterHook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -257,7 +257,7 @@ injectMember {
|
||||
method {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -286,13 +286,12 @@ private boolean test()
|
||||
下面是一个错误的案列。
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
emptyParam()
|
||||
}
|
||||
method {
|
||||
name = "test"
|
||||
emptyParam()
|
||||
}.hook {
|
||||
// <情景1> 设置了错误的类型,原类型为 Boolean
|
||||
beforeHook {
|
||||
before {
|
||||
result = 0
|
||||
}
|
||||
// <情景2> 返回了错误的类型,原类型为 Boolean
|
||||
@@ -306,7 +305,7 @@ injectMember {
|
||||
|
||||
::: warning
|
||||
|
||||
若上述场景在 **beforeHook** 或 **afterHook** 中发生,则会造成被 Hook 的 APP (宿主) 由 **XposedBridge** 抛出异常 (会对其暴露被 Hook 的事实)。
|
||||
若上述场景在 **before** 或 **after** 中发生,则会造成被 Hook 的 APP (宿主) 由 **XposedBridge** 抛出异常 (会对其暴露被 Hook 的事实)。
|
||||
|
||||
:::
|
||||
|
||||
@@ -1452,7 +1451,7 @@ Custom Hooking Members is empty
|
||||
injectMember {
|
||||
// 括号里的方法参数被留空了
|
||||
members()
|
||||
afterHook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
@@ -1479,7 +1478,7 @@ HookParam Method args index must be >= 0
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 假设 param 是空的
|
||||
args().last()...
|
||||
// 设置了小于 0 的 index
|
||||
@@ -1509,7 +1508,7 @@ HookParam instance got null! Is this a static member?
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 调用了此变量
|
||||
instance...
|
||||
// 调用了此方法
|
||||
@@ -1539,7 +1538,7 @@ Current hooked Member args is null
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 调用了此变量
|
||||
args...
|
||||
}
|
||||
@@ -1567,7 +1566,7 @@ Current hooked Member is null
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 调用了此变量
|
||||
member...
|
||||
}
|
||||
@@ -1595,7 +1594,7 @@ Current hooked Member is not a Method
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 调用了此变量
|
||||
method...
|
||||
}
|
||||
@@ -1623,7 +1622,7 @@ Current hooked Member is not a Constructor
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 调用了此变量
|
||||
constructor...
|
||||
}
|
||||
@@ -1651,7 +1650,7 @@ HookParam instance cannot cast to **TYPE**
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 类型被 cast 为 Activity 但假设当前实例的类型并非此类型
|
||||
instance<Activity>()...
|
||||
}
|
||||
@@ -1679,7 +1678,7 @@ HookParam Method args is empty, mabe not has args
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 调用了此方法
|
||||
args(...).set(...)
|
||||
}
|
||||
@@ -1707,7 +1706,7 @@ HookParam Method args index out of bounds, max is **NUMBER**
|
||||
```kotlin
|
||||
injectMember {
|
||||
// ...
|
||||
afterHook {
|
||||
after {
|
||||
// 下标从 0 开始,假设原始的参数下标是 5 个,但是这里填写了 6
|
||||
args(index = 6).set(...)
|
||||
}
|
||||
@@ -1790,6 +1789,54 @@ TargetClass.hook {
|
||||
|
||||
::: danger IllegalStateException
|
||||
|
||||
This hook instance is create by Members, not support any hook class instance
|
||||
|
||||
:::
|
||||
|
||||
**异常原因**
|
||||
|
||||
使用 `Member.hook { ... }` 并非 `Class.hook { ... }` 创建了 Hook 实例并使用了 `instanceClass`。
|
||||
|
||||
**解决方案**
|
||||
|
||||
你只能在使用 `Class.hook { ... }` 创建 Hook 实例的情况下使用 `instanceClass`。
|
||||
|
||||
###### exception
|
||||
|
||||
::: danger IllegalStateException
|
||||
|
||||
Use of searchClass { ... }.hook { ... } is an error, please use like searchClass { ... }.get()?.hook { ... }
|
||||
|
||||
:::
|
||||
|
||||
**异常原因**
|
||||
|
||||
使用 `searchClass { ... }.hook { ... }` 方式直接创建了 Hook 实例。
|
||||
|
||||
**解决方案**
|
||||
|
||||
请使用 `searchClass { ... }.get()?.hook { ... }` 方式创建 Hook 实例。
|
||||
|
||||
###### exception
|
||||
|
||||
::: danger IllegalStateException
|
||||
|
||||
This type \[**TYPE**\] not support to hook, supported are Constructors and Methods
|
||||
|
||||
:::
|
||||
|
||||
**异常原因**
|
||||
|
||||
使用 `Member.hook { ... }` 时创建了不支持 Hook 的成员对象,例如 `Field`。
|
||||
|
||||
**解决方案**
|
||||
|
||||
你只能 Hook `Constructor` 和 `Method`。
|
||||
|
||||
###### exception
|
||||
|
||||
::: danger IllegalStateException
|
||||
|
||||
LayoutInflatedParam View instance got null
|
||||
|
||||
:::
|
||||
|
@@ -182,7 +182,38 @@ class HookXposedEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, ...
|
||||
|
||||
#### isUsingResourcesHook 参数
|
||||
|
||||
`isUsingResourcesHook` 决定了自动处理程序是否生成针对 Resources Hook 的相关代码,此功能默认是启用的。
|
||||
`isUsingResourcesHook` 决定了自动处理程序是否生成针对 Resources Hook 的相关代码,此功能默认不启用。
|
||||
|
||||
默认情况下生成的入口类将为如下所示。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
|
||||
// ...
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若你当前的项目需要用到 Resources Hook,可以设置 `isUsingResourcesHook = true` 来启用自动生成。
|
||||
|
||||
::: warning
|
||||
|
||||
此功能在 **1.2.0** 版本后将不再默认启用,如需使用请手动启用。
|
||||
|
||||
:::
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed(isUsingResourcesHook = true)
|
||||
```
|
||||
|
||||
启用后生成的入口类将为如下所示。
|
||||
|
||||
@@ -205,31 +236,6 @@ class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage, IXpos
|
||||
}
|
||||
```
|
||||
|
||||
若你当前的项目并不需要用到 Resources Hook,可以设置 `isUsingResourcesHook = false` 来关闭自动生成。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
|
||||
```
|
||||
|
||||
关闭后生成的入口类将为如下所示。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin:no-line-numbers
|
||||
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
|
||||
// ...
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
|
||||
由于 Xposed 入口类是被 **YukiHookAPI** 动态生成的,它会同时生成如下两个文件。
|
||||
|
@@ -33,19 +33,32 @@ Host Environment
|
||||
> 上方的结构换做代码将可写为如下形式。
|
||||
|
||||
```kotlin
|
||||
// 新版写法
|
||||
TargetClass.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
before {
|
||||
// Your code here.
|
||||
}
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
// 旧版写法
|
||||
TargetClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
// Your code here.
|
||||
}
|
||||
beforeHook {
|
||||
before {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
after {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
// Resources Hook (2.x.x 将停止支持)
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
@@ -80,20 +93,17 @@ resources().hook {
|
||||
|
||||
```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 @@ loadApp(name = "com.android.browser") {
|
||||
|
||||
那么,我想继续 Hook `onStart` 方法要怎么做呢?
|
||||
|
||||
在刚刚的代码中,继续插入一个 `injectMember` 方法体即可。
|
||||
我们可以对 `ActivityClass` 使用 Kotlin 的 `apply` 方法创建一个调用空间。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```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 @@ loadApp(name = "com.android.browser") {
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
"com.example.demo.TestClass".toClass().hook {
|
||||
injectMember {
|
||||
"com.example.demo.TestClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
若 `com.example.demo` 是你要 Hook 的 APP,那么写法可以更简单。
|
||||
@@ -157,11 +166,12 @@ loadApp(name = "com.android.browser") {
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
"$packageName.TestClass".toClass().hook {
|
||||
injectMember {
|
||||
"$packageName.TestClass".toClass()
|
||||
.method {
|
||||
// Your code here.
|
||||
}.hook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip
|
||||
@@ -182,16 +192,13 @@ loadApp(name = "com.android.browser") {
|
||||
|
||||
```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 @@ loadZygote {
|
||||
|
||||
```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
|
||||
|
||||
此功能将在 2.x.x 版本停止支持并移除。
|
||||
|
||||
:::
|
||||
|
||||
假设,我们要 Hook `com.android.browser` 中 `string` 类型的 `app_name` 内容替换为 `123`。
|
||||
|
||||
在 `encase` 方法体中添加代码。
|
||||
@@ -303,15 +320,15 @@ loadZygote {
|
||||
|
||||
```kotlin
|
||||
// 设置一个变量保存当前实例
|
||||
val hookResult = injectMember {
|
||||
val hookResult =
|
||||
method {
|
||||
name = "test"
|
||||
returnType = UnitType
|
||||
}.hook {
|
||||
after {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
afterHook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
// 在适当的时候调用如下方法即可
|
||||
hookResult.remove()
|
||||
```
|
||||
@@ -321,12 +338,11 @@ hookResult.remove()
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
returnType = UnitType
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
name = "test"
|
||||
returnType = UnitType
|
||||
}.hook {
|
||||
after {
|
||||
// 直接调用如下方法即可
|
||||
removeSelf()
|
||||
}
|
||||
@@ -350,7 +366,7 @@ injectMember {
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
hook {
|
||||
// Your code here.
|
||||
}.result {
|
||||
// 处理 Hook 开始时的异常
|
||||
@@ -377,7 +393,7 @@ injectResource {
|
||||
}
|
||||
```
|
||||
|
||||
你还可以处理 Hook 的 `Class` 不存在时发生的异常。
|
||||
**(旧版本适用)** 你还可以处理 Hook 的 `Class` 不存在时发生的异常。
|
||||
|
||||
> 示例如下
|
||||
|
||||
@@ -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 @@ injectMember {
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
// ...
|
||||
}.hook {
|
||||
after {
|
||||
RuntimeException("Exception Test").throwToApp()
|
||||
}
|
||||
}
|
||||
@@ -472,11 +487,10 @@ injectMember {
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
method {
|
||||
// ...
|
||||
}
|
||||
afterHook {
|
||||
method {
|
||||
// ...
|
||||
}.hook {
|
||||
after {
|
||||
throw RuntimeException("Exception Test")
|
||||
}.onFailureThrowToApp()
|
||||
}
|
||||
@@ -486,7 +500,7 @@ injectMember {
|
||||
|
||||
::: warning
|
||||
|
||||
为了保证 Hook 调用域与宿主内调用域相互隔离,异常只有在 **beforeHook** 与 **afterHook** 回调方法体中才能抛给宿主。
|
||||
为了保证 Hook 调用域与宿主内调用域相互隔离,异常只有在 **before** 与 **after** 回调方法体中才能抛给宿主。
|
||||
|
||||
:::
|
||||
|
||||
@@ -496,42 +510,6 @@ injectMember {
|
||||
|
||||
:::
|
||||
|
||||
## 状态监听
|
||||
|
||||
在使用 `XposedHelpers` 的同学往往会在 Hook 后打印 `Unhook` 的方法确定是否 Hook 成功。
|
||||
|
||||
在 `YukiHookAPI` 中,你可以用以下方法方便地重新实现这个功能。
|
||||
|
||||
首先我们可以监听 Hook 已经准备开始。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
YourClass.hook {
|
||||
// Your code here.
|
||||
}.onPrepareHook {
|
||||
loggerD(msg = "$instanceClass hook start")
|
||||
}
|
||||
```
|
||||
|
||||
::: danger
|
||||
|
||||
**instanceClass** 建议只在 **onPrepareHook** 中使用,否则被 Hook 的 **Class** 不存在会抛出无法拦截的异常导致 Hook 进程“死掉”。
|
||||
|
||||
:::
|
||||
|
||||
然后,我们还可以对 Hook 的方法结果进行监听是否成功。
|
||||
|
||||
> 示例如下
|
||||
|
||||
```kotlin
|
||||
injectMember {
|
||||
// Your code here.
|
||||
}.onHooked { member ->
|
||||
loggerD(msg = "$member has hooked")
|
||||
}
|
||||
```
|
||||
|
||||
## 扩展用法
|
||||
|
||||
> 你可以在 Hook 过程中使用下面的方法方便地实现各种判断和功能。
|
||||
|
@@ -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 指定的 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 (固定用法)
|
||||
resources().hook {
|
||||
injectResource {
|
||||
@@ -107,7 +105,7 @@ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPa
|
||||
|
||||
#### Before/After Hook
|
||||
|
||||
`YukiHookAPI` 同样对 `HookParam` 实现了 **lambda** 方法体 `this` 用法,在 `beforeHook`、`afterHook` 等方法体内即可全局得到 `HookParam` 对象。
|
||||
`YukiHookAPI` 同样对 `HookParam` 实现了 **lambda** 方法体 `this` 用法,在 `before`、`after` 等方法体内即可全局得到 `HookParam` 对象。
|
||||
|
||||
> API 功能差异对比如下
|
||||
|
||||
@@ -115,7 +113,7 @@ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPa
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
afterHook {
|
||||
after {
|
||||
// 得到当前 Hook 的实例
|
||||
instance
|
||||
// 得到当前 Hook 的 Class 实例
|
||||
|
@@ -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