mirror of
				https://github.com/HighCapable/YukiHookAPI.git
				synced 2025-10-25 12:59:24 +08:00 
			
		
		
		
	Modify change injection process to GenerateData and integrate into the new code file
This commit is contained in:
		| @@ -34,7 +34,8 @@ 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_ksp_xposed.sources.CodeSourceFileTemplate | ||||
| import com.highcapable.yukihookapi_ksp_xposed.bean.GenerateData | ||||
| import com.highcapable.yukihookapi_ksp_xposed.factory.sources | ||||
| import org.w3c.dom.Element | ||||
| import org.w3c.dom.Node | ||||
| import java.io.File | ||||
| @@ -68,11 +69,11 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { | ||||
|  | ||||
|         /** | ||||
|          * 创建一个环境方法体方便调用 | ||||
|          * @param ignoredError 是否忽略错误 - 默认否 | ||||
|          * @param ignored 是否忽略错误 - 默认否 | ||||
|          * @param env 方法体 | ||||
|          */ | ||||
|         private fun environment(ignoredError: Boolean = false, env: SymbolProcessorEnvironment.() -> Unit) { | ||||
|             if (ignoredError) runCatching { environment.apply(env) } | ||||
|         private fun environment(ignored: Boolean = false, env: SymbolProcessorEnvironment.() -> Unit) { | ||||
|             if (ignored) runCatching { environment.apply(env) } | ||||
|             else environment.apply(env) | ||||
|         } | ||||
|  | ||||
| @@ -86,6 +87,18 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { | ||||
|             throw RuntimeException("[$TAG] $msg\n$helpMsg") | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * 创建代码文件 - 类型 kt | ||||
|          * @param fileName 文件名 | ||||
|          * @param packageName 包名 | ||||
|          * @param content 代码内容 | ||||
|          */ | ||||
|         private fun SymbolProcessorEnvironment.createCodeFile(fileName: String, packageName: String, content: String?) = | ||||
|             codeGenerator.createNewFile( | ||||
|                 dependencies = Dependencies.ALL_FILES, | ||||
|                 packageName, fileName | ||||
|             ).apply { content?.toByteArray()?.let { write(it) }; flush() }.close() | ||||
|  | ||||
|         /** | ||||
|          * 发出警告 | ||||
|          * @param msg 错误消息 | ||||
| @@ -98,10 +111,7 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { | ||||
|          */ | ||||
|         private fun String.removeSpecialChars() = replace("\\s*|\t|\r|\n".toRegex(), replacement = "").replace(oldValue = "\"", newValue = "'") | ||||
|  | ||||
|         override fun process(resolver: Resolver) = emptyList<KSAnnotated>().let { | ||||
|             startProcess(resolver) | ||||
|             it | ||||
|         } | ||||
|         override fun process(resolver: Resolver) = emptyList<KSAnnotated>().let { startProcess(resolver); it } | ||||
|  | ||||
|         /** | ||||
|          * 开始作业入口 | ||||
| @@ -109,40 +119,28 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { | ||||
|          */ | ||||
|         private fun startProcess(resolver: Resolver) = environment { | ||||
|             var isInjectOnce = true | ||||
|             val data = GenerateData() | ||||
|             resolver.getSymbolsWithAnnotation(annotationName).apply { | ||||
|                 /** | ||||
|                  * 检索需要注入的类 | ||||
|                  * @param sourcePath 指定的 source 路径 | ||||
|                  * @param custMPackageName 自定义模块包名 | ||||
|                  * @param xInitClassName xposed_init 入口类名 | ||||
|                  * @param isUsingResourcesHook 是否启用 Resources Hook | ||||
|                  */ | ||||
|                 fun fetchKSClassDeclaration( | ||||
|                     sourcePath: String, | ||||
|                     custMPackageName: String, | ||||
|                     xInitClassName: String, | ||||
|                     isUsingResourcesHook: Boolean | ||||
|                 ) { | ||||
|                 fun fetchKSClassDeclaration(sourcePath: String) { | ||||
|                     asSequence().filterIsInstance<KSClassDeclaration>().forEach { | ||||
|                         if (isInjectOnce) when { | ||||
|                             it.superTypes.any { type -> type.element.toString() == "IYukiHookXposedInit" } -> { | ||||
|                                 val xInitPatchName = xInitClassName.ifBlank { "${it.simpleName.asString()}$xposedClassShortName" } | ||||
|                                 if (xInitClassName == it.simpleName.asString()) problem(msg = "Duplicate entryClassName \"$xInitClassName\"") | ||||
|                                 generateAssetsFile( | ||||
|                                     codePath = (it.location as? FileLocation?)?.filePath ?: "", | ||||
|                                     sourcePath = sourcePath, | ||||
|                                     packageName = it.packageName.asString(), | ||||
|                                     custMPackageName = custMPackageName, | ||||
|                                     entryClassName = it.simpleName.asString(), | ||||
|                                     xInitClassName = xInitPatchName, | ||||
|                                     isUsingResourcesHook = isUsingResourcesHook | ||||
|                                 ) | ||||
|                                 val xInitPatchName = data.xInitClassName.ifBlank { "${it.simpleName.asString()}$xposedClassShortName" } | ||||
|                                 if (data.xInitClassName == it.simpleName.asString()) | ||||
|                                     problem(msg = "Duplicate entryClassName \"${data.xInitClassName}\"") | ||||
|                                 data.entryPackageName = it.packageName.asString() | ||||
|                                 data.entryClassName = it.simpleName.asString() | ||||
|                                 data.xInitClassName = xInitPatchName | ||||
|                                 generateAssetsFile(codePath = (it.location as? FileLocation?)?.filePath ?: "", sourcePath = sourcePath, data) | ||||
|                             } | ||||
|                             it.superTypes.any { type -> type.element.toString() == "YukiHookXposedInitProxy" } -> | ||||
|                                 problem(msg = "\"YukiHookXposedInitProxy\" was deprecated, please replace to \"IYukiHookXposedInit\"") | ||||
|                             else -> problem(msg = "HookEntryClass \"${it.simpleName.asString()}\" must be implements \"IYukiHookXposedInit\"") | ||||
|                         } | ||||
|                         else problem(msg = "\"@InjectYukiHookWithXposed\" only can be use in once times") | ||||
|                         } else problem(msg = "\"@InjectYukiHookWithXposed\" only can be use in once times") | ||||
|                         /** 仅处理第一个标记的类 - 再次处理将拦截并报错 */ | ||||
|                         isInjectOnce = false | ||||
|                     } | ||||
| @@ -150,30 +148,27 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { | ||||
|                 forEach { | ||||
|                     it.annotations.forEach { annotation -> | ||||
|                         var sourcePath = "" // 项目相对路径 | ||||
|                         var custMPackageName = "" // 自定义模块包名 | ||||
|                         var entryClassName = "" // xposed_init 入口类名 | ||||
|                         var isUsingResourcesHook = false // 是否启用 Resources Hook | ||||
|                         annotation.arguments.forEach { args -> | ||||
|                             if (args.name?.asString() == "sourcePath") | ||||
|                                 sourcePath = args.value.toString().trim() | ||||
|                             if (args.name?.asString() == "modulePackageName") | ||||
|                                 custMPackageName = args.value.toString().trim() | ||||
|                                 data.customMPackageName = args.value.toString().trim() | ||||
|                             if (args.name?.asString() == "entryClassName") | ||||
|                                 entryClassName = args.value.toString().trim() | ||||
|                                 data.entryClassName = args.value.toString().trim() | ||||
|                             if (args.name?.asString() == "isUsingResourcesHook") | ||||
|                                 isUsingResourcesHook = args.value as? Boolean ?: true | ||||
|                                 data.isUsingResourcesHook = args.value as? Boolean ?: true | ||||
|                         } | ||||
|                         if ((custMPackageName.startsWith(".") || | ||||
|                                     custMPackageName.endsWith(".") || | ||||
|                                     custMPackageName.contains(".").not() || | ||||
|                                     custMPackageName.contains("..")) && | ||||
|                             custMPackageName.isNotEmpty() | ||||
|                         ) problem(msg = "Invalid modulePackageName \"$custMPackageName\"") | ||||
|                         if ((Pattern.compile("[*,.:~`'\"|/\\\\?!^()\\[\\]{}%@#$&\\-+=<>]").matcher(entryClassName).find() || | ||||
|                                     true.let { for (i in 0..9) if (entryClassName.startsWith(i.toString())) return@let true;false }) | ||||
|                             && entryClassName.isNotEmpty() | ||||
|                         ) problem(msg = "Invalid entryClassName \"$entryClassName\"") | ||||
|                         else fetchKSClassDeclaration(sourcePath, custMPackageName, entryClassName, isUsingResourcesHook) | ||||
|                         if ((data.customMPackageName.startsWith(".") || | ||||
|                                     data.customMPackageName.endsWith(".") || | ||||
|                                     data.customMPackageName.contains(".").not() || | ||||
|                                     data.customMPackageName.contains("..")) && | ||||
|                             data.customMPackageName.isNotEmpty() | ||||
|                         ) problem(msg = "Invalid modulePackageName \"${data.customMPackageName}\"") | ||||
|                         if ((Pattern.compile("[*,.:~`'\"|/\\\\?!^()\\[\\]{}%@#$&\\-+=<>]").matcher(data.entryClassName).find() || | ||||
|                                     true.let { for (i in 0..9) if (data.entryClassName.startsWith(i.toString())) return@let true; false }) | ||||
|                             && data.entryClassName.isNotEmpty() | ||||
|                         ) problem(msg = "Invalid entryClassName \"${data.entryClassName}\"") | ||||
|                         else fetchKSClassDeclaration(sourcePath) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| @@ -183,21 +178,9 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { | ||||
|          * 自动生成 Xposed assets 入口文件 | ||||
|          * @param codePath 注解类的完整代码文件路径 | ||||
|          * @param sourcePath 指定的 source 路径 | ||||
|          * @param packageName 包名 | ||||
|          * @param custMPackageName 自定义模块包名 | ||||
|          * @param entryClassName 入口类名 | ||||
|          * @param xInitClassName xposed_init 入口类名 | ||||
|          * @param isUsingResourcesHook 是否启用 Resources Hook | ||||
|          * @param data 生成的模板数据 | ||||
|          */ | ||||
|         private fun generateAssetsFile( | ||||
|             codePath: String, | ||||
|             sourcePath: String, | ||||
|             packageName: String, | ||||
|             custMPackageName: String, | ||||
|             entryClassName: String, | ||||
|             xInitClassName: String, | ||||
|             isUsingResourcesHook: Boolean | ||||
|         ) = environment { | ||||
|         private fun generateAssetsFile(codePath: String, sourcePath: String, data: GenerateData) = environment { | ||||
|             if (codePath.isBlank()) problem(msg = "Project CodePath not available") | ||||
|             if (sourcePath.isBlank()) problem(msg = "Project SourcePath not available") | ||||
|             /** | ||||
| @@ -214,7 +197,7 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { | ||||
|             val projectPath = when { | ||||
|                 codePath.contains("\\") -> sourcePath.replace("/", "\\") | ||||
|                 codePath.contains("/") -> sourcePath.replace("\\", "/") | ||||
|                 else -> error("Unix File Separator unknown") | ||||
|                 else -> error("Unknown Unix File Separator") | ||||
|             }.let { | ||||
|                 if (codePath.contains(it)) | ||||
|                     codePath.split(it)[0].apply { rootPath = this } + it | ||||
| @@ -226,78 +209,52 @@ class YukiHookXposedProcessor : SymbolProcessorProvider { | ||||
|             val manifestFile = File("$projectPath${separator}AndroidManifest.xml") | ||||
|             if (manifestFile.exists()) { | ||||
|                 if (assetsFile.exists().not() || assetsFile.isDirectory.not()) assetsFile.apply { delete(); mkdirs() } | ||||
|                 val modulePackageName = parseModulePackageName(manifestFile, gradleFile, gradleKtsFile) | ||||
|                 if (modulePackageName.isBlank() && custMPackageName.isBlank()) | ||||
|                 data.modulePackageName = parseModulePackageName(manifestFile, gradleFile, gradleKtsFile) | ||||
|                 if (data.modulePackageName.isBlank() && data.customMPackageName.isBlank()) | ||||
|                     problem(msg = "Cannot identify your Module App's package name, tried AndroidManifest.xml, build.gradle and build.gradle.kts") | ||||
|                 File("${assetsFile.absolutePath}${separator}xposed_init") | ||||
|                     .writeText(text = "$packageName.$xInitClassName") | ||||
|                     .writeText(text = "${data.entryPackageName}.${data.xInitClassName}") | ||||
|                 File("${assetsFile.absolutePath}${separator}yukihookapi_init") | ||||
|                     .writeText(text = "$packageName.$entryClassName") | ||||
|                 generateClassFile(packageName, modulePackageName, custMPackageName, entryClassName, xInitClassName, isUsingResourcesHook) | ||||
|                     .writeText(text = "${data.entryPackageName}.${data.entryClassName}") | ||||
|                 generateClassFile(data) | ||||
|             } else problem(msg = "Project Source Path \"$sourcePath\" verify failed! Is this an Android Project?") | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * 自动生成指定类文件 | ||||
|          * @param packageName 包名 | ||||
|          * @param modulePackageName 模块包名 | ||||
|          * @param customMPackageName 自定义模块包名 | ||||
|          * @param entryClassName 入口类名 | ||||
|          * @param xInitClassName xposed_init 入口类名 | ||||
|          * @param isUsingResourcesHook 是否启用 Resources Hook | ||||
|          * @param data 生成的模板数据 | ||||
|          */ | ||||
|         private fun generateClassFile( | ||||
|             packageName: String, | ||||
|             modulePackageName: String, | ||||
|             customMPackageName: String, | ||||
|             entryClassName: String, | ||||
|             xInitClassName: String, | ||||
|             isUsingResourcesHook: Boolean | ||||
|         ) = environment(ignoredError = true) { | ||||
|             if (customMPackageName.isNotBlank()) | ||||
|                 warn(msg = "You set the customize module package name to \"$customMPackageName\", please check for yourself if it is correct") | ||||
|         private fun generateClassFile(data: GenerateData) = environment(ignored = true) { | ||||
|             if (data.customMPackageName.isNotBlank()) warn( | ||||
|                 msg = "You set the customize module package name to \"${data.customMPackageName}\", " + | ||||
|                         "please check for yourself if it is correct" | ||||
|             ) | ||||
|             val mdAppInjectPackageName = "com.highcapable.yukihookapi.hook.xposed.application.inject" | ||||
|             val ykBridgeInjectPackageName = "com.highcapable.yukihookapi.hook.xposed.bridge.inject" | ||||
|             /** 插入 ModuleApplication_Injector 代码 */ | ||||
|             codeGenerator.createNewFile( | ||||
|                 dependencies = Dependencies.ALL_FILES, | ||||
|             createCodeFile( | ||||
|                 fileName = "ModuleApplication_Injector", | ||||
|                 packageName = mdAppInjectPackageName, | ||||
|                 fileName = "ModuleApplication_Injector" | ||||
|             ).apply { | ||||
|                 write(CodeSourceFileTemplate.getModuleApplicationInjectorFileByteArray(mdAppInjectPackageName, packageName, entryClassName)) | ||||
|                 flush() | ||||
|                 close() | ||||
|             } | ||||
|                 content = data.apply { injectPackageName = mdAppInjectPackageName }.sources()["ModuleApplication_Injector"] | ||||
|             ) | ||||
|             /** 插入 YukiHookBridge_Injector 代码 */ | ||||
|             codeGenerator.createNewFile( | ||||
|                 dependencies = Dependencies.ALL_FILES, | ||||
|             createCodeFile( | ||||
|                 fileName = "YukiHookBridge_Injector", | ||||
|                 packageName = ykBridgeInjectPackageName, | ||||
|                 fileName = "YukiHookBridge_Injector" | ||||
|             ).apply { | ||||
|                 write(CodeSourceFileTemplate.getYukiHookBridgeInjectorFileByteArray(ykBridgeInjectPackageName)) | ||||
|                 flush() | ||||
|                 close() | ||||
|             } | ||||
|                 content = data.apply { injectPackageName = ykBridgeInjectPackageName }.sources()["YukiHookBridge_Injector"] | ||||
|             ) | ||||
|             /** 插入 xposed_init 代码 */ | ||||
|             codeGenerator.createNewFile( | ||||
|                 dependencies = Dependencies.ALL_FILES, | ||||
|                 packageName = packageName, | ||||
|                 fileName = xInitClassName | ||||
|             ).apply { | ||||
|                 write(CodeSourceFileTemplate.getXposedInitFileByteArray(packageName, entryClassName, xInitClassName, isUsingResourcesHook)) | ||||
|                 flush() | ||||
|                 close() | ||||
|             } | ||||
|             createCodeFile( | ||||
|                 fileName = data.xInitClassName, | ||||
|                 packageName = data.entryPackageName, | ||||
|                 content = data.sources()["xposed_init"] | ||||
|             ) | ||||
|             /** 插入 xposed_init_Impl 代码 */ | ||||
|             codeGenerator.createNewFile( | ||||
|                 dependencies = Dependencies.ALL_FILES, | ||||
|                 packageName = packageName, | ||||
|                 fileName = "${entryClassName}_Impl" | ||||
|             ).apply { | ||||
|                 write(CodeSourceFileTemplate.getXposedInitImplFileByteArray(packageName, modulePackageName, customMPackageName, entryClassName)) | ||||
|                 flush() | ||||
|                 close() | ||||
|             } | ||||
|             createCodeFile( | ||||
|                 fileName = "${data.entryClassName}_Impl", | ||||
|                 packageName = data.entryPackageName, | ||||
|                 content = data.sources()["xposed_init_Impl"] | ||||
|             ) | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|   | ||||
| @@ -0,0 +1,48 @@ | ||||
| /* | ||||
|  * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API. | ||||
|  * Copyright (C) 2019-2022 HighCapable | ||||
|  * https://github.com/fankes/YukiHookAPI | ||||
|  * | ||||
|  * MIT License | ||||
|  * | ||||
|  * 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/9/20. | ||||
|  */ | ||||
| package com.highcapable.yukihookapi_ksp_xposed.bean | ||||
|  | ||||
| /** | ||||
|  * 生成的模板数据实例 | ||||
|  * @param entryPackageName 入口类包名 | ||||
|  * @param injectPackageName 注入类包名 | ||||
|  * @param modulePackageName 模块包名 (命名空间) | ||||
|  * @param customMPackageName 自定义模块包名 | ||||
|  * @param entryClassName 入口类名 | ||||
|  * @param xInitClassName xposed_init 入口类名 | ||||
|  * @param isUsingResourcesHook 是否启用 Resources Hook | ||||
|  */ | ||||
| data class GenerateData( | ||||
|     var entryPackageName: String = "", | ||||
|     var injectPackageName: String = "", | ||||
|     var modulePackageName: String = "", | ||||
|     var customMPackageName: String = "", | ||||
|     var entryClassName: String = "", | ||||
|     var xInitClassName: String = "", | ||||
|     var isUsingResourcesHook: Boolean = true | ||||
| ) | ||||
| @@ -0,0 +1,180 @@ | ||||
| /* | ||||
|  * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API. | ||||
|  * Copyright (C) 2019-2022 HighCapable | ||||
|  * https://github.com/fankes/YukiHookAPI | ||||
|  * | ||||
|  * MIT License | ||||
|  * | ||||
|  * 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/9/20. | ||||
|  */ | ||||
| package com.highcapable.yukihookapi_ksp_xposed.factory | ||||
|  | ||||
| import com.highcapable.yukihookapi_ksp_xposed.bean.GenerateData | ||||
| import java.text.SimpleDateFormat | ||||
| import java.util.* | ||||
|  | ||||
| /** | ||||
|  * 创建文件注释 | ||||
|  * @param entryClassName 入口类名 - 空则不生成 | ||||
|  * @param currrentClassTag 当前注入类标签 | ||||
|  * @return [String] | ||||
|  */ | ||||
| private fun createCommentContent(entryClassName: String = "", currrentClassTag: String) = | ||||
|     ("/**\n" + | ||||
|             " * $currrentClassTag Inject Class\n" + | ||||
|             " *\n" + | ||||
|             " * Compiled from YukiHookXposedProcessor\n" + | ||||
|             " *\n" + | ||||
|             (if (entryClassName.isNotBlank()) " * HookEntryClass: [$entryClassName]\n *\n" else "") + | ||||
|             " * Generate Date: ${SimpleDateFormat.getDateTimeInstance().format(Date())}\n" + | ||||
|             " *\n" + | ||||
|             " * Powered by YukiHookAPI (C) HighCapable 2022\n" + | ||||
|             " *\n" + | ||||
|             " * Project Address: [YukiHookAPI](https://github.com/fankes/YukiHookAPI)\n" + | ||||
|             " */\n") | ||||
|  | ||||
| /** | ||||
|  * 获得注入文件代码内容 | ||||
|  * @return [Map]<[String],[String]> | ||||
|  */ | ||||
| fun GenerateData.sources() = mapOf( | ||||
|     "ModuleApplication_Injector" to ("@file:Suppress(\"ClassName\")\n" + | ||||
|             "\n" + | ||||
|             "package $entryPackageName\n" + | ||||
|             "\n" + | ||||
|             "import $entryPackageName.$entryClassName\n" + | ||||
|             "\n" + | ||||
|             createCommentContent(entryClassName, currrentClassTag = "ModuleApplication") + | ||||
|             "object ModuleApplication_Injector {\n" + | ||||
|             "\n" + | ||||
|             "    @JvmStatic\n" + | ||||
|             "    fun callApiInit() = try {\n" + | ||||
|             "        $entryClassName().onInit()\n" + | ||||
|             "    } catch (_: Throwable) {\n" + | ||||
|             "    }\n" + | ||||
|             "}"), | ||||
|     "YukiHookBridge_Injector" to ("@file:Suppress(\"ClassName\")\n" + | ||||
|             "\n" + | ||||
|             "package $entryPackageName\n" + | ||||
|             "\n" + | ||||
|             createCommentContent(currrentClassTag = "YukiHookBridge") + | ||||
|             "object YukiHookBridge_Injector {\n" + | ||||
|             "\n" + | ||||
|             "    @JvmStatic\n" + | ||||
|             "    fun getModuleGeneratedVersion() = \"${System.currentTimeMillis()}\"\n" + | ||||
|             "}"), | ||||
|     "xposed_init" to ("@file:Suppress(\"ClassName\")\n" + | ||||
|             "\n" + | ||||
|             "package $entryPackageName\n" + | ||||
|             "\n" + | ||||
|             "import androidx.annotation.Keep\n" + | ||||
|             "import com.highcapable.yukihookapi.hook.xposed.bridge.event.YukiXposedEvent\n" + | ||||
|             "import com.highcapable.yukihookapi.annotation.YukiGenerateApi\n" + | ||||
|             (if (isUsingResourcesHook) "import de.robv.android.xposed.IXposedHookInitPackageResources\n" else "") + | ||||
|             "import de.robv.android.xposed.IXposedHookLoadPackage\n" + | ||||
|             "import de.robv.android.xposed.IXposedHookZygoteInit\n" + | ||||
|             (if (isUsingResourcesHook) "import de.robv.android.xposed.callbacks.XC_InitPackageResources\n" else "") + | ||||
|             "import de.robv.android.xposed.callbacks.XC_LoadPackage\n" + | ||||
|             "\n" + | ||||
|             createCommentContent(entryClassName, currrentClassTag = "Xposed Init") + | ||||
|             "@Keep\n" + | ||||
|             "@YukiGenerateApi\n" + | ||||
|             "class $xInitClassName : IXposedHookZygoteInit, IXposedHookLoadPackage" + | ||||
|             "${if (isUsingResourcesHook) ", IXposedHookInitPackageResources" else ""} {\n" + | ||||
|             "\n" + | ||||
|             "    override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {\n" + | ||||
|             "        ${entryClassName}_Impl.callInitZygote(sparam)\n" + | ||||
|             "        YukiXposedEvent.EventHandler.callInitZygote(sparam)\n" + | ||||
|             "    }\n" + | ||||
|             "\n" + | ||||
|             "    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" + | ||||
|             "        ${entryClassName}_Impl.callHandleLoadPackage(lpparam)\n" + | ||||
|             "        YukiXposedEvent.EventHandler.callHandleLoadPackage(lpparam)\n" + | ||||
|             "    }\n" + | ||||
|             (if (isUsingResourcesHook) | ||||
|                 ("\n    override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {\n" + | ||||
|                         "        ${entryClassName}_Impl.callHandleInitPackageResources(resparam)\n" + | ||||
|                         "        YukiXposedEvent.EventHandler.callHandleInitPackageResources(resparam)\n" + | ||||
|                         "    }\n") else "") + | ||||
|             "}"), | ||||
|     "xposed_init_Impl" to ("@file:Suppress(\"ClassName\")\n" + | ||||
|             "\n" + | ||||
|             "package $entryPackageName\n" + | ||||
|             "\n" + | ||||
|             "import com.highcapable.yukihookapi.annotation.YukiGenerateApi\n" + | ||||
|             "import com.highcapable.yukihookapi.hook.log.loggerE\n" + | ||||
|             "import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge\n" + | ||||
|             "import de.robv.android.xposed.IXposedHookZygoteInit\n" + | ||||
|             "import de.robv.android.xposed.callbacks.XC_InitPackageResources\n" + | ||||
|             "import de.robv.android.xposed.callbacks.XC_LoadPackage\n" + | ||||
|             (if (customMPackageName.isBlank()) "import $modulePackageName.BuildConfig\n" else "") + | ||||
|             "\n" + | ||||
|             createCommentContent(entryClassName, currrentClassTag = "Xposed Init Impl") + | ||||
|             "@YukiGenerateApi\n" + | ||||
|             "object ${entryClassName}_Impl {\n" + | ||||
|             "\n" + | ||||
|             "    private const val modulePackageName = " + | ||||
|             (if (customMPackageName.isNotBlank()) "\"$customMPackageName\"" else "BuildConfig.APPLICATION_ID") + "\n" + | ||||
|             "\n" + | ||||
|             "    private var isZygoteBinded = false\n" + | ||||
|             "\n" + | ||||
|             "    private val hookEntry = $entryClassName()\n" + | ||||
|             "\n" + | ||||
|             "    private fun callXposedLoaded(\n" + | ||||
|             "        isZygoteLoaded: Boolean = false,\n" + | ||||
|             "        lpparam: XC_LoadPackage.LoadPackageParam? = null,\n" + | ||||
|             "        resparam: XC_InitPackageResources.InitPackageResourcesParam? = null\n" + | ||||
|             "    ) {\n" + | ||||
|             "        if (isZygoteBinded.not()) runCatching {\n" + | ||||
|             "            hookEntry.onXposedEvent()\n" + | ||||
|             "            hookEntry.onInit()\n" + | ||||
|             "            if (YukiHookBridge.isXposedCallbackSetUp) {\n" + | ||||
|             "                loggerE(msg = \"You cannot load a hooker in \\\"onInit\\\" or \\\"onXposedEvent\\\" method! Aborted\")\n" + | ||||
|             "                return\n" + | ||||
|             "            }\n" + | ||||
|             "            hookEntry.onHook()\n" + | ||||
|             "            YukiHookBridge.callXposedInitialized()\n" + | ||||
|             "            YukiHookBridge.modulePackageName = modulePackageName\n" + | ||||
|             "        }.onFailure { loggerE(msg = \"YukiHookAPI try to load HookEntryClass failed\", e = it) }\n" + | ||||
|             "        YukiHookBridge.callXposedLoaded(isZygoteLoaded, lpparam, resparam)\n" + | ||||
|             "    }\n" + | ||||
|             "\n" + | ||||
|             "    @YukiGenerateApi\n" + | ||||
|             "    fun callInitZygote(sparam: IXposedHookZygoteInit.StartupParam?) {\n" + | ||||
|             "        if (sparam == null) return\n" + | ||||
|             "        runCatching {\n" + | ||||
|             "            YukiHookBridge.callXposedZygoteLoaded(sparam)\n" + | ||||
|             "        }.onFailure { loggerE(msg = \"YukiHookAPI bind initZygote failed\", e = it) }\n" + | ||||
|             "        callXposedLoaded(isZygoteLoaded = true)\n" + | ||||
|             "        isZygoteBinded = true\n" + | ||||
|             "    }\n" + | ||||
|             "\n" + | ||||
|             "    @YukiGenerateApi\n" + | ||||
|             "    fun callHandleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" + | ||||
|             "        if (lpparam != null) callXposedLoaded(lpparam = lpparam)\n" + | ||||
|             "    }\n" + | ||||
|             "\n" + | ||||
|             "    @YukiGenerateApi\n" + | ||||
|             "    fun callHandleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {\n" + | ||||
|             "        if (resparam != null) callXposedLoaded(resparam = resparam)\n" + | ||||
|             "    }\n" + | ||||
|             "}") | ||||
| ) | ||||
| @@ -1,214 +0,0 @@ | ||||
| /* | ||||
|  * YukiHookAPI - An efficient Kotlin version of the Xposed Hook API. | ||||
|  * Copyright (C) 2019-2022 HighCapable | ||||
|  * https://github.com/fankes/YukiHookAPI | ||||
|  * | ||||
|  * MIT License | ||||
|  * | ||||
|  * 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/4/27. | ||||
|  */ | ||||
| package com.highcapable.yukihookapi_ksp_xposed.sources | ||||
|  | ||||
| import java.text.SimpleDateFormat | ||||
| import java.util.* | ||||
|  | ||||
| /** | ||||
|  * 代码文件注入模板类 | ||||
|  */ | ||||
| object CodeSourceFileTemplate { | ||||
|  | ||||
|     /** | ||||
|      * 获得文件注释 | ||||
|      * @param entryClassName 入口类名 - 空则不生成 | ||||
|      * @param currrentClassTag 当前注入类标签 | ||||
|      * @return [String] | ||||
|      */ | ||||
|     private fun getCommentContent(entryClassName: String = "", currrentClassTag: String) = | ||||
|         ("/**\n" + | ||||
|                 " * $currrentClassTag Inject Class\n" + | ||||
|                 " *\n" + | ||||
|                 " * Compiled from YukiHookXposedProcessor\n" + | ||||
|                 " *\n" + | ||||
|                 (if (entryClassName.isNotBlank()) " * HookEntryClass: [$entryClassName]\n *\n" else "") + | ||||
|                 " * Generate Date: ${SimpleDateFormat.getDateTimeInstance().format(Date())}\n" + | ||||
|                 " *\n" + | ||||
|                 " * Powered by YukiHookAPI (C) HighCapable 2022\n" + | ||||
|                 " *\n" + | ||||
|                 " * Project Address: [YukiHookAPI](https://github.com/fankes/YukiHookAPI)\n" + | ||||
|                 " */\n") | ||||
|  | ||||
|     /** | ||||
|      * 获得 ModuleApplication_Injector 注入文件 | ||||
|      * @param packageName 包名 | ||||
|      * @param entryPackageName 入口类包名 | ||||
|      * @param entryClassName 入口类名 | ||||
|      * @return [ByteArray] | ||||
|      */ | ||||
|     fun getModuleApplicationInjectorFileByteArray(packageName: String, entryPackageName: String, entryClassName: String) = | ||||
|         ("@file:Suppress(\"ClassName\")\n" + | ||||
|                 "\n" + | ||||
|                 "package $packageName\n" + | ||||
|                 "\n" + | ||||
|                 "import $entryPackageName.$entryClassName\n" + | ||||
|                 "\n" + | ||||
|                 getCommentContent(entryClassName, currrentClassTag = "ModuleApplication") + | ||||
|                 "object ModuleApplication_Injector {\n" + | ||||
|                 "\n" + | ||||
|                 "    @JvmStatic\n" + | ||||
|                 "    fun callApiInit() = try {\n" + | ||||
|                 "        $entryClassName().onInit()\n" + | ||||
|                 "    } catch (_: Throwable) {\n" + | ||||
|                 "    }\n" + | ||||
|                 "}").toByteArray() | ||||
|  | ||||
|     /** | ||||
|      * 获得 YukiHookBridge_Injector 注入文件 | ||||
|      * @param packageName 包名 | ||||
|      * @return [ByteArray] | ||||
|      */ | ||||
|     fun getYukiHookBridgeInjectorFileByteArray(packageName: String) = | ||||
|         ("@file:Suppress(\"ClassName\")\n" + | ||||
|                 "\n" + | ||||
|                 "package $packageName\n" + | ||||
|                 "\n" + | ||||
|                 getCommentContent(currrentClassTag = "YukiHookBridge") + | ||||
|                 "object YukiHookBridge_Injector {\n" + | ||||
|                 "\n" + | ||||
|                 "    @JvmStatic\n" + | ||||
|                 "    fun getModuleGeneratedVersion() = \"${System.currentTimeMillis()}\"\n" + | ||||
|                 "}").toByteArray() | ||||
|  | ||||
|     /** | ||||
|      * 获得 xposed_init 注入文件 | ||||
|      * @param packageName 包名 | ||||
|      * @param entryClassName 入口类名 | ||||
|      * @param xInitClassName xposed_init 入口类名 | ||||
|      * @param isUsingResourcesHook 是否启用 Resources Hook | ||||
|      * @return [ByteArray] | ||||
|      */ | ||||
|     fun getXposedInitFileByteArray(packageName: String, entryClassName: String, xInitClassName: String, isUsingResourcesHook: Boolean) = | ||||
|         ("@file:Suppress(\"ClassName\")\n" + | ||||
|                 "\n" + | ||||
|                 "package $packageName\n" + | ||||
|                 "\n" + | ||||
|                 "import androidx.annotation.Keep\n" + | ||||
|                 "import com.highcapable.yukihookapi.hook.xposed.bridge.event.YukiXposedEvent\n" + | ||||
|                 "import com.highcapable.yukihookapi.annotation.YukiGenerateApi\n" + | ||||
|                 (if (isUsingResourcesHook) "import de.robv.android.xposed.IXposedHookInitPackageResources\n" else "") + | ||||
|                 "import de.robv.android.xposed.IXposedHookLoadPackage\n" + | ||||
|                 "import de.robv.android.xposed.IXposedHookZygoteInit\n" + | ||||
|                 (if (isUsingResourcesHook) "import de.robv.android.xposed.callbacks.XC_InitPackageResources\n" else "") + | ||||
|                 "import de.robv.android.xposed.callbacks.XC_LoadPackage\n" + | ||||
|                 "\n" + | ||||
|                 getCommentContent(entryClassName, currrentClassTag = "Xposed Init") + | ||||
|                 "@Keep\n" + | ||||
|                 "@YukiGenerateApi\n" + | ||||
|                 "class $xInitClassName : IXposedHookZygoteInit, IXposedHookLoadPackage" + | ||||
|                 "${if (isUsingResourcesHook) ", IXposedHookInitPackageResources" else ""} {\n" + | ||||
|                 "\n" + | ||||
|                 "    override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {\n" + | ||||
|                 "        ${entryClassName}_Impl.callInitZygote(sparam)\n" + | ||||
|                 "        YukiXposedEvent.EventHandler.callInitZygote(sparam)\n" + | ||||
|                 "    }\n" + | ||||
|                 "\n" + | ||||
|                 "    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" + | ||||
|                 "        ${entryClassName}_Impl.callHandleLoadPackage(lpparam)\n" + | ||||
|                 "        YukiXposedEvent.EventHandler.callHandleLoadPackage(lpparam)\n" + | ||||
|                 "    }\n" + | ||||
|                 (if (isUsingResourcesHook) | ||||
|                     ("\n    override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {\n" + | ||||
|                             "        ${entryClassName}_Impl.callHandleInitPackageResources(resparam)\n" + | ||||
|                             "        YukiXposedEvent.EventHandler.callHandleInitPackageResources(resparam)\n" + | ||||
|                             "    }\n") else "") + | ||||
|                 "}").toByteArray() | ||||
|  | ||||
|     /** | ||||
|      * 获得 xposed_init_Impl 注入文件 | ||||
|      * @param packageName 包名 | ||||
|      * @param modulePackageName 模块包名 | ||||
|      * @param customMPackageName 自定义模块包名 | ||||
|      * @param entryClassName 入口类名 | ||||
|      * @return [ByteArray] | ||||
|      */ | ||||
|     fun getXposedInitImplFileByteArray(packageName: String, modulePackageName: String, customMPackageName: String, entryClassName: String) = | ||||
|         ("@file:Suppress(\"ClassName\")\n" + | ||||
|                 "\n" + | ||||
|                 "package $packageName\n" + | ||||
|                 "\n" + | ||||
|                 "import com.highcapable.yukihookapi.annotation.YukiGenerateApi\n" + | ||||
|                 "import com.highcapable.yukihookapi.hook.log.loggerE\n" + | ||||
|                 "import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge\n" + | ||||
|                 "import de.robv.android.xposed.IXposedHookZygoteInit\n" + | ||||
|                 "import de.robv.android.xposed.callbacks.XC_InitPackageResources\n" + | ||||
|                 "import de.robv.android.xposed.callbacks.XC_LoadPackage\n" + | ||||
|                 (if (customMPackageName.isBlank()) "import $modulePackageName.BuildConfig\n" else "") + | ||||
|                 "\n" + | ||||
|                 getCommentContent(entryClassName, currrentClassTag = "Xposed Init Impl") + | ||||
|                 "@YukiGenerateApi\n" + | ||||
|                 "object ${entryClassName}_Impl {\n" + | ||||
|                 "\n" + | ||||
|                 "    private const val modulePackageName = " + | ||||
|                 (if (customMPackageName.isNotBlank()) "\"$customMPackageName\"" else "BuildConfig.APPLICATION_ID") + "\n" + | ||||
|                 "\n" + | ||||
|                 "    private var isZygoteBinded = false\n" + | ||||
|                 "\n" + | ||||
|                 "    private val hookEntry = $entryClassName()\n" + | ||||
|                 "\n" + | ||||
|                 "    private fun callXposedLoaded(\n" + | ||||
|                 "        isZygoteLoaded: Boolean = false,\n" + | ||||
|                 "        lpparam: XC_LoadPackage.LoadPackageParam? = null,\n" + | ||||
|                 "        resparam: XC_InitPackageResources.InitPackageResourcesParam? = null\n" + | ||||
|                 "    ) {\n" + | ||||
|                 "        if (isZygoteBinded.not()) runCatching {\n" + | ||||
|                 "            hookEntry.onXposedEvent()\n" + | ||||
|                 "            hookEntry.onInit()\n" + | ||||
|                 "            if (YukiHookBridge.isXposedCallbackSetUp) {\n" + | ||||
|                 "                loggerE(msg = \"You cannot load a hooker in \\\"onInit\\\" or \\\"onXposedEvent\\\" method! Aborted\")\n" + | ||||
|                 "                return\n" + | ||||
|                 "            }\n" + | ||||
|                 "            hookEntry.onHook()\n" + | ||||
|                 "            YukiHookBridge.callXposedInitialized()\n" + | ||||
|                 "            YukiHookBridge.modulePackageName = modulePackageName\n" + | ||||
|                 "        }.onFailure { loggerE(msg = \"YukiHookAPI try to load HookEntryClass failed\", e = it) }\n" + | ||||
|                 "        YukiHookBridge.callXposedLoaded(isZygoteLoaded, lpparam, resparam)\n" + | ||||
|                 "    }\n" + | ||||
|                 "\n" + | ||||
|                 "    @YukiGenerateApi\n" + | ||||
|                 "    fun callInitZygote(sparam: IXposedHookZygoteInit.StartupParam?) {\n" + | ||||
|                 "        if (sparam == null) return\n" + | ||||
|                 "        runCatching {\n" + | ||||
|                 "            YukiHookBridge.callXposedZygoteLoaded(sparam)\n" + | ||||
|                 "        }.onFailure { loggerE(msg = \"YukiHookAPI bind initZygote failed\", e = it) }\n" + | ||||
|                 "        callXposedLoaded(isZygoteLoaded = true)\n" + | ||||
|                 "        isZygoteBinded = true\n" + | ||||
|                 "    }\n" + | ||||
|                 "\n" + | ||||
|                 "    @YukiGenerateApi\n" + | ||||
|                 "    fun callHandleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {\n" + | ||||
|                 "        if (lpparam != null) callXposedLoaded(lpparam = lpparam)\n" + | ||||
|                 "    }\n" + | ||||
|                 "\n" + | ||||
|                 "    @YukiGenerateApi\n" + | ||||
|                 "    fun callHandleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {\n" + | ||||
|                 "        if (resparam != null) callXposedLoaded(resparam = resparam)\n" + | ||||
|                 "    }\n" + | ||||
|                 "}").toByteArray() | ||||
| } | ||||
		Reference in New Issue
	
	Block a user