diff --git a/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md b/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md index 2c8d3a8f..cc6cb1c3 100644 --- a/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md +++ b/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md @@ -242,7 +242,7 @@ fun members(vararg member: Member?) ```kotlin injectMember { - members(instanceClass.getDeclaredMethod("test", StringType)) + members(instanceClass.getDeclaredMethod("test", StringClass)) beforeHook {} afterHook {} } @@ -255,9 +255,9 @@ injectMember { ```kotlin injectMember { members( - instanceClass.getDeclaredMethod("test1", StringType), - instanceClass.getDeclaredMethod("test2", StringType), - instanceClass.getDeclaredMethod("test3", StringType) + instanceClass.getDeclaredMethod("test1", StringClass), + instanceClass.getDeclaredMethod("test2", StringClass), + instanceClass.getDeclaredMethod("test3", StringClass) ) beforeHook {} afterHook {} @@ -332,7 +332,7 @@ inline fun method(initiate: MethodConditions): MethodFinder.Result injectMember { method { name = "test" - param(StringType) + param(StringClass) returnType = UnitType } beforeHook {} @@ -389,7 +389,7 @@ inline fun constructor(initiate: ConstructorConditions): ConstructorFinder.Resul ```kotlin injectMember { - constructor { param(StringType) } + constructor { param(StringClass) } beforeHook {} afterHook {} } @@ -443,7 +443,7 @@ inline fun HookParam.field(initiate: FieldConditions): FieldFinder.Result injectMember { method { name = "test" - param(StringType) + param(StringClass) returnType = UnitType } afterHook { diff --git a/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md b/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md index 6b428815..5f84e6f2 100644 --- a/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md +++ b/docs-source/src/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md @@ -427,8 +427,8 @@ fun callOriginal(): T? injectMember { method { name = "test" - param(StringType) - returnType = StringType + param(StringClass) + returnType = StringClass } afterHook { // <方案1> 不使用泛型,不获取方法执行结果,调用将使用原方法传入的 args 自动传参 @@ -478,8 +478,8 @@ fun invokeOriginal(vararg args: Any?): T? injectMember { method { name = "test" - param(StringType) - returnType = StringType + param(StringClass) + returnType = StringClass } afterHook { // <方案1> 不使用泛型,不获取方法执行结果 diff --git a/docs-source/src/en/api/special-features/reflection.md b/docs-source/src/en/api/special-features/reflection.md index 8ff26fc7..239a9646 100644 --- a/docs-source/src/en/api/special-features/reflection.md +++ b/docs-source/src/en/api/special-features/reflection.md @@ -222,10 +222,10 @@ searchClass { implements("java.io.Serializable") // Specify the type and style of the constructor // And the number count that exists in the current class - constructor { param(StringType) }.count(num = 1) + constructor { param(StringClass) }.count(num = 1) // Specify the type and style of the variable // And the number that exists in the current class count - field { type = StringType }.count(num = 2) + field { type = StringClass }.count(num = 2) // Specify the type and style of the variable // And the number that exists in the current class count field { type = BooleanType }.count(num = 1) @@ -245,15 +245,15 @@ searchClass { // Specify the modifier, and the number count in the current class method { modifiers { isStatic && isPrivate } - param(StringType) + param(StringClass) returnType = UnitType }.count(num = 1) // Specify the type and style of the method // Specify the modifier, and the number count in the current class method { modifiers { isPrivate && isStatic.not() } - param(BooleanType, StringType) - returnType = StringType + param(BooleanType, StringClass) + returnType = StringClass }.count(num = 1) // Specify the type and style of the method // Specify the modifier, and the number count in the current class @@ -267,7 +267,7 @@ searchClass { // And the number count that exists in the current class method { modifiers { isPrivate && isStatic.not() } - param(BooleanType, VagueType, VagueType, StringType) + param(BooleanType, VagueType, VagueType, StringClass) returnType = UnitType }.count(num = 1) // Directly specify the number of all methods that exist in the current class count @@ -532,7 +532,7 @@ val instance = Test() // Call and execute using YukiHookAPI Test::class.java.method { name = "doTask" - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -599,7 +599,7 @@ val instance = Test() Test::class.java.method { name = "getName" emptyParam() - returnType = StringType + returnType = StringClass }.get(instance).string() // Get the result of the method ``` @@ -655,7 +655,7 @@ Test::class.java.method { name = "release" // Use VagueType to fill in the type you don't want to fill in // While ensuring that other types can match - param(StringType, VagueType, BooleanType) + param(StringClass, VagueType, BooleanType) }.get(instance) // Get this method ``` @@ -673,7 +673,7 @@ val instance = Test() // Call and execute using YukiHookAPI Test::class.java.method { name = "doBaseTask" - param(StringType) + param(StringClass) // Just add this condition superClass() }.get(instance).call("task_name") @@ -693,7 +693,7 @@ val instance = Test() // Call and execute using YukiHookAPI Test::class.java.method { name = "doBaseTask" - param(StringType) + param(StringClass) // Add a find condition superClass(isOnlySuperClass = true) }.get(instance).call("task_name") @@ -732,7 +732,7 @@ Test::class.java.method { // Set name is case insensitive it.equals("dotask", isIgnoreCase = true) } - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -749,7 +749,7 @@ Test::class.java.method { // Only contains oTas it.contains("oTas") } - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -766,7 +766,7 @@ Test::class.java.method { // Contains do at the beginning and Task at the end it.startsWith("do") && it.endsWith("Task") } - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -783,7 +783,7 @@ Test::class.java.method { // Start with do, end with Task, just letters it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters() } - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -902,7 +902,7 @@ Suppose we want to get the contents of the static field `TAG` this time. ```kotlin Test::class.java.field { name = "TAG" - type = StringType + type = StringClass }.get().string() // The type of Field is string and can be cast directly ``` @@ -915,7 +915,7 @@ Just add a filter. ```kotlin Test::class.java.field { name = "TAG" - type = StringType + type = StringClass // This field to identify the lookup needs to be static modifiers { isStatic } }.get().string() // The type of Field is string and can be cast directly @@ -1004,7 +1004,7 @@ val instance = Test() // Call and execute using YukiHookAPI Test::class.java.method { name = "b" - param(StringType) + param(StringClass) }.get(instance).call("test_string") // Get the method whose name is b and whose parameter is [String] ``` @@ -1017,7 +1017,7 @@ The second option is to determine where the parameters of the method are located val instance = Test() // Call and execute using YukiHookAPI Test::class.java.method { - param(StringType).index().first() + param(StringClass).index().first() }.get(instance).call("test_string") // Get the method whose first method parameter is [String] ``` @@ -1058,7 +1058,7 @@ instance.current { // Execute the doTask method method { name = "doTask" - param(StringType) + param(StringClass) }.call("task_name") // Execute the stop method method { @@ -1082,7 +1082,7 @@ instance.current { // Execute the doBaseTask method of the parent class superClass().method { name = "doBaseTask" - param(StringType) + param(StringClass) }.call("task_name") } ``` @@ -1099,7 +1099,7 @@ instance .current() .method { name = "doTask" - param(StringType) + param(StringClass) }.call("task_name") // Execute the stop method instance @@ -1123,7 +1123,7 @@ val instance = Test() instance.current { method { name = "doTask" - param(StringType) + param(StringClass) }.call("task_name") }.current() .method { @@ -1150,7 +1150,7 @@ instance.current { }.current { method { name = "doBaseTask" - param(StringType) + param(StringClass) }.call("task_name") } // @@ -1159,7 +1159,7 @@ instance.current { }.current() ?.method { name = "doBaseTask" - param(StringType) + param(StringClass) }?.call("task_name") } ``` @@ -1209,7 +1209,7 @@ At this time, we can also use the `buildOf` method to create an instance. "com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current { method { name = "doTask" - param(StringType) + param(StringClass) }.call("task_name") } ``` @@ -1263,7 +1263,7 @@ Test::class.java.hook { method { name = "getString" emptyParam() - returnType = StringType + returnType = StringClass } replaceTo("Hooked") } @@ -1279,7 +1279,7 @@ At this point, we use reflection to call this method, and we will get the result val result = Test::class.java.method { name = "getString" emptyParam() - returnType = StringType + returnType = StringClass }.get().string() ``` @@ -1292,7 +1292,7 @@ If we want to get the original method and result of this method without hooking, val result = Test::class.java.method { name = "getString" emptyParam() - returnType = StringType + returnType = StringClass }.get().original().string() ``` @@ -1357,13 +1357,13 @@ Test::class.java.method { }.remedys { method { name = "doTask" - param(StringType) + param(StringClass) }.onFind { // Found logic can be implemented here } method { name = "doTask" - param(StringType, IntType) + param(StringClass, IntType) }.onFind { // Found logic can be implemented here } @@ -1658,7 +1658,7 @@ method { name = "test" param(BooleanType).index(num = 2) // ❗ Wrong usage, please keep only one index method - returnType(StringType).index(num = 1) + returnType(StringClass).index(num = 1) } ``` @@ -1821,13 +1821,13 @@ When find methods and fields, we usually need to specify the type in find condit ```kotlin field { name = "test" - type = Boolean::class.java + type = Boolean::class.javaPrimitiveType } ``` -Expressing the type `Boolean::class.java` in `Kotlin` is very long and not convenient. +Expressing the type of `Boolean::class.javaPrimitiveType` in `Kotlin` is very long and inconvenient. -Therefore, `YukiHookAPI` encapsulates common type calls for developers, including Android's basic types and Java's basic types. +Therefore, `YukiHookAPI` encapsulates common type calls for developers, including Android related types and Java common types and **primitive type keywords**. At this time, the above type can be written in the following form. @@ -1840,19 +1840,19 @@ field { } ``` -Common basic types in Java have been encapsulated as **Name + Type**, such as `IntType`, `FloatType`. +The **primitive type keywords** in common Java types have been encapsulated as **Type(Class Name) + Type**, such as `IntType`, `FloatType` (their bytecode types are `int`, ` float`). Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type `String[]`. You need to write `java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass` to get this type. -Does it feel very troublesome? At this time, we can use the extension method `ArrayClass(StringType)` to get this type. +Does it feel very troublesome, at this time we can use the method `ArrayClass(StringClass)` to get this type. At the same time, since `String` is a common type, you can also directly use `StringArrayClass` to get this type. -Some common methods found in Hook have their corresponding encapsulation types for use, in the format **Name + Class**. +Some common methods found in Hook have their corresponding encapsulation types for use, in the format **Type(Class Name) + Class**. -For example, the Hook `onCreate` method needs to find the `Bundle::class.java` type. +For example, the Hook `onCreate` method needs to look up the `Bundle::class.java` type. > The following example @@ -1863,6 +1863,34 @@ method { } ``` +The following are wrapper names for some special case types in Java represented in `YukiHookAPI`. + +- `void` → `UnitType` + +- `java.lang.Void` → `UnitClass` + +- `java.lang.Object` → `AnyClass` + +- `java.lang.Integer` → `IntClass` + +- `java.lang.Character` → `CharClass` + +::: warning + +Encapsulating types with **Type(Class Name) + Type** will and only be represented as Java **primitive type keywords**. + +Since the concept of **primitive types** does not exist in Kotlin, they will all be defined as **KClass**. + +There are 9 **primitive type keywords** in Java, of which 8 are **primitive type**, namely **boolean**, **char**, **byte**, **short** , **int**, **float**, **long**, **double**, of which the **void** type is a special case. + +At the same time, they all have their own corresponding package types in Java, such as **java.lang.Boolean**, **java.lang.Integer**, these types are **unequal**, Please note the distinction. + +Similarly, arrays also have corresponding wrapper types, which also need to be distinguished from Java **primitive type keywords**. + +For example, the encapsulation type of **byte[]** is **ByteArrayType** or **ArrayClass(ByteType)**, and the encapsulation type of **Byte[]** is **ByteArrayClass** or **ArrayClass(ByteClass )**, these types are also **unequal**. + +::: + ::: tip For more types, see [ComponentTypeFactory](../public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory), [GraphicsTypeFactory](../public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory), [ViewTypeFactory](../public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory), [VariableTypeFactory](../public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory). diff --git a/docs-source/src/en/config/api-exception.md b/docs-source/src/en/config/api-exception.md index 343503cb..cec17d09 100644 --- a/docs-source/src/en/config/api-exception.md +++ b/docs-source/src/en/config/api-exception.md @@ -598,7 +598,7 @@ The `Class` instance subscripted by the `index` number of `param` was not found method { name = "test" // Assume that the Class with subscript "No.1" set here does not exist - param(StringType, "com.example.TestClass", BooleanType) + param(StringClass, "com.example.TestClass", BooleanType) } ``` @@ -867,7 +867,7 @@ PackageParam::class.java.hook { // MethodFinder::class.java.method { name = "name" - param(StringType) + param(StringClass) }.get().call("name") // ... ``` diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md index ea68e3ae..80ac6328 100644 --- a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md +++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md @@ -234,7 +234,7 @@ fun members(vararg member: Member?) ```kotlin injectMember { - members(instanceClass.getDeclaredMethod("test", StringType)) + members(instanceClass.getDeclaredMethod("test", StringClass)) beforeHook {} afterHook {} } @@ -247,9 +247,9 @@ injectMember { ```kotlin injectMember { members( - instanceClass.getDeclaredMethod("test1", StringType), - instanceClass.getDeclaredMethod("test2", StringType), - instanceClass.getDeclaredMethod("test3", StringType) + instanceClass.getDeclaredMethod("test1", StringClass), + instanceClass.getDeclaredMethod("test2", StringClass), + instanceClass.getDeclaredMethod("test3", StringClass) ) beforeHook {} afterHook {} @@ -324,7 +324,7 @@ inline fun method(initiate: MethodConditions): MethodFinder.Result injectMember { method { name = "test" - param(StringType) + param(StringClass) returnType = UnitType } beforeHook {} @@ -381,7 +381,7 @@ inline fun constructor(initiate: ConstructorConditions): ConstructorFinder.Resul ```kotlin injectMember { - constructor { param(StringType) } + constructor { param(StringClass) } beforeHook {} afterHook {} } @@ -435,7 +435,7 @@ inline fun HookParam.field(initiate: FieldConditions): FieldFinder.Result injectMember { method { name = "test" - param(StringType) + param(StringClass) returnType = UnitType } afterHook { diff --git a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md index 55991df3..42dd84de 100644 --- a/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md +++ b/docs-source/src/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md @@ -419,8 +419,8 @@ fun callOriginal(): T? injectMember { method { name = "test" - param(StringType) - returnType = StringType + param(StringClass) + returnType = StringClass } afterHook { // <方案1> 不使用泛型,不获取方法执行结果,调用将使用原方法传入的 args 自动传参 @@ -470,8 +470,8 @@ fun invokeOriginal(vararg args: Any?): T? injectMember { method { name = "test" - param(StringType) - returnType = StringType + param(StringClass) + returnType = StringClass } afterHook { // <方案1> 不使用泛型,不获取方法执行结果 diff --git a/docs-source/src/zh-cn/api/special-features/reflection.md b/docs-source/src/zh-cn/api/special-features/reflection.md index 9cbff29b..b9476460 100644 --- a/docs-source/src/zh-cn/api/special-features/reflection.md +++ b/docs-source/src/zh-cn/api/special-features/reflection.md @@ -198,9 +198,9 @@ searchClass { // 指定实现的接口,可以直接写为完整类名,你还可以同时指定多个 implements("java.io.Serializable") // 指定构造方法的类型与样式,以及在当前类中存在的个数 count - constructor { param(StringType) }.count(num = 1) + constructor { param(StringClass) }.count(num = 1) // 指定变量的类型与样式,以及在当前类中存在的个数 count - field { type = StringType }.count(num = 2) + field { type = StringClass }.count(num = 2) // 指定变量的类型与样式,以及在当前类中存在的个数 count field { type = BooleanType }.count(num = 1) // 直接指定所有变量在当前类中存在的个数 count @@ -216,14 +216,14 @@ searchClass { // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count method { modifiers { isStatic && isPrivate } - param(StringType) + param(StringClass) returnType = UnitType }.count(num = 1) // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count method { modifiers { isPrivate && isStatic.not() } - param(BooleanType, StringType) - returnType = StringType + param(BooleanType, StringClass) + returnType = StringClass }.count(num = 1) // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count method { @@ -234,7 +234,7 @@ searchClass { // 指定方法的类型与样式,同时指定修饰符和模糊类型 VagueType,以及在当前类中存在的个数 count method { modifiers { isPrivate && isStatic.not() } - param(BooleanType, VagueType, VagueType, StringType) + param(BooleanType, VagueType, VagueType, StringClass) returnType = UnitType }.count(num = 1) // 直接指定所有方法在当前类中存在的个数 count @@ -491,7 +491,7 @@ val instance = Test() // 使用 YukiHookAPI 调用并执行 Test::class.java.method { name = "doTask" - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -558,7 +558,7 @@ val instance = Test() Test::class.java.method { name = "getName" emptyParam() - returnType = StringType + returnType = StringClass }.get(instance).string() // 得到方法的结果 ``` @@ -610,7 +610,7 @@ val instance = Test() Test::class.java.method { name = "release" // 使用 VagueType 来填充不想填写的类型,同时保证其它类型能够匹配 - param(StringType, VagueType, BooleanType) + param(StringClass, VagueType, BooleanType) }.get(instance) // 得到这个方法 ``` @@ -628,7 +628,7 @@ val instance = Test() // 使用 YukiHookAPI 调用并执行 Test::class.java.method { name = "doBaseTask" - param(StringType) + param(StringClass) // 只需要添加这个条件 superClass() }.get(instance).call("task_name") @@ -648,7 +648,7 @@ val instance = Test() // 使用 YukiHookAPI 调用并执行 Test::class.java.method { name = "doBaseTask" - param(StringType) + param(StringClass) // 加入一个查找条件 superClass(isOnlySuperClass = true) }.get(instance).call("task_name") @@ -687,7 +687,7 @@ Test::class.java.method { // 设置名称不区分大小写 it.equals("dotask", isIgnoreCase = true) } - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -704,7 +704,7 @@ Test::class.java.method { // 仅包含 oTas it.contains("oTas") } - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -721,7 +721,7 @@ Test::class.java.method { // 开头包含 do,结尾包含 Task it.startsWith("do") && it.endsWith("Task") } - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -738,7 +738,7 @@ Test::class.java.method { // 开头包含 do,结尾包含 Task,仅包含字母 it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters() } - param(StringType) + param(StringClass) }.get(instance).call("task_name") ``` @@ -855,7 +855,7 @@ Test::class.java.method { ```kotlin Test::class.java.field { name = "TAG" - type = StringType + type = StringClass }.get().string() // Field 的类型是字符串,可直接进行 cast ``` @@ -868,7 +868,7 @@ Test::class.java.field { ```kotlin Test::class.java.field { name = "TAG" - type = StringType + type = StringClass // 标识查找的这个变量需要是静态 modifiers { isStatic } }.get().string() // Field 的类型是字符串,可直接进行 cast @@ -957,7 +957,7 @@ val instance = Test() // 使用 YukiHookAPI 调用并执行 Test::class.java.method { name = "b" - param(StringType) + param(StringClass) }.get(instance).call("test_string") // 得到名称为 b 方法参数为 [String] 的方法 ``` @@ -970,7 +970,7 @@ Test::class.java.method { val instance = Test() // 使用 YukiHookAPI 调用并执行 Test::class.java.method { - param(StringType).index().first() + param(StringClass).index().first() }.get(instance).call("test_string") // 得到第一个方法参数为 [String] 的方法 ``` @@ -1009,7 +1009,7 @@ instance.current { // 执行 doTask 方法 method { name = "doTask" - param(StringType) + param(StringClass) }.call("task_name") // 执行 stop 方法 method { @@ -1033,7 +1033,7 @@ instance.current { // 执行父类的 doBaseTask 方法 superClass().method { name = "doBaseTask" - param(StringType) + param(StringClass) }.call("task_name") } ``` @@ -1050,7 +1050,7 @@ instance .current() .method { name = "doTask" - param(StringType) + param(StringClass) }.call("task_name") // 执行 stop 方法 instance @@ -1074,7 +1074,7 @@ val instance = Test() instance.current { method { name = "doTask" - param(StringType) + param(StringClass) }.call("task_name") }.current() .method { @@ -1100,7 +1100,7 @@ instance.current { }.current { method { name = "doBaseTask" - param(StringType) + param(StringClass) }.call("task_name") } // <方案2> @@ -1109,7 +1109,7 @@ instance.current { }.current() ?.method { name = "doBaseTask" - param(StringType) + param(StringClass) }?.call("task_name") } ``` @@ -1157,7 +1157,7 @@ Test(true).doTask("task_name") "com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current { method { name = "doTask" - param(StringType) + param(StringClass) }.call("task_name") } ``` @@ -1211,7 +1211,7 @@ Test::class.java.hook { method { name = "getString" emptyParam() - returnType = StringType + returnType = StringClass } replaceTo("Hooked") } @@ -1227,7 +1227,7 @@ Test::class.java.hook { val result = Test::class.java.method { name = "getString" emptyParam() - returnType = StringType + returnType = StringClass }.get().string() ``` @@ -1240,7 +1240,7 @@ val result = Test::class.java.method { val result = Test::class.java.method { name = "getString" emptyParam() - returnType = StringType + returnType = StringClass }.get().original().string() ``` @@ -1305,13 +1305,13 @@ Test::class.java.method { }.remedys { method { name = "doTask" - param(StringType) + param(StringClass) }.onFind { // 可在这里实现找到的逻辑 } method { name = "doTask" - param(StringType, IntType) + param(StringClass, IntType) }.onFind { // 可在这里实现找到的逻辑 } @@ -1600,7 +1600,7 @@ method { name = "test" param(BooleanType).index(num = 2) // ❗错误的使用方法,请仅保留一个 index 方法 - returnType(StringType).index(num = 1) + returnType(StringClass).index(num = 1) } ``` @@ -1761,13 +1761,13 @@ field { ```kotlin field { name = "test" - type = Boolean::class.java + type = Boolean::class.javaPrimitiveType } ``` -在 `Kotlin` 中表达出 `Boolean::class.java` 这个类型的写法很长,感觉并不方便。 +在 `Kotlin` 中表达出 `Boolean::class.javaPrimitiveType` 这个类型的写法很长,感觉并不方便。 -因此,`YukiHookAPI` 为开发者封装了常见的类型调用,其中包含了 Android 的基本类型和 Java 的基本类型。 +因此,`YukiHookAPI` 为开发者封装了常见的类型调用,其中包含了 Android 的相关类型和 Java 的常见类型与**原始类型关键字**。 这个时候上面的类型就可以写作如下形式了。 @@ -1780,13 +1780,13 @@ field { } ``` -在 Java 中常见的基本类型都已被封装为 **类型 + Type** 的方式,例如 `IntType`、`FloatType`。 +在 Java 常见类型中的**原始类型 (或基本类型) 关键字**都已被封装为 **类型 + Type** 的方式,例如 `IntType`、`FloatType` (它们的字节码类型为 `int`、`float`)。 相应地,数组类型也有方便的使用方法,假设我们要获得 `String[]` 类型的数组。 需要写做 `java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass` 才能得到这个类型。 -感觉是不是很麻烦,这个时候我们可以使用扩展方法 `ArrayClass(StringType)` 来得到这个类型。 +感觉是不是很麻烦,这个时候我们可以使用方法 `ArrayClass(StringClass)` 来得到这个类型。 同时由于 `String` 是常见类型,所以还可以直接使用 `StringArrayClass` 来得到这个类型。 @@ -1803,6 +1803,32 @@ method { } ``` +以下是 Java 中一些特例类型在 `YukiHookAPI` 中的封装名称。 + +- `void` → `UnitType` + +- `java.lang.Void` → `UnitClass` + +- `java.lang.Object` → `AnyClass` + +- `java.lang.Integer` → `IntClass` + +- `java.lang.Character` → `CharClass` + +::: warning + +以 **类型 + Type** 封装类型会且仅会表示为 Java **原始类型关键字**,由于 Kotlin 中不存在**原始类型**这个概念,所以它们都会被定义为 **KClass**。 + +Java 中共有 9 个**原始类型关键字**,其中 8 个为**原始类型**,分别为 **boolean**、**char**、**byte**、**short**、**int**、**float**、**long**、**double**,其中 **void** 类型是一个特例。 + +同时它们都有 Java 自身对应的封装类型,例如 **java.lang.Boolean**、**java.lang.Integer**,这些类型是**不相等的**,请注意区分。 + +同样地,数组也有对应的封装类型,它们也需要与 Java **原始类型关键字** 进行区分。 + +例如 **byte[]** 的封装类型为 **ByteArrayType** 或 **ArrayClass(ByteType)**,而 **Byte[]** 的封装类型为 **ByteArrayClass** 或 **ArrayClass(ByteClass)**,这些类型也是**不相等的**。 + +::: + ::: tip 更多类型可查看 [ComponentTypeFactory](../public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory)、[GraphicsTypeFactory](../public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory)、[ViewTypeFactory](../public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory)、[VariableTypeFactory](../public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory)。 diff --git a/docs-source/src/zh-cn/config/api-exception.md b/docs-source/src/zh-cn/config/api-exception.md index bbc767b0..3d89dc69 100644 --- a/docs-source/src/zh-cn/config/api-exception.md +++ b/docs-source/src/zh-cn/config/api-exception.md @@ -586,7 +586,7 @@ Method/Constructor match paramType\[**INDEX**\] class is not found method { name = "test" // 假设这里设置的 1 号下标的 Class 并不存在 - param(StringType, "com.example.TestClass", BooleanType) + param(StringClass, "com.example.TestClass", BooleanType) } ``` @@ -832,7 +832,7 @@ PackageParam::class.java.hook { // <情景3> MethodFinder::class.java.method { name = "name" - param(StringType) + param(StringClass) }.get().call("name") // ... ``` diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.kt index 3711e203..2dcedacc 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.kt @@ -173,7 +173,7 @@ class YukiMemberHookCreator(@PublishedApi internal val packageParam: PackagePara ) } when (hookClass.name) { - AnyType.name -> throwProblem( + AnyClass.name -> throwProblem( name = "Object", content = "This is the parent Class of all objects, if you hook it, it may cause a lot of memory leaks" ) diff --git a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.kt b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.kt index f5a5d4d5..a2a64f0b 100644 --- a/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.kt +++ b/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.kt @@ -25,12 +25,13 @@ * * This file is Created by fankes on 2022/2/2. */ -@file:Suppress("unused", "KDocUnresolvedReference", "DEPRECATION", "FunctionName", "NewApi") +@file:Suppress("unused", "KDocUnresolvedReference", "DEPRECATION", "FunctionName", "NewApi", "UNCHECKED_CAST") package com.highcapable.yukihookapi.hook.type.java import android.os.Build import com.highcapable.yukihookapi.hook.factory.classOf +import com.highcapable.yukihookapi.hook.factory.toClass import dalvik.system.BaseDexClassLoader import dalvik.system.DexClassLoader import dalvik.system.InMemoryDexClassLoader @@ -55,87 +56,217 @@ import java.util.zip.ZipEntry import java.util.zip.ZipFile import java.util.zip.ZipInputStream import java.util.zip.ZipOutputStream +import java.lang.reflect.Array as JavaArray /** - * 任意类型的数组 + * 获得任意类型的数组 * - * Java 中表示:array[] + * 它在 Java 中表示为:([type])[] * @param type 类型 - * @return [Class] + * @return [Class]<[JavaArray]> */ -fun ArrayClass(type: Class<*>) = java.lang.reflect.Array.newInstance(type, 0).javaClass +fun ArrayClass(type: Class<*>) = JavaArray.newInstance(type, 0).javaClass as Class /** * 获得 [Any] 类型 + * + * - ❗此方法已弃用 - 在之后的版本中将直接被删除 + * + * - ❗请现在转移到 [AnyClass] * @return [Class] */ -val AnyType get() = classOf() - -/** - * 获得 [Unit] 类型 - * @return [Class] - */ -val UnitType get() = Void.TYPE ?: classOf() +@Deprecated(message = "请使用新的命名方法", replaceWith = ReplaceWith(expression = "AnyClass")) +val AnyType get() = AnyClass /** * 获得 [Boolean] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "boolean" * @return [Class] */ -val BooleanType get() = Boolean::class.javaPrimitiveType ?: UnitType - -/** - * 获得 [Int] 类型 - * @return [Class] - */ -val IntType get() = Int::class.javaPrimitiveType ?: UnitType - -/** - * 获得 [Long] 类型 - * @return [Class] - */ -val LongType get() = Long::class.javaPrimitiveType ?: UnitType - -/** - * 获得 [Short] 类型 - * @return [Class] - */ -val ShortType get() = Short::class.javaPrimitiveType ?: UnitType - -/** - * 获得 [Float] 类型 - * @return [Class] - */ -val FloatType get() = Float::class.javaPrimitiveType ?: UnitType - -/** - * 获得 [Double] 类型 - * @return [Class] - */ -val DoubleType get() = Double::class.javaPrimitiveType ?: UnitType - -/** - * 获得 [String] 类型 - * @return [Class] - */ -val StringType get() = classOf() +val BooleanType get() = "boolean".toClass() /** * 获得 [Char] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "char" * @return [Class] */ -val CharType get() = classOf() +val CharType get() = "char".toClass() /** * 获得 [Byte] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "byte" * @return [Class] */ -val ByteType get() = classOf() +val ByteType get() = "byte".toClass() + +/** + * 获得 [Short] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "short" + * @return [Class] + */ +val ShortType get() = "short".toClass() + +/** + * 获得 [Int] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "int" + * @return [Class] + */ +val IntType get() = "int".toClass() + +/** + * 获得 [Float] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "float" + * @return [Class] + */ +val FloatType get() = "float".toClass() + +/** + * 获得 [Long] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "long" + * @return [Class] + */ +val LongType get() = "long".toClass() + +/** + * 获得 [Double] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "double" + * @return [Class] + */ +val DoubleType get() = "double".toClass() + +/** + * 获得 [Unit] 类型 + * + * 这是 Java 原始类型 (Primitive Type) - 它在字节码中的关键字为 "void" + * @return [Class] + */ +val UnitType get() = "void".toClass() + +/** + * 获得 [Any] 类型 + * + * 它等价于 Java 中的 [java.lang.Object] + * @return [Class] + */ +val AnyClass get() = classOf() + +/** + * 获得 [Boolean] 类型 + * + * 它等价于 Java 中的 [java.lang.Boolean] + * @return [Class] + */ +val BooleanClass get() = classOf() + +/** + * 获得 [Char] 类型 + * + * 它等价于 Java 中的 [java.lang.Character] + * @return [Class] + */ +val CharClass get() = classOf() + +/** + * 获得 [Byte] 类型 + * + * 它等价于 Java 中的 [java.lang.Byte] + * @return [Class] + */ +val ByteClass get() = classOf() + +/** + * 获得 [Short] 类型 + * + * 它等价于 Java 中的 [java.lang.Short] + * @return [Class] + */ +val ShortClass get() = classOf() + +/** + * 获得 [Int] 类型 + * + * 它等价于 Java 中的 [java.lang.Integer] + * @return [Class] + */ +val IntClass get() = classOf() + +/** + * 获得 [Float] 类型 + * + * 它等价于 Java 中的 [java.lang.Float] + * @return [Class] + */ +val FloatClass get() = classOf() + +/** + * 获得 [Long] 类型 + * + * 它等价于 Java 中的 [java.lang.Long] + * @return [Class] + */ +val LongClass get() = classOf() + +/** + * 获得 [Double] 类型 + * + * 它等价于 Java 中的 [java.lang.Double] + * @return [Class] + */ +val DoubleClass get() = classOf() + +/** + * 获得 [Unit] 类型 + * + * 它等价于 Java 中的 [java.lang.Void] + * @return [Class] + */ +val UnitClass get() = classOf() + +/** + * 获得 [String] 类型 + * + * - ❗此方法已弃用 - 在之后的版本中将直接被删除 + * + * - ❗请现在转移到 [StringClass] + * @return [Class] + */ +@Deprecated(message = "请使用新的命名方法", replaceWith = ReplaceWith(expression = "StringClass")) +val StringType get() = StringClass /** * 获得 [CharSequence] 类型 + * + * - ❗此方法已弃用 - 在之后的版本中将直接被删除 + * + * - ❗请现在转移到 [CharSequenceClass] * @return [Class] */ -val CharSequenceType get() = classOf() +@Deprecated(message = "请使用新的命名方法", replaceWith = ReplaceWith(expression = "CharSequenceClass")) +val CharSequenceType get() = CharSequenceClass + +/** + * 获得 [String] 类型 + * + * 它等价于 Java 中的 [java.lang.String] + * @return [Class] + */ +val StringClass get() = classOf() + +/** + * 获得 [CharSequence] 类型 + * + * 它等价于 Java 中的 [java.lang.CharSequence] + * @return [Class] + */ +val CharSequenceClass get() = classOf() /** * 获得 [Serializable] 类型 @@ -145,73 +276,163 @@ val SerializableClass get() = classOf() /** * 获得 [Array] 类型 + * + * 它等价于 Java 中的 [java.lang.reflect.Array] * @return [Class] */ -val ArrayClass get() = classOf>() +val ArrayClass get() = classOf() /** - * 获得 [Any] - [Array] 类型 + * 获得 [Boolean] - [Array] 类型 * - * Java 中表示:Object[] + * 这是 Java 原始类型 (Primitive Type) 数组 - 它在字节码中的关键字为 "boolean[]" * @return [Class] */ -val AnyArrayClass get() = ArrayClass(AnyType) +val BooleanArrayType get() = ArrayClass(BooleanType) + +/** + * 获得 [Char] - [Array] 类型 + * + * 这是 Java 原始类型 (Primitive Type) 数组 - 它在字节码中的关键字为 "char[]" + * @return [Class] + */ +val CharArrayType get() = ArrayClass(CharType) /** * 获得 [Byte] - [Array] 类型 * - * Java 中表示:byte[] + * 这是 Java 原始类型 (Primitive Type) 数组 - 它在字节码中的关键字为 "byte[]" * @return [Class] */ -val ByteArrayClass get() = ArrayClass(ByteType) - -/** - * 获得 [Int] - [Array] 类型 - * - * Java 中表示:int[] - * @return [Class] - */ -val IntArrayClass get() = ArrayClass(IntType) - -/** - * 获得 [String] - [Array] 类型 - * - * Java 中表示:String[] - * @return [Class] - */ -val StringArrayClass get() = ArrayClass(StringType) - -/** - * 获得 [Long] - [Array] 类型 - * - * Java 中表示:long[] - * @return [Class] - */ -val LongArrayClass get() = ArrayClass(LongType) +val ByteArrayType get() = ArrayClass(ByteType) /** * 获得 [Short] - [Array] 类型 * - * Java 中表示:short[] + * 这是 Java 原始类型 (Primitive Type) 数组 - 它在字节码中的关键字为 "short[]" * @return [Class] */ -val ShortArrayClass get() = ArrayClass(ShortType) +val ShortArraytType get() = ArrayClass(ShortType) + +/** + * 获得 [Int] - [Array] 类型 + * + * 这是 Java 原始类型 (Primitive Type) 数组 - 它在字节码中的关键字为 "int[]" + * @return [Class] + */ +val IntArrayType get() = ArrayClass(IntType) /** * 获得 [Float] - [Array] 类型 * - * Java 中表示:float[] + * 这是 Java 原始类型 (Primitive Type) 数组 - 它在字节码中的关键字为 "float[]" * @return [Class] */ -val FloatArrayClass get() = ArrayClass(FloatType) +val FloatArrayType get() = ArrayClass(FloatType) + +/** + * 获得 [Long] - [Array] 类型 + * + * 这是 Java 原始类型 (Primitive Type) 数组 - 它在字节码中的关键字为 "long[]" + * @return [Class] + */ +val LongArrayType get() = ArrayClass(LongType) /** * 获得 [Double] - [Array] 类型 * - * Java 中表示:double[] + * 这是 Java 原始类型 (Primitive Type) 数组 - 它在字节码中的关键字为 "double[]" * @return [Class] */ -val DoubleArrayClass get() = ArrayClass(DoubleType) +val DoubleArrayType get() = ArrayClass(DoubleType) + +/** + * 获得 [Any] - [Array] 类型 + * + * 它在 Java 中表示为:Object[] + * @return [Class] + */ +val AnyArrayClass get() = ArrayClass(AnyClass) + +/** + * 获得 [Boolean] - [Array] 类型 + * + * 它在 Java 中表示为:Boolean[] + * @return [Class] + */ +val BooleanArrayClass get() = ArrayClass(BooleanClass) + +/** + * 获得 [Char] - [Array] 类型 + * + * 它在 Java 中表示为:Character[] + * @return [Class] + */ +val CharArrayClass get() = ArrayClass(CharClass) + +/** + * 获得 [Byte] - [Array] 类型 + * + * 它在 Java 中表示为:Byte[] + * @return [Class] + */ +val ByteArrayClass get() = ArrayClass(ByteClass) + +/** + * 获得 [Short] - [Array] 类型 + * + * 它在 Java 中表示为:Short[] + * @return [Class] + */ +val ShortArrayClass get() = ArrayClass(ShortClass) + +/** + * 获得 [Int] - [Array] 类型 + * + * 它在 Java 中表示为:Integer[] + * @return [Class] + */ +val IntArrayClass get() = ArrayClass(IntClass) + +/** + * 获得 [Float] - [Array] 类型 + * + * 它在 Java 中表示为:Float[] + * @return [Class] + */ +val FloatArrayClass get() = ArrayClass(FloatClass) + +/** + * 获得 [Long] - [Array] 类型 + * + * 它在 Java 中表示为:Long[] + * @return [Class] + */ +val LongArrayClass get() = ArrayClass(LongClass) + +/** + * 获得 [Double] - [Array] 类型 + * + * 它在 Java 中表示为:Double[] + * @return [Class] + */ +val DoubleArrayClass get() = ArrayClass(DoubleClass) + +/** + * 获得 [String] - [Array] 类型 + * + * 它在 Java 中表示为:String[] + * @return [Class] + */ +val StringArrayClass get() = ArrayClass(StringClass) + +/** + * 获得 [CharSequence] - [Array] 类型 + * + * 它在 Java 中表示为:CharSequence[] + * @return [Class] + */ +val CharSequenceArrayClass get() = ArrayClass(CharSequenceClass) /** * 获得 [Cloneable] 类型 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 943ebb91..1bed935d 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 @@ -45,10 +45,7 @@ import com.highcapable.yukihookapi.hook.log.yLoggerE import com.highcapable.yukihookapi.hook.log.yLoggerW import com.highcapable.yukihookapi.hook.param.type.HookEntryType import com.highcapable.yukihookapi.hook.type.android.* -import com.highcapable.yukihookapi.hook.type.java.BooleanType -import com.highcapable.yukihookapi.hook.type.java.IntType -import com.highcapable.yukihookapi.hook.type.java.JavaClassLoader -import com.highcapable.yukihookapi.hook.type.java.StringType +import com.highcapable.yukihookapi.hook.type.java.* import com.highcapable.yukihookapi.hook.xposed.bridge.YukiHookBridge import com.highcapable.yukihookapi.hook.xposed.bridge.dummy.YukiModuleResources import com.highcapable.yukihookapi.hook.xposed.bridge.factory.YukiHookHelper @@ -261,7 +258,7 @@ internal object AppParasitics { classLoaderCallbacks[loader.hashCode()] = result if (isClassLoaderHooked) return runCatching { - YukiHookHelper.hook(JavaClassLoader.method { name = "loadClass"; param(StringType, BooleanType) }, object : YukiMemberHook() { + YukiHookHelper.hook(JavaClassLoader.method { name = "loadClass"; param(StringClass, BooleanType) }, object : YukiMemberHook() { override fun afterHookedMember(param: Param) { param.instance?.also { loader -> (param.result as? Class<*>?)?.also { classLoaderCallbacks[loader.hashCode()]?.invoke(it) } @@ -278,7 +275,7 @@ internal object AppParasitics { */ internal fun injectModuleAppResources(hostResources: Resources) { if (YukiHookBridge.hasXposedBridge) runCatching { - hostResources.assets.current(ignored = true).method { name = "addAssetPath"; param(StringType) }.call(moduleAppFilePath) + hostResources.assets.current(ignored = true).method { name = "addAssetPath"; param(StringClass) }.call(moduleAppFilePath) }.onFailure { yLoggerE(msg = "Failed to inject module resources into [$hostResources]", e = it) } else yLoggerW(msg = "You can only inject module resources in Xposed Environment")