diff --git a/docs/api/public/PackageParam.md b/docs/api/public/PackageParam.md index c1550201..2b3432d1 100644 --- a/docs/api/public/PackageParam.md +++ b/docs/api/public/PackageParam.md @@ -551,7 +551,7 @@ fun findClass(vararg name: String, loader: ClassLoader?): VariousClass > 通过完整包名+名称查找需要被 Hook 的 `Class`。 -!> 使用此方法会得到一个 `HookClass` 仅用于 Hook,若想查找 `Class` 请使用 `classOf`、`toAppClass` 功能。 +!> 使用此方法会得到一个 `HookClass` 仅用于 Hook,若想查找 `Class` 请使用 `toClass`、`toAppClass` 功能。 **功能示例** diff --git a/docs/api/public/ReflectionFactory.md b/docs/api/public/ReflectionFactory.md index 0389919a..f5f98f8e 100644 --- a/docs/api/public/ReflectionFactory.md +++ b/docs/api/public/ReflectionFactory.md @@ -108,28 +108,38 @@ val Class<*>.hasExtends: Boolean > 当前 `Class` 是否有继承关系,父类是 `Any` 将被认为没有继承关系。 -### classOf *- method* - -```kotlin -fun classOf(name: String, loader: ClassLoader?): Class<*> -``` +### ~~classOf *- method*~~ **变更记录** `v1.0` `添加` +`v1.0.93` `移除` + +请转到 `toClass(...)` 方法 + +### String.toClass *- ext-method* + +```kotlin +fun String.toClass(loader: ClassLoader?): Class<*> +``` + +**变更记录** + +`v1.0.93` `新增` + **功能描述** -> 通过字符串使用指定的 `ClassLoader` 转换为实体类。 +> 通过字符串类名转换为 `loader` 中的实体类。 **功能示例** -你可以直接填写你要查找的目标 `Class`,必须在当前 `ClassLoader` 下存在。 +你可以直接填写你要查找的目标 `Class`,必须在默认 `ClassLoader` 下存在。 > 示例如下 ```kotlin -classOf(name = "com.example.demo.DemoClass") +"com.example.demo.DemoClass".toClass() ``` 你还可以自定义 `Class` 所在的 `ClassLoader`。 @@ -138,7 +148,7 @@ classOf(name = "com.example.demo.DemoClass") ```kotlin val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader -classOf(name = "com.example.demo.DemoClass", customClassLoader) +"com.example.demo.DemoClass".toClass(customClassLoader) ``` ### classOf *- method* diff --git a/docs/guide/special-feature.md b/docs/guide/special-feature.md index 422c84bc..ee8321e0 100644 --- a/docs/guide/special-feature.md +++ b/docs/guide/special-feature.md @@ -660,7 +660,7 @@ Test(true).doTask("task_name") > 示例如下 ```kotlin -classOf("com.demo.Test") +"com.demo.Test".toClass() .getDeclaredConstructor(Boolean::class.java) .apply { isAccessible = true } .newInstance(true) @@ -679,7 +679,7 @@ classOf("com.demo.Test") > 示例如下 ```kotlin -classOf("com.demo.Test").buildOfAny(true) { param(BooleanType) }?.current { +"com.demo.Test".toClass().buildOfAny(true) { param(BooleanType) }?.current { method { name = "doTask" param(StringType) @@ -916,7 +916,7 @@ public class BTest { ```kotlin // 首先查询到这个 Class -val currentClass = if("com.demo.ATest".hasClass) classOf("com.demo.ATest") else classOf("com.demo.BTest") +val currentClass = if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass() // 然后再查询这个方法并调用 currentClass.method { name = "doTask" diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/bean/VariousClass.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/bean/VariousClass.kt index d09afab1..423d621c 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/bean/VariousClass.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/bean/VariousClass.kt @@ -27,7 +27,7 @@ */ package com.highcapable.yukihookapi.hook.bean -import com.highcapable.yukihookapi.hook.factory.classOf +import com.highcapable.yukihookapi.hook.factory.toClass /** * 这是一个不确定性 [Class] 类名装载器 @@ -48,7 +48,7 @@ class VariousClass(vararg var name: String) { if (name.isNotEmpty()) run { name.forEach { runCatching { - finalClass = classOf(it, loader) + finalClass = it.toClass(loader) return@run } } diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.kt index a38b2317..24250125 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.kt @@ -29,7 +29,7 @@ package com.highcapable.yukihookapi.hook.core.finder.base import com.highcapable.yukihookapi.annotation.YukiPrivateApi import com.highcapable.yukihookapi.hook.bean.VariousClass -import com.highcapable.yukihookapi.hook.factory.classOf +import com.highcapable.yukihookapi.hook.factory.toClass import com.highcapable.yukihookapi.hook.type.defined.UndefinedType import java.lang.reflect.Member import kotlin.math.abs @@ -113,7 +113,7 @@ abstract class BaseFinder { internal fun Any?.compat(tag: String, loader: ClassLoader?) = when (this) { null -> null is Class<*> -> this - is String -> runCatching { classOf(name = this, loader) }.getOrNull() ?: UndefinedType + is String -> runCatching { toClass(loader) }.getOrNull() ?: UndefinedType is VariousClass -> runCatching { get(loader) }.getOrNull() ?: UndefinedType else -> error("$tag match type \"$javaClass\" not allowed") } as Class<*>? diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt index 1d1309f1..7d2b63cc 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.kt @@ -74,24 +74,31 @@ enum class MembersType { val Class<*>.hasExtends get() = superclass.name != "java.lang.Object" /** - * 通过字符串转换为实体类 - * @param name [Class] 的完整包名+名称 - * @param loader [Class] 所在的 [ClassLoader] - 默认空 - 可不填 + * 通过字符串类名转换为 [loader] 中的实体类 + * + * - ❗此方法已弃用 - 在之后的版本中将直接被删除 + * + * - ❗请现在转移到 [toClass] * @return [Class] * @throws NoClassDefFoundError 如果找不到 [Class] 或设置了错误的 [ClassLoader] */ -fun classOf(name: String, loader: ClassLoader? = null): Class<*> { - val hashCode = ("[$name][$loader]").hashCode() +@Deprecated(message = "请使用新的命名方法", ReplaceWith(expression = "name.toClass(loader)")) +fun classOf(name: String, loader: ClassLoader? = null) = name.toClass(loader) + +/** + * 通过字符串类名转换为 [loader] 中的实体类 + * @param loader [Class] 所在的 [ClassLoader] - 默认空 - 不填使用默认 [ClassLoader] + * @return [Class] + * @throws NoClassDefFoundError 如果找不到 [Class] 或设置了错误的 [ClassLoader] + */ +fun String.toClass(loader: ClassLoader? = null): Class<*> { + val hashCode = ("[$this][$loader]").hashCode() return ReflectsCacheStore.findClass(hashCode) ?: run { when { - YukiHookBridge.hasXposedBridge -> - runCatching { YukiHookHelper.findClass(name, loader) }.getOrNull() - ?: when (loader) { - null -> Class.forName(name) - else -> loader.loadClass(name) - } - loader == null -> Class.forName(name) - else -> loader.loadClass(name) + YukiHookBridge.hasXposedBridge -> runCatching { YukiHookHelper.findClass(name = this, loader) }.getOrNull() + ?: (if (loader == null) Class.forName(this) else loader.loadClass(this)) + loader == null -> Class.forName(this) + else -> loader.loadClass(this) }.also { ReflectsCacheStore.putClass(hashCode, it) } } } @@ -102,14 +109,14 @@ fun classOf(name: String, loader: ClassLoader? = null): Class<*> { * @return [Class] * @throws NoClassDefFoundError 如果找不到 [Class] 或设置了错误的 [ClassLoader] */ -inline fun classOf(loader: ClassLoader? = null) = loader?.let { classOf(T::class.java.name, loader) } ?: T::class.java +inline fun classOf(loader: ClassLoader? = null) = loader?.let { T::class.java.name.toClass(loader) } ?: T::class.java /** * 通过字符串类名使用指定的 [ClassLoader] 查找是否存在 * @param loader [Class] 所在的 [ClassLoader] - 不填使用默认 [ClassLoader] * @return [Boolean] 是否存在 */ -fun String.hasClass(loader: ClassLoader? = null) = runCatching { classOf(name = this, loader); true }.getOrNull() ?: false +fun String.hasClass(loader: ClassLoader? = null) = runCatching { toClass(loader); true }.getOrNull() ?: false /** * 查找变量是否存在 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt index 334cc6e1..4db6f176 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/param/PackageParam.kt @@ -44,6 +44,7 @@ import com.highcapable.yukihookapi.hook.core.YukiMemberHookCreator import com.highcapable.yukihookapi.hook.core.YukiResourcesHookCreator import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.factory.classOf +import com.highcapable.yukihookapi.hook.factory.toClass import com.highcapable.yukihookapi.hook.param.type.HookEntryType import com.highcapable.yukihookapi.hook.param.wrapper.PackageParamWrapper import com.highcapable.yukihookapi.hook.utils.value @@ -341,7 +342,7 @@ open class PackageParam internal constructor(@PublishedApi internal var wrapper: * @return [Class] * @throws NoClassDefFoundError 如果找不到 [Class] */ - fun String.toAppClass() = classOf(name = this, appClassLoader) + fun String.toAppClass() = toClass(appClassLoader) /** * [VariousClass] 转换为当前 Hook APP 的实体类 @@ -357,25 +358,25 @@ open class PackageParam internal constructor(@PublishedApi internal var wrapper: * @param loader [Class] 所在的 [ClassLoader] - 不填使用 [appClassLoader] * @return [Boolean] 是否存在 */ - fun String.hasClass(loader: ClassLoader? = appClassLoader) = runCatching { classOf(name = this, loader); true }.getOrNull() ?: false + fun String.hasClass(loader: ClassLoader? = appClassLoader) = runCatching { toClass(loader); true }.getOrNull() ?: false /** * 查找并装载 [HookClass] * - * - ❗使用此方法会得到一个 [HookClass] 仅用于 Hook - 若想查找 [Class] 请使用 [classOf]、[toAppClass] 功能 + * - ❗使用此方法会得到一个 [HookClass] 仅用于 Hook - 若想查找 [Class] 请使用 [toClass]、[toAppClass] 功能 * @param name 类名 * @param loader 当前 [ClassLoader] - 默认使用 [appClassLoader] - 设为 null 使用默认 [ClassLoader] * @return [HookClass] */ fun findClass(name: String, loader: ClassLoader? = appClassLoader) = - runCatching { classOf(name, loader).toHookClass() }.getOrElse { HookClass(name = name, throwable = it) } + runCatching { name.toClass(loader).toHookClass() }.getOrElse { HookClass(name = name, throwable = it) } /** * 查找并装载 [HookClass] * * 使用此方法查找将会取 [name] 其中命中存在的第一个 [Class] 作为结果 * - * - ❗使用此方法会得到一个 [HookClass] 仅用于 Hook - 若想查找 [Class] 请使用 [classOf]、[toAppClass] 功能 + * - ❗使用此方法会得到一个 [HookClass] 仅用于 Hook - 若想查找 [Class] 请使用 [toClass]、[toAppClass] 功能 * @param name 可填入多个类名 - 自动匹配 * @param loader 当前 [ClassLoader] - 默认使用 [appClassLoader] - 设为 null 使用默认 [ClassLoader] * @return [HookClass] diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.kt index 79f79051..84f7b610 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.kt @@ -55,6 +55,7 @@ import android.view.accessibility.AccessibilityManager import android.view.accessibility.AccessibilityNodeInfo import android.widget.Toast import com.highcapable.yukihookapi.hook.factory.classOf +import com.highcapable.yukihookapi.hook.factory.toClass import org.w3c.dom.UserDataHandler import java.awt.Component @@ -74,7 +75,7 @@ val ContextClass get() = classOf() * 获得 [ContextImpl] 类型 * @return [Class] */ -val ContextImplClass get() = classOf(name = "android.app.ContextImpl") +val ContextImplClass get() = "android.app.ContextImpl".toClass() /** * 获得 [ContextWrapper] 类型 @@ -110,13 +111,13 @@ val PackageInfoClass get() = classOf() * 获得 [ApplicationPackageManager] 类型 * @return [Class] */ -val ApplicationPackageManagerClass get() = classOf(name = "android.app.ApplicationPackageManager") +val ApplicationPackageManagerClass get() = "android.app.ApplicationPackageManager".toClass() /** * 获得 [ActivityThread] 类型 * @return [Class] */ -val ActivityThreadClass get() = classOf(name = "android.app.ActivityThread") +val ActivityThreadClass get() = "android.app.ActivityThread".toClass() /** * 获得 [ActivityManager] 类型 @@ -128,49 +129,49 @@ val ActivityManagerClass get() = classOf() * 获得 [IActivityManager] 类型 * @return [Class] */ -val IActivityManagerClass get() = classOf(name = "android.app.IActivityManager") +val IActivityManagerClass get() = "android.app.IActivityManager".toClass() /** * 获得 [ActivityManagerNative] 类型 * @return [Class] */ -val ActivityManagerNativeClass get() = classOf(name = "android.app.ActivityManagerNative") +val ActivityManagerNativeClass get() = "android.app.ActivityManagerNative".toClass() /** * 获得 [IActivityTaskManager] 类型 * @return [Class] */ -val IActivityTaskManagerClass get() = classOf(name = "android.app.IActivityTaskManager") +val IActivityTaskManagerClass get() = "android.app.IActivityTaskManager".toClass() /** * 获得 [ActivityTaskManager] 类型 * @return [Class] */ -val ActivityTaskManagerClass get() = classOf(name = "android.app.ActivityTaskManager") +val ActivityTaskManagerClass get() = "android.app.ActivityTaskManager".toClass() /** * 获得 [IPackageManager] 类型 * @return [Class] */ -val IPackageManagerClass get() = classOf(name = "android.content.pm.IPackageManager") +val IPackageManagerClass get() = "android.content.pm.IPackageManager".toClass() /** * 获得 [ClientTransaction] 类型 * @return [Class] */ -val ClientTransactionClass get() = classOf(name = "android.app.servertransaction.ClientTransaction") +val ClientTransactionClass get() = "android.app.servertransaction.ClientTransaction".toClass() /** * 获得 [LoadedApk] 类型 * @return [Class] */ -val LoadedApkClass get() = classOf(name = "android.app.LoadedApk") +val LoadedApkClass get() = "android.app.LoadedApk".toClass() /** * 获得 [Singleton] 类型 * @return [Class] */ -val SingletonClass get() = classOf(name = "android.util.Singleton") +val SingletonClass get() = "android.util.Singleton".toClass() /** * 获得 [Activity] 类型 @@ -188,31 +189,31 @@ val LooperClass get() = classOf() * 获得 [Fragment] 类型 - Support * @return [Class] */ -val FragmentClass_AndroidSupport get() = classOf(name = "android.support.v4.app.Fragment") +val FragmentClass_AndroidSupport get() = "android.support.v4.app.Fragment".toClass() /** * 获得 [Fragment] 类型 - AndroidX * @return [Class] */ -val FragmentClass_AndroidX get() = classOf(name = "androidx.fragment.app.Fragment") +val FragmentClass_AndroidX get() = "androidx.fragment.app.Fragment".toClass() /** * 获得 [FragmentActivity] 类型 - Support * @return [Class] */ -val FragmentActivityClass_AndroidSupport get() = classOf(name = "android.support.v4.app.FragmentActivity") +val FragmentActivityClass_AndroidSupport get() = "android.support.v4.app.FragmentActivity".toClass() /** * 获得 [FragmentActivity] 类型 - AndroidX * @return [Class] */ -val FragmentActivityClass_AndroidX get() = classOf(name = "androidx.fragment.app.FragmentActivity") +val FragmentActivityClass_AndroidX get() = "androidx.fragment.app.FragmentActivity".toClass() /** * 获得 [DocumentFile] 类型 - AndroidX * @return [Class] */ -val DocumentFileClass get() = classOf(name = "androidx.documentfile.provider.DocumentFile") +val DocumentFileClass get() = "androidx.documentfile.provider.DocumentFile".toClass() /** * 获得 [Service] 类型 @@ -592,7 +593,7 @@ val XmlClass get() = classOf() * 获得 [ContrastColorUtil] 类型 * @return [Class] */ -val ContrastColorUtilClass get() = classOf(name = "com.android.internal.util.ContrastColorUtil") +val ContrastColorUtilClass get() = "com.android.internal.util.ContrastColorUtil".toClass() /** * 获得 [StatusBarNotification] 类型 diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/AppParasitics.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/AppParasitics.kt index 96fab2a2..6efc0d6c 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/AppParasitics.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/AppParasitics.kt @@ -284,7 +284,7 @@ internal object AppParasitics { }?.takeIf { it.isNotBlank() } ?: context.packageManager?.runCatching { queryIntentActivities(getLaunchIntentForPackage(context.packageName)!!, 0).first().activityInfo.name }?.getOrNull() ?: "" - if ((proxyClassName.hasClass(context.classLoader) && classOf(proxyClassName, context.classLoader).hasMethod { + if ((proxyClassName.hasClass(context.classLoader) && proxyClassName.toClass(context.classLoader).hasMethod { name = "setIntent"; param(IntentClass); superClass() }).not() ) (if (proxyClassName.isBlank()) error("Cound not got launch intent for package \"${context.packageName}\"") diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/delegate/InstrumentationDelegate.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/delegate/InstrumentationDelegate.kt index daf91c84..43e8fe5e 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/delegate/InstrumentationDelegate.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/delegate/InstrumentationDelegate.kt @@ -74,7 +74,7 @@ internal class InstrumentationDelegate private constructor(private val baseInsta baseInstance.newActivity(cl, className, intent) } catch (e: Throwable) { if (className?.startsWith(YukiHookBridge.modulePackageName) == true) - classOf(className).buildOf() ?: throw e + className.toClass().buildOf() ?: throw e else throw e }