mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-09 12:04:07 +08:00
Added new documentations files
This commit is contained in:
9
docs-source/src/en/guide/example.md
Normal file
9
docs-source/src/en/guide/example.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Usage Example *
|
||||
|
||||
::: warning
|
||||
|
||||
The current page has not been translated yet.
|
||||
|
||||
If necessary, please temporarily switch to the **Simplified Chinese** page, or help us improve the translation of this page.
|
||||
|
||||
:::
|
186
docs-source/src/en/guide/home.md
Normal file
186
docs-source/src/en/guide/home.md
Normal file
@@ -0,0 +1,186 @@
|
||||
# Introduce
|
||||
|
||||
> This is a Hook API Framework, it does not provide any Hook function itself, it needs the support of basic Xposed API.
|
||||
|
||||
## Background
|
||||
|
||||
This is an efficient Xposed Hook API rebuilt in `Kotlin`.
|
||||
|
||||
The name is taken from ["ももくり" heroine Yuki Kurihara](https://www.bilibili.com/bangumi/play/ss5016).
|
||||
|
||||
Formerly the Innocent Xposed API used in [Development Learning Project](https://github.com/fankes/TMore), now renamed and open sourced.
|
||||
|
||||
## Usage
|
||||
|
||||
`YukiHookAPI` is built entirely with `Kotlin` `lambda` syntax.
|
||||
|
||||
Abandoning the original less friendly `XposedHelpers`, you can use it to easily create Xposed Modules and easily implement custom Hook API.
|
||||
|
||||
## Language Requirement
|
||||
|
||||
Please use `Kotlin`, the framework part of the code composition is also compatible with `Java` but the implementation of the basic Hook scene **may not work at all**.
|
||||
|
||||
All demo code in this document will be described using `Kotlin`, if you don't know how to use `Kotlin` then you may not be able to use `YukiHookAPI`.
|
||||
|
||||
Part of the Java Demo code can be found [here](https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/java), but not recommended.
|
||||
|
||||
## Source of Inspiration
|
||||
|
||||
Previously, when we built an Xposed Module, we first needed to create an `xposed_init` file under `assets`.
|
||||
|
||||
Then, manually fill in your own entry class name into the file and use `XposedHelpers` to implement our Hook logic.
|
||||
|
||||
Since `Kotlin` is the main Android development language, this API is really not very elegant to use.
|
||||
|
||||
Is there any **easy to use, light, elegant** solution?
|
||||
|
||||
With this idea, `YukiHookAPI` was born.
|
||||
|
||||
Now, we only need to write a small amount of code, and all the time and expense are handed over to automation.
|
||||
|
||||
With `Kotlin`'s elegant `lambda` writing and `YukiHookAPI`, you can make your Hook logic more beautiful and clear.
|
||||
|
||||
> The following example
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = encase {
|
||||
loadZygote {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "sym_def_app_icon"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
loadApp(name = "com.android.browser") {
|
||||
ActivityClass.hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}
|
||||
beforeHook {
|
||||
// Your code here.
|
||||
}
|
||||
afterHook {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
}
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
|
||||
|
||||
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",
|
||||
Bundle::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
|
||||
override fun afterHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||
if (lpparam.packageName == "com.android.browser")
|
||||
XposedHelpers.findAndHookMethod(
|
||||
Activity::class.java.name,
|
||||
lpparam.classLoader, "onCreate",
|
||||
Bundle::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun beforeHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
|
||||
override fun afterHookedMethod(param: MethodHookParam?) {
|
||||
// Your code here.
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
|
||||
if (resparam.packageName == "com.android.browser")
|
||||
resparam.res.setReplacement(
|
||||
"com.android.browser", "mipmap", "ic_launcher",
|
||||
moduleResources.fwd(R.mipmap.ic_launcher)
|
||||
)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
Yes, you read that right, just needing these codes can completely replace the Xposed API to achieve the same function.
|
||||
|
||||
Now, with the help of the efficient and powerful `YukiHookAPI`, you can implement a very simple Xposed Module.
|
||||
|
||||
## Suppored Hook Framework
|
||||
|
||||
The following are the `Hook Framework` and Xposed framework supported by `YukiHookAPI`.
|
||||
|
||||
| Hook Framework | ST | Description |
|
||||
| --------------------------------------------------------- | --- | ----------------------------------------------------------------------------------------- |
|
||||
| [LSPosed](https://github.com/LSPosed/LSPosed) | ✅ | Stable use in multiple scenarios |
|
||||
| [LSPatch](https://github.com/LSPosed/LSPatch) | ⭕ | WIP after this project is improved |
|
||||
| [EdXposed](https://github.com/ElderDrivers/EdXposed) | ❎ | Maintenance has stopped, no longer recommended |
|
||||
| [Pine](https://github.com/canyie/pine) | ⭕ | Only available |
|
||||
| [SandHook](https://github.com/asLody/SandHook) | ⭕ | Only available |
|
||||
| [Whale](https://github.com/asLody/whale) | ⭕ | Need [xposed-hook-based-on-whale](https://github.com/WindySha/xposed-hook-based-on-whale) |
|
||||
| [YAHFA](https://github.com/PAGalaxyLab/YAHFA) | ❗ | Need to implement the Xposed API yourself |
|
||||
| [FastHook](https://github.com/turing-technician/FastHook) | ❗ | Need to implement the Xposed API yourself |
|
||||
| [Epic](https://github.com/tiann/epic) | ❗ | Need [Dexposed](https://github.com/alibaba/dexposed) by yourself |
|
||||
| [TaiChi](https://github.com/taichi-framework/TaiChi) | ⭕ | Only available for Xposed Module |
|
||||
| [Xposed](https://github.com/rovo89/Xposed) | ❎ | Not test, no longer recommended |
|
89
docs-source/src/en/guide/knowledge.md
Normal file
89
docs-source/src/en/guide/knowledge.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Basic Knowledge
|
||||
|
||||
> Here is a collection of Xposed-related introductions and the key points of knowledge that need to be grasped before start.
|
||||
>
|
||||
> Anyone who already knows can skip it.
|
||||
|
||||
The basic knowledge content <u>**not necessarily completely accurate**</u>, please read it according to your own opinion.
|
||||
|
||||
If you find **any errors in this page, please correct it and help us improve**.
|
||||
|
||||
## Related Introduction
|
||||
|
||||
> Here's an introduction to Xposed and how Hooks work.
|
||||
|
||||
### What is Xposed
|
||||
|
||||
> Xposed Framework (Xposed Framework) is a set of open source framework services that run in Android high-privilege mode. It can affect program operation (modify the system) without modifying the APK file. Based on it, many Powerful modules that operate simultaneously without conflicting functions.
|
||||
|
||||
The above content is copied from Baidu Encyclopedia.
|
||||
|
||||
### What can Xposed do
|
||||
|
||||
> The structure below describes the basic workings and principles of Xposed.
|
||||
|
||||
```:no-line-numbers
|
||||
Xposed Framework
|
||||
└── App's Environment
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
App's Environment
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
...
|
||||
```
|
||||
|
||||
We can achieve the ultimate goal of controlling its behavior by injecting the **Host (App)** when the **Host (App)** is running.
|
||||
|
||||
This mode of operation of Xposed is called **parasitism**. The Xposed Module follows the lifecycle of the host and completes its own life course within the lifecycle of the **Host**.
|
||||
|
||||
We can call the **Host**'s methods, fields, and constructors through reflection, and use the Hook operation provided by `XposedBridge` to dynamically insert our own code before and after the method to be executed by the **Host (App)**, or completely replace the target, or even intercept.
|
||||
|
||||
### Development Process
|
||||
|
||||
Today's Xposed Manager has been completely replaced by its derivative works, and the era of **SuperSU** has ended, and now, with **Magisk**, everything behind is possible again.
|
||||
|
||||
> Its development history can be roughly divided into **Xposed(Dalvik)** → **Xposed(ART)** → **Xposed(Magisk)** → **EdXposed(Riru)**/**LSPosed(Riru/ Zygisk)**
|
||||
|
||||
### Derivatives
|
||||
|
||||
> The structure below describes how and how the Xposed-like Hook Framework works.
|
||||
|
||||
```:no-line-numbers
|
||||
App's Environment
|
||||
└── Hook Framework
|
||||
└── Hooker (Hooked)
|
||||
...
|
||||
```
|
||||
|
||||
Through the operation principle of Xposed, many frameworks of the same type have been derived. As mobile devices in today's era are more and more difficult to obtain Root permissions or even flash, and when they are not just needed, some Root-free frameworks are also produced, such as **Tai Chi**.
|
||||
|
||||
These Hook Frameworks at the ART level can also complete the Hook process with the same principle as Xposed without using the Xposed API. The operating principle of Root-free is to modify the APK and inject the Hook process into the **Host**, and control it through external modules.
|
||||
|
||||
Another product is to use the existing functions of the Android operating environment to virtualize an environment that is completely the same as the current device system, and run App in it. This is the virtual App technology **VirtualApp**, which was later derived as **VirtualXposed** .
|
||||
|
||||
The Root-free frameworks mentioned above are **Tai Chi/Wuji**, **VirtualXposed/SandVXposed**.
|
||||
|
||||
### What YukiHookAPI does
|
||||
|
||||
Since Xposed appeared until now, apart from `XposedHelpers`, which is well known to developers, there is still no set of syntactic sugar for `Kotlin` and API with complete usage encapsulation.
|
||||
|
||||
The birth of this API framework is to hope that in the current era of Xposed, more capable Xposed Module developers can avoid detours and complete the entire development process more easily and simply.
|
||||
|
||||
In the future, `YukiHookAPI` will adapt to more third-party Hook Frameworks based on the goal of using the Xposed API, so as to improve the entire ecosystem and help more developers make Xposed Module development simpler and easier to understand.
|
||||
|
||||
## Let's Started
|
||||
|
||||
Before starting, you need to have the following basics to better use `YukiHookAPI`.
|
||||
|
||||
- Grasp and understand Android development and simple system operation principles
|
||||
|
||||
- To grasp and understand the internal structure of Android APK and simple decompilation knowledge, you can refer to [Jadx](https://github.com/skylot/jadx) and [ApkTool](https://github.com/iBotPeaches/Apktool)
|
||||
|
||||
- Grasp and proficient in using Java reflection, understand simple Smali syntax, understand Dex file structure, and use reverse analysis to locate method locations
|
||||
|
||||
- Grasp the basic native [Xposed API](https://api.xposed.info) usage, understand the operation principle of Xposed
|
||||
|
||||
- Grasp Kotlin language and learn to use **Kotlin lambda**
|
||||
|
||||
- Grasp and understand Kotlin and Java mixing, calling each other, and Java bytecode generated by Kotlin
|
259
docs-source/src/en/guide/move-to-new-api.md
Normal file
259
docs-source/src/en/guide/move-to-new-api.md
Normal file
@@ -0,0 +1,259 @@
|
||||
# Migrate from Xposed API
|
||||
|
||||
> If you are familiar with Xposed API, you can refer to the same point below to quickly migrate your API to `YukiHookAPI`.
|
||||
|
||||
## Migrate Hook Entry Point
|
||||
|
||||
> Migrated from `XC_LoadPackage.LoadPackageParam` to `PackageParam`.
|
||||
|
||||
`YukiHookAPI` implements the `lambda` method body `this` usage for `PackageParam`, and the `PackageParam` object can be obtained globally in the `encase` method body.
|
||||
|
||||
> The API function differences are compared as follows
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
override fun onHook() = encase {
|
||||
// Get the package name of the current Hook
|
||||
packageName
|
||||
// Get the ApplicationInfo of the current Hook
|
||||
appInfo
|
||||
// Get the system context object
|
||||
systemContext
|
||||
// Get the host Application lifecycle
|
||||
appContext
|
||||
// Hook specified app
|
||||
loadApp(name = "com.demo.test") {
|
||||
// Class Hook
|
||||
findClass("com.demo.test.TestClass").hook {
|
||||
injectMember {
|
||||
method {
|
||||
name = "test"
|
||||
param(BooleanType)
|
||||
}
|
||||
afterHook {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
// Resources Hook (fixed usage)
|
||||
resources().hook {
|
||||
injectResource {
|
||||
conditions {
|
||||
name = "ic_launcher"
|
||||
mipmap()
|
||||
}
|
||||
replaceToModuleResource(R.mipmap.ic_launcher)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
private lateinit var moduleResources: XModuleResources
|
||||
|
||||
override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
|
||||
moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
|
||||
}
|
||||
|
||||
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
|
||||
// Get the package name of the current Hook
|
||||
lpparam.packageName
|
||||
// Get the ApplicationInfo of the current Hook
|
||||
lpparam.applicationInfo
|
||||
// Get the system context object
|
||||
// There is no ready-made calling method in the native Xposed API, you need to reflect ActivityThread to achieve it
|
||||
// Get the host Application lifecycle
|
||||
AndroidAppHelper.currentApplication()
|
||||
// Class Hook
|
||||
if(lpparam.packageName == "com.demo.test")
|
||||
XposedHelpers.findAndHookMethod(
|
||||
"com.demo.test.TestClass", lpparam.classLoader,
|
||||
"test", Boolean::class.java,
|
||||
object : XC_MethodHook() {
|
||||
override fun afterHookedMethod(param: MethodHookParam) {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
|
||||
// Get the package name of the current Hook
|
||||
resparam.packageName
|
||||
// Resources Hook
|
||||
resparam.res.setReplacement(
|
||||
"com.demo.test", "mipmap", "ic_launcher",
|
||||
moduleResources.fwd(R.mipmap.ic_launcher)
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Migrate Hook Method Body
|
||||
|
||||
> Migrated from `XC_MethodHook.MethodHookParam` to `HookParam`.
|
||||
|
||||
### 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`.
|
||||
|
||||
> The API function differences are compared as follows
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
afterHook {
|
||||
// Get the current Hook instance
|
||||
instance
|
||||
// Get the Class instance of the current Hook
|
||||
instanceClass
|
||||
// Get and cast the current Hook instance to the specified type T
|
||||
instance<T>()
|
||||
// Get the method parameter array
|
||||
args
|
||||
// Get the first T of the method parameter
|
||||
args().first().cast<T>()
|
||||
// Get the last bit of the method parameter T
|
||||
args().last().cast<T>()
|
||||
// Get any subscript T of the method parameter, here is an example of 2
|
||||
args(index = 2).cast<T>()
|
||||
// Set any subscript of the method parameter, here is an example of 2
|
||||
args(index = 2).set(...)
|
||||
// Get the return value
|
||||
result
|
||||
// Get the return value and cast to T
|
||||
result<T>()
|
||||
// Modify the content of the return value
|
||||
result = ...
|
||||
// Remove the content of the return value
|
||||
resultNull()
|
||||
// Throw an exception to the Hook app
|
||||
Throwable("Fatal").throwToApp()
|
||||
// Execute the original method without hook and call with the original method parameters, generics can be omitted
|
||||
callOriginal<Any?>()
|
||||
// Execute the original method without Hook and customize the method parameter call, the generic type can be omitted
|
||||
invokeOriginal<Any?>(...)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
override fun afterHookedMethod(param: MethodHookParam) {
|
||||
// Get the current Hook instance
|
||||
param.thisObject
|
||||
// Get the Class instance of the current Hook
|
||||
param.thisObject.javaClass
|
||||
// Get and cast the current Hook instance to the specified type T
|
||||
param.thisObject as T
|
||||
// Get the method parameter array
|
||||
param.args
|
||||
// Get the first T of the method parameter
|
||||
param.args[0] as T
|
||||
// Get the last bit of the method parameter T
|
||||
param.args[param.args.lastIndex] as T
|
||||
// Get any subscript T of the method parameter, here is an example of 2
|
||||
param.args[2] as T
|
||||
// Set any subscript of the method parameter, here is an example of 2
|
||||
param.args[2] = ...
|
||||
// Get the return value
|
||||
param.result
|
||||
// Get the return value and cast to T
|
||||
param.result as T
|
||||
// Modify the content of the return value
|
||||
param.result = ...
|
||||
// Remove the content of the return value
|
||||
param.result = null
|
||||
// Throw an exception to the Hook app
|
||||
param.throwable = Throwable("Fatal")
|
||||
// Execute the original method without hooking
|
||||
XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
### Replace Hook
|
||||
|
||||
The `replaceHook` method is special, and the `YukiHookAPI` makes a variety of forms for it to choose from.
|
||||
|
||||
> The API function differences are compared as follows
|
||||
|
||||
:::: code-group
|
||||
::: code-group-item Yuki Hook API
|
||||
|
||||
```kotlin
|
||||
/// A method with no return value void
|
||||
|
||||
replaceUnit {
|
||||
// Implement the replaced logic directly here
|
||||
}
|
||||
|
||||
/// A method with a return value
|
||||
|
||||
replaceAny {
|
||||
// Implement the replaced logic here
|
||||
// ...
|
||||
// Need to return the return value corresponding to the method, no need to write return, just put the parameter in the last digit
|
||||
// Assuming the return value of this method is an Int, we just need to ensure that the last bit is the return value we need
|
||||
0
|
||||
}
|
||||
|
||||
/// For some methods, we just need to replace their return value, then there are the following implementations
|
||||
/// It should be noted that the parameters passed in by the method of directly replacing the return value are fixed. If you want to dynamically replace the return value, please use the above replaceAny method body
|
||||
|
||||
// Replace with the return value you need
|
||||
replaceTo(...)
|
||||
// Replace with return value of type Boolean
|
||||
replaceToTrue()
|
||||
// Intercept return value
|
||||
intercept()
|
||||
```
|
||||
|
||||
:::
|
||||
::: code-group-item Xposed API
|
||||
|
||||
```kotlin
|
||||
/// A method with no return value void
|
||||
|
||||
override fun replaceHookedMethod(param: MethodHookParam): Any? {
|
||||
// Implement the replaced logic directly here
|
||||
return null
|
||||
}
|
||||
|
||||
/// A method with a return value
|
||||
|
||||
override fun replaceHookedMethod(param: MethodHookParam): Int {
|
||||
// Implement the replaced logic here
|
||||
// ...
|
||||
// Assume the return value of this method is an Int
|
||||
return 0
|
||||
}
|
||||
|
||||
/// For some methods, we just need to replace their return value, then there are the following implementations
|
||||
|
||||
// Replace with the return value you need
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = ...
|
||||
// Replace with return value of type Boolean
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = true
|
||||
// Intercept return value
|
||||
override fun replaceHookedMethod(param: MethodHookParam) = null
|
||||
```
|
||||
|
||||
:::
|
||||
::::
|
||||
|
||||
## Migrate Other Features
|
||||
|
||||
`YukiHookAPI` is a complete rewrite of the Xposed API, you can refer to [API Document](../api/home) and [Special Features](../api/special-features/reflection) to determine some functional Migration and use.
|
208
docs-source/src/en/guide/quick-start.md
Normal file
208
docs-source/src/en/guide/quick-start.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# Quick Start
|
||||
|
||||
> Integrate `YukiHookAPI` into your project.
|
||||
|
||||
## Environment Requirements
|
||||
|
||||
- Windows 7 and above / macOS 10.14 and above / Linux distributions (Arch/Debian)
|
||||
|
||||
- Android Studio 2021.1 and above
|
||||
|
||||
- IntelliJ IDEA 2021.1 and above
|
||||
|
||||
- Kotlin 1.7.0 and above
|
||||
|
||||
- Android Gradle Plugin 7.0 and above
|
||||
|
||||
- Gradle 7.0 and above
|
||||
|
||||
- JVM 11 and above (Since API `1.0.80`)
|
||||
|
||||
## Automatically build the project
|
||||
|
||||
`YukiHookAPI` provides an automated build tool that can help you quickly build an Android standard project template with Xposed Module dependencies, and use the built template to start the next step directly.
|
||||
|
||||
You can [click here](../tools/yukihookapi-projectbuilder) to check it out.
|
||||
|
||||
## Manually configure the project
|
||||
|
||||
If you don't want to use automated build tools, you can still manually configure project dependencies as follows.
|
||||
|
||||
### Create Project
|
||||
|
||||
Use `Android Studio` or `IntelliJ IDEA` to create a new Android project and select `Kotlin` in the `Language` column to automatically add basic dependencies.
|
||||
|
||||
### Integration Dependencies
|
||||
|
||||
Add dependencies to your project `build.gradle`.
|
||||
|
||||
> The following example
|
||||
|
||||
```groovy
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
// ❗If your Plugin version is too low, be sure to add it as an Xposed Module, other cases are optional
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
|
||||
// ❗Be sure to add it as an Xposed Module, optional in other cases
|
||||
maven { url "https://api.xposed.info/" }
|
||||
// MavenCentral has a 2-hour cache, if you cannot integrate the latest version, please add this address
|
||||
maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
|
||||
}
|
||||
```
|
||||
|
||||
Add `plugin` to your app `build.gradle`.
|
||||
|
||||
> The following example
|
||||
|
||||
```groovy
|
||||
plugins {
|
||||
// ❗Be sure to add it as an Xposed Module, optional in other cases
|
||||
id 'com.google.devtools.ksp' version '<ksp-version>'
|
||||
}
|
||||
```
|
||||
|
||||
Add dependencies to your app `build.gradle`.
|
||||
|
||||
> The following example
|
||||
|
||||
```groovy
|
||||
dependencies {
|
||||
// base dependencies
|
||||
implementation 'com.highcapable.yukihookapi:api:<yuki-version>'
|
||||
// ❗Be sure to add it as an Xposed Module, optional in other cases
|
||||
compileOnly 'de.robv.android.xposed:api:82'
|
||||
// ❗Be sure to add it as an Xposed Module, optional in other cases
|
||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:<yuki-version>'
|
||||
}
|
||||
```
|
||||
|
||||
Please modify **<ksp-version>** to the latest version from [here](https://github.com/google/ksp/releases) **(Please choose your current corresponding Kotlin version)**.
|
||||
|
||||
Please modify **<yuki-version>** to the latest version [here](../about/changelog).
|
||||
|
||||
::: danger
|
||||
|
||||
The **api** of **YukiHookAPI** and the versions that **ksp-xposed** depend on must correspond one by one, otherwise a version mismatch error will occur.
|
||||
|
||||
:::
|
||||
|
||||
Modify the JVM version of `Kotlin` to 11 and above in your app `build.gradle`.
|
||||
|
||||
> The following example
|
||||
|
||||
```groovy
|
||||
android {
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '11'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: warning
|
||||
|
||||
Since API **1.0.80** version, the default JVM version is 11, and 1.8 and below are no longer supported.
|
||||
|
||||
:::
|
||||
|
||||
### Use as Xposed Module
|
||||
|
||||
Add the base code to your `AndroidManifest.xml`.
|
||||
|
||||
> The following example
|
||||
|
||||
```xml
|
||||
<!-- Set as Xposed Module -->
|
||||
<meta-data
|
||||
android:name="xposedmodule"
|
||||
android:value="true" />
|
||||
|
||||
<!-- set your module description -->
|
||||
<meta-data
|
||||
android:name="xposeddescription"
|
||||
android:value="Fill in your Xposed Module description" />
|
||||
|
||||
<!-- The minimum Xposed version number, if you are using EdXposed/LSPosed, the minimum recommended is 93 -->
|
||||
<meta-data
|
||||
android:name="xposedminversion"
|
||||
android:value="93" />
|
||||
|
||||
<!-- Optional: configure support for New XSharePrefs without adjusting xposedminversion to 93 -->
|
||||
<meta-data
|
||||
android:name="xposedsharedprefs"
|
||||
android:value="true"/>
|
||||
```
|
||||
|
||||
Create a Hook entry class in your project, inherit from `IYukiHookXposedInit` and add the annotation `@InjectYukiHookWithXposed`.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
@InjectYukiHookWithXposed
|
||||
class HookEntry : IYukiHookXposedInit {
|
||||
|
||||
override fun onHook() = YukiHookAPI.encase {
|
||||
// Your code here.
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
::: tip Suggestion
|
||||
|
||||
You can inherit **Application** of your module app from **ModuleApplication** to achieve a complete user experience.
|
||||
|
||||
For more functions, please refer to [ModuleApplication](../api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication).
|
||||
|
||||
:::
|
||||
|
||||
Then, you can start writing Hook code.
|
||||
|
||||
For configuration details related to use as an Xposed Module, you can [click here](../config/xposed-using) to continue reading.
|
||||
|
||||
If you are currently using Xposed API, you can refer to [Migrating from Xposed API](../guide/move-to-new-api).
|
||||
|
||||
### Use as Hook API
|
||||
|
||||
#### Integration
|
||||
|
||||
Create your custom `Application`.
|
||||
|
||||
::: danger
|
||||
|
||||
Regardless of the **Hook Framework** you use, you need to add its docking Xposed dependency support.
|
||||
|
||||
If the target **Hook Framework** does not integrate Xposed API, you need to implement and connect **XposedBridge** by yourself.
|
||||
|
||||
:::
|
||||
|
||||
Add `YukiHookAPI.encase` method to `attachBaseContext`.
|
||||
|
||||
> The following example
|
||||
|
||||
```kotlin
|
||||
override fun attachBaseContext(base: Context?) {
|
||||
// Load Hook Framework
|
||||
//
|
||||
// Your code here.
|
||||
//
|
||||
// Load YukiHookAPI
|
||||
YukiHookAPI.encase(base) {
|
||||
// Your code here.
|
||||
}
|
||||
super.attachBaseContext(base)
|
||||
}
|
||||
```
|
||||
|
||||
Then, you can start writing Hook code in much the same way you would use it as an Xposed Module.
|
||||
|
||||
For configuration details related to use as a Hook API, you can [click here](../config/api-using) to continue reading.
|
||||
|
||||
::: warning
|
||||
|
||||
**YukiHookModuleStatus**, **YukiHookModulePrefs**, **YukiHookDataChannel** and Resources Hook functionality will not work when using a custom Hook Framework instead of the full Xposed Module.
|
||||
|
||||
:::
|
Reference in New Issue
Block a user