docs: update to new usage

This commit is contained in:
2023-10-03 04:17:25 +08:00
parent 375b2f3398
commit 6e658baf17
18 changed files with 649 additions and 681 deletions

View File

@@ -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

View File

@@ -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) .
:::

View File

@@ -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.
}
}
}
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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.

View File

@@ -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)
)
}
}
```

View File

@@ -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

View File

@@ -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.
}
}
}

View File

@@ -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 对象进行设置

View File

@@ -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)。
:::

View File

@@ -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.
}
}
}
}

View File

@@ -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
:::

View File

@@ -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** 动态生成的,它会同时生成如下两个文件。

View File

@@ -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 过程中使用下面的方法方便地实现各种判断和功能。

View File

@@ -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)
)
}
}
```

View File

@@ -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 实例

View File

@@ -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.
}
}
}