mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +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