diff --git a/.idea/compiler.xml b/.idea/compiler.xml index fb7f4a8a..cc12a2ed 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,9 @@ - + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 4c8a5d41..39c318f1 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -12,6 +12,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 71110e38..ff7db3dc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,6 +1,7 @@ plugins { id 'com.android.application' id 'org.jetbrains.kotlin.android' + id 'com.google.devtools.ksp' version '1.6.10-1.0.2' } android { @@ -32,12 +33,16 @@ android { } dependencies { + // Used 82 API Version + compileOnly 'de.robv.android.xposed:api:82' // Implementation API implementation project(':yukihookapi') + ksp project(':yukihookapi-ksp-xposed') implementation 'androidx.core:core-ktx:1.7.0' implementation 'androidx.appcompat:appcompat:1.4.1' implementation 'com.google.android.material:material:1.5.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.3' + implementation project(path: ':yukihookapi') testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' diff --git a/app/src/main/assets/xposed_init b/app/src/main/assets/xposed_init new file mode 100644 index 00000000..2f660c0f --- /dev/null +++ b/app/src/main/assets/xposed_init @@ -0,0 +1 @@ +com.highcapable.yukihookapi.demo.InjectTest_YukiHookXposedInit \ No newline at end of file diff --git a/app/src/main/java/com/highcapable/yukihookapi/demo/hook/MainHooker.kt b/app/src/main/java/com/highcapable/yukihookapi/demo/hook/MainHooker.kt index 01d0c496..4e00d9c4 100644 --- a/app/src/main/java/com/highcapable/yukihookapi/demo/hook/MainHooker.kt +++ b/app/src/main/java/com/highcapable/yukihookapi/demo/hook/MainHooker.kt @@ -36,6 +36,7 @@ import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.type.BundleClass import com.highcapable.yukihookapi.hook.type.StringType +// for test class MainHooker : YukiBaseHooker() { override fun onHook() = diff --git a/app/src/main/java/com/highcapable/yukihookapi/demo/hook/inject/MainInjecter.kt b/app/src/main/java/com/highcapable/yukihookapi/demo/hook/inject/MainInjecter.kt index b838f6d7..2386dd09 100644 --- a/app/src/main/java/com/highcapable/yukihookapi/demo/hook/inject/MainInjecter.kt +++ b/app/src/main/java/com/highcapable/yukihookapi/demo/hook/inject/MainInjecter.kt @@ -35,6 +35,8 @@ import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed import com.highcapable.yukihookapi.demo.BuildConfig import com.highcapable.yukihookapi.demo.InjectTest import com.highcapable.yukihookapi.demo.MainActivity +import com.highcapable.yukihookapi.demo.hook.MainHooker +import com.highcapable.yukihookapi.demo.hook.SecondHooker import com.highcapable.yukihookapi.hook.factory.encase import com.highcapable.yukihookapi.hook.factory.findMethod import com.highcapable.yukihookapi.hook.proxy.YukiHookXposedInitProxy @@ -48,7 +50,7 @@ class MainInjecter : YukiHookXposedInitProxy { override fun onHook() { // 方案 1 - // encase(BuildConfig.APPLICATION_ID, MainHooker(), SecondHooker()) + encase(MainHooker(), SecondHooker()) // 方案 2 encase(BuildConfig.APPLICATION_ID) { loadApp(name = BuildConfig.APPLICATION_ID) { diff --git a/build.gradle b/build.gradle index 185268c6..f6f49f8a 100644 --- a/build.gradle +++ b/build.gradle @@ -6,6 +6,7 @@ buildscript { maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' } maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' } maven { url "https://www.jitpack.io" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } mavenCentral() } dependencies { @@ -23,6 +24,7 @@ allprojects { maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' } maven { url 'https://maven.aliyun.com/nexus/content/repositories/jcenter' } maven { url "https://www.jitpack.io" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } mavenCentral() } } diff --git a/settings.gradle b/settings.gradle index 21f6fa4b..ab9623ef 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,3 +1,4 @@ rootProject.name = "YukiHookAPI" include ':app' include ':yukihookapi' +include ':yukihookapi-ksp-xposed' diff --git a/yukihookapi-ksp-xposed/.gitignore b/yukihookapi-ksp-xposed/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/yukihookapi-ksp-xposed/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/yukihookapi-ksp-xposed/build.gradle b/yukihookapi-ksp-xposed/build.gradle new file mode 100644 index 00000000..8d8f7265 --- /dev/null +++ b/yukihookapi-ksp-xposed/build.gradle @@ -0,0 +1,20 @@ +plugins { + id 'java-library' + id 'org.jetbrains.kotlin.jvm' + id 'com.google.devtools.ksp' version '1.6.10-1.0.2' +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +dependencies { + // Used 82 API Version + compileOnly 'de.robv.android.xposed:api:82' + compileOnly 'androidx.annotation:annotation:1.3.0' + implementation project(':yukihookapi') + implementation 'com.google.auto.service:auto-service-annotations:1.0.1' + compileOnly 'com.google.devtools.ksp:symbol-processing-api:1.6.10-1.0.2' + ksp 'dev.zacsweers.autoservice:auto-service-ksp:1.0.0' +} \ No newline at end of file diff --git a/yukihookapi-ksp-xposed/src/main/java/com/highcapable/yukihookapi_ksp_xposed/YukiHookXposedProcessor.kt b/yukihookapi-ksp-xposed/src/main/java/com/highcapable/yukihookapi_ksp_xposed/YukiHookXposedProcessor.kt new file mode 100644 index 00000000..9a45b3af --- /dev/null +++ b/yukihookapi-ksp-xposed/src/main/java/com/highcapable/yukihookapi_ksp_xposed/YukiHookXposedProcessor.kt @@ -0,0 +1,183 @@ +/** + * MIT License + * + * Copyright (C) 2022 HighCapable + * + * This file is part of YukiHookAPI. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * This file is Created by fankes on 2022/2/5. + */ +@file:Suppress("unused") + +package com.highcapable.yukihookapi_ksp_xposed + +import com.google.auto.service.AutoService +import com.google.devtools.ksp.processing.* +import com.google.devtools.ksp.symbol.FileLocation +import com.google.devtools.ksp.symbol.KSAnnotated +import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed +import java.io.File + +/** + * 这是 YukiHook API 的自动生成处理类 - 核心基于 KSP + * + * 可以帮你快速生成 Xposed 入口类和包名 + * + * 你只需要添加 [InjectYukiHookWithXposed] 注释即可完美解决一切问题 + */ +@AutoService(SymbolProcessorProvider::class) +class YukiHookXposedProcessor : SymbolProcessorProvider { + + override fun create(environment: SymbolProcessorEnvironment) = object : SymbolProcessor { + + /** 插入 Xposed 尾部的名称 */ + private val xposedClassShortName = "_YukiHookXposedInit" + + /** + * 创建一个环境方法体方便调用 + * @param env 方法体 + */ + private fun environment(env: SymbolProcessorEnvironment.() -> Unit) = runCatching { environment.apply(env) } + + override fun process(resolver: Resolver) = emptyList().let { + injectProcess(resolver) + it + } + + /** + * 开始作业入口 + * @param resolver [Resolver] + */ + private fun injectProcess(resolver: Resolver) = environment { + var injectOnce = true + resolver.getSymbolsWithAnnotation(InjectYukiHookWithXposed::class.java.name) + .asSequence() + .filterIsInstance().forEach { + if (injectOnce) { + injectAssets( + codePath = (it.location as? FileLocation?)?.filePath ?: "", + packageName = it.packageName.asString(), + className = it.simpleName.asString() + ) + injectClass(it.packageName.asString(), it.simpleName.asString()) + } else logger.error(message = "@InjectYukiHookWithXposed only can be use in once times") + /** 仅处理第一个标记的类 - 再次处理将拦截并报错 */ + injectOnce = false + } + } + + /** + * 自动生成 Xposed assets 入口文件 + * @param codePath 注释类的完整代码文件路径 + * @param packageName 包名 + * @param className 类名 + */ + private fun injectAssets(codePath: String, packageName: String, className: String) = environment { + runCatching { + if (codePath.isBlank()) error("Project CodePath is empty") + val projectPath = when (File.separator) { + "\\" -> { + if (codePath.contains("\\src\\main\\")) + codePath.split("\\src\\main\\")[0] + "\\src\\main\\" + else error("Project source path must be ..\\src\\main\\..") + } + "/" -> { + if (codePath.contains("/src/main/")) + codePath.split("/src/main/")[0] + "/src/main/" + else error("Project source path must be ../src/main/..") + } + else -> error("Unix File Separator unknown") + } + File("$projectPath${File.separator}assets").also { assFile -> + if (!assFile.exists() || !assFile.isDirectory) { + assFile.delete() + assFile.mkdirs() + } + File("${assFile.absolutePath}${File.separator}xposed_init") + .writeText(text = "$packageName.${className}$xposedClassShortName") + } + }.onFailure { + logger.error(message = "Inject XposedAssets Failed! $it") + } + } + + /** + * 注入并生成指定类 + * @param packageName 包名 + * @param className 类名 + */ + private fun injectClass(packageName: String, className: String) = environment { + var realPackageName = "unknown" + if (packageName.contains(".hook.")) + realPackageName = packageName.split(".hook.")[0] + else logger.warn(message = "YukiHook cannot identify your App's package name,please refer to the wiki https://github.com/fankes/YukiHookAPI/wiki to fix the package name or manually configure the package name") + codeGenerator.createNewFile(Dependencies.ALL_FILES, packageName, fileName = "${className}_YukiHookXposedInit") + .apply { + /** 🤡 由于插入的代码量不大就不想用工具生成了 */ + write( + ("@file:Suppress(\"EXPERIMENTAL_API_USAGE\")\n" + + "\n" + + "package $packageName\n" + + "\n" + + "import androidx.annotation.Keep\n" + + "import com.highcapable.yukihookapi.YukiHookAPI\n" + + "import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus\n" + + "import com.highcapable.yukihookapi.hook.log.loggerE\n" + + "import de.robv.android.xposed.IXposedHookLoadPackage\n" + + "import de.robv.android.xposed.XC_MethodReplacement\n" + + "import de.robv.android.xposed.XposedHelpers\n" + + "import de.robv.android.xposed.callbacks.XC_LoadPackage\n" + + "import $packageName.$className\n" + + "\n" + + "@Keep\n" + + "class $className$xposedClassShortName : IXposedHookLoadPackage {\n" + + "\n" + + " override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" + + " if (lpparam == null) return\n" + + " runCatching {\n" + + " $className().onHook()\n" + + " }.onFailure {\n" + + " loggerE(msg = \"Try to load $packageName.$className Failed\", e = it)\n" + + " }\n" + + " YukiHookAPI.modulePackageName.ifEmpty {\n" + + " YukiHookAPI.modulePackageName = \"$realPackageName\"\n" + + " \"$realPackageName\"\n" + + " }.also {\n" + + " if (lpparam.packageName == it)\n" + + " XposedHelpers.findAndHookMethod(\n" + + " YukiHookModuleStatus::class.java.name,\n" + + " lpparam.classLoader,\n" + + " \"isActive\",\n" + + " object : XC_MethodReplacement() {\n" + + " override fun replaceHookedMethod(param: MethodHookParam?) = true\n" + + " })\n" + + " }\n" + + " YukiHookAPI.onXposedLoaded(lpparam)\n" + + " }\n" + + "}").toByteArray() + ) + flush() + close() + } + } + } +} \ No newline at end of file diff --git a/yukihookapi/build.gradle b/yukihookapi/build.gradle index 3452abd2..5731c2c0 100644 --- a/yukihookapi/build.gradle +++ b/yukihookapi/build.gradle @@ -1,41 +1,19 @@ plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' + id 'java-library' + id 'org.jetbrains.kotlin.jvm' } -android { - compileSdk 31 - - defaultConfig { - minSdk 22 - targetSdk 31 - - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - consumerProguardFiles "consumer-rules.pro" - } - - sourceSets { main { java.srcDirs("src/main/kotlin") } } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - kotlinOptions { - jvmTarget = '1.8' - } +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + sourceSets.main { java.srcDir("src/api/kotlin") } } +kotlin { sourceSets.main { kotlin.srcDir("src/api/kotlin") } } + dependencies { // Used 82 API Version compileOnly 'de.robv.android.xposed:api:82' - implementation 'androidx.appcompat:appcompat:1.4.1' - testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'androidx.test.ext:junit:1.1.3' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + compileOnly fileTree(include: ['android-stub.jar'], dir: 'libs') + implementation 'androidx.annotation:annotation:1.3.0' } \ No newline at end of file diff --git a/yukihookapi/consumer-rules.pro b/yukihookapi/consumer-rules.pro deleted file mode 100644 index e69de29b..00000000 diff --git a/yukihookapi/libs/android-stub.jar b/yukihookapi/libs/android-stub.jar new file mode 100644 index 00000000..ba207008 Binary files /dev/null and b/yukihookapi/libs/android-stub.jar differ diff --git a/yukihookapi/proguard-rules.pro b/yukihookapi/proguard-rules.pro deleted file mode 100644 index 481bb434..00000000 --- a/yukihookapi/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Uncomment this to preserve the line number information for -# debugging stack traces. -#-keepattributes SourceFile,LineNumberTable - -# If you keep the line number information, uncomment this to -# hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt similarity index 74% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt index 337379b0..a416a940 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/YukiHookAPI.kt @@ -30,11 +30,14 @@ package com.highcapable.yukihookapi import android.content.pm.ApplicationInfo +import androidx.annotation.Keep import com.highcapable.yukihookapi.YukiHookAPI.encase import com.highcapable.yukihookapi.annotation.DoNotUseField +import com.highcapable.yukihookapi.annotation.DoNotUseMethod import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker -import com.highcapable.yukihookapi.param.CustomParam -import com.highcapable.yukihookapi.param.PackageParam +import com.highcapable.yukihookapi.hook.param.CustomParam +import com.highcapable.yukihookapi.hook.param.PackageParam +import de.robv.android.xposed.callbacks.XC_LoadPackage /** * YukiHook 的装载 API 调用类 @@ -43,22 +46,36 @@ import com.highcapable.yukihookapi.param.PackageParam * * 模块装载方式已经自动对接 Xposed API - 可直接调用 [encase] 完成操作 */ +@Keep object YukiHookAPI { /** 全局标识 */ const val TAG = "YukiHookAPI" - /** Xposed Hook API 绑定的模块包名 */ + /** + * Xposed Hook API 绑定的模块包名 - 未写将自动生成 + * - 你不应该设置此变量的名称 - 请使用 [encase] 装载模块包名 + */ @DoNotUseField - internal var modulePackageName = "" + @Keep + var modulePackageName = "" /** Xposed Hook API 方法体回调 */ - @DoNotUseField - internal var packageParamCallback: (PackageParam.() -> Unit)? = null + private var packageParamCallback: (PackageParam.() -> Unit)? = null + + /** + * 装载 Xposed API 回调 + * + * - 装载代码将自动生成 - 你不应该手动使用此方法装载 Xposed 模块事件 + * @param lpparam Xposed [XC_LoadPackage.LoadPackageParam] + */ + @DoNotUseMethod + @Keep + fun onXposedLoaded(lpparam: XC_LoadPackage.LoadPackageParam) = packageParamCallback?.invoke(PackageParam(lpparam)) /** * 作为模块装载调用入口方法 - Xposed API - * @param moduleName 模块包名 - 填入当前的 BuildConfig.APPLICATION_ID + * @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成 * @param initiate Hook 方法体 */ fun encase(moduleName: String = "", initiate: PackageParam.() -> Unit) { @@ -68,7 +85,7 @@ object YukiHookAPI { /** * 作为模块装载调用入口方法 - Xposed API - * @param moduleName 模块包名 - 填入当前的 BuildConfig.APPLICATION_ID + * @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成 * @param hooker Hook 子类数组 - 必填不能为空 * @throws IllegalStateException 如果 [hooker] 是空的 */ diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseField.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseField.kt similarity index 96% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseField.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseField.kt index 067ebe64..b67e7034 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseField.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseField.kt @@ -45,7 +45,7 @@ package com.highcapable.yukihookapi.annotation ) @Retention(AnnotationRetention.BINARY) /** - * ⚠️ 警告方法外部调用声明 + * -️ 警告方法外部调用声明 * 此方法除继承和接口外不应该在这里被调用 * 如果调用此方法可能会出现错误或 APP 发生异常 */ diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseMethod.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseMethod.kt similarity index 96% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseMethod.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseMethod.kt index 652d06de..c34423d0 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseMethod.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/DoNotUseMethod.kt @@ -45,7 +45,7 @@ package com.highcapable.yukihookapi.annotation ) @Retention(AnnotationRetention.BINARY) /** - * ⚠️ 警告方法外部调用声明 + * - 警告方法外部调用声明 * 此方法除继承和接口外不应该在这里被调用 * 如果调用此方法可能会出现错误或 APP 发生异常 */ diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/UseLessField.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/UseLessField.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/UseLessField.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/UseLessField.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/UseLessMethod.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/UseLessMethod.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/UseLessMethod.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/UseLessMethod.kt diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.kt new file mode 100644 index 00000000..90f200f1 --- /dev/null +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.kt @@ -0,0 +1,65 @@ +/** + * MIT License + * + * Copyright (C) 2022 HighCapable + * + * This file is part of YukiHookAPI. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * This file is Created by fankes on 2022/2/3. + */ +@file:Suppress("unused") + +package com.highcapable.yukihookapi.annotation.xposed + +import androidx.annotation.Keep +import com.highcapable.yukihookapi.YukiHookAPI +import com.highcapable.yukihookapi.hook.proxy.YukiHookXposedInitProxy + +/** + * 标识 YukiHook 注入 Xposed 入口的类注释 + * + * - 你的项目 source 目录必须为 ../src/main/ 后方内容根据你自行喜好定义即可 - 否则编译会报错 + * + * - 你的 Hook 入口类(HookEntryClass) 需要按照此格式创建 --> 你的模块APP包名/hook/...可允许子包名存在.../你的入口类 + * + * 例子:com.example.module.hook.MainHook、com.example.module.hook.inject.MainInject、com.example.module.hook.custom.CustomClass + * + * 你的 xposed_init 入口将被自动生成为 --> 你的模块APP包名/hook/...可允许子包名存在.../你的入口类_YukiHookXposedInit + * + * 例子:com.example.module.hook.MainHook_YukiHookXposedInit + * + * - 你的模块包名将被这样识别:|com.example.module|.hook... + * + * - 若你不喜欢这样创建类 - 没问题 - 请在 [YukiHookAPI.encase] 中自行指定模块包名即可 - 但不按照规则定义包名你将会收到编译警告 + * + * 例子:YukiHookAPI.encase(moduleName = "com.example.module", ...) + * + * - 最后这一点很重要:请不要随意修改项目 ../src/main/assets/xposed_init 中的内容 - 否则可能会导致模块装载发生错误 + * + * 你必须将被注释的类继承于 [YukiHookXposedInitProxy] 接口实现 [YukiHookXposedInitProxy.onHook] 方法 - 否则编译会报错 + * + * 只能拥有一个 Hook 入口 - 若存在多个注释编译会报错 + * + * 详情请参考 [YukiHookAPI Wiki](https://github.com/fankes/YukiHookAPI/wiki) + */ +@Target(AnnotationTarget.CLASS) +@Keep +annotation class InjectYukiHookWithXposed \ No newline at end of file diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt similarity index 99% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt index d70a3e5c..2612dfb5 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiHookCreater.kt @@ -34,8 +34,8 @@ import com.highcapable.yukihookapi.hook.core.finder.ConstructorFinder import com.highcapable.yukihookapi.hook.core.finder.FieldFinder import com.highcapable.yukihookapi.hook.core.finder.MethodFinder import com.highcapable.yukihookapi.hook.log.loggerE -import com.highcapable.yukihookapi.param.HookParam -import com.highcapable.yukihookapi.param.PackageParam +import com.highcapable.yukihookapi.hook.param.HookParam +import com.highcapable.yukihookapi.hook.param.PackageParam import de.robv.android.xposed.XC_MethodHook import de.robv.android.xposed.XC_MethodReplacement import de.robv.android.xposed.XposedBridge diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/finder/ConstructorFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/ConstructorFinder.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/finder/ConstructorFinder.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/ConstructorFinder.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/FieldFinder.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/MethodFinder.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.kt similarity index 97% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.kt index 7c50214a..419fef8d 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.kt @@ -29,8 +29,8 @@ package com.highcapable.yukihookapi.hook.entity import com.highcapable.yukihookapi.YukiHookAPI import com.highcapable.yukihookapi.annotation.DoNotUseMethod +import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.proxy.YukiHookXposedInitProxy -import com.highcapable.yukihookapi.param.PackageParam /** * YukiHook 的子类实现 diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.kt similarity index 84% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.kt index 9f8d4aa6..07c0590a 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.kt @@ -35,12 +35,12 @@ import android.net.Uri import android.os.Bundle import com.highcapable.yukihookapi.YukiHookAPI import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker +import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.proxy.YukiHookXposedInitProxy -import com.highcapable.yukihookapi.param.PackageParam /** * 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI] - * @param moduleName 模块包名 - 填入当前的 BuildConfig.APPLICATION_ID + * @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成 * @param initiate Hook 方法体 */ fun YukiHookXposedInitProxy.encase(moduleName: String = "", initiate: PackageParam.() -> Unit) = @@ -48,11 +48,18 @@ fun YukiHookXposedInitProxy.encase(moduleName: String = "", initiate: PackagePar /** * 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI] - * @param moduleName 模块包名 - 填入当前的 BuildConfig.APPLICATION_ID * @param hooker Hook 子类数组 - 必填不能为空 * @throws IllegalStateException 如果 [hooker] 是空的 */ -fun YukiHookXposedInitProxy.encase(moduleName: String = "", vararg hooker: YukiBaseHooker) = +fun YukiHookXposedInitProxy.encase(vararg hooker: YukiBaseHooker) = YukiHookAPI.encase(hooker = hooker) + +/** + * 在 [YukiHookXposedInitProxy] 中装载 [YukiHookAPI] + * @param moduleName 你的模块包名 - 可通过 Xposed API 自动生成 + * @param hooker Hook 子类数组 - 必填不能为空 + * @throws IllegalStateException 如果 [hooker] 是空的 + */ +fun YukiHookXposedInitProxy.encase(moduleName: String, vararg hooker: YukiBaseHooker) = YukiHookAPI.encase(moduleName, *hooker) /** diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/log/LoggerFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/log/LoggerFactory.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/log/LoggerFactory.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/log/LoggerFactory.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/CustomParam.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/CustomParam.kt similarity index 97% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/CustomParam.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/CustomParam.kt index 412653a0..ca3e7a0f 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/CustomParam.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/CustomParam.kt @@ -25,7 +25,7 @@ * * This file is Created by fankes on 2022/2/2. */ -package com.highcapable.yukihookapi.param +package com.highcapable.yukihookapi.hook.param import android.content.pm.ApplicationInfo diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/HookParam.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/HookParam.kt similarity index 99% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/HookParam.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/HookParam.kt index 13da5dfa..1a52905d 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/HookParam.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/HookParam.kt @@ -27,7 +27,7 @@ */ @file:Suppress("unused", "MemberVisibilityCanBePrivate") -package com.highcapable.yukihookapi.param +package com.highcapable.yukihookapi.hook.param import de.robv.android.xposed.XC_MethodHook import java.lang.reflect.Constructor diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/PackageParam.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt similarity index 95% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/PackageParam.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt index 5635367c..6ec12d2d 100644 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/param/PackageParam.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt @@ -27,7 +27,7 @@ */ @file:Suppress("unused", "MemberVisibilityCanBePrivate", "EXPERIMENTAL_API_USAGE") -package com.highcapable.yukihookapi.param +package com.highcapable.yukihookapi.hook.param import android.content.pm.ApplicationInfo import com.highcapable.yukihookapi.annotation.DoNotUseMethod @@ -40,7 +40,7 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage * * 如果你想将 YukiHook 作为 Hook API 使用 - 你可自定义 [customParam] * - * ⚠️ 特别注意如果 [baseParam] 和 [customParam] 都为空将发生问题 + * - 特别注意如果 [baseParam] 和 [customParam] 都为空将发生问题 * @param baseParam 对接 Xposed API 的 [XC_LoadPackage.LoadPackageParam] - 默认空 * @param customParam 自定义装载类 - 默认空 */ @@ -116,7 +116,7 @@ open class PackageParam( /** * 将目标 [Class] 绑定到 [appClassLoader] * - * ⚠️ 请注意未绑定到 [appClassLoader] 的 [Class] 不能被装载 - 调用 [hook] 方法会自动绑定 + * - 请注意未绑定到 [appClassLoader] 的 [Class] 不能被装载 - 调用 [hook] 方法会自动绑定 * @return [Class] * @throws NoClassDefFoundError 如果找不到类会报错 */ diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/proxy/YukiHookXposedInitProxy.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/proxy/YukiHookXposedInitProxy.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/proxy/YukiHookXposedInitProxy.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/proxy/YukiHookXposedInitProxy.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/type/ComponentTypeFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/ComponentTypeFactory.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/type/ComponentTypeFactory.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/ComponentTypeFactory.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/type/VariableTypeFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/VariableTypeFactory.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/type/VariableTypeFactory.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/VariableTypeFactory.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/type/ViewTypeFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/ViewTypeFactory.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/type/ViewTypeFactory.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/ViewTypeFactory.kt diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionUtils.java b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionUtils.java similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionUtils.java rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/utils/ReflectionUtils.java diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookModuleStatus.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookModuleStatus.kt similarity index 100% rename from yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookModuleStatus.kt rename to yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookModuleStatus.kt diff --git a/yukihookapi/src/main/AndroidManifest.xml b/yukihookapi/src/main/AndroidManifest.xml deleted file mode 100644 index e0750efc..00000000 --- a/yukihookapi/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/yukihookapi/src/main/assets/xposed_init b/yukihookapi/src/main/assets/xposed_init deleted file mode 100644 index 37941abb..00000000 --- a/yukihookapi/src/main/assets/xposed_init +++ /dev/null @@ -1 +0,0 @@ -com.highcapable.yukihookapi.hook.xposed.YukiHookLoadPackage \ No newline at end of file diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.kt b/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.kt deleted file mode 100644 index 9da1f9ce..00000000 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.kt +++ /dev/null @@ -1,45 +0,0 @@ -/** - * MIT License - * - * Copyright (C) 2022 HighCapable - * - * This file is part of YukiHookAPI. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * This file is Created by fankes on 2022/2/3. - */ -package com.highcapable.yukihookapi.annotation.xposed - -import androidx.annotation.Keep -import com.highcapable.yukihookapi.hook.proxy.YukiHookXposedInitProxy -import com.highcapable.yukihookapi.hook.xposed.YukiHookLoadPackage - -/** - * 标识注入 YukiHook 的类 - * - * 此类将使用 [YukiHookLoadPackage] 自动调用 XposedInit - * - * 你可以将被注释的类继承于 [YukiHookXposedInitProxy] 接口实现 [YukiHookXposedInitProxy.onHook] 方法 - * - * 只能拥有一个 Hook 入口 - 多个入口将以首个得到的入口为准 - */ -@Target(AnnotationTarget.CLASS) -@Keep -annotation class InjectYukiHookWithXposed diff --git a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookLoadPackage.kt b/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookLoadPackage.kt deleted file mode 100644 index 1a5cab8c..00000000 --- a/yukihookapi/src/main/kotlin/com/highcapable/yukihookapi/hook/xposed/YukiHookLoadPackage.kt +++ /dev/null @@ -1,90 +0,0 @@ -/** - * MIT License - * - * Copyright (C) 2022 HighCapable - * - * This file is part of YukiHookAPI. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * This file is Created by fankes on 2022/2/2. - */ -@file:Suppress("EXPERIMENTAL_API_USAGE") - -package com.highcapable.yukihookapi.hook.xposed - -import androidx.annotation.Keep -import com.highcapable.yukihookapi.YukiHookAPI -import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed -import com.highcapable.yukihookapi.hook.factory.clazz -import com.highcapable.yukihookapi.hook.factory.findConstructor -import com.highcapable.yukihookapi.hook.factory.findMethod -import com.highcapable.yukihookapi.hook.log.loggerE -import com.highcapable.yukihookapi.hook.proxy.YukiHookXposedInitProxy -import com.highcapable.yukihookapi.hook.type.BooleanType -import com.highcapable.yukihookapi.param.PackageParam -import de.robv.android.xposed.IXposedHookLoadPackage -import de.robv.android.xposed.callbacks.XC_LoadPackage - -/** - * 接管 Xposed 的 [IXposedHookLoadPackage] 入口 - * - * 你可以使用 [YukiHookAPI.encase] 或在 [YukiHookXposedInitProxy] 中监听模块开始装载 - * - * 需要标识 Hook 入口的类 - 请声明注释 [InjectYukiHookWithXposed] - */ -@Keep -class YukiHookLoadPackage : IXposedHookLoadPackage { - - override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) { - if (lpparam == null) return - runCatching { - /** 执行入口方法 */ - hookEntryClassName().clazz.apply { - findMethod(name = "onHook")?.invoke(findConstructor()?.newInstance()) - } - }.onFailure { - loggerE(msg = "Try to load ${hookEntryClassName()} Failed", e = it) - } - /** 装载 APP Hook 实体类 */ - PackageParam(lpparam).apply { - /** Hook 模块激活状态 */ - loadApp(name = YukiHookAPI.modulePackageName) { - YukiHookModuleStatus::class.java.hook { - injectMember { - method { - name = "isActive" - returnType = BooleanType - } - replaceToTrue() - }.onAllFailure { loggerE(msg = "Try to Hook ModuleStatus Failed", e = it) } - } - } - /** 设置装载回调 */ - YukiHookAPI.packageParamCallback?.invoke(this) - } - } - - /** - * 获得目标装载类名 - 通过 APT 自动设置 TODO 待实现 - * @return [String] 目标装载类名 - */ - @Keep - private fun hookEntryClassName() = "com.highcapable.yukihookapi.demo.hook.inject.MainInjecter" -} \ No newline at end of file