diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 00000000..46e59536 --- /dev/null +++ b/docs/404.html @@ -0,0 +1,33 @@ + + +
+ + + + + +abstract class BaseFinder
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u5206\u79BB\u539F\u59CB\u547D\u540D BaseFinder
\u4E2D\u7684\u90E8\u5206\u65B9\u6CD5\u4E0E\u53C2\u6570\u5230 MemberBaseFinder
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F
Class
\u4E0EMember
\u67E5\u627E\u7C7B\u529F\u80FD\u7684\u57FA\u672C\u7C7B\u5B9E\u73B0\u3002
inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5B57\u8282\u7801\u4E0B\u6807\u7B5B\u9009\u5B9E\u73B0\u7C7B\u3002
fun index(num: Int)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u4E0B\u6807\u3002
\u82E5 index
\u5C0F\u4E8E\u96F6\u5219\u4E3A\u5012\u5E8F\uFF0C\u6B64\u65F6\u53EF\u4EE5\u4F7F\u7528 IndexTypeConditionSort.reverse
\u65B9\u6CD5\u5B9E\u73B0\u3002
\u53EF\u4F7F\u7528 IndexTypeConditionSort.first
\u548C IndexTypeConditionSort.last
\u8BBE\u7F6E\u9996\u4F4D\u548C\u672B\u4F4D\u7B5B\u9009\u6761\u4EF6\u3002
fun index(): IndexTypeConditionSort
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u4E0B\u6807\u3002
inner class IndexTypeConditionSort internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5B57\u8282\u7801\u4E0B\u6807\u6392\u5E8F\u5B9E\u73B0\u7C7B\u3002
fun first()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u6EE1\u8DB3\u6761\u4EF6\u7684\u7B2C\u4E00\u4E2A\u3002
fun last()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u6EE1\u8DB3\u6761\u4EF6\u7684\u6700\u540E\u4E00\u4E2A\u3002
fun reverse(num: Int)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,52),l=[p];function c(t,r){return e(),o("div",null,l)}const i=s(a,[["render",c],["__file","BaseFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/BaseFinder.html.8588c8ac.js b/docs/assets/BaseFinder.html.8588c8ac.js new file mode 100644 index 00000000..1929a43a --- /dev/null +++ b/docs/assets/BaseFinder.html.8588c8ac.js @@ -0,0 +1,9 @@ +import{_ as s,o as e,c as n,a as o}from"./app.fb8271cf.js";const a={},l=o(`\u8BBE\u7F6E\u5012\u5E8F\u4E0B\u6807\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
abstract class BaseFinder
+
Change Records
v1.0.70
added
v1.1.0
modified
\u5206\u79BB\u539F\u59CB\u547D\u540D BaseFinder
\u4E2D\u7684\u90E8\u5206\u65B9\u6CD5\u4E0E\u53C2\u6570\u5230 MemberBaseFinder
Function Illustrate
\u8FD9\u662F
Class
\u4E0EMember
\u67E5\u627E\u7C7B\u529F\u80FD\u7684\u57FA\u672C\u7C7B\u5B9E\u73B0\u3002
inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
+
Change Records
v1.0.70
added
Function Illustrate
\u5B57\u8282\u7801\u4E0B\u6807\u7B5B\u9009\u5B9E\u73B0\u7C7B\u3002
fun index(num: Int)
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E\u4E0B\u6807\u3002
\u82E5 index
\u5C0F\u4E8E\u96F6\u5219\u4E3A\u5012\u5E8F\uFF0C\u6B64\u65F6\u53EF\u4EE5\u4F7F\u7528 IndexTypeConditionSort.reverse
\u65B9\u6CD5\u5B9E\u73B0\u3002
\u53EF\u4F7F\u7528 IndexTypeConditionSort.first
\u548C IndexTypeConditionSort.last
\u8BBE\u7F6E\u9996\u4F4D\u548C\u672B\u4F4D\u7B5B\u9009\u6761\u4EF6\u3002
fun index(): IndexTypeConditionSort
+
Change Records
v1.0.70
added
Function Illustrate
\u5F97\u5230\u4E0B\u6807\u3002
inner class IndexTypeConditionSort internal constructor()
+
Change Records
v1.0.70
added
Function Illustrate
\u5B57\u8282\u7801\u4E0B\u6807\u6392\u5E8F\u5B9E\u73B0\u7C7B\u3002
fun first()
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E\u6EE1\u8DB3\u6761\u4EF6\u7684\u7B2C\u4E00\u4E2A\u3002
fun last()
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E\u6EE1\u8DB3\u6761\u4EF6\u7684\u6700\u540E\u4E00\u4E2A\u3002
fun reverse(num: Int)
+
Change Records
v1.0.70
added
Function Illustrate
`,53),t=[l];function p(c,r){return e(),n("div",null,t)}const i=s(a,[["render",p],["__file","BaseFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/BaseFinder.html.8f275c85.js b/docs/assets/BaseFinder.html.8f275c85.js new file mode 100644 index 00000000..31aba98c --- /dev/null +++ b/docs/assets/BaseFinder.html.8f275c85.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0f719471","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html","title":"BaseFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"BaseFinder.IndexTypeCondition - class","slug":"basefinder-indextypecondition-class","link":"#basefinder-indextypecondition-class","children":[{"level":3,"title":"index - method","slug":"index-method","link":"#index-method","children":[]},{"level":3,"title":"index - method","slug":"index-method-1","link":"#index-method-1","children":[]},{"level":3,"title":"IndexTypeConditionSort - class","slug":"indextypeconditionsort-class","link":"#indextypeconditionsort-class","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.md"}');export{e as data}; diff --git a/docs/assets/BaseFinder.html.a5dbb7a7.js b/docs/assets/BaseFinder.html.a5dbb7a7.js new file mode 100644 index 00000000..4fb0f3ba --- /dev/null +++ b/docs/assets/BaseFinder.html.a5dbb7a7.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-4fca92c0","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html","title":"BaseFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"BaseFinder.IndexTypeCondition - class","slug":"basefinder-indextypecondition-class","link":"#basefinder-indextypecondition-class","children":[{"level":3,"title":"index - method","slug":"index-method","link":"#index-method","children":[]},{"level":3,"title":"index - method","slug":"index-method-1","link":"#index-method-1","children":[]},{"level":3,"title":"IndexTypeConditionSort - class","slug":"indextypeconditionsort-class","link":"#indextypeconditionsort-class","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.md"}');export{e as data}; diff --git a/docs/assets/ChannelData.html.194718a1.js b/docs/assets/ChannelData.html.194718a1.js new file mode 100644 index 00000000..8fa38613 --- /dev/null +++ b/docs/assets/ChannelData.html.194718a1.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-493d37f6","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html","title":"ChannelData - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.md"}');export{a as data}; diff --git a/docs/assets/ChannelData.html.2358cb0e.js b/docs/assets/ChannelData.html.2358cb0e.js new file mode 100644 index 00000000..7fb06487 --- /dev/null +++ b/docs/assets/ChannelData.html.2358cb0e.js @@ -0,0 +1,23 @@ +import{_ as s,o as a,c as n,a as l}from"./app.fb8271cf.js";const e={},o=l(`\u8BBE\u7F6E\u5012\u5E8F\u4E0B\u6807\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
data class ChannelData<T>(var key: String, var value: T?)
+
Change Records
v1.0.88
added
Function Illustrate
\u6570\u636E\u901A\u8BAF\u6865\u952E\u503C\u6784\u9020\u7C7B\u3002
\u8FD9\u4E2A\u7C7B\u662F\u5BF9 YukiHookDataChannel
\u7684\u4E00\u4E2A\u6269\u5C55\u7528\u6CD5\u3002
Function Example
\u5EFA\u7ACB\u4E00\u4E2A\u6A21\u677F\u7C7B\u5B9A\u4E49\u6A21\u5757\u4E0E\u5BBF\u4E3B\u9700\u8981\u53D1\u9001\u7684\u952E\u503C\u6570\u636E\u3002
The following example
object DataConst {
+
+ val TEST_KV_DATA_1 = ChannelData("test_data_1", "defalut value")
+ val TEST_KV_DATA_2 = ChannelData("test_data_2", 0)
+}
+
\u952E\u503C\u6570\u636E\u5B9A\u4E49\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u65B9\u4FBF\u5730\u5728\u6A21\u5757\u548C\u5BBF\u4E3B\u4E2D\u8C03\u7528\u6240\u9700\u8981\u53D1\u9001\u7684\u6570\u636E\u3002
\u6A21\u5757\u793A\u4F8B\u5982\u4E0B
// \u4ECE\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u83B7\u53D6
+dataChannel(packageName = "com.example.demo").wait(DataConst.TEST_KV_DATA_1) { value ->
+ // Your code here.
+}
+// \u53D1\u9001\u7ED9\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B - \u672A\u586B\u5199 value \u65F6\u5C06\u4F7F\u7528\u6A21\u677F\u63D0\u4F9B\u7684\u9ED8\u8BA4\u503C
+dataChannel(packageName = "com.example.demo").put(DataConst.TEST_KV_DATA_1, value = "sending value")
+
\u5BBF\u4E3B\u793A\u4F8B\u5982\u4E0B
// \u4ECE\u6A21\u5757\u83B7\u53D6
+dataChannel.wait(DataConst.TEST_KV_DATA_1) { value ->
+ // Your code here.
+}
+// \u53D1\u9001\u7ED9\u6A21\u5757 - \u672A\u586B\u5199 value \u65F6\u5C06\u4F7F\u7528\u6A21\u677F\u63D0\u4F9B\u7684\u9ED8\u8BA4\u503C
+dataChannel.put(DataConst.TEST_KV_DATA_1, value = "sending value")
+
\u4F60\u4F9D\u7136\u53EF\u4EE5\u4E0D\u4F7F\u7528\u6A21\u677F\u5B9A\u4E49\u7684\u9ED8\u8BA4\u503C\uFF0C\u968F\u65F6\u4FEE\u6539\u4F60\u7684\u9ED8\u8BA4\u503C\u3002
The following example
// \u83B7\u53D6 - \u6B64\u65F6 value \u53D6\u5230\u7684\u9ED8\u8BA4\u503C\u5C06\u4F1A\u662F 2 - \u5E76\u4E0D\u662F\u6A21\u677F\u63D0\u4F9B\u7684 0
+dataChannel.wait(DataConst.TEST_KV_DATA_2, value = 2) { value ->
+ // Your code here.
+}
+
data class ChannelData<T>(var key: String, var value: T?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6570\u636E\u901A\u8BAF\u6865\u952E\u503C\u6784\u9020\u7C7B\u3002
\u8FD9\u4E2A\u7C7B\u662F\u5BF9 YukiHookDataChannel
\u7684\u4E00\u4E2A\u6269\u5C55\u7528\u6CD5\u3002
\u529F\u80FD\u793A\u4F8B
\u5EFA\u7ACB\u4E00\u4E2A\u6A21\u677F\u7C7B\u5B9A\u4E49\u6A21\u5757\u4E0E\u5BBF\u4E3B\u9700\u8981\u53D1\u9001\u7684\u952E\u503C\u6570\u636E\u3002
\u793A\u4F8B\u5982\u4E0B
object DataConst {
+
+ val TEST_KV_DATA_1 = ChannelData("test_data_1", "defalut value")
+ val TEST_KV_DATA_2 = ChannelData("test_data_2", 0)
+}
+
\u952E\u503C\u6570\u636E\u5B9A\u4E49\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u65B9\u4FBF\u5730\u5728\u6A21\u5757\u548C\u5BBF\u4E3B\u4E2D\u8C03\u7528\u6240\u9700\u8981\u53D1\u9001\u7684\u6570\u636E\u3002
\u6A21\u5757\u793A\u4F8B\u5982\u4E0B
// \u4ECE\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u83B7\u53D6
+dataChannel(packageName = "com.example.demo").wait(DataConst.TEST_KV_DATA_1) { value ->
+ // Your code here.
+}
+// \u53D1\u9001\u7ED9\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B - \u672A\u586B\u5199 value \u65F6\u5C06\u4F7F\u7528\u6A21\u677F\u63D0\u4F9B\u7684\u9ED8\u8BA4\u503C
+dataChannel(packageName = "com.example.demo").put(DataConst.TEST_KV_DATA_1, value = "sending value")
+
\u5BBF\u4E3B\u793A\u4F8B\u5982\u4E0B
// \u4ECE\u6A21\u5757\u83B7\u53D6
+dataChannel.wait(DataConst.TEST_KV_DATA_1) { value ->
+ // Your code here.
+}
+// \u53D1\u9001\u7ED9\u6A21\u5757 - \u672A\u586B\u5199 value \u65F6\u5C06\u4F7F\u7528\u6A21\u677F\u63D0\u4F9B\u7684\u9ED8\u8BA4\u503C
+dataChannel.put(DataConst.TEST_KV_DATA_1, value = "sending value")
+
\u4F60\u4F9D\u7136\u53EF\u4EE5\u4E0D\u4F7F\u7528\u6A21\u677F\u5B9A\u4E49\u7684\u9ED8\u8BA4\u503C\uFF0C\u968F\u65F6\u4FEE\u6539\u4F60\u7684\u9ED8\u8BA4\u503C\u3002
\u793A\u4F8B\u5982\u4E0B
// \u83B7\u53D6 - \u6B64\u65F6 value \u53D6\u5230\u7684\u9ED8\u8BA4\u503C\u5C06\u4F1A\u662F 2 - \u5E76\u4E0D\u662F\u6A21\u677F\u63D0\u4F9B\u7684 0
+dataChannel.wait(DataConst.TEST_KV_DATA_2, value = 2) { value ->
+ // Your code here.
+}
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
',5),l=o("\u8BE6\u60C5\u53EF "),_={href:"https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"},h=o("\u70B9\u51FB\u8FD9\u91CC"),k=o(" \u8FDB\u884C\u67E5\u770B\u3002");function m(y,f){const t=c("ExternalLinkIcon");return a(),r("div",null,[i,e("p",null,[l,e("a",_,[h,s(t)]),k])])}const b=n(d,[["render",m],["__file","ComponentTypeFactory.html.vue"]]);export{b as default}; diff --git a/docs/assets/ComponentTypeFactory.html.5af05d7d.js b/docs/assets/ComponentTypeFactory.html.5af05d7d.js new file mode 100644 index 00000000..66963498 --- /dev/null +++ b/docs/assets/ComponentTypeFactory.html.5af05d7d.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-8293d958","path":"/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html","title":"ComponentTypeFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.md"}');export{e as data}; diff --git a/docs/assets/ComponentTypeFactory.html.61d8989e.js b/docs/assets/ComponentTypeFactory.html.61d8989e.js new file mode 100644 index 00000000..ba0fbc9b --- /dev/null +++ b/docs/assets/ComponentTypeFactory.html.61d8989e.js @@ -0,0 +1 @@ +import{_ as n,r as a,o as c,c as s,b as e,d as r,a as i,e as o}from"./app.fb8271cf.js";const p={},l=i('\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A
Android
\u76F8\u5173\u7EC4\u4EF6\u7684Class
\u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0
first
Function Illustrate
',6),d=o("\u8BE6\u60C5\u53EF "),h={href:"https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"},_=o("\u70B9\u51FB\u8FD9\u91CC"),m=o(" \u8FDB\u884C\u67E5\u770B\u3002");function u(k,f){const t=a("ExternalLinkIcon");return c(),s("div",null,[l,e("p",null,[d,e("a",h,[_,r(t)]),m])])}const g=n(p,[["render",u],["__file","ComponentTypeFactory.html.vue"]]);export{g as default}; diff --git a/docs/assets/ConstructorFinder.html.022babd4.js b/docs/assets/ConstructorFinder.html.022babd4.js new file mode 100644 index 00000000..0188d364 --- /dev/null +++ b/docs/assets/ConstructorFinder.html.022babd4.js @@ -0,0 +1,87 @@ +import{_ as s,o as n,c as o,a}from"./app.fb8271cf.js";const e={},l=a(`\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A
Android
\u76F8\u5173\u7EC4\u4EF6\u7684Class
\u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ConstructorFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
+
Change Records
v1.0
first
v1.0.2
modified
\u5408\u5E76\u5230 BaseFinder
v1.1.0
modified
\u5408\u5E76\u5230 MemberBaseFinder
Function Illustrate
Constructor
\u67E5\u627E\u7C7B\u3002
\u53EF\u901A\u8FC7\u6307\u5B9A\u7C7B\u578B\u67E5\u627E\u6307\u5B9A Constructor
\u6216\u4E00\u7EC4 Constructor
\u3002
var paramCount: Int
+
Change Records
v1.0.67
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u53D8\u91CF\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.67
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
modified
\u5408\u5E76\u5230 ModifierConditions
Function Illustrate
\u8BBE\u7F6E
Constructor
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\uFF0C\u9ED8\u8BA4\u6A21\u7CCA\u67E5\u627E\u5E76\u53D6\u7B2C\u4E00\u4E2A\u5339\u914D\u7684 Constructor
\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun emptyParam(): IndexTypeCondition
+
Change Records
v1.0.75
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002
fun param(vararg paramType: Any): IndexTypeCondition
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u3002
\u5982\u679C\u540C\u65F6\u4F7F\u7528\u4E86 paramCount
\u5219 paramType
\u7684\u6570\u91CF\u5FC5\u987B\u4E0E paramCount
\u5B8C\u5168\u5339\u914D\u3002
\u5982\u679C Constructor
\u4E2D\u5B58\u5728\u4E00\u4E9B\u65E0\u610F\u4E49\u53C8\u5F88\u957F\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 VagueType \u6765\u66FF\u4EE3\u5B83\u3002
Pay Attention
\u65E0\u53C2 Constructor \u8BF7\u4F7F\u7528 emptyParam \u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002
\u6709\u53C2 Constructor \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u5B9A\u53C2\u6570\u6216\u4F7F\u7528 paramCount \u6307\u5B9A\u4E2A\u6570\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(num: Int): IndexTypeCondition
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(numRange: IntRange): IndexTypeCondition
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E\u5728
classSet
\u7684\u6240\u6709\u7236\u7C7B\u4E2D\u67E5\u627E\u5F53\u524DConstructor
\u3002
Notice
\u82E5\u5F53\u524D classSet \u7684\u7236\u7C7B\u8F83\u591A\u53EF\u80FD\u4F1A\u8017\u65F6\uFF0CAPI \u4F1A\u81EA\u52A8\u5FAA\u73AF\u5230\u7236\u7C7B\u7EE7\u627F\u662F Any \u524D\u7684\u6700\u540E\u4E00\u4E2A\u7C7B\u3002
inner class RemedyPlan internal constructor()
+
Change Records
v1.0
first
Function Illustrate
Constructor
\u91CD\u67E5\u627E\u5B9E\u73B0\u7C7B\uFF0C\u53EF\u7D2F\u8BA1\u5931\u8D25\u6B21\u6570\u76F4\u5230\u67E5\u627E\u6210\u529F\u3002
inline fun constructor(initiate: ConstructorConditions)
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA\u9700\u8981\u91CD\u65B0\u67E5\u627E\u7684
Constructor
\u3002
\u4F60\u53EF\u4EE5\u6DFB\u52A0\u591A\u4E2A\u5907\u9009 Constructor
\uFF0C\u76F4\u5230\u6210\u529F\u4E3A\u6B62\uFF0C\u82E5\u6700\u540E\u4F9D\u7136\u5931\u8D25\uFF0C\u5C06\u505C\u6B62\u67E5\u627E\u5E76\u8F93\u51FA\u9519\u8BEF\u65E5\u5FD7\u3002
inner class Result internal constructor()
+
Change Records
v1.0.1
added
Function Illustrate
RemedyPlan
\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
fun onFind(initiate: HashSet<Constructor<*>>.() -> Unit)
+
Change Records
v1.0.1
added
v1.1.0
modified
initiate
\u53C2\u6570 Constructor
\u53D8\u4E3A HashSet<Constructor>
Function Illustrate
\u5F53\u5728
RemedyPlan
\u4E2D\u627E\u5230\u7ED3\u679C\u65F6\u3002
Function Example
\u4F60\u53EF\u4EE5\u65B9\u4FBF\u5730\u5BF9\u91CD\u67E5\u627E\u7684 Constructor
\u5B9E\u73B0 onFind
\u65B9\u6CD5\u3002
The following example
constructor {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.1.0
added
Function Illustrate
Constructor
\u67E5\u627E\u7ED3\u679C\u5904\u7406\u7C7B\uFF0C\u4E3AhookInstance
\u63D0\u4F9B\u3002
inline fun result(initiate: Process.() -> Unit): Process
+
Change Records
v1.1.0
added
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
Function Example
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
The following example
constructor {
+ // Your code here.
+}.result {
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
fun all(): Process
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A
Constructor
\u5B9E\u4F8B\u7ED3\u679C\u5230hookInstance
\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u521B\u5EFA
Constructor
\u91CD\u67E5\u627E\u529F\u80FD\u3002
Function Example
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Constructor
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchConstructor
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Constructor
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
The following example
constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u76D1\u542C\u627E\u4E0D\u5230
Constructor
\u65F6\u3002
\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u6B21\u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u4E0D\u4F1A\u8FD4\u56DE RemedyPlan
\u7684\u9519\u8BEF\u4FE1\u606F\u3002
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.0
first
v1.1.0
modified
\u7EE7\u627F\u5230\u63A5\u53E3 BaseResult
Function Illustrate
Constructor
\u67E5\u627E\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
Function Example
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
The following example
constructor {
+ // Your code here.
+}.result {
+ get().call()
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
fun get(): Instance
+
Change Records
v1.0.2
added
Function Illustrate
\u83B7\u5F97
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
\u82E5\u6709\u591A\u4E2A Constructor
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
Pay Attention
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u8BF7\u4F7F\u7528 wait \u56DE\u8C03\u7ED3\u679C\u65B9\u6CD5\u3002
Function Example
\u4F60\u53EF\u4EE5\u901A\u8FC7\u83B7\u5F97\u65B9\u6CD5\u6240\u5728\u5B9E\u4F8B\u6765\u6267\u884C\u6784\u9020\u65B9\u6CD5\u521B\u5EFA\u65B0\u7684\u5B9E\u4F8B\u5BF9\u8C61\u3002
The following example
constructor {
+ // Your code here.
+}.get().call()
+
\u4F60\u53EF\u4EE5 cast
\u6784\u9020\u65B9\u6CD5\u4E3A\u6307\u5B9A\u7C7B\u578B\u7684\u5B9E\u4F8B\u5BF9\u8C61\u3002
The following example
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>()
+
Pay Attention
\u82E5\u6784\u9020\u65B9\u6CD5\u542B\u6709\u53C2\u6570\u5219\u540E\u65B9\u53C2\u6570\u5FC5\u586B\u3002
The following example
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>("param1", "param2")
+
fun all(): ArrayList<Instance>
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Constructor
\u5B9E\u4F8B\u7ED3\u679C\u3002
Function Example
\u4F60\u53EF\u4EE5\u901A\u8FC7\u6B64\u65B9\u6CD5\u6765\u83B7\u5F97\u5F53\u524D\u6761\u4EF6\u7ED3\u679C\u4E2D\u5339\u914D\u7684\u5168\u90E8 Constructor
\u3002
The following example
constructor {
+ // Your code here.
+}.all().forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Constructor<*>?
+
Change Records
v1.0.67
added
Function Illustrate
\u5F97\u5230
Constructor
\u672C\u8EAB\u3002
\u82E5\u6709\u591A\u4E2A Constructor
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE null
\u3002
fun giveAll(): HashSet<Constructor<*>>
+
Change Records
v1.1.0
added
Function Illustrate
\u5F97\u5230
Constructor
\u672C\u8EAB\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Constructor
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE\u7A7A\u7684 HashSet
\u3002
fun wait(initiate: Instance.() -> Unit)
+
Change Records
v1.0.2
added
Function Illustrate
\u83B7\u5F97
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u82E5\u6709\u591A\u4E2A Constructor
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
Pay Attention
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
fun waitAll(initiate: ArrayList<Instance>.() -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Constructor
\u5B9E\u4F8B\u7ED3\u679C\u3002
Pay Attention
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA
Constructor
\u91CD\u67E5\u627E\u529F\u80FD\u3002
Function Example
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Constructor
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchConstructor
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Constructor
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
The following example
constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u76D1\u542C\u627E\u4E0D\u5230
Constructor
\u65F6\u3002
\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u6B21\u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u4E0D\u4F1A\u8FD4\u56DE RemedyPlan
\u7684\u9519\u8BEF\u4FE1\u606F\u3002
fun ignored(): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u5FFD\u7565\u5F02\u5E38\u5E76\u505C\u6B62\u6253\u5370\u4EFB\u4F55\u9519\u8BEF\u65E5\u5FD7\u3002
\u82E5 isNotIgnoredHookingFailure
\u4E3A false
\u5219\u81EA\u52A8\u5FFD\u7565\u3002
Notice
\u6B64\u65F6\u82E5\u8981\u76D1\u542C\u5F02\u5E38\u7ED3\u679C\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u5B9E\u73B0 onNoSuchConstructor \u65B9\u6CD5\u3002
Change Records
v1.0.3
added
v1.1.0
deprecated
\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()
inner class Instance internal constructor(private val constructor: Constructor<*>?)
+
Change Records
v1.0.2
added
v1.1.0
modified
\u65B0\u589E constructor
\u53C2\u6570
Function Illustrate
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
fun call(vararg param: Any?): Any?
+
Change Records
v1.0.2
added
Function Illustrate
\u6267\u884C
Constructor
\u521B\u5EFA\u76EE\u6807\u5B9E\u4F8B\uFF0C\u4E0D\u6307\u5B9A\u76EE\u6807\u5B9E\u4F8B\u7C7B\u578B\u3002
fun <T> newInstance(vararg param: Any?): T?
+
Change Records
v1.0.2
added
Function Illustrate
`,288),p=[l];function c(t,r){return n(),o("div",null,p)}const i=s(e,[["render",c],["__file","ConstructorFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/ConstructorFinder.html.0c13dc47.js b/docs/assets/ConstructorFinder.html.0c13dc47.js new file mode 100644 index 00000000..2f28cba1 --- /dev/null +++ b/docs/assets/ConstructorFinder.html.0c13dc47.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-a71937aa","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html","title":"ConstructorFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-2","link":"#paramcount-method-2","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Process - class","slug":"process-class","link":"#process-class","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchConstructor - method","slug":"onnosuchconstructor-method","link":"#onnosuchconstructor-method","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method-1","link":"#result-method-1","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method-1","link":"#all-method-1","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method-1","link":"#remedys-method-1","children":[]},{"level":3,"title":"onNoSuchConstructor - method","slug":"onnosuchconstructor-method-1","link":"#onnosuchconstructor-method-1","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.md"}');export{e as data}; diff --git a/docs/assets/ConstructorFinder.html.254da89b.js b/docs/assets/ConstructorFinder.html.254da89b.js new file mode 100644 index 00000000..953ffdfe --- /dev/null +++ b/docs/assets/ConstructorFinder.html.254da89b.js @@ -0,0 +1,87 @@ +import{_ as s,o as n,c as o,a}from"./app.fb8271cf.js";const e={},l=a(`\u6267\u884C
Constructor
\u521B\u5EFA\u76EE\u6807\u5B9E\u4F8B \uFF0C\u6307\u5B9AT
\u76EE\u6807\u5B9E\u4F8B\u7C7B\u578B\u3002
class ConstructorFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.2
\u4FEE\u6539
\u5408\u5E76\u5230 BaseFinder
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 MemberBaseFinder
\u529F\u80FD\u63CF\u8FF0
Constructor
\u67E5\u627E\u7C7B\u3002
\u53EF\u901A\u8FC7\u6307\u5B9A\u7C7B\u578B\u67E5\u627E\u6307\u5B9A Constructor
\u6216\u4E00\u7EC4 Constructor
\u3002
var paramCount: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u53D8\u91CF\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 ModifierConditions
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\uFF0C\u9ED8\u8BA4\u6A21\u7CCA\u67E5\u627E\u5E76\u53D6\u7B2C\u4E00\u4E2A\u5339\u914D\u7684 Constructor
\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun emptyParam(): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.75
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002
fun param(vararg paramType: Any): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u3002
\u5982\u679C\u540C\u65F6\u4F7F\u7528\u4E86 paramCount
\u5219 paramType
\u7684\u6570\u91CF\u5FC5\u987B\u4E0E paramCount
\u5B8C\u5168\u5339\u914D\u3002
\u5982\u679C Constructor
\u4E2D\u5B58\u5728\u4E00\u4E9B\u65E0\u610F\u4E49\u53C8\u5F88\u957F\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 VagueType \u6765\u66FF\u4EE3\u5B83\u3002
\u7279\u522B\u6CE8\u610F
\u65E0\u53C2 Constructor \u8BF7\u4F7F\u7528 emptyParam \u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002
\u6709\u53C2 Constructor \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u5B9A\u53C2\u6570\u6216\u4F7F\u7528 paramCount \u6307\u5B9A\u4E2A\u6570\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(num: Int): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(numRange: IntRange): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun superClass(isOnlySuperClass: Boolean)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5728
classSet
\u7684\u6240\u6709\u7236\u7C7B\u4E2D\u67E5\u627E\u5F53\u524DConstructor
\u3002
\u6CE8\u610F
\u82E5\u5F53\u524D classSet \u7684\u7236\u7C7B\u8F83\u591A\u53EF\u80FD\u4F1A\u8017\u65F6\uFF0CAPI \u4F1A\u81EA\u52A8\u5FAA\u73AF\u5230\u7236\u7C7B\u7EE7\u627F\u662F Any \u524D\u7684\u6700\u540E\u4E00\u4E2A\u7C7B\u3002
inner class RemedyPlan internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
Constructor
\u91CD\u67E5\u627E\u5B9E\u73B0\u7C7B\uFF0C\u53EF\u7D2F\u8BA1\u5931\u8D25\u6B21\u6570\u76F4\u5230\u67E5\u627E\u6210\u529F\u3002
inline fun constructor(initiate: ConstructorConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u9700\u8981\u91CD\u65B0\u67E5\u627E\u7684
Constructor
\u3002
\u4F60\u53EF\u4EE5\u6DFB\u52A0\u591A\u4E2A\u5907\u9009 Constructor
\uFF0C\u76F4\u5230\u6210\u529F\u4E3A\u6B62\uFF0C\u82E5\u6700\u540E\u4F9D\u7136\u5931\u8D25\uFF0C\u5C06\u505C\u6B62\u67E5\u627E\u5E76\u8F93\u51FA\u9519\u8BEF\u65E5\u5FD7\u3002
inner class Result internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.1
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
RemedyPlan
\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
fun onFind(initiate: HashSet<Constructor<*>>.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.1
\u65B0\u589E
v1.1.0
\u4FEE\u6539
initiate
\u53C2\u6570 Constructor
\u53D8\u4E3A HashSet<Constructor>
\u529F\u80FD\u63CF\u8FF0
\u5F53\u5728
RemedyPlan
\u4E2D\u627E\u5230\u7ED3\u679C\u65F6\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u65B9\u4FBF\u5730\u5BF9\u91CD\u67E5\u627E\u7684 Constructor
\u5B9E\u73B0 onFind
\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Constructor
\u67E5\u627E\u7ED3\u679C\u5904\u7406\u7C7B\uFF0C\u4E3AhookInstance
\u63D0\u4F9B\u3002
inline fun result(initiate: Process.() -> Unit): Process
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.result {
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
fun all(): Process
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A
Constructor
\u5B9E\u4F8B\u7ED3\u679C\u5230hookInstance
\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA
Constructor
\u91CD\u67E5\u627E\u529F\u80FD\u3002
\u529F\u80FD\u793A\u4F8B
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Constructor
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchConstructor
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Constructor
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u627E\u4E0D\u5230
Constructor
\u65F6\u3002
\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u6B21\u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u4E0D\u4F1A\u8FD4\u56DE RemedyPlan
\u7684\u9519\u8BEF\u4FE1\u606F\u3002
inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u7EE7\u627F\u5230\u63A5\u53E3 BaseResult
\u529F\u80FD\u63CF\u8FF0
Constructor
\u67E5\u627E\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.result {
+ get().call()
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
fun get(): Instance
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
\u82E5\u6709\u591A\u4E2A Constructor
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u8BF7\u4F7F\u7528 wait \u56DE\u8C03\u7ED3\u679C\u65B9\u6CD5\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u901A\u8FC7\u83B7\u5F97\u65B9\u6CD5\u6240\u5728\u5B9E\u4F8B\u6765\u6267\u884C\u6784\u9020\u65B9\u6CD5\u521B\u5EFA\u65B0\u7684\u5B9E\u4F8B\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.get().call()
+
\u4F60\u53EF\u4EE5 cast
\u6784\u9020\u65B9\u6CD5\u4E3A\u6307\u5B9A\u7C7B\u578B\u7684\u5B9E\u4F8B\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>()
+
\u7279\u522B\u6CE8\u610F
\u82E5\u6784\u9020\u65B9\u6CD5\u542B\u6709\u53C2\u6570\u5219\u540E\u65B9\u53C2\u6570\u5FC5\u586B\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>("param1", "param2")
+
fun all(): ArrayList<Instance>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Constructor
\u5B9E\u4F8B\u7ED3\u679C\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u901A\u8FC7\u6B64\u65B9\u6CD5\u6765\u83B7\u5F97\u5F53\u524D\u6761\u4EF6\u7ED3\u679C\u4E2D\u5339\u914D\u7684\u5168\u90E8 Constructor
\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.all().forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Constructor<*>?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Constructor
\u672C\u8EAB\u3002
\u82E5\u6709\u591A\u4E2A Constructor
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE null
\u3002
fun giveAll(): HashSet<Constructor<*>>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Constructor
\u672C\u8EAB\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Constructor
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE\u7A7A\u7684 HashSet
\u3002
fun wait(initiate: Instance.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u82E5\u6709\u591A\u4E2A Constructor
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
fun waitAll(initiate: ArrayList<Instance>.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Constructor
\u5B9E\u4F8B\u7ED3\u679C\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA
Constructor
\u91CD\u67E5\u627E\u529F\u80FD\u3002
\u529F\u80FD\u793A\u4F8B
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Constructor
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchConstructor
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Constructor
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
\u793A\u4F8B\u5982\u4E0B
constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u627E\u4E0D\u5230
Constructor
\u65F6\u3002
\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u6B21\u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u4E0D\u4F1A\u8FD4\u56DE RemedyPlan
\u7684\u9519\u8BEF\u4FE1\u606F\u3002
fun ignored(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565\u5F02\u5E38\u5E76\u505C\u6B62\u6253\u5370\u4EFB\u4F55\u9519\u8BEF\u65E5\u5FD7\u3002
\u82E5 isNotIgnoredHookingFailure
\u4E3A false
\u5219\u81EA\u52A8\u5FFD\u7565\u3002
\u6CE8\u610F
\u6B64\u65F6\u82E5\u8981\u76D1\u542C\u5F02\u5E38\u7ED3\u679C\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u5B9E\u73B0 onNoSuchConstructor \u65B9\u6CD5\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.3
\u65B0\u589E
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()
inner class Instance internal constructor(private val constructor: Constructor<*>?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u65B0\u589E constructor
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
Constructor
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
fun call(vararg param: Any?): Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Constructor
\u521B\u5EFA\u76EE\u6807\u5B9E\u4F8B\uFF0C\u4E0D\u6307\u5B9A\u76EE\u6807\u5B9E\u4F8B\u7C7B\u578B\u3002
fun <T> newInstance(vararg param: Any?): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,287),p=[l];function c(t,r){return n(),o("div",null,p)}const i=s(e,[["render",c],["__file","ConstructorFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/ConstructorFinder.html.7de4f560.js b/docs/assets/ConstructorFinder.html.7de4f560.js new file mode 100644 index 00000000..6d28dc6c --- /dev/null +++ b/docs/assets/ConstructorFinder.html.7de4f560.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-1e2cbc9c","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html","title":"ConstructorFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-2","link":"#paramcount-method-2","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Process - class","slug":"process-class","link":"#process-class","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchConstructor - method","slug":"onnosuchconstructor-method","link":"#onnosuchconstructor-method","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method-1","link":"#result-method-1","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method-1","link":"#all-method-1","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method-1","link":"#remedys-method-1","children":[]},{"level":3,"title":"onNoSuchConstructor - method","slug":"onnosuchconstructor-method-1","link":"#onnosuchconstructor-method-1","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]}]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.md"}');export{e as data}; diff --git a/docs/assets/ConstructorRules.html.d56dfdf4.js b/docs/assets/ConstructorRules.html.d56dfdf4.js new file mode 100644 index 00000000..2a34c793 --- /dev/null +++ b/docs/assets/ConstructorRules.html.d56dfdf4.js @@ -0,0 +1,8 @@ +import{_ as s,o,c as a,a as n}from"./app.fb8271cf.js";const e={},t=n(`\u6267\u884C
Constructor
\u521B\u5EFA\u76EE\u6807\u5B9E\u4F8B \uFF0C\u6307\u5B9AT
\u76EE\u6807\u5B9E\u4F8B\u7C7B\u578B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ConstructorRules internal constructor(internal val rulesData: ConstructorRulesData) : BaseRules
+
Change Records
v1.1.0
added
Function Illustrate
Constructor
\u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
var paramCount: Int
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u53D8\u91CF\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
fun emptyParam()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002
fun param(vararg paramType: Any)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u3002
\u5982\u679C\u540C\u65F6\u4F7F\u7528\u4E86 paramCount
\u5219 paramType
\u7684\u6570\u91CF\u5FC5\u987B\u4E0E paramCount
\u5B8C\u5168\u5339\u914D\u3002
\u5982\u679C Constructor
\u4E2D\u5B58\u5728\u4E00\u4E9B\u65E0\u610F\u4E49\u53C8\u5F88\u957F\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 VagueType
\u6765\u66FF\u4EE3\u5B83\u3002
Pay Attention
\u65E0\u53C2 Constructor \u8BF7\u4F7F\u7528 emptyParam \u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002
\u6709\u53C2 Constructor \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u5B9A\u53C2\u6570\u6216\u4F7F\u7528 paramCount \u6307\u5B9A\u4E2A\u6570\u3002
fun paramCount(numRange: IntRange)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
fun paramCount(conditions: CountConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
class ConstructorRules internal constructor(internal val rulesData: ConstructorRulesData) : BaseRules
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Constructor
\u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
var paramCount: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u53D8\u91CF\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
fun modifiers(conditions: ModifierConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
fun emptyParam()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002
fun param(vararg paramType: Any)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u3002
\u5982\u679C\u540C\u65F6\u4F7F\u7528\u4E86 paramCount
\u5219 paramType
\u7684\u6570\u91CF\u5FC5\u987B\u4E0E paramCount
\u5B8C\u5168\u5339\u914D\u3002
\u5982\u679C Constructor
\u4E2D\u5B58\u5728\u4E00\u4E9B\u65E0\u610F\u4E49\u53C8\u5F88\u957F\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 VagueType
\u6765\u66FF\u4EE3\u5B83\u3002
\u7279\u522B\u6CE8\u610F
\u65E0\u53C2 Constructor \u8BF7\u4F7F\u7528 emptyParam \u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002
\u6709\u53C2 Constructor \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u5B9A\u53C2\u6570\u6216\u4F7F\u7528 paramCount \u6307\u5B9A\u4E2A\u6570\u3002
fun paramCount(numRange: IntRange)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
fun paramCount(conditions: CountConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Constructor
\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
class CountRules private constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u4E00\u4E2A\u6A21\u7CCA
Class
\u3001Member
\u6570\u7EC4 (\u4E0B\u6807) \u4E2A\u6570\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
\u53EF\u5BF9 R8 \u6DF7\u6DC6\u540E\u7684 Class
\u3001Member
\u8FDB\u884C\u66F4\u52A0\u8BE6\u7EC6\u7684\u5B9A\u4F4D\u3002
fun Int.isZero(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u4E3A 0\u3002
fun Int.moreThan(count: Int): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5927\u4E8E
count
\u3002
fun Int.lessThan(count: Int): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5C0F\u4E8E
count
\u3002
fun Int.inInterval(countRange: IntRange): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,31),t=[l];function p(c,r){return o(),n("div",null,t)}const i=s(a,[["render",p],["__file","CountRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/CountRules.html.52ed8a0d.js b/docs/assets/CountRules.html.52ed8a0d.js new file mode 100644 index 00000000..cbb5bdc9 --- /dev/null +++ b/docs/assets/CountRules.html.52ed8a0d.js @@ -0,0 +1,6 @@ +import{_ as s,o as n,c as o,a as e}from"./app.fb8271cf.js";const a={},t=e(`\u5728
countRange
\u533A\u95F4 A \u2264 this \u2264 B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class CountRules private constructor()
+
Change Records
v1.1.0
added
Function Illustrate
\u8FD9\u662F\u4E00\u4E2A\u6A21\u7CCA
Class
\u3001Member
\u6570\u7EC4 (\u4E0B\u6807) \u4E2A\u6570\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
\u53EF\u5BF9 R8 \u6DF7\u6DC6\u540E\u7684 Class
\u3001Member
\u8FDB\u884C\u66F4\u52A0\u8BE6\u7EC6\u7684\u5B9A\u4F4D\u3002
fun Int.isZero(): Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u662F\u5426\u4E3A 0\u3002
fun Int.moreThan(count: Int): Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u5927\u4E8E
count
\u3002
fun Int.lessThan(count: Int): Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u5C0F\u4E8E
count
\u3002
fun Int.inInterval(countRange: IntRange): Boolean
+
Change Records
v1.1.0
added
Function Illustrate
`,32),l=[t];function c(p,r){return n(),o("div",null,l)}const i=s(a,[["render",c],["__file","CountRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/CurrentClass.html.072e89c6.js b/docs/assets/CurrentClass.html.072e89c6.js new file mode 100644 index 00000000..4732e1b6 --- /dev/null +++ b/docs/assets/CurrentClass.html.072e89c6.js @@ -0,0 +1,16 @@ +import{_ as s,o as a,c as e,a as n}from"./app.fb8271cf.js";const o={},l=n(`\u5728
countRange
\u533A\u95F4 A \u2264 this \u2264 B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class CurrentClass internal constructor(internal val classSet: Class<*>, internal val instance: Any)
+
Change Records
v1.0.70
added
v1.1.0
modified
\u8C03\u6574\u4E86\u6784\u9020\u65B9\u6CD5\u7684\u53C2\u6570\u540D\u79F0
Function Illustrate
\u5F53\u524D\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61\u3002
val name: String
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D
classSet
\u7684Class.getName
\u3002
val simpleName: String
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D
classSet
\u7684Class.getSimpleName
\u3002
fun generic(): GenericClass?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u4E2D\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u4E2D\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
fun superClass(): SuperClass
+
Change Records
v1.0.80
added
Function Illustrate
\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u3002
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
Change Records
v1.0.70
added
Function Illustrate
\u8C03\u7528\u5F53\u524D\u5B9E\u4F8B\u4E2D\u7684\u53D8\u91CF\u3002
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
Change Records
v1.0.70
added
Function Illustrate
\u8C03\u7528\u5F53\u524D\u5B9E\u4F8B\u4E2D\u7684\u65B9\u6CD5\u3002
inner class SuperClass internal constructor(internal val superClassSet: Class<*>)
+
Change Records
v1.0.80
added
v1.1.0
modified
\u65B0\u589E superClassSet
\u53C2\u6570
Function Illustrate
\u5F53\u524D\u7C7B\u7684\u7236\u7C7B\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61\u3002
val name: String
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D
classSet
\u4E2D\u7236\u7C7B\u7684Class.getName
\u3002
val simpleName: String
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D
classSet
\u4E2D\u7236\u7C7B\u7684Class.getSimpleName
\u3002
fun generic(): GenericClass?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u7236\u7C7B\u4E2D\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u7236\u7C7B\u4E2D\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
Change Records
v1.0.80
added
Function Illustrate
\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u4E2D\u7684\u53D8\u91CF\u3002
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
Change Records
v1.0.80
added
Function Illustrate
`,99),p=[l];function c(t,r){return a(),e("div",null,p)}const i=s(o,[["render",c],["__file","CurrentClass.html.vue"]]);export{i as default}; diff --git a/docs/assets/CurrentClass.html.16c29272.js b/docs/assets/CurrentClass.html.16c29272.js new file mode 100644 index 00000000..112eac14 --- /dev/null +++ b/docs/assets/CurrentClass.html.16c29272.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-b6a815c4","path":"/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html","title":"CurrentClass - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"simpleName - field","slug":"simplename-field","link":"#simplename-field","children":[]},{"level":2,"title":"generic - method","slug":"generic-method","link":"#generic-method","children":[]},{"level":2,"title":"generic - method","slug":"generic-method-1","link":"#generic-method-1","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":2,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":2,"title":"SuperClass - class","slug":"superclass-class","link":"#superclass-class","children":[{"level":3,"title":"name - field","slug":"name-field-1","link":"#name-field-1","children":[]},{"level":3,"title":"simpleName - field","slug":"simplename-field-1","link":"#simplename-field-1","children":[]},{"level":3,"title":"generic - method","slug":"generic-method-2","link":"#generic-method-2","children":[]},{"level":3,"title":"generic - method","slug":"generic-method-3","link":"#generic-method-3","children":[]},{"level":3,"title":"field - method","slug":"field-method-1","link":"#field-method-1","children":[]},{"level":3,"title":"method - method","slug":"method-method-1","link":"#method-method-1","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.md"}');export{e as data}; diff --git a/docs/assets/CurrentClass.html.2e606398.js b/docs/assets/CurrentClass.html.2e606398.js new file mode 100644 index 00000000..f6b8435e --- /dev/null +++ b/docs/assets/CurrentClass.html.2e606398.js @@ -0,0 +1,16 @@ +import{_ as s,o as a,c as n,a as o}from"./app.fb8271cf.js";const e={},l=o(`\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u4E2D\u7684\u65B9\u6CD5\u3002
class CurrentClass internal constructor(internal val classSet: Class<*>, internal val instance: Any)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u8C03\u6574\u4E86\u6784\u9020\u65B9\u6CD5\u7684\u53C2\u6570\u540D\u79F0
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61\u3002
val name: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D
classSet
\u7684Class.getName
\u3002
val simpleName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D
classSet
\u7684Class.getSimpleName
\u3002
fun generic(): GenericClass?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u4E2D\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u4E2D\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
fun superClass(): SuperClass
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u3002
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8C03\u7528\u5F53\u524D\u5B9E\u4F8B\u4E2D\u7684\u53D8\u91CF\u3002
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8C03\u7528\u5F53\u524D\u5B9E\u4F8B\u4E2D\u7684\u65B9\u6CD5\u3002
inner class SuperClass internal constructor(internal val superClassSet: Class<*>)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u65B0\u589E superClassSet
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D\u7C7B\u7684\u7236\u7C7B\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61\u3002
val name: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D
classSet
\u4E2D\u7236\u7C7B\u7684Class.getName
\u3002
val simpleName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D
classSet
\u4E2D\u7236\u7C7B\u7684Class.getSimpleName
\u3002
fun generic(): GenericClass?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u7236\u7C7B\u4E2D\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u7236\u7C7B\u4E2D\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u4E2D\u7684\u53D8\u91CF\u3002
inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,98),p=[l];function c(t,r){return a(),n("div",null,p)}const i=s(e,[["render",c],["__file","CurrentClass.html.vue"]]);export{i as default}; diff --git a/docs/assets/CurrentClass.html.641fcd58.js b/docs/assets/CurrentClass.html.641fcd58.js new file mode 100644 index 00000000..5ddbd91d --- /dev/null +++ b/docs/assets/CurrentClass.html.641fcd58.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-6e47300f","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html","title":"CurrentClass - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"simpleName - field","slug":"simplename-field","link":"#simplename-field","children":[]},{"level":2,"title":"generic - method","slug":"generic-method","link":"#generic-method","children":[]},{"level":2,"title":"generic - method","slug":"generic-method-1","link":"#generic-method-1","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":2,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":2,"title":"SuperClass - class","slug":"superclass-class","link":"#superclass-class","children":[{"level":3,"title":"name - field","slug":"name-field-1","link":"#name-field-1","children":[]},{"level":3,"title":"simpleName - field","slug":"simplename-field-1","link":"#simplename-field-1","children":[]},{"level":3,"title":"generic - method","slug":"generic-method-2","link":"#generic-method-2","children":[]},{"level":3,"title":"generic - method","slug":"generic-method-3","link":"#generic-method-3","children":[]},{"level":3,"title":"field - method","slug":"field-method-1","link":"#field-method-1","children":[]},{"level":3,"title":"method - method","slug":"method-method-1","link":"#method-method-1","children":[]}]}],"git":{"updatedTime":1663646280000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.md"}');export{e as data}; diff --git a/docs/assets/DefinedTypeFactory.html.1a27d470.js b/docs/assets/DefinedTypeFactory.html.1a27d470.js new file mode 100644 index 00000000..39a5f5ff --- /dev/null +++ b/docs/assets/DefinedTypeFactory.html.1a27d470.js @@ -0,0 +1,2 @@ +import{_ as e,o as s,c as a,a as o}from"./app.fb8271cf.js";const t={},n=o(`\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u4E2D\u7684\u65B9\u6CD5\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u4E00\u4E2A\u5185\u90E8\u7C7B\u578B\u7684\u5B9A\u4E49\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u7528\u4E8E\u53CD\u5C04 API \u76F8\u5173\u7528\u6CD5\u7684\u5EF6\u4F38\u3002
val VagueType: Class<*>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,11),c=[n];function p(l,r){return s(),a("div",null,c)}const i=e(t,[["render",p],["__file","DefinedTypeFactory.html.vue"]]);export{i as default}; diff --git a/docs/assets/DefinedTypeFactory.html.8137c32c.js b/docs/assets/DefinedTypeFactory.html.8137c32c.js new file mode 100644 index 00000000..2b751bdf --- /dev/null +++ b/docs/assets/DefinedTypeFactory.html.8137c32c.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-a2615d0c","path":"/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html","title":"DefinedTypeFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"VagueType - field","slug":"vaguetype-field","link":"#vaguetype-field","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.md"}');export{e as data}; diff --git a/docs/assets/DefinedTypeFactory.html.ba3bdd0b.js b/docs/assets/DefinedTypeFactory.html.ba3bdd0b.js new file mode 100644 index 00000000..335162e7 --- /dev/null +++ b/docs/assets/DefinedTypeFactory.html.ba3bdd0b.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5acc12ab","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html","title":"DefinedTypeFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"VagueType - field","slug":"vaguetype-field","link":"#vaguetype-field","children":[]}],"git":{"updatedTime":1663475472000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.md"}');export{e as data}; diff --git a/docs/assets/DefinedTypeFactory.html.bca7fe3f.js b/docs/assets/DefinedTypeFactory.html.bca7fe3f.js new file mode 100644 index 00000000..0e7af4e5 --- /dev/null +++ b/docs/assets/DefinedTypeFactory.html.bca7fe3f.js @@ -0,0 +1,2 @@ +import{_ as e,o as s,c as o,a}from"./app.fb8271cf.js";const t={},n=a(`\u5F97\u5230\u6A21\u7CCA\u7C7B\u578B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.1.0
added
Function Illustrate
\u8FD9\u662F\u4E00\u4E2A\u5185\u90E8\u7C7B\u578B\u7684\u5B9A\u4E49\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u7528\u4E8E\u53CD\u5C04 API \u76F8\u5173\u7528\u6CD5\u7684\u5EF6\u4F38\u3002
val VagueType: Class<*>
+
Change Records
v1.1.0
added
Function Illustrate
`,12),c=[n];function r(l,p){return s(),o("div",null,c)}const i=e(t,[["render",r],["__file","DefinedTypeFactory.html.vue"]]);export{i as default}; diff --git a/docs/assets/DexClassFinder.html.5d8e12f0.js b/docs/assets/DexClassFinder.html.5d8e12f0.js new file mode 100644 index 00000000..87366d74 --- /dev/null +++ b/docs/assets/DexClassFinder.html.5d8e12f0.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2a898c66","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html","title":"DexClassFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"companion object - object","slug":"companion-object-object","link":"#companion-object-object","children":[{"level":3,"title":"clearCache - method","slug":"clearcache-method","link":"#clearcache-method","children":[]}]},{"level":2,"title":"fullName - field","slug":"fullname-field","link":"#fullname-field","children":[]},{"level":2,"title":"simpleName - field","slug":"simplename-field","link":"#simplename-field","children":[]},{"level":2,"title":"singleName - field","slug":"singlename-field","link":"#singlename-field","children":[]},{"level":2,"title":"from - method","slug":"from-method","link":"#from-method","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"fullName - method","slug":"fullname-method","link":"#fullname-method","children":[]},{"level":2,"title":"simpleName - method","slug":"simplename-method","link":"#simplename-method","children":[]},{"level":2,"title":"singleName - method","slug":"singlename-method","link":"#singlename-method","children":[]},{"level":2,"title":"fullName - method","slug":"fullname-method-1","link":"#fullname-method-1","children":[]},{"level":2,"title":"simpleName - method","slug":"simplename-method-1","link":"#simplename-method-1","children":[]},{"level":2,"title":"singleName - method","slug":"singlename-method-1","link":"#singlename-method-1","children":[]},{"level":2,"title":"extends - method","slug":"extends-method","link":"#extends-method","children":[]},{"level":2,"title":"extends - method","slug":"extends-method-1","link":"#extends-method-1","children":[]},{"level":2,"title":"implements - method","slug":"implements-method","link":"#implements-method","children":[]},{"level":2,"title":"implements - method","slug":"implements-method-1","link":"#implements-method-1","children":[]},{"level":2,"title":"anonymous - method","slug":"anonymous-method","link":"#anonymous-method","children":[]},{"level":2,"title":"noExtends - method","slug":"noextends-method","link":"#noextends-method","children":[]},{"level":2,"title":"noImplements - method","slug":"noimplements-method","link":"#noimplements-method","children":[]},{"level":2,"title":"noSuper - method","slug":"nosuper-method","link":"#nosuper-method","children":[]},{"level":2,"title":"enclosing - method","slug":"enclosing-method","link":"#enclosing-method","children":[]},{"level":2,"title":"enclosing - method","slug":"enclosing-method-1","link":"#enclosing-method-1","children":[]},{"level":2,"title":"FromPackageRules - class","slug":"frompackagerules-class","link":"#frompackagerules-class","children":[{"level":3,"title":"absolute - method","slug":"absolute-method","link":"#absolute-method","children":[]}]},{"level":2,"title":"ClassNameRules - class","slug":"classnamerules-class","link":"#classnamerules-class","children":[{"level":3,"title":"optional - method","slug":"optional-method","link":"#optional-method","children":[]}]},{"level":2,"title":"member - method","slug":"member-method","link":"#member-method","children":[]},{"level":2,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":2,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":2,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":2,"title":"Result - class","slug":"result-class","link":"#result-class","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"all - method","slug":"all-method-1","link":"#all-method-1","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"onNoClassDefFoundError - method","slug":"onnoclassdeffounderror-method","link":"#onnoclassdeffounderror-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.md"}');export{e as data}; diff --git a/docs/assets/DexClassFinder.html.5e274913.js b/docs/assets/DexClassFinder.html.5e274913.js new file mode 100644 index 00000000..ee758bb4 --- /dev/null +++ b/docs/assets/DexClassFinder.html.5e274913.js @@ -0,0 +1,45 @@ +import{_ as s,o,c as e,a}from"./app.fb8271cf.js";const n={},l=a(`\u5F97\u5230\u6A21\u7CCA\u7C7B\u578B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class DexClassFinder internal constructor(
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+
Change Records
v1.1.0
added
Function Illustrate
Class
\u67E5\u627E\u7C7B\u3002
\u53EF\u4F7F\u7528 BaseDexClassLoader
\u901A\u8FC7\u6307\u5B9A\u6761\u4EF6\u67E5\u627E\u6307\u5B9A Class
\u6216\u4E00\u7EC4 Class
\u3002
Notice
\u6B64\u529F\u80FD\u5C1A\u5728\u8BD5\u9A8C\u9636\u6BB5\uFF0C\u6027\u80FD\u4E0E\u7A33\u5B9A\u6027\u53EF\u80FD\u4ECD\u7136\u5B58\u5728\u95EE\u9898\uFF0C\u4F7F\u7528\u8FC7\u7A0B\u9047\u5230\u95EE\u9898\u8BF7\u5411\u6211\u4EEC\u62A5\u544A\u5E76\u5E2E\u52A9\u6211\u4EEC\u6539\u8FDB\u3002
Change Records
v1.1.0
added
fun clearCache(context: Context?, versionName: String?, versionCode: Long?)
+
Change Records
v1.1.0
added
Function Illustrate
\u6E05\u9664\u5F53\u524D
DexClassFinder
\u7684Class
\u7F13\u5B58\u3002
\u9002\u7528\u4E8E\u5168\u90E8\u901A\u8FC7 ClassLoader.searchClass \u6216 PackageParam.searchClass \u83B7\u53D6\u7684 DexClassFinder
\u3002
var fullName: String
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u5B8C\u6574\u540D\u79F0\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getName
\u3002
\u4F8B\u5982 com.demo.Test
\u9700\u8981\u586B\u5199 com.demo.Test
\u3002
var simpleName: String
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u7B80\u5355\u540D\u79F0\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getSimpleName
\u3002
\u4F8B\u5982 com.demo.Test
\u53EA\u9700\u8981\u586B\u5199 Test
\u3002
\u5BF9\u4E8E\u533F\u540D\u7C7B\u4F8B\u5982 com.demo.Test$InnerTest
\u4F1A\u4E3A\u7A7A\uFF0C\u6B64\u65F6\u4F60\u53EF\u4EE5\u4F7F\u7528 singleName\u3002
var singleName: String
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u72EC\u7ACB\u540D\u79F0\u3002
\u8BBE\u7F6E\u540E\u5C06\u9996\u5148\u4F7F\u7528 Class.getSimpleName
\uFF0C\u82E5\u4E3A\u7A7A\u5219\u4F1A\u4F7F\u7528 Class.getName
\u8FDB\u884C\u5904\u7406\u3002
\u4F8B\u5982 com.demo.Test
\u53EA\u9700\u8981\u586B\u5199 Test
\u3002
\u5BF9\u4E8E\u533F\u540D\u7C7B\u4F8B\u5982 com.demo.Test$InnerTest
\u53EA\u9700\u8981\u586B\u5199 Test$InnerTest
\u3002
fun from(vararg name: String): FromPackageRules
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u5728\u6307\u5B9A\u5305\u540D\u8303\u56F4\u67E5\u627E\u5F53\u524D
Class
\u3002
\u8BBE\u7F6E\u540E\u4EC5\u4F1A\u5728\u5F53\u524D name
\u5F00\u5934\u5339\u914D\u7684\u5305\u540D\u8DEF\u5F84\u4E0B\u8FDB\u884C\u67E5\u627E\uFF0C\u53EF\u63D0\u5347\u67E5\u627E\u901F\u5EA6\u3002
\u4F8B\u5982 \u2193
com.demo.test
com.demo.test.demo
Notice
\u5EFA\u8BAE\u8BBE\u7F6E\u6B64\u53C2\u6570\u6307\u5B9A\u67E5\u627E\u8303\u56F4\uFF0C\u5426\u5219 Class \u8FC7\u591A\u65F6\u5C06\u4F1A\u975E\u5E38\u6162\u3002
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
fun fullName(value: String): ClassNameRules
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u5B8C\u6574\u540D\u79F0\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getName
\u3002
\u4F8B\u5982 com.demo.Test
\u9700\u8981\u586B\u5199 com.demo.Test
\u3002
fun simpleName(value: String): ClassNameRules
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u7B80\u5355\u540D\u79F0\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getSimpleName
\u3002
\u4F8B\u5982 com.demo.Test
\u53EA\u9700\u8981\u586B\u5199 Test
\u3002
\u5BF9\u4E8E\u533F\u540D\u7C7B\u4F8B\u5982 com.demo.Test$InnerTest \u4F1A\u4E3A\u7A7A
\uFF0C\u6B64\u65F6\u4F60\u53EF\u4EE5\u4F7F\u7528 singleName\u3002
fun singleName(value: String): ClassNameRules
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u72EC\u7ACB\u540D\u79F0\u3002
\u8BBE\u7F6E\u540E\u5C06\u9996\u5148\u4F7F\u7528 Class.getSimpleName
\uFF0C\u82E5\u4E3A\u7A7A\u5219\u4F1A\u4F7F\u7528 Class.getName
\u8FDB\u884C\u5904\u7406\u3002
\u4F8B\u5982 com.demo.Test
\u53EA\u9700\u8981\u586B\u5199 Test
\u3002
\u5BF9\u4E8E\u533F\u540D\u7C7B\u4F8B\u5982 com.demo.Test$InnerTest
\u53EA\u9700\u8981\u586B\u5199 Test$InnerTest
\u3002
fun fullName(conditions: NameConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u5B8C\u6574\u540D\u79F0\u6761\u4EF6\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getName
\u3002
fun simpleName(conditions: NameConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u7B80\u5355\u540D\u79F0\u6761\u4EF6\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getSimpleName
\u3002
fun singleName(conditions: NameConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u72EC\u7ACB\u540D\u79F0\u6761\u4EF6\u3002
\u8BBE\u7F6E\u540E\u5C06\u9996\u5148\u4F7F\u7528 Class.getSimpleName
\uFF0C\u82E5\u4E3A\u7A7A\u5219\u4F1A\u4F7F\u7528 Class.getName
\u8FDB\u884C\u5904\u7406\u3002
inline fun <reified T> extends()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u7EE7\u627F\u7684\u7236\u7C7B\u3002
fun extends(vararg name: String)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u7EE7\u627F\u7684\u7236\u7C7B\u3002
\u4F1A\u540C\u65F6\u67E5\u627E name
\u4E2D\u6240\u6709\u5339\u914D\u7684\u7236\u7C7B\u3002
inline fun <reified T> implements()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u5B9E\u73B0\u7684\u63A5\u53E3\u7C7B\u3002
fun implements(vararg name: String)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u5B9E\u73B0\u7684\u63A5\u53E3\u7C7B\u3002
\u4F1A\u540C\u65F6\u67E5\u627E name
\u4E2D\u6240\u6709\u5339\u914D\u7684\u63A5\u53E3\u7C7B\u3002
fun anonymous()
+
Change Records
v1.1.0
added
Function Illustrate
\u6807\u8BC6
Class
\u4E3A\u533F\u540D\u7C7B\u3002
\u4F8B\u5982 com.demo.Test$1
\u6216 com.demo.Test$InnerTest
\u3002
\u6807\u8BC6\u540E\u4F60\u53EF\u4EE5\u4F7F\u7528 enclosing \u6765\u8FDB\u4E00\u6B65\u6307\u5B9A\u533F\u540D\u7C7B\u7684 (\u5C01\u95ED\u7C7B) \u4E3B\u7C7B\u3002
fun noExtends()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u6CA1\u6709\u4EFB\u4F55\u7EE7\u627F\u3002
\u6B64\u65F6 Class
\u53EA\u5E94\u8BE5\u7EE7\u627F\u4E8E Any
\u3002
Notice
\u8BBE\u7F6E\u6B64\u6761\u4EF6\u540E extends \u5C06\u5931\u6548\u3002
fun noImplements()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u6CA1\u6709\u4EFB\u4F55\u63A5\u53E3\u3002
Notice
\u8BBE\u7F6E\u6B64\u6761\u4EF6\u540E implements \u5C06\u5931\u6548\u3002
fun noSuper()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u6CA1\u6709\u4EFB\u4F55\u7EE7\u627F\u4E0E\u63A5\u53E3\u3002
\u6B64\u65F6 Class
\u53EA\u5E94\u8BE5\u7EE7\u627F\u4E8E Any
\u3002
Notice
\u8BBE\u7F6E\u6B64\u6761\u4EF6\u540E extends \u4E0E implements \u5C06\u5931\u6548\u3002
inline fun <reified T> enclosing()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u533F\u540D\u7C7B\u7684 (\u5C01\u95ED\u7C7B) \u4E3B\u7C7B\u3002
fun enclosing(vararg name: String)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u533F\u540D\u7C7B\u7684 (\u5C01\u95ED\u7C7B) \u4E3B\u7C7B\u3002
\u4F1A\u540C\u65F6\u67E5\u627E name
\u4E2D\u6240\u6709\u5339\u914D\u7684 (\u5C01\u95ED\u7C7B) \u4E3B\u7C7B\u3002
inner class FromPackageRules internal constructor(private val packages: ArrayList<ClassRulesData.PackageRulesData>)
+
Change Records
v1.1.0
added
Function Illustrate
\u5305\u540D\u8303\u56F4\u540D\u79F0\u8FC7\u6EE4\u5339\u914D\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
fun absolute()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u5305\u540D\u7EDD\u5BF9\u5339\u914D\u3002
\u4F8B\u5982\u6709\u5982\u4E0B\u5305\u540D \u2193
com.demo.test.a
com.demo.test.a.b
com.demo.test.active
\u82E5\u5305\u540D\u6761\u4EF6\u4E3A com.demo.test.a
\u5219\u7EDD\u5BF9\u5339\u914D\u4EC5\u80FD\u5339\u914D\u5230\u7B2C\u4E00\u4E2A\u3002
\u76F8\u53CD\u5730\uFF0C\u4E0D\u8BBE\u7F6E\u4EE5\u4E0A\u793A\u4F8B\u4F1A\u5168\u90E8\u5339\u914D\u3002
inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+
Change Records
v1.1.0
added
Function Illustrate
\u7C7B\u540D\u5339\u914D\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
fun optional()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u7C7B\u540D\u53EF\u9009\u3002
\u4F8B\u5982\u6709\u5982\u4E0B\u7C7B\u540D \u2193
com.demo.Test
fullName / Test
simpleName
defpackage.a
fullName / a
simpleName
\u8FD9\u4E24\u4E2A\u7C7B\u540D\u90FD\u662F\u540C\u4E00\u4E2A\u7C7B\uFF0C\u4F46\u662F\u5728\u6709\u4E9B\u7248\u672C\u4E2D\u88AB\u6DF7\u6DC6\u6709\u4E9B\u7248\u672C\u6CA1\u6709\u3002
\u6B64\u65F6\u53EF\u8BBE\u7F6E\u7C7B\u540D\u4E3A com.demo.Test
fullName / Test
simpleName\u3002
\u8FD9\u6837\u5C31\u53EF\u5728\u5B8C\u5168\u5339\u914D\u7C7B\u540D\u60C5\u51B5\u4E0B\u4F7F\u7528\u7C7B\u540D\u800C\u5FFD\u7565\u5176\u5B83\u67E5\u627E\u6761\u4EF6\uFF0C\u5426\u5219\u5FFD\u7565\u6B64\u6761\u4EF6\u7EE7\u7EED\u4F7F\u7528\u5176\u5B83\u67E5\u627E\u6761\u4EF6\u3002
inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u6EE1\u8DB3\u7684Member
\u6761\u4EF6\u3002
inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u6EE1\u8DB3\u7684Field
\u6761\u4EF6\u3002
inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u6EE1\u8DB3\u7684Method
\u6761\u4EF6\u3002
inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Class
\u6EE1\u8DB3\u7684Constructor
\u6761\u4EF6\u3002
inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+
Change Records
v1.1.0
added
Function Illustrate
Class
\u67E5\u627E\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
fun get(): Class<*>?
+
Change Records
v1.1.0
added
Function Illustrate
\u5F97\u5230
Class
\u672C\u8EAB\u3002
\u82E5\u6709\u591A\u4E2A Class
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE null
\u3002
\u82E5\u4F60\u8BBE\u7F6E\u4E86 async
\u8BF7\u4F7F\u7528 wait \u65B9\u6CD5\u3002
fun all(): HashSet<Class<*>>
+
Change Records
v1.1.0
added
Function Illustrate
\u5F97\u5230
Class
\u672C\u8EAB\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Class
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE\u7A7A\u7684 HashSet
\u3002
\u82E5\u4F60\u8BBE\u7F6E\u4E86 async
\u8BF7\u4F7F\u7528 waitAll \u65B9\u6CD5\u3002
fun all(result: (Class<*>) -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u5F97\u5230
Class
\u672C\u8EAB\u6570\u7EC4 (\u4F9D\u6B21\u904D\u5386)\u3002
\u56DE\u8C03\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Class
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u4E0D\u4F1A\u6267\u884C\u3002
\u82E5\u4F60\u8BBE\u7F6E\u4E86 async
\u8BF7\u4F7F\u7528 waitAll \u65B9\u6CD5\u3002
fun wait(result: (Class<*>?) -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u5F97\u5230
Class
\u672C\u8EAB (\u5F02\u6B65)\u3002
\u82E5\u6709\u591A\u4E2A Class
\u7ED3\u679C\u53EA\u4F1A\u56DE\u8C03\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u56DE\u8C03 null\u3002
\u4F60\u9700\u8981\u8BBE\u7F6E async
\u540E\u6B64\u65B9\u6CD5\u624D\u4F1A\u88AB\u56DE\u8C03\uFF0C\u5426\u5219\u8BF7\u4F7F\u7528 get \u65B9\u6CD5\u3002
fun waitAll(result: (HashSet<Class<*>>) -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u5F97\u5230
Class
\u672C\u8EAB\u6570\u7EC4 (\u5F02\u6B65)\u3002
\u56DE\u8C03\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Class
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u56DE\u8C03\u7A7A\u7684 HashSet
\u3002
\u4F60\u9700\u8981\u8BBE\u7F6E async
\u540E\u6B64\u65B9\u6CD5\u624D\u4F1A\u88AB\u56DE\u8C03\uFF0C\u5426\u5219\u8BF7\u4F7F\u7528 all \u65B9\u6CD5\u3002
fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u76D1\u542C\u627E\u4E0D\u5230
Class
\u65F6\u3002
fun ignored(): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u5FFD\u7565\u5F02\u5E38\u5E76\u505C\u6B62\u6253\u5370\u4EFB\u4F55\u9519\u8BEF\u65E5\u5FD7\u3002
\u6B64\u65F6\u82E5\u8981\u76D1\u542C\u5F02\u5E38\u7ED3\u679C\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u5B9E\u73B0 onNoClassDefFoundError \u65B9\u6CD5\u3002
`,310),p=[l];function c(t,r){return o(),e("div",null,p)}const i=s(n,[["render",c],["__file","DexClassFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/DexClassFinder.html.78c5f805.js b/docs/assets/DexClassFinder.html.78c5f805.js new file mode 100644 index 00000000..eae2076a --- /dev/null +++ b/docs/assets/DexClassFinder.html.78c5f805.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-45111efc","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html","title":"DexClassFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"companion object - object","slug":"companion-object-object","link":"#companion-object-object","children":[{"level":3,"title":"clearCache - method","slug":"clearcache-method","link":"#clearcache-method","children":[]}]},{"level":2,"title":"fullName - field","slug":"fullname-field","link":"#fullname-field","children":[]},{"level":2,"title":"simpleName - field","slug":"simplename-field","link":"#simplename-field","children":[]},{"level":2,"title":"singleName - field","slug":"singlename-field","link":"#singlename-field","children":[]},{"level":2,"title":"from - method","slug":"from-method","link":"#from-method","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"fullName - method","slug":"fullname-method","link":"#fullname-method","children":[]},{"level":2,"title":"simpleName - method","slug":"simplename-method","link":"#simplename-method","children":[]},{"level":2,"title":"singleName - method","slug":"singlename-method","link":"#singlename-method","children":[]},{"level":2,"title":"fullName - method","slug":"fullname-method-1","link":"#fullname-method-1","children":[]},{"level":2,"title":"simpleName - method","slug":"simplename-method-1","link":"#simplename-method-1","children":[]},{"level":2,"title":"singleName - method","slug":"singlename-method-1","link":"#singlename-method-1","children":[]},{"level":2,"title":"extends - method","slug":"extends-method","link":"#extends-method","children":[]},{"level":2,"title":"extends - method","slug":"extends-method-1","link":"#extends-method-1","children":[]},{"level":2,"title":"implements - method","slug":"implements-method","link":"#implements-method","children":[]},{"level":2,"title":"implements - method","slug":"implements-method-1","link":"#implements-method-1","children":[]},{"level":2,"title":"anonymous - method","slug":"anonymous-method","link":"#anonymous-method","children":[]},{"level":2,"title":"noExtends - method","slug":"noextends-method","link":"#noextends-method","children":[]},{"level":2,"title":"noImplements - method","slug":"noimplements-method","link":"#noimplements-method","children":[]},{"level":2,"title":"noSuper - method","slug":"nosuper-method","link":"#nosuper-method","children":[]},{"level":2,"title":"enclosing - method","slug":"enclosing-method","link":"#enclosing-method","children":[]},{"level":2,"title":"enclosing - method","slug":"enclosing-method-1","link":"#enclosing-method-1","children":[]},{"level":2,"title":"FromPackageRules - class","slug":"frompackagerules-class","link":"#frompackagerules-class","children":[{"level":3,"title":"absolute - method","slug":"absolute-method","link":"#absolute-method","children":[]}]},{"level":2,"title":"ClassNameRules - class","slug":"classnamerules-class","link":"#classnamerules-class","children":[{"level":3,"title":"optional - method","slug":"optional-method","link":"#optional-method","children":[]}]},{"level":2,"title":"member - method","slug":"member-method","link":"#member-method","children":[]},{"level":2,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":2,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":2,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":2,"title":"Result - class","slug":"result-class","link":"#result-class","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"all - method","slug":"all-method-1","link":"#all-method-1","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"onNoClassDefFoundError - method","slug":"onnoclassdeffounderror-method","link":"#onnoclassdeffounderror-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]}]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.md"}');export{e as data}; diff --git a/docs/assets/DexClassFinder.html.92677d64.js b/docs/assets/DexClassFinder.html.92677d64.js new file mode 100644 index 00000000..78a19b2a --- /dev/null +++ b/docs/assets/DexClassFinder.html.92677d64.js @@ -0,0 +1,45 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},l=e(`class DexClassFinder internal constructor(
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Class
\u67E5\u627E\u7C7B\u3002
\u53EF\u4F7F\u7528 BaseDexClassLoader
\u901A\u8FC7\u6307\u5B9A\u6761\u4EF6\u67E5\u627E\u6307\u5B9A Class
\u6216\u4E00\u7EC4 Class
\u3002
\u6CE8\u610F
\u6B64\u529F\u80FD\u5C1A\u5728\u8BD5\u9A8C\u9636\u6BB5\uFF0C\u6027\u80FD\u4E0E\u7A33\u5B9A\u6027\u53EF\u80FD\u4ECD\u7136\u5B58\u5728\u95EE\u9898\uFF0C\u4F7F\u7528\u8FC7\u7A0B\u9047\u5230\u95EE\u9898\u8BF7\u5411\u6211\u4EEC\u62A5\u544A\u5E76\u5E2E\u52A9\u6211\u4EEC\u6539\u8FDB\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
fun clearCache(context: Context?, versionName: String?, versionCode: Long?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6E05\u9664\u5F53\u524D
DexClassFinder
\u7684Class
\u7F13\u5B58\u3002
\u9002\u7528\u4E8E\u5168\u90E8\u901A\u8FC7 ClassLoader.searchClass \u6216 PackageParam.searchClass \u83B7\u53D6\u7684 DexClassFinder
\u3002
var fullName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u5B8C\u6574\u540D\u79F0\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getName
\u3002
\u4F8B\u5982 com.demo.Test
\u9700\u8981\u586B\u5199 com.demo.Test
\u3002
var simpleName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u7B80\u5355\u540D\u79F0\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getSimpleName
\u3002
\u4F8B\u5982 com.demo.Test
\u53EA\u9700\u8981\u586B\u5199 Test
\u3002
\u5BF9\u4E8E\u533F\u540D\u7C7B\u4F8B\u5982 com.demo.Test$InnerTest
\u4F1A\u4E3A\u7A7A\uFF0C\u6B64\u65F6\u4F60\u53EF\u4EE5\u4F7F\u7528 singleName\u3002
var singleName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u72EC\u7ACB\u540D\u79F0\u3002
\u8BBE\u7F6E\u540E\u5C06\u9996\u5148\u4F7F\u7528 Class.getSimpleName
\uFF0C\u82E5\u4E3A\u7A7A\u5219\u4F1A\u4F7F\u7528 Class.getName
\u8FDB\u884C\u5904\u7406\u3002
\u4F8B\u5982 com.demo.Test
\u53EA\u9700\u8981\u586B\u5199 Test
\u3002
\u5BF9\u4E8E\u533F\u540D\u7C7B\u4F8B\u5982 com.demo.Test$InnerTest
\u53EA\u9700\u8981\u586B\u5199 Test$InnerTest
\u3002
fun from(vararg name: String): FromPackageRules
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5728\u6307\u5B9A\u5305\u540D\u8303\u56F4\u67E5\u627E\u5F53\u524D
Class
\u3002
\u8BBE\u7F6E\u540E\u4EC5\u4F1A\u5728\u5F53\u524D name
\u5F00\u5934\u5339\u914D\u7684\u5305\u540D\u8DEF\u5F84\u4E0B\u8FDB\u884C\u67E5\u627E\uFF0C\u53EF\u63D0\u5347\u67E5\u627E\u901F\u5EA6\u3002
\u4F8B\u5982 \u2193
com.demo.test
com.demo.test.demo
\u6CE8\u610F
\u5EFA\u8BAE\u8BBE\u7F6E\u6B64\u53C2\u6570\u6307\u5B9A\u67E5\u627E\u8303\u56F4\uFF0C\u5426\u5219 Class \u8FC7\u591A\u65F6\u5C06\u4F1A\u975E\u5E38\u6162\u3002
fun modifiers(conditions: ModifierConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
fun fullName(value: String): ClassNameRules
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u5B8C\u6574\u540D\u79F0\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getName
\u3002
\u4F8B\u5982 com.demo.Test
\u9700\u8981\u586B\u5199 com.demo.Test
\u3002
fun simpleName(value: String): ClassNameRules
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u7B80\u5355\u540D\u79F0\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getSimpleName
\u3002
\u4F8B\u5982 com.demo.Test
\u53EA\u9700\u8981\u586B\u5199 Test
\u3002
\u5BF9\u4E8E\u533F\u540D\u7C7B\u4F8B\u5982 com.demo.Test$InnerTest \u4F1A\u4E3A\u7A7A
\uFF0C\u6B64\u65F6\u4F60\u53EF\u4EE5\u4F7F\u7528 singleName\u3002
fun singleName(value: String): ClassNameRules
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u72EC\u7ACB\u540D\u79F0\u3002
\u8BBE\u7F6E\u540E\u5C06\u9996\u5148\u4F7F\u7528 Class.getSimpleName
\uFF0C\u82E5\u4E3A\u7A7A\u5219\u4F1A\u4F7F\u7528 Class.getName
\u8FDB\u884C\u5904\u7406\u3002
\u4F8B\u5982 com.demo.Test
\u53EA\u9700\u8981\u586B\u5199 Test
\u3002
\u5BF9\u4E8E\u533F\u540D\u7C7B\u4F8B\u5982 com.demo.Test$InnerTest
\u53EA\u9700\u8981\u586B\u5199 Test$InnerTest
\u3002
fun fullName(conditions: NameConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u5B8C\u6574\u540D\u79F0\u6761\u4EF6\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getName
\u3002
fun simpleName(conditions: NameConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u7B80\u5355\u540D\u79F0\u6761\u4EF6\u3002
\u53EA\u4F1A\u67E5\u627E\u5339\u914D\u5230\u7684 Class.getSimpleName
\u3002
fun singleName(conditions: NameConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u72EC\u7ACB\u540D\u79F0\u6761\u4EF6\u3002
\u8BBE\u7F6E\u540E\u5C06\u9996\u5148\u4F7F\u7528 Class.getSimpleName
\uFF0C\u82E5\u4E3A\u7A7A\u5219\u4F1A\u4F7F\u7528 Class.getName
\u8FDB\u884C\u5904\u7406\u3002
inline fun <reified T> extends()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u7EE7\u627F\u7684\u7236\u7C7B\u3002
fun extends(vararg name: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u7EE7\u627F\u7684\u7236\u7C7B\u3002
\u4F1A\u540C\u65F6\u67E5\u627E name
\u4E2D\u6240\u6709\u5339\u914D\u7684\u7236\u7C7B\u3002
inline fun <reified T> implements()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u5B9E\u73B0\u7684\u63A5\u53E3\u7C7B\u3002
fun implements(vararg name: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u5B9E\u73B0\u7684\u63A5\u53E3\u7C7B\u3002
\u4F1A\u540C\u65F6\u67E5\u627E name
\u4E2D\u6240\u6709\u5339\u914D\u7684\u63A5\u53E3\u7C7B\u3002
fun anonymous()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6807\u8BC6
Class
\u4E3A\u533F\u540D\u7C7B\u3002
\u4F8B\u5982 com.demo.Test$1
\u6216 com.demo.Test$InnerTest
\u3002
\u6807\u8BC6\u540E\u4F60\u53EF\u4EE5\u4F7F\u7528 enclosing \u6765\u8FDB\u4E00\u6B65\u6307\u5B9A\u533F\u540D\u7C7B\u7684 (\u5C01\u95ED\u7C7B) \u4E3B\u7C7B\u3002
fun noExtends()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u6CA1\u6709\u4EFB\u4F55\u7EE7\u627F\u3002
\u6B64\u65F6 Class
\u53EA\u5E94\u8BE5\u7EE7\u627F\u4E8E Any
\u3002
\u6CE8\u610F
\u8BBE\u7F6E\u6B64\u6761\u4EF6\u540E extends \u5C06\u5931\u6548\u3002
fun noImplements()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u6CA1\u6709\u4EFB\u4F55\u63A5\u53E3\u3002
\u6CE8\u610F
\u8BBE\u7F6E\u6B64\u6761\u4EF6\u540E implements \u5C06\u5931\u6548\u3002
fun noSuper()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u6CA1\u6709\u4EFB\u4F55\u7EE7\u627F\u4E0E\u63A5\u53E3\u3002
\u6B64\u65F6 Class
\u53EA\u5E94\u8BE5\u7EE7\u627F\u4E8E Any
\u3002
\u6CE8\u610F
\u8BBE\u7F6E\u6B64\u6761\u4EF6\u540E extends \u4E0E implements \u5C06\u5931\u6548\u3002
inline fun <reified T> enclosing()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u533F\u540D\u7C7B\u7684 (\u5C01\u95ED\u7C7B) \u4E3B\u7C7B\u3002
fun enclosing(vararg name: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u533F\u540D\u7C7B\u7684 (\u5C01\u95ED\u7C7B) \u4E3B\u7C7B\u3002
\u4F1A\u540C\u65F6\u67E5\u627E name
\u4E2D\u6240\u6709\u5339\u914D\u7684 (\u5C01\u95ED\u7C7B) \u4E3B\u7C7B\u3002
inner class FromPackageRules internal constructor(private val packages: ArrayList<ClassRulesData.PackageRulesData>)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5305\u540D\u8303\u56F4\u540D\u79F0\u8FC7\u6EE4\u5339\u914D\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
fun absolute()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5305\u540D\u7EDD\u5BF9\u5339\u914D\u3002
\u4F8B\u5982\u6709\u5982\u4E0B\u5305\u540D \u2193
com.demo.test.a
com.demo.test.a.b
com.demo.test.active
\u82E5\u5305\u540D\u6761\u4EF6\u4E3A com.demo.test.a
\u5219\u7EDD\u5BF9\u5339\u914D\u4EC5\u80FD\u5339\u914D\u5230\u7B2C\u4E00\u4E2A\u3002
\u76F8\u53CD\u5730\uFF0C\u4E0D\u8BBE\u7F6E\u4EE5\u4E0A\u793A\u4F8B\u4F1A\u5168\u90E8\u5339\u914D\u3002
inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u7C7B\u540D\u5339\u914D\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
fun optional()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u7C7B\u540D\u53EF\u9009\u3002
\u4F8B\u5982\u6709\u5982\u4E0B\u7C7B\u540D \u2193
com.demo.Test
fullName / Test
simpleName
defpackage.a
fullName / a
simpleName
\u8FD9\u4E24\u4E2A\u7C7B\u540D\u90FD\u662F\u540C\u4E00\u4E2A\u7C7B\uFF0C\u4F46\u662F\u5728\u6709\u4E9B\u7248\u672C\u4E2D\u88AB\u6DF7\u6DC6\u6709\u4E9B\u7248\u672C\u6CA1\u6709\u3002
\u6B64\u65F6\u53EF\u8BBE\u7F6E\u7C7B\u540D\u4E3A com.demo.Test
fullName / Test
simpleName\u3002
\u8FD9\u6837\u5C31\u53EF\u5728\u5B8C\u5168\u5339\u914D\u7C7B\u540D\u60C5\u51B5\u4E0B\u4F7F\u7528\u7C7B\u540D\u800C\u5FFD\u7565\u5176\u5B83\u67E5\u627E\u6761\u4EF6\uFF0C\u5426\u5219\u5FFD\u7565\u6B64\u6761\u4EF6\u7EE7\u7EED\u4F7F\u7528\u5176\u5B83\u67E5\u627E\u6761\u4EF6\u3002
inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u6EE1\u8DB3\u7684Member
\u6761\u4EF6\u3002
inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u6EE1\u8DB3\u7684Field
\u6761\u4EF6\u3002
inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u6EE1\u8DB3\u7684Method
\u6761\u4EF6\u3002
inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Class
\u6EE1\u8DB3\u7684Constructor
\u6761\u4EF6\u3002
inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Class
\u67E5\u627E\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
fun get(): Class<*>?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Class
\u672C\u8EAB\u3002
\u82E5\u6709\u591A\u4E2A Class
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE null
\u3002
\u82E5\u4F60\u8BBE\u7F6E\u4E86 async
\u8BF7\u4F7F\u7528 wait \u65B9\u6CD5\u3002
fun all(): HashSet<Class<*>>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Class
\u672C\u8EAB\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Class
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE\u7A7A\u7684 HashSet
\u3002
\u82E5\u4F60\u8BBE\u7F6E\u4E86 async
\u8BF7\u4F7F\u7528 waitAll \u65B9\u6CD5\u3002
fun all(result: (Class<*>) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Class
\u672C\u8EAB\u6570\u7EC4 (\u4F9D\u6B21\u904D\u5386)\u3002
\u56DE\u8C03\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Class
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u4E0D\u4F1A\u6267\u884C\u3002
\u82E5\u4F60\u8BBE\u7F6E\u4E86 async
\u8BF7\u4F7F\u7528 waitAll \u65B9\u6CD5\u3002
fun wait(result: (Class<*>?) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Class
\u672C\u8EAB (\u5F02\u6B65)\u3002
\u82E5\u6709\u591A\u4E2A Class
\u7ED3\u679C\u53EA\u4F1A\u56DE\u8C03\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u56DE\u8C03 null\u3002
\u4F60\u9700\u8981\u8BBE\u7F6E async
\u540E\u6B64\u65B9\u6CD5\u624D\u4F1A\u88AB\u56DE\u8C03\uFF0C\u5426\u5219\u8BF7\u4F7F\u7528 get \u65B9\u6CD5\u3002
fun waitAll(result: (HashSet<Class<*>>) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Class
\u672C\u8EAB\u6570\u7EC4 (\u5F02\u6B65)\u3002
\u56DE\u8C03\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Class
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u56DE\u8C03\u7A7A\u7684 HashSet
\u3002
\u4F60\u9700\u8981\u8BBE\u7F6E async
\u540E\u6B64\u65B9\u6CD5\u624D\u4F1A\u88AB\u56DE\u8C03\uFF0C\u5426\u5219\u8BF7\u4F7F\u7528 all \u65B9\u6CD5\u3002
fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u627E\u4E0D\u5230
Class
\u65F6\u3002
fun ignored(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565\u5F02\u5E38\u5E76\u505C\u6B62\u6253\u5370\u4EFB\u4F55\u9519\u8BEF\u65E5\u5FD7\u3002
\u6B64\u65F6\u82E5\u8981\u76D1\u542C\u5F02\u5E38\u7ED3\u679C\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u5B9E\u73B0 onNoClassDefFoundError \u65B9\u6CD5\u3002
`,309),p=[l];function c(t,r){return o(),a("div",null,p)}const i=s(n,[["render",c],["__file","DexClassFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/FieldFinder.html.25713065.js b/docs/assets/FieldFinder.html.25713065.js new file mode 100644 index 00000000..45943452 --- /dev/null +++ b/docs/assets/FieldFinder.html.25713065.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-22449c48","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html","title":"FieldFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"type - field","slug":"type-field","link":"#type-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"order - method","slug":"order-method","link":"#order-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"name - method","slug":"name-method-1","link":"#name-method-1","children":[]},{"level":2,"title":"type - method","slug":"type-method","link":"#type-method","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchField - method","slug":"onnosuchfield-method","link":"#onnosuchfield-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]}]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.md"}');export{e as data}; diff --git a/docs/assets/FieldFinder.html.4410e26c.js b/docs/assets/FieldFinder.html.4410e26c.js new file mode 100644 index 00000000..61197677 --- /dev/null +++ b/docs/assets/FieldFinder.html.4410e26c.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-42e0f0ab","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html","title":"FieldFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"type - field","slug":"type-field","link":"#type-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"order - method","slug":"order-method","link":"#order-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"name - method","slug":"name-method-1","link":"#name-method-1","children":[]},{"level":2,"title":"type - method","slug":"type-method","link":"#type-method","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"field - method","slug":"field-method","link":"#field-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchField - method","slug":"onnosuchfield-method","link":"#onnosuchfield-method","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.md"}');export{e as data}; diff --git a/docs/assets/FieldFinder.html.7f3e47fc.js b/docs/assets/FieldFinder.html.7f3e47fc.js new file mode 100644 index 00000000..1224985c --- /dev/null +++ b/docs/assets/FieldFinder.html.7f3e47fc.js @@ -0,0 +1,83 @@ +import{_ as s,o,c as e,a as n}from"./app.fb8271cf.js";const a={},l=n(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class FieldFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>?) : MemberBaseFinder
+
Change Records
v1.0
first
v1.0.2
modified
\u5408\u5E76\u5230 BaseFinder
v1.1.0
modified
\u5408\u5E76\u5230 MemberBaseFinder
Function Illustrate
Field
\u67E5\u627E\u7C7B\u3002
\u53EF\u901A\u8FC7\u6307\u5B9A\u7C7B\u578B\u67E5\u627E\u6307\u5B9A Field
\u6216\u4E00\u7EC4 Field
\u3002
Change Records
v1.0
first
v1.0.2
removed
var name: String
+
Change Records
v1.0
first
v1.0.70
modified
\u5141\u8BB8\u4E0D\u586B\u5199\u540D\u79F0
Function Illustrate
\u8BBE\u7F6E
Field
\u540D\u79F0\u3002
Pay Attention
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
var type: Any?
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E
Field
\u7C7B\u578B\u3002
\u53EF\u4E0D\u586B\u5199\u7C7B\u578B\u3002
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.67
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
modified
\u5408\u5E76\u5230 ModifierConditions
Function Illustrate
\u8BBE\u7F6E
Field
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun order(): IndexTypeCondition
+
Change Records
v1.0.70
added
Function Illustrate
\u987A\u5E8F\u7B5B\u9009\u5B57\u8282\u7801\u7684\u4E0B\u6807\u3002
fun name(value: String): IndexTypeCondition
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E
Field
\u540D\u79F0\u3002
Pay Attention
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun name(conditions: NameConditions): IndexTypeCondition
+
Change Records
v1.0.88
added
v1.1.0
modified
\u5408\u5E76\u5230 NameConditions
Function Illustrate
\u8BBE\u7F6E
Field
\u540D\u79F0\u6761\u4EF6\u3002
Pay Attention
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun type(value: Any): IndexTypeCondition
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E
Field
\u7C7B\u578B\u3002
Pay Attention
\u53EF\u4E0D\u586B\u5199\u7C7B\u578B\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E\u5728
classSet
\u7684\u6240\u6709\u7236\u7C7B\u4E2D\u67E5\u627E\u5F53\u524DField
\u3002
Notice
\u82E5\u5F53\u524D classSet \u7684\u7236\u7C7B\u8F83\u591A\u53EF\u80FD\u4F1A\u8017\u65F6\uFF0CAPI \u4F1A\u81EA\u52A8\u5FAA\u73AF\u5230\u7236\u7C7B\u7EE7\u627F\u662F Any \u524D\u7684\u6700\u540E\u4E00\u4E2A\u7C7B\u3002
inner class RemedyPlan internal constructor()
+
Change Records
v1.1.0
added
Function Illustrate
Field
\u91CD\u67E5\u627E\u5B9E\u73B0\u7C7B\uFF0C\u53EF\u7D2F\u8BA1\u5931\u8D25\u6B21\u6570\u76F4\u5230\u67E5\u627E\u6210\u529F\u3002
inline fun field(initiate: FieldConditions): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u521B\u5EFA\u9700\u8981\u91CD\u65B0\u67E5\u627E\u7684
Field
\u3002
\u4F60\u53EF\u4EE5\u6DFB\u52A0\u591A\u4E2A\u5907\u9009 Field
\uFF0C\u76F4\u5230\u6210\u529F\u4E3A\u6B62\uFF0C\u82E5\u6700\u540E\u4F9D\u7136\u5931\u8D25\uFF0C\u5C06\u505C\u6B62\u67E5\u627E\u5E76\u8F93\u51FA\u9519\u8BEF\u65E5\u5FD7\u3002
inner class Result internal constructor()
+
Change Records
v1.1.0
added
Function Illustrate
RemedyPlan
\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
fun onFind(initiate: HashSet<Field>.() -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u5F53\u5728
RemedyPlan
\u4E2D\u627E\u5230\u7ED3\u679C\u65F6\u3002
Function Example
\u4F60\u53EF\u4EE5\u65B9\u4FBF\u5730\u5BF9\u91CD\u67E5\u627E\u7684 Field
\u5B9E\u73B0 onFind
\u65B9\u6CD5\u3002
The following example
field {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
+
Change Records
v1.0
first
v1.1.0
modified
\u7EE7\u627F\u5230\u63A5\u53E3 BaseResult
Function Illustrate
Field
\u67E5\u627E\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
Function Example
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
The following example
field {
+ // Your code here.
+}.result {
+ get(instance).set("something")
+ get(instance).string()
+ get(instance).cast<CustomClass>()
+ get().boolean()
+ all(instance)
+ give()
+ giveAll()
+ onNoSuchField {}
+}
+
fun get(instance: Any?): Instance
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u5F97
Field
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
\u82E5\u6709\u591A\u4E2A Field
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
Function Example
\u4F60\u53EF\u4EE5\u8F7B\u677E\u5730\u5F97\u5230 Field
\u7684\u5B9E\u4F8B\u4EE5\u53CA\u4F7F\u7528\u5B83\u8FDB\u884C\u8BBE\u7F6E\u5B9E\u4F8B\u3002
The following example
field {
+ // Your code here.
+}.get(instance).set("something")
+
\u5982\u679C\u4F60\u53D6\u5230\u7684\u662F\u9759\u6001 Field
\uFF0C\u53EF\u4EE5\u4E0D\u9700\u8981\u8BBE\u7F6E\u5B9E\u4F8B\u3002
The following example
field {
+ // Your code here.
+}.get().set("something")
+
fun all(instance: Any?): ArrayList<Instance>
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97
Field
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Field
\u5B9E\u4F8B\u7ED3\u679C\u3002
Function Example
\u4F60\u53EF\u4EE5\u901A\u8FC7\u6B64\u65B9\u6CD5\u6765\u83B7\u5F97\u5F53\u524D\u6761\u4EF6\u7ED3\u679C\u4E2D\u5339\u914D\u7684\u5168\u90E8 Field
\uFF0C\u5176 Field
\u6240\u5728\u5B9E\u4F8B\u7528\u6CD5\u4E0E get
\u76F8\u540C\u3002
The following example
field {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.self
+}
+
fun give(): Field?
+
Change Records
v1.0
first
Function Illustrate
\u5F97\u5230
Field
\u672C\u8EAB\u3002
\u82E5\u6709\u591A\u4E2A Field \u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE null
\u3002
fun giveAll(): HashSet<Field>
+
Change Records
v1.1.0
added
Function Illustrate
\u5F97\u5230
Field
\u672C\u8EAB\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Field
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE\u7A7A\u7684 HashSet
\u3002
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97
Field
\u5B9E\u4F8B\u5904\u7406\u7C7B\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u82E5\u6709\u591A\u4E2A Field
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
Pay Attention
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97
Field
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Field
\u5B9E\u4F8B\u7ED3\u679C\u3002
Pay Attention
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u521B\u5EFA
Field
\u91CD\u67E5\u627E\u529F\u80FD\u3002
Function Example
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Field
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchField
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Field
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
The following example
field {
+ // Your code here.
+}.remedys {
+ field {
+ // Your code here.
+ }
+ field {
+ // Your code here.
+ }
+}
+
fun onNoSuchField(result: (Throwable) -> Unit): Result
+
Change Records
v1.0
first
Function Illustrate
\u76D1\u542C\u627E\u4E0D\u5230
Field
\u65F6\u3002
fun ignored(): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u5FFD\u7565\u5F02\u5E38\u5E76\u505C\u6B62\u6253\u5370\u4EFB\u4F55\u9519\u8BEF\u65E5\u5FD7\u3002
\u82E5 isNotIgnoredHookingFailure
\u4E3A false
\u5219\u81EA\u52A8\u5FFD\u7565\u3002
Notice
\u6B64\u65F6\u82E5\u8981\u76D1\u542C\u5F02\u5E38\u7ED3\u679C\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u5B9E\u73B0 onNoSuchField \u65B9\u6CD5\u3002
Change Records
v1.0.3
added
v1.1.0
deprecated
\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()
inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
+
Change Records
v1.0
first
v1.1.0
modified
\u65B0\u589E field
\u53C2\u6570
\u4E0D\u518D\u5BF9\u5916\u516C\u5F00 self
\u53C2\u6570
Function Illustrate
Field
\u5B9E\u4F8B\u53D8\u91CF\u5904\u7406\u7C7B\u3002
Change Records
v1.0
first
v1.1.0
removed
\u8BF7\u76F4\u63A5\u4F7F\u7528 any
\u65B9\u6CD5\u5F97\u5230 Field
\u81EA\u8EAB\u7684\u5B9E\u4F8B\u5316\u5BF9\u8C61
fun current(ignored: Boolean): CurrentClass?
+
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D
Field
\u81EA\u8EABself
\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61CurrentClass
\u3002
fun <T> cast(): T?
+
Change Records
v1.0
first
v1.0.68
modified
\u4FEE\u6539 \u4E3A of
cast
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
\u5B9E\u4F8B\u3002
fun byte(): Byte?
+
Change Records
v1.0.68
added
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Byte \u5B9E\u4F8B\u3002
fun int(): Int
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofInt
int
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Int \u5B9E\u4F8B\u3002
fun long(): Long
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofLong
long
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Long \u5B9E\u4F8B\u3002
fun short(): Short
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofShort
short
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Short \u5B9E\u4F8B\u3002
fun double(): Double
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofDouble
double
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Double \u5B9E\u4F8B\u3002
fun float(): Float
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofFloat
float
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Float \u5B9E\u4F8B\u3002
fun string(): String
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofString
string
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
String \u5B9E\u4F8B\u3002
fun char(): Char
+
Change Records
v1.0.68
added
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Char \u5B9E\u4F8B\u3002
fun boolean(): Boolean
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofBoolean
boolean
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Boolean \u5B9E\u4F8B\u3002
fun any(): Any?
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofAny
any
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Any \u5B9E\u4F8B\u3002
inline fun <reified T> array(): Array<T>
+
Change Records
v1.0.68
added
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
Array \u5B9E\u4F8B\u3002
inline fun <reified T> list(): List<T>
+
Change Records
v1.0.68
added
Function Illustrate
\u5F97\u5230\u5F53\u524D
Field
List \u5B9E\u4F8B\u3002
fun set(any: Any?)
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D
Field
\u5B9E\u4F8B\u3002
fun setTrue()
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D
Field
\u5B9E\u4F8B\u4E3Atrue
\u3002
Pay Attention
\u8BF7\u786E\u4FDD\u5B9E\u4F8B\u5BF9\u8C61\u7C7B\u578B\u4E3A Boolean\u3002
fun setFalse()
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D
Field
\u5B9E\u4F8B\u4E3Afalse
\u3002
Pay Attention
\u8BF7\u786E\u4FDD\u5B9E\u4F8B\u5BF9\u8C61\u7C7B\u578B\u4E3A Boolean\u3002
fun setNull()
+
Change Records
v1.0
first
Function Illustrate
`,368),p=[l];function c(t,r){return o(),e("div",null,p)}const i=s(a,[["render",c],["__file","FieldFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/FieldFinder.html.908d5caa.js b/docs/assets/FieldFinder.html.908d5caa.js new file mode 100644 index 00000000..d78de7b7 --- /dev/null +++ b/docs/assets/FieldFinder.html.908d5caa.js @@ -0,0 +1,83 @@ +import{_ as s,o,c as n,a as e}from"./app.fb8271cf.js";const a={},l=e(`\u8BBE\u7F6E\u5F53\u524D
Field
\u5B9E\u4F8B\u4E3Anull
\u3002
class FieldFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>?) : MemberBaseFinder
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.2
\u4FEE\u6539
\u5408\u5E76\u5230 BaseFinder
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 MemberBaseFinder
\u529F\u80FD\u63CF\u8FF0
Field
\u67E5\u627E\u7C7B\u3002
\u53EF\u901A\u8FC7\u6307\u5B9A\u7C7B\u578B\u67E5\u627E\u6307\u5B9A Field
\u6216\u4E00\u7EC4 Field
\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.2
\u79FB\u9664
var name: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.70
\u4FEE\u6539
\u5141\u8BB8\u4E0D\u586B\u5199\u540D\u79F0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u540D\u79F0\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
var type: Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u7C7B\u578B\u3002
\u53EF\u4E0D\u586B\u5199\u7C7B\u578B\u3002
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 ModifierConditions
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun order(): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u987A\u5E8F\u7B5B\u9009\u5B57\u8282\u7801\u7684\u4E0B\u6807\u3002
fun name(value: String): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u540D\u79F0\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun name(conditions: NameConditions): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 NameConditions
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u540D\u79F0\u6761\u4EF6\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun type(value: Any): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u7C7B\u578B\u3002
\u7279\u522B\u6CE8\u610F
\u53EF\u4E0D\u586B\u5199\u7C7B\u578B\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun superClass(isOnlySuperClass: Boolean)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5728
classSet
\u7684\u6240\u6709\u7236\u7C7B\u4E2D\u67E5\u627E\u5F53\u524DField
\u3002
\u6CE8\u610F
\u82E5\u5F53\u524D classSet \u7684\u7236\u7C7B\u8F83\u591A\u53EF\u80FD\u4F1A\u8017\u65F6\uFF0CAPI \u4F1A\u81EA\u52A8\u5FAA\u73AF\u5230\u7236\u7C7B\u7EE7\u627F\u662F Any \u524D\u7684\u6700\u540E\u4E00\u4E2A\u7C7B\u3002
inner class RemedyPlan internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Field
\u91CD\u67E5\u627E\u5B9E\u73B0\u7C7B\uFF0C\u53EF\u7D2F\u8BA1\u5931\u8D25\u6B21\u6570\u76F4\u5230\u67E5\u627E\u6210\u529F\u3002
inline fun field(initiate: FieldConditions): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u9700\u8981\u91CD\u65B0\u67E5\u627E\u7684
Field
\u3002
\u4F60\u53EF\u4EE5\u6DFB\u52A0\u591A\u4E2A\u5907\u9009 Field
\uFF0C\u76F4\u5230\u6210\u529F\u4E3A\u6B62\uFF0C\u82E5\u6700\u540E\u4F9D\u7136\u5931\u8D25\uFF0C\u5C06\u505C\u6B62\u67E5\u627E\u5E76\u8F93\u51FA\u9519\u8BEF\u65E5\u5FD7\u3002
inner class Result internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
RemedyPlan
\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
fun onFind(initiate: HashSet<Field>.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u5728
RemedyPlan
\u4E2D\u627E\u5230\u7ED3\u679C\u65F6\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u65B9\u4FBF\u5730\u5BF9\u91CD\u67E5\u627E\u7684 Field
\u5B9E\u73B0 onFind
\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
field {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u7EE7\u627F\u5230\u63A5\u53E3 BaseResult
\u529F\u80FD\u63CF\u8FF0
Field
\u67E5\u627E\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
\u793A\u4F8B\u5982\u4E0B
field {
+ // Your code here.
+}.result {
+ get(instance).set("something")
+ get(instance).string()
+ get(instance).cast<CustomClass>()
+ get().boolean()
+ all(instance)
+ give()
+ giveAll()
+ onNoSuchField {}
+}
+
fun get(instance: Any?): Instance
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Field
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
\u82E5\u6709\u591A\u4E2A Field
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u8F7B\u677E\u5730\u5F97\u5230 Field
\u7684\u5B9E\u4F8B\u4EE5\u53CA\u4F7F\u7528\u5B83\u8FDB\u884C\u8BBE\u7F6E\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
field {
+ // Your code here.
+}.get(instance).set("something")
+
\u5982\u679C\u4F60\u53D6\u5230\u7684\u662F\u9759\u6001 Field
\uFF0C\u53EF\u4EE5\u4E0D\u9700\u8981\u8BBE\u7F6E\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
field {
+ // Your code here.
+}.get().set("something")
+
fun all(instance: Any?): ArrayList<Instance>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Field
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Field
\u5B9E\u4F8B\u7ED3\u679C\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u901A\u8FC7\u6B64\u65B9\u6CD5\u6765\u83B7\u5F97\u5F53\u524D\u6761\u4EF6\u7ED3\u679C\u4E2D\u5339\u914D\u7684\u5168\u90E8 Field
\uFF0C\u5176 Field
\u6240\u5728\u5B9E\u4F8B\u7528\u6CD5\u4E0E get
\u76F8\u540C\u3002
\u793A\u4F8B\u5982\u4E0B
field {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.self
+}
+
fun give(): Field?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Field
\u672C\u8EAB\u3002
\u82E5\u6709\u591A\u4E2A Field \u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE null
\u3002
fun giveAll(): HashSet<Field>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Field
\u672C\u8EAB\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Field
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE\u7A7A\u7684 HashSet
\u3002
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Field
\u5B9E\u4F8B\u5904\u7406\u7C7B\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u82E5\u6709\u591A\u4E2A Field
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Field
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Field
\u5B9E\u4F8B\u7ED3\u679C\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA
Field
\u91CD\u67E5\u627E\u529F\u80FD\u3002
\u529F\u80FD\u793A\u4F8B
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Field
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchField
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Field
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
\u793A\u4F8B\u5982\u4E0B
field {
+ // Your code here.
+}.remedys {
+ field {
+ // Your code here.
+ }
+ field {
+ // Your code here.
+ }
+}
+
fun onNoSuchField(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u627E\u4E0D\u5230
Field
\u65F6\u3002
fun ignored(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565\u5F02\u5E38\u5E76\u505C\u6B62\u6253\u5370\u4EFB\u4F55\u9519\u8BEF\u65E5\u5FD7\u3002
\u82E5 isNotIgnoredHookingFailure
\u4E3A false
\u5219\u81EA\u52A8\u5FFD\u7565\u3002
\u6CE8\u610F
\u6B64\u65F6\u82E5\u8981\u76D1\u542C\u5F02\u5E38\u7ED3\u679C\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u5B9E\u73B0 onNoSuchField \u65B9\u6CD5\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.3
\u65B0\u589E
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()
inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u65B0\u589E field
\u53C2\u6570
\u4E0D\u518D\u5BF9\u5916\u516C\u5F00 self
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
Field
\u5B9E\u4F8B\u53D8\u91CF\u5904\u7406\u7C7B\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u79FB\u9664
\u8BF7\u76F4\u63A5\u4F7F\u7528 any
\u65B9\u6CD5\u5F97\u5230 Field
\u81EA\u8EAB\u7684\u5B9E\u4F8B\u5316\u5BF9\u8C61
fun current(ignored: Boolean): CurrentClass?
+
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D
Field
\u81EA\u8EABself
\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61CurrentClass
\u3002
fun <T> cast(): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A of
cast
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
\u5B9E\u4F8B\u3002
fun byte(): Byte?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Byte \u5B9E\u4F8B\u3002
fun int(): Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofInt
int
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Int \u5B9E\u4F8B\u3002
fun long(): Long
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofLong
long
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Long \u5B9E\u4F8B\u3002
fun short(): Short
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofShort
short
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Short \u5B9E\u4F8B\u3002
fun double(): Double
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofDouble
double
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Double \u5B9E\u4F8B\u3002
fun float(): Float
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofFloat
float
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Float \u5B9E\u4F8B\u3002
fun string(): String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofString
string
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
String \u5B9E\u4F8B\u3002
fun char(): Char
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Char \u5B9E\u4F8B\u3002
fun boolean(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofBoolean
boolean
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Boolean \u5B9E\u4F8B\u3002
fun any(): Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofAny
any
\u79FB\u52A8\u65B9\u6CD5\u5230 Instance
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Any \u5B9E\u4F8B\u3002
inline fun <reified T> array(): Array<T>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
Array \u5B9E\u4F8B\u3002
inline fun <reified T> list(): List<T>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D
Field
List \u5B9E\u4F8B\u3002
fun set(any: Any?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D
Field
\u5B9E\u4F8B\u3002
fun setTrue()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D
Field
\u5B9E\u4F8B\u4E3Atrue
\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD\u5B9E\u4F8B\u5BF9\u8C61\u7C7B\u578B\u4E3A Boolean\u3002
fun setFalse()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D
Field
\u5B9E\u4F8B\u4E3Afalse
\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD\u5B9E\u4F8B\u5BF9\u8C61\u7C7B\u578B\u4E3A Boolean\u3002
fun setNull()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
`,367),p=[l];function c(t,r){return o(),n("div",null,p)}const i=s(a,[["render",c],["__file","FieldFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/FieldRules.html.1fea86e8.js b/docs/assets/FieldRules.html.1fea86e8.js new file mode 100644 index 00000000..951404f5 --- /dev/null +++ b/docs/assets/FieldRules.html.1fea86e8.js @@ -0,0 +1,6 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const n={},l=a(`\u8BBE\u7F6E\u5F53\u524D
Field
\u5B9E\u4F8B\u4E3Anull
\u3002
class FieldRules internal constructor(internal val rulesData: FieldRulesData) : BaseRules
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Field
\u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
var name: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u540D\u79F0\u3002
var type: Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u7C7B\u578B\u3002
\u53EF\u4E0D\u586B\u5199\u7C7B\u578B\u3002
fun modifiers(conditions: ModifierConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Field
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
fun name(conditions: NameConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,32),p=[l];function c(t,r){return e(),o("div",null,p)}const i=s(n,[["render",c],["__file","FieldRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/FieldRules.html.6858f0d6.js b/docs/assets/FieldRules.html.6858f0d6.js new file mode 100644 index 00000000..624620bb --- /dev/null +++ b/docs/assets/FieldRules.html.6858f0d6.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-3e67a42e","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html","title":"FieldRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"type - field","slug":"type-field","link":"#type-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.md"}');export{e as data}; diff --git a/docs/assets/FieldRules.html.990238ad.js b/docs/assets/FieldRules.html.990238ad.js new file mode 100644 index 00000000..a82a20ab --- /dev/null +++ b/docs/assets/FieldRules.html.990238ad.js @@ -0,0 +1,6 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const n={},l=a(`\u8BBE\u7F6E
Field
\u540D\u79F0\u6761\u4EF6\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class FieldRules internal constructor(internal val rulesData: FieldRulesData) : BaseRules
+
Change Records
v1.1.0
added
Function Illustrate
Field
\u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
var name: String
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Field
\u540D\u79F0\u3002
var type: Any?
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Field
\u7C7B\u578B\u3002
\u53EF\u4E0D\u586B\u5199\u7C7B\u578B\u3002
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Field
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
fun name(conditions: NameConditions)
+
Change Records
v1.1.0
added
Function Illustrate
`,33),p=[l];function c(t,r){return e(),o("div",null,p)}const i=s(n,[["render",c],["__file","FieldRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/FieldRules.html.9b04521f.js b/docs/assets/FieldRules.html.9b04521f.js new file mode 100644 index 00000000..62a7727e --- /dev/null +++ b/docs/assets/FieldRules.html.9b04521f.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-21f64ebf","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html","title":"FieldRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"type - field","slug":"type-field","link":"#type-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.md"}');export{e as data}; diff --git a/docs/assets/GenericClass.html.3a0e1ac6.js b/docs/assets/GenericClass.html.3a0e1ac6.js new file mode 100644 index 00000000..70026217 --- /dev/null +++ b/docs/assets/GenericClass.html.3a0e1ac6.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-69c1c226","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html","title":"GenericClass - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"argument - method","slug":"argument-method","link":"#argument-method","children":[]}],"git":{"updatedTime":1663646280000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.md"}');export{e as data}; diff --git a/docs/assets/GenericClass.html.7b666428.js b/docs/assets/GenericClass.html.7b666428.js new file mode 100644 index 00000000..8b97cc1e --- /dev/null +++ b/docs/assets/GenericClass.html.7b666428.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0183e3fc","path":"/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html","title":"GenericClass - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"argument - method","slug":"argument-method","link":"#argument-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.md"}');export{e as data}; diff --git a/docs/assets/GenericClass.html.b1c03ed1.js b/docs/assets/GenericClass.html.b1c03ed1.js new file mode 100644 index 00000000..bbd799cc --- /dev/null +++ b/docs/assets/GenericClass.html.b1c03ed1.js @@ -0,0 +1,3 @@ +import{_ as s,o as a,c as e,a as n}from"./app.fb8271cf.js";const o={},l=n(`\u8BBE\u7F6E
Field
\u540D\u79F0\u6761\u4EF6\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class GenericClass internal constructor(private val type: ParameterizedType)
+
Change Records
v1.1.0
added
Function Illustrate
\u5F53\u524D
Class
\u7684\u6CDB\u578B\u7236\u7C7B\u64CD\u4F5C\u5BF9\u8C61\u3002
fun argument(index: Int): Class<*>
+
Change Records
v1.1.0
added
Function Illustrate
`,13),t=[l];function c(p,r){return a(),e("div",null,t)}const d=s(o,[["render",c],["__file","GenericClass.html.vue"]]);export{d as default}; diff --git a/docs/assets/GenericClass.html.ca958253.js b/docs/assets/GenericClass.html.ca958253.js new file mode 100644 index 00000000..f492b8c3 --- /dev/null +++ b/docs/assets/GenericClass.html.ca958253.js @@ -0,0 +1,3 @@ +import{_ as s,o as a,c as e,a as n}from"./app.fb8271cf.js";const o={},l=n(`\u83B7\u5F97\u6CDB\u578B\u53C2\u6570\u6570\u7EC4\u4E0B\u6807\u7684
Class
\u5B9E\u4F8B\u3002
class GenericClass internal constructor(private val type: ParameterizedType)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D
Class
\u7684\u6CDB\u578B\u7236\u7C7B\u64CD\u4F5C\u5BF9\u8C61\u3002
fun argument(index: Int): Class<*>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,12),c=[l];function p(t,r){return a(),e("div",null,c)}const i=s(o,[["render",p],["__file","GenericClass.html.vue"]]);export{i as default}; diff --git a/docs/assets/GraphicsTypeFactory.html.61eca533.js b/docs/assets/GraphicsTypeFactory.html.61eca533.js new file mode 100644 index 00000000..12367e8c --- /dev/null +++ b/docs/assets/GraphicsTypeFactory.html.61eca533.js @@ -0,0 +1 @@ +import{_ as a,r as c,o as s,c as r,b as o,d as n,a as i,e}from"./app.fb8271cf.js";const p={},l=i('\u83B7\u5F97\u6CDB\u578B\u53C2\u6570\u6570\u7EC4\u4E0B\u6807\u7684
Class
\u5B9E\u4F8B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0
first
Function Illustrate
',6),d=e("\u8BE6\u60C5\u53EF "),h={href:"https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"},_=e("\u70B9\u51FB\u8FD9\u91CC"),u=e(" \u8FDB\u884C\u67E5\u770B\u3002");function k(f,g){const t=c("ExternalLinkIcon");return s(),r("div",null,[l,o("p",null,[d,o("a",h,[_,n(t)]),u])])}const y=a(p,[["render",k],["__file","GraphicsTypeFactory.html.vue"]]);export{y as default}; diff --git a/docs/assets/GraphicsTypeFactory.html.a3936b7c.js b/docs/assets/GraphicsTypeFactory.html.a3936b7c.js new file mode 100644 index 00000000..0feaa1bf --- /dev/null +++ b/docs/assets/GraphicsTypeFactory.html.a3936b7c.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-7b0abf86","path":"/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html","title":"GraphicsTypeFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.md"}');export{a as data}; diff --git a/docs/assets/GraphicsTypeFactory.html.bfb4e259.js b/docs/assets/GraphicsTypeFactory.html.bfb4e259.js new file mode 100644 index 00000000..04f16a1f --- /dev/null +++ b/docs/assets/GraphicsTypeFactory.html.bfb4e259.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-4ea62475","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html","title":"GraphicsTypeFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.md"}');export{a as data}; diff --git a/docs/assets/GraphicsTypeFactory.html.df9b6853.js b/docs/assets/GraphicsTypeFactory.html.df9b6853.js new file mode 100644 index 00000000..2efc4e9b --- /dev/null +++ b/docs/assets/GraphicsTypeFactory.html.df9b6853.js @@ -0,0 +1 @@ +import{_ as c,r as a,o as r,c as s,b as o,d as n,a as p,e}from"./app.fb8271cf.js";const i={},d=p('\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A
Android
\u76F8\u5173Graphics
\u7684Class
\u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
',5),h=e("\u8BE6\u60C5\u53EF "),l={href:"https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"},_=e("\u70B9\u51FB\u8FD9\u91CC"),k=e(" \u8FDB\u884C\u67E5\u770B\u3002");function y(f,u){const t=a("ExternalLinkIcon");return r(),s("div",null,[d,o("p",null,[h,o("a",l,[_,n(t)]),k])])}const b=c(i,[["render",y],["__file","GraphicsTypeFactory.html.vue"]]);export{b as default}; diff --git a/docs/assets/HookClass.html.486aa6ea.js b/docs/assets/HookClass.html.486aa6ea.js new file mode 100644 index 00000000..f842a15f --- /dev/null +++ b/docs/assets/HookClass.html.486aa6ea.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-735374af","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html","title":"HookClass - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.md"}');export{a as data}; diff --git a/docs/assets/HookClass.html.52e59cf0.js b/docs/assets/HookClass.html.52e59cf0.js new file mode 100644 index 00000000..cb4233db --- /dev/null +++ b/docs/assets/HookClass.html.52e59cf0.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-57506200","path":"/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html","title":"HookClass - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.md"}');export{a as data}; diff --git a/docs/assets/HookClass.html.7354fd95.js b/docs/assets/HookClass.html.7354fd95.js new file mode 100644 index 00000000..cd407e2a --- /dev/null +++ b/docs/assets/HookClass.html.7354fd95.js @@ -0,0 +1,2 @@ +import{_ as s,o,c as a,a as n}from"./app.fb8271cf.js";const l={},e=n(`\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A
Android
\u76F8\u5173Graphics
\u7684Class
\u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002
class HookClass internal constructor(internal var instance: Class<*>?, internal var name: String, internal var throwable: Throwable?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
HookClass
\u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u4E00\u4E2A\u5F53\u524D Hook \u7684
Class
\u63A5\u7BA1\u7C7B\u3002
instance
\u4E3A\u5B9E\u4F8B\uFF0Cname
\u4E3A\u5B9E\u4F8B\u5B8C\u6574\u5305\u540D\uFF0Cthrowable
\u4E3A\u627E\u4E0D\u5230\u5B9E\u4F8B\u7684\u65F6\u5019\u629B\u51FA\u7684\u5F02\u5E38\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class HookClass internal constructor(internal var instance: Class<*>?, internal var name: String, internal var throwable: Throwable?)
+
Change Records
v1.0
first
v1.1.0
modified
HookClass
\u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E
Function Illustrate
\u521B\u5EFA\u4E00\u4E2A\u5F53\u524D Hook \u7684
Class
\u63A5\u7BA1\u7C7B\u3002
instance
\u4E3A\u5B9E\u4F8B\uFF0Cname
\u4E3A\u5B9E\u4F8B\u5B8C\u6574\u5305\u540D\uFF0Cthrowable
\u4E3A\u627E\u4E0D\u5230\u5B9E\u4F8B\u7684\u65F6\u5019\u629B\u51FA\u7684\u5F02\u5E38\u3002
class HookParam internal constructor(private val creatorInstance: YukiMemberHookCreator, private var param: YukiHookCallback.Param?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u79FB\u52A8 HookParamWrapper
\u5230 YukiHookCallback.Param
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 creater \u547D\u540D\u5230 creator
\u529F\u80FD\u63CF\u8FF0
Hook \u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u76EE\u6807\u5BF9\u8C61\u5B9E\u73B0\u7C7B\u3002
val args: Array<Any?>
+
\u53D8\u66F4\u8BB0\u5F55
\u5728 v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61
member
\u6216constructor
\u7684\u53C2\u6570\u5BF9\u8C61\u6570\u7EC4\u3002
\u8FD9\u91CC\u7684\u6570\u7EC4\u6BCF\u9879\u7C7B\u578B\u9ED8\u8BA4\u4E3A Any
\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 args
\u65B9\u6CD5\u6765\u5B9E\u73B0 ArgsModifyer.cast
\u529F\u80FD\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.75
\u79FB\u9664
\u8BF7\u4F7F\u7528 args(index = 0)
\u6216 args().first()
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.75
\u79FB\u9664
\u8BF7\u4F7F\u7528 args().last()
val instance: Any
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u5BF9\u8C61\u3002
\u7279\u522B\u6CE8\u610F
\u5982\u679C\u4F60\u5F53\u524D Hook \u7684\u5BF9\u8C61\u662F\u4E00\u4E2A\u9759\u6001\uFF0C\u90A3\u4E48\u5B83\u5C06\u4E0D\u5B58\u5728\u5B9E\u4F8B\u7684\u5BF9\u8C61\u3002
val instanceClass: Class<*>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u7C7B\u5BF9\u8C61\u3002
val member: Member
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
Member
\u3002
\u5728\u4E0D\u786E\u5B9A Member
\u7C7B\u578B\u4E3A Method
\u6216 Constructor
\u65F6\u53EF\u4EE5\u4F7F\u7528\u6B64\u65B9\u6CD5\u3002
val method: Method
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684\u65B9\u6CD5\u3002
val constructor: Constructor
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684\u6784\u9020\u65B9\u6CD5\u3002
var result: Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u3001\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u8FD4\u56DE\u503C\u3002
val hasThrowable: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5224\u65AD\u662F\u5426\u5B58\u5728\u8BBE\u7F6E\u8FC7\u7684\u65B9\u6CD5\u8C03\u7528\u629B\u51FA\u5F02\u5E38\u3002
val throwable: Throwable?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u8BBE\u7F6E\u7684\u65B9\u6CD5\u8C03\u7528\u629B\u51FA\u5F02\u5E38\u3002
fun Throwable.throwToApp()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5411 Hook APP \u629B\u51FA\u5F02\u5E38\u3002
\u4F7F\u7528 hasThrowable
\u5224\u65AD\u5F53\u524D\u662F\u5426\u5B58\u5728\u88AB\u629B\u51FA\u7684\u5F02\u5E38\u3002
\u4F7F\u7528 throwable
\u83B7\u53D6\u5F53\u524D\u8BBE\u7F6E\u7684\u65B9\u6CD5\u8C03\u7528\u629B\u51FA\u5F02\u5E38\u3002
\u4EC5\u4F1A\u5728\u56DE\u8C03\u65B9\u6CD5\u7684 MemberHookCreator.beforeHook
\u6216 MemberHookCreator.afterHook
\u4E2D\u751F\u6548\u3002
\u7279\u522B\u6CE8\u610F
\u8BBE\u7F6E\u540E\u4F1A\u540C\u65F6\u6267\u884C resultNull \u65B9\u6CD5\u5E76\u5C06\u5F02\u5E38\u629B\u51FA\u7ED9\u5F53\u524D Hook APP\u3002
\u529F\u80FD\u793A\u4F8B
Hook \u8FC7\u7A0B\u4E2D\u7684\u5F02\u5E38\u4EC5\u4F1A\u4F5C\u7528\u4E8E (Xposed) \u5BBF\u4E3B\u73AF\u5883\uFF0C\u76EE\u6807 Hook APP \u4E0D\u4F1A\u53D7\u5230\u5F71\u54CD\u3002
\u82E5\u60F3\u5C06\u5F02\u5E38\u629B\u7ED9 Hook APP\uFF0C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u5982\u4E0B\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ method {
+ // ...
+ }
+ beforeHook {
+ RuntimeException("Test Exception").throwToApp()
+ }
+}
+
\u7279\u522B\u6CE8\u610F
\u5411 Hook APP \u629B\u51FA\u5F02\u5E38\u4F1A\u5BF9\u5176\u66B4\u9732\u88AB Hook \u7684\u4E8B\u5B9E\uFF0C\u662F\u4E0D\u5B89\u5168\u7684\uFF0C\u5BB9\u6613\u88AB\u68C0\u6D4B\uFF0C\u8BF7\u6309\u5B9E\u9645\u573A\u666F\u5408\u7406\u4F7F\u7528\u3002
inline fun <reified T> result(): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.75
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u8FD4\u56DE\u503CT
\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.75
\u79FB\u9664
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.75
\u79FB\u9664
inline fun <reified T> instance(): T
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u5BF9\u8C61
T
\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u901A\u8FC7 instance
\u65B9\u6CD5\u8F7B\u677E\u4F7F\u7528\u6CDB\u578B cast
\u4E3A\u76EE\u6807\u5BF9\u8C61\u7684\u7C7B\u578B\u3002
\u793A\u4F8B\u5982\u4E0B
instance<Activity>().finish()
+
fun args(): ArgsIndexCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.75
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u53C2\u6570\u6570\u7EC4\u4E0B\u6807\u5B9E\u4F8B\u5316\u7C7B\u3002
fun args(index: Int): ArgsModifyer
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.75
\u4FEE\u6539
\u9ED8\u8BA4\u503C index = 0
\u79FB\u52A8\u5230\u65B0\u7684\u4F7F\u7528\u65B9\u6CD5 args().first()
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u53C2\u6570\u5B9E\u4F8B\u5316\u5BF9\u8C61\u7C7B\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u901A\u8FC7 args
\u65B9\u6CD5\u4FEE\u6539\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u53C2\u6570\u5185\u5BB9\u3002
\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 set
\u65B9\u6CD5\u8BBE\u7F6E param
\u4E3A\u4F60\u7684\u76EE\u6807\u5B9E\u4F8B\uFF0C\u63A5\u53D7 Any
\u7C7B\u578B\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD param \u7C7B\u578B\u4E3A\u4F60\u7684\u76EE\u6807\u5B9E\u4F8B\u7C7B\u578B\u3002
\u793A\u4F8B\u5982\u4E0B
args(index = 0).set("modify the value")
+
\u4F60\u53EF\u4EE5\u8FD9\u6837\u76F4\u63A5\u8BBE\u7F6E\u7B2C\u4E00\u4F4D param
\u7684\u503C\u3002
\u793A\u4F8B\u5982\u4E0B
args().first().set("modify the value")
+
\u4F60\u8FD8\u53EF\u4EE5\u76F4\u63A5\u8BBE\u7F6E\u6700\u540E\u4E00\u4F4D param
\u7684\u503C\u3002
\u793A\u4F8B\u5982\u4E0B
args().last().set("modify the value")
+
\u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 setNull
\u65B9\u6CD5\u8BBE\u7F6E param
\u4E3A\u7A7A\u3002
\u793A\u4F8B\u5982\u4E0B
args(index = 1).setNull()
+
\u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 setTrue
\u65B9\u6CD5\u8BBE\u7F6E param
\u4E3A true
\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD param \u7C7B\u578B\u4E3A Boolean\u3002
\u793A\u4F8B\u5982\u4E0B
args(index = 1).setTrue()
+
\u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 setFalse
\u65B9\u6CD5\u8BBE\u7F6E param
\u4E3A false
\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD param \u7C7B\u578B\u4E3A Boolean\u3002
\u793A\u4F8B\u5982\u4E0B
args(index = 1).setFalse()
+
fun callOriginal(): Any?
+
fun <T> callOriginal(): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C\u539F\u59CB
Member
\u3002
\u8C03\u7528\u81EA\u8EAB\u672A\u8FDB\u884C Hook \u7684\u539F\u59CB Member
\u5E76\u8C03\u7528\u539F\u59CB\u53C2\u6570\u6267\u884C\u3002
\u529F\u80FD\u5B9E\u4F8B
\u6B64\u65B9\u6CD5\u53EF\u4EE5 invoke
\u539F\u59CB\u672A\u7ECF Hook \u7684 Member
\u5BF9\u8C61\uFF0C\u53D6\u51B3\u4E8E\u539F\u59CB Member
\u7684\u53C2\u6570\u3002
\u8C03\u7528\u81EA\u8EAB\u539F\u59CB\u7684\u65B9\u6CD5\u4E0D\u4F1A\u518D\u7ECF\u8FC7\u5F53\u524D beforeHook
\u3001afterHook
\u4EE5\u53CA replaceUnit
\u3001replaceAny
\u3002
\u6BD4\u5982\u6211\u4EEC Hook \u7684\u8FD9\u4E2A\u65B9\u6CD5\u88AB\u8FD9\u6837\u8C03\u7528 test("test value")
\uFF0C\u4F7F\u7528\u6B64\u65B9\u6CD5\u4F1A\u8C03\u7528\u5176\u4E2D\u7684 "test value"
\u4F5C\u4E3A\u53C2\u6570\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = StringType
+ }
+ afterHook {
+ // <\u65B9\u68481> \u4E0D\u4F7F\u7528\u6CDB\u578B\uFF0C\u4E0D\u83B7\u53D6\u65B9\u6CD5\u6267\u884C\u7ED3\u679C\uFF0C\u8C03\u7528\u5C06\u4F7F\u7528\u539F\u65B9\u6CD5\u4F20\u5165\u7684 args \u81EA\u52A8\u4F20\u53C2
+ callOriginal()
+ // <\u65B9\u68482> \u4F7F\u7528\u6CDB\u578B\uFF0C\u5DF2\u77E5\u65B9\u6CD5\u6267\u884C\u7ED3\u679C\u53C2\u6570\u7C7B\u578B\u8FDB\u884C cast
+ // \u5047\u8BBE\u8FD4\u56DE\u503C\u4E3A String\uFF0C\u5931\u8D25\u4F1A\u8FD4\u56DE null\uFF0C\u8C03\u7528\u5C06\u4F7F\u7528\u539F\u65B9\u6CD5\u4F20\u5165\u7684 args \u81EA\u52A8\u4F20\u53C2
+ val value = callOriginal<String>()
+ }
+}
+
fun invokeOriginal(vararg args: Any?): Any?
+
fun <T> invokeOriginal(vararg args: Any?): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u4E0D\u518D\u9700\u8981\u4F7F\u7528 member.invokeOriginal
\u8FDB\u884C\u8C03\u7528
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C\u539F\u59CB
Member
\u3002
\u8C03\u7528\u81EA\u8EAB\u672A\u8FDB\u884C Hook \u7684\u539F\u59CB Member
\u5E76\u81EA\u5B9A\u4E49 args
\u6267\u884C\u3002
\u529F\u80FD\u5B9E\u4F8B
\u6B64\u65B9\u6CD5\u53EF\u4EE5 invoke
\u539F\u59CB\u672A\u7ECF Hook \u7684 Member
\u5BF9\u8C61\uFF0C\u53EF\u81EA\u5B9A\u4E49\u9700\u8981\u8C03\u7528\u7684\u53C2\u6570\u5185\u5BB9\u3002
\u8C03\u7528\u81EA\u8EAB\u539F\u59CB\u7684\u65B9\u6CD5\u4E0D\u4F1A\u518D\u7ECF\u8FC7\u5F53\u524D beforeHook
\u3001afterHook
\u4EE5\u53CA replaceUnit
\u3001replaceAny
\u3002
\u6BD4\u5982\u6211\u4EEC Hook \u7684\u8FD9\u4E2A\u65B9\u6CD5\u88AB\u8FD9\u6837\u8C03\u7528 test("test value")
\uFF0C\u4F7F\u7528\u6B64\u65B9\u6CD5\u53EF\u81EA\u5B9A\u4E49\u5176\u4E2D\u7684 args
\u4F5C\u4E3A\u53C2\u6570\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = StringType
+ }
+ afterHook {
+ // <\u65B9\u68481> \u4E0D\u4F7F\u7528\u6CDB\u578B\uFF0C\u4E0D\u83B7\u53D6\u65B9\u6CD5\u6267\u884C\u7ED3\u679C
+ invokeOriginal("test value")
+ // <\u65B9\u68482> \u4F7F\u7528\u6CDB\u578B\uFF0C\u5DF2\u77E5\u65B9\u6CD5\u6267\u884C\u7ED3\u679C\u53C2\u6570\u7C7B\u578B\u8FDB\u884C cast\uFF0C\u5047\u8BBE\u8FD4\u56DE\u503C\u4E3A String\uFF0C\u5931\u8D25\u4F1A\u8FD4\u56DE null
+ val value = invokeOriginal<String>("test value")
+ }
+}
+
fun resultTrue()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u65B9\u6CD5\u7684
result
\u8FD4\u56DE\u503C\u4E3Atrue
\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD result \u7C7B\u578B\u4E3A Boolean\u3002
fun resultFalse()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u65B9\u6CD5\u7684
result
\u8FD4\u56DE\u503C\u4E3Afalse
\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD result \u7C7B\u578B\u4E3A Boolean\u3002
fun resultNull()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u6CE8\u610F
\u6B64\u65B9\u6CD5\u5C06\u5F3A\u5236\u8BBE\u7F6E Hook \u5BF9\u8C61\u65B9\u6CD5\u7684 result \u4E3A null\u3002
inner class ArgsIndexCondition internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.75
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5BF9\u65B9\u6CD5\u53C2\u6570\u7684\u6570\u7EC4\u4E0B\u6807\u8FDB\u884C\u5B9E\u4F8B\u5316\u7C7B\u3002
fun first(): ArgsModifyer
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.75
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u53C2\u6570\u6570\u7EC4\u7B2C\u4E00\u4F4D\u3002
fun last(): ArgsModifyer
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.75
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u53C2\u6570\u6570\u7EC4\u6700\u540E\u4E00\u4F4D\u3002
inner class ArgsModifyer internal constructor(private val index: Int)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5BF9\u65B9\u6CD5\u53C2\u6570\u7684\u4FEE\u6539\u8FDB\u884C\u5B9E\u4F8B\u5316\u7C7B\u3002
fun <T> cast(): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A of
cast
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61
T
\u3002
fun byte(): Byte?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Byte\u3002
fun int(): Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofInt
int
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Int\u3002
fun long(): Long
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofLong
long
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Long\u3002
fun short(): Short
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofShort
short
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Short\u3002
fun double(): Double
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofDouble
double
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Double\u3002
fun float(): Float
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofFloat
float
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Float\u3002
fun string(): String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofString
string
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 String\u3002
fun char(): Char
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Char\u3002
fun boolean(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.66
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A ofBoolean
boolean
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Boolean\u3002
fun any(): Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.77
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Any\u3002
inline fun <reified T> array(): Array<T>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Array\u3002
inline fun <reified T> list(): List<T>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 List\u3002
fun <T> set(any: T?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u3002
fun setNull()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u4E3A
null
\u3002
fun setTrue()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u4E3A
true
\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD\u76EE\u6807\u5BF9\u8C61\u7684\u7C7B\u578B\u662F Boolean\u3002
fun setFalse()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u4E3A
false
\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u786E\u4FDD\u76EE\u6807\u5BF9\u8C61\u7684\u7C7B\u578B\u662F Boolean\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class HookParam internal constructor(private val creatorInstance: YukiMemberHookCreator, private var param: YukiHookCallback.Param?)
+
Change Records
v1.0
first
v1.1.0
modified
\u79FB\u52A8 HookParamWrapper
\u5230 YukiHookCallback.Param
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 creater \u547D\u540D\u5230 creator
Function Illustrate
Hook \u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u76EE\u6807\u5BF9\u8C61\u5B9E\u73B0\u7C7B\u3002
val args: Array<Any?>
+
Change Records
\u5728 v1.0
\u6DFB\u52A0
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61
member
\u6216constructor
\u7684\u53C2\u6570\u5BF9\u8C61\u6570\u7EC4\u3002
\u8FD9\u91CC\u7684\u6570\u7EC4\u6BCF\u9879\u7C7B\u578B\u9ED8\u8BA4\u4E3A Any
\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 args
\u65B9\u6CD5\u6765\u5B9E\u73B0 ArgsModifyer.cast
\u529F\u80FD\u3002
Change Records
v1.0
first
v1.0.75
removed
\u8BF7\u4F7F\u7528 args(index = 0)
\u6216 args().first()
Change Records
v1.0
first
v1.0.75
removed
\u8BF7\u4F7F\u7528 args().last()
val instance: Any
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u5BF9\u8C61\u3002
Pay Attention
\u5982\u679C\u4F60\u5F53\u524D Hook \u7684\u5BF9\u8C61\u662F\u4E00\u4E2A\u9759\u6001\uFF0C\u90A3\u4E48\u5B83\u5C06\u4E0D\u5B58\u5728\u5B9E\u4F8B\u7684\u5BF9\u8C61\u3002
val instanceClass: Class<*>
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u7C7B\u5BF9\u8C61\u3002
val member: Member
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
Member
\u3002
\u5728\u4E0D\u786E\u5B9A Member
\u7C7B\u578B\u4E3A Method
\u6216 Constructor
\u65F6\u53EF\u4EE5\u4F7F\u7528\u6B64\u65B9\u6CD5\u3002
val method: Method
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684\u65B9\u6CD5\u3002
val constructor: Constructor
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684\u6784\u9020\u65B9\u6CD5\u3002
var result: Any?
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u3001\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u8FD4\u56DE\u503C\u3002
val hasThrowable: Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u5224\u65AD\u662F\u5426\u5B58\u5728\u8BBE\u7F6E\u8FC7\u7684\u65B9\u6CD5\u8C03\u7528\u629B\u51FA\u5F02\u5E38\u3002
val throwable: Throwable?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u53D6\u8BBE\u7F6E\u7684\u65B9\u6CD5\u8C03\u7528\u629B\u51FA\u5F02\u5E38\u3002
fun Throwable.throwToApp()
+
Change Records
v1.1.0
added
Function Illustrate
\u5411 Hook APP \u629B\u51FA\u5F02\u5E38\u3002
\u4F7F\u7528 hasThrowable
\u5224\u65AD\u5F53\u524D\u662F\u5426\u5B58\u5728\u88AB\u629B\u51FA\u7684\u5F02\u5E38\u3002
\u4F7F\u7528 throwable
\u83B7\u53D6\u5F53\u524D\u8BBE\u7F6E\u7684\u65B9\u6CD5\u8C03\u7528\u629B\u51FA\u5F02\u5E38\u3002
\u4EC5\u4F1A\u5728\u56DE\u8C03\u65B9\u6CD5\u7684 MemberHookCreator.beforeHook
\u6216 MemberHookCreator.afterHook
\u4E2D\u751F\u6548\u3002
Pay Attention
\u8BBE\u7F6E\u540E\u4F1A\u540C\u65F6\u6267\u884C resultNull \u65B9\u6CD5\u5E76\u5C06\u5F02\u5E38\u629B\u51FA\u7ED9\u5F53\u524D Hook APP\u3002
Function Example
Hook \u8FC7\u7A0B\u4E2D\u7684\u5F02\u5E38\u4EC5\u4F1A\u4F5C\u7528\u4E8E (Xposed) \u5BBF\u4E3B\u73AF\u5883\uFF0C\u76EE\u6807 Hook APP \u4E0D\u4F1A\u53D7\u5230\u5F71\u54CD\u3002
\u82E5\u60F3\u5C06\u5F02\u5E38\u629B\u7ED9 Hook APP\uFF0C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u5982\u4E0B\u65B9\u6CD5\u3002
The following example
injectMember {
+ method {
+ // ...
+ }
+ beforeHook {
+ RuntimeException("Test Exception").throwToApp()
+ }
+}
+
Pay Attention
\u5411 Hook APP \u629B\u51FA\u5F02\u5E38\u4F1A\u5BF9\u5176\u66B4\u9732\u88AB Hook \u7684\u4E8B\u5B9E\uFF0C\u662F\u4E0D\u5B89\u5168\u7684\uFF0C\u5BB9\u6613\u88AB\u68C0\u6D4B\uFF0C\u8BF7\u6309\u5B9E\u9645\u573A\u666F\u5408\u7406\u4F7F\u7528\u3002
inline fun <reified T> result(): T?
+
Change Records
v1.0.75
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u8FD4\u56DE\u503CT
\u3002
Change Records
v1.0.66
added
v1.0.75
removed
Change Records
v1.0.66
added
v1.0.75
removed
inline fun <reified T> instance(): T
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u5BF9\u8C61
T
\u3002
Function Example
\u4F60\u53EF\u4EE5\u901A\u8FC7 instance
\u65B9\u6CD5\u8F7B\u677E\u4F7F\u7528\u6CDB\u578B cast
\u4E3A\u76EE\u6807\u5BF9\u8C61\u7684\u7C7B\u578B\u3002
The following example
instance<Activity>().finish()
+
fun args(): ArgsIndexCondition
+
Change Records
v1.0.75
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u53C2\u6570\u6570\u7EC4\u4E0B\u6807\u5B9E\u4F8B\u5316\u7C7B\u3002
fun args(index: Int): ArgsModifyer
+
Change Records
v1.0
first
v1.0.75
modified
\u9ED8\u8BA4\u503C index = 0
\u79FB\u52A8\u5230\u65B0\u7684\u4F7F\u7528\u65B9\u6CD5 args().first()
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u53C2\u6570\u5B9E\u4F8B\u5316\u5BF9\u8C61\u7C7B\u3002
Function Example
\u4F60\u53EF\u4EE5\u901A\u8FC7 args
\u65B9\u6CD5\u4FEE\u6539\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u53C2\u6570\u5185\u5BB9\u3002
\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 set
\u65B9\u6CD5\u8BBE\u7F6E param
\u4E3A\u4F60\u7684\u76EE\u6807\u5B9E\u4F8B\uFF0C\u63A5\u53D7 Any
\u7C7B\u578B\u3002
Pay Attention
\u8BF7\u786E\u4FDD param \u7C7B\u578B\u4E3A\u4F60\u7684\u76EE\u6807\u5B9E\u4F8B\u7C7B\u578B\u3002
The following example
args(index = 0).set("modify the value")
+
\u4F60\u53EF\u4EE5\u8FD9\u6837\u76F4\u63A5\u8BBE\u7F6E\u7B2C\u4E00\u4F4D param
\u7684\u503C\u3002
The following example
args().first().set("modify the value")
+
\u4F60\u8FD8\u53EF\u4EE5\u76F4\u63A5\u8BBE\u7F6E\u6700\u540E\u4E00\u4F4D param
\u7684\u503C\u3002
The following example
args().last().set("modify the value")
+
\u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 setNull
\u65B9\u6CD5\u8BBE\u7F6E param
\u4E3A\u7A7A\u3002
The following example
args(index = 1).setNull()
+
\u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 setTrue
\u65B9\u6CD5\u8BBE\u7F6E param
\u4E3A true
\u3002
Pay Attention
\u8BF7\u786E\u4FDD param \u7C7B\u578B\u4E3A Boolean\u3002
The following example
args(index = 1).setTrue()
+
\u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 setFalse
\u65B9\u6CD5\u8BBE\u7F6E param
\u4E3A false
\u3002
Pay Attention
\u8BF7\u786E\u4FDD param \u7C7B\u578B\u4E3A Boolean\u3002
The following example
args(index = 1).setFalse()
+
fun callOriginal(): Any?
+
fun <T> callOriginal(): T?
+
Change Records
v1.1.0
added
Function Illustrate
\u6267\u884C\u539F\u59CB
Member
\u3002
\u8C03\u7528\u81EA\u8EAB\u672A\u8FDB\u884C Hook \u7684\u539F\u59CB Member
\u5E76\u8C03\u7528\u539F\u59CB\u53C2\u6570\u6267\u884C\u3002
\u529F\u80FD\u5B9E\u4F8B
\u6B64\u65B9\u6CD5\u53EF\u4EE5 invoke
\u539F\u59CB\u672A\u7ECF Hook \u7684 Member
\u5BF9\u8C61\uFF0C\u53D6\u51B3\u4E8E\u539F\u59CB Member
\u7684\u53C2\u6570\u3002
\u8C03\u7528\u81EA\u8EAB\u539F\u59CB\u7684\u65B9\u6CD5\u4E0D\u4F1A\u518D\u7ECF\u8FC7\u5F53\u524D beforeHook
\u3001afterHook
\u4EE5\u53CA replaceUnit
\u3001replaceAny
\u3002
\u6BD4\u5982\u6211\u4EEC Hook \u7684\u8FD9\u4E2A\u65B9\u6CD5\u88AB\u8FD9\u6837\u8C03\u7528 test("test value")
\uFF0C\u4F7F\u7528\u6B64\u65B9\u6CD5\u4F1A\u8C03\u7528\u5176\u4E2D\u7684 "test value"
\u4F5C\u4E3A\u53C2\u6570\u3002
The following example
injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = StringType
+ }
+ afterHook {
+ // <\u65B9\u68481> \u4E0D\u4F7F\u7528\u6CDB\u578B\uFF0C\u4E0D\u83B7\u53D6\u65B9\u6CD5\u6267\u884C\u7ED3\u679C\uFF0C\u8C03\u7528\u5C06\u4F7F\u7528\u539F\u65B9\u6CD5\u4F20\u5165\u7684 args \u81EA\u52A8\u4F20\u53C2
+ callOriginal()
+ // <\u65B9\u68482> \u4F7F\u7528\u6CDB\u578B\uFF0C\u5DF2\u77E5\u65B9\u6CD5\u6267\u884C\u7ED3\u679C\u53C2\u6570\u7C7B\u578B\u8FDB\u884C cast
+ // \u5047\u8BBE\u8FD4\u56DE\u503C\u4E3A String\uFF0C\u5931\u8D25\u4F1A\u8FD4\u56DE null\uFF0C\u8C03\u7528\u5C06\u4F7F\u7528\u539F\u65B9\u6CD5\u4F20\u5165\u7684 args \u81EA\u52A8\u4F20\u53C2
+ val value = callOriginal<String>()
+ }
+}
+
fun invokeOriginal(vararg args: Any?): Any?
+
fun <T> invokeOriginal(vararg args: Any?): T?
+
Change Records
v1.0
first
v1.1.0
modified
\u4E0D\u518D\u9700\u8981\u4F7F\u7528 member.invokeOriginal
\u8FDB\u884C\u8C03\u7528
Function Illustrate
\u6267\u884C\u539F\u59CB
Member
\u3002
\u8C03\u7528\u81EA\u8EAB\u672A\u8FDB\u884C Hook \u7684\u539F\u59CB Member
\u5E76\u81EA\u5B9A\u4E49 args
\u6267\u884C\u3002
\u529F\u80FD\u5B9E\u4F8B
\u6B64\u65B9\u6CD5\u53EF\u4EE5 invoke
\u539F\u59CB\u672A\u7ECF Hook \u7684 Member
\u5BF9\u8C61\uFF0C\u53EF\u81EA\u5B9A\u4E49\u9700\u8981\u8C03\u7528\u7684\u53C2\u6570\u5185\u5BB9\u3002
\u8C03\u7528\u81EA\u8EAB\u539F\u59CB\u7684\u65B9\u6CD5\u4E0D\u4F1A\u518D\u7ECF\u8FC7\u5F53\u524D beforeHook
\u3001afterHook
\u4EE5\u53CA replaceUnit
\u3001replaceAny
\u3002
\u6BD4\u5982\u6211\u4EEC Hook \u7684\u8FD9\u4E2A\u65B9\u6CD5\u88AB\u8FD9\u6837\u8C03\u7528 test("test value")
\uFF0C\u4F7F\u7528\u6B64\u65B9\u6CD5\u53EF\u81EA\u5B9A\u4E49\u5176\u4E2D\u7684 args
\u4F5C\u4E3A\u53C2\u6570\u3002
The following example
injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = StringType
+ }
+ afterHook {
+ // <\u65B9\u68481> \u4E0D\u4F7F\u7528\u6CDB\u578B\uFF0C\u4E0D\u83B7\u53D6\u65B9\u6CD5\u6267\u884C\u7ED3\u679C
+ invokeOriginal("test value")
+ // <\u65B9\u68482> \u4F7F\u7528\u6CDB\u578B\uFF0C\u5DF2\u77E5\u65B9\u6CD5\u6267\u884C\u7ED3\u679C\u53C2\u6570\u7C7B\u578B\u8FDB\u884C cast\uFF0C\u5047\u8BBE\u8FD4\u56DE\u503C\u4E3A String\uFF0C\u5931\u8D25\u4F1A\u8FD4\u56DE null
+ val value = invokeOriginal<String>("test value")
+ }
+}
+
fun resultTrue()
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u65B9\u6CD5\u7684
result
\u8FD4\u56DE\u503C\u4E3Atrue
\u3002
Pay Attention
\u8BF7\u786E\u4FDD result \u7C7B\u578B\u4E3A Boolean\u3002
fun resultFalse()
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u65B9\u6CD5\u7684
result
\u8FD4\u56DE\u503C\u4E3Afalse
\u3002
Pay Attention
\u8BF7\u786E\u4FDD result \u7C7B\u578B\u4E3A Boolean\u3002
fun resultNull()
+
Change Records
v1.0
first
Function Illustrate
Notice
\u6B64\u65B9\u6CD5\u5C06\u5F3A\u5236\u8BBE\u7F6E Hook \u5BF9\u8C61\u65B9\u6CD5\u7684 result \u4E3A null\u3002
inner class ArgsIndexCondition internal constructor()
+
Change Records
v1.0.75
added
Function Illustrate
\u5BF9\u65B9\u6CD5\u53C2\u6570\u7684\u6570\u7EC4\u4E0B\u6807\u8FDB\u884C\u5B9E\u4F8B\u5316\u7C7B\u3002
fun first(): ArgsModifyer
+
Change Records
v1.0.75
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u53C2\u6570\u6570\u7EC4\u7B2C\u4E00\u4F4D\u3002
fun last(): ArgsModifyer
+
Change Records
v1.0.75
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684
method
\u6216constructor
\u7684\u53C2\u6570\u6570\u7EC4\u6700\u540E\u4E00\u4F4D\u3002
inner class ArgsModifyer internal constructor(private val index: Int)
+
Change Records
v1.0
first
Function Illustrate
\u5BF9\u65B9\u6CD5\u53C2\u6570\u7684\u4FEE\u6539\u8FDB\u884C\u5B9E\u4F8B\u5316\u7C7B\u3002
fun <T> cast(): T?
+
Change Records
v1.0.66
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A of
cast
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61
T
\u3002
fun byte(): Byte?
+
Change Records
v1.0.68
added
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Byte\u3002
fun int(): Int
+
Change Records
v1.0.66
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofInt
int
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Int\u3002
fun long(): Long
+
Change Records
v1.0.66
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofLong
long
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Long\u3002
fun short(): Short
+
Change Records
v1.0.66
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofShort
short
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Short\u3002
fun double(): Double
+
Change Records
v1.0.66
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofDouble
double
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Double\u3002
fun float(): Float
+
Change Records
v1.0.66
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofFloat
float
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Float\u3002
fun string(): String
+
Change Records
v1.0.66
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofString
string
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 String\u3002
fun char(): Char
+
Change Records
v1.0.68
added
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Char\u3002
fun boolean(): Boolean
+
Change Records
v1.0.66
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A ofBoolean
boolean
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Boolean\u3002
fun any(): Any?
+
Change Records
v1.0.77
added
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Any\u3002
inline fun <reified T> array(): Array<T>
+
Change Records
v1.0.68
added
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Array\u3002
inline fun <reified T> list(): List<T>
+
Change Records
v1.0.68
added
Function Illustrate
\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 List\u3002
fun <T> set(any: T?)
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u3002
fun setNull()
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u4E3A
null
\u3002
fun setTrue()
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u4E3A
true
\u3002
Pay Attention
\u8BF7\u786E\u4FDD\u76EE\u6807\u5BF9\u8C61\u7684\u7C7B\u578B\u662F Boolean\u3002
fun setFalse()
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u4E3A
false
\u3002
Pay Attention
\u8BF7\u786E\u4FDD\u76EE\u6807\u5BF9\u8C61\u7684\u7C7B\u578B\u662F Boolean\u3002
class HookResources internal constructor(var instance: YukiResources?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,6),l=[n];function r(t,p){return o(),e("div",null,l)}const i=s(c,[["render",r],["__file","HookResources.html.vue"]]);export{i as default}; diff --git a/docs/assets/HookResources.html.b888e8b6.js b/docs/assets/HookResources.html.b888e8b6.js new file mode 100644 index 00000000..7b4a84dc --- /dev/null +++ b/docs/assets/HookResources.html.b888e8b6.js @@ -0,0 +1,2 @@ +import{_ as s,o,c as e,a as n}from"./app.fb8271cf.js";const a={},c=n(`\u521B\u5EFA\u4E00\u4E2A\u5F53\u524D Hook \u7684
YukiResources
\u63A5\u7BA1\u7C7B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class HookResources internal constructor(var instance: YukiResources?)
+
Change Records
v1.0.80
added
Function Illustrate
`,7),t=[c];function r(l,p){return o(),e("div",null,t)}const u=s(a,[["render",r],["__file","HookResources.html.vue"]]);export{u as default}; diff --git a/docs/assets/IYukiHookXposedInit.html.4813ba4f.js b/docs/assets/IYukiHookXposedInit.html.4813ba4f.js new file mode 100644 index 00000000..2eb2b3bc --- /dev/null +++ b/docs/assets/IYukiHookXposedInit.html.4813ba4f.js @@ -0,0 +1,5 @@ +import{_ as o,o as e,c as s,a as n}from"./app.fb8271cf.js";const p={},a=n(`\u521B\u5EFA\u4E00\u4E2A\u5F53\u524D Hook \u7684
YukiResources
\u63A5\u7BA1\u7C7B\u3002
interface IYukiHookXposedInit
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u4F5C\u5E9F
\u4F5C\u5E9F\u4E86 \u540D\u79F0\u4F46\u4FDD\u7559\u63A5\u53E3YukiHookXposedInitProxy
\u8F6C\u79FB\u5230 IYukiHookXposedInit
\u65B0\u540D\u79F0
\u529F\u80FD\u63CF\u8FF0
YukiHookAPI \u7684 Xposed \u88C5\u8F7D API \u8C03\u7528\u63A5\u53E3\u3002
fun onInit()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u914D\u7F6E
YukiHookAPI.Configs
\u7684\u521D\u59CB\u5316\u65B9\u6CD5\u3002
\u7279\u522B\u6CE8\u610F
\u5728\u8FD9\u91CC\u53EA\u80FD\u8FDB\u884C\u521D\u59CB\u5316\u914D\u7F6E\uFF0C\u4E0D\u80FD\u8FDB\u884C Hook \u64CD\u4F5C\u3002
\u6B64\u65B9\u6CD5\u53EF\u9009\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u9009\u62E9\u4E0D\u5BF9 YukiHookAPI.Configs \u8FDB\u884C\u914D\u7F6E\u3002
fun onHook()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
Xposed API \u7684\u6A21\u5757\u88C5\u8F7D\u8C03\u7528\u5165\u53E3\u65B9\u6CD5\u3002
fun onXposedEvent()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C Xposed \u539F\u751F\u88C5\u8F7D\u4E8B\u4EF6\u3002
\u82E5\u4F60\u7684 Hook \u4E8B\u4EF6\u4E2D\u5B58\u5728\u9700\u8981\u517C\u5BB9\u7684\u539F\u751F Xposed \u529F\u80FD\uFF0C\u53EF\u5728\u8FD9\u91CC\u5B9E\u73B0\u3002
\u8BF7\u5728\u8FD9\u91CC\u4F7F\u7528 YukiXposedEvent \u521B\u5EFA\u56DE\u8C03\u4E8B\u4EF6\u76D1\u542C\u3002
\u53EF\u76D1\u542C\u7684\u4E8B\u4EF6\u5982\u4E0B\uFF1A
YukiXposedEvent.onInitZygote
YukiXposedEvent.onHandleLoadPackage
YukiXposedEvent.onHandleInitPackageResources
\u7279\u522B\u6CE8\u610F
\u6B64\u63A5\u53E3\u4EC5\u4F9B\u76D1\u542C\u548C\u5B9E\u73B0\u539F\u751F Xposed API \u7684\u529F\u80FD\uFF0C\u8BF7\u4E0D\u8981\u5728\u8FD9\u91CC\u64CD\u4F5C YukiHookAPI\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230 IYukiHookXposedInit
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
interface IYukiHookXposedInit
+
Change Records
v1.0
first
v1.0.80
modified
deprecated
\u4F5C\u5E9F\u4E86 \u540D\u79F0\u4F46\u4FDD\u7559\u63A5\u53E3YukiHookXposedInitProxy
\u8F6C\u79FB\u5230 IYukiHookXposedInit
\u65B0\u540D\u79F0
Function Illustrate
YukiHookAPI \u7684 Xposed \u88C5\u8F7D API \u8C03\u7528\u63A5\u53E3\u3002
fun onInit()
+
Change Records
v1.0.5
added
Function Illustrate
\u914D\u7F6E
YukiHookAPI.Configs
\u7684\u521D\u59CB\u5316\u65B9\u6CD5\u3002
Pay Attention
\u5728\u8FD9\u91CC\u53EA\u80FD\u8FDB\u884C\u521D\u59CB\u5316\u914D\u7F6E\uFF0C\u4E0D\u80FD\u8FDB\u884C Hook \u64CD\u4F5C\u3002
\u6B64\u65B9\u6CD5\u53EF\u9009\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u9009\u62E9\u4E0D\u5BF9 YukiHookAPI.Configs \u8FDB\u884C\u914D\u7F6E\u3002
fun onHook()
+
Change Records
v1.0
first
Function Illustrate
Xposed API \u7684\u6A21\u5757\u88C5\u8F7D\u8C03\u7528\u5165\u53E3\u65B9\u6CD5\u3002
fun onXposedEvent()
+
Change Records
v1.0.80
added
Function Illustrate
\u76D1\u542C Xposed \u539F\u751F\u88C5\u8F7D\u4E8B\u4EF6\u3002
\u82E5\u4F60\u7684 Hook \u4E8B\u4EF6\u4E2D\u5B58\u5728\u9700\u8981\u517C\u5BB9\u7684\u539F\u751F Xposed \u529F\u80FD\uFF0C\u53EF\u5728\u8FD9\u91CC\u5B9E\u73B0\u3002
\u8BF7\u5728\u8FD9\u91CC\u4F7F\u7528 YukiXposedEvent \u521B\u5EFA\u56DE\u8C03\u4E8B\u4EF6\u76D1\u542C\u3002
\u53EF\u76D1\u542C\u7684\u4E8B\u4EF6\u5982\u4E0B\uFF1A
YukiXposedEvent.onInitZygote
YukiXposedEvent.onHandleLoadPackage
YukiXposedEvent.onHandleInitPackageResources
Pay Attention
\u6B64\u63A5\u53E3\u4EC5\u4F9B\u76D1\u542C\u548C\u5B9E\u73B0\u539F\u751F Xposed API \u7684\u529F\u80FD\uFF0C\u8BF7\u4E0D\u8981\u5728\u8FD9\u91CC\u64CD\u4F5C YukiHookAPI\u3002
Change Records
v1.0
first
v1.0.80
deprecated
\u8BF7\u8F6C\u79FB\u5230 IYukiHookXposedInit
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
annotation class InjectYukiHookWithXposed(
+ val sourcePath: String,
+ val modulePackageName: String,
+ val entryClassName: String,
+ val isUsingResourcesHook: Boolean
+)
+
Change Records
v1.0
first
v1.0.80
modified
\u65B0\u589E entryClassName
\u53C2\u6570
v1.0.92
modified
\u65B0\u589E isUsingResourcesHook
\u53C2\u6570
Function Illustrate
\u6807\u8BC6
YukiHookAPI
\u6CE8\u5165 Xposed \u5165\u53E3\u7684\u7C7B\u6CE8\u89E3\u3002
Function Example
\u8BE6\u60C5\u8BF7\u53C2\u8003 InjectYukiHookWithXposed Annotation\u3002
`,13),p=[t];function l(c,r){return o(),n("div",null,p)}const d=s(e,[["render",l],["__file","InjectYukiHookWithXposed.html.vue"]]);export{d as default}; diff --git a/docs/assets/InjectYukiHookWithXposed.html.cf9b500d.js b/docs/assets/InjectYukiHookWithXposed.html.cf9b500d.js new file mode 100644 index 00000000..d1e87a41 --- /dev/null +++ b/docs/assets/InjectYukiHookWithXposed.html.cf9b500d.js @@ -0,0 +1 @@ +const o=JSON.parse('{"key":"v-30f3ba1e","path":"/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html","title":"InjectYukiHookWithXposed - annotation","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1663862409000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.md"}');export{o as data}; diff --git a/docs/assets/InjectYukiHookWithXposed.html.ecb261b1.js b/docs/assets/InjectYukiHookWithXposed.html.ecb261b1.js new file mode 100644 index 00000000..f30992e4 --- /dev/null +++ b/docs/assets/InjectYukiHookWithXposed.html.ecb261b1.js @@ -0,0 +1,7 @@ +import{_ as s,o,c as n,a}from"./app.fb8271cf.js";const e={},p=a(`annotation class InjectYukiHookWithXposed(
+ val sourcePath: String,
+ val modulePackageName: String,
+ val entryClassName: String,
+ val isUsingResourcesHook: Boolean
+)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u65B0\u589E entryClassName
\u53C2\u6570
v1.0.92
\u4FEE\u6539
\u65B0\u589E isUsingResourcesHook
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
\u6807\u8BC6
YukiHookAPI
\u6CE8\u5165 Xposed \u5165\u53E3\u7684\u7C7B\u6CE8\u89E3\u3002
\u529F\u80FD\u793A\u4F8B
\u8BE6\u60C5\u8BF7\u53C2\u8003 InjectYukiHookWithXposed \u6CE8\u89E3\u3002
`,12),l=[p];function c(t,r){return o(),n("div",null,l)}const d=s(e,[["render",c],["__file","InjectYukiHookWithXposed.html.vue"]]);export{d as default}; diff --git a/docs/assets/LoggerFactory.html.72d1861a.js b/docs/assets/LoggerFactory.html.72d1861a.js new file mode 100644 index 00000000..230cdc71 --- /dev/null +++ b/docs/assets/LoggerFactory.html.72d1861a.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-004a009e","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html","title":"LoggerFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"LoggerType - class","slug":"loggertype-class","link":"#loggertype-class","children":[{"level":3,"title":"LOGD - enum","slug":"logd-enum","link":"#logd-enum","children":[]},{"level":3,"title":"XPOSEDBRIDGE - enum","slug":"xposedbridge-enum","link":"#xposedbridge-enum","children":[]},{"level":3,"title":"SCOPE - enum","slug":"scope-enum","link":"#scope-enum","children":[]},{"level":3,"title":"BOTH - enum","slug":"both-enum","link":"#both-enum","children":[]}]},{"level":2,"title":"YukiHookLogger - object","slug":"yukihooklogger-object","link":"#yukihooklogger-object","children":[{"level":3,"title":"contents - field","slug":"contents-field","link":"#contents-field","children":[]},{"level":3,"title":"clear - method","slug":"clear-method","link":"#clear-method","children":[]},{"level":3,"title":"saveToFile - method","slug":"savetofile-method","link":"#savetofile-method","children":[]},{"level":3,"title":"Configs - object","slug":"configs-object","link":"#configs-object","children":[]}]},{"level":2,"title":"loggerD - method","slug":"loggerd-method","link":"#loggerd-method","children":[]},{"level":2,"title":"loggerI - method","slug":"loggeri-method","link":"#loggeri-method","children":[]},{"level":2,"title":"loggerW - method","slug":"loggerw-method","link":"#loggerw-method","children":[]},{"level":2,"title":"loggerE - method","slug":"loggere-method","link":"#loggere-method","children":[]}],"git":{"updatedTime":1663835655000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.md"}');export{e as data}; diff --git a/docs/assets/LoggerFactory.html.84495d50.js b/docs/assets/LoggerFactory.html.84495d50.js new file mode 100644 index 00000000..4d72d152 --- /dev/null +++ b/docs/assets/LoggerFactory.html.84495d50.js @@ -0,0 +1,27 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const n={},l=a(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0
first
Function Illustrate
\u8FD9\u662F
YukiHookAPI
\u7684\u65E5\u5FD7\u5C01\u88C5\u7C7B\uFF0C\u53EF\u5B9E\u73B0\u540C\u65F6\u5411Logcat
\u548CXposedBridge.log
\u6253\u5370\u65E5\u5FD7\u7684\u529F\u80FD\u3002
enum class LoggerType
+
Change Records
v1.1.0
added
Function Illustrate
\u9700\u8981\u6253\u5370\u7684\u65E5\u5FD7\u7C7B\u578B\u3002
\u51B3\u5B9A\u4E8E\u6A21\u5757\u4E0E (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u7684\u6253\u5370\u65B9\u5F0F\u3002
LOGD
+
Change Records
v1.1.0
added
Function Illustrate
\u4EC5\u4F7F\u7528
android.util.Log
\u3002
XPOSEDBRIDGE
+
Change Records
v1.1.0
added
Function Illustrate
\u4EC5\u4F7F\u7528
XposedBridge.log
\u3002
Pay Attention
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528\uFF0C\u6A21\u5757\u73AF\u5883\u5C06\u4E0D\u751F\u6548\u3002
SCOPE
+
Change Records
v1.1.0
added
Function Illustrate
\u5206\u533A\u4F7F\u7528\u3002
(Xposed) \u5BBF\u4E3B\u73AF\u5883\u4EC5\u4F7F\u7528 XPOSEDBRIDGE
\u3002
\u6A21\u5757\u73AF\u5883\u4EC5\u4F7F\u7528 LOGD
\u3002
BOTH
+
Change Records
v1.1.0
added
Function Illustrate
\u540C\u65F6\u4F7F\u7528\u3002
(Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528 LOGD
\u4E0E XPOSEDBRIDGE
\u3002
\u6A21\u5757\u73AF\u5883\u4EC5\u4F7F\u7528 LOGD
\u3002
object YukiHookLogger
+
Change Records
v1.1.0
added
Function Illustrate
\u8C03\u8BD5\u65E5\u5FD7\u5B9E\u73B0\u7C7B\u3002
val contents: String
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D\u65E5\u5FD7\u6587\u4EF6\u5185\u5BB9\u3002
\u5982\u679C\u5F53\u524D\u6CA1\u6709\u5DF2\u8BB0\u5F55\u7684\u65E5\u5FD7\u4F1A\u8FD4\u56DE\u7A7A\u5B57\u7B26\u4E32\u3002
fun clear()
+
Change Records
v1.1.0
added
Function Illustrate
\u6E05\u9664\u5168\u90E8\u5DF2\u8BB0\u5F55\u7684\u65E5\u5FD7\u3002
fun saveToFile(fileName: String)
+
Change Records
v1.1.0
added
Function Illustrate
\u4FDD\u5B58\u5F53\u524D\u65E5\u5FD7\u5230\u6587\u4EF6\u3002
\u82E5\u5F53\u524D\u672A\u5F00\u542F Configs.isRecord
\u6216\u8BB0\u5F55\u4E3A\u7A7A\u5219\u4E0D\u4F1A\u8FDB\u884C\u4EFB\u4F55\u64CD\u4F5C\u3002
\u65E5\u5FD7\u6587\u4EF6\u4F1A\u8FFD\u52A0\u5230 fileName
\u7684\u6587\u4EF6\u7ED3\u5C3E\uFF0C\u82E5\u6587\u4EF6\u4E0D\u5B58\u5728\u4F1A\u81EA\u52A8\u521B\u5EFA\u3002
Pay Attention
\u6587\u4EF6\u8BFB\u5199\u6743\u9650\u53D6\u51B3\u4E8E\u5F53\u524D\u5BBF\u4E3B\u5DF2\u83B7\u53D6\u7684\u6743\u9650\u3002
object Configs
+
Change Records
v1.1.0
added
Function Illustrate
\u914D\u7F6E
YukiHookLogger
\u3002
const val TAG: Int
+
Change Records
v1.1.0
added
Function Illustrate
\u6807\u7B7E\u3002
const val PRIORITY: Int
+
Change Records
v1.1.0
added
Function Illustrate
\u4F18\u5148\u7EA7\u3002
const val PACKAGE_NAME: Int
+
Change Records
v1.1.0
added
Function Illustrate
\u5F53\u524D\u5BBF\u4E3B\u7684\u5305\u540D\u3002
const val USER_ID: Int
+
Change Records
v1.1.0
added
Function Illustrate
\u5F53\u524D\u5BBF\u4E3B\u7684\u7528\u6237 ID (\u4E3B\u7528\u6237\u4E0D\u663E\u793A)\u3002
var isEnable: Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u662F\u5426\u542F\u7528\u8C03\u8BD5\u65E5\u5FD7\u7684\u8F93\u51FA\u529F\u80FD\u3002
\u5173\u95ED\u540E\u5C06\u4F1A\u505C\u7528 YukiHookAPI
\u5BF9\u5168\u90E8\u65E5\u5FD7\u7684\u8F93\u51FA\u3002
\u4F46\u662F\u4E0D\u5F71\u54CD\u5F53\u4F60\u624B\u52A8\u8C03\u7528\u4E0B\u9762\u8FD9\u4E9B\u65B9\u6CD5\u8F93\u51FA\u65E5\u5FD7\u3002
loggerD
\u3001loggerI
\u3001loggerW
\u3001loggerE
\u3002
\u5F53 isEnable
\u5173\u95ED\u540E YukiHookAPI.Configs.isDebug
\u4E5F\u5C06\u540C\u65F6\u5173\u95ED\u3002
var isRecord: Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u662F\u5426\u542F\u7528\u8C03\u8BD5\u65E5\u5FD7\u7684\u8BB0\u5F55\u529F\u80FD\u3002
\u5F00\u542F\u540E\u5C06\u4F1A\u5728\u5185\u5B58\u4E2D\u8BB0\u5F55\u5168\u90E8\u53EF\u7528\u7684\u65E5\u5FD7\u548C\u5F02\u5E38\u5806\u6808\u3002
\u9700\u8981\u540C\u65F6\u542F\u7528 isEnable \u624D\u80FD\u6709\u6548\u3002
Pay Attention
\u8FC7\u91CF\u7684\u65E5\u5FD7\u53EF\u80FD\u4F1A\u5BFC\u81F4\u5BBF\u4E3B\u8FD0\u884C\u7F13\u6162\u6216\u9020\u6210\u9891\u7E41 GC\u3002
\u5F00\u542F\u540E\u4F60\u53EF\u4EE5\u8C03\u7528 YukiHookLogger.saveToFile \u5B9E\u65F6\u4FDD\u5B58\u65E5\u5FD7\u5230\u6587\u4EF6\u6216\u4F7F\u7528 YukiHookLogger.contents \u83B7\u53D6\u5B9E\u65F6\u65E5\u5FD7\u6587\u4EF6\u3002
var tag: String
+
Change Records
v1.1.0
added
Function Illustrate
\u8FD9\u662F\u4E00\u4E2A\u8C03\u8BD5\u65E5\u5FD7\u7684\u5168\u5C40\u6807\u8BC6\u3002
\u9ED8\u8BA4\u6587\u6848\u4E3A YukiHookAPI
\u3002
\u4F60\u53EF\u4EE5\u4FEE\u6539\u4E3A\u4F60\u81EA\u5DF1\u7684\u6587\u6848\u3002
fun elements(vararg item: Int)
+
Change Records
v1.1.0
added
Function Illustrate
\u81EA\u5B9A\u4E49\u8C03\u8BD5\u65E5\u5FD7\u5BF9\u5916\u663E\u793A\u7684\u5143\u7D20\u3002
\u53EA\u5BF9\u65E5\u5FD7\u8BB0\u5F55\u548C XposedBridge.log
\u751F\u6548\u3002
\u65E5\u5FD7\u5143\u7D20\u7684\u6392\u5217\u5C06\u6309\u7167\u4F60\u5728 item
\u4E2D\u8BBE\u7F6E\u7684\u987A\u5E8F\u8FDB\u884C\u663E\u793A\u3002
\u4F60\u8FD8\u53EF\u4EE5\u7559\u7A7A item
\u4EE5\u4E0D\u663E\u793A\u9664\u65E5\u5FD7\u5185\u5BB9\u5916\u7684\u5168\u90E8\u5143\u7D20\u3002
\u53EF\u7528\u7684\u5143\u7D20\u6709\uFF1ATAG
\u3001PRIORITY
\u3001PACKAGE_NAME
\u3001USER_ID
\u3002
Function Example
\u6253\u5370\u7684\u65E5\u5FD7\u6837\u5F0F\u5C06\u6309\u7167\u4F60\u8BBE\u7F6E\u7684\u6392\u5217\u987A\u5E8F\u548C\u5143\u7D20\u5185\u5BB9\u8FDB\u884C\u3002
The following example
elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+
\u4EE5\u4E0A\u5185\u5BB9\u5B9A\u4E49\u7684\u65E5\u5FD7\u5C06\u663E\u793A\u4E3A\u5982\u4E0B\u6837\u5F0F\u3002
The following example
[YukiHookAPI][D][com.demo.test][999]--> This is a log
+
\u5982\u679C\u6211\u4EEC\u8C03\u6574\u5143\u7D20\u987A\u5E8F\u4EE5\u53CA\u51CF\u5C11\u4E2A\u6570\uFF0C\u90A3\u4E48\u7ED3\u679C\u53C8\u4F1A\u4E0D\u4E00\u6837\u3002
The following example
elements(PACKAGE_NAME, USER_ID, PRIORITY)
+
\u4EE5\u4E0A\u5185\u5BB9\u5B9A\u4E49\u7684\u65E5\u5FD7\u5C06\u663E\u793A\u4E3A\u5982\u4E0B\u6837\u5F0F\u3002
The following example
[com.demo.test][999][D]--> This is a log
+
fun loggerD(tag: String, msg: String, type: LoggerType)
+
Change Records
v1.0
first
v1.1.0
modified
\u65B0\u589E type
\u53C2\u6570
Function Illustrate
\u5411
Logcat
\u548CXposedBridge
\u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522BD
\u3002
tag
\u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag
\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002
fun loggerI(tag: String, msg: String, type: LoggerType)
+
Change Records
v1.0
first
v1.1.0
modified
\u65B0\u589E type
\u53C2\u6570
Function Illustrate
\u5411
Logcat
\u548CXposedBridge
\u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522BI
\u3002
tag
\u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag
\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002
fun loggerW(tag: String, msg: String, type: LoggerType)
+
Change Records
v1.0
first
v1.1.0
modified
\u65B0\u589E type
\u53C2\u6570
Function Illustrate
\u5411
Logcat
\u548CXposedBridge
\u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522BW
\u3002
tag
\u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag
\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002
fun loggerE(tag: String, msg: String, e: Throwable?, type: LoggerType)
+
Change Records
v1.0
first
v1.1.0
modified
\u65B0\u589E type
\u53C2\u6570
Function Illustrate
\u5411
Logcat
\u548CXposedBridge
\u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522BE
\uFF0C\u53EF\u643A\u5E26e
\u5F02\u5E38\u4FE1\u606F\uFF0C\u5C06\u6253\u5370\u5F02\u5E38\u5806\u6808\u3002
tag
\u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag
\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F
YukiHookAPI
\u7684\u65E5\u5FD7\u5C01\u88C5\u7C7B\uFF0C\u53EF\u5B9E\u73B0\u540C\u65F6\u5411Logcat
\u548CXposedBridge.log
\u6253\u5370\u65E5\u5FD7\u7684\u529F\u80FD\u3002
enum class LoggerType
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u9700\u8981\u6253\u5370\u7684\u65E5\u5FD7\u7C7B\u578B\u3002
\u51B3\u5B9A\u4E8E\u6A21\u5757\u4E0E (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u7684\u6253\u5370\u65B9\u5F0F\u3002
LOGD
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EC5\u4F7F\u7528
android.util.Log
\u3002
XPOSEDBRIDGE
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EC5\u4F7F\u7528
XposedBridge.log
\u3002
\u7279\u522B\u6CE8\u610F
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528\uFF0C\u6A21\u5757\u73AF\u5883\u5C06\u4E0D\u751F\u6548\u3002
SCOPE
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5206\u533A\u4F7F\u7528\u3002
(Xposed) \u5BBF\u4E3B\u73AF\u5883\u4EC5\u4F7F\u7528 XPOSEDBRIDGE
\u3002
\u6A21\u5757\u73AF\u5883\u4EC5\u4F7F\u7528 LOGD
\u3002
BOTH
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u540C\u65F6\u4F7F\u7528\u3002
(Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528 LOGD
\u4E0E XPOSEDBRIDGE
\u3002
\u6A21\u5757\u73AF\u5883\u4EC5\u4F7F\u7528 LOGD
\u3002
object YukiHookLogger
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8C03\u8BD5\u65E5\u5FD7\u5B9E\u73B0\u7C7B\u3002
val contents: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D\u65E5\u5FD7\u6587\u4EF6\u5185\u5BB9\u3002
\u5982\u679C\u5F53\u524D\u6CA1\u6709\u5DF2\u8BB0\u5F55\u7684\u65E5\u5FD7\u4F1A\u8FD4\u56DE\u7A7A\u5B57\u7B26\u4E32\u3002
fun clear()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6E05\u9664\u5168\u90E8\u5DF2\u8BB0\u5F55\u7684\u65E5\u5FD7\u3002
fun saveToFile(fileName: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4FDD\u5B58\u5F53\u524D\u65E5\u5FD7\u5230\u6587\u4EF6\u3002
\u82E5\u5F53\u524D\u672A\u5F00\u542F Configs.isRecord
\u6216\u8BB0\u5F55\u4E3A\u7A7A\u5219\u4E0D\u4F1A\u8FDB\u884C\u4EFB\u4F55\u64CD\u4F5C\u3002
\u65E5\u5FD7\u6587\u4EF6\u4F1A\u8FFD\u52A0\u5230 fileName
\u7684\u6587\u4EF6\u7ED3\u5C3E\uFF0C\u82E5\u6587\u4EF6\u4E0D\u5B58\u5728\u4F1A\u81EA\u52A8\u521B\u5EFA\u3002
\u7279\u522B\u6CE8\u610F
\u6587\u4EF6\u8BFB\u5199\u6743\u9650\u53D6\u51B3\u4E8E\u5F53\u524D\u5BBF\u4E3B\u5DF2\u83B7\u53D6\u7684\u6743\u9650\u3002
object Configs
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u914D\u7F6E
YukiHookLogger
\u3002
const val TAG: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6807\u7B7E\u3002
const val PRIORITY: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4F18\u5148\u7EA7\u3002
const val PACKAGE_NAME: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D\u5BBF\u4E3B\u7684\u5305\u540D\u3002
const val USER_ID: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D\u5BBF\u4E3B\u7684\u7528\u6237 ID (\u4E3B\u7528\u6237\u4E0D\u663E\u793A)\u3002
var isEnable: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528\u8C03\u8BD5\u65E5\u5FD7\u7684\u8F93\u51FA\u529F\u80FD\u3002
\u5173\u95ED\u540E\u5C06\u4F1A\u505C\u7528 YukiHookAPI
\u5BF9\u5168\u90E8\u65E5\u5FD7\u7684\u8F93\u51FA\u3002
\u4F46\u662F\u4E0D\u5F71\u54CD\u5F53\u4F60\u624B\u52A8\u8C03\u7528\u4E0B\u9762\u8FD9\u4E9B\u65B9\u6CD5\u8F93\u51FA\u65E5\u5FD7\u3002
loggerD
\u3001loggerI
\u3001loggerW
\u3001loggerE
\u3002
\u5F53 isEnable
\u5173\u95ED\u540E YukiHookAPI.Configs.isDebug
\u4E5F\u5C06\u540C\u65F6\u5173\u95ED\u3002
var isRecord: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528\u8C03\u8BD5\u65E5\u5FD7\u7684\u8BB0\u5F55\u529F\u80FD\u3002
\u5F00\u542F\u540E\u5C06\u4F1A\u5728\u5185\u5B58\u4E2D\u8BB0\u5F55\u5168\u90E8\u53EF\u7528\u7684\u65E5\u5FD7\u548C\u5F02\u5E38\u5806\u6808\u3002
\u9700\u8981\u540C\u65F6\u542F\u7528 isEnable \u624D\u80FD\u6709\u6548\u3002
\u7279\u522B\u6CE8\u610F
\u8FC7\u91CF\u7684\u65E5\u5FD7\u53EF\u80FD\u4F1A\u5BFC\u81F4\u5BBF\u4E3B\u8FD0\u884C\u7F13\u6162\u6216\u9020\u6210\u9891\u7E41 GC\u3002
\u5F00\u542F\u540E\u4F60\u53EF\u4EE5\u8C03\u7528 YukiHookLogger.saveToFile \u5B9E\u65F6\u4FDD\u5B58\u65E5\u5FD7\u5230\u6587\u4EF6\u6216\u4F7F\u7528 YukiHookLogger.contents \u83B7\u53D6\u5B9E\u65F6\u65E5\u5FD7\u6587\u4EF6\u3002
var tag: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u4E00\u4E2A\u8C03\u8BD5\u65E5\u5FD7\u7684\u5168\u5C40\u6807\u8BC6\u3002
\u9ED8\u8BA4\u6587\u6848\u4E3A YukiHookAPI
\u3002
\u4F60\u53EF\u4EE5\u4FEE\u6539\u4E3A\u4F60\u81EA\u5DF1\u7684\u6587\u6848\u3002
fun elements(vararg item: Int)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u81EA\u5B9A\u4E49\u8C03\u8BD5\u65E5\u5FD7\u5BF9\u5916\u663E\u793A\u7684\u5143\u7D20\u3002
\u53EA\u5BF9\u65E5\u5FD7\u8BB0\u5F55\u548C XposedBridge.log
\u751F\u6548\u3002
\u65E5\u5FD7\u5143\u7D20\u7684\u6392\u5217\u5C06\u6309\u7167\u4F60\u5728 item
\u4E2D\u8BBE\u7F6E\u7684\u987A\u5E8F\u8FDB\u884C\u663E\u793A\u3002
\u4F60\u8FD8\u53EF\u4EE5\u7559\u7A7A item
\u4EE5\u4E0D\u663E\u793A\u9664\u65E5\u5FD7\u5185\u5BB9\u5916\u7684\u5168\u90E8\u5143\u7D20\u3002
\u53EF\u7528\u7684\u5143\u7D20\u6709\uFF1ATAG
\u3001PRIORITY
\u3001PACKAGE_NAME
\u3001USER_ID
\u3002
\u529F\u80FD\u793A\u4F8B
\u6253\u5370\u7684\u65E5\u5FD7\u6837\u5F0F\u5C06\u6309\u7167\u4F60\u8BBE\u7F6E\u7684\u6392\u5217\u987A\u5E8F\u548C\u5143\u7D20\u5185\u5BB9\u8FDB\u884C\u3002
\u793A\u4F8B\u5982\u4E0B
elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+
\u4EE5\u4E0A\u5185\u5BB9\u5B9A\u4E49\u7684\u65E5\u5FD7\u5C06\u663E\u793A\u4E3A\u5982\u4E0B\u6837\u5F0F\u3002
\u793A\u4F8B\u5982\u4E0B
[YukiHookAPI][D][com.demo.test][999]--> This is a log
+
\u5982\u679C\u6211\u4EEC\u8C03\u6574\u5143\u7D20\u987A\u5E8F\u4EE5\u53CA\u51CF\u5C11\u4E2A\u6570\uFF0C\u90A3\u4E48\u7ED3\u679C\u53C8\u4F1A\u4E0D\u4E00\u6837\u3002
\u793A\u4F8B\u5982\u4E0B
elements(PACKAGE_NAME, USER_ID, PRIORITY)
+
\u4EE5\u4E0A\u5185\u5BB9\u5B9A\u4E49\u7684\u65E5\u5FD7\u5C06\u663E\u793A\u4E3A\u5982\u4E0B\u6837\u5F0F\u3002
\u793A\u4F8B\u5982\u4E0B
[com.demo.test][999][D]--> This is a log
+
fun loggerD(tag: String, msg: String, type: LoggerType)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u65B0\u589E type
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
\u5411
Logcat
\u548CXposedBridge
\u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522BD
\u3002
tag
\u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag
\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002
fun loggerI(tag: String, msg: String, type: LoggerType)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u65B0\u589E type
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
\u5411
Logcat
\u548CXposedBridge
\u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522BI
\u3002
tag
\u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag
\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002
fun loggerW(tag: String, msg: String, type: LoggerType)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u65B0\u589E type
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
\u5411
Logcat
\u548CXposedBridge
\u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522BW
\u3002
tag
\u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag
\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002
fun loggerE(tag: String, msg: String, e: Throwable?, type: LoggerType)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u65B0\u589E type
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
\u5411
Logcat
\u548CXposedBridge
\u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522BE
\uFF0C\u53EF\u643A\u5E26e
\u5F02\u5E38\u4FE1\u606F\uFF0C\u5C06\u6253\u5370\u5F02\u5E38\u5806\u6808\u3002
tag
\u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag
\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MemberRules internal constructor(internal val rulesData: MemberRulesData) : BaseRules
+
Change Records
v1.1.0
added
Function Illustrate
Member
\u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Member
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
`,14),t=[l];function r(c,p){return e(),o("div",null,t)}const d=s(n,[["render",r],["__file","MemberRules.html.vue"]]);export{d as default}; diff --git a/docs/assets/MemberRules.html.a071b3c6.js b/docs/assets/MemberRules.html.a071b3c6.js new file mode 100644 index 00000000..061bfb09 --- /dev/null +++ b/docs/assets/MemberRules.html.a071b3c6.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-77f11cf9","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html","title":"MemberRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.md"}');export{e as data}; diff --git a/docs/assets/MemberRules.html.b3e5d297.js b/docs/assets/MemberRules.html.b3e5d297.js new file mode 100644 index 00000000..cc7f351a --- /dev/null +++ b/docs/assets/MemberRules.html.b3e5d297.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2cab152c","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html","title":"MemberRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.md"}');export{e as data}; diff --git a/docs/assets/MemberRules.html.fbc5b06f.js b/docs/assets/MemberRules.html.fbc5b06f.js new file mode 100644 index 00000000..b2510ed3 --- /dev/null +++ b/docs/assets/MemberRules.html.fbc5b06f.js @@ -0,0 +1,3 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const n={},l=a(`class MemberRules internal constructor(internal val rulesData: MemberRulesData) : BaseRules
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Member
\u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
fun modifiers(conditions: ModifierConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Member
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
`,13),p=[l];function c(r,t){return e(),o("div",null,p)}const i=s(n,[["render",c],["__file","MemberRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/MemberRulesResult.html.2524371e.js b/docs/assets/MemberRulesResult.html.2524371e.js new file mode 100644 index 00000000..d5541ca4 --- /dev/null +++ b/docs/assets/MemberRulesResult.html.2524371e.js @@ -0,0 +1,6 @@ +import{_ as s,o as e,c as o,a as n}from"./app.fb8271cf.js";const a={},l=n(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+
Change Records
v1.1.0
added
Function Illustrate
\u5F53\u524D
Member
\u67E5\u627E\u6761\u4EF6\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
fun none(): MemberRulesResult
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D
Member
\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u4E2A\u6570\u4E3A0
\u3002
fun count(num: Int): MemberRulesResult
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D
Member
\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u9700\u8981\u5168\u90E8\u5339\u914D\u7684\u4E2A\u6570\u3002
fun count(numRange: IntRange): MemberRulesResult
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D
Member
\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u9700\u8981\u5168\u90E8\u5339\u914D\u7684\u4E2A\u6570\u8303\u56F4\u3002
fun count(conditions: CountConditions): MemberRulesResult
+
Change Records
v1.1.0
added
Function Illustrate
`,31),t=[l];function c(p,r){return e(),o("div",null,t)}const u=s(a,[["render",c],["__file","MemberRulesResult.html.vue"]]);export{u as default}; diff --git a/docs/assets/MemberRulesResult.html.49b372bb.js b/docs/assets/MemberRulesResult.html.49b372bb.js new file mode 100644 index 00000000..e51c92e9 --- /dev/null +++ b/docs/assets/MemberRulesResult.html.49b372bb.js @@ -0,0 +1,6 @@ +import{_ as s,o,c as e,a as n}from"./app.fb8271cf.js";const a={},l=n(`\u8BBE\u7F6E\u5F53\u524D
Member
\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u9700\u8981\u5168\u90E8\u5339\u914D\u7684\u4E2A\u6570\u6761\u4EF6\u3002
class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D
Member
\u67E5\u627E\u6761\u4EF6\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
fun none(): MemberRulesResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D
Member
\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u4E2A\u6570\u4E3A0
\u3002
fun count(num: Int): MemberRulesResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D
Member
\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u9700\u8981\u5168\u90E8\u5339\u914D\u7684\u4E2A\u6570\u3002
fun count(numRange: IntRange): MemberRulesResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D
Member
\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u9700\u8981\u5168\u90E8\u5339\u914D\u7684\u4E2A\u6570\u8303\u56F4\u3002
fun count(conditions: CountConditions): MemberRulesResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,30),p=[l];function c(t,r){return o(),e("div",null,p)}const u=s(a,[["render",c],["__file","MemberRulesResult.html.vue"]]);export{u as default}; diff --git a/docs/assets/MemberRulesResult.html.58e81c94.js b/docs/assets/MemberRulesResult.html.58e81c94.js new file mode 100644 index 00000000..97637a07 --- /dev/null +++ b/docs/assets/MemberRulesResult.html.58e81c94.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-b8000f3a","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html","title":"MemberRulesResult - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"none - method","slug":"none-method","link":"#none-method","children":[]},{"level":2,"title":"count - method","slug":"count-method","link":"#count-method","children":[]},{"level":2,"title":"count - method","slug":"count-method-1","link":"#count-method-1","children":[]},{"level":2,"title":"count - method","slug":"count-method-2","link":"#count-method-2","children":[]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.md"}');export{e as data}; diff --git a/docs/assets/MemberRulesResult.html.e79843c3.js b/docs/assets/MemberRulesResult.html.e79843c3.js new file mode 100644 index 00000000..ee7ccdb9 --- /dev/null +++ b/docs/assets/MemberRulesResult.html.e79843c3.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5e375d98","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html","title":"MemberRulesResult - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"none - method","slug":"none-method","link":"#none-method","children":[]},{"level":2,"title":"count - method","slug":"count-method","link":"#count-method","children":[]},{"level":2,"title":"count - method","slug":"count-method-1","link":"#count-method-1","children":[]},{"level":2,"title":"count - method","slug":"count-method-2","link":"#count-method-2","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.md"}');export{e as data}; diff --git a/docs/assets/MethodFinder.html.03ce70ab.js b/docs/assets/MethodFinder.html.03ce70ab.js new file mode 100644 index 00000000..3a3ce265 --- /dev/null +++ b/docs/assets/MethodFinder.html.03ce70ab.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-fd738322","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html","title":"MethodFinder - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"returnType - field","slug":"returntype-field","link":"#returntype-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"order - method","slug":"order-method","link":"#order-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"name - method","slug":"name-method-1","link":"#name-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-2","link":"#paramcount-method-2","children":[]},{"level":2,"title":"returnType - method","slug":"returntype-method","link":"#returntype-method","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Process - class","slug":"process-class","link":"#process-class","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchMethod - method","slug":"onnosuchmethod-method","link":"#onnosuchmethod-method","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method-1","link":"#result-method-1","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method-1","link":"#all-method-1","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method-1","link":"#remedys-method-1","children":[]},{"level":3,"title":"onNoSuchMethod - method","slug":"onnosuchmethod-method-1","link":"#onnosuchmethod-method-1","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]},{"level":3,"title":"array - method","slug":"array-method","link":"#array-method","children":[]},{"level":3,"title":"list - method","slug":"list-method","link":"#list-method","children":[]}]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.md"}');export{e as data}; diff --git a/docs/assets/MethodFinder.html.55746f01.js b/docs/assets/MethodFinder.html.55746f01.js new file mode 100644 index 00000000..0a8c8e89 --- /dev/null +++ b/docs/assets/MethodFinder.html.55746f01.js @@ -0,0 +1,102 @@ +import{_ as s,o,c as n,a}from"./app.fb8271cf.js";const e={},l=a(`\u8BBE\u7F6E\u5F53\u524D
Member
\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u9700\u8981\u5168\u90E8\u5339\u914D\u7684\u4E2A\u6570\u6761\u4EF6\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MethodFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
+
Change Records
v1.0
first
v1.0.2
modified
\u5408\u5E76\u5230 BaseFinder
v1.1.0
modified
\u5408\u5E76\u5230 MemberBaseFinder
Function Illustrate
Method
\u67E5\u627E\u7C7B\u3002
\u53EF\u901A\u8FC7\u6307\u5B9A\u7C7B\u578B\u67E5\u627E\u6307\u5B9A Method
\u6216\u4E00\u7EC4 Method
\u3002
var name: String
+
Change Records
v1.0
first
v1.0.70
modified
\u5141\u8BB8\u4E0D\u586B\u5199\u540D\u79F0
Function Illustrate
\u8BBE\u7F6E
Method
\u540D\u79F0\u3002
Pay Attention
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
var paramCount: Int
+
Change Records
v1.0.67
added
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u53D8\u91CF\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
var returnType: Any?
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E
Method
\u8FD4\u56DE\u503C\uFF0C\u53EF\u4E0D\u586B\u5199\u8FD4\u56DE\u503C\u3002
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
Change Records
v1.0.67
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
modified
\u5408\u5E76\u5230 ModifierConditions
Function Illustrate
\u8BBE\u7F6E
Method
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun emptyParam(): IndexTypeCondition
+
Change Records
v1.0.75
added
Function Illustrate
\u8BBE\u7F6E
Method
\u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002
fun param(vararg paramType: Any): IndexTypeCondition
+
Change Records
v1.0
first
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u3002
\u5982\u679C\u540C\u65F6\u4F7F\u7528\u4E86 paramCount
\u5219 paramType
\u7684\u6570\u91CF\u5FC5\u987B\u4E0E paramCount
\u5B8C\u5168\u5339\u914D\u3002
\u5982\u679C Method
\u4E2D\u5B58\u5728\u4E00\u4E9B\u65E0\u610F\u4E49\u53C8\u5F88\u957F\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 VagueType \u6765\u66FF\u4EE3\u5B83\u3002
Pay Attention
\u65E0\u53C2 Method \u8BF7\u4F7F\u7528 emptyParam \u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002
\u6709\u53C2 Method \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u5B9A\u53C2\u6570\u6216\u4F7F\u7528 paramCount \u6307\u5B9A\u4E2A\u6570\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun order(): IndexTypeCondition
+
Change Records
v1.0.70
added
Function Illustrate
\u987A\u5E8F\u7B5B\u9009\u5B57\u8282\u7801\u7684\u4E0B\u6807\u3002
fun name(value: String): IndexTypeCondition
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E
Method
\u540D\u79F0\u3002
Pay Attention
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun name(conditions: NameConditions): IndexTypeCondition
+
Change Records
v1.0.88
added
v1.1.0
modified
\u5408\u5E76\u5230 NameConditions
Function Illustrate
\u8BBE\u7F6E
Method
\u540D\u79F0\u6761\u4EF6\u3002
Pay Attention
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(num: Int): IndexTypeCondition
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(numRange: IntRange): IndexTypeCondition
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun returnType(value: Any): IndexTypeCondition
+
Change Records
v1.0.70
added
Function Illustrate
\u8BBE\u7F6E
Method
\u8FD4\u56DE\u503C\u3002
\u53EF\u4E0D\u586B\u5199\u8FD4\u56DE\u503C\u3002
Pay Attention
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun superClass(isOnlySuperClass: Boolean)
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E\u5728
classSet
\u7684\u6240\u6709\u7236\u7C7B\u4E2D\u67E5\u627E\u5F53\u524DMethod
\u3002
Notice
\u82E5\u5F53\u524D classSet \u7684\u7236\u7C7B\u8F83\u591A\u53EF\u80FD\u4F1A\u8017\u65F6\uFF0CAPI \u4F1A\u81EA\u52A8\u5FAA\u73AF\u5230\u7236\u7C7B\u7EE7\u627F\u662F Any \u524D\u7684\u6700\u540E\u4E00\u4E2A\u7C7B\u3002
inner class RemedyPlan internal constructor()
+
Change Records
v1.0
first
Function Illustrate
Method
\u91CD\u67E5\u627E\u5B9E\u73B0\u7C7B\uFF0C\u53EF\u7D2F\u8BA1\u5931\u8D25\u6B21\u6570\u76F4\u5230\u67E5\u627E\u6210\u529F\u3002
inline fun method(initiate: MethodConditions): Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA\u9700\u8981\u91CD\u65B0\u67E5\u627E\u7684
Method
\u3002
\u4F60\u53EF\u4EE5\u6DFB\u52A0\u591A\u4E2A\u5907\u9009 Method
\uFF0C\u76F4\u5230\u6210\u529F\u4E3A\u6B62\uFF0C\u82E5\u6700\u540E\u4F9D\u7136\u5931\u8D25\uFF0C\u5C06\u505C\u6B62\u67E5\u627E\u5E76\u8F93\u51FA\u9519\u8BEF\u65E5\u5FD7\u3002
inner class Result internal constructor()
+
Change Records
v1.0.1
added
Function Illustrate
RemedyPlan
\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
fun onFind(initiate: HashSet<Method>.() -> Unit)
+
Change Records
v1.0.1
added
v1.1.0
modified
initiate
\u53C2\u6570 Method
\u53D8\u4E3A HashSet<Method>
Function Illustrate
\u5F53\u5728
RemedyPlan
\u4E2D\u627E\u5230\u7ED3\u679C\u65F6\u3002
Function Example
\u4F60\u53EF\u4EE5\u65B9\u4FBF\u5730\u5BF9\u91CD\u67E5\u627E\u7684 Method
\u5B9E\u73B0 onFind
\u65B9\u6CD5\u3002
The following example
method {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
Change Records
v1.1.0
added
Function Illustrate
Method
\u67E5\u627E\u7ED3\u679C\u5904\u7406\u7C7B\uFF0C\u4E3AhookInstance
\u63D0\u4F9B\u3002
inline fun result(initiate: Process.() -> Unit): Process
+
Change Records
v1.1.0
added
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
Function Example
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
The following example
method {
+ // Your code here.
+}.result {
+ all()
+ remedys {}
+ onNoSuchMethod {}
+}
+
fun all(): Process
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A
Method
\u5B9E\u4F8B\u7ED3\u679C\u5230hookInstance
\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u521B\u5EFA
Method
\u91CD\u67E5\u627E\u529F\u80FD\u3002
Function Example
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Method
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchMethod
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Method
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
The following example
method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u76D1\u542C\u627E\u4E0D\u5230
Method
\u65F6\u3002
\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u6B21\u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u4E0D\u4F1A\u8FD4\u56DE RemedyPlan
\u7684\u9519\u8BEF\u4FE1\u606F\u3002
inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
+
Change Records
v1.0
first
v1.1.0
modified
\u7EE7\u627F\u5230\u63A5\u53E3 BaseResult
Function Illustrate
Method
\u67E5\u627E\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
Function Example
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
The following example
method {
+ // Your code here.
+}.result {
+ get(instance).call()
+ all(instance)
+ remedys {}
+ onNoSuchMethod {}
+}
+
fun get(instance: Any?): Instance
+
Change Records
v1.0.2
added
Function Illustrate
\u83B7\u5F97
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
\u82E5\u6709\u591A\u4E2A Method
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
Pay Attention
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u8BF7\u4F7F\u7528 wait \u56DE\u8C03\u7ED3\u679C\u65B9\u6CD5\u3002
Function Example
\u4F60\u53EF\u4EE5\u901A\u8FC7\u83B7\u5F97\u65B9\u6CD5\u6240\u5728\u5B9E\u4F8B\u6765\u6267\u884C Method
\u3002
The following example
method {
+ // Your code here.
+}.get(instance).call()
+
\u82E5\u5F53\u524D\u4E3A\u9759\u6001\u65B9\u6CD5\uFF0C\u4F60\u53EF\u4EE5\u4E0D\u8BBE\u7F6E\u5B9E\u4F8B\u3002
The following example
method {
+ // Your code here.
+}.get().call()
+
fun all(instance: Any?): ArrayList<Instance>
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Method
\u5B9E\u4F8B\u7ED3\u679C\u3002
Function Example
\u4F60\u53EF\u4EE5\u901A\u8FC7\u6B64\u65B9\u6CD5\u6765\u83B7\u5F97\u5F53\u524D\u6761\u4EF6\u7ED3\u679C\u4E2D\u5339\u914D\u7684\u5168\u90E8 Method
\uFF0C\u5176\u65B9\u6CD5\u6240\u5728\u5B9E\u4F8B\u7528\u6CD5\u4E0E get
\u76F8\u540C\u3002
The following example
method {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Method?
+
Change Records
v1.0.67
added
Function Illustrate
\u5F97\u5230
Method
\u672C\u8EAB\u3002
\u82E5\u6709\u591A\u4E2A Method
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE null
\u3002
fun giveAll(): HashSet<Method>
+
Change Records
v1.1.0
added
Function Illustrate
\u5F97\u5230
Method
\u672C\u8EAB\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Method
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE\u7A7A\u7684 HashSet
\u3002
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
Change Records
v1.0.2
added
Function Illustrate
\u83B7\u5F97
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u82E5\u6709\u591A\u4E2A Method
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
Pay Attention
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Method
\u5B9E\u4F8B\u7ED3\u679C\u3002
Pay Attention
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA
Method
\u91CD\u67E5\u627E\u529F\u80FD\u3002
Function Example
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Method
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchMethod
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Method
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
The following example
method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u76D1\u542C\u627E\u4E0D\u5230
Method
\u65F6\u3002
\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u6B21\u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u4E0D\u4F1A\u8FD4\u56DE RemedyPlan
\u7684\u9519\u8BEF\u4FE1\u606F\u3002
fun ignored(): Result
+
Change Records
v1.1.0
added
Function Illustrate
\u5FFD\u7565\u5F02\u5E38\u5E76\u505C\u6B62\u6253\u5370\u4EFB\u4F55\u9519\u8BEF\u65E5\u5FD7\u3002
\u82E5 isNotIgnoredHookingFailure
\u4E3A false
\u5219\u81EA\u52A8\u5FFD\u7565\u3002
Notice
\u6B64\u65F6\u82E5\u8981\u76D1\u542C\u5F02\u5E38\u7ED3\u679C\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u5B9E\u73B0 onNoSuchMethod \u65B9\u6CD5\u3002
Change Records
v1.0.3
added
v1.1.0
deprecated
\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()
inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
+
Change Records
v1.0.2
added
v1.1.0
modified
\u65B0\u589E method
\u53C2\u6570
Function Illustrate
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
fun original(): Instance
+
Change Records
v1.1.0
added
Function Illustrate
\u6807\u8BC6\u9700\u8981\u8C03\u7528\u5F53\u524D
Method
\u672A\u7ECF Hook \u7684\u539F\u59CB\u65B9\u6CD5\u3002
\u82E5\u5F53\u524D Method
\u5E76\u672A Hook \u5219\u4F1A\u4F7F\u7528\u539F\u59CB\u7684 Method.invoke
\u65B9\u6CD5\u8C03\u7528\u3002
Pay Attention
\u4F60\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528\u6B64\u529F\u80FD\u3002
fun call(vararg param: Any?): Any?
+
Change Records
v1.0.2
added
Function Illustrate
\u6267\u884C
Method
\uFF0C\u4E0D\u6307\u5B9A\u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun <T> invoke(vararg param: Any?): T?
+
Change Records
v1.0.2
added
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9AT
\u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun byte(vararg param: Any?): Byte?
+
Change Records
v1.0.68
added
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Byte \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun int(vararg param: Any?): Int
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A callInt
int
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Int \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun long(vararg param: Any?): Long
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A callLong
long
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Long \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun short(vararg param: Any?): Short
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A callShort
short
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Short \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun double(vararg param: Any?): Double
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A callDouble
double
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Double \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun float(vararg param: Any?): Float
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A callFloat
float
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Float \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun string(vararg param: Any?): String
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A callString
string
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A String \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun char(vararg param: Any?): Char
+
Change Records
v1.0.68
added
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Char \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun boolean(vararg param: Any?): Boolean
+
Change Records
v1.0.65
added
v1.0.68
modified
\u4FEE\u6539 \u4E3A callBoolean
boolean
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Boolean \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
inline fun <reified T> array(vararg param: Any?): Array<T>
+
Change Records
v1.0.68
added
Function Illustrate
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Array \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
inline fun <reified T> list(vararg param: Any?): List<T>
+
Change Records
v1.0.68
added
Function Illustrate
`,418),p=[l];function c(t,r){return o(),n("div",null,p)}const i=s(e,[["render",c],["__file","MethodFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/MethodFinder.html.97f89f93.js b/docs/assets/MethodFinder.html.97f89f93.js new file mode 100644 index 00000000..1656f173 --- /dev/null +++ b/docs/assets/MethodFinder.html.97f89f93.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-a4aa4d00","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html","title":"MethodFinder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"returnType - field","slug":"returntype-field","link":"#returntype-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"order - method","slug":"order-method","link":"#order-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"name - method","slug":"name-method-1","link":"#name-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-2","link":"#paramcount-method-2","children":[]},{"level":2,"title":"returnType - method","slug":"returntype-method","link":"#returntype-method","children":[]},{"level":2,"title":"superClass - method","slug":"superclass-method","link":"#superclass-method","children":[]},{"level":2,"title":"RemedyPlan - class","slug":"remedyplan-class","link":"#remedyplan-class","children":[{"level":3,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Process - class","slug":"process-class","link":"#process-class","children":[{"level":3,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":3,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method","link":"#remedys-method","children":[]},{"level":3,"title":"onNoSuchMethod - method","slug":"onnosuchmethod-method","link":"#onnosuchmethod-method","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method-1","link":"#result-method-1","children":[]},{"level":3,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":3,"title":"all - method","slug":"all-method-1","link":"#all-method-1","children":[]},{"level":3,"title":"give - method","slug":"give-method","link":"#give-method","children":[]},{"level":3,"title":"giveAll - method","slug":"giveall-method","link":"#giveall-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"waitAll - method","slug":"waitall-method","link":"#waitall-method","children":[]},{"level":3,"title":"remedys - method","slug":"remedys-method-1","link":"#remedys-method-1","children":[]},{"level":3,"title":"onNoSuchMethod - method","slug":"onnosuchmethod-method-1","link":"#onnosuchmethod-method-1","children":[]},{"level":3,"title":"ignored - method","slug":"ignored-method","link":"#ignored-method","children":[]},{"level":3,"title":"Instance - class","slug":"instance-class","link":"#instance-class","children":[]},{"level":3,"title":"array - method","slug":"array-method","link":"#array-method","children":[]},{"level":3,"title":"list - method","slug":"list-method","link":"#list-method","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.md"}');export{e as data}; diff --git a/docs/assets/MethodFinder.html.9844b141.js b/docs/assets/MethodFinder.html.9844b141.js new file mode 100644 index 00000000..15fa46ad --- /dev/null +++ b/docs/assets/MethodFinder.html.9844b141.js @@ -0,0 +1,102 @@ +import{_ as s,o,c as n,a}from"./app.fb8271cf.js";const e={},l=a(`\u6267\u884C
Method
\uFF0C\u6307\u5B9A List \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
class MethodFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.2
\u4FEE\u6539
\u5408\u5E76\u5230 BaseFinder
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 MemberBaseFinder
\u529F\u80FD\u63CF\u8FF0
Method
\u67E5\u627E\u7C7B\u3002
\u53EF\u901A\u8FC7\u6307\u5B9A\u7C7B\u578B\u67E5\u627E\u6307\u5B9A Method
\u6216\u4E00\u7EC4 Method
\u3002
var name: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.70
\u4FEE\u6539
\u5141\u8BB8\u4E0D\u586B\u5199\u540D\u79F0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u540D\u79F0\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
var paramCount: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u53D8\u91CF\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
var returnType: Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u8FD4\u56DE\u503C\uFF0C\u53EF\u4E0D\u586B\u5199\u8FD4\u56DE\u503C\u3002
fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 ModifierConditions
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun emptyParam(): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.75
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002
fun param(vararg paramType: Any): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u3002
\u5982\u679C\u540C\u65F6\u4F7F\u7528\u4E86 paramCount
\u5219 paramType
\u7684\u6570\u91CF\u5FC5\u987B\u4E0E paramCount
\u5B8C\u5168\u5339\u914D\u3002
\u5982\u679C Method
\u4E2D\u5B58\u5728\u4E00\u4E9B\u65E0\u610F\u4E49\u53C8\u5F88\u957F\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 VagueType \u6765\u66FF\u4EE3\u5B83\u3002
\u7279\u522B\u6CE8\u610F
\u65E0\u53C2 Method \u8BF7\u4F7F\u7528 emptyParam \u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002
\u6709\u53C2 Method \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u5B9A\u53C2\u6570\u6216\u4F7F\u7528 paramCount \u6307\u5B9A\u4E2A\u6570\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun order(): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u987A\u5E8F\u7B5B\u9009\u5B57\u8282\u7801\u7684\u4E0B\u6807\u3002
fun name(value: String): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u540D\u79F0\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun name(conditions: NameConditions): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 NameConditions
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u540D\u79F0\u6761\u4EF6\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4E0D\u586B\u5199\u540D\u79F0\u5219\u5FC5\u987B\u5B58\u5728\u4E00\u4E2A\u5176\u5B83\u6761\u4EF6\u3002
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(num: Int): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(numRange: IntRange): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun paramCount(conditions: CountConditions): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun returnType(value: Any): IndexTypeCondition
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u8FD4\u56DE\u503C\u3002
\u53EF\u4E0D\u586B\u5199\u8FD4\u56DE\u503C\u3002
\u7279\u522B\u6CE8\u610F
\u5B58\u5728\u591A\u4E2A IndexTypeCondition \u65F6\u9664\u4E86 order \u53EA\u4F1A\u751F\u6548\u6700\u540E\u4E00\u4E2A\u3002
fun superClass(isOnlySuperClass: Boolean)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5728
classSet
\u7684\u6240\u6709\u7236\u7C7B\u4E2D\u67E5\u627E\u5F53\u524DMethod
\u3002
\u6CE8\u610F
\u82E5\u5F53\u524D classSet \u7684\u7236\u7C7B\u8F83\u591A\u53EF\u80FD\u4F1A\u8017\u65F6\uFF0CAPI \u4F1A\u81EA\u52A8\u5FAA\u73AF\u5230\u7236\u7C7B\u7EE7\u627F\u662F Any \u524D\u7684\u6700\u540E\u4E00\u4E2A\u7C7B\u3002
inner class RemedyPlan internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
Method
\u91CD\u67E5\u627E\u5B9E\u73B0\u7C7B\uFF0C\u53EF\u7D2F\u8BA1\u5931\u8D25\u6B21\u6570\u76F4\u5230\u67E5\u627E\u6210\u529F\u3002
inline fun method(initiate: MethodConditions): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u9700\u8981\u91CD\u65B0\u67E5\u627E\u7684
Method
\u3002
\u4F60\u53EF\u4EE5\u6DFB\u52A0\u591A\u4E2A\u5907\u9009 Method
\uFF0C\u76F4\u5230\u6210\u529F\u4E3A\u6B62\uFF0C\u82E5\u6700\u540E\u4F9D\u7136\u5931\u8D25\uFF0C\u5C06\u505C\u6B62\u67E5\u627E\u5E76\u8F93\u51FA\u9519\u8BEF\u65E5\u5FD7\u3002
inner class Result internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.1
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
RemedyPlan
\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
fun onFind(initiate: HashSet<Method>.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.1
\u65B0\u589E
v1.1.0
\u4FEE\u6539
initiate
\u53C2\u6570 Method
\u53D8\u4E3A HashSet<Method>
\u529F\u80FD\u63CF\u8FF0
\u5F53\u5728
RemedyPlan
\u4E2D\u627E\u5230\u7ED3\u679C\u65F6\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u65B9\u4FBF\u5730\u5BF9\u91CD\u67E5\u627E\u7684 Method
\u5B9E\u73B0 onFind
\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Method
\u67E5\u627E\u7ED3\u679C\u5904\u7406\u7C7B\uFF0C\u4E3AhookInstance
\u63D0\u4F9B\u3002
inline fun result(initiate: Process.() -> Unit): Process
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // Your code here.
+}.result {
+ all()
+ remedys {}
+ onNoSuchMethod {}
+}
+
fun all(): Process
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A
Method
\u5B9E\u4F8B\u7ED3\u679C\u5230hookInstance
\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA
Method
\u91CD\u67E5\u627E\u529F\u80FD\u3002
\u529F\u80FD\u793A\u4F8B
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Method
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchMethod
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Method
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u627E\u4E0D\u5230
Method
\u65F6\u3002
\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u6B21\u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u4E0D\u4F1A\u8FD4\u56DE RemedyPlan
\u7684\u9519\u8BEF\u4FE1\u606F\u3002
inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u7EE7\u627F\u5230\u63A5\u53E3 BaseResult
\u529F\u80FD\u63CF\u8FF0
Method
\u67E5\u627E\u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u7ED3\u679C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u4F7F\u7528 lambda
\u5F62\u5F0F\u521B\u5EFA Result
\u7C7B\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // Your code here.
+}.result {
+ get(instance).call()
+ all(instance)
+ remedys {}
+ onNoSuchMethod {}
+}
+
fun get(instance: Any?): Instance
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
\u82E5\u6709\u591A\u4E2A Method
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u8BF7\u4F7F\u7528 wait \u56DE\u8C03\u7ED3\u679C\u65B9\u6CD5\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u901A\u8FC7\u83B7\u5F97\u65B9\u6CD5\u6240\u5728\u5B9E\u4F8B\u6765\u6267\u884C Method
\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // Your code here.
+}.get(instance).call()
+
\u82E5\u5F53\u524D\u4E3A\u9759\u6001\u65B9\u6CD5\uFF0C\u4F60\u53EF\u4EE5\u4E0D\u8BBE\u7F6E\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // Your code here.
+}.get().call()
+
fun all(instance: Any?): ArrayList<Instance>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Method
\u5B9E\u4F8B\u7ED3\u679C\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u901A\u8FC7\u6B64\u65B9\u6CD5\u6765\u83B7\u5F97\u5F53\u524D\u6761\u4EF6\u7ED3\u679C\u4E2D\u5339\u914D\u7684\u5168\u90E8 Method
\uFF0C\u5176\u65B9\u6CD5\u6240\u5728\u5B9E\u4F8B\u7528\u6CD5\u4E0E get
\u76F8\u540C\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.call(...)
+}
+
fun give(): Method?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Method
\u672C\u8EAB\u3002
\u82E5\u6709\u591A\u4E2A Method
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE null
\u3002
fun giveAll(): HashSet<Method>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230
Method
\u672C\u8EAB\u6570\u7EC4\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Method
\u5B9E\u4F8B\u3002
\u5728\u67E5\u627E\u6761\u4EF6\u627E\u4E0D\u5230\u4EFB\u4F55\u7ED3\u679C\u7684\u65F6\u5019\u5C06\u8FD4\u56DE\u7A7A\u7684 HashSet
\u3002
fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u82E5\u6709\u591A\u4E2A Method
\u7ED3\u679C\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u4E2A\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\u6570\u7EC4\uFF0C\u914D\u5408RemedyPlan
\u4F7F\u7528\u3002
\u8FD4\u56DE\u5168\u90E8\u67E5\u627E\u6761\u4EF6\u5339\u914D\u7684\u591A\u4E2A Method
\u5B9E\u4F8B\u7ED3\u679C\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u8BBE\u7F6E\u4E86 remedys \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u624D\u80FD\u83B7\u5F97\u7ED3\u679C\u3002
\u82E5\u4F60\u6CA1\u6709\u8BBE\u7F6E remedys \u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002
inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA
Method
\u91CD\u67E5\u627E\u529F\u80FD\u3002
\u529F\u80FD\u793A\u4F8B
\u5F53\u4F60\u9047\u5230\u4E00\u79CD Method
\u53EF\u80FD\u5B58\u5728\u4E0D\u540C\u5F62\u5F0F\u7684\u5B58\u5728\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u5B83\uFF0C\u800C\u6CA1\u6709\u5FC5\u8981\u4F7F\u7528 onNoSuchMethod
\u6355\u83B7\u5F02\u5E38\u4E8C\u6B21\u67E5\u627E Method
\u3002
\u82E5\u7B2C\u4E00\u6B21\u67E5\u627E\u5931\u8D25\u4E86\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u6DFB\u52A0\u6B64\u65B9\u6CD5\u4F53\u76F4\u5230\u6210\u529F\u4E3A\u6B62\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u627E\u4E0D\u5230
Method
\u65F6\u3002
\u53EA\u4F1A\u8FD4\u56DE\u7B2C\u4E00\u6B21\u7684\u9519\u8BEF\u4FE1\u606F\uFF0C\u4E0D\u4F1A\u8FD4\u56DE RemedyPlan
\u7684\u9519\u8BEF\u4FE1\u606F\u3002
fun ignored(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565\u5F02\u5E38\u5E76\u505C\u6B62\u6253\u5370\u4EFB\u4F55\u9519\u8BEF\u65E5\u5FD7\u3002
\u82E5 isNotIgnoredHookingFailure
\u4E3A false
\u5219\u81EA\u52A8\u5FFD\u7565\u3002
\u6CE8\u610F
\u6B64\u65F6\u82E5\u8981\u76D1\u542C\u5F02\u5E38\u7ED3\u679C\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u5B9E\u73B0 onNoSuchMethod \u65B9\u6CD5\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.3
\u65B0\u589E
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()
inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u65B0\u589E method
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
Method
\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
fun original(): Instance
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6807\u8BC6\u9700\u8981\u8C03\u7528\u5F53\u524D
Method
\u672A\u7ECF Hook \u7684\u539F\u59CB\u65B9\u6CD5\u3002
\u82E5\u5F53\u524D Method
\u5E76\u672A Hook \u5219\u4F1A\u4F7F\u7528\u539F\u59CB\u7684 Method.invoke
\u65B9\u6CD5\u8C03\u7528\u3002
\u7279\u522B\u6CE8\u610F
\u4F60\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528\u6B64\u529F\u80FD\u3002
fun call(vararg param: Any?): Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u4E0D\u6307\u5B9A\u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun <T> invoke(vararg param: Any?): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9AT
\u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun byte(vararg param: Any?): Byte?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Byte \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun int(vararg param: Any?): Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A callInt
int
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Int \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun long(vararg param: Any?): Long
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A callLong
long
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Long \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun short(vararg param: Any?): Short
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A callShort
short
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Short \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun double(vararg param: Any?): Double
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A callDouble
double
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Double \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun float(vararg param: Any?): Float
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A callFloat
float
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Float \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun string(vararg param: Any?): String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A callString
string
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A String \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun char(vararg param: Any?): Char
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Char \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
fun boolean(vararg param: Any?): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.65
\u65B0\u589E
v1.0.68
\u4FEE\u6539
\u4FEE\u6539 \u4E3A callBoolean
boolean
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Boolean \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
inline fun <reified T> array(vararg param: Any?): Array<T>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6267\u884C
Method
\uFF0C\u6307\u5B9A Array \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
inline fun <reified T> list(vararg param: Any?): List<T>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,417),p=[l];function c(t,r){return o(),n("div",null,p)}const i=s(e,[["render",c],["__file","MethodFinder.html.vue"]]);export{i as default}; diff --git a/docs/assets/MethodRules.html.146b27be.js b/docs/assets/MethodRules.html.146b27be.js new file mode 100644 index 00000000..7d700841 --- /dev/null +++ b/docs/assets/MethodRules.html.146b27be.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5388621e","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html","title":"MethodRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"name - field","slug":"name-field","link":"#name-field","children":[]},{"level":2,"title":"paramCount - field","slug":"paramcount-field","link":"#paramcount-field","children":[]},{"level":2,"title":"returnType - field","slug":"returntype-field","link":"#returntype-field","children":[]},{"level":2,"title":"modifiers - method","slug":"modifiers-method","link":"#modifiers-method","children":[]},{"level":2,"title":"emptyParam - method","slug":"emptyparam-method","link":"#emptyparam-method","children":[]},{"level":2,"title":"param - method","slug":"param-method","link":"#param-method","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method","link":"#paramcount-method","children":[]},{"level":2,"title":"paramCount - method","slug":"paramcount-method-1","link":"#paramcount-method-1","children":[]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.md"}');export{e as data}; diff --git a/docs/assets/MethodRules.html.9819df7e.js b/docs/assets/MethodRules.html.9819df7e.js new file mode 100644 index 00000000..0ea501e7 --- /dev/null +++ b/docs/assets/MethodRules.html.9819df7e.js @@ -0,0 +1,11 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},p=e(`\u6267\u884C
Method
\uFF0C\u6307\u5B9A List \u8FD4\u56DE\u503C\u7C7B\u578B\u3002
class MethodRules internal constructor(internal val rulesData: MethodRulesData) : BaseRules
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Method
\u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
var name: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u540D\u79F0\u3002
var paramCount: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u53D8\u91CF\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
var returnType: Any?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u8FD4\u56DE\u503C\u3002
\u53EF\u4E0D\u586B\u5199\u8FD4\u56DE\u503C\u3002
fun modifiers(conditions: ModifierConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
fun emptyParam()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002
fun param(vararg paramType: Any)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u3002
\u5982\u679C\u540C\u65F6\u4F7F\u7528\u4E86 paramCount
\u5219 paramType
\u7684\u6570\u91CF\u5FC5\u987B\u4E0E paramCount
\u5B8C\u5168\u5339\u914D\u3002
\u5982\u679C Method
\u4E2D\u5B58\u5728\u4E00\u4E9B\u65E0\u610F\u4E49\u53C8\u5F88\u957F\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 VagueType
\u6765\u66FF\u4EE3\u5B83\u3002
\u7279\u522B\u6CE8\u610F
\u65E0\u53C2 Method \u8BF7\u4F7F\u7528 emptyParam \u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002
\u6709\u53C2 Method \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u5B9A\u53C2\u6570\u6216\u4F7F\u7528 paramCount \u6307\u5B9A\u4E2A\u6570\u3002
fun name(conditions: NameConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u540D\u79F0\u6761\u4EF6\u3002
fun paramCount(numRange: IntRange)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
fun paramCount(conditions: CountConditions)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class MethodRules internal constructor(internal val rulesData: MethodRulesData) : BaseRules
+
Change Records
v1.1.0
added
Function Illustrate
Method
\u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
var name: String
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u540D\u79F0\u3002
var paramCount: Int
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u53D8\u91CF\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u3002
\u82E5\u53C2\u6570\u4E2A\u6570\u5C0F\u4E8E\u96F6\u5219\u5FFD\u7565\u5E76\u4F7F\u7528 param
\u3002
var returnType: Any?
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u8FD4\u56DE\u503C\u3002
\u53EF\u4E0D\u586B\u5199\u8FD4\u56DE\u503C\u3002
fun modifiers(conditions: ModifierConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u6807\u8BC6\u7B26\u7B5B\u9009\u6761\u4EF6\u3002
\u53EF\u4E0D\u8BBE\u7F6E\u7B5B\u9009\u6761\u4EF6\u3002
fun emptyParam()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002
fun param(vararg paramType: Any)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u3002
\u5982\u679C\u540C\u65F6\u4F7F\u7528\u4E86 paramCount
\u5219 paramType
\u7684\u6570\u91CF\u5FC5\u987B\u4E0E paramCount
\u5B8C\u5168\u5339\u914D\u3002
\u5982\u679C Method
\u4E2D\u5B58\u5728\u4E00\u4E9B\u65E0\u610F\u4E49\u53C8\u5F88\u957F\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 VagueType
\u6765\u66FF\u4EE3\u5B83\u3002
Pay Attention
\u65E0\u53C2 Method \u8BF7\u4F7F\u7528 emptyParam \u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002
\u6709\u53C2 Method \u5FC5\u987B\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u5B9A\u53C2\u6570\u6216\u4F7F\u7528 paramCount \u6307\u5B9A\u4E2A\u6570\u3002
fun name(conditions: NameConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u540D\u79F0\u6761\u4EF6\u3002
fun paramCount(numRange: IntRange)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u3002
fun paramCount(conditions: CountConditions)
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E
Method
\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
\u4F60\u53EF\u4EE5\u4E0D\u4F7F\u7528 param
\u6307\u5B9A\u53C2\u6570\u7C7B\u578B\u800C\u662F\u4EC5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6307\u5B9A\u53C2\u6570\u4E2A\u6570\u6761\u4EF6\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ModifierRules private constructor()
+
Change Records
v1.0.67
added
v1.1.0
modified
\u65B0\u589E Class
\u7684\u63CF\u8FF0\u7B26\u5224\u65AD
\u4F5C\u4E3A lambda \u6574\u4F53\u5224\u65AD\u6761\u4EF6\u4F7F\u7528
\u79FB\u52A8\u5230 base \u5305\u540D
\u79C1\u6709\u5316\u6784\u9020\u65B9\u6CD5
Function Illustrate
\u8FD9\u662F\u4E00\u4E2A
Class
\u3001Member
\u63CF\u8FF0\u7B26\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
\u53EF\u5BF9 R8 \u6DF7\u6DC6\u540E\u7684 Class
\u3001Member
\u8FDB\u884C\u66F4\u52A0\u8BE6\u7EC6\u7684\u5B9A\u4F4D\u3002
val isPublic: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bpublic
\u3002
val isPrivate: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bprivate
\u3002
val isProtected: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bprotected
\u3002
val isStatic: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bstatic
\u3002
\u5BF9\u4E8E\u4EFB\u610F\u7684\u9759\u6001 Class
\u3001Member
\u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002
Notice
Kotlin \u2192 Jvm \u540E\u7684 object \u7C7B\u4E2D\u7684\u65B9\u6CD5\u5E76\u4E0D\u662F\u9759\u6001\u7684\u3002
val isFinal: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bfinal
\u3002
Notice
Kotlin \u2192 Jvm \u540E\u6CA1\u6709 open \u7B26\u53F7\u6807\u8BC6\u7684 Class\u3001Member \u548C\u6CA1\u6709\u4EFB\u4F55\u5173\u8054\u7684 Class\u3001Member \u90FD\u5C06\u4E3A final\u3002
val isSynchronized: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bsynchronized
\u3002
val isVolatile: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Field
\u7C7B\u578B\u662F\u5426\u5305\u542Bvolatile
\u3002
val isTransient: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Field
\u7C7B\u578B\u662F\u5426\u5305\u542Btransient
\u3002
val isNative: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Method
\u7C7B\u578B\u662F\u5426\u5305\u542Bnative
\u3002
\u5BF9\u4E8E\u4EFB\u610F JNI \u5BF9\u63A5\u7684 Method
\u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002
val isInterface: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Class
\u7C7B\u578B\u662F\u5426\u5305\u542Binterface
\u3002
val isAbstract: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Babstract
\u3002
\u5BF9\u4E8E\u4EFB\u610F\u7684\u62BD\u8C61 Class
\u3001Member
\u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002
val isStrict: Boolean
+
Change Records
v1.0.67
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
`,114),l=[n];function d(t,p){return s(),o("div",null,l)}const r=e(c,[["render",d],["__file","ModifierRules.html.vue"]]);export{r as default}; diff --git a/docs/assets/ModifierRules.html.4767495f.js b/docs/assets/ModifierRules.html.4767495f.js new file mode 100644 index 00000000..0a585935 --- /dev/null +++ b/docs/assets/ModifierRules.html.4767495f.js @@ -0,0 +1,14 @@ +import{_ as e,o as s,c as o,a}from"./app.fb8271cf.js";const c={},n=a(`
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bstrictfp
\u3002
class ModifierRules private constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u65B0\u589E Class
\u7684\u63CF\u8FF0\u7B26\u5224\u65AD
\u4F5C\u4E3A lambda \u6574\u4F53\u5224\u65AD\u6761\u4EF6\u4F7F\u7528
\u79FB\u52A8\u5230 base \u5305\u540D
\u79C1\u6709\u5316\u6784\u9020\u65B9\u6CD5
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u4E00\u4E2A
Class
\u3001Member
\u63CF\u8FF0\u7B26\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
\u53EF\u5BF9 R8 \u6DF7\u6DC6\u540E\u7684 Class
\u3001Member
\u8FDB\u884C\u66F4\u52A0\u8BE6\u7EC6\u7684\u5B9A\u4F4D\u3002
val isPublic: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bpublic
\u3002
val isPrivate: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bprivate
\u3002
val isProtected: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bprotected
\u3002
val isStatic: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bstatic
\u3002
\u5BF9\u4E8E\u4EFB\u610F\u7684\u9759\u6001 Class
\u3001Member
\u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002
\u6CE8\u610F
Kotlin \u2192 Jvm \u540E\u7684 object \u7C7B\u4E2D\u7684\u65B9\u6CD5\u5E76\u4E0D\u662F\u9759\u6001\u7684\u3002
val isFinal: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bfinal
\u3002
\u6CE8\u610F
Kotlin \u2192 Jvm \u540E\u6CA1\u6709 open \u7B26\u53F7\u6807\u8BC6\u7684 Class\u3001Member \u548C\u6CA1\u6709\u4EFB\u4F55\u5173\u8054\u7684 Class\u3001Member \u90FD\u5C06\u4E3A final\u3002
val isSynchronized: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bsynchronized
\u3002
val isVolatile: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Field
\u7C7B\u578B\u662F\u5426\u5305\u542Bvolatile
\u3002
val isTransient: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Field
\u7C7B\u578B\u662F\u5426\u5305\u542Btransient
\u3002
val isNative: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Method
\u7C7B\u578B\u662F\u5426\u5305\u542Bnative
\u3002
\u5BF9\u4E8E\u4EFB\u610F JNI \u5BF9\u63A5\u7684 Method
\u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002
val isInterface: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Class
\u7C7B\u578B\u662F\u5426\u5305\u542Binterface
\u3002
val isAbstract: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Babstract
\u3002
\u5BF9\u4E8E\u4EFB\u610F\u7684\u62BD\u8C61 Class
\u3001Member
\u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002
val isStrict: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
`,113),l=[n];function p(d,t){return s(),o("div",null,l)}const r=e(c,[["render",p],["__file","ModifierRules.html.vue"]]);export{r as default}; diff --git a/docs/assets/ModifierRules.html.c36dff17.js b/docs/assets/ModifierRules.html.c36dff17.js new file mode 100644 index 00000000..d292c3c1 --- /dev/null +++ b/docs/assets/ModifierRules.html.c36dff17.js @@ -0,0 +1 @@ +const i=JSON.parse('{"key":"v-8d5ce71a","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html","title":"ModifierRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"isPublic - i-ext-field","slug":"ispublic-i-ext-field","link":"#ispublic-i-ext-field","children":[]},{"level":2,"title":"isPrivate - i-ext-field","slug":"isprivate-i-ext-field","link":"#isprivate-i-ext-field","children":[]},{"level":2,"title":"isProtected - i-ext-field","slug":"isprotected-i-ext-field","link":"#isprotected-i-ext-field","children":[]},{"level":2,"title":"isStatic - i-ext-field","slug":"isstatic-i-ext-field","link":"#isstatic-i-ext-field","children":[]},{"level":2,"title":"isFinal - i-ext-field","slug":"isfinal-i-ext-field","link":"#isfinal-i-ext-field","children":[]},{"level":2,"title":"isSynchronized - i-ext-field","slug":"issynchronized-i-ext-field","link":"#issynchronized-i-ext-field","children":[]},{"level":2,"title":"isVolatile - i-ext-field","slug":"isvolatile-i-ext-field","link":"#isvolatile-i-ext-field","children":[]},{"level":2,"title":"isTransient - i-ext-field","slug":"istransient-i-ext-field","link":"#istransient-i-ext-field","children":[]},{"level":2,"title":"isNative - i-ext-field","slug":"isnative-i-ext-field","link":"#isnative-i-ext-field","children":[]},{"level":2,"title":"isInterface - i-ext-field","slug":"isinterface-i-ext-field","link":"#isinterface-i-ext-field","children":[]},{"level":2,"title":"isAbstract - i-ext-field","slug":"isabstract-i-ext-field","link":"#isabstract-i-ext-field","children":[]},{"level":2,"title":"isStrict - i-ext-field","slug":"isstrict-i-ext-field","link":"#isstrict-i-ext-field","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.md"}');export{i as data}; diff --git a/docs/assets/ModifierRules.html.f7582dc2.js b/docs/assets/ModifierRules.html.f7582dc2.js new file mode 100644 index 00000000..5b70ccb0 --- /dev/null +++ b/docs/assets/ModifierRules.html.f7582dc2.js @@ -0,0 +1 @@ +const i=JSON.parse('{"key":"v-547a3c3c","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html","title":"ModifierRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"isPublic - i-ext-field","slug":"ispublic-i-ext-field","link":"#ispublic-i-ext-field","children":[]},{"level":2,"title":"isPrivate - i-ext-field","slug":"isprivate-i-ext-field","link":"#isprivate-i-ext-field","children":[]},{"level":2,"title":"isProtected - i-ext-field","slug":"isprotected-i-ext-field","link":"#isprotected-i-ext-field","children":[]},{"level":2,"title":"isStatic - i-ext-field","slug":"isstatic-i-ext-field","link":"#isstatic-i-ext-field","children":[]},{"level":2,"title":"isFinal - i-ext-field","slug":"isfinal-i-ext-field","link":"#isfinal-i-ext-field","children":[]},{"level":2,"title":"isSynchronized - i-ext-field","slug":"issynchronized-i-ext-field","link":"#issynchronized-i-ext-field","children":[]},{"level":2,"title":"isVolatile - i-ext-field","slug":"isvolatile-i-ext-field","link":"#isvolatile-i-ext-field","children":[]},{"level":2,"title":"isTransient - i-ext-field","slug":"istransient-i-ext-field","link":"#istransient-i-ext-field","children":[]},{"level":2,"title":"isNative - i-ext-field","slug":"isnative-i-ext-field","link":"#isnative-i-ext-field","children":[]},{"level":2,"title":"isInterface - i-ext-field","slug":"isinterface-i-ext-field","link":"#isinterface-i-ext-field","children":[]},{"level":2,"title":"isAbstract - i-ext-field","slug":"isabstract-i-ext-field","link":"#isabstract-i-ext-field","children":[]},{"level":2,"title":"isStrict - i-ext-field","slug":"isstrict-i-ext-field","link":"#isstrict-i-ext-field","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.md"}');export{i as data}; diff --git a/docs/assets/ModuleAppActivity.html.09451ff7.js b/docs/assets/ModuleAppActivity.html.09451ff7.js new file mode 100644 index 00000000..d215c181 --- /dev/null +++ b/docs/assets/ModuleAppActivity.html.09451ff7.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-1446bdca","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html","title":"ModuleAppActivity - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.md"}');export{a as data}; diff --git a/docs/assets/ModuleAppActivity.html.1aa71ae6.js b/docs/assets/ModuleAppActivity.html.1aa71ae6.js new file mode 100644 index 00000000..63ac91b8 --- /dev/null +++ b/docs/assets/ModuleAppActivity.html.1aa71ae6.js @@ -0,0 +1,2 @@ +import{_ as e,o as s,c as o,a as t}from"./app.fb8271cf.js";const a={},n=t(`
Class
\u3001Member
\u7C7B\u578B\u662F\u5426\u5305\u542Bstrictfp
\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
open class ModuleAppActivity : Activity()
+
Change Records
v1.1.0
added
Function Illustrate
\u4EE3\u7406
Activity
\u3002
\u7EE7\u627F\u4E8E\u6B64\u7C7B\u7684 Activity
\u53EF\u4EE5\u540C\u65F6\u5728\u5BBF\u4E3B\u4E0E\u6A21\u5757\u4E2D\u542F\u52A8\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u9700\u8981\u5728\u5BBF\u4E3B\u542F\u52A8\u65F6\u8C03\u7528 Context.registerModuleAppActivities
\u8FDB\u884C\u6CE8\u518C\u3002
open class ModuleAppActivity : Activity()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EE3\u7406
Activity
\u3002
\u7EE7\u627F\u4E8E\u6B64\u7C7B\u7684 Activity
\u53EF\u4EE5\u540C\u65F6\u5728\u5BBF\u4E3B\u4E0E\u6A21\u5757\u4E2D\u542F\u52A8\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u9700\u8981\u5728\u5BBF\u4E3B\u542F\u52A8\u65F6\u8C03\u7528 Context.registerModuleAppActivities
\u8FDB\u884C\u6CE8\u518C\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
open class ModuleAppCompatActivity : AppCompatActivity()
+
Change Records
v1.1.0
added
Function Illustrate
\u4EE3\u7406
AppCompatActivity
\u3002
\u7EE7\u627F\u4E8E\u6B64\u7C7B\u7684 Activity
\u53EF\u4EE5\u540C\u65F6\u5728\u5BBF\u4E3B\u4E0E\u6A21\u5757\u4E2D\u542F\u52A8\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u9700\u8981\u5728\u5BBF\u4E3B\u542F\u52A8\u65F6\u8C03\u7528 Context.registerModuleAppActivities
\u8FDB\u884C\u6CE8\u518C\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u9700\u8981\u91CD\u5199 moduleTheme
\u8BBE\u7F6E AppCompat \u4E3B\u9898\uFF0C\u5426\u5219\u4F1A\u65E0\u6CD5\u542F\u52A8\u3002
open val moduleTheme: Int
+
Change Records
v1.1.0
added
Function Illustrate
`,16),p=[n];function c(l,r){return o(),s("div",null,p)}const d=e(t,[["render",c],["__file","ModuleAppCompatActivity.html.vue"]]);export{d as default}; diff --git a/docs/assets/ModuleAppCompatActivity.html.a20d9206.js b/docs/assets/ModuleAppCompatActivity.html.a20d9206.js new file mode 100644 index 00000000..d644bc38 --- /dev/null +++ b/docs/assets/ModuleAppCompatActivity.html.a20d9206.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-cadbe48e","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html","title":"ModuleAppCompatActivity - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"moduleTheme - field","slug":"moduletheme-field","link":"#moduletheme-field","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.md"}');export{e as data}; diff --git a/docs/assets/ModuleAppCompatActivity.html.dd9e40e9.js b/docs/assets/ModuleAppCompatActivity.html.dd9e40e9.js new file mode 100644 index 00000000..c6e0a8ca --- /dev/null +++ b/docs/assets/ModuleAppCompatActivity.html.dd9e40e9.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-c7cef530","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html","title":"ModuleAppCompatActivity - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"moduleTheme - field","slug":"moduletheme-field","link":"#moduletheme-field","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.md"}');export{e as data}; diff --git a/docs/assets/ModuleAppCompatActivity.html.de402219.js b/docs/assets/ModuleAppCompatActivity.html.de402219.js new file mode 100644 index 00000000..4fa1460e --- /dev/null +++ b/docs/assets/ModuleAppCompatActivity.html.de402219.js @@ -0,0 +1,3 @@ +import{_ as s,o,c as e,a as p}from"./app.fb8271cf.js";const a={},t=p(`\u8BBE\u7F6E\u5F53\u524D\u4EE3\u7406\u7684
Activity
\u4E3B\u9898\u3002
open class ModuleAppCompatActivity : AppCompatActivity()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EE3\u7406
AppCompatActivity
\u3002
\u7EE7\u627F\u4E8E\u6B64\u7C7B\u7684 Activity
\u53EF\u4EE5\u540C\u65F6\u5728\u5BBF\u4E3B\u4E0E\u6A21\u5757\u4E2D\u542F\u52A8\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u9700\u8981\u5728\u5BBF\u4E3B\u542F\u52A8\u65F6\u8C03\u7528 Context.registerModuleAppActivities
\u8FDB\u884C\u6CE8\u518C\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u9700\u8981\u91CD\u5199 moduleTheme
\u8BBE\u7F6E AppCompat \u4E3B\u9898\uFF0C\u5426\u5219\u4F1A\u65E0\u6CD5\u542F\u52A8\u3002
open val moduleTheme: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,15),c=[t];function l(n,d){return o(),e("div",null,c)}const r=s(a,[["render",l],["__file","ModuleAppCompatActivity.html.vue"]]);export{r as default}; diff --git a/docs/assets/ModuleApplication.html.57573770.js b/docs/assets/ModuleApplication.html.57573770.js new file mode 100644 index 00000000..cb8892d0 --- /dev/null +++ b/docs/assets/ModuleApplication.html.57573770.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-7fec5836","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html","title":"ModuleApplication - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"appContext - field","slug":"appcontext-field","link":"#appcontext-field","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.md"}');export{e as data}; diff --git a/docs/assets/ModuleApplication.html.a386b8db.js b/docs/assets/ModuleApplication.html.a386b8db.js new file mode 100644 index 00000000..3acb16ac --- /dev/null +++ b/docs/assets/ModuleApplication.html.a386b8db.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-4709ad58","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html","title":"ModuleApplication - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"appContext - field","slug":"appcontext-field","link":"#appcontext-field","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.md"}');export{e as data}; diff --git a/docs/assets/ModuleApplication.html.ad43cded.js b/docs/assets/ModuleApplication.html.ad43cded.js new file mode 100644 index 00000000..44f4abb1 --- /dev/null +++ b/docs/assets/ModuleApplication.html.ad43cded.js @@ -0,0 +1,17 @@ +import{_ as a,r as l,o as p,c,b as s,d as i,a as o,e as n}from"./app.fb8271cf.js";const t={},d=o(`\u8BBE\u7F6E\u5F53\u524D\u4EE3\u7406\u7684
Activity
\u4E3B\u9898\u3002
open class ModuleApplication: Application()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.77
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u5BF9\u4F7F\u7528
YukiHookAPI
Xposed \u6A21\u5757\u5B9E\u73B0\u4E2D\u7684\u4E00\u4E2A\u6269\u5C55\u529F\u80FD\u3002
\u5728\u4F60\u7684 Xposed \u6A21\u5757\u7684 Application
\u4E2D\u7EE7\u627F\u6B64\u7C7B\u3002
\u6216\u5728 AndroidManifest.xml
\u7684 application
\u6807\u7B7E\u4E2D\u6307\u5B9A\u6B64\u7C7B\u3002
\u76EE\u524D\u53EF\u5B9E\u73B0\u529F\u80FD\u5982\u4E0B
`,9),r=o("\u5168\u5C40\u5171\u4EAB\u6A21\u5757\u4E2D\u9759\u6001\u7684 appContext
\u5728\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E2D\u88C5\u8F7D YukiHookAPI.Config
\u4EE5\u786E\u4FDD YukiHookAPI.Configs.debugTag
\u4E0D\u9700\u8981\u91CD\u590D\u5B9A\u4E49
\u5728\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E2D\u4F7F\u7528 YukiHookDataChannel
\u8FDB\u884C\u901A\u8BAF
\u529F\u80FD\u793A\u4F8B
\u5C06\u6B64\u7C7B\u7EE7\u627F\u5230\u4F60\u7684\u81EA\u5B9A\u4E49 Application
\u4E0A\u3002
\u793A\u4F8B\u5982\u4E0B
package com.demo
+
+class MyApplication: ModuleApplication() {
+
+ override fun onCreate() {
+ super.onCreate()
+ }
+}
+
\u5728 AndroidManifest.xml
\u7684 application
\u6807\u7B7E\u4E2D\u6307\u5B9A\u81EA\u5B9A\u4E49\u7684 Application
\u3002
\u793A\u4F8B\u5982\u4E0B
<application
+ android:name="com.demo.MyApplication"
+ ...>
+
\u5982\u679C\u4F60\u4E0D\u9700\u8981\u81EA\u5B9A\u4E49 Application
\u53EF\u4EE5\u76F4\u63A5\u5C06 ModuleApplication
\u8BBE\u7F6E\u5230 AndroidManifest.xml
\u7684 application
\u6807\u7B7E\u4E2D\u3002
\u793A\u4F8B\u5982\u4E0B
<application
+ android:name="com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication"
+ ...>
+
val appContext: ModuleApplication
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.77
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,16);function k(b,C){const e=l("ExternalLinkIcon");return p(),c("div",null,[d,s("ul",null,[r,s("li",null,[s("p",null,[u,s("a",A,[y,i(e)])])]),v]),m])}const D=a(t,[["render",k],["__file","ModuleApplication.html.vue"]]);export{D as default}; diff --git a/docs/assets/ModuleApplication.html.e946b5fe.js b/docs/assets/ModuleApplication.html.e946b5fe.js new file mode 100644 index 00000000..3ffd9e7f --- /dev/null +++ b/docs/assets/ModuleApplication.html.e946b5fe.js @@ -0,0 +1,17 @@ +import{_ as a,r as l,o as p,c,b as s,d as i,a as e,e as n}from"./app.fb8271cf.js";const t={},d=e(`\u83B7\u53D6\u5168\u5C40\u9759\u6001
Application
\u5B9E\u4F8B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
open class ModuleApplication: Application()
+
Change Records
v1.0.77
added
Function Illustrate
\u8FD9\u662F\u5BF9\u4F7F\u7528
YukiHookAPI
Xposed \u6A21\u5757\u5B9E\u73B0\u4E2D\u7684\u4E00\u4E2A\u6269\u5C55\u529F\u80FD\u3002
\u5728\u4F60\u7684 Xposed \u6A21\u5757\u7684 Application
\u4E2D\u7EE7\u627F\u6B64\u7C7B\u3002
\u6216\u5728 AndroidManifest.xml
\u7684 application
\u6807\u7B7E\u4E2D\u6307\u5B9A\u6B64\u7C7B\u3002
\u76EE\u524D\u53EF\u5B9E\u73B0\u529F\u80FD\u5982\u4E0B
`,10),r=e("\u5168\u5C40\u5171\u4EAB\u6A21\u5757\u4E2D\u9759\u6001\u7684 appContext
\u5728\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E2D\u88C5\u8F7D YukiHookAPI.Config
\u4EE5\u786E\u4FDD YukiHookAPI.Configs.debugTag
\u4E0D\u9700\u8981\u91CD\u590D\u5B9A\u4E49
\u5728\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E2D\u4F7F\u7528 YukiHookDataChannel
\u8FDB\u884C\u901A\u8BAF
Function Example
\u5C06\u6B64\u7C7B\u7EE7\u627F\u5230\u4F60\u7684\u81EA\u5B9A\u4E49 Application
\u4E0A\u3002
The following example
package com.demo
+
+class MyApplication: ModuleApplication() {
+
+ override fun onCreate() {
+ super.onCreate()
+ }
+}
+
\u5728 AndroidManifest.xml
\u7684 application
\u6807\u7B7E\u4E2D\u6307\u5B9A\u81EA\u5B9A\u4E49\u7684 Application
\u3002
The following example
<application
+ android:name="com.demo.MyApplication"
+ ...>
+
\u5982\u679C\u4F60\u4E0D\u9700\u8981\u81EA\u5B9A\u4E49 Application
\u53EF\u4EE5\u76F4\u63A5\u5C06 ModuleApplication
\u8BBE\u7F6E\u5230 AndroidManifest.xml
\u7684 application
\u6807\u7B7E\u4E2D\u3002
The following example
<application
+ android:name="com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication"
+ ...>
+
val appContext: ModuleApplication
+
Change Records
v1.0.77
added
Function Illustrate
`,16);function h(g,C){const o=l("ExternalLinkIcon");return p(),c("div",null,[d,s("ul",null,[r,s("li",null,[s("p",null,[u,s("a",A,[y,i(o)])])]),m]),v])}const k=a(t,[["render",h],["__file","ModuleApplication.html.vue"]]);export{k as default}; diff --git a/docs/assets/ModuleContextThemeWrapper.html.0879426b.js b/docs/assets/ModuleContextThemeWrapper.html.0879426b.js new file mode 100644 index 00000000..267c5d53 --- /dev/null +++ b/docs/assets/ModuleContextThemeWrapper.html.0879426b.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-78731c50","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html","title":"ModuleContextThemeWrapper - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"applyConfiguration - method","slug":"applyconfiguration-method","link":"#applyconfiguration-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.md"}');export{e as data}; diff --git a/docs/assets/ModuleContextThemeWrapper.html.229a46ac.js b/docs/assets/ModuleContextThemeWrapper.html.229a46ac.js new file mode 100644 index 00000000..b2580a5e --- /dev/null +++ b/docs/assets/ModuleContextThemeWrapper.html.229a46ac.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-44efb702","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html","title":"ModuleContextThemeWrapper - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"applyConfiguration - method","slug":"applyconfiguration-method","link":"#applyconfiguration-method","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.md"}');export{e as data}; diff --git a/docs/assets/ModuleContextThemeWrapper.html.5787cac6.js b/docs/assets/ModuleContextThemeWrapper.html.5787cac6.js new file mode 100644 index 00000000..876ae822 --- /dev/null +++ b/docs/assets/ModuleContextThemeWrapper.html.5787cac6.js @@ -0,0 +1,3 @@ +import{_ as s,o,c as e,a as n}from"./app.fb8271cf.js";const a={},t=n(`\u83B7\u53D6\u5168\u5C40\u9759\u6001
Application
\u5B9E\u4F8B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) : ContextThemeWrapper
+
Change Records
v1.1.0
added
Function Illustrate
\u4EE3\u7406
ContextThemeWrapper
\u3002
\u901A\u8FC7\u5305\u88C5\uFF0C\u4F60\u53EF\u4EE5\u8F7B\u677E\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u6765\u81EA\u6A21\u5757\u7684\u4E3B\u9898\u8D44\u6E90\u3002
fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E\u5F53\u524D
ModuleContextThemeWrapper
\u7684Configuration
\u3002
\u8BBE\u7F6E\u540E\u4F1A\u81EA\u52A8\u8C03\u7528 Resources.updateConfiguration
\u3002
class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) : ContextThemeWrapper
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EE3\u7406
ContextThemeWrapper
\u3002
\u901A\u8FC7\u5305\u88C5\uFF0C\u4F60\u53EF\u4EE5\u8F7B\u677E\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u6765\u81EA\u6A21\u5757\u7684\u4E3B\u9898\u8D44\u6E90\u3002
fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E\u5F53\u524D
ModuleContextThemeWrapper
\u7684Configuration
\u3002
\u8BBE\u7F6E\u540E\u4F1A\u81EA\u52A8\u8C03\u7528 Resources.updateConfiguration
\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
abstract class ModulePreferenceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener
+
Change Records
v1.0.78
added
Function Illustrate
\u8FD9\u662F\u5BF9\u4F7F\u7528
YukiHookAPI
Xposed \u6A21\u5757\u5B9E\u73B0\u4E2D\u7684\u4E00\u4E2A\u6269\u5C55\u529F\u80FD\u3002
\u6B64\u7C7B\u63A5\u7BA1\u4E86 PreferenceFragmentCompat
\u5E76\u5BF9\u5176\u5B9E\u73B0\u4E86 Sp \u5B58\u50A8\u5728 Xposed \u6A21\u5757\u4E2D\u7684\u5168\u5C40\u53EF\u8BFB\u53EF\u5199\u3002
\u5728\u4F60\u4F7F\u7528 PreferenceFragmentCompat
\u7684\u5B9E\u4F8B\u4E2D\uFF0C\u5C06\u7EE7\u627F\u5BF9\u8C61\u6362\u6210\u6B64\u7C7B\u3002
\u7136\u540E\u8BF7\u5C06\u91CD\u5199\u65B9\u6CD5\u7531 onCreatePreferences
\u66FF\u6362\u4E3A onCreatePreferencesInModuleApp
\u5373\u53EF\u3002
Function Example
\u4F7F\u7528 ModulePreferenceFragment
\u521B\u5EFA\u4E00\u4E2A PreferenceFragmentCompat
\u5BF9\u8C61\u3002
The following example
class SettingsFragment : ModulePreferenceFragment() {
+
+ override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(R.xml.settings_preferences, rootKey)
+ // Your code here.
+ }
+}
+
\u5176\u4F59\u7528\u6CD5\u4E0E PreferenceFragmentCompat
\u4FDD\u6301\u4E00\u81F4\u3002
abstract fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?)
+
Change Records
v1.0.78
added
Function Illustrate
\u5BF9\u63A5\u539F\u59CB\u65B9\u6CD5
onCreatePreferences
\u3002
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?)
+
Change Records
v1.0.78
added
Function Illustrate
\u5B9E\u73B0\u4E86
SharedPreferences.OnSharedPreferenceChangeListener
\u7684\u539F\u751F\u76D1\u542C\u529F\u80FD\u3002
Function Example
Notice
\u5728\u4F7F\u7528 onSharedPreferenceChanged \u65F6\u8BF7\u4FDD\u7559 super \u65B9\u6CD5\u3002
The following example
class SettingsFragment : ModulePreferenceFragment() {
+
+ override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
+ // ...
+ }
+
+ override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
+ super.onSharedPreferenceChanged(sharedPreferences, key)
+ // Your code here.
+ }
+}
+
abstract class ModulePreferenceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.78
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u5BF9\u4F7F\u7528
YukiHookAPI
Xposed \u6A21\u5757\u5B9E\u73B0\u4E2D\u7684\u4E00\u4E2A\u6269\u5C55\u529F\u80FD\u3002
\u6B64\u7C7B\u63A5\u7BA1\u4E86 PreferenceFragmentCompat
\u5E76\u5BF9\u5176\u5B9E\u73B0\u4E86 Sp \u5B58\u50A8\u5728 Xposed \u6A21\u5757\u4E2D\u7684\u5168\u5C40\u53EF\u8BFB\u53EF\u5199\u3002
\u5728\u4F60\u4F7F\u7528 PreferenceFragmentCompat
\u7684\u5B9E\u4F8B\u4E2D\uFF0C\u5C06\u7EE7\u627F\u5BF9\u8C61\u6362\u6210\u6B64\u7C7B\u3002
\u7136\u540E\u8BF7\u5C06\u91CD\u5199\u65B9\u6CD5\u7531 onCreatePreferences
\u66FF\u6362\u4E3A onCreatePreferencesInModuleApp
\u5373\u53EF\u3002
\u529F\u80FD\u793A\u4F8B
\u4F7F\u7528 ModulePreferenceFragment
\u521B\u5EFA\u4E00\u4E2A PreferenceFragmentCompat
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
class SettingsFragment : ModulePreferenceFragment() {
+
+ override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(R.xml.settings_preferences, rootKey)
+ // Your code here.
+ }
+}
+
\u5176\u4F59\u7528\u6CD5\u4E0E PreferenceFragmentCompat
\u4FDD\u6301\u4E00\u81F4\u3002
abstract fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.78
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5BF9\u63A5\u539F\u59CB\u65B9\u6CD5
onCreatePreferences
\u3002
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.78
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5B9E\u73B0\u4E86
SharedPreferences.OnSharedPreferenceChangeListener
\u7684\u539F\u751F\u76D1\u542C\u529F\u80FD\u3002
\u529F\u80FD\u793A\u4F8B
\u6CE8\u610F
\u5728\u4F7F\u7528 onSharedPreferenceChanged \u65F6\u8BF7\u4FDD\u7559 super \u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
class SettingsFragment : ModulePreferenceFragment() {
+
+ override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
+ // ...
+ }
+
+ override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
+ super.onSharedPreferenceChanged(sharedPreferences, key)
+ // Your code here.
+ }
+}
+
class NameRules private constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
NameConditions
\u66F4\u540D\u4E3A NameRules
\u4F5C\u4E3A lambda \u6574\u4F53\u5224\u65AD\u6761\u4EF6\u4F7F\u7528
\u79FB\u52A8\u5230 base \u5305\u540D
\u79C1\u6709\u5316\u6784\u9020\u65B9\u6CD5
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u4E00\u4E2A\u6A21\u7CCA
Class
\u3001Member
\u540D\u79F0\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
\u53EF\u5BF9 R8 \u6DF7\u6DC6\u540E\u7684 Class
\u3001Member
\u8FDB\u884C\u66F4\u52A0\u8BE6\u7EC6\u7684\u5B9A\u4F4D\u3002
fun String.isSynthetic(index: Int): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u4E3A\u533F\u540D\u7C7B\u7684\u4E3B\u7C7B\u8C03\u7528\u5BF9\u8C61\u3002
fun String.isOnlySymbols(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u53EA\u6709\u7B26\u53F7\u3002
fun String.isOnlyLetters(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u53EA\u6709\u5B57\u6BCD\u3002
fun String.isOnlyNumbers(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u53EA\u6709\u6570\u5B57\u3002
fun String.isOnlyLettersNumbers(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u53EA\u6709\u5B57\u6BCD\u6216\u6570\u5B57\u3002
fun String.isOnlyLowercase(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u53EA\u6709\u5C0F\u5199\u5B57\u6BCD\u3002
\u5728\u6CA1\u6709\u5176\u5B83\u6761\u4EF6\u7684\u60C5\u51B5\u4E0B\u8BBE\u7F6E\u6B64\u6761\u4EF6\u5141\u8BB8\u5224\u65AD\u5BF9\u8C61\u5B58\u5728\u5B57\u6BCD\u4EE5\u5916\u7684\u5B57\u7B26\u3002
fun String.isOnlyUppercase(): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u53EA\u6709\u5927\u5199\u5B57\u6BCD\u3002
\u5728\u6CA1\u6709\u5176\u5B83\u6761\u4EF6\u7684\u60C5\u51B5\u4E0B\u8BBE\u7F6E\u6B64\u6761\u4EF6\u5141\u8BB8\u5224\u65AD\u5BF9\u8C61\u5B58\u5728\u5B57\u6BCD\u4EE5\u5916\u7684\u5B57\u7B26\u3002
`,70),l=[p];function c(t,r){return e(),o("div",null,l)}const i=s(a,[["render",c],["__file","NameRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/NameRules.html.47e512e4.js b/docs/assets/NameRules.html.47e512e4.js new file mode 100644 index 00000000..b5c0a9bf --- /dev/null +++ b/docs/assets/NameRules.html.47e512e4.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-58c26516","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html","title":"NameRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"String.isSynthetic - i-ext-method","slug":"string-issynthetic-i-ext-method","link":"#string-issynthetic-i-ext-method","children":[]},{"level":2,"title":"String.isOnlySymbols - i-ext-method","slug":"string-isonlysymbols-i-ext-method","link":"#string-isonlysymbols-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLetters - i-ext-method","slug":"string-isonlyletters-i-ext-method","link":"#string-isonlyletters-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyNumbers - i-ext-method","slug":"string-isonlynumbers-i-ext-method","link":"#string-isonlynumbers-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLettersNumbers - i-ext-method","slug":"string-isonlylettersnumbers-i-ext-method","link":"#string-isonlylettersnumbers-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyLowercase - i-ext-method","slug":"string-isonlylowercase-i-ext-method","link":"#string-isonlylowercase-i-ext-method","children":[]},{"level":2,"title":"String.isOnlyUppercase - i-ext-method","slug":"string-isonlyuppercase-i-ext-method","link":"#string-isonlyuppercase-i-ext-method","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.md"}');export{e as data}; diff --git a/docs/assets/NameRules.html.5da95c04.js b/docs/assets/NameRules.html.5da95c04.js new file mode 100644 index 00000000..ef11b6a1 --- /dev/null +++ b/docs/assets/NameRules.html.5da95c04.js @@ -0,0 +1,9 @@ +import{_ as s,o as e,c as o,a as n}from"./app.fb8271cf.js";const a={},l=n(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class NameRules private constructor()
+
Change Records
v1.0.88
added
v1.1.0
modified
NameConditions
\u66F4\u540D\u4E3A NameRules
\u4F5C\u4E3A lambda \u6574\u4F53\u5224\u65AD\u6761\u4EF6\u4F7F\u7528
\u79FB\u52A8\u5230 base \u5305\u540D
\u79C1\u6709\u5316\u6784\u9020\u65B9\u6CD5
Function Illustrate
\u8FD9\u662F\u4E00\u4E2A\u6A21\u7CCA
Class
\u3001Member
\u540D\u79F0\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
\u53EF\u5BF9 R8 \u6DF7\u6DC6\u540E\u7684 Class
\u3001Member
\u8FDB\u884C\u66F4\u52A0\u8BE6\u7EC6\u7684\u5B9A\u4F4D\u3002
fun String.isSynthetic(index: Int): Boolean
+
Change Records
v1.0.88
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
\u662F\u5426\u4E3A\u533F\u540D\u7C7B\u7684\u4E3B\u7C7B\u8C03\u7528\u5BF9\u8C61\u3002
fun String.isOnlySymbols(): Boolean
+
Change Records
v1.0.88
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
\u662F\u5426\u53EA\u6709\u7B26\u53F7\u3002
fun String.isOnlyLetters(): Boolean
+
Change Records
v1.0.88
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
\u662F\u5426\u53EA\u6709\u5B57\u6BCD\u3002
fun String.isOnlyNumbers(): Boolean
+
Change Records
v1.0.88
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
\u662F\u5426\u53EA\u6709\u6570\u5B57\u3002
fun String.isOnlyLettersNumbers(): Boolean
+
Change Records
v1.0.88
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
\u662F\u5426\u53EA\u6709\u5B57\u6BCD\u6216\u6570\u5B57\u3002
fun String.isOnlyLowercase(): Boolean
+
Change Records
v1.0.88
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
\u662F\u5426\u53EA\u6709\u5C0F\u5199\u5B57\u6BCD\u3002
\u5728\u6CA1\u6709\u5176\u5B83\u6761\u4EF6\u7684\u60C5\u51B5\u4E0B\u8BBE\u7F6E\u6B64\u6761\u4EF6\u5141\u8BB8\u5224\u65AD\u5BF9\u8C61\u5B58\u5728\u5B57\u6BCD\u4EE5\u5916\u7684\u5B57\u7B26\u3002
fun String.isOnlyUppercase(): Boolean
+
Change Records
v1.0.88
added
v1.1.0
modified
\u7EDF\u4E00\u5408\u5E76\u5230\u6269\u5C55\u65B9\u6CD5\u5E76\u6539\u540D
Function Illustrate
\u662F\u5426\u53EA\u6709\u5927\u5199\u5B57\u6BCD\u3002
\u5728\u6CA1\u6709\u5176\u5B83\u6761\u4EF6\u7684\u60C5\u51B5\u4E0B\u8BBE\u7F6E\u6B64\u6761\u4EF6\u5141\u8BB8\u5224\u65AD\u5BF9\u8C61\u5B58\u5728\u5B57\u6BCD\u4EE5\u5916\u7684\u5B57\u7B26\u3002
`,71),t=[l];function p(c,r){return e(),o("div",null,t)}const i=s(a,[["render",p],["__file","NameRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/PackageParam.html.3014d07d.js b/docs/assets/PackageParam.html.3014d07d.js new file mode 100644 index 00000000..1b79e294 --- /dev/null +++ b/docs/assets/PackageParam.html.3014d07d.js @@ -0,0 +1,104 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},l=e(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
open class PackageParam internal constructor(internal var wrapper: PackageParamWrapper?)
+
Change Records
v1.0
first
Function Illustrate
\u88C5\u8F7D Hook \u7684\u76EE\u6807 APP \u5165\u53E3\u5BF9\u8C61\u5B9E\u73B0\u7C7B\u3002
val appClassLoader\uFF1AClassLoader
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u7684
ClassLoader
\u3002
val appInfo: ApplicationInfo
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u7684
ApplicationInfo
\u3002
val appUserId: Int
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u7684\u7528\u6237 ID\u3002
\u673A\u4E3B\u4E3A 0
\uFF0C\u5E94\u7528\u53CC\u5F00 (\u5206\u8EAB) \u6216\u5DE5\u4F5C\u8D44\u6599\u56E0\u7CFB\u7EDF\u73AF\u5883\u4E0D\u540C ID \u4E5F\u5404\u4E0D\u76F8\u540C\u3002
val appContext: Application?
+
Change Records
v1.0.72
added
v1.1.0
modified
\u52A0\u5165\u53EF\u7A7A\u7C7B\u578B (\u7A7A\u5B89\u5168)
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u7684
Application
\u3002
Pay Attention
\u9996\u6B21\u88C5\u8F7D\u53EF\u80FD\u662F\u7A7A\u7684\uFF0C\u8BF7\u5EF6\u8FDF\u4E00\u6BB5\u65F6\u95F4\u518D\u83B7\u53D6\u6216\u4F7F\u7528 onAppLifecycle \u76D1\u542C\u6765\u5B8C\u6210\u3002
val appResources\uFF1AResources?
+
Change Records
v1.0.80
added
v1.1.0
modified
\u52A0\u5165\u53EF\u7A7A\u7C7B\u578B (\u7A7A\u5B89\u5168)
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u7684 Resources\u3002
Pay Attention
\u4F60\u53EA\u80FD\u5728 HookResources.hook \u65B9\u6CD5\u4F53\u5185\u6216 appContext \u88C5\u8F7D\u5B8C\u6BD5\u65F6\u8FDB\u884C\u8C03\u7528\u3002
val systemContext: Context
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D\u7CFB\u7EDF\u6846\u67B6\u7684
Context
\u3002
val processName: String
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u7684\u8FDB\u7A0B\u540D\u79F0\u3002
val packageName: String
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u7684\u5305\u540D\u3002
val isFirstApplication: Boolean
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u662F\u5426\u4E3A\u7B2C\u4E00\u4E2A
Application
\u3002
val mainProcessName: String
+
Change Records
v1.0.70
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook APP \u7684\u4E3B\u8FDB\u7A0B\u540D\u79F0\u3002
\u5176\u5BF9\u5E94\u7684\u5C31\u662F packageName
\u3002
val moduleAppFilePath: String
+
Change Records
v1.0.80
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB APK \u6587\u4EF6\u8DEF\u5F84\u3002
Pay Attention
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u83B7\u53D6\u5230\u7A7A\u5B57\u7B26\u4E32\u3002
val moduleAppResources: YukiModuleResources
+
Change Records
v1.0.80
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB
Resources
\u3002
Pay Attention
\u4F5C\u4E3A Hook API \u6216\u4E0D\u652F\u6301\u7684 Hook Framework \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
val prefs: YukiHookModulePrefs
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u5F97\u5F53\u524D\u4F7F\u7528\u7684\u5B58\u53D6\u6570\u636E\u5BF9\u8C61\u7F13\u5B58\u5B9E\u4F8B\u3002
Pay Attention
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
fun prefs(name: String): YukiHookModulePrefs
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u83B7\u5F97\u5F53\u524D\u4F7F\u7528\u7684\u5B58\u53D6\u6570\u636E\u5BF9\u8C61\u7F13\u5B58\u5B9E\u4F8B\u3002
\u4F60\u53EF\u4EE5\u901A\u8FC7 name
\u6765\u81EA\u5B9A\u4E49 Sp \u5B58\u50A8\u7684\u540D\u79F0\u3002
Pay Attention
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
val dataChannel: YukiHookDataChannel.NameSpace
+
Change Records
v1.0.88
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D\u4F7F\u7528\u7684\u6570\u636E\u901A\u8BAF\u6865\u547D\u540D\u7A7A\u95F4\u5BF9\u8C61\u3002
Pay Attention
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
fun resources(): HookResources
+
Change Records
v1.0.80
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D Hook APP \u7684
YukiResources
\u5BF9\u8C61\u3002
\u8BF7\u8C03\u7528 HookResources.hook
\u65B9\u6CD5\u5F00\u59CB Hook\u3002
fun refreshModuleAppResources()
+
Change Records
v1.0.87
added
Function Illustrate
\u5237\u65B0\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB
Resources
\u3002
inline fun onAppLifecycle(initiate: AppLifecycle.() -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u76D1\u542C\u5F53\u524D Hook APP \u751F\u547D\u5468\u671F\u88C5\u8F7D\u4E8B\u4EF6\u3002
Notice
\u5728 loadZygote \u4E2D\u4E0D\u4F1A\u88AB\u88C5\u8F7D\uFF0C\u4EC5\u4F1A\u5728 loadSystem\u3001loadApp \u4E2D\u88C5\u8F7D\u3002
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u8BF7\u4F7F\u7528\u539F\u751F\u7684 Application \u5B9E\u73B0\u751F\u547D\u5468\u671F\u76D1\u542C\u3002
inline fun loadApp(name: String, initiate: PackageParam.() -> Unit)
+
fun loadApp(name: String, hooker: YukiBaseHooker)
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u88C5\u8F7D\u5E76 Hook \u6307\u5B9A\u5305\u540D\u7684 APP\u3002
name
\u4E3A APP \u7684\u5305\u540D\uFF0C\u540E\u65B9\u7684\u4E24\u4E2A\u53C2\u6570\u4E00\u4E2A\u53EF\u4F5C\u4E3A lambda
\u65B9\u6CD5\u4F53\u4F7F\u7528\uFF0C\u4E00\u4E2A\u53EF\u4EE5\u76F4\u63A5\u88C5\u8F7D\u5B50 Hooker\u3002
\u88C5\u8F7D\u5E76 Hook \u6307\u5B9A\u3001\u5168\u90E8\u5305\u540D\u7684 APP\u3002
\u82E5\u8981\u88C5\u8F7D APP Zygote \u4E8B\u4EF6\uFF0C\u8BF7\u4F7F\u7528 loadZygote
\u3002
\u82E5\u8981 Hook \u7CFB\u7EDF\u6846\u67B6\uFF0C\u8BF7\u4F7F\u7528 loadSystem
\u3002
Function Example
\u4F60\u53EF\u4EE5\u4F7F\u7528 loadApp
\u7684 lambda
\u65B9\u6CD5\u4F53\u5F62\u5F0F\u6216\u76F4\u63A5\u88C5\u8F7D\u4E00\u4E2A Hooker\u3002
The following example
// \u4F7F\u7528 lambda
+loadApp(name = "com.example.test") {
+ // Your code here.
+}
+// \u4F7F\u7528 Hooker
+loadApp(name = "com.example.test", CustomHooker)
+
\u82E5\u4E0D\u6307\u5B9A name
\u53C2\u6570\uFF0C\u5219\u6B64\u65B9\u6CD5\u4F53\u9ED8\u8BA4\u4F1A\u8FC7\u6EE4\u5F53\u524D\u7CFB\u7EDF\u4E2D\u5168\u90E8\u53EF\u88AB Hook \u7684 APP\u3002
The following example
// \u4F7F\u7528 lambda
+loadApp {
+ // Your code here.
+}
+// \u4F7F\u7528 Hooker
+loadApp(hooker = CustomHooker)
+
inline fun loadZygote(initiate: PackageParam.() -> Unit)
+
fun loadZygote(hooker: YukiBaseHooker)
+
Change Records
v1.0.80
added
Function Illustrate
\u88C5\u8F7D APP Zygote \u4E8B\u4EF6\u3002
\u65B9\u6CD5\u4E2D\u7684\u4E24\u4E2A\u53C2\u6570\u4E00\u4E2A\u53EF\u4F5C\u4E3A lambda
\u65B9\u6CD5\u4F53\u4F7F\u7528\uFF0C\u4E00\u4E2A\u53EF\u4EE5\u76F4\u63A5\u88C5\u8F7D\u5B50 Hooker\u3002
inline fun loadSystem(initiate: PackageParam.() -> Unit)
+
fun loadSystem(hooker: YukiBaseHooker)
+
Change Records
v1.0.82
added
Function Illustrate
\u88C5\u8F7D\u5E76 Hook \u7CFB\u7EDF\u6846\u67B6\u3002
\u65B9\u6CD5\u4E2D\u7684\u4E24\u4E2A\u53C2\u6570\u4E00\u4E2A\u53EF\u4F5C\u4E3A lambda
\u65B9\u6CD5\u4F53\u4F7F\u7528\uFF0C\u4E00\u4E2A\u53EF\u4EE5\u76F4\u63A5\u88C5\u8F7D\u5B50 Hooker\u3002
inline fun withProcess(name: String, initiate: PackageParam.() -> Unit)
+
fun withProcess(name: String, hooker: YukiBaseHooker)
+
Change Records
v1.0.70
added
Function Illustrate
\u88C5\u8F7D\u5E76 Hook APP \u7684\u6307\u5B9A\u8FDB\u7A0B\u3002
name
\u4E3A APP \u7684\u8FDB\u7A0B\u540D\u79F0\uFF0C\u540E\u65B9\u7684\u4E24\u4E2A\u53C2\u6570\u4E00\u4E2A\u53EF\u4F5C\u4E3A lambda
\u65B9\u6CD5\u4F53\u4F7F\u7528\uFF0C\u4E00\u4E2A\u53EF\u4EE5\u76F4\u63A5\u88C5\u8F7D\u5B50 Hooker\u3002
fun loadHooker(hooker: YukiBaseHooker)
+
Change Records
v1.0
first
Function Illustrate
\u88C5\u8F7D Hook \u5B50\u7C7B\u3002
\u4F60\u53EF\u4EE5\u586B\u5165 hooker
\u5728 Hooker \u4E2D\u7EE7\u7EED\u88C5\u8F7D Hooker\u3002
inline fun searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
Change Records
v1.1.0
added
Function Illustrate
\u901A\u8FC7
appClassLoader
\u6309\u6307\u5B9A\u6761\u4EF6\u67E5\u627E\u5E76\u5F97\u5230\u5F53\u524D Hook APP Dex \u4E2D\u7684Class
\u3002
Pay Attention
\u6B64\u65B9\u6CD5\u5728 Class \u6570\u91CF\u8FC7\u591A\u53CA\u67E5\u627E\u6761\u4EF6\u590D\u6742\u65F6\u4F1A\u975E\u5E38\u8017\u65F6\u3002
\u5EFA\u8BAE\u542F\u7528 async \u6216\u8BBE\u7F6E name \u53C2\u6570\uFF0Cname \u53C2\u6570\u5C06\u5728 Hook APP (\u5BBF\u4E3B) \u4E0D\u540C\u7248\u672C\u4E2D\u81EA\u52A8\u8FDB\u884C\u672C\u5730\u7F13\u5B58\u4EE5\u63D0\u5347\u6548\u7387\u3002
\u6B64\u529F\u80FD\u5C1A\u5728\u8BD5\u9A8C\u9636\u6BB5\uFF0C\u6027\u80FD\u4E0E\u7A33\u5B9A\u6027\u53EF\u80FD\u4ECD\u7136\u5B58\u5728\u95EE\u9898\uFF0C\u4F7F\u7528\u8FC7\u7A0B\u9047\u5230\u95EE\u9898\u8BF7\u5411\u6211\u4EEC\u62A5\u544A\u5E76\u5E2E\u52A9\u6211\u4EEC\u6539\u8FDB\u3002
Change Records
v1.0
first
v1.1.0
deprecated
\u8BF7\u8F6C\u79FB\u5230 toClass(...)
\u65B9\u6CD5
Change Records
v1.0
first
v1.1.0
deprecated
\u8BF7\u8F6C\u79FB\u5230 hasClass(...)
\u65B9\u6CD5
fun String.toClass(loader: ClassLoader?): Class<*>
+
fun VariousClass.toClass(loader: ClassLoader?): Class<*>
+
Change Records
v1.1.0
added
Function Illustrate
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u3001
VariousClass
\u8F6C\u6362\u4E3Aloader
\u4E2D\u7684\u5B9E\u4F53\u7C7B\u3002
\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D appClassLoader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
Function Example
\u4F60\u53EF\u4EE5\u8F7B\u677E\u5730\u5C06 String
\u7C7B\u578B\u7684 Class
\u5305\u540D\u8F6C\u4E3A Class
\u5B9E\u4F8B\u3002
The following example
"com.example.demo.DemoClass".toClass()
+
\u4F60\u8FD8\u53EF\u4EE5\u5411 loader
\u53C2\u6570\u4F20\u5165\u4F60\u81EA\u5B9A\u4E49\u7684 ClassLoader
\u3002
The following example
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
\u4F60\u8FD8\u53EF\u4EE5\u521B\u5EFA\u4E00\u4E2A VariousClass
\uFF0C\u5E76\u8F6C\u6362\u4E3A\u5B9E\u4F53\u7C7B\u3002
VariousClass
\u4F1A\u679A\u4E3E\u6240\u6709\u8BBE\u7F6E\u7684 Class
\u5E76\u6700\u7EC8\u83B7\u5F97\u7B2C\u4E00\u4E2A\u5B58\u5728\u7684 Class
\u3002
The following example
VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass()
+
\u540C\u6837\u5730\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5411 loader
\u53C2\u6570\u4F20\u5165\u4F60\u81EA\u5B9A\u4E49\u7684 ClassLoader
\u3002
The following example
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass(customClassLoader)
+
fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
+
fun VariousClass.toClassOrNull(loader: ClassLoader?): Class<*>?
+
Change Records
v1.1.0
added
Function Illustrate
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u3001
VariousClass
\u8F6C\u6362\u4E3Aloader
\u4E2D\u7684\u5B9E\u4F53\u7C7B\u3002
\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D appClassLoader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
\u627E\u4E0D\u5230 Class
\u4F1A\u8FD4\u56DE null
\uFF0C\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
Function Example
\u7528\u6CD5\u8BF7\u53C2\u8003 String+VariousClass.toClass \u65B9\u6CD5\u3002
fun String.hasClass(loader: ClassLoader?): Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u67E5\u627E\u662F\u5426\u5B58\u5728\u3002
\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D appClassLoader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
Function Example
\u4F60\u53EF\u4EE5\u8F7B\u677E\u7684\u4F7F\u7528\u6B64\u65B9\u6CD5\u5224\u65AD\u5B57\u7B26\u4E32\u4E2D\u7684\u7C7B\u662F\u5426\u5B58\u5728\u3002
The following example
if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49\u5176\u4E2D\u7684 loader
\u53C2\u6570\uFF0C\u9ED8\u8BA4\u4E3A appClassLoader
\u3002
The following example
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
fun findClass(name: String, loader: ClassLoader?): HookClass
+
fun findClass(vararg name: String, loader: ClassLoader?): VariousClass
+
Change Records
v1.0
first
v1.0.1
modified
\u79FB\u9664\u4E86 \u65B9\u6CD5findClass(various: VariousClass)
v1.1.0
modified
\u65B0\u589E loader
\u53C2\u6570
Function Illustrate
\u901A\u8FC7\u5B8C\u6574\u5305\u540D+\u540D\u79F0\u67E5\u627E\u9700\u8981\u88AB Hook \u7684
Class
\u3002
Notice
\u4F7F\u7528\u6B64\u65B9\u6CD5\u4F1A\u5F97\u5230\u4E00\u4E2A HookClass \u4EC5\u7528\u4E8E Hook\uFF0C\u82E5\u60F3\u67E5\u627E Class \u8BF7\u4F7F\u7528 toClass \u529F\u80FD\u3002
Function Example
\u4F60\u53EF\u4EE5\u4F7F\u7528\u4E09\u79CD\u65B9\u5F0F\u67E5\u627E\u4F60\u9700\u8981 Hook \u7684\u76EE\u6807 Class
\u3002
\u4F60\u53EF\u4EE5\u76F4\u63A5\u5C06\u88AB\u67E5\u627E\u7684 Class
\u5B8C\u6574\u5305\u540D+\u540D\u79F0\u586B\u5165 name
\u4E2D\u3002
The following example
findClass(name = "com.example.demo.DemoClass")
+
\u82E5\u4F60\u4E0D\u786E\u5B9A\u591A\u4E2A\u7248\u672C\u7684 Class
\u4EE5\u53CA\u4E0D\u540C\u540D\u79F0\uFF0C\u4F60\u53EF\u4EE5\u5C06\u591A\u4E2A\u5B8C\u6574\u5305\u540D+\u540D\u79F0\u586B\u5165 name
\u4E2D\u3002
The following example
findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
+
\u4F60\u8FD8\u53EF\u4EE5\u521B\u5EFA\u4E00\u4E2A VariousClass
\uFF0C\u5C06 Class
\u7684\u5B8C\u6574\u5305\u540D+\u540D\u79F0\u586B\u5165 VariousClass
\u7684 name
\u4E2D\u5E76\u586B\u5165 various
\u53C2\u6570\u4E2D\u3002
The following example
val variousClass = VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
+
\u82E5\u4F60\u5F53\u524D\u9700\u8981\u67E5\u627E\u7684 Class
\u4E0D\u5C5E\u4E8E appClassLoader
\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 loader
\u53C2\u6570\u6307\u5B9A\u4F60\u8981\u88C5\u8F7D\u7684 ClassLoader
\u3002
The following example
val outsideLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u5C31\u662F\u4F60\u7684 ClassLoader
+findClass(name = "com.example.demo.OutsideClass", loader = outsideLoader)
+
\u540C\u6837\u5730\uFF0C\u5728\u4E0D\u786E\u5B9A\u591A\u4E2A\u7248\u672C\u7684 Class
\u4EE5\u53CA\u4E0D\u540C\u540D\u79F0\u65F6\uFF0C\u4E5F\u53EF\u4EE5\u4F7F\u7528 loader
\u53C2\u6570\u6307\u5B9A\u4F60\u8981\u88C5\u8F7D\u7684 ClassLoader
\u3002
The following example
val outsideLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u5C31\u662F\u4F60\u7684 ClassLoader
+findClass("com.example.demo.OutsideClass1", "com.example.demo.OutsideClass2", "com.example.demo.OutsideClass3", loader = outsideLoader)
+
inline fun String.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun Class<*>.hook(isForceUseAbsolute: Boolean, initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun VariousClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun HookClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
Change Records
v1.0
first
v1.0.1
modified
\u65B0\u589E VariousClass
\u7684\u76F4\u63A5\u8C03\u7528 hook
\u65B9\u6CD5
v1.0.2
modified
\u65B0\u589E String
\u7684\u76F4\u63A5\u8C03\u7528 hook
\u65B9\u6CD5
v1.0.3
modified
\u65B0\u589E YukiMemberHookCreator.Result
\u8FD4\u56DE\u503C
v1.0.70
modified
\u65B0\u589E isUseAppClassLoader
\u53C2\u6570
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
modified
\u79FB\u9664\u4E86 \u53C2\u6570isUseAppClassLoader
\u6DFB\u52A0\u4E86 isForceUseAbsolute
\u53C2\u6570\u5230 Class.hook
\u65B9\u6CD5
Function Illustrate
\u8FD9\u662F\u4E00\u5207 Hook \u7684\u5165\u53E3\u521B\u5EFA\u65B9\u6CD5\uFF0CHook \u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u3002
Function Example
\u5982\u4F60\u6240\u89C1\uFF0CHook \u65B9\u6CD5\u4F53\u7684\u521B\u5EFA\u53EF\u4F7F\u7528 4 \u79CD\u65B9\u5F0F\u3002
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u5F97\u5230 HookClass
\u5B9E\u4F8B\u8FDB\u884C\u521B\u5EFA\u3002
The following example
"com.example.demo.DemoClass".hook {
+ // Your code here.
+}
+
+
\u901A\u8FC7 findClass
\u5F97\u5230 HookClass
\u5B9E\u4F8B\u8FDB\u884C\u521B\u5EFA\u3002
The following example
findClass(name = "com.example.demo.DemoClass").hook {
+ // Your code here.
+}
+
\u4F7F\u7528 stub
\u6216\u76F4\u63A5\u62FF\u5230 Class
\u5B9E\u4F8B\u8FDB\u884C\u521B\u5EFA\u3002
\u9ED8\u8BA4\u60C5\u51B5\u4E0B API \u4F1A\u5C06 Class
\u5B9E\u4F8B\u8F6C\u6362\u4E3A\u7C7B\u540D\u5E76\u7ED1\u5B9A\u5230 appClassLoader
\uFF0C\u82E5\u5931\u8D25\uFF0C\u5219\u4F1A\u4F7F\u7528\u539F\u59CB Class
\u5B9E\u4F8B\u76F4\u63A5\u8FDB\u884C Hook\u3002
The following example
Stub::class.java.hook {
+ // Your code here.
+}
+
\u82E5\u5F53\u524D Class
\u4E0D\u5728 appClassLoader
\u4E14\u81EA\u52A8\u5339\u914D\u65E0\u6CD5\u627E\u5230\u8BE5 Class
\uFF0C\u8BF7\u542F\u7528 isForceUseAbsolute
\u3002
The following example
YourClass::class.java.hook(isForceUseAbsolute = true) {
+ // Your code here.
+}
+
\u4F7F\u7528 VariousClass
\u5B9E\u4F8B\u8FDB\u884C\u521B\u5EFA\u3002
The following example
VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
+ // Your code here.
+}
+
\u6216\u8005\u76F4\u63A5\u4F7F\u7528\u53EF\u53D8\u5B57\u7B26\u4E32\u6570\u7EC4\u8FDB\u884C\u521B\u5EFA\u3002
The following example
findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
+ // Your code here.
+}
+
inline fun HookResources.hook(initiate: YukiResourcesHookCreator.() -> Unit)
+
Change Records
v1.0.80
added
Function Illustrate
Hook APP \u7684 Resources\u3002
Pay Attention
\u8BF7\u6CE8\u610F\u4F60\u9700\u8981\u786E\u4FDD\u5F53\u524D Hook Framework \u652F\u6301\u4E14 InjectYukiHookWithXposed.isUsingResourcesHook \u5DF2\u542F\u7528\u3002
Function Example
Resources Hook \u4E3A\u56FA\u5B9A\u7528\u6CD5\uFF0C\u83B7\u53D6 resources
\u5BF9\u8C61\uFF0C\u7136\u540E\u8C03\u7528 hook
\u65B9\u6CD5\u5F00\u59CB Hook\u3002
The following example
resources().hook {
+ // Your code here.
+}
+
Pay Attention
\u8FD9\u662F\u56FA\u5B9A\u7528\u6CD5\uFF0C\u4E3A\u4E86\u9632\u6B62\u53D1\u751F\u95EE\u9898\uFF0C\u4F60\u4E0D\u53EF\u624B\u52A8\u5B9E\u73B0\u4EFB\u4F55 HookResources \u5B9E\u4F8B\u6267\u884C hook \u8C03\u7528\u3002
\u5C06 Resources \u7684 Hook \u8BBE\u7F6E\u4E3A\u8FD9\u6837\u662F\u4E3A\u4E86\u4E0E findClass(...).hook
\u505A\u5230\u7EDF\u4E00\uFF0C\u4F7F\u5F97\u8C03\u7528\u8D77\u6765\u903B\u8F91\u4E0D\u4F1A\u6DF7\u4E71\u3002
inner class AppLifecycle internal constructor()
+
Change Records
v1.0.88
added
Function Illustrate
\u5F53\u524D Hook APP \u7684\u751F\u547D\u5468\u671F\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
fun attachBaseContext(result: (baseContext: Context, hasCalledSuper: Boolean) -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.attachBaseContext
\u3002
fun onCreate(initiate: Application.() -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onCreate
\u3002
fun onTerminate(initiate: Application.() -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onTerminate
\u3002
fun onLowMemory(initiate: Application.() -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onLowMemory
\u3002
fun onTrimMemory(result: (self: Application, level: Int) -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onTrimMemory
\u3002
fun onConfigurationChanged(result: (self: Application, config: Configuration) -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onConfigurationChanged
\u3002
fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
`,381),p=[l];function c(t,r){return o(),a("div",null,p)}const i=s(n,[["render",c],["__file","PackageParam.html.vue"]]);export{i as default}; diff --git a/docs/assets/PackageParam.html.37aae471.js b/docs/assets/PackageParam.html.37aae471.js new file mode 100644 index 00000000..1c096318 --- /dev/null +++ b/docs/assets/PackageParam.html.37aae471.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-100b529c","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html","title":"PackageParam - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"appClassLoader - field","slug":"appclassloader-field","link":"#appclassloader-field","children":[]},{"level":2,"title":"appInfo - field","slug":"appinfo-field","link":"#appinfo-field","children":[]},{"level":2,"title":"appUserId - field","slug":"appuserid-field","link":"#appuserid-field","children":[]},{"level":2,"title":"appContext - field","slug":"appcontext-field","link":"#appcontext-field","children":[]},{"level":2,"title":"appResources - field","slug":"appresources-field","link":"#appresources-field","children":[]},{"level":2,"title":"systemContext - field","slug":"systemcontext-field","link":"#systemcontext-field","children":[]},{"level":2,"title":"processName - field","slug":"processname-field","link":"#processname-field","children":[]},{"level":2,"title":"packageName - field","slug":"packagename-field","link":"#packagename-field","children":[]},{"level":2,"title":"isFirstApplication - field","slug":"isfirstapplication-field","link":"#isfirstapplication-field","children":[]},{"level":2,"title":"mainProcessName - field","slug":"mainprocessname-field","link":"#mainprocessname-field","children":[]},{"level":2,"title":"moduleAppFilePath - field","slug":"moduleappfilepath-field","link":"#moduleappfilepath-field","children":[]},{"level":2,"title":"moduleAppResources - field","slug":"moduleappresources-field","link":"#moduleappresources-field","children":[]},{"level":2,"title":"prefs - field","slug":"prefs-field","link":"#prefs-field","children":[]},{"level":2,"title":"prefs - method","slug":"prefs-method","link":"#prefs-method","children":[]},{"level":2,"title":"dataChannel - field","slug":"datachannel-field","link":"#datachannel-field","children":[]},{"level":2,"title":"resources - method","slug":"resources-method","link":"#resources-method","children":[]},{"level":2,"title":"refreshModuleAppResources - method","slug":"refreshmoduleappresources-method","link":"#refreshmoduleappresources-method","children":[]},{"level":2,"title":"onAppLifecycle - method","slug":"onapplifecycle-method","link":"#onapplifecycle-method","children":[]},{"level":2,"title":"loadApp - method","slug":"loadapp-method","link":"#loadapp-method","children":[]},{"level":2,"title":"loadZygote - method","slug":"loadzygote-method","link":"#loadzygote-method","children":[]},{"level":2,"title":"loadSystem - method","slug":"loadsystem-method","link":"#loadsystem-method","children":[]},{"level":2,"title":"withProcess - method","slug":"withprocess-method","link":"#withprocess-method","children":[]},{"level":2,"title":"loadHooker - method","slug":"loadhooker-method","link":"#loadhooker-method","children":[]},{"level":2,"title":"searchClass - method","slug":"searchclass-method","link":"#searchclass-method","children":[]},{"level":2,"title":"String+VariousClass.toClass - i-ext-method","slug":"string-variousclass-toclass-i-ext-method","link":"#string-variousclass-toclass-i-ext-method","children":[]},{"level":2,"title":"String+VariousClass.toClassOrNull - i-ext-method","slug":"string-variousclass-toclassornull-i-ext-method","link":"#string-variousclass-toclassornull-i-ext-method","children":[]},{"level":2,"title":"String.hasClass - i-ext-method","slug":"string-hasclass-i-ext-method","link":"#string-hasclass-i-ext-method","children":[]},{"level":2,"title":"findClass - method","slug":"findclass-method","link":"#findclass-method","children":[]},{"level":2,"title":"String+Class+VariousClass+HookClass.hook - i-ext-method","slug":"string-class-variousclass-hookclass-hook-i-ext-method","link":"#string-class-variousclass-hookclass-hook-i-ext-method","children":[]},{"level":2,"title":"HookResources.hook - i-ext-method","slug":"hookresources-hook-i-ext-method","link":"#hookresources-hook-i-ext-method","children":[]},{"level":2,"title":"AppLifecycle - class","slug":"applifecycle-class","link":"#applifecycle-class","children":[{"level":3,"title":"attachBaseContext - method","slug":"attachbasecontext-method","link":"#attachbasecontext-method","children":[]},{"level":3,"title":"onCreate - method","slug":"oncreate-method","link":"#oncreate-method","children":[]},{"level":3,"title":"onTerminate - method","slug":"onterminate-method","link":"#onterminate-method","children":[]},{"level":3,"title":"onLowMemory - method","slug":"onlowmemory-method","link":"#onlowmemory-method","children":[]},{"level":3,"title":"onTrimMemory - method","slug":"ontrimmemory-method","link":"#ontrimmemory-method","children":[]},{"level":3,"title":"onConfigurationChanged - method","slug":"onconfigurationchanged-method","link":"#onconfigurationchanged-method","children":[]},{"level":3,"title":"registerReceiver - method","slug":"registerreceiver-method","link":"#registerreceiver-method","children":[]}]}],"git":{"updatedTime":1663766338000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.md"}');export{e as data}; diff --git a/docs/assets/PackageParam.html.4c3306f9.js b/docs/assets/PackageParam.html.4c3306f9.js new file mode 100644 index 00000000..ded7f4bb --- /dev/null +++ b/docs/assets/PackageParam.html.4c3306f9.js @@ -0,0 +1,104 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},l=e(`\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\u76D1\u542C\u3002
open class PackageParam internal constructor(internal var wrapper: PackageParamWrapper?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u88C5\u8F7D Hook \u7684\u76EE\u6807 APP \u5165\u53E3\u5BF9\u8C61\u5B9E\u73B0\u7C7B\u3002
val appClassLoader\uFF1AClassLoader
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u7684
ClassLoader
\u3002
val appInfo: ApplicationInfo
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u7684
ApplicationInfo
\u3002
val appUserId: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u7684\u7528\u6237 ID\u3002
\u673A\u4E3B\u4E3A 0
\uFF0C\u5E94\u7528\u53CC\u5F00 (\u5206\u8EAB) \u6216\u5DE5\u4F5C\u8D44\u6599\u56E0\u7CFB\u7EDF\u73AF\u5883\u4E0D\u540C ID \u4E5F\u5404\u4E0D\u76F8\u540C\u3002
val appContext: Application?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.72
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u52A0\u5165\u53EF\u7A7A\u7C7B\u578B (\u7A7A\u5B89\u5168)
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u7684
Application
\u3002
\u7279\u522B\u6CE8\u610F
\u9996\u6B21\u88C5\u8F7D\u53EF\u80FD\u662F\u7A7A\u7684\uFF0C\u8BF7\u5EF6\u8FDF\u4E00\u6BB5\u65F6\u95F4\u518D\u83B7\u53D6\u6216\u4F7F\u7528 onAppLifecycle \u76D1\u542C\u6765\u5B8C\u6210\u3002
val appResources\uFF1AResources?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u52A0\u5165\u53EF\u7A7A\u7C7B\u578B (\u7A7A\u5B89\u5168)
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u7684 Resources\u3002
\u7279\u522B\u6CE8\u610F
\u4F60\u53EA\u80FD\u5728 HookResources.hook \u65B9\u6CD5\u4F53\u5185\u6216 appContext \u88C5\u8F7D\u5B8C\u6BD5\u65F6\u8FDB\u884C\u8C03\u7528\u3002
val systemContext: Context
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D\u7CFB\u7EDF\u6846\u67B6\u7684
Context
\u3002
val processName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u7684\u8FDB\u7A0B\u540D\u79F0\u3002
val packageName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u7684\u5305\u540D\u3002
val isFirstApplication: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u662F\u5426\u4E3A\u7B2C\u4E00\u4E2A
Application
\u3002
val mainProcessName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook APP \u7684\u4E3B\u8FDB\u7A0B\u540D\u79F0\u3002
\u5176\u5BF9\u5E94\u7684\u5C31\u662F packageName
\u3002
val moduleAppFilePath: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB APK \u6587\u4EF6\u8DEF\u5F84\u3002
\u7279\u522B\u6CE8\u610F
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u83B7\u53D6\u5230\u7A7A\u5B57\u7B26\u4E32\u3002
val moduleAppResources: YukiModuleResources
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB
Resources
\u3002
\u7279\u522B\u6CE8\u610F
\u4F5C\u4E3A Hook API \u6216\u4E0D\u652F\u6301\u7684 Hook Framework \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
val prefs: YukiHookModulePrefs
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D\u4F7F\u7528\u7684\u5B58\u53D6\u6570\u636E\u5BF9\u8C61\u7F13\u5B58\u5B9E\u4F8B\u3002
\u7279\u522B\u6CE8\u610F
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
fun prefs(name: String): YukiHookModulePrefs
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D\u4F7F\u7528\u7684\u5B58\u53D6\u6570\u636E\u5BF9\u8C61\u7F13\u5B58\u5B9E\u4F8B\u3002
\u4F60\u53EF\u4EE5\u901A\u8FC7 name
\u6765\u81EA\u5B9A\u4E49 Sp \u5B58\u50A8\u7684\u540D\u79F0\u3002
\u7279\u522B\u6CE8\u610F
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
val dataChannel: YukiHookDataChannel.NameSpace
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D\u4F7F\u7528\u7684\u6570\u636E\u901A\u8BAF\u6865\u547D\u540D\u7A7A\u95F4\u5BF9\u8C61\u3002
\u7279\u522B\u6CE8\u610F
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u65E0\u6CD5\u4F7F\u7528\uFF0C\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
fun resources(): HookResources
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D Hook APP \u7684
YukiResources
\u5BF9\u8C61\u3002
\u8BF7\u8C03\u7528 HookResources.hook
\u65B9\u6CD5\u5F00\u59CB Hook\u3002
fun refreshModuleAppResources()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.87
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5237\u65B0\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB
Resources
\u3002
inline fun onAppLifecycle(initiate: AppLifecycle.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5F53\u524D Hook APP \u751F\u547D\u5468\u671F\u88C5\u8F7D\u4E8B\u4EF6\u3002
\u6CE8\u610F
\u5728 loadZygote \u4E2D\u4E0D\u4F1A\u88AB\u88C5\u8F7D\uFF0C\u4EC5\u4F1A\u5728 loadSystem\u3001loadApp \u4E2D\u88C5\u8F7D\u3002
\u4F5C\u4E3A Hook API \u88C5\u8F7D\u65F6\u8BF7\u4F7F\u7528\u539F\u751F\u7684 Application \u5B9E\u73B0\u751F\u547D\u5468\u671F\u76D1\u542C\u3002
inline fun loadApp(name: String, initiate: PackageParam.() -> Unit)
+
fun loadApp(name: String, hooker: YukiBaseHooker)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u88C5\u8F7D\u5E76 Hook \u6307\u5B9A\u5305\u540D\u7684 APP\u3002
name
\u4E3A APP \u7684\u5305\u540D\uFF0C\u540E\u65B9\u7684\u4E24\u4E2A\u53C2\u6570\u4E00\u4E2A\u53EF\u4F5C\u4E3A lambda
\u65B9\u6CD5\u4F53\u4F7F\u7528\uFF0C\u4E00\u4E2A\u53EF\u4EE5\u76F4\u63A5\u88C5\u8F7D\u5B50 Hooker\u3002
\u88C5\u8F7D\u5E76 Hook \u6307\u5B9A\u3001\u5168\u90E8\u5305\u540D\u7684 APP\u3002
\u82E5\u8981\u88C5\u8F7D APP Zygote \u4E8B\u4EF6\uFF0C\u8BF7\u4F7F\u7528 loadZygote
\u3002
\u82E5\u8981 Hook \u7CFB\u7EDF\u6846\u67B6\uFF0C\u8BF7\u4F7F\u7528 loadSystem
\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u4F7F\u7528 loadApp
\u7684 lambda
\u65B9\u6CD5\u4F53\u5F62\u5F0F\u6216\u76F4\u63A5\u88C5\u8F7D\u4E00\u4E2A Hooker\u3002
\u793A\u4F8B\u5982\u4E0B
// \u4F7F\u7528 lambda
+loadApp(name = "com.example.test") {
+ // Your code here.
+}
+// \u4F7F\u7528 Hooker
+loadApp(name = "com.example.test", CustomHooker)
+
\u82E5\u4E0D\u6307\u5B9A name
\u53C2\u6570\uFF0C\u5219\u6B64\u65B9\u6CD5\u4F53\u9ED8\u8BA4\u4F1A\u8FC7\u6EE4\u5F53\u524D\u7CFB\u7EDF\u4E2D\u5168\u90E8\u53EF\u88AB Hook \u7684 APP\u3002
\u793A\u4F8B\u5982\u4E0B
// \u4F7F\u7528 lambda
+loadApp {
+ // Your code here.
+}
+// \u4F7F\u7528 Hooker
+loadApp(hooker = CustomHooker)
+
inline fun loadZygote(initiate: PackageParam.() -> Unit)
+
fun loadZygote(hooker: YukiBaseHooker)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u88C5\u8F7D APP Zygote \u4E8B\u4EF6\u3002
\u65B9\u6CD5\u4E2D\u7684\u4E24\u4E2A\u53C2\u6570\u4E00\u4E2A\u53EF\u4F5C\u4E3A lambda
\u65B9\u6CD5\u4F53\u4F7F\u7528\uFF0C\u4E00\u4E2A\u53EF\u4EE5\u76F4\u63A5\u88C5\u8F7D\u5B50 Hooker\u3002
inline fun loadSystem(initiate: PackageParam.() -> Unit)
+
fun loadSystem(hooker: YukiBaseHooker)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.82
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u88C5\u8F7D\u5E76 Hook \u7CFB\u7EDF\u6846\u67B6\u3002
\u65B9\u6CD5\u4E2D\u7684\u4E24\u4E2A\u53C2\u6570\u4E00\u4E2A\u53EF\u4F5C\u4E3A lambda
\u65B9\u6CD5\u4F53\u4F7F\u7528\uFF0C\u4E00\u4E2A\u53EF\u4EE5\u76F4\u63A5\u88C5\u8F7D\u5B50 Hooker\u3002
inline fun withProcess(name: String, initiate: PackageParam.() -> Unit)
+
fun withProcess(name: String, hooker: YukiBaseHooker)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u88C5\u8F7D\u5E76 Hook APP \u7684\u6307\u5B9A\u8FDB\u7A0B\u3002
name
\u4E3A APP \u7684\u8FDB\u7A0B\u540D\u79F0\uFF0C\u540E\u65B9\u7684\u4E24\u4E2A\u53C2\u6570\u4E00\u4E2A\u53EF\u4F5C\u4E3A lambda
\u65B9\u6CD5\u4F53\u4F7F\u7528\uFF0C\u4E00\u4E2A\u53EF\u4EE5\u76F4\u63A5\u88C5\u8F7D\u5B50 Hooker\u3002
fun loadHooker(hooker: YukiBaseHooker)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u88C5\u8F7D Hook \u5B50\u7C7B\u3002
\u4F60\u53EF\u4EE5\u586B\u5165 hooker
\u5728 Hooker \u4E2D\u7EE7\u7EED\u88C5\u8F7D Hooker\u3002
inline fun searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7
appClassLoader
\u6309\u6307\u5B9A\u6761\u4EF6\u67E5\u627E\u5E76\u5F97\u5230\u5F53\u524D Hook APP Dex \u4E2D\u7684Class
\u3002
\u7279\u522B\u6CE8\u610F
\u6B64\u65B9\u6CD5\u5728 Class \u6570\u91CF\u8FC7\u591A\u53CA\u67E5\u627E\u6761\u4EF6\u590D\u6742\u65F6\u4F1A\u975E\u5E38\u8017\u65F6\u3002
\u5EFA\u8BAE\u542F\u7528 async \u6216\u8BBE\u7F6E name \u53C2\u6570\uFF0Cname \u53C2\u6570\u5C06\u5728 Hook APP (\u5BBF\u4E3B) \u4E0D\u540C\u7248\u672C\u4E2D\u81EA\u52A8\u8FDB\u884C\u672C\u5730\u7F13\u5B58\u4EE5\u63D0\u5347\u6548\u7387\u3002
\u6B64\u529F\u80FD\u5C1A\u5728\u8BD5\u9A8C\u9636\u6BB5\uFF0C\u6027\u80FD\u4E0E\u7A33\u5B9A\u6027\u53EF\u80FD\u4ECD\u7136\u5B58\u5728\u95EE\u9898\uFF0C\u4F7F\u7528\u8FC7\u7A0B\u9047\u5230\u95EE\u9898\u8BF7\u5411\u6211\u4EEC\u62A5\u544A\u5E76\u5E2E\u52A9\u6211\u4EEC\u6539\u8FDB\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230 toClass(...)
\u65B9\u6CD5
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230 hasClass(...)
\u65B9\u6CD5
fun String.toClass(loader: ClassLoader?): Class<*>
+
fun VariousClass.toClass(loader: ClassLoader?): Class<*>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u3001
VariousClass
\u8F6C\u6362\u4E3Aloader
\u4E2D\u7684\u5B9E\u4F53\u7C7B\u3002
\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D appClassLoader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u8F7B\u677E\u5730\u5C06 String
\u7C7B\u578B\u7684 Class
\u5305\u540D\u8F6C\u4E3A Class
\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
"com.example.demo.DemoClass".toClass()
+
\u4F60\u8FD8\u53EF\u4EE5\u5411 loader
\u53C2\u6570\u4F20\u5165\u4F60\u81EA\u5B9A\u4E49\u7684 ClassLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
\u4F60\u8FD8\u53EF\u4EE5\u521B\u5EFA\u4E00\u4E2A VariousClass
\uFF0C\u5E76\u8F6C\u6362\u4E3A\u5B9E\u4F53\u7C7B\u3002
VariousClass
\u4F1A\u679A\u4E3E\u6240\u6709\u8BBE\u7F6E\u7684 Class
\u5E76\u6700\u7EC8\u83B7\u5F97\u7B2C\u4E00\u4E2A\u5B58\u5728\u7684 Class
\u3002
\u793A\u4F8B\u5982\u4E0B
VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass()
+
\u540C\u6837\u5730\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5411 loader
\u53C2\u6570\u4F20\u5165\u4F60\u81EA\u5B9A\u4E49\u7684 ClassLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass(customClassLoader)
+
fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
+
fun VariousClass.toClassOrNull(loader: ClassLoader?): Class<*>?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u3001
VariousClass
\u8F6C\u6362\u4E3Aloader
\u4E2D\u7684\u5B9E\u4F53\u7C7B\u3002
\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D appClassLoader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
\u627E\u4E0D\u5230 Class
\u4F1A\u8FD4\u56DE null
\uFF0C\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
\u529F\u80FD\u793A\u4F8B
\u7528\u6CD5\u8BF7\u53C2\u8003 String+VariousClass.toClass \u65B9\u6CD5\u3002
fun String.hasClass(loader: ClassLoader?): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u67E5\u627E\u662F\u5426\u5B58\u5728\u3002
\u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D appClassLoader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u8F7B\u677E\u7684\u4F7F\u7528\u6B64\u65B9\u6CD5\u5224\u65AD\u5B57\u7B26\u4E32\u4E2D\u7684\u7C7B\u662F\u5426\u5B58\u5728\u3002
\u793A\u4F8B\u5982\u4E0B
if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49\u5176\u4E2D\u7684 loader
\u53C2\u6570\uFF0C\u9ED8\u8BA4\u4E3A appClassLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
fun findClass(name: String, loader: ClassLoader?): HookClass
+
fun findClass(vararg name: String, loader: ClassLoader?): VariousClass
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u4FEE\u6539
\u79FB\u9664\u4E86 \u65B9\u6CD5findClass(various: VariousClass)
v1.1.0
\u4FEE\u6539
\u65B0\u589E loader
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u5B8C\u6574\u5305\u540D+\u540D\u79F0\u67E5\u627E\u9700\u8981\u88AB Hook \u7684
Class
\u3002
\u6CE8\u610F
\u4F7F\u7528\u6B64\u65B9\u6CD5\u4F1A\u5F97\u5230\u4E00\u4E2A HookClass \u4EC5\u7528\u4E8E Hook\uFF0C\u82E5\u60F3\u67E5\u627E Class \u8BF7\u4F7F\u7528 toClass \u529F\u80FD\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u4F7F\u7528\u4E09\u79CD\u65B9\u5F0F\u67E5\u627E\u4F60\u9700\u8981 Hook \u7684\u76EE\u6807 Class
\u3002
\u4F60\u53EF\u4EE5\u76F4\u63A5\u5C06\u88AB\u67E5\u627E\u7684 Class
\u5B8C\u6574\u5305\u540D+\u540D\u79F0\u586B\u5165 name
\u4E2D\u3002
\u793A\u4F8B\u5982\u4E0B
findClass(name = "com.example.demo.DemoClass")
+
\u82E5\u4F60\u4E0D\u786E\u5B9A\u591A\u4E2A\u7248\u672C\u7684 Class
\u4EE5\u53CA\u4E0D\u540C\u540D\u79F0\uFF0C\u4F60\u53EF\u4EE5\u5C06\u591A\u4E2A\u5B8C\u6574\u5305\u540D+\u540D\u79F0\u586B\u5165 name
\u4E2D\u3002
\u793A\u4F8B\u5982\u4E0B
findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
+
\u4F60\u8FD8\u53EF\u4EE5\u521B\u5EFA\u4E00\u4E2A VariousClass
\uFF0C\u5C06 Class
\u7684\u5B8C\u6574\u5305\u540D+\u540D\u79F0\u586B\u5165 VariousClass
\u7684 name
\u4E2D\u5E76\u586B\u5165 various
\u53C2\u6570\u4E2D\u3002
\u793A\u4F8B\u5982\u4E0B
val variousClass = VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
+
\u82E5\u4F60\u5F53\u524D\u9700\u8981\u67E5\u627E\u7684 Class
\u4E0D\u5C5E\u4E8E appClassLoader
\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 loader
\u53C2\u6570\u6307\u5B9A\u4F60\u8981\u88C5\u8F7D\u7684 ClassLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
val outsideLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u5C31\u662F\u4F60\u7684 ClassLoader
+findClass(name = "com.example.demo.OutsideClass", loader = outsideLoader)
+
\u540C\u6837\u5730\uFF0C\u5728\u4E0D\u786E\u5B9A\u591A\u4E2A\u7248\u672C\u7684 Class
\u4EE5\u53CA\u4E0D\u540C\u540D\u79F0\u65F6\uFF0C\u4E5F\u53EF\u4EE5\u4F7F\u7528 loader
\u53C2\u6570\u6307\u5B9A\u4F60\u8981\u88C5\u8F7D\u7684 ClassLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
val outsideLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u5C31\u662F\u4F60\u7684 ClassLoader
+findClass("com.example.demo.OutsideClass1", "com.example.demo.OutsideClass2", "com.example.demo.OutsideClass3", loader = outsideLoader)
+
inline fun String.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun Class<*>.hook(isForceUseAbsolute: Boolean, initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun VariousClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun HookClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u4FEE\u6539
\u65B0\u589E VariousClass
\u7684\u76F4\u63A5\u8C03\u7528 hook
\u65B9\u6CD5
v1.0.2
\u4FEE\u6539
\u65B0\u589E String
\u7684\u76F4\u63A5\u8C03\u7528 hook
\u65B9\u6CD5
v1.0.3
\u4FEE\u6539
\u65B0\u589E YukiMemberHookCreator.Result
\u8FD4\u56DE\u503C
v1.0.70
\u4FEE\u6539
\u65B0\u589E isUseAppClassLoader
\u53C2\u6570
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
\u4FEE\u6539
\u79FB\u9664\u4E86 \u53C2\u6570isUseAppClassLoader
\u6DFB\u52A0\u4E86 isForceUseAbsolute
\u53C2\u6570\u5230 Class.hook
\u65B9\u6CD5
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u4E00\u5207 Hook \u7684\u5165\u53E3\u521B\u5EFA\u65B9\u6CD5\uFF0CHook \u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u3002
\u529F\u80FD\u793A\u4F8B
\u5982\u4F60\u6240\u89C1\uFF0CHook \u65B9\u6CD5\u4F53\u7684\u521B\u5EFA\u53EF\u4F7F\u7528 4 \u79CD\u65B9\u5F0F\u3002
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u5F97\u5230 HookClass
\u5B9E\u4F8B\u8FDB\u884C\u521B\u5EFA\u3002
\u793A\u4F8B\u5982\u4E0B
"com.example.demo.DemoClass".hook {
+ // Your code here.
+}
+
+
\u901A\u8FC7 findClass
\u5F97\u5230 HookClass
\u5B9E\u4F8B\u8FDB\u884C\u521B\u5EFA\u3002
\u793A\u4F8B\u5982\u4E0B
findClass(name = "com.example.demo.DemoClass").hook {
+ // Your code here.
+}
+
\u4F7F\u7528 stub
\u6216\u76F4\u63A5\u62FF\u5230 Class
\u5B9E\u4F8B\u8FDB\u884C\u521B\u5EFA\u3002
\u9ED8\u8BA4\u60C5\u51B5\u4E0B API \u4F1A\u5C06 Class
\u5B9E\u4F8B\u8F6C\u6362\u4E3A\u7C7B\u540D\u5E76\u7ED1\u5B9A\u5230 appClassLoader
\uFF0C\u82E5\u5931\u8D25\uFF0C\u5219\u4F1A\u4F7F\u7528\u539F\u59CB Class
\u5B9E\u4F8B\u76F4\u63A5\u8FDB\u884C Hook\u3002
\u793A\u4F8B\u5982\u4E0B
Stub::class.java.hook {
+ // Your code here.
+}
+
\u82E5\u5F53\u524D Class
\u4E0D\u5728 appClassLoader
\u4E14\u81EA\u52A8\u5339\u914D\u65E0\u6CD5\u627E\u5230\u8BE5 Class
\uFF0C\u8BF7\u542F\u7528 isForceUseAbsolute
\u3002
\u793A\u4F8B\u5982\u4E0B
YourClass::class.java.hook(isForceUseAbsolute = true) {
+ // Your code here.
+}
+
\u4F7F\u7528 VariousClass
\u5B9E\u4F8B\u8FDB\u884C\u521B\u5EFA\u3002
\u793A\u4F8B\u5982\u4E0B
VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
+ // Your code here.
+}
+
\u6216\u8005\u76F4\u63A5\u4F7F\u7528\u53EF\u53D8\u5B57\u7B26\u4E32\u6570\u7EC4\u8FDB\u884C\u521B\u5EFA\u3002
\u793A\u4F8B\u5982\u4E0B
findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
+ // Your code here.
+}
+
inline fun HookResources.hook(initiate: YukiResourcesHookCreator.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Hook APP \u7684 Resources\u3002
\u7279\u522B\u6CE8\u610F
\u8BF7\u6CE8\u610F\u4F60\u9700\u8981\u786E\u4FDD\u5F53\u524D Hook Framework \u652F\u6301\u4E14 InjectYukiHookWithXposed.isUsingResourcesHook \u5DF2\u542F\u7528\u3002
\u529F\u80FD\u793A\u4F8B
Resources Hook \u4E3A\u56FA\u5B9A\u7528\u6CD5\uFF0C\u83B7\u53D6 resources
\u5BF9\u8C61\uFF0C\u7136\u540E\u8C03\u7528 hook
\u65B9\u6CD5\u5F00\u59CB Hook\u3002
\u793A\u4F8B\u5982\u4E0B
resources().hook {
+ // Your code here.
+}
+
\u7279\u522B\u6CE8\u610F
\u8FD9\u662F\u56FA\u5B9A\u7528\u6CD5\uFF0C\u4E3A\u4E86\u9632\u6B62\u53D1\u751F\u95EE\u9898\uFF0C\u4F60\u4E0D\u53EF\u624B\u52A8\u5B9E\u73B0\u4EFB\u4F55 HookResources \u5B9E\u4F8B\u6267\u884C hook \u8C03\u7528\u3002
\u5C06 Resources \u7684 Hook \u8BBE\u7F6E\u4E3A\u8FD9\u6837\u662F\u4E3A\u4E86\u4E0E findClass(...).hook
\u505A\u5230\u7EDF\u4E00\uFF0C\u4F7F\u5F97\u8C03\u7528\u8D77\u6765\u903B\u8F91\u4E0D\u4F1A\u6DF7\u4E71\u3002
inner class AppLifecycle internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D Hook APP \u7684\u751F\u547D\u5468\u671F\u5B9E\u4F8B\u5904\u7406\u7C7B\u3002
fun attachBaseContext(result: (baseContext: Context, hasCalledSuper: Boolean) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.attachBaseContext
\u3002
fun onCreate(initiate: Application.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onCreate
\u3002
fun onTerminate(initiate: Application.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onTerminate
\u3002
fun onLowMemory(initiate: Application.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onLowMemory
\u3002
fun onTrimMemory(result: (self: Application, level: Int) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onTrimMemory
\u3002
fun onConfigurationChanged(result: (self: Application, config: Configuration) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D
Application.onConfigurationChanged
\u3002
fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,380),p=[l];function c(r,t){return o(),a("div",null,p)}const i=s(n,[["render",c],["__file","PackageParam.html.vue"]]);export{i as default}; diff --git a/docs/assets/PackageParam.html.7a64d58c.js b/docs/assets/PackageParam.html.7a64d58c.js new file mode 100644 index 00000000..808c99ae --- /dev/null +++ b/docs/assets/PackageParam.html.7a64d58c.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-b381a126","path":"/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html","title":"PackageParam - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"appClassLoader - field","slug":"appclassloader-field","link":"#appclassloader-field","children":[]},{"level":2,"title":"appInfo - field","slug":"appinfo-field","link":"#appinfo-field","children":[]},{"level":2,"title":"appUserId - field","slug":"appuserid-field","link":"#appuserid-field","children":[]},{"level":2,"title":"appContext - field","slug":"appcontext-field","link":"#appcontext-field","children":[]},{"level":2,"title":"appResources - field","slug":"appresources-field","link":"#appresources-field","children":[]},{"level":2,"title":"systemContext - field","slug":"systemcontext-field","link":"#systemcontext-field","children":[]},{"level":2,"title":"processName - field","slug":"processname-field","link":"#processname-field","children":[]},{"level":2,"title":"packageName - field","slug":"packagename-field","link":"#packagename-field","children":[]},{"level":2,"title":"isFirstApplication - field","slug":"isfirstapplication-field","link":"#isfirstapplication-field","children":[]},{"level":2,"title":"mainProcessName - field","slug":"mainprocessname-field","link":"#mainprocessname-field","children":[]},{"level":2,"title":"moduleAppFilePath - field","slug":"moduleappfilepath-field","link":"#moduleappfilepath-field","children":[]},{"level":2,"title":"moduleAppResources - field","slug":"moduleappresources-field","link":"#moduleappresources-field","children":[]},{"level":2,"title":"prefs - field","slug":"prefs-field","link":"#prefs-field","children":[]},{"level":2,"title":"prefs - method","slug":"prefs-method","link":"#prefs-method","children":[]},{"level":2,"title":"dataChannel - field","slug":"datachannel-field","link":"#datachannel-field","children":[]},{"level":2,"title":"resources - method","slug":"resources-method","link":"#resources-method","children":[]},{"level":2,"title":"refreshModuleAppResources - method","slug":"refreshmoduleappresources-method","link":"#refreshmoduleappresources-method","children":[]},{"level":2,"title":"onAppLifecycle - method","slug":"onapplifecycle-method","link":"#onapplifecycle-method","children":[]},{"level":2,"title":"loadApp - method","slug":"loadapp-method","link":"#loadapp-method","children":[]},{"level":2,"title":"loadZygote - method","slug":"loadzygote-method","link":"#loadzygote-method","children":[]},{"level":2,"title":"loadSystem - method","slug":"loadsystem-method","link":"#loadsystem-method","children":[]},{"level":2,"title":"withProcess - method","slug":"withprocess-method","link":"#withprocess-method","children":[]},{"level":2,"title":"loadHooker - method","slug":"loadhooker-method","link":"#loadhooker-method","children":[]},{"level":2,"title":"searchClass - method","slug":"searchclass-method","link":"#searchclass-method","children":[]},{"level":2,"title":"String+VariousClass.toClass - i-ext-method","slug":"string-variousclass-toclass-i-ext-method","link":"#string-variousclass-toclass-i-ext-method","children":[]},{"level":2,"title":"String+VariousClass.toClassOrNull - i-ext-method","slug":"string-variousclass-toclassornull-i-ext-method","link":"#string-variousclass-toclassornull-i-ext-method","children":[]},{"level":2,"title":"String.hasClass - i-ext-method","slug":"string-hasclass-i-ext-method","link":"#string-hasclass-i-ext-method","children":[]},{"level":2,"title":"findClass - method","slug":"findclass-method","link":"#findclass-method","children":[]},{"level":2,"title":"String+Class+VariousClass+HookClass.hook - i-ext-method","slug":"string-class-variousclass-hookclass-hook-i-ext-method","link":"#string-class-variousclass-hookclass-hook-i-ext-method","children":[]},{"level":2,"title":"HookResources.hook - i-ext-method","slug":"hookresources-hook-i-ext-method","link":"#hookresources-hook-i-ext-method","children":[]},{"level":2,"title":"AppLifecycle - class","slug":"applifecycle-class","link":"#applifecycle-class","children":[{"level":3,"title":"attachBaseContext - method","slug":"attachbasecontext-method","link":"#attachbasecontext-method","children":[]},{"level":3,"title":"onCreate - method","slug":"oncreate-method","link":"#oncreate-method","children":[]},{"level":3,"title":"onTerminate - method","slug":"onterminate-method","link":"#onterminate-method","children":[]},{"level":3,"title":"onLowMemory - method","slug":"onlowmemory-method","link":"#onlowmemory-method","children":[]},{"level":3,"title":"onTrimMemory - method","slug":"ontrimmemory-method","link":"#ontrimmemory-method","children":[]},{"level":3,"title":"onConfigurationChanged - method","slug":"onconfigurationchanged-method","link":"#onconfigurationchanged-method","children":[]},{"level":3,"title":"registerReceiver - method","slug":"registerreceiver-method","link":"#registerreceiver-method","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.md"}');export{e as data}; diff --git a/docs/assets/PrefsData.html.0d8e9948.js b/docs/assets/PrefsData.html.0d8e9948.js new file mode 100644 index 00000000..0ad483e3 --- /dev/null +++ b/docs/assets/PrefsData.html.0d8e9948.js @@ -0,0 +1,18 @@ +import{_ as s,o as a,c as n,a as l}from"./app.fb8271cf.js";const o={},p=l(`\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\u76D1\u542C\u3002
data class PrefsData<T>(var key: String, var value: T)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u952E\u503C\u5BF9\u5B58\u50A8\u6784\u9020\u7C7B\u3002
\u8FD9\u4E2A\u7C7B\u662F\u5BF9 YukiHookModulePrefs
\u7684\u4E00\u4E2A\u6269\u5C55\u7528\u6CD5\u3002
\u529F\u80FD\u793A\u4F8B
\u5EFA\u7ACB\u4E00\u4E2A\u6A21\u677F\u7C7B\u5B9A\u4E49\u6A21\u5757\u4E0E\u5BBF\u4E3B\u9700\u8981\u4F7F\u7528\u7684\u952E\u503C\u6570\u636E\u3002
\u793A\u4F8B\u5982\u4E0B
object DataConst {
+
+ val TEST_KV_DATA_1 = PrefsData("test_data_1", "defalut value")
+ val TEST_KV_DATA_2 = PrefsData("test_data_2", false)
+ val TEST_KV_DATA_3 = PrefsData("test_data_3", 0)
+}
+
\u952E\u503C\u6570\u636E\u5B9A\u4E49\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u65B9\u4FBF\u5730\u5728\u6A21\u5757\u548C\u5BBF\u4E3B\u4E2D\u8C03\u7528\u6240\u9700\u8981\u7684\u6570\u636E\u3002
\u6A21\u5757\u793A\u4F8B\u5982\u4E0B
// \u8BFB\u53D6
+val data = modulePrefs.get(DataConst.TEST_KV_DATA_1)
+// \u5199\u5165
+modulePrefs.put(DataConst.TEST_KV_DATA_1, "written value")
+
\u5BBF\u4E3B\u793A\u4F8B\u5982\u4E0B
// \u8BFB\u53D6 String
+val dataString = prefs.get(DataConst.TEST_KV_DATA_1)
+// \u8BFB\u53D6 Boolean
+val dataBoolean = prefs.get(DataConst.TEST_KV_DATA_2)
+
\u4F60\u4F9D\u7136\u53EF\u4EE5\u4E0D\u4F7F\u7528\u6A21\u677F\u5B9A\u4E49\u7684\u9ED8\u8BA4\u503C\uFF0C\u968F\u65F6\u4FEE\u6539\u4F60\u7684\u9ED8\u8BA4\u503C\u3002
\u793A\u4F8B\u5982\u4E0B
// \u8BFB\u53D6 - \u6B64\u65F6 data \u53D6\u5230\u7684\u9ED8\u8BA4\u503C\u5C06\u4F1A\u662F 2 - \u5E76\u4E0D\u662F\u6A21\u677F\u63D0\u4F9B\u7684 0
+val data = prefs.get(DataConst.TEST_KV_DATA_3, 2)
+
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
data class PrefsData<T>(var key: String, var value: T)
+
Change Records
v1.0.67
added
Function Illustrate
\u952E\u503C\u5BF9\u5B58\u50A8\u6784\u9020\u7C7B\u3002
\u8FD9\u4E2A\u7C7B\u662F\u5BF9 YukiHookModulePrefs
\u7684\u4E00\u4E2A\u6269\u5C55\u7528\u6CD5\u3002
Function Example
\u5EFA\u7ACB\u4E00\u4E2A\u6A21\u677F\u7C7B\u5B9A\u4E49\u6A21\u5757\u4E0E\u5BBF\u4E3B\u9700\u8981\u4F7F\u7528\u7684\u952E\u503C\u6570\u636E\u3002
The following example
object DataConst {
+
+ val TEST_KV_DATA_1 = PrefsData("test_data_1", "defalut value")
+ val TEST_KV_DATA_2 = PrefsData("test_data_2", false)
+ val TEST_KV_DATA_3 = PrefsData("test_data_3", 0)
+}
+
\u952E\u503C\u6570\u636E\u5B9A\u4E49\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u65B9\u4FBF\u5730\u5728\u6A21\u5757\u548C\u5BBF\u4E3B\u4E2D\u8C03\u7528\u6240\u9700\u8981\u7684\u6570\u636E\u3002
\u6A21\u5757\u793A\u4F8B\u5982\u4E0B
// \u8BFB\u53D6
+val data = modulePrefs.get(DataConst.TEST_KV_DATA_1)
+// \u5199\u5165
+modulePrefs.put(DataConst.TEST_KV_DATA_1, "written value")
+
\u5BBF\u4E3B\u793A\u4F8B\u5982\u4E0B
// \u8BFB\u53D6 String
+val dataString = prefs.get(DataConst.TEST_KV_DATA_1)
+// \u8BFB\u53D6 Boolean
+val dataBoolean = prefs.get(DataConst.TEST_KV_DATA_2)
+
\u4F60\u4F9D\u7136\u53EF\u4EE5\u4E0D\u4F7F\u7528\u6A21\u677F\u5B9A\u4E49\u7684\u9ED8\u8BA4\u503C\uFF0C\u968F\u65F6\u4FEE\u6539\u4F60\u7684\u9ED8\u8BA4\u503C\u3002
The following example
// \u8BFB\u53D6 - \u6B64\u65F6 data \u53D6\u5230\u7684\u9ED8\u8BA4\u503C\u5C06\u4F1A\u662F 2 - \u5E76\u4E0D\u662F\u6A21\u677F\u63D0\u4F9B\u7684 0
+val data = prefs.get(DataConst.TEST_KV_DATA_3, 2)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u81EA\u5B9A\u4E49
Member
\u548CClass
\u76F8\u5173\u529F\u80FD\u7684\u67E5\u627E\u5339\u914D\u4EE5\u53CAinvoke
\u7684\u5C01\u88C5\u7C7B\u3002
enum class MembersType
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5B9A\u4E49\u4E00\u4E2A
Class
\u4E2D\u7684Member
\u7C7B\u578B
ALL
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5168\u90E8
Method
\u4E0EConstructor
\u3002
METHOD
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5168\u90E8
Method
\u3002
CONSTRUCTOR
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5168\u90E8
Constructor
\u3002
inline fun ClassLoader.searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u5F53\u524D
ClassLoader
\u6309\u6307\u5B9A\u6761\u4EF6\u67E5\u627E\u5E76\u5F97\u5230 Dex \u4E2D\u7684Class
\u3002
\u7279\u522B\u6CE8\u610F
\u6B64\u65B9\u6CD5\u5728 Class \u6570\u91CF\u8FC7\u591A\u53CA\u67E5\u627E\u6761\u4EF6\u590D\u6742\u65F6\u4F1A\u975E\u5E38\u8017\u65F6\u3002
\u5EFA\u8BAE\u542F\u7528 async \u6216\u8BBE\u7F6E name \u53C2\u6570\uFF0Cname \u53C2\u6570\u5C06\u5728 Hook APP (\u5BBF\u4E3B) \u4E0D\u540C\u7248\u672C\u4E2D\u81EA\u52A8\u8FDB\u884C\u672C\u5730\u7F13\u5B58\u4EE5\u63D0\u5347\u6548\u7387\u3002
\u6B64\u529F\u80FD\u5C1A\u5728\u8BD5\u9A8C\u9636\u6BB5\uFF0C\u6027\u80FD\u4E0E\u7A33\u5B9A\u6027\u53EF\u80FD\u4ECD\u7136\u5B58\u5728\u95EE\u9898\uFF0C\u4F7F\u7528\u8FC7\u7A0B\u9047\u5230\u95EE\u9898\u8BF7\u5411\u6211\u4EEC\u62A5\u544A\u5E76\u5E2E\u52A9\u6211\u4EEC\u6539\u8FDB\u3002
fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5F53\u524D
ClassLoader
\u7684ClassLoader.loadClass
\u65B9\u6CD5\u88C5\u8F7D\u3002
\u7279\u522B\u6CE8\u610F
\u53EA\u6709\u5F53\u524D ClassLoader \u6709\u4E3B\u52A8\u4F7F\u7528 ClassLoader.loadClass \u4E8B\u4EF6\u65F6\u624D\u80FD\u88AB\u6355\u83B7\u3002
\u8FD9\u662F\u4E00\u4E2A\u5B9E\u9A8C\u6027\u529F\u80FD\uFF0C\u4E00\u822C\u60C5\u51B5\u4E0B\u4E0D\u4F1A\u7528\u5230\u6B64\u65B9\u6CD5\uFF0C\u4E0D\u4FDD\u8BC1\u4E0D\u4F1A\u53D1\u751F\u9519\u8BEF\u3002
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u5176\u5B83\u73AF\u5883\u4E0B\u4F7F\u7528\u5C06\u4E0D\u751F\u6548\u4E14\u4F1A\u6253\u5370\u8B66\u544A\u4FE1\u606F\u3002
\u529F\u80FD\u793A\u4F8B
\u9488\u5BF9\u4E00\u4E9B\u4F7F\u7528\u7279\u5B9A ClassLoader
\u88C5\u8F7D Class
\u7684\u5BBF\u4E3B\u5E94\u7528\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6765\u76D1\u542C Class
\u52A0\u8F7D\u60C5\u51B5\u3002
\u6CE8\u610F
\u4E3A\u4E86\u9632\u6B62\u53D1\u751F\u95EE\u9898\uFF0C\u4F60\u9700\u8981\u5F97\u5230\u4E00\u4E2A\u5B58\u5728\u7684 ClassLoader \u5B9E\u4F8B\u6765\u4F7F\u7528\u6B64\u529F\u80FD\u3002
\u6BD4\u5982\u6211\u4EEC\u5728 PackageParam
\u4E2D\u4F7F\u7528 appClassLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
appClassLoader.onLoadClass { clazz ->
+ // \u5F97\u5230 clazz \u5373\u52A0\u8F7D\u5BF9\u8C61
+ clazz... // \u8FD9\u91CC\u8FDB\u884C\u4F60\u9700\u8981\u7684\u64CD\u4F5C
+}
+
\u6216\u4F7F\u7528\u4F60\u5F97\u5230\u7684\u5B58\u5728\u7684 ClassLoader
\u5B9E\u4F8B\uFF0C\u53EF\u4EE5\u901A\u8FC7 Hook \u83B7\u53D6\u3002
\u793A\u4F8B\u5982\u4E0B
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+customClassLoader?.onLoadClass { clazz ->
+ // ...
+}
+
\u5728\u5224\u65AD\u5230\u8FD9\u4E2A Class
\u88AB\u88C5\u8F7D\u6210\u529F\u65F6\uFF0C\u5F00\u59CB\u6267\u884C\u4F60\u7684 Hook \u529F\u80FD\u3002
\u793A\u4F8B\u5982\u4E0B
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+customClassLoader?.onLoadClass { clazz ->
+ if(clazz.name == /** \u4F60\u9700\u8981\u7684 Class \u540D\u79F0 */) {
+ clazz.hook {
+ // ...
+ }
+ }
+}
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u79FB\u9664
HookClass
\u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u79FB\u9664
HookClass
\u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u79FB\u9664
\u8BF7\u76F4\u63A5\u4F7F\u7528 hasClass()
\u65E0\u53C2\u65B9\u6CD5
val Class<*>.hasExtends: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D
Class
\u662F\u5426\u6709\u7EE7\u627F\u5173\u7CFB\uFF0C\u7236\u7C7B\u662FAny
\u5C06\u88AB\u8BA4\u4E3A\u6CA1\u6709\u7EE7\u627F\u5173\u7CFB\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u5230 toClass(...)
\u65B9\u6CD5
fun String.toClass(loader: ClassLoader?): Class<*>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u8F6C\u6362\u4E3A
loader
\u4E2D\u7684\u5B9E\u4F53\u7C7B\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u76F4\u63A5\u586B\u5199\u4F60\u8981\u67E5\u627E\u7684\u76EE\u6807 Class
\uFF0C\u5FC5\u987B\u5728\u9ED8\u8BA4 ClassLoader
\u4E0B\u5B58\u5728\u3002
\u793A\u4F8B\u5982\u4E0B
"com.example.demo.DemoClass".toClass()
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 Class
\u6240\u5728\u7684 ClassLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u8F6C\u6362\u4E3A
loader
\u4E2D\u7684\u5B9E\u4F53\u7C7B\u3002
\u627E\u4E0D\u5230 Class
\u4F1A\u8FD4\u56DE null
\uFF0C\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
\u529F\u80FD\u793A\u4F8B
\u7528\u6CD5\u8BF7\u53C2\u8003 String.toClass \u65B9\u6CD5\u3002
inline fun <reified T> classOf(loader: ClassLoader?): Class<*>
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7
T
\u5F97\u5230\u5176Class
\u5B9E\u4F8B\u5E76\u8F6C\u6362\u4E3A\u5B9E\u4F53\u7C7B\u3002
\u529F\u80FD\u793A\u4F8B
\u6211\u4EEC\u8981\u83B7\u53D6\u4E00\u4E2A Class
\u5728 Kotlin
\u4E0B\u4E0D\u901A\u8FC7\u53CD\u5C04\u65F6\u5E94\u8BE5\u8FD9\u6837\u505A\u3002
\u793A\u4F8B\u5982\u4E0B
DemoClass::class.java
+
\u73B0\u5728\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5 cast
\u4E00\u4E2A\u5B9E\u4F8B\u5E76\u83B7\u53D6\u5B83\u7684 Class
\u5BF9\u8C61\uFF0C\u5FC5\u987B\u5728\u5F53\u524D ClassLoader
\u4E0B\u5B58\u5728\u3002
\u793A\u4F8B\u5982\u4E0B
classOf<DemoClass>()
+
\u82E5\u76EE\u6807\u5B58\u5728\u7684 Class
\u4E3A stub
\uFF0C\u901A\u8FC7\u8FD9\u79CD\u65B9\u5F0F\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 Class
\u6240\u5728\u7684 ClassLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+classOf<DemoClass>(customClassLoader)
+
fun String.hasClass(loader: ClassLoader?): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u652F\u6301\u76F4\u63A5\u4F7F\u7528\u7A7A\u53C2\u6570\u65B9\u6CD5\u4F7F\u7528\u9ED8\u8BA4 ClassLoader
\u8FDB\u884C\u5224\u65AD
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u4F7F\u7528\u6307\u5B9A\u7684
ClassLoader
\u67E5\u627E\u662F\u5426\u5B58\u5728\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u8F7B\u677E\u7684\u4F7F\u7528\u6B64\u65B9\u6CD5\u5224\u65AD\u5B57\u7B26\u4E32\u4E2D\u7684\u7C7B\u662F\u5426\u5B58\u5728\uFF0C\u6548\u679C\u7B49\u540C\u4E8E\u76F4\u63A5\u4F7F\u7528 Class.forName
\u3002
\u793A\u4F8B\u5982\u4E0B
if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
\u586B\u5165\u65B9\u6CD5\u4E2D\u7684 loader
\u53C2\u6570\u53EF\u5224\u65AD\u6307\u5B9A\u7684 ClassLoader
\u4E2D\u7684 Class
\u662F\u5426\u5B58\u5728\u3002
\u793A\u4F8B\u5982\u4E0B
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.4
\u65B0\u589E
v1.0.67
\u4FEE\u6539
\u5408\u5E76\u5230 FieldFinder
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u53D8\u91CF\u662F\u5426\u5B58\u5728\u3002
inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u4FEE\u6539
\u65B0\u589E returnType
\u53C2\u6570
v1.0.67
\u4FEE\u6539
\u5408\u5E76\u5230 MethodFinder
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u65B9\u6CD5\u662F\u5426\u5B58\u5728\u3002
inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
v1.0.67
\u4FEE\u6539
\u5408\u5E76\u5230 ConstructorFinder
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u6784\u9020\u65B9\u6CD5\u662F\u5426\u5B58\u5728\u3002
inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
\u4FEE\u6539
\u5408\u5E76\u5230 ModifierConditions
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E
Member
\u4E2D\u5339\u914D\u7684\u63CF\u8FF0\u7B26\u3002
inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E
Class
\u4E2D\u5339\u914D\u7684\u63CF\u8FF0\u7B26\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u79FB\u9664
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u79FB\u9664
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u79FB\u9664
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u79FB\u9664
inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u5E76\u5F97\u5230\u53D8\u91CF\u3002
inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u4FEE\u6539
\u66F4\u540D\u4E3A obtainMethod
method
\u65B0\u589E returnType
\u53C2\u6570
v1.0.2
\u4FEE\u6539
\u5408\u5E76\u5230 MethodFinder
\u65B9\u6CD5\u4F53
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u5E76\u5F97\u5230\u65B9\u6CD5\u3002
inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u4FEE\u6539
\u66F4\u540D\u4E3A obtainConstructor
constructor
v1.0.2
\u4FEE\u6539
\u5408\u5E76\u5230 ConstructorFinder
\u65B9\u6CD5\u4F53
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u5E76\u5F97\u5230\u6784\u9020\u65B9\u6CD5\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u4FEE\u6539
\u66F4\u540D\u4E3A invokeStatic
callStatic
v1.0.2
\u79FB\u9664
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.1
\u4FEE\u6539
\u66F4\u540D\u4E3A invokeAny
call
v1.0.2
\u79FB\u9664
fun Class<*>.generic(): GenericClass?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D
Class
\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D
Class
\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
+
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
v1.1.0
\u65B0\u589E
\u65B0\u589E ignored
\u53C2\u6570\uFF0C\u53EF\u4EE5\u5FFD\u7565\u5728 CurrentClass
\u4E2D\u51FA\u73B0\u7684\u5F02\u5E38
\u65B0\u589E\u4E0D\u4F7F\u7528 current { ... }
\u8C03\u7528\u57DF\u76F4\u63A5\u4F7F\u7528 current()
\u5F97\u5230\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230 buildOf
\u65B9\u6CD5
inline fun Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): Any?
+
inline fun <T> Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
\u4FEE\u6539
\u52A0\u5165\u65E0\u6CDB\u578B\u65B9\u6CD5 buildOf
\u529F\u80FD\u63CF\u8FF0
\u901A\u8FC7\u6784\u9020\u65B9\u6CD5\u521B\u5EFA\u65B0\u5B9E\u4F8B\uFF0C\u6307\u5B9A\u7C7B\u578B
T
\u6216\u4EFB\u610F\u7C7B\u578BAny
\u3002
inline fun Class<*>.allMethods(result: (index: Int, method: Method) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u904D\u5386\u5F53\u524D\u7C7B\u4E2D\u7684\u6240\u6709\u65B9\u6CD5\u3002
inline fun Class<*>.allConstructors(result: (index: Int, constructor: Constructor<*>) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u904D\u5386\u5F53\u524D\u7C7B\u4E2D\u7684\u6240\u6709\u6784\u9020\u65B9\u6CD5\u3002
inline fun Class<*>.allFields(result: (index: Int, field: Field) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
`,309),p=[l];function c(t,r){return o(),a("div",null,p)}const i=s(n,[["render",c],["__file","ReflectionFactory.html.vue"]]);export{i as default}; diff --git a/docs/assets/ReflectionFactory.html.daab3686.js b/docs/assets/ReflectionFactory.html.daab3686.js new file mode 100644 index 00000000..3482e786 --- /dev/null +++ b/docs/assets/ReflectionFactory.html.daab3686.js @@ -0,0 +1,59 @@ +import{_ as s,o,c as e,a}from"./app.fb8271cf.js";const n={},l=a(`\u904D\u5386\u5F53\u524D\u7C7B\u4E2D\u7684\u6240\u6709\u53D8\u91CF\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0
first
Function Illustrate
\u8FD9\u662F\u81EA\u5B9A\u4E49
Member
\u548CClass
\u76F8\u5173\u529F\u80FD\u7684\u67E5\u627E\u5339\u914D\u4EE5\u53CAinvoke
\u7684\u5C01\u88C5\u7C7B\u3002
enum class MembersType
+
Change Records
v1.1.0
added
Function Illustrate
\u5B9A\u4E49\u4E00\u4E2A
Class
\u4E2D\u7684Member
\u7C7B\u578B
ALL
+
Change Records
v1.1.0
added
Function Illustrate
\u5168\u90E8
Method
\u4E0EConstructor
\u3002
METHOD
+
Change Records
v1.1.0
added
Function Illustrate
\u5168\u90E8
Method
\u3002
CONSTRUCTOR
+
Change Records
v1.1.0
added
Function Illustrate
\u5168\u90E8
Constructor
\u3002
inline fun ClassLoader.searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
Change Records
v1.1.0
added
Function Illustrate
\u901A\u8FC7\u5F53\u524D
ClassLoader
\u6309\u6307\u5B9A\u6761\u4EF6\u67E5\u627E\u5E76\u5F97\u5230 Dex \u4E2D\u7684Class
\u3002
Pay Attention
\u6B64\u65B9\u6CD5\u5728 Class \u6570\u91CF\u8FC7\u591A\u53CA\u67E5\u627E\u6761\u4EF6\u590D\u6742\u65F6\u4F1A\u975E\u5E38\u8017\u65F6\u3002
\u5EFA\u8BAE\u542F\u7528 async \u6216\u8BBE\u7F6E name \u53C2\u6570\uFF0Cname \u53C2\u6570\u5C06\u5728 Hook APP (\u5BBF\u4E3B) \u4E0D\u540C\u7248\u672C\u4E2D\u81EA\u52A8\u8FDB\u884C\u672C\u5730\u7F13\u5B58\u4EE5\u63D0\u5347\u6548\u7387\u3002
\u6B64\u529F\u80FD\u5C1A\u5728\u8BD5\u9A8C\u9636\u6BB5\uFF0C\u6027\u80FD\u4E0E\u7A33\u5B9A\u6027\u53EF\u80FD\u4ECD\u7136\u5B58\u5728\u95EE\u9898\uFF0C\u4F7F\u7528\u8FC7\u7A0B\u9047\u5230\u95EE\u9898\u8BF7\u5411\u6211\u4EEC\u62A5\u544A\u5E76\u5E2E\u52A9\u6211\u4EEC\u6539\u8FDB\u3002
fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u76D1\u542C\u5F53\u524D
ClassLoader
\u7684ClassLoader.loadClass
\u65B9\u6CD5\u88C5\u8F7D\u3002
Pay Attention
\u53EA\u6709\u5F53\u524D ClassLoader \u6709\u4E3B\u52A8\u4F7F\u7528 ClassLoader.loadClass \u4E8B\u4EF6\u65F6\u624D\u80FD\u88AB\u6355\u83B7\u3002
\u8FD9\u662F\u4E00\u4E2A\u5B9E\u9A8C\u6027\u529F\u80FD\uFF0C\u4E00\u822C\u60C5\u51B5\u4E0B\u4E0D\u4F1A\u7528\u5230\u6B64\u65B9\u6CD5\uFF0C\u4E0D\u4FDD\u8BC1\u4E0D\u4F1A\u53D1\u751F\u9519\u8BEF\u3002
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u5176\u5B83\u73AF\u5883\u4E0B\u4F7F\u7528\u5C06\u4E0D\u751F\u6548\u4E14\u4F1A\u6253\u5370\u8B66\u544A\u4FE1\u606F\u3002
Function Example
\u9488\u5BF9\u4E00\u4E9B\u4F7F\u7528\u7279\u5B9A ClassLoader
\u88C5\u8F7D Class
\u7684\u5BBF\u4E3B\u5E94\u7528\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528\u6B64\u65B9\u6CD5\u6765\u76D1\u542C Class
\u52A0\u8F7D\u60C5\u51B5\u3002
Notice
\u4E3A\u4E86\u9632\u6B62\u53D1\u751F\u95EE\u9898\uFF0C\u4F60\u9700\u8981\u5F97\u5230\u4E00\u4E2A\u5B58\u5728\u7684 ClassLoader \u5B9E\u4F8B\u6765\u4F7F\u7528\u6B64\u529F\u80FD\u3002
\u6BD4\u5982\u6211\u4EEC\u5728 PackageParam
\u4E2D\u4F7F\u7528 appClassLoader
\u3002
The following example
appClassLoader.onLoadClass { clazz ->
+ // \u5F97\u5230 clazz \u5373\u52A0\u8F7D\u5BF9\u8C61
+ clazz... // \u8FD9\u91CC\u8FDB\u884C\u4F60\u9700\u8981\u7684\u64CD\u4F5C
+}
+
\u6216\u4F7F\u7528\u4F60\u5F97\u5230\u7684\u5B58\u5728\u7684 ClassLoader
\u5B9E\u4F8B\uFF0C\u53EF\u4EE5\u901A\u8FC7 Hook \u83B7\u53D6\u3002
The following example
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+customClassLoader?.onLoadClass { clazz ->
+ // ...
+}
+
\u5728\u5224\u65AD\u5230\u8FD9\u4E2A Class
\u88AB\u88C5\u8F7D\u6210\u529F\u65F6\uFF0C\u5F00\u59CB\u6267\u884C\u4F60\u7684 Hook \u529F\u80FD\u3002
The following example
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+customClassLoader?.onLoadClass { clazz ->
+ if(clazz.name == /** \u4F60\u9700\u8981\u7684 Class \u540D\u79F0 */) {
+ clazz.hook {
+ // ...
+ }
+ }
+}
+
Change Records
v1.0
first
v1.1.0
removed
HookClass
\u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E
Change Records
v1.0
first
v1.1.0
removed
HookClass
\u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E
Change Records
v1.0
first
v1.1.0
removed
\u8BF7\u76F4\u63A5\u4F7F\u7528 hasClass()
\u65E0\u53C2\u65B9\u6CD5
val Class<*>.hasExtends: Boolean
+
Change Records
v1.0.80
added
Function Illustrate
\u5F53\u524D
Class
\u662F\u5426\u6709\u7EE7\u627F\u5173\u7CFB\uFF0C\u7236\u7C7B\u662FAny
\u5C06\u88AB\u8BA4\u4E3A\u6CA1\u6709\u7EE7\u627F\u5173\u7CFB\u3002
Change Records
v1.0
first
v1.1.0
deprecated
\u8BF7\u8F6C\u5230 toClass(...)
\u65B9\u6CD5
fun String.toClass(loader: ClassLoader?): Class<*>
+
Change Records
v1.1.0
added
Function Illustrate
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u8F6C\u6362\u4E3A
loader
\u4E2D\u7684\u5B9E\u4F53\u7C7B\u3002
Function Example
\u4F60\u53EF\u4EE5\u76F4\u63A5\u586B\u5199\u4F60\u8981\u67E5\u627E\u7684\u76EE\u6807 Class
\uFF0C\u5FC5\u987B\u5728\u9ED8\u8BA4 ClassLoader
\u4E0B\u5B58\u5728\u3002
The following example
"com.example.demo.DemoClass".toClass()
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 Class
\u6240\u5728\u7684 ClassLoader
\u3002
The following example
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
+
Change Records
v1.1.0
added
Function Illustrate
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u8F6C\u6362\u4E3A
loader
\u4E2D\u7684\u5B9E\u4F53\u7C7B\u3002
\u627E\u4E0D\u5230 Class
\u4F1A\u8FD4\u56DE null
\uFF0C\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
Function Example
\u7528\u6CD5\u8BF7\u53C2\u8003 String.toClass \u65B9\u6CD5\u3002
inline fun <reified T> classOf(loader: ClassLoader?): Class<*>
+
Change Records
v1.1.0
added
Function Illustrate
\u901A\u8FC7
T
\u5F97\u5230\u5176Class
\u5B9E\u4F8B\u5E76\u8F6C\u6362\u4E3A\u5B9E\u4F53\u7C7B\u3002
Function Example
\u6211\u4EEC\u8981\u83B7\u53D6\u4E00\u4E2A Class
\u5728 Kotlin
\u4E0B\u4E0D\u901A\u8FC7\u53CD\u5C04\u65F6\u5E94\u8BE5\u8FD9\u6837\u505A\u3002
The following example
DemoClass::class.java
+
\u73B0\u5728\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5 cast
\u4E00\u4E2A\u5B9E\u4F8B\u5E76\u83B7\u53D6\u5B83\u7684 Class
\u5BF9\u8C61\uFF0C\u5FC5\u987B\u5728\u5F53\u524D ClassLoader
\u4E0B\u5B58\u5728\u3002
The following example
classOf<DemoClass>()
+
\u82E5\u76EE\u6807\u5B58\u5728\u7684 Class
\u4E3A stub
\uFF0C\u901A\u8FC7\u8FD9\u79CD\u65B9\u5F0F\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 Class
\u6240\u5728\u7684 ClassLoader
\u3002
The following example
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+classOf<DemoClass>(customClassLoader)
+
fun String.hasClass(loader: ClassLoader?): Boolean
+
Change Records
v1.0
first
v1.1.0
modified
\u652F\u6301\u76F4\u63A5\u4F7F\u7528\u7A7A\u53C2\u6570\u65B9\u6CD5\u4F7F\u7528\u9ED8\u8BA4 ClassLoader
\u8FDB\u884C\u5224\u65AD
Function Illustrate
\u901A\u8FC7\u5B57\u7B26\u4E32\u7C7B\u540D\u4F7F\u7528\u6307\u5B9A\u7684
ClassLoader
\u67E5\u627E\u662F\u5426\u5B58\u5728\u3002
Function Example
\u4F60\u53EF\u4EE5\u8F7B\u677E\u7684\u4F7F\u7528\u6B64\u65B9\u6CD5\u5224\u65AD\u5B57\u7B26\u4E32\u4E2D\u7684\u7C7B\u662F\u5426\u5B58\u5728\uFF0C\u6548\u679C\u7B49\u540C\u4E8E\u76F4\u63A5\u4F7F\u7528 Class.forName
\u3002
The following example
if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
\u586B\u5165\u65B9\u6CD5\u4E2D\u7684 loader
\u53C2\u6570\u53EF\u5224\u65AD\u6307\u5B9A\u7684 ClassLoader
\u4E2D\u7684 Class
\u662F\u5426\u5B58\u5728\u3002
The following example
val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
+
Change Records
v1.0.4
added
v1.0.67
modified
\u5408\u5E76\u5230 FieldFinder
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u67E5\u627E\u53D8\u91CF\u662F\u5426\u5B58\u5728\u3002
inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
+
Change Records
v1.0
first
v1.0.1
modified
\u65B0\u589E returnType
\u53C2\u6570
v1.0.67
modified
\u5408\u5E76\u5230 MethodFinder
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u67E5\u627E\u65B9\u6CD5\u662F\u5426\u5B58\u5728\u3002
inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
+
Change Records
v1.0.2
added
v1.0.67
modified
\u5408\u5E76\u5230 ConstructorFinder
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u67E5\u627E\u6784\u9020\u65B9\u6CD5\u662F\u5426\u5B58\u5728\u3002
inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
+
Change Records
v1.0.67
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
modified
\u5408\u5E76\u5230 ModifierConditions
Function Illustrate
\u67E5\u627E
Member
\u4E2D\u5339\u914D\u7684\u63CF\u8FF0\u7B26\u3002
inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u67E5\u627E
Class
\u4E2D\u5339\u914D\u7684\u63CF\u8FF0\u7B26\u3002
Change Records
v1.0
first
v1.0.1
removed
Change Records
v1.0
first
v1.0.1
removed
Change Records
v1.0
first
v1.0.1
removed
Change Records
v1.0
first
v1.0.1
removed
inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
+
Change Records
v1.0.2
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u67E5\u627E\u5E76\u5F97\u5230\u53D8\u91CF\u3002
inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
+
Change Records
v1.0
first
v1.0.1
modified
\u66F4\u540D\u4E3A obtainMethod
method
\u65B0\u589E returnType
\u53C2\u6570
v1.0.2
modified
\u5408\u5E76\u5230 MethodFinder
\u65B9\u6CD5\u4F53
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u67E5\u627E\u5E76\u5F97\u5230\u65B9\u6CD5\u3002
inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
Change Records
v1.0
first
v1.0.1
modified
\u66F4\u540D\u4E3A obtainConstructor
constructor
v1.0.2
modified
\u5408\u5E76\u5230 ConstructorFinder
\u65B9\u6CD5\u4F53
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u67E5\u627E\u5E76\u5F97\u5230\u6784\u9020\u65B9\u6CD5\u3002
Change Records
v1.0
first
v1.0.1
modified
\u66F4\u540D\u4E3A invokeStatic
callStatic
v1.0.2
removed
Change Records
v1.0
first
v1.0.1
modified
\u66F4\u540D\u4E3A invokeAny
call
v1.0.2
removed
fun Class<*>.generic(): GenericClass?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D
Class
\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D
Class
\u7684\u6CDB\u578B\u7236\u7C7B\u3002
\u5982\u679C\u5F53\u524D\u5B9E\u4F8B\u4E0D\u5B58\u5728\u6CDB\u578B\u5C06\u8FD4\u56DE null
\u3002
inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
+
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
+
Change Records
v1.0.70
added
v1.1.0
added
\u65B0\u589E ignored
\u53C2\u6570\uFF0C\u53EF\u4EE5\u5FFD\u7565\u5728 CurrentClass
\u4E2D\u51FA\u73B0\u7684\u5F02\u5E38
\u65B0\u589E\u4E0D\u4F7F\u7528 current { ... }
\u8C03\u7528\u57DF\u76F4\u63A5\u4F7F\u7528 current()
\u5F97\u5230\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61
Function Illustrate
\u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61\u3002
Change Records
v1.0.70
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
deprecated
\u8BF7\u8F6C\u79FB\u5230 buildOf
\u65B9\u6CD5
inline fun Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): Any?
+
inline fun <T> Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): T?
+
Change Records
v1.0.70
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
v1.1.0
modified
\u52A0\u5165\u65E0\u6CDB\u578B\u65B9\u6CD5 buildOf
Function Illustrate
\u901A\u8FC7\u6784\u9020\u65B9\u6CD5\u521B\u5EFA\u65B0\u5B9E\u4F8B\uFF0C\u6307\u5B9A\u7C7B\u578B
T
\u6216\u4EFB\u610F\u7C7B\u578BAny
\u3002
inline fun Class<*>.allMethods(result: (index: Int, method: Method) -> Unit)
+
Change Records
v1.0.70
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u904D\u5386\u5F53\u524D\u7C7B\u4E2D\u7684\u6240\u6709\u65B9\u6CD5\u3002
inline fun Class<*>.allConstructors(result: (index: Int, constructor: Constructor<*>) -> Unit)
+
Change Records
v1.0.70
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u904D\u5386\u5F53\u524D\u7C7B\u4E2D\u7684\u6240\u6709\u6784\u9020\u65B9\u6CD5\u3002
inline fun Class<*>.allFields(result: (index: Int, field: Field) -> Unit)
+
Change Records
v1.0.70
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
`,310),p=[l];function c(t,r){return o(),e("div",null,p)}const i=s(n,[["render",c],["__file","ReflectionFactory.html.vue"]]);export{i as default}; diff --git a/docs/assets/ReflectionFactory.html.f7b7c82c.js b/docs/assets/ReflectionFactory.html.f7b7c82c.js new file mode 100644 index 00000000..baf72260 --- /dev/null +++ b/docs/assets/ReflectionFactory.html.f7b7c82c.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-213d88b3","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html","title":"ReflectionFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"MembersType - class","slug":"memberstype-class","link":"#memberstype-class","children":[{"level":3,"title":"ALL - enum","slug":"all-enum","link":"#all-enum","children":[]},{"level":3,"title":"METHOD - enum","slug":"method-enum","link":"#method-enum","children":[]},{"level":3,"title":"CONSTRUCTOR - enum","slug":"constructor-enum","link":"#constructor-enum","children":[]}]},{"level":2,"title":"ClassLoader.searchClass - ext-method","slug":"classloader-searchclass-ext-method","link":"#classloader-searchclass-ext-method","children":[]},{"level":2,"title":"ClassLoader.onLoadClass - ext-method","slug":"classloader-onloadclass-ext-method","link":"#classloader-onloadclass-ext-method","children":[]},{"level":2,"title":"Class.hasExtends - ext-field","slug":"class-hasextends-ext-field","link":"#class-hasextends-ext-field","children":[]},{"level":2,"title":"String.toClass - ext-method","slug":"string-toclass-ext-method","link":"#string-toclass-ext-method","children":[]},{"level":2,"title":"String.toClassOrNull - ext-method","slug":"string-toclassornull-ext-method","link":"#string-toclassornull-ext-method","children":[]},{"level":2,"title":"classOf - method","slug":"classof-method","link":"#classof-method","children":[]},{"level":2,"title":"String.hasClass - ext-method","slug":"string-hasclass-ext-method","link":"#string-hasclass-ext-method","children":[]},{"level":2,"title":"Class.hasField - ext-method","slug":"class-hasfield-ext-method","link":"#class-hasfield-ext-method","children":[]},{"level":2,"title":"Class.hasMethod - ext-method","slug":"class-hasmethod-ext-method","link":"#class-hasmethod-ext-method","children":[]},{"level":2,"title":"Class.hasConstructor - ext-method","slug":"class-hasconstructor-ext-method","link":"#class-hasconstructor-ext-method","children":[]},{"level":2,"title":"Member.hasModifiers - ext-method","slug":"member-hasmodifiers-ext-method","link":"#member-hasmodifiers-ext-method","children":[]},{"level":2,"title":"Class.hasModifiers - ext-method","slug":"class-hasmodifiers-ext-method","link":"#class-hasmodifiers-ext-method","children":[]},{"level":2,"title":"Class.field - ext-method","slug":"class-field-ext-method","link":"#class-field-ext-method","children":[]},{"level":2,"title":"Class.method - ext-method","slug":"class-method-ext-method","link":"#class-method-ext-method","children":[]},{"level":2,"title":"Class.constructor - ext-method","slug":"class-constructor-ext-method","link":"#class-constructor-ext-method","children":[]},{"level":2,"title":"Class.generic - ext-method","slug":"class-generic-ext-method","link":"#class-generic-ext-method","children":[]},{"level":2,"title":"Class.generic - ext-method","slug":"class-generic-ext-method-1","link":"#class-generic-ext-method-1","children":[]},{"level":2,"title":"Any.current - ext-method","slug":"any-current-ext-method","link":"#any-current-ext-method","children":[]},{"level":2,"title":"Class.buildOf - ext-method","slug":"class-buildof-ext-method","link":"#class-buildof-ext-method","children":[]},{"level":2,"title":"Class.allMethods - ext-method","slug":"class-allmethods-ext-method","link":"#class-allmethods-ext-method","children":[]},{"level":2,"title":"Class.allConstructors - ext-method","slug":"class-allconstructors-ext-method","link":"#class-allconstructors-ext-method","children":[]},{"level":2,"title":"Class.allFields - ext-method","slug":"class-allfields-ext-method","link":"#class-allfields-ext-method","children":[]}],"git":{"updatedTime":1663766338000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":5}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.md"}');export{e as data}; diff --git a/docs/assets/VariableTypeFactory.html.550d3346.js b/docs/assets/VariableTypeFactory.html.550d3346.js new file mode 100644 index 00000000..cf2240f1 --- /dev/null +++ b/docs/assets/VariableTypeFactory.html.550d3346.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-14ec8671","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html","title":"VariableTypeFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.md"}');export{a as data}; diff --git a/docs/assets/VariableTypeFactory.html.6d08103b.js b/docs/assets/VariableTypeFactory.html.6d08103b.js new file mode 100644 index 00000000..ee5d7a2e --- /dev/null +++ b/docs/assets/VariableTypeFactory.html.6d08103b.js @@ -0,0 +1 @@ +import{_ as a,r as n,o as r,c as s,b as o,d as c,a as i,e}from"./app.fb8271cf.js";const l={},p=i('\u904D\u5386\u5F53\u524D\u7C7B\u4E2D\u7684\u6240\u6709\u53D8\u91CF\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0
first
Function Illustrate
',6),d=e("\u8BE6\u60C5\u53EF "),h={href:"https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"},_=e("\u70B9\u51FB\u8FD9\u91CC"),u=e(" \u8FDB\u884C\u67E5\u770B\u3002");function k(b,f){const t=n("ExternalLinkIcon");return r(),s("div",null,[p,o("p",null,[d,o("a",h,[_,c(t)]),u])])}const y=a(l,[["render",k],["__file","VariableTypeFactory.html.vue"]]);export{y as default}; diff --git a/docs/assets/VariableTypeFactory.html.c8d4e99d.js b/docs/assets/VariableTypeFactory.html.c8d4e99d.js new file mode 100644 index 00000000..5a791e6e --- /dev/null +++ b/docs/assets/VariableTypeFactory.html.c8d4e99d.js @@ -0,0 +1 @@ +import{_ as t,r as c,o as r,c as s,b as o,d as n,a as i,e}from"./app.fb8271cf.js";const l={},p=i('\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A
Java
\u76F8\u5173\u57FA\u672C\u53D8\u91CF\u7C7B\u578B\u7684Class
\u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
',5),d=e("\u8BE6\u60C5\u53EF "),_={href:"https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"},h=e("\u70B9\u51FB\u8FD9\u91CC"),k=e(" \u8FDB\u884C\u67E5\u770B\u3002");function b(y,f){const a=c("ExternalLinkIcon");return r(),s("div",null,[p,o("p",null,[d,o("a",_,[h,n(a)]),k])])}const m=t(l,[["render",b],["__file","VariableTypeFactory.html.vue"]]);export{m as default}; diff --git a/docs/assets/VariableTypeFactory.html.d4c9dbd1.js b/docs/assets/VariableTypeFactory.html.d4c9dbd1.js new file mode 100644 index 00000000..d38d949a --- /dev/null +++ b/docs/assets/VariableTypeFactory.html.d4c9dbd1.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-ba01a600","path":"/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html","title":"VariableTypeFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.md"}');export{a as data}; diff --git a/docs/assets/VariousClass.html.3e45065c.js b/docs/assets/VariousClass.html.3e45065c.js new file mode 100644 index 00000000..25dd19fe --- /dev/null +++ b/docs/assets/VariousClass.html.3e45065c.js @@ -0,0 +1,4 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},l=e(`\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A
Java
\u76F8\u5173\u57FA\u672C\u53D8\u91CF\u7C7B\u578B\u7684Class
\u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class VariousClass(vararg var name: String)
+
Change Records
v1.0
first
Function Illustrate
\u8FD9\u662F\u4E00\u4E2A\u4E0D\u786E\u5B9A\u6027
Class
\u7C7B\u540D\u88C5\u8F7D\u5668\uFF0C\u901A\u8FC7name
\u88C5\u8F7DClass
\u540D\u79F0\u6570\u7EC4\u3002
fun get(loader: ClassLoader? = null): Class<*>
+
Change Records
v1.0.70
added
Function Illustrate
\u83B7\u53D6\u5339\u914D\u7684\u5B9E\u4F53\u7C7B\u3002
\u4F7F\u7528\u5F53\u524D loader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
fun getOrNull(loader: ClassLoader? = null): Class<*>?
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u53D6\u5339\u914D\u7684\u5B9E\u4F53\u7C7B\u3002
\u4F7F\u7528\u5F53\u524D loader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
\u5339\u914D\u4E0D\u5230 Class
\u4F1A\u8FD4\u56DE null
\uFF0C\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
class VariousClass(vararg var name: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F\u4E00\u4E2A\u4E0D\u786E\u5B9A\u6027
Class
\u7C7B\u540D\u88C5\u8F7D\u5668\uFF0C\u901A\u8FC7name
\u88C5\u8F7DClass
\u540D\u79F0\u6570\u7EC4\u3002
fun get(loader: ClassLoader? = null): Class<*>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5339\u914D\u7684\u5B9E\u4F53\u7C7B\u3002
\u4F7F\u7528\u5F53\u524D loader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
fun getOrNull(loader: ClassLoader? = null): Class<*>?
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5339\u914D\u7684\u5B9E\u4F53\u7C7B\u3002
\u4F7F\u7528\u5F53\u524D loader
\u88C5\u8F7D\u76EE\u6807 Class
\u3002
\u5339\u914D\u4E0D\u5230 Class
\u4F1A\u8FD4\u56DE null
\uFF0C\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0
first
Function Illustrate
',6),l=e("\u8BE6\u60C5\u53EF "),h={href:"https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"},_=e("\u70B9\u51FB\u8FD9\u91CC"),u=e(" \u8FDB\u884C\u67E5\u770B\u3002");function k(f,m){const t=n("ExternalLinkIcon");return c(),s("div",null,[d,o("p",null,[l,o("a",h,[_,r(t)]),u])])}const g=a(p,[["render",k],["__file","ViewTypeFactory.html.vue"]]);export{g as default}; diff --git a/docs/assets/ViewTypeFactory.html.f12c489b.js b/docs/assets/ViewTypeFactory.html.f12c489b.js new file mode 100644 index 00000000..89306a93 --- /dev/null +++ b/docs/assets/ViewTypeFactory.html.f12c489b.js @@ -0,0 +1 @@ +import{_ as c,r as a,o as r,c as n,b as o,d as s,a as i,e}from"./app.fb8271cf.js";const d={},p=i('\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A
Android
\u76F8\u5173Widget
\u7684Class
\u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
',5),l=e("\u8BE6\u60C5\u53EF "),_={href:"https://github.com/fankes/YukiHookAPI/blob/master/yukihookapi/src/api/kotlin/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.kt",target:"_blank",rel:"noopener noreferrer"},h=e("\u70B9\u51FB\u8FD9\u91CC"),k=e(" \u8FDB\u884C\u67E5\u770B\u3002");function y(f,u){const t=a("ExternalLinkIcon");return r(),n("div",null,[p,o("p",null,[l,o("a",_,[h,s(t)]),k])])}const b=c(d,[["render",y],["__file","ViewTypeFactory.html.vue"]]);export{b as default}; diff --git a/docs/assets/YukiBaseHooker.html.0fb80f07.js b/docs/assets/YukiBaseHooker.html.0fb80f07.js new file mode 100644 index 00000000..8353e419 --- /dev/null +++ b/docs/assets/YukiBaseHooker.html.0fb80f07.js @@ -0,0 +1,3 @@ +import{_ as s,o,c as e,a}from"./app.fb8271cf.js";const n={},t=a(`\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A
Android
\u76F8\u5173Widget
\u7684Class
\u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
abstract class YukiBaseHooker : PackageParam()
+
Change Records
v1.0
first
Function Illustrate
YukiHookAPI
\u7684\u5B50\u7C7B Hooker \u5B9E\u73B0\u3002
fun onHook()
+
Change Records
v1.0
first
Function Illustrate
`,13),c=[t];function l(r,p){return o(),e("div",null,c)}const d=s(n,[["render",l],["__file","YukiBaseHooker.html.vue"]]);export{d as default}; diff --git a/docs/assets/YukiBaseHooker.html.6b167698.js b/docs/assets/YukiBaseHooker.html.6b167698.js new file mode 100644 index 00000000..9c524c2e --- /dev/null +++ b/docs/assets/YukiBaseHooker.html.6b167698.js @@ -0,0 +1,3 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},c=e(`\u5B50\u7C7B Hook \u5F00\u59CB\u3002
abstract class YukiBaseHooker : PackageParam()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
YukiHookAPI
\u7684\u5B50\u7C7B Hooker \u5B9E\u73B0\u3002
fun onHook()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
`,12),l=[c];function p(t,r){return o(),a("div",null,l)}const i=s(n,[["render",p],["__file","YukiBaseHooker.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiBaseHooker.html.99eec744.js b/docs/assets/YukiBaseHooker.html.99eec744.js new file mode 100644 index 00000000..dae112b1 --- /dev/null +++ b/docs/assets/YukiBaseHooker.html.99eec744.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-e288ce96","path":"/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html","title":"YukiBaseHooker - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"onHook - method","slug":"onhook-method","link":"#onhook-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.md"}');export{e as data}; diff --git a/docs/assets/YukiBaseHooker.html.b68236f9.js b/docs/assets/YukiBaseHooker.html.b68236f9.js new file mode 100644 index 00000000..95473403 --- /dev/null +++ b/docs/assets/YukiBaseHooker.html.b68236f9.js @@ -0,0 +1 @@ +const o=JSON.parse('{"key":"v-516df326","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html","title":"YukiBaseHooker - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"onHook - method","slug":"onhook-method","link":"#onhook-method","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.md"}');export{o as data}; diff --git a/docs/assets/YukiHookAPI.html.18811dc9.js b/docs/assets/YukiHookAPI.html.18811dc9.js new file mode 100644 index 00000000..a6184fff --- /dev/null +++ b/docs/assets/YukiHookAPI.html.18811dc9.js @@ -0,0 +1,98 @@ +import{_ as s,o as n,c as o,a}from"./app.fb8271cf.js";const e={},l=a(`\u5B50\u7C7B Hook \u5F00\u59CB\u3002
object YukiHookAPI
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F
YukiHookAPI
\u7684 API \u8C03\u7528\u603B\u7C7B\uFF0CHook \u76F8\u5173\u529F\u80FD\u7684\u5F00\u59CB\u3001Hook \u76F8\u5173\u529F\u80FD\u7684\u914D\u7F6E\u90FD\u5728\u8FD9\u91CC\u3002
const val API_VERSION_NAME: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.4
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D
YukiHookAPI
\u7684\u7248\u672C\u3002
const val API_VERSION_CODE: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.4
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D
YukiHookAPI
\u7684\u7248\u672C\u53F7\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
v1.0.91
\u79FB\u9664
\u8BF7\u8F6C\u79FB\u5230 Status.executorName
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
v1.0.91
\u79FB\u9664
\u8BF7\u8F6C\u79FB\u5230 Status.executorVersion
object Status
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.91
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u524D
YukiHookAPI
\u7684\u72B6\u6001\u3002
val compiledTimestamp: Long
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u9879\u76EE\u7F16\u8BD1\u5B8C\u6210\u7684\u65F6\u95F4\u6233 (\u5F53\u524D\u672C\u5730\u65F6\u95F4)\u3002
val isXposedEnvironment: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D\u662F\u5426\u4E3A (Xposed) \u5BBF\u4E3B\u73AF\u5883\u3002
val executorName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.91
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u6846\u67B6\u7684\u540D\u79F0\u3002
\u65E0\u6CD5\u83B7\u53D6\u4F1A\u8FD4\u56DE unknown
\uFF0CXposedBridge
\u4E0D\u5B58\u5728\u4F1A\u8FD4\u56DE invalid
\u3002
\u6CE8\u610F
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
val executorVersion: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.91
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D Hook \u6846\u67B6\u7684\u7248\u672C\u3002
\u65E0\u6CD5\u83B7\u53D6\u4F1A\u8FD4\u56DE -1
\u3002
\u6CE8\u610F
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
val isModuleActive: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.91
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5224\u65AD\u6A21\u5757\u662F\u5426\u5728 Xposed \u6216\u592A\u6781\u3001\u65E0\u6781\u4E2D\u6FC0\u6D3B\u3002
\u6CE8\u610F
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u4F60\u9700\u8981\u5C06 Application \u7EE7\u627F\u4E8E ModuleApplication\u3002
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4EC5\u8FD4\u56DE\u975E isTaiChiModuleActive \u7684\u6FC0\u6D3B\u72B6\u6001\u3002
val isXposedModuleActive: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.91
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EC5\u5224\u65AD\u6A21\u5757\u662F\u5426\u5728 Xposed \u4E2D\u6FC0\u6D3B\u3002
\u6CE8\u610F
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u59CB\u7EC8\u8FD4\u56DE true\u3002
val isTaiChiModuleActive: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.91
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EC5\u5224\u65AD\u6A21\u5757\u662F\u5426\u5728\u592A\u6781\u3001\u65E0\u6781\u4E2D\u6FC0\u6D3B\u3002
\u6CE8\u610F
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u4F60\u9700\u8981\u5C06 Application \u7EE7\u627F\u4E8E ModuleApplication\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u59CB\u7EC8\u8FD4\u56DE false\u3002
val isSupportResourcesHook: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.91
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5224\u65AD\u5F53\u524D Hook Framework \u662F\u5426\u652F\u6301\u8D44\u6E90\u94A9\u5B50(Resources Hook)\u3002
\u6CE8\u610F
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u53EF\u80FD\u4F1A\u5EF6\u8FDF\u7B49\u5F85\u4E8B\u4EF6\u56DE\u8C03\u540E\u624D\u4F1A\u8FD4\u56DE true\u3002
\u8BF7\u6CE8\u610F\u4F60\u9700\u8981\u786E\u4FDD InjectYukiHookWithXposed.isUsingResourcesHook \u5DF2\u542F\u7528\uFF0C\u5426\u5219\u59CB\u7EC8\u8FD4\u56DE false\u3002
object Configs
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5BF9 API \u76F8\u5173\u529F\u80FD\u7684\u914D\u7F6E\u7C7B\u3002
inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u914D\u7F6E
YukiHookLogger.Configs
\u76F8\u5173\u53C2\u6570\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230 YukiHookLogger.Configs.tag
var isDebug: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528 DEBUG \u6A21\u5F0F\u3002
\u9ED8\u8BA4\u4E3A\u5F00\u542F\u72B6\u6001\uFF0C\u5F00\u542F\u540E\u6A21\u5757\u5C06\u4F1A\u5411 Logcat
\u548C XposedBridge.log
\u6253\u5370\u8BE6\u7EC6\u7684 Hook \u65E5\u5FD7\uFF0C\u5173\u95ED\u540E\u4EC5\u4F1A\u6253\u5370 E
\u7EA7\u522B\u7684\u65E5\u5FD7\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.4
\u65B0\u589E
v1.1.0
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230 YukiHookLogger.Configs.isEnable
var isEnableModulePrefsCache: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528
YukiHookModulePrefs
\u7684\u952E\u503C\u7F13\u5B58\u529F\u80FD\u3002
\u4E3A\u9632\u6B62\u5185\u5B58\u590D\u7528\u8FC7\u9AD8\u95EE\u9898\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\u3002
\u4F60\u53EF\u4EE5\u624B\u52A8\u5728 YukiHookModulePrefs
\u4E2D\u81EA\u7531\u5F00\u542F\u548C\u5173\u95ED\u7F13\u5B58\u529F\u80FD\u4EE5\u53CA\u6E05\u9664\u7F13\u5B58\u3002
var isEnableModuleAppResourcesCache: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.87
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB
Resources
\u7F13\u5B58\u529F\u80FD\u3002
\u4E3A\u9632\u6B62\u5185\u5B58\u590D\u7528\u8FC7\u9AD8\u95EE\u9898\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\u3002
\u4F60\u53EF\u4EE5\u624B\u52A8\u8C03\u7528 PackageParam.refreshModuleAppResources
\u6765\u5237\u65B0\u7F13\u5B58\u3002
\u6CE8\u610F
\u5173\u95ED\u540E\u6BCF\u6B21\u4F7F\u7528 PackageParam.moduleAppResources \u90FD\u4F1A\u91CD\u65B0\u521B\u5EFA\uFF0C\u53EF\u80FD\u4F1A\u9020\u6210\u8FD0\u884C\u7F13\u6162\u3002
var isEnableHookModuleStatus: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528 Hook Xposed \u6A21\u5757\u6FC0\u6D3B\u7B49\u72B6\u6001\u529F\u80FD.
\u4E3A\u539F\u751F\u652F\u6301 Xposed \u6A21\u5757\u6FC0\u6D3B\u72B6\u6001\u68C0\u6D4B\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\u3002
\u6CE8\u610F
\u5173\u95ED\u540E\u4F60\u5C06\u4E0D\u80FD\u518D\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u4F7F\u7528 YukiHookAPI.Status \u4E2D\u7684\u6FC0\u6D3B\u72B6\u6001\u5224\u65AD\u529F\u80FD\u3002
var isEnableHookSharedPreferences: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528 Hook
SharedPreferences
\u3002
\u542F\u7528\u540E\u5C06\u5728\u6A21\u5757\u542F\u52A8\u65F6\u5F3A\u5236\u5C06 SharedPreferences
\u6587\u4EF6\u6743\u9650\u8C03\u6574\u4E3A Context.MODE_WORLD_READABLE
(0664)\u3002
\u6CE8\u610F
\u8FD9\u662F\u4E00\u4E2A\u53EF\u9009\u7684\u5B9E\u9A8C\u6027\u529F\u80FD\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u4E0D\u542F\u7528\u3002
\u4EC5\u7528\u4E8E\u4FEE\u590D\u67D0\u4E9B\u7CFB\u7EDF\u53EF\u80FD\u4F1A\u51FA\u73B0\u5728\u542F\u7528\u4E86 New XSharedPreferences \u540E\u4F9D\u7136\u51FA\u73B0\u6587\u4EF6\u6743\u9650\u9519\u8BEF\u95EE\u9898\uFF0C\u82E5\u4F60\u80FD\u6B63\u5E38\u4F7F\u7528 YukiHookModulePrefs \u5C31\u4E0D\u5EFA\u8BAE\u542F\u7528\u6B64\u529F\u80FD\u3002
var isEnableDataChannel: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528\u5F53\u524D Xposed \u6A21\u5757\u4E0E\u5BBF\u4E3B\u4EA4\u4E92\u7684
YukiHookDataChannel
\u529F\u80FD\u3002
\u8BF7\u786E\u4FDD Xposed \u6A21\u5757\u7684 Application
\u7EE7\u627F\u4E8E ModuleApplication
\u624D\u80FD\u6709\u6548\u3002
\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\uFF0C\u5173\u95ED\u540E\u5C06\u4E0D\u4F1A\u5728\u529F\u80FD\u521D\u59CB\u5316\u7684\u65F6\u5019\u88C5\u8F7D YukiHookDataChannel
\u3002
var isEnableMemberCache: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.68
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u662F\u5426\u542F\u7528
Member
\u7F13\u5B58\u529F\u80FD\u3002
\u4E3A\u9632\u6B62 Member
\u590D\u7528\u8FC7\u9AD8\u9020\u6210\u7684\u7CFB\u7EDF GC \u95EE\u9898\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\u3002
\u542F\u7528\u540E\u4F1A\u7F13\u5B58\u5DF2\u7ECF\u627E\u5230\u7684 Method
\u3001Constructor
\u3001Field
\u3002
\u7F13\u5B58\u7684 Member
\u90FD\u5C06\u5904\u4E8E MemberCacheStore
\u7684\u5168\u5C40\u9759\u6001\u5B9E\u4F8B\u4E2D\u3002
\u63A8\u8350\u4F7F\u7528 MethodFinder
\u3001ConstructorFinder
\u3001FieldFinder
\u6765\u83B7\u53D6 Member
\u3002
\u9664\u975E\u7F13\u5B58\u7684 Member
\u53D1\u751F\u4E86\u6DF7\u6DC6\u7684\u95EE\u9898\uFF0C\u4F8B\u5982\u4F7F\u7528 R8 \u6DF7\u6DC6\u540E\u7684 APP \u7684\u76EE\u6807 Member
\uFF0C\u5426\u5219\u5EFA\u8BAE\u542F\u7528\u3002
inline fun configs(initiate: Configs.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5BF9
Configs
\u7C7B\u5B9E\u73B0\u4E86\u4E00\u4E2Alambda
\u65B9\u6CD5\u4F53\u3002
\u4F60\u53EF\u4EE5\u8F7B\u677E\u7684\u8C03\u7528\u5B83\u8FDB\u884C\u914D\u7F6E\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u5728 HookEntryClass
\u7684 onInit
\u65B9\u6CD5\u4E2D\u8C03\u7528 configs
\u65B9\u6CD5\u548C debugLog
\u65B9\u6CD5\u5B8C\u6210\u5BF9 API \u7684\u529F\u80FD\u914D\u7F6E\uFF0C\u5B9E\u65F6\u751F\u6548\u3002
\u793A\u4F8B\u5982\u4E0B
class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() {
+ YukiHookAPI.configs {
+ debugLog {
+ tag = "YukiHookAPI"
+ isEnable = true
+ isRecord = false
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ isDebug = BuildConfig.DEBUG
+ isEnableModulePrefsCache = true
+ isEnableModuleAppResourcesCache = true
+ isEnableHookModuleStatus = true
+ isEnableHookSharedPreferences = false
+ isEnableDataChannel = true
+ isEnableMemberCache = true
+ }
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
\u82E5\u89C9\u5F97\u4E0A\u9762\u7684\u5199\u6CD5\u4E0D\u7F8E\u89C2\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5199\u5F97\u66F4\u52A0\u7B80\u6D01\u3002
\u793A\u4F8B\u5982\u4E0B
class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() = configs {
+ debugLog {
+ tag = "YukiHookAPI"
+ isEnable = true
+ isRecord = false
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ isDebug = BuildConfig.DEBUG
+ isEnableModulePrefsCache = true
+ isEnableModuleAppResourcesCache = true
+ isEnableHookModuleStatus = true
+ isEnableHookSharedPreferences = false
+ isEnableDataChannel = true
+ isEnableMemberCache = true
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
\u4F60\u4E5F\u53EF\u4EE5\u4E0D\u901A\u8FC7 configs
\u548C debugLog
\u65B9\u6CD5\uFF0C\u76F4\u63A5\u8FDB\u884C\u914D\u7F6E\u3002
\u793A\u4F8B\u5982\u4E0B
class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() {
+ YukiHookLogger.Configs.tag = "YukiHookAPI"
+ YukiHookLogger.Configs.isEnable = true
+ YukiHookLogger.Configs.isRecord = false
+ YukiHookLogger.Configs.elements(
+ YukiHookLogger.Configs.TAG,
+ YukiHookLogger.Configs.PRIORITY,
+ YukiHookLogger.Configs.PACKAGE_NAME,
+ YukiHookLogger.Configs.USER_ID
+ )
+ YukiHookAPI.Configs.isDebug = BuildConfig.DEBUG
+ YukiHookAPI.Configs.isEnableModulePrefsCache = true
+ YukiHookAPI.Configs.isEnableModuleAppResourcesCache = true
+ YukiHookAPI.Configs.isEnableHookModuleStatus = true
+ YukiHookAPI.Configs.isEnableHookSharedPreferences = false
+ YukiHookAPI.Configs.isEnableDataChannel = true
+ YukiHookAPI.Configs.isEnableMemberCache = true
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
fun encase(initiate: PackageParam.() -> Unit)
+
fun encase(vararg hooker: YukiBaseHooker)
+
fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
+
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u88C5\u8F7D Hook \u5165\u53E3\u7684\u6838\u5FC3\u65B9\u6CD5\u3002
\u529F\u80FD\u793A\u4F8B
\u8BE6\u60C5\u8BF7\u53C2\u8003
`,202),p=[l];function c(r,t){return n(),o("div",null,p)}const d=s(e,[["render",c],["__file","YukiHookAPI.html.vue"]]);export{d as default}; diff --git a/docs/assets/YukiHookAPI.html.1c02f82e.js b/docs/assets/YukiHookAPI.html.1c02f82e.js new file mode 100644 index 00000000..dba8302a --- /dev/null +++ b/docs/assets/YukiHookAPI.html.1c02f82e.js @@ -0,0 +1,98 @@ +import{_ as s,o as n,c as o,a}from"./app.fb8271cf.js";const e={},l=a(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
object YukiHookAPI
+
Change Records
v1.0
first
Function Illustrate
\u8FD9\u662F
YukiHookAPI
\u7684 API \u8C03\u7528\u603B\u7C7B\uFF0CHook \u76F8\u5173\u529F\u80FD\u7684\u5F00\u59CB\u3001Hook \u76F8\u5173\u529F\u80FD\u7684\u914D\u7F6E\u90FD\u5728\u8FD9\u91CC\u3002
const val API_VERSION_NAME: String
+
Change Records
v1.0.4
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D
YukiHookAPI
\u7684\u7248\u672C\u3002
const val API_VERSION_CODE: Int
+
Change Records
v1.0.4
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D
YukiHookAPI
\u7684\u7248\u672C\u53F7\u3002
Change Records
v1.0.5
added
v1.0.91
removed
\u8BF7\u8F6C\u79FB\u5230 Status.executorName
Change Records
v1.0.5
added
v1.0.91
removed
\u8BF7\u8F6C\u79FB\u5230 Status.executorVersion
object Status
+
Change Records
v1.0.91
added
Function Illustrate
\u5F53\u524D
YukiHookAPI
\u7684\u72B6\u6001\u3002
val compiledTimestamp: Long
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u53D6\u9879\u76EE\u7F16\u8BD1\u5B8C\u6210\u7684\u65F6\u95F4\u6233 (\u5F53\u524D\u672C\u5730\u65F6\u95F4)\u3002
val isXposedEnvironment: Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D\u662F\u5426\u4E3A (Xposed) \u5BBF\u4E3B\u73AF\u5883\u3002
val executorName: String
+
Change Records
v1.0.91
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u6846\u67B6\u7684\u540D\u79F0\u3002
\u65E0\u6CD5\u83B7\u53D6\u4F1A\u8FD4\u56DE unknown
\uFF0CXposedBridge
\u4E0D\u5B58\u5728\u4F1A\u8FD4\u56DE invalid
\u3002
Notice
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
val executorVersion: Int
+
Change Records
v1.0.91
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D Hook \u6846\u67B6\u7684\u7248\u672C\u3002
\u65E0\u6CD5\u83B7\u53D6\u4F1A\u8FD4\u56DE -1
\u3002
Notice
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
val isModuleActive: Boolean
+
Change Records
v1.0.91
added
Function Illustrate
\u5224\u65AD\u6A21\u5757\u662F\u5426\u5728 Xposed \u6216\u592A\u6781\u3001\u65E0\u6781\u4E2D\u6FC0\u6D3B\u3002
Notice
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u4F60\u9700\u8981\u5C06 Application \u7EE7\u627F\u4E8E ModuleApplication\u3002
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4EC5\u8FD4\u56DE\u975E isTaiChiModuleActive \u7684\u6FC0\u6D3B\u72B6\u6001\u3002
val isXposedModuleActive: Boolean
+
Change Records
v1.0.91
added
Function Illustrate
\u4EC5\u5224\u65AD\u6A21\u5757\u662F\u5426\u5728 Xposed \u4E2D\u6FC0\u6D3B\u3002
Notice
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u59CB\u7EC8\u8FD4\u56DE true\u3002
val isTaiChiModuleActive: Boolean
+
Change Records
v1.0.91
added
Function Illustrate
\u4EC5\u5224\u65AD\u6A21\u5757\u662F\u5426\u5728\u592A\u6781\u3001\u65E0\u6781\u4E2D\u6FC0\u6D3B\u3002
Notice
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u4F60\u9700\u8981\u5C06 Application \u7EE7\u627F\u4E8E ModuleApplication\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u59CB\u7EC8\u8FD4\u56DE false\u3002
val isSupportResourcesHook: Boolean
+
Change Records
v1.0.91
added
Function Illustrate
\u5224\u65AD\u5F53\u524D Hook Framework \u662F\u5426\u652F\u6301\u8D44\u6E90\u94A9\u5B50(Resources Hook)\u3002
Notice
\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u9700\u8981\u542F\u7528 Configs.isEnableHookModuleStatus\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u53EF\u80FD\u4F1A\u5EF6\u8FDF\u7B49\u5F85\u4E8B\u4EF6\u56DE\u8C03\u540E\u624D\u4F1A\u8FD4\u56DE true\u3002
\u8BF7\u6CE8\u610F\u4F60\u9700\u8981\u786E\u4FDD InjectYukiHookWithXposed.isUsingResourcesHook \u5DF2\u542F\u7528\uFF0C\u5426\u5219\u59CB\u7EC8\u8FD4\u56DE false\u3002
object Configs
+
Change Records
v1.0
first
Function Illustrate
\u5BF9 API \u76F8\u5173\u529F\u80FD\u7684\u914D\u7F6E\u7C7B\u3002
inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u914D\u7F6E
YukiHookLogger.Configs
\u76F8\u5173\u53C2\u6570\u3002
Change Records
v1.0
first
v1.1.0
deprecated
\u8BF7\u8F6C\u79FB\u5230 YukiHookLogger.Configs.tag
var isDebug: Boolean
+
Change Records
v1.0
first
Function Illustrate
\u662F\u5426\u542F\u7528 DEBUG \u6A21\u5F0F\u3002
\u9ED8\u8BA4\u4E3A\u5F00\u542F\u72B6\u6001\uFF0C\u5F00\u542F\u540E\u6A21\u5757\u5C06\u4F1A\u5411 Logcat
\u548C XposedBridge.log
\u6253\u5370\u8BE6\u7EC6\u7684 Hook \u65E5\u5FD7\uFF0C\u5173\u95ED\u540E\u4EC5\u4F1A\u6253\u5370 E
\u7EA7\u522B\u7684\u65E5\u5FD7\u3002
Change Records
v1.0.4
added
v1.1.0
deprecated
\u8BF7\u8F6C\u79FB\u5230 YukiHookLogger.Configs.isEnable
var isEnableModulePrefsCache: Boolean
+
Change Records
v1.0.5
added
Function Illustrate
\u662F\u5426\u542F\u7528
YukiHookModulePrefs
\u7684\u952E\u503C\u7F13\u5B58\u529F\u80FD\u3002
\u4E3A\u9632\u6B62\u5185\u5B58\u590D\u7528\u8FC7\u9AD8\u95EE\u9898\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\u3002
\u4F60\u53EF\u4EE5\u624B\u52A8\u5728 YukiHookModulePrefs
\u4E2D\u81EA\u7531\u5F00\u542F\u548C\u5173\u95ED\u7F13\u5B58\u529F\u80FD\u4EE5\u53CA\u6E05\u9664\u7F13\u5B58\u3002
var isEnableModuleAppResourcesCache: Boolean
+
Change Records
v1.0.87
added
Function Illustrate
\u662F\u5426\u542F\u7528\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB
Resources
\u7F13\u5B58\u529F\u80FD\u3002
\u4E3A\u9632\u6B62\u5185\u5B58\u590D\u7528\u8FC7\u9AD8\u95EE\u9898\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\u3002
\u4F60\u53EF\u4EE5\u624B\u52A8\u8C03\u7528 PackageParam.refreshModuleAppResources
\u6765\u5237\u65B0\u7F13\u5B58\u3002
Notice
\u5173\u95ED\u540E\u6BCF\u6B21\u4F7F\u7528 PackageParam.moduleAppResources \u90FD\u4F1A\u91CD\u65B0\u521B\u5EFA\uFF0C\u53EF\u80FD\u4F1A\u9020\u6210\u8FD0\u884C\u7F13\u6162\u3002
var isEnableHookModuleStatus: Boolean
+
Change Records
v1.0.88
added
Function Illustrate
\u662F\u5426\u542F\u7528 Hook Xposed \u6A21\u5757\u6FC0\u6D3B\u7B49\u72B6\u6001\u529F\u80FD.
\u4E3A\u539F\u751F\u652F\u6301 Xposed \u6A21\u5757\u6FC0\u6D3B\u72B6\u6001\u68C0\u6D4B\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\u3002
Notice
\u5173\u95ED\u540E\u4F60\u5C06\u4E0D\u80FD\u518D\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u4F7F\u7528 YukiHookAPI.Status \u4E2D\u7684\u6FC0\u6D3B\u72B6\u6001\u5224\u65AD\u529F\u80FD\u3002
var isEnableHookSharedPreferences: Boolean
+
Change Records
v1.1.0
added
Function Illustrate
\u662F\u5426\u542F\u7528 Hook
SharedPreferences
\u3002
\u542F\u7528\u540E\u5C06\u5728\u6A21\u5757\u542F\u52A8\u65F6\u5F3A\u5236\u5C06 SharedPreferences
\u6587\u4EF6\u6743\u9650\u8C03\u6574\u4E3A Context.MODE_WORLD_READABLE
(0664)\u3002
Notice
\u8FD9\u662F\u4E00\u4E2A\u53EF\u9009\u7684\u5B9E\u9A8C\u6027\u529F\u80FD\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u4E0D\u542F\u7528\u3002
\u4EC5\u7528\u4E8E\u4FEE\u590D\u67D0\u4E9B\u7CFB\u7EDF\u53EF\u80FD\u4F1A\u51FA\u73B0\u5728\u542F\u7528\u4E86 New XSharedPreferences \u540E\u4F9D\u7136\u51FA\u73B0\u6587\u4EF6\u6743\u9650\u9519\u8BEF\u95EE\u9898\uFF0C\u82E5\u4F60\u80FD\u6B63\u5E38\u4F7F\u7528 YukiHookModulePrefs \u5C31\u4E0D\u5EFA\u8BAE\u542F\u7528\u6B64\u529F\u80FD\u3002
var isEnableDataChannel: Boolean
+
Change Records
v1.0.88
added
Function Illustrate
\u662F\u5426\u542F\u7528\u5F53\u524D Xposed \u6A21\u5757\u4E0E\u5BBF\u4E3B\u4EA4\u4E92\u7684
YukiHookDataChannel
\u529F\u80FD\u3002
\u8BF7\u786E\u4FDD Xposed \u6A21\u5757\u7684 Application
\u7EE7\u627F\u4E8E ModuleApplication
\u624D\u80FD\u6709\u6548\u3002
\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\uFF0C\u5173\u95ED\u540E\u5C06\u4E0D\u4F1A\u5728\u529F\u80FD\u521D\u59CB\u5316\u7684\u65F6\u5019\u88C5\u8F7D YukiHookDataChannel
\u3002
var isEnableMemberCache: Boolean
+
Change Records
v1.0.68
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u662F\u5426\u542F\u7528
Member
\u7F13\u5B58\u529F\u80FD\u3002
\u4E3A\u9632\u6B62 Member
\u590D\u7528\u8FC7\u9AD8\u9020\u6210\u7684\u7CFB\u7EDF GC \u95EE\u9898\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u542F\u7528\u3002
\u542F\u7528\u540E\u4F1A\u7F13\u5B58\u5DF2\u7ECF\u627E\u5230\u7684 Method
\u3001Constructor
\u3001Field
\u3002
\u7F13\u5B58\u7684 Member
\u90FD\u5C06\u5904\u4E8E MemberCacheStore
\u7684\u5168\u5C40\u9759\u6001\u5B9E\u4F8B\u4E2D\u3002
\u63A8\u8350\u4F7F\u7528 MethodFinder
\u3001ConstructorFinder
\u3001FieldFinder
\u6765\u83B7\u53D6 Member
\u3002
\u9664\u975E\u7F13\u5B58\u7684 Member
\u53D1\u751F\u4E86\u6DF7\u6DC6\u7684\u95EE\u9898\uFF0C\u4F8B\u5982\u4F7F\u7528 R8 \u6DF7\u6DC6\u540E\u7684 APP \u7684\u76EE\u6807 Member
\uFF0C\u5426\u5219\u5EFA\u8BAE\u542F\u7528\u3002
inline fun configs(initiate: Configs.() -> Unit)
+
Change Records
v1.0
first
Function Illustrate
\u5BF9
Configs
\u7C7B\u5B9E\u73B0\u4E86\u4E00\u4E2Alambda
\u65B9\u6CD5\u4F53\u3002
\u4F60\u53EF\u4EE5\u8F7B\u677E\u7684\u8C03\u7528\u5B83\u8FDB\u884C\u914D\u7F6E\u3002
Function Example
\u4F60\u53EF\u4EE5\u5728 HookEntryClass
\u7684 onInit
\u65B9\u6CD5\u4E2D\u8C03\u7528 configs
\u65B9\u6CD5\u548C debugLog
\u65B9\u6CD5\u5B8C\u6210\u5BF9 API \u7684\u529F\u80FD\u914D\u7F6E\uFF0C\u5B9E\u65F6\u751F\u6548\u3002
The following example
class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() {
+ YukiHookAPI.configs {
+ debugLog {
+ tag = "YukiHookAPI"
+ isEnable = true
+ isRecord = false
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ isDebug = BuildConfig.DEBUG
+ isEnableModulePrefsCache = true
+ isEnableModuleAppResourcesCache = true
+ isEnableHookModuleStatus = true
+ isEnableHookSharedPreferences = false
+ isEnableDataChannel = true
+ isEnableMemberCache = true
+ }
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
\u82E5\u89C9\u5F97\u4E0A\u9762\u7684\u5199\u6CD5\u4E0D\u7F8E\u89C2\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5199\u5F97\u66F4\u52A0\u7B80\u6D01\u3002
The following example
class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() = configs {
+ debugLog {
+ tag = "YukiHookAPI"
+ isEnable = true
+ isRecord = false
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ isDebug = BuildConfig.DEBUG
+ isEnableModulePrefsCache = true
+ isEnableModuleAppResourcesCache = true
+ isEnableHookModuleStatus = true
+ isEnableHookSharedPreferences = false
+ isEnableDataChannel = true
+ isEnableMemberCache = true
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
\u4F60\u4E5F\u53EF\u4EE5\u4E0D\u901A\u8FC7 configs
\u548C debugLog
\u65B9\u6CD5\uFF0C\u76F4\u63A5\u8FDB\u884C\u914D\u7F6E\u3002
The following example
class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() {
+ YukiHookLogger.Configs.tag = "YukiHookAPI"
+ YukiHookLogger.Configs.isEnable = true
+ YukiHookLogger.Configs.isRecord = false
+ YukiHookLogger.Configs.elements(
+ YukiHookLogger.Configs.TAG,
+ YukiHookLogger.Configs.PRIORITY,
+ YukiHookLogger.Configs.PACKAGE_NAME,
+ YukiHookLogger.Configs.USER_ID
+ )
+ YukiHookAPI.Configs.isDebug = BuildConfig.DEBUG
+ YukiHookAPI.Configs.isEnableModulePrefsCache = true
+ YukiHookAPI.Configs.isEnableModuleAppResourcesCache = true
+ YukiHookAPI.Configs.isEnableHookModuleStatus = true
+ YukiHookAPI.Configs.isEnableHookSharedPreferences = false
+ YukiHookAPI.Configs.isEnableDataChannel = true
+ YukiHookAPI.Configs.isEnableMemberCache = true
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
fun encase(initiate: PackageParam.() -> Unit)
+
fun encase(vararg hooker: YukiBaseHooker)
+
fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
+
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
+
Change Records
v1.0
first
Function Illustrate
\u88C5\u8F7D Hook \u5165\u53E3\u7684\u6838\u5FC3\u65B9\u6CD5\u3002
Function Example
\u8BE6\u60C5\u8BF7\u53C2\u8003
`,203),p=[l];function c(r,t){return n(),o("div",null,p)}const d=s(e,[["render",c],["__file","YukiHookAPI.html.vue"]]);export{d as default}; diff --git a/docs/assets/YukiHookAPI.html.476693ca.js b/docs/assets/YukiHookAPI.html.476693ca.js new file mode 100644 index 00000000..6e2936e1 --- /dev/null +++ b/docs/assets/YukiHookAPI.html.476693ca.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-6931cb54","path":"/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.html","title":"YukiHookAPI - object","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"API_VERSION_NAME - field","slug":"api-version-name-field","link":"#api-version-name-field","children":[]},{"level":2,"title":"API_VERSION_CODE - field","slug":"api-version-code-field","link":"#api-version-code-field","children":[]},{"level":2,"title":"Status - object","slug":"status-object","link":"#status-object","children":[{"level":3,"title":"compiledTimestamp - field","slug":"compiledtimestamp-field","link":"#compiledtimestamp-field","children":[]},{"level":3,"title":"isXposedEnvironment - field","slug":"isxposedenvironment-field","link":"#isxposedenvironment-field","children":[]},{"level":3,"title":"executorName - field","slug":"executorname-field","link":"#executorname-field","children":[]},{"level":3,"title":"executorVersion - field","slug":"executorversion-field","link":"#executorversion-field","children":[]},{"level":3,"title":"isModuleActive - field","slug":"ismoduleactive-field","link":"#ismoduleactive-field","children":[]},{"level":3,"title":"isXposedModuleActive - field","slug":"isxposedmoduleactive-field","link":"#isxposedmoduleactive-field","children":[]},{"level":3,"title":"isTaiChiModuleActive - field","slug":"istaichimoduleactive-field","link":"#istaichimoduleactive-field","children":[]},{"level":3,"title":"isSupportResourcesHook - field","slug":"issupportresourceshook-field","link":"#issupportresourceshook-field","children":[]}]},{"level":2,"title":"Configs - object","slug":"configs-object","link":"#configs-object","children":[{"level":3,"title":"debugLog - method","slug":"debuglog-method","link":"#debuglog-method","children":[]},{"level":3,"title":"isDebug - field","slug":"isdebug-field","link":"#isdebug-field","children":[]},{"level":3,"title":"isEnableModulePrefsCache - field","slug":"isenablemoduleprefscache-field","link":"#isenablemoduleprefscache-field","children":[]},{"level":3,"title":"isEnableModuleAppResourcesCache - field","slug":"isenablemoduleappresourcescache-field","link":"#isenablemoduleappresourcescache-field","children":[]},{"level":3,"title":"isEnableHookModuleStatus - field","slug":"isenablehookmodulestatus-field","link":"#isenablehookmodulestatus-field","children":[]},{"level":3,"title":"isEnableHookSharedPreferences - field","slug":"isenablehooksharedpreferences-field","link":"#isenablehooksharedpreferences-field","children":[]},{"level":3,"title":"isEnableDataChannel - field","slug":"isenabledatachannel-field","link":"#isenabledatachannel-field","children":[]},{"level":3,"title":"isEnableMemberCache - field","slug":"isenablemembercache-field","link":"#isenablemembercache-field","children":[]}]},{"level":2,"title":"configs - method","slug":"configs-method","link":"#configs-method","children":[]},{"level":2,"title":"encase - method","slug":"encase-method","link":"#encase-method","children":[]}],"git":{"updatedTime":1664200621000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md"}');export{e as data}; diff --git a/docs/assets/YukiHookAPI.html.77b2a461.js b/docs/assets/YukiHookAPI.html.77b2a461.js new file mode 100644 index 00000000..12c4307c --- /dev/null +++ b/docs/assets/YukiHookAPI.html.77b2a461.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-053599a5","path":"/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.html","title":"YukiHookAPI - object","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"API_VERSION_NAME - field","slug":"api-version-name-field","link":"#api-version-name-field","children":[]},{"level":2,"title":"API_VERSION_CODE - field","slug":"api-version-code-field","link":"#api-version-code-field","children":[]},{"level":2,"title":"Status - object","slug":"status-object","link":"#status-object","children":[{"level":3,"title":"compiledTimestamp - field","slug":"compiledtimestamp-field","link":"#compiledtimestamp-field","children":[]},{"level":3,"title":"isXposedEnvironment - field","slug":"isxposedenvironment-field","link":"#isxposedenvironment-field","children":[]},{"level":3,"title":"executorName - field","slug":"executorname-field","link":"#executorname-field","children":[]},{"level":3,"title":"executorVersion - field","slug":"executorversion-field","link":"#executorversion-field","children":[]},{"level":3,"title":"isModuleActive - field","slug":"ismoduleactive-field","link":"#ismoduleactive-field","children":[]},{"level":3,"title":"isXposedModuleActive - field","slug":"isxposedmoduleactive-field","link":"#isxposedmoduleactive-field","children":[]},{"level":3,"title":"isTaiChiModuleActive - field","slug":"istaichimoduleactive-field","link":"#istaichimoduleactive-field","children":[]},{"level":3,"title":"isSupportResourcesHook - field","slug":"issupportresourceshook-field","link":"#issupportresourceshook-field","children":[]}]},{"level":2,"title":"Configs - object","slug":"configs-object","link":"#configs-object","children":[{"level":3,"title":"debugLog - method","slug":"debuglog-method","link":"#debuglog-method","children":[]},{"level":3,"title":"isDebug - field","slug":"isdebug-field","link":"#isdebug-field","children":[]},{"level":3,"title":"isEnableModulePrefsCache - field","slug":"isenablemoduleprefscache-field","link":"#isenablemoduleprefscache-field","children":[]},{"level":3,"title":"isEnableModuleAppResourcesCache - field","slug":"isenablemoduleappresourcescache-field","link":"#isenablemoduleappresourcescache-field","children":[]},{"level":3,"title":"isEnableHookModuleStatus - field","slug":"isenablehookmodulestatus-field","link":"#isenablehookmodulestatus-field","children":[]},{"level":3,"title":"isEnableHookSharedPreferences - field","slug":"isenablehooksharedpreferences-field","link":"#isenablehooksharedpreferences-field","children":[]},{"level":3,"title":"isEnableDataChannel - field","slug":"isenabledatachannel-field","link":"#isenabledatachannel-field","children":[]},{"level":3,"title":"isEnableMemberCache - field","slug":"isenablemembercache-field","link":"#isenablemembercache-field","children":[]}]},{"level":2,"title":"configs - method","slug":"configs-method","link":"#configs-method","children":[]},{"level":2,"title":"encase - method","slug":"encase-method","link":"#encase-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/YukiHookAPI.md"}');export{e as data}; diff --git a/docs/assets/YukiHookDataChannel.html.74e08a45.js b/docs/assets/YukiHookDataChannel.html.74e08a45.js new file mode 100644 index 00000000..b3f03ab2 --- /dev/null +++ b/docs/assets/YukiHookDataChannel.html.74e08a45.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-632be8ee","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html","title":"YukiHookDataChannel - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"NameSpace - class","slug":"namespace-class","link":"#namespace-class","children":[{"level":3,"title":"with - method","slug":"with-method","link":"#with-method","children":[]},{"level":3,"title":"put - method","slug":"put-method","link":"#put-method","children":[]},{"level":3,"title":"put - method","slug":"put-method-1","link":"#put-method-1","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method-1","link":"#wait-method-1","children":[]},{"level":3,"title":"checkingVersionEquals - method","slug":"checkingversionequals-method","link":"#checkingversionequals-method","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.md"}');export{e as data}; diff --git a/docs/assets/YukiHookDataChannel.html.75c012dd.js b/docs/assets/YukiHookDataChannel.html.75c012dd.js new file mode 100644 index 00000000..4f40930b --- /dev/null +++ b/docs/assets/YukiHookDataChannel.html.75c012dd.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-7414265a","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html","title":"YukiHookDataChannel - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"NameSpace - class","slug":"namespace-class","link":"#namespace-class","children":[{"level":3,"title":"with - method","slug":"with-method","link":"#with-method","children":[]},{"level":3,"title":"put - method","slug":"put-method","link":"#put-method","children":[]},{"level":3,"title":"put - method","slug":"put-method-1","link":"#put-method-1","children":[]},{"level":3,"title":"wait - method","slug":"wait-method","link":"#wait-method","children":[]},{"level":3,"title":"wait - method","slug":"wait-method-1","link":"#wait-method-1","children":[]},{"level":3,"title":"checkingVersionEquals - method","slug":"checkingversionequals-method","link":"#checkingversionequals-method","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.md"}');export{e as data}; diff --git a/docs/assets/YukiHookDataChannel.html.b01666c1.js b/docs/assets/YukiHookDataChannel.html.b01666c1.js new file mode 100644 index 00000000..87b7b4b1 --- /dev/null +++ b/docs/assets/YukiHookDataChannel.html.b01666c1.js @@ -0,0 +1,12 @@ +import{_ as s,o as a,c as o,a as n}from"./app.fb8271cf.js";const l={},p=n(`class YukiHookDataChannel private constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5B9E\u73B0 Xposed \u6A21\u5757\u7684\u6570\u636E\u901A\u8BAF\u6865\u3002
\u901A\u8FC7\u6A21\u5757\u4E0E\u5BBF\u4E3B\u76F8\u4E92\u6CE8\u518C BroadcastReceiver
\u6765\u5B9E\u73B0\u6570\u636E\u7684\u4EA4\u4E92\u3002
\u6A21\u5757\u9700\u8981\u5C06 Application
\u7EE7\u627F\u4E8E ModuleApplication
\u6765\u5B9E\u73B0\u6B64\u529F\u80FD\u3002
\u7279\u522B\u6CE8\u610F
\u6A21\u5757\u4E0E\u5BBF\u4E3B\u9700\u8981\u4FDD\u6301\u5B58\u6D3B\u72B6\u6001\uFF0C\u5426\u5219\u65E0\u6CD5\u5EFA\u7ACB\u901A\u8BAF\u3002
inner class NameSpace internal constructor(private val context: Context?, private val packageName: String, private val isSecure: Boolean)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.0.90
\u4FEE\u6539
\u65B0\u589E isSecure
\u53C2\u6570
\u529F\u80FD\u63CF\u8FF0
YukiHookDataChannel
\u547D\u540D\u7A7A\u95F4\u3002
inline fun with(initiate: NameSpace.() -> Unit): NameSpace
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u4E00\u4E2A\u8C03\u7528\u7A7A\u95F4\u3002
fun <T> put(key: String, value: T)
+
fun <T> put(data: ChannelData<T>, value: T?)
+
fun put(vararg data: ChannelData<*>)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u53D1\u9001\u952E\u503C\u6570\u636E\u3002
fun put(key: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EC5\u53D1\u9001\u952E\u503C\u76D1\u542C\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u503C
VALUE_WAIT_FOR_LISTENER
\u53D1\u9001\u952E\u503C\u6570\u636E\u3002
fun <T> wait(key: String, result: (value: T) -> Unit)
+
fun <T> wait(data: ChannelData<T>, result: (value: T) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
v1.0.90
\u4FEE\u6539
\u79FB\u9664\u9ED8\u8BA4\u503C value
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u952E\u503C\u6570\u636E\u3002
fun wait(key: String, callback: () -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4EC5\u83B7\u53D6\u76D1\u542C\u7ED3\u679C\uFF0C\u4E0D\u83B7\u53D6\u952E\u503C\u6570\u636E\u3002
\u7279\u522B\u6CE8\u610F
\u4EC5\u9650\u4F7F\u7528 VALUE_WAIT_FOR_LISTENER \u53D1\u9001\u7684\u76D1\u542C\u624D\u80FD\u88AB\u63A5\u6536\u3002
fun checkingVersionEquals(result: (Boolean) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7684\u7248\u672C\u662F\u5426\u5339\u914D\u3002
\u901A\u8FC7\u6B64\u65B9\u6CD5\u53EF\u539F\u751F\u5224\u65AD Xposed \u6A21\u5757\u66F4\u65B0\u540E\u5BBF\u4E3B\u5E76\u672A\u91CD\u65B0\u88C5\u8F7D\u9020\u6210\u4E24\u8005\u4E0D\u5339\u914D\u7684\u60C5\u51B5\u3002
`,60),e=[p];function c(t,r){return a(),o("div",null,e)}const d=s(l,[["render",c],["__file","YukiHookDataChannel.html.vue"]]);export{d as default}; diff --git a/docs/assets/YukiHookDataChannel.html.f40252bf.js b/docs/assets/YukiHookDataChannel.html.f40252bf.js new file mode 100644 index 00000000..f95e048d --- /dev/null +++ b/docs/assets/YukiHookDataChannel.html.f40252bf.js @@ -0,0 +1,12 @@ +import{_ as s,o as a,c as n,a as o}from"./app.fb8271cf.js";const l={},e=o(`Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class YukiHookDataChannel private constructor()
+
Change Records
v1.0.88
added
Function Illustrate
\u5B9E\u73B0 Xposed \u6A21\u5757\u7684\u6570\u636E\u901A\u8BAF\u6865\u3002
\u901A\u8FC7\u6A21\u5757\u4E0E\u5BBF\u4E3B\u76F8\u4E92\u6CE8\u518C BroadcastReceiver
\u6765\u5B9E\u73B0\u6570\u636E\u7684\u4EA4\u4E92\u3002
\u6A21\u5757\u9700\u8981\u5C06 Application
\u7EE7\u627F\u4E8E ModuleApplication
\u6765\u5B9E\u73B0\u6B64\u529F\u80FD\u3002
Pay Attention
\u6A21\u5757\u4E0E\u5BBF\u4E3B\u9700\u8981\u4FDD\u6301\u5B58\u6D3B\u72B6\u6001\uFF0C\u5426\u5219\u65E0\u6CD5\u5EFA\u7ACB\u901A\u8BAF\u3002
inner class NameSpace internal constructor(private val context: Context?, private val packageName: String, private val isSecure: Boolean)
+
Change Records
v1.0.88
added
v1.0.90
modified
\u65B0\u589E isSecure
\u53C2\u6570
Function Illustrate
YukiHookDataChannel
\u547D\u540D\u7A7A\u95F4\u3002
inline fun with(initiate: NameSpace.() -> Unit): NameSpace
+
Change Records
v1.0.88
added
Function Illustrate
\u521B\u5EFA\u4E00\u4E2A\u8C03\u7528\u7A7A\u95F4\u3002
fun <T> put(key: String, value: T)
+
fun <T> put(data: ChannelData<T>, value: T?)
+
fun put(vararg data: ChannelData<*>)
+
Change Records
v1.0.88
added
Function Illustrate
\u53D1\u9001\u952E\u503C\u6570\u636E\u3002
fun put(key: String)
+
Change Records
v1.0.88
added
Function Illustrate
\u4EC5\u53D1\u9001\u952E\u503C\u76D1\u542C\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u503C
VALUE_WAIT_FOR_LISTENER
\u53D1\u9001\u952E\u503C\u6570\u636E\u3002
fun <T> wait(key: String, result: (value: T) -> Unit)
+
fun <T> wait(data: ChannelData<T>, result: (value: T) -> Unit)
+
Change Records
v1.0.88
added
v1.0.90
modified
\u79FB\u9664\u9ED8\u8BA4\u503C value
Function Illustrate
\u83B7\u53D6\u952E\u503C\u6570\u636E\u3002
fun wait(key: String, callback: () -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u4EC5\u83B7\u53D6\u76D1\u542C\u7ED3\u679C\uFF0C\u4E0D\u83B7\u53D6\u952E\u503C\u6570\u636E\u3002
Pay Attention
\u4EC5\u9650\u4F7F\u7528 VALUE_WAIT_FOR_LISTENER \u53D1\u9001\u7684\u76D1\u542C\u624D\u80FD\u88AB\u63A5\u6536\u3002
fun checkingVersionEquals(result: (Boolean) -> Unit)
+
Change Records
v1.0.88
added
Function Illustrate
\u83B7\u53D6\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7684\u7248\u672C\u662F\u5426\u5339\u914D\u3002
\u901A\u8FC7\u6B64\u65B9\u6CD5\u53EF\u539F\u751F\u5224\u65AD Xposed \u6A21\u5757\u66F4\u65B0\u540E\u5BBF\u4E3B\u5E76\u672A\u91CD\u65B0\u88C5\u8F7D\u9020\u6210\u4E24\u8005\u4E0D\u5339\u914D\u7684\u60C5\u51B5\u3002
`,61),p=[e];function t(c,r){return a(),n("div",null,p)}const y=s(l,[["render",t],["__file","YukiHookDataChannel.html.vue"]]);export{y as default}; diff --git a/docs/assets/YukiHookFactory.html.122ae5d0.js b/docs/assets/YukiHookFactory.html.122ae5d0.js new file mode 100644 index 00000000..166a5b9c --- /dev/null +++ b/docs/assets/YukiHookFactory.html.122ae5d0.js @@ -0,0 +1,12 @@ +import{_ as o,o as e,c as s,a as n}from"./app.fb8271cf.js";const a={},p=n(`\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5408\u5E76\u5230 IYukiHookXposedInit
\uFF0C\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u8FD9\u662F
YukiHookAPI
\u76F8\u5173lambda
\u65B9\u6CD5\u7684\u5C01\u88C5\u7C7B\u4EE5\u53CA\u90E8\u5206 API \u7528\u6CD5\u3002
inline fun IYukiHookXposedInit.configs(initiate: YukiHookAPI.Configs.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.1
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5408\u5E76\u5230 IYukiHookXposedInit
\u529F\u80FD\u63CF\u8FF0
\u5728
IYukiHookXposedInit
\u4E2D\u914D\u7F6EConfigs
\u3002
fun IYukiHookXposedInit.encase(initiate: PackageParam.() -> Unit)
+
fun IYukiHookXposedInit.encase(vararg hooker: YukiBaseHooker)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5408\u5E76\u5230 IYukiHookXposedInit
\u529F\u80FD\u63CF\u8FF0
\u5728
IYukiHookXposedInit
\u4E2D\u8C03\u7528YukiHookAPI
\u3002
val Context.modulePrefs: YukiHookModulePrefs
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u6A21\u5757\u7684\u5B58\u53D6\u5BF9\u8C61\u3002
fun Context.modulePrefs(name: String): YukiHookModulePrefs
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u6A21\u5757\u7684\u5B58\u53D6\u5BF9\u8C61\uFF0C\u53EF\u8BBE\u7F6E
name
\u4E3A\u81EA\u5B9A\u4E49 Sp \u5B58\u50A8\u540D\u79F0\u3002
fun Context.dataChannel(packageName: String): YukiHookDataChannel.NameSpace
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u6A21\u5757\u7684\u6570\u636E\u901A\u8BAF\u6865\u547D\u540D\u7A7A\u95F4\u5BF9\u8C61\u3002
\u7279\u522B\u6CE8\u610F
\u53EA\u80FD\u5728\u6A21\u5757\u73AF\u5883\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u5176\u5B83\u73AF\u5883\u4E0B\u4F7F\u7528\u5C06\u4E0D\u8D77\u4F5C\u7528\u3002
val Context.processName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D\u8FDB\u7A0B\u540D\u79F0\u3002
fun Context.injectModuleAppResources()
+
fun Resources.injectModuleAppResources()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5411 Hook APP (\u5BBF\u4E3B)
Context
\u6216Resources
\u6CE8\u5165\u5F53\u524D Xposed \u6A21\u5757\u7684\u8D44\u6E90\u3002
\u6CE8\u5165\u6210\u529F\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u4F8B\u5982 ImageView.setImageResource
\u6216 Resources.getString
\u88C5\u8F7D\u5F53\u524D Xposed \u6A21\u5757\u7684\u8D44\u6E90 ID\u3002
\u6CE8\u5165\u7684\u8D44\u6E90\u4F5C\u7528\u57DF\u4EC5\u9650\u5F53\u524D Context
\u6216 Resources
\uFF0C\u4F60\u9700\u8981\u5728\u6BCF\u4E2A\u7528\u5230\u5BBF\u4E3B Context
\u6216 Resources
\u7684\u5730\u65B9\u91CD\u590D\u8C03\u7528\u6B64\u65B9\u6CD5\u8FDB\u884C\u6CE8\u5165\u624D\u80FD\u4F7F\u7528\u3002
\u7279\u522B\u6CE8\u610F
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u5176\u5B83\u73AF\u5883\u4E0B\u4F7F\u7528\u5C06\u4E0D\u751F\u6548\u4E14\u4F1A\u6253\u5370\u8B66\u544A\u4FE1\u606F\u3002
fun Context.registerModuleAppActivities(proxy: Any?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5411 Hook APP (\u5BBF\u4E3B) \u6CE8\u518C\u5F53\u524D Xposed \u6A21\u5757\u7684
Activity
\u3002
\u6CE8\u518C\u6210\u529F\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 Context.startActivity
\u6765\u542F\u52A8\u672A\u5728\u5BBF\u4E3B\u4E2D\u6CE8\u518C\u7684 Activity
\u3002
\u4F7F\u7528\u6B64\u65B9\u6CD5\u4F1A\u5728\u672A\u6CE8\u518C\u7684 Activity
\u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u542F\u52A8\u65F6\u81EA\u52A8\u8C03\u7528 injectModuleAppResources
\u6CE8\u5165\u5F53\u524D Xposed \u6A21\u5757\u7684\u8D44\u6E90\u3002
\u4F60\u8981\u5C06\u9700\u8981\u5728\u5BBF\u4E3B\u542F\u52A8\u7684 Activity
\u7EE7\u627F\u4E8E ModuleAppActivity
\u6216 ModuleAppCompatActivity
\u3002
\u7279\u522B\u6CE8\u610F
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u5176\u5B83\u73AF\u5883\u4E0B\u4F7F\u7528\u5C06\u4E0D\u751F\u6548\u4E14\u4F1A\u6253\u5370\u8B66\u544A\u4FE1\u606F\u3002
fun Context.applyModuleTheme(theme: Int, configuration: Configuration?): ModuleContextThemeWrapper
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u751F\u6210\u4E00\u4E2A
ContextThemeWrapper
\u4EE3\u7406\u4EE5\u5E94\u7528\u5F53\u524D Xposed \u6A21\u5757\u7684\u4E3B\u9898\u8D44\u6E90\u3002
\u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u4F7F\u7528\u6B64\u65B9\u6CD5\u4F1A\u81EA\u52A8\u8C03\u7528 injectModuleAppResources
\u6CE8\u5165\u5F53\u524D Xposed \u6A21\u5757\u7684\u8D44\u6E90\u3002
\u5982\u679C\u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u4F7F\u7528\u6B64\u65B9\u6CD5\u53D1\u751F ClassCastException
\uFF0C\u8BF7\u624B\u52A8\u8BBE\u7F6E configuration
\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
v1.0.91
\u79FB\u9664
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isSupportResourcesHook
\u53D8\u66F4\u8BB0\u5F55
v1.0.6
\u65B0\u589E
v1.0.91
\u79FB\u9664
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isModuleActive
\u53D8\u66F4\u8BB0\u5F55
v1.0.6
\u65B0\u589E
v1.0.91
\u79FB\u9664
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isXposedModuleActive
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.91
\u79FB\u9664
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isTaiChiModuleActive
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.91
\u4F5C\u5E9F
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
Change Records
v1.0
first
v1.0.80
modified
\u5408\u5E76\u5230 IYukiHookXposedInit
\uFF0C\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u8FD9\u662F
YukiHookAPI
\u76F8\u5173lambda
\u65B9\u6CD5\u7684\u5C01\u88C5\u7C7B\u4EE5\u53CA\u90E8\u5206 API \u7528\u6CD5\u3002
inline fun IYukiHookXposedInit.configs(initiate: YukiHookAPI.Configs.() -> Unit)
+
Change Records
v1.0.1
added
v1.0.80
modified
\u5408\u5E76\u5230 IYukiHookXposedInit
Function Illustrate
\u5728
IYukiHookXposedInit
\u4E2D\u914D\u7F6EConfigs
\u3002
fun IYukiHookXposedInit.encase(initiate: PackageParam.() -> Unit)
+
fun IYukiHookXposedInit.encase(vararg hooker: YukiBaseHooker)
+
Change Records
v1.0
first
v1.0.80
modified
\u5408\u5E76\u5230 IYukiHookXposedInit
Function Illustrate
\u5728
IYukiHookXposedInit
\u4E2D\u8C03\u7528YukiHookAPI
\u3002
val Context.modulePrefs: YukiHookModulePrefs
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u6A21\u5757\u7684\u5B58\u53D6\u5BF9\u8C61\u3002
fun Context.modulePrefs(name: String): YukiHookModulePrefs
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u6A21\u5757\u7684\u5B58\u53D6\u5BF9\u8C61\uFF0C\u53EF\u8BBE\u7F6E
name
\u4E3A\u81EA\u5B9A\u4E49 Sp \u5B58\u50A8\u540D\u79F0\u3002
fun Context.dataChannel(packageName: String): YukiHookDataChannel.NameSpace
+
Change Records
v1.0.88
added
Function Illustrate
\u83B7\u53D6\u6A21\u5757\u7684\u6570\u636E\u901A\u8BAF\u6865\u547D\u540D\u7A7A\u95F4\u5BF9\u8C61\u3002
Pay Attention
\u53EA\u80FD\u5728\u6A21\u5757\u73AF\u5883\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u5176\u5B83\u73AF\u5883\u4E0B\u4F7F\u7528\u5C06\u4E0D\u8D77\u4F5C\u7528\u3002
val Context.processName: String
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6\u5F53\u524D\u8FDB\u7A0B\u540D\u79F0\u3002
fun Context.injectModuleAppResources()
+
fun Resources.injectModuleAppResources()
+
Change Records
v1.1.0
added
Function Illustrate
\u5411 Hook APP (\u5BBF\u4E3B)
Context
\u6216Resources
\u6CE8\u5165\u5F53\u524D Xposed \u6A21\u5757\u7684\u8D44\u6E90\u3002
\u6CE8\u5165\u6210\u529F\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u4F8B\u5982 ImageView.setImageResource
\u6216 Resources.getString
\u88C5\u8F7D\u5F53\u524D Xposed \u6A21\u5757\u7684\u8D44\u6E90 ID\u3002
\u6CE8\u5165\u7684\u8D44\u6E90\u4F5C\u7528\u57DF\u4EC5\u9650\u5F53\u524D Context
\u6216 Resources
\uFF0C\u4F60\u9700\u8981\u5728\u6BCF\u4E2A\u7528\u5230\u5BBF\u4E3B Context
\u6216 Resources
\u7684\u5730\u65B9\u91CD\u590D\u8C03\u7528\u6B64\u65B9\u6CD5\u8FDB\u884C\u6CE8\u5165\u624D\u80FD\u4F7F\u7528\u3002
Pay Attention
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u5176\u5B83\u73AF\u5883\u4E0B\u4F7F\u7528\u5C06\u4E0D\u751F\u6548\u4E14\u4F1A\u6253\u5370\u8B66\u544A\u4FE1\u606F\u3002
fun Context.registerModuleAppActivities(proxy: Any?)
+
Change Records
v1.1.0
added
Function Illustrate
\u5411 Hook APP (\u5BBF\u4E3B) \u6CE8\u518C\u5F53\u524D Xposed \u6A21\u5757\u7684
Activity
\u3002
\u6CE8\u518C\u6210\u529F\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 Context.startActivity
\u6765\u542F\u52A8\u672A\u5728\u5BBF\u4E3B\u4E2D\u6CE8\u518C\u7684 Activity
\u3002
\u4F7F\u7528\u6B64\u65B9\u6CD5\u4F1A\u5728\u672A\u6CE8\u518C\u7684 Activity
\u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u542F\u52A8\u65F6\u81EA\u52A8\u8C03\u7528 injectModuleAppResources
\u6CE8\u5165\u5F53\u524D Xposed \u6A21\u5757\u7684\u8D44\u6E90\u3002
\u4F60\u8981\u5C06\u9700\u8981\u5728\u5BBF\u4E3B\u542F\u52A8\u7684 Activity
\u7EE7\u627F\u4E8E ModuleAppActivity
\u6216 ModuleAppCompatActivity
\u3002
Pay Attention
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u5176\u5B83\u73AF\u5883\u4E0B\u4F7F\u7528\u5C06\u4E0D\u751F\u6548\u4E14\u4F1A\u6253\u5370\u8B66\u544A\u4FE1\u606F\u3002
fun Context.applyModuleTheme(theme: Int, configuration: Configuration?): ModuleContextThemeWrapper
+
Change Records
v1.1.0
added
Function Illustrate
\u751F\u6210\u4E00\u4E2A
ContextThemeWrapper
\u4EE3\u7406\u4EE5\u5E94\u7528\u5F53\u524D Xposed \u6A21\u5757\u7684\u4E3B\u9898\u8D44\u6E90\u3002
\u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u4F7F\u7528\u6B64\u65B9\u6CD5\u4F1A\u81EA\u52A8\u8C03\u7528 injectModuleAppResources
\u6CE8\u5165\u5F53\u524D Xposed \u6A21\u5757\u7684\u8D44\u6E90\u3002
\u5982\u679C\u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u4F7F\u7528\u6B64\u65B9\u6CD5\u53D1\u751F ClassCastException
\uFF0C\u8BF7\u624B\u52A8\u8BBE\u7F6E configuration
\u3002
Change Records
v1.0.80
added
v1.0.91
removed
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isSupportResourcesHook
Change Records
v1.0.6
added
v1.0.91
removed
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isModuleActive
Change Records
v1.0.6
added
v1.0.91
removed
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isXposedModuleActive
Change Records
v1.0
first
v1.0.91
removed
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isTaiChiModuleActive
Change Records
v1.0
first
v1.0.91
deprecated
\u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class YukiHookModulePrefs private constructor(private var context: Context?)
+
Change Records
v1.0
first
Function Illustrate
\u5B9E\u73B0 Xposed \u6A21\u5757\u7684\u6570\u636E\u5B58\u53D6\uFF0C\u5BF9\u63A5
SharedPreferences
\u548CXSharedPreferences
\u3002
\u5728\u4E0D\u540C\u73AF\u5883\u667A\u80FD\u9009\u62E9\u5B58\u53D6\u4F7F\u7528\u7684\u5BF9\u8C61\u3002
Pay Attention
\u6B64\u529F\u80FD\u4E3A\u5B9E\u9A8C\u6027\u529F\u80FD\uFF0C\u4EC5\u5728 LSPosed \u73AF\u5883\u6D4B\u8BD5\u901A\u8FC7\uFF0CEdXposed \u7406\u8BBA\u4E5F\u53EF\u4EE5\u4F7F\u7528\u4F46\u4E0D\u518D\u63A8\u8350\u3002
\u4F7F\u7528 LSPosed \u73AF\u5883\u8BF7\u5728 AndroidManifests.xml
\u4E2D\u5C06 xposedminversion
\u6700\u4F4E\u8BBE\u7F6E\u4E3A 93
\u3002
Pay Attention
\u5F53\u4F60\u5728 Xposed \u6A21\u5757\u4E2D\u5B58\u53D6\u6570\u636E\u7684\u65F6\u5019 context \u5FC5\u987B\u4E0D\u80FD\u662F\u7A7A\u7684\u3002
\u82E5\u4F60\u6B63\u5728\u4F7F\u7528 PreferenceFragmentCompat
\uFF0C\u8BF7\u8FC1\u79FB\u5230 ModulePreferenceFragment
\u4EE5\u9002\u914D\u4E0A\u8FF0\u529F\u80FD\u7279\u6027\u3002
\u53EF\u9009\u914D\u7F6E
\u82E5\u4F60\u4E0D\u60F3\u5C06\u4F60\u7684\u6A21\u5757\u7684 xposedminversion
\u6700\u4F4E\u8BBE\u7F6E\u4E3A 93
\uFF0C\u4F60\u53EF\u4EE5\u5728 AndroidManifest.xml
\u4E2D\u6DFB\u52A0 xposedsharedprefs
\u6765\u5B9E\u73B0\u652F\u6301\u3002
The following example
<meta-data
+ android:name="xposedsharedprefs"
+ android:value="true"/>
+
val isXSharePrefsReadable: Boolean
+
Change Records
v1.0.90
added
Function Illustrate
\u83B7\u53D6
XSharedPreferences
\u662F\u5426\u53EF\u8BFB\u3002
Pay Attention
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528\uFF0C\u6A21\u5757\u73AF\u5883\u4E2D\u59CB\u7EC8\u8FD4\u56DE false\u3002
val isRunInNewXShareMode: Boolean
+
Change Records
v1.0.78
added
Function Illustrate
\u83B7\u53D6
YukiHookModulePrefs
\u662F\u5426\u6B63\u5904\u4E8E EdXposed/LSPosed \u7684\u6700\u9AD8\u6743\u9650\u8FD0\u884C\u3002
\u524D\u63D0\u6761\u4EF6\u4E3A\u5F53\u524D Xposed \u6A21\u5757\u5DF2\u88AB\u6FC0\u6D3B\u3002
Pay Attention
\u53EA\u80FD\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u4F7F\u7528\uFF0C(Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u59CB\u7EC8\u8FD4\u56DE false\u3002
fun name(name: String): YukiHookModulePrefs
+
Change Records
v1.0
first
Function Illustrate
\u81EA\u5B9A\u4E49 Sp \u5B58\u50A8\u540D\u79F0\u3002
Function Example
\u5728 Activity
\u4E2D\u7684\u4F7F\u7528\u65B9\u6CD5\u3002
The following example
modulePrefs("custom_name").getString("custom_key")
+
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883 PackageParam
\u4E2D\u7684\u4F7F\u7528\u65B9\u6CD5\u3002
The following example
prefs("custom_name").getString("custom_key")
+
fun direct(): YukiHookModulePrefs
+
Change Records
v1.0.5
added
Function Illustrate
\u5FFD\u7565\u7F13\u5B58\u76F4\u63A5\u8BFB\u53D6\u952E\u503C\u3002
\u65E0\u8BBA\u662F\u5426\u5F00\u542F YukiHookAPI.Configs.isEnableModulePrefsCache
\u3002
\u4EC5\u5728 XSharedPreferences
\u4E0B\u751F\u6548\u3002
fun getString(key: String, value: String): String
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6
String
\u952E\u503C\u3002
fun getStringSet(key: String, value: Set<String>): Set<String>
+
Change Records
v1.0.77
added
Function Illustrate
\u83B7\u53D6
Set<String>
\u952E\u503C\u3002
fun getBoolean(key: String, value: Boolean): Boolean
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6
Boolean
\u952E\u503C\u3002
fun getInt(key: String, value: Int): Int
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6
Int
\u952E\u503C\u3002
fun getLong(key: String, value: Long): Long
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6
Long
\u952E\u503C\u3002
fun getFloat(key: String, value: Float): Float
+
Change Records
v1.0
first
Function Illustrate
\u83B7\u53D6
Float
\u952E\u503C\u3002
fun all(): HashMap<String, Any?>
+
Change Records
v1.0.77
added
Function Illustrate
\u83B7\u53D6\u5168\u90E8\u5B58\u50A8\u7684\u952E\u503C\u6570\u636E\u3002
\u667A\u80FD\u8BC6\u522B\u5BF9\u5E94\u73AF\u5883\u8BFB\u53D6\u952E\u503C\u6570\u636E\u3002
Pay Attention
\u6BCF\u6B21\u8C03\u7528\u90FD\u4F1A\u83B7\u53D6\u5B9E\u65F6\u7684\u6570\u636E\uFF0C\u4E0D\u53D7\u7F13\u5B58\u63A7\u5236\uFF0C\u8BF7\u52FF\u5728\u9AD8\u5E76\u53D1\u573A\u666F\u4E2D\u4F7F\u7528\u3002
fun remove(key: String)
+
Change Records
v1.0
first
Function Illustrate
\u79FB\u9664\u5168\u90E8\u5305\u542B
key
\u7684\u5B58\u50A8\u6570\u636E\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
inline fun <reified T> remove(prefs: PrefsData<T>)
+
Change Records
v1.0.67
added
Function Illustrate
\u79FB\u9664
PrefsData.key
\u7684\u5B58\u50A8\u6570\u636E\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun clear()
+
Change Records
v1.0.77
added
Function Illustrate
\u79FB\u9664\u5168\u90E8\u5B58\u50A8\u6570\u636E\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putString(key: String, value: String)
+
Change Records
v1.0
first
Function Illustrate
\u5B58\u50A8
String
\u952E\u503C\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putStringSet(key: String, value: Set<String>)
+
Change Records
v1.0.77
added
Function Illustrate
\u5B58\u50A8
Set<String>
\u952E\u503C\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putBoolean(key: String, value: Boolean)
+
Change Records
v1.0
first
Function Illustrate
\u5B58\u50A8
Boolean
\u952E\u503C\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putInt(key: String, value: Int)
+
Change Records
v1.0
first
Function Illustrate
\u5B58\u50A8
Int
\u952E\u503C\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putLong(key: String, value: Long)
+
Change Records
v1.0
first
Function Illustrate
\u5B58\u50A8
Long
\u952E\u503C\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putFloat(key: String, value: Float)
+
Change Records
v1.0
first
Function Illustrate
\u5B58\u50A8
Float
\u952E\u503C\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
inline fun <reified T> get(prefs: PrefsData<T>, value: T): T
+
Change Records
v1.0.67
added
Function Illustrate
\u667A\u80FD\u83B7\u53D6\u6307\u5B9A\u7C7B\u578B\u7684\u952E\u503C\u3002
inline fun <reified T> put(prefs: PrefsData<T>, value: T)
+
Change Records
v1.0.67
added
Function Illustrate
\u667A\u80FD\u5B58\u50A8\u6307\u5B9A\u7C7B\u578B\u7684\u952E\u503C\u3002
Notice
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun clearCache()
+
Change Records
v1.0.5
added
Function Illustrate
\u6E05\u9664
XSharedPreferences
\u4E2D\u7F13\u5B58\u7684\u952E\u503C\u6570\u636E\u3002
\u65E0\u8BBA\u662F\u5426\u5F00\u542F YukiHookAPI.Configs.isEnableModulePrefsCache
\u3002
\u8C03\u7528\u6B64\u65B9\u6CD5\u5C06\u6E05\u9664\u5F53\u524D\u5B58\u50A8\u7684\u5168\u90E8\u952E\u503C\u7F13\u5B58\u3002
\u4E0B\u6B21\u5C06\u4ECE XSharedPreferences
\u91CD\u65B0\u8BFB\u53D6\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528\u3002
`,168);function S(q,_){const e=p("ExternalLinkIcon");return t(),c("div",null,[d,o("p",null,[i,o("a",y,[u,n(e)]),g]),h,A,o("p",null,[F,o("a",B,[C,n(e)]),D]),k,o("p",null,[m,o("a",b,[v,n(e)]),f]),x])}const I=l(r,[["render",S],["__file","YukiHookModulePrefs.html.vue"]]);export{I as default}; diff --git a/docs/assets/YukiHookModulePrefs.html.9506520f.js b/docs/assets/YukiHookModulePrefs.html.9506520f.js new file mode 100644 index 00000000..d50be9e0 --- /dev/null +++ b/docs/assets/YukiHookModulePrefs.html.9506520f.js @@ -0,0 +1,30 @@ +import{_ as l,r as p,o as t,c,b as o,d as n,a,e as s}from"./app.fb8271cf.js";const r={},d=a(`class YukiHookModulePrefs private constructor(private var context: Context?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5B9E\u73B0 Xposed \u6A21\u5757\u7684\u6570\u636E\u5B58\u53D6\uFF0C\u5BF9\u63A5
SharedPreferences
\u548CXSharedPreferences
\u3002
\u5728\u4E0D\u540C\u73AF\u5883\u667A\u80FD\u9009\u62E9\u5B58\u53D6\u4F7F\u7528\u7684\u5BF9\u8C61\u3002
\u7279\u522B\u6CE8\u610F
\u6B64\u529F\u80FD\u4E3A\u5B9E\u9A8C\u6027\u529F\u80FD\uFF0C\u4EC5\u5728 LSPosed \u73AF\u5883\u6D4B\u8BD5\u901A\u8FC7\uFF0CEdXposed \u7406\u8BBA\u4E5F\u53EF\u4EE5\u4F7F\u7528\u4F46\u4E0D\u518D\u63A8\u8350\u3002
\u4F7F\u7528 LSPosed \u73AF\u5883\u8BF7\u5728 AndroidManifests.xml
\u4E2D\u5C06 xposedminversion
\u6700\u4F4E\u8BBE\u7F6E\u4E3A 93
\u3002
\u7279\u522B\u6CE8\u610F
\u5F53\u4F60\u5728 Xposed \u6A21\u5757\u4E2D\u5B58\u53D6\u6570\u636E\u7684\u65F6\u5019 context \u5FC5\u987B\u4E0D\u80FD\u662F\u7A7A\u7684\u3002
\u82E5\u4F60\u6B63\u5728\u4F7F\u7528 PreferenceFragmentCompat
\uFF0C\u8BF7\u8FC1\u79FB\u5230 ModulePreferenceFragment
\u4EE5\u9002\u914D\u4E0A\u8FF0\u529F\u80FD\u7279\u6027\u3002
\u53EF\u9009\u914D\u7F6E
\u82E5\u4F60\u4E0D\u60F3\u5C06\u4F60\u7684\u6A21\u5757\u7684 xposedminversion
\u6700\u4F4E\u8BBE\u7F6E\u4E3A 93
\uFF0C\u4F60\u53EF\u4EE5\u5728 AndroidManifest.xml
\u4E2D\u6DFB\u52A0 xposedsharedprefs
\u6765\u5B9E\u73B0\u652F\u6301\u3002
\u793A\u4F8B\u5982\u4E0B
<meta-data
+ android:name="xposedsharedprefs"
+ android:value="true"/>
+
val isXSharePrefsReadable: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.90
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6
XSharedPreferences
\u662F\u5426\u53EF\u8BFB\u3002
\u7279\u522B\u6CE8\u610F
\u53EA\u80FD\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528\uFF0C\u6A21\u5757\u73AF\u5883\u4E2D\u59CB\u7EC8\u8FD4\u56DE false\u3002
val isRunInNewXShareMode: Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.78
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6
YukiHookModulePrefs
\u662F\u5426\u6B63\u5904\u4E8E EdXposed/LSPosed \u7684\u6700\u9AD8\u6743\u9650\u8FD0\u884C\u3002
\u524D\u63D0\u6761\u4EF6\u4E3A\u5F53\u524D Xposed \u6A21\u5757\u5DF2\u88AB\u6FC0\u6D3B\u3002
\u7279\u522B\u6CE8\u610F
\u53EA\u80FD\u5728\u6A21\u5757\u73AF\u5883\u4E2D\u4F7F\u7528\uFF0C(Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u59CB\u7EC8\u8FD4\u56DE false\u3002
fun name(name: String): YukiHookModulePrefs
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u81EA\u5B9A\u4E49 Sp \u5B58\u50A8\u540D\u79F0\u3002
\u529F\u80FD\u793A\u4F8B
\u5728 Activity
\u4E2D\u7684\u4F7F\u7528\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
modulePrefs("custom_name").getString("custom_key")
+
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883 PackageParam
\u4E2D\u7684\u4F7F\u7528\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
prefs("custom_name").getString("custom_key")
+
fun direct(): YukiHookModulePrefs
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565\u7F13\u5B58\u76F4\u63A5\u8BFB\u53D6\u952E\u503C\u3002
\u65E0\u8BBA\u662F\u5426\u5F00\u542F YukiHookAPI.Configs.isEnableModulePrefsCache
\u3002
\u4EC5\u5728 XSharedPreferences
\u4E0B\u751F\u6548\u3002
fun getString(key: String, value: String): String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6
String
\u952E\u503C\u3002
fun getStringSet(key: String, value: Set<String>): Set<String>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.77
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6
Set<String>
\u952E\u503C\u3002
fun getBoolean(key: String, value: Boolean): Boolean
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6
Boolean
\u952E\u503C\u3002
fun getInt(key: String, value: Int): Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6
Int
\u952E\u503C\u3002
fun getLong(key: String, value: Long): Long
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6
Long
\u952E\u503C\u3002
fun getFloat(key: String, value: Float): Float
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6
Float
\u952E\u503C\u3002
fun all(): HashMap<String, Any?>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.77
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5168\u90E8\u5B58\u50A8\u7684\u952E\u503C\u6570\u636E\u3002
\u667A\u80FD\u8BC6\u522B\u5BF9\u5E94\u73AF\u5883\u8BFB\u53D6\u952E\u503C\u6570\u636E\u3002
\u7279\u522B\u6CE8\u610F
\u6BCF\u6B21\u8C03\u7528\u90FD\u4F1A\u83B7\u53D6\u5B9E\u65F6\u7684\u6570\u636E\uFF0C\u4E0D\u53D7\u7F13\u5B58\u63A7\u5236\uFF0C\u8BF7\u52FF\u5728\u9AD8\u5E76\u53D1\u573A\u666F\u4E2D\u4F7F\u7528\u3002
fun remove(key: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u79FB\u9664\u5168\u90E8\u5305\u542B
key
\u7684\u5B58\u50A8\u6570\u636E\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
inline fun <reified T> remove(prefs: PrefsData<T>)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u79FB\u9664
PrefsData.key
\u7684\u5B58\u50A8\u6570\u636E\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun clear()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.77
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u79FB\u9664\u5168\u90E8\u5B58\u50A8\u6570\u636E\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putString(key: String, value: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5B58\u50A8
String
\u952E\u503C\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putStringSet(key: String, value: Set<String>)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.77
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5B58\u50A8
Set<String>
\u952E\u503C\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putBoolean(key: String, value: Boolean)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5B58\u50A8
Boolean
\u952E\u503C\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putInt(key: String, value: Int)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5B58\u50A8
Int
\u952E\u503C\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putLong(key: String, value: Long)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5B58\u50A8
Long
\u952E\u503C\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun putFloat(key: String, value: Float)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5B58\u50A8
Float
\u952E\u503C\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
inline fun <reified T> get(prefs: PrefsData<T>, value: T): T
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u667A\u80FD\u83B7\u53D6\u6307\u5B9A\u7C7B\u578B\u7684\u952E\u503C\u3002
inline fun <reified T> put(prefs: PrefsData<T>, value: T)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.67
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u667A\u80FD\u5B58\u50A8\u6307\u5B9A\u7C7B\u578B\u7684\u952E\u503C\u3002
\u6CE8\u610F
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0B\u53EA\u8BFB\uFF0C\u65E0\u6CD5\u4F7F\u7528\u3002
fun clearCache()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6E05\u9664
XSharedPreferences
\u4E2D\u7F13\u5B58\u7684\u952E\u503C\u6570\u636E\u3002
\u65E0\u8BBA\u662F\u5426\u5F00\u542F YukiHookAPI.Configs.isEnableModulePrefsCache
\u3002
\u8C03\u7528\u6B64\u65B9\u6CD5\u5C06\u6E05\u9664\u5F53\u524D\u5B58\u50A8\u7684\u5168\u90E8\u952E\u503C\u7F13\u5B58\u3002
\u4E0B\u6B21\u5C06\u4ECE XSharedPreferences
\u91CD\u65B0\u8BFB\u53D6\u3002
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528\u3002
`,168);function S(q,_){const e=p("ExternalLinkIcon");return t(),c("div",null,[d,o("p",null,[i,o("a",y,[g,n(e)]),u]),A,h,o("p",null,[B,o("a",F,[D,n(e)]),C]),k,o("p",null,[m,o("a",b,[v,n(e)]),f]),x])}const X=l(r,[["render",S],["__file","YukiHookModulePrefs.html.vue"]]);export{X as default}; diff --git a/docs/assets/YukiHookModulePrefs.html.e0f278fe.js b/docs/assets/YukiHookModulePrefs.html.e0f278fe.js new file mode 100644 index 00000000..5516f188 --- /dev/null +++ b/docs/assets/YukiHookModulePrefs.html.e0f278fe.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-003862c2","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html","title":"YukiHookModulePrefs - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"isXSharePrefsReadable - field","slug":"isxshareprefsreadable-field","link":"#isxshareprefsreadable-field","children":[]},{"level":2,"title":"isRunInNewXShareMode - field","slug":"isruninnewxsharemode-field","link":"#isruninnewxsharemode-field","children":[]},{"level":2,"title":"name - method","slug":"name-method","link":"#name-method","children":[]},{"level":2,"title":"direct - method","slug":"direct-method","link":"#direct-method","children":[]},{"level":2,"title":"getString - method","slug":"getstring-method","link":"#getstring-method","children":[]},{"level":2,"title":"getStringSet - method","slug":"getstringset-method","link":"#getstringset-method","children":[]},{"level":2,"title":"getBoolean - method","slug":"getboolean-method","link":"#getboolean-method","children":[]},{"level":2,"title":"getInt - method","slug":"getint-method","link":"#getint-method","children":[]},{"level":2,"title":"getLong - method","slug":"getlong-method","link":"#getlong-method","children":[]},{"level":2,"title":"getFloat - method","slug":"getfloat-method","link":"#getfloat-method","children":[]},{"level":2,"title":"all - method","slug":"all-method","link":"#all-method","children":[]},{"level":2,"title":"remove - method","slug":"remove-method","link":"#remove-method","children":[]},{"level":2,"title":"remove - method","slug":"remove-method-1","link":"#remove-method-1","children":[]},{"level":2,"title":"clear - method","slug":"clear-method","link":"#clear-method","children":[]},{"level":2,"title":"putString - method","slug":"putstring-method","link":"#putstring-method","children":[]},{"level":2,"title":"putStringSet - method","slug":"putstringset-method","link":"#putstringset-method","children":[]},{"level":2,"title":"putBoolean - method","slug":"putboolean-method","link":"#putboolean-method","children":[]},{"level":2,"title":"putInt - method","slug":"putint-method","link":"#putint-method","children":[]},{"level":2,"title":"putLong - method","slug":"putlong-method","link":"#putlong-method","children":[]},{"level":2,"title":"putFloat - method","slug":"putfloat-method","link":"#putfloat-method","children":[]},{"level":2,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":2,"title":"put - method","slug":"put-method","link":"#put-method","children":[]},{"level":2,"title":"clearCache - method","slug":"clearcache-method","link":"#clearcache-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.md"}');export{e as data}; diff --git a/docs/assets/YukiMemberHookCreator.html.37dcaec4.js b/docs/assets/YukiMemberHookCreator.html.37dcaec4.js new file mode 100644 index 00000000..5bf412b4 --- /dev/null +++ b/docs/assets/YukiMemberHookCreator.html.37dcaec4.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-3ac40680","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html","title":"YukiMemberHookCreator - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"PRIORITY_DEFAULT - field","slug":"priority-default-field","link":"#priority-default-field","children":[]},{"level":2,"title":"PRIORITY_LOWEST - field","slug":"priority-lowest-field","link":"#priority-lowest-field","children":[]},{"level":2,"title":"PRIORITY_HIGHEST - field","slug":"priority-highest-field","link":"#priority-highest-field","children":[]},{"level":2,"title":"instanceClass - field","slug":"instanceclass-field","link":"#instanceclass-field","children":[]},{"level":2,"title":"injectMember - method","slug":"injectmember-method","link":"#injectmember-method","children":[]},{"level":2,"title":"useDangerousOperation - method","slug":"usedangerousoperation-method","link":"#usedangerousoperation-method","children":[]},{"level":2,"title":"MemberHookCreator - class","slug":"memberhookcreator-class","link":"#memberhookcreator-class","children":[{"level":3,"title":"members - method","slug":"members-method","link":"#members-method","children":[]},{"level":3,"title":"allMembers - method","slug":"allmembers-method","link":"#allmembers-method","children":[]},{"level":3,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":3,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":3,"title":"HookParam.field - i-ext-method","slug":"hookparam-field-i-ext-method","link":"#hookparam-field-i-ext-method","children":[]},{"level":3,"title":"HookParam.method - i-ext-method","slug":"hookparam-method-i-ext-method","link":"#hookparam-method-i-ext-method","children":[]},{"level":3,"title":"HookParam.constructor - i-ext-method","slug":"hookparam-constructor-i-ext-method","link":"#hookparam-constructor-i-ext-method","children":[]},{"level":3,"title":"HookParam.injectMember - i-ext-method","slug":"hookparam-injectmember-i-ext-method","link":"#hookparam-injectmember-i-ext-method","children":[]},{"level":3,"title":"beforeHook - method","slug":"beforehook-method","link":"#beforehook-method","children":[]},{"level":3,"title":"afterHook - method","slug":"afterhook-method","link":"#afterhook-method","children":[]},{"level":3,"title":"replaceAny - method","slug":"replaceany-method","link":"#replaceany-method","children":[]},{"level":3,"title":"replaceUnit - method","slug":"replaceunit-method","link":"#replaceunit-method","children":[]},{"level":3,"title":"replaceTo - method","slug":"replaceto-method","link":"#replaceto-method","children":[]},{"level":3,"title":"replaceToTrue - method","slug":"replacetotrue-method","link":"#replacetotrue-method","children":[]},{"level":3,"title":"replaceToFalse - method","slug":"replacetofalse-method","link":"#replacetofalse-method","children":[]},{"level":3,"title":"intercept - method","slug":"intercept-method","link":"#intercept-method","children":[]},{"level":3,"title":"removeSelf - method","slug":"removeself-method","link":"#removeself-method","children":[]},{"level":3,"title":"HookCallback - class","slug":"hookcallback-class","link":"#hookcallback-class","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method-1","link":"#result-method-1","children":[]},{"level":3,"title":"by - method","slug":"by-method-1","link":"#by-method-1","children":[]},{"level":3,"title":"onPrepareHook - method","slug":"onpreparehook-method","link":"#onpreparehook-method","children":[]},{"level":3,"title":"onHookClassNotFoundFailure - method","slug":"onhookclassnotfoundfailure-method","link":"#onhookclassnotfoundfailure-method","children":[]},{"level":3,"title":"ignoredHookClassNotFoundFailure - method","slug":"ignoredhookclassnotfoundfailure-method","link":"#ignoredhookclassnotfoundfailure-method","children":[]}]}],"git":{"updatedTime":1663743027000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md"}');export{e as data}; diff --git a/docs/assets/YukiMemberHookCreator.html.55afd41d.js b/docs/assets/YukiMemberHookCreator.html.55afd41d.js new file mode 100644 index 00000000..de9db0a6 --- /dev/null +++ b/docs/assets/YukiMemberHookCreator.html.55afd41d.js @@ -0,0 +1,121 @@ +import{_ as s,o,c as n,a as e}from"./app.fb8271cf.js";const a={},l=e(`class YukiMemberHookCreator(internal val packageParam: PackageParam, internal val hookClass: HookClass)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5BF9 hookClass
\u8FDB\u884C inline \u5904\u7406
v1.1.0
\u4FEE\u6539
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 Creater \u547D\u540D\u5230 Creator
\u529F\u80FD\u63CF\u8FF0
YukiHookAPI
\u7684Member
\u6838\u5FC3 Hook \u5B9E\u73B0\u7C7B\u3002
val PRIORITY_DEFAULT: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u9ED8\u8BA4 Hook \u56DE\u8C03\u4F18\u5148\u7EA7\u3002
val PRIORITY_LOWEST: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5EF6\u8FDF\u56DE\u8C03 Hook \u65B9\u6CD5\u7ED3\u679C\u3002
val PRIORITY_HIGHEST: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u66F4\u5FEB\u56DE\u8C03 Hook \u65B9\u6CD5\u7ED3\u679C\u3002
val instanceClass: Class<*>
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.2
\u4FEE\u6539
\u66F4\u540D\u4E3A thisClass
instanceClass
\u529F\u80FD\u63CF\u8FF0
\u5F97\u5230\u5F53\u524D\u88AB Hook \u7684
Class
\u3002
\u7279\u522B\u6CE8\u610F
\u4E0D\u63A8\u8350\u76F4\u63A5\u4F7F\u7528\uFF0C\u4E07\u4E00\u5F97\u4E0D\u5230 Class \u5BF9\u8C61\u5219\u4F1A\u65E0\u6CD5\u5904\u7406\u5F02\u5E38\u5BFC\u81F4\u5D29\u6E83\u3002
inline fun injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u589E\u52A0 priority
Hook \u4F18\u5148\u7EA7
\u529F\u80FD\u63CF\u8FF0
\u6CE8\u5165\u8981 Hook \u7684
Method
\u3001Constructor
\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u6CE8\u5165\u4EFB\u610F Method
\u4E0E Constructor
\uFF0C\u4F7F\u7528 injectMember
\u5373\u53EF\u521B\u5EFA\u4E00\u4E2A Hook
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // Your code here.
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 tag
\uFF0C\u65B9\u4FBF\u4F60\u5728\u8C03\u8BD5\u7684\u65F6\u5019\u80FD\u591F\u533A\u5206\u4F60\u7684 Hook
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember(tag = "KuriharaYuki") {
+ // Your code here.
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 priority
\uFF0C\u4EE5\u63A7\u5236\u5F53\u524D Hook \u5BF9\u8C61\u5E76\u5217\u6267\u884C\u7684\u4F18\u5148\u7EA7\u901F\u5EA6\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember(priority = PRIORITY_HIGHEST) {
+ // Your code here.
+}
+
fun useDangerousOperation(option: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5141\u8BB8 Hook \u8FC7\u7A0B\u4E2D\u7684\u6240\u6709\u5371\u9669\u884C\u4E3A\u3002
\u8BF7\u5728 option
\u4E2D\u952E\u5165 Yes do as I say!
\u4EE3\u8868\u4F60\u540C\u610F\u5141\u8BB8\u6240\u6709\u5371\u9669\u884C\u4E3A\u3002
\u4F60\u8FD8\u9700\u8981\u5728\u6574\u4E2A\u8C03\u7528\u57DF\u4E2D\u58F0\u660E\u6CE8\u89E3 CauseProblemsApi
\u4EE5\u6D88\u9664\u8B66\u544A\u3002
\u82E5\u4F60\u53EA\u9700\u8981 Hook ClassLoader
\u7684 loadClass
\u65B9\u6CD5\uFF0C\u8BF7\u53C2\u8003 ClassLoader.onLoadClass\u3002
\u7279\u522B\u6CE8\u610F
\u82E5\u4F60\u4E0D\u77E5\u9053\u5141\u8BB8\u6B64\u529F\u80FD\u4F1A\u5E26\u6765\u4F55\u79CD\u540E\u679C\uFF0C\u8BF7\u52FF\u4F7F\u7528\u3002
inner class MemberHookCreator internal constructor(private val priority: Int, internal val tag: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u589E\u52A0 priority
Hook \u4F18\u5148\u7EA7
v1.0.81
\u4FEE\u6539
\u589E\u52A0 packageName
\u5F53\u524D Hook \u7684 APP \u5305\u540D
v1.1.0
\u4FEE\u6539
\u79FB\u9664 packageName
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 Creater \u547D\u540D\u5230 Creator
\u529F\u80FD\u63CF\u8FF0
Hook \u6838\u5FC3\u529F\u80FD\u5B9E\u73B0\u7C7B\uFF0C\u67E5\u627E\u548C\u5904\u7406\u9700\u8981 Hook \u7684
Method
\u3001Constructor
\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u79FB\u9664
\u8BF7\u8F6C\u79FB\u5230 members
fun members(vararg member: Member?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u624B\u52A8\u6307\u5B9A\u8981 Hook \u7684
Method
\u3001Constructor
\u3002
\u6CE8\u610F
\u4E0D\u5EFA\u8BAE\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u7F6E\u76EE\u6807\u9700\u8981 Hook \u7684 Member \u5BF9\u8C61\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 method \u6216 constructor \u65B9\u6CD5\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u8C03\u7528 instanceClass
\u6765\u624B\u52A8\u67E5\u627E\u8981 Hook \u7684 Method
\u3001Constructor
\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ members(instanceClass.getDeclaredMethod("test", StringType))
+ beforeHook {}
+ afterHook {}
+}
+
\u540C\u6837\u5730\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u4F20\u5165\u4E00\u7EC4 Member
\u540C\u65F6\u8FDB\u884C Hook\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ members(
+ instanceClass.getDeclaredMethod("test1", StringType),
+ instanceClass.getDeclaredMethod("test2", StringType),
+ instanceClass.getDeclaredMethod("test3", StringType)
+ )
+ beforeHook {}
+ afterHook {}
+}
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4F5C\u5E9F
\u8BF7\u4F7F\u7528 method { name = /** name */ }.all()
\u6765\u53D6\u4EE3\u5B83
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4F5C\u5E9F
\u8BF7\u4F7F\u7528 allMembers(MembersType.CONSTRUCTOR)
\u6765\u53D6\u4EE3\u5B83
fun allMembers(type: MembersType)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u5E76 Hook
hookClass
\u4E2D\u7684\u5168\u90E8Method
\u3001Constructor
\u3002
\u6CE8\u610F
\u65E0\u6CD5\u51C6\u786E\u5904\u7406\u6BCF\u4E2A Member \u7684\u8FD4\u56DE\u503C\u548C param\uFF0C\u5EFA\u8BAE\u4F7F\u7528 method or constructor \u5BF9\u6BCF\u4E2A Member \u5355\u72EC Hook\u3002
inline fun method(initiate: MethodConditions): MethodFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u5F53\u524D
Class
\u9700\u8981 Hook \u7684Method
\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u53C2\u8003 MethodFinder \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = UnitType
+ }
+ beforeHook {}
+ afterHook {}
+}
+
\u82E5\u60F3 Hook \u5F53\u524D\u67E5\u627E method { ... }
\u6761\u4EF6\u7684\u5168\u90E8\u7ED3\u679C\uFF0C\u4F60\u53EA\u9700\u8981\u5728\u6700\u540E\u52A0\u5165 all
\u5373\u53EF\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ method {
+ name = "test"
+ paramCount(1..5)
+ }.all()
+ beforeHook {}
+ afterHook {}
+}
+
\u6B64\u65F6 beforeHook
\u4E0E afterHook
\u4F1A\u5728\u6BCF\u4E2A\u67E5\u627E\u5230\u7684\u7ED3\u679C\u4E2D\u591A\u6B21\u56DE\u8C03 Hook \u65B9\u6CD5\u4F53\u3002
\u6CE8\u610F
\u82E5\u6CA1\u6709 all\uFF0C\u9ED8\u8BA4\u53EA\u4F1A Hook \u5F53\u524D\u6761\u4EF6\u67E5\u627E\u5230\u7684\u6570\u7EC4\u4E0B\u6807\u7ED3\u679C\u7B2C\u4E00\u4F4D\u3002
inline fun constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u67E5\u627E\u5F53\u524D
Class
\u9700\u8981 Hook \u7684Constructor
\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u53C2\u8003 ConstructorFinder \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ constructor { param(StringType) }
+ beforeHook {}
+ afterHook {}
+}
+
\u82E5\u60F3 Hook \u5F53\u524D\u67E5\u627E constructor { ... }
\u6761\u4EF6\u7684\u5168\u90E8\u7ED3\u679C\uFF0C\u4F60\u53EA\u9700\u8981\u5728\u6700\u540E\u52A0\u5165 all
\u5373\u53EF\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ constructor { paramCount(1..5) }.all()
+ beforeHook {}
+ afterHook {}
+}
+
\u6B64\u65F6 beforeHook
\u4E0E afterHook
\u4F1A\u5728\u6BCF\u4E2A\u67E5\u627E\u5230\u7684\u7ED3\u679C\u4E2D\u591A\u6B21\u56DE\u8C03 Hook \u65B9\u6CD5\u4F53\u3002
\u6CE8\u610F
\u82E5\u6CA1\u6709 all\uFF0C\u9ED8\u8BA4\u53EA\u4F1A Hook \u5F53\u524D\u6761\u4EF6\u67E5\u627E\u5230\u7684\u6570\u7EC4\u4E0B\u6807\u7ED3\u679C\u7B2C\u4E00\u4F4D\u3002
inline fun HookParam.field(initiate: FieldConditions): FieldFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u4F7F\u7528\u5F53\u524D
hookClass
\u67E5\u627E\u5E76\u5F97\u5230Field
\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u53C2\u8003 FieldFinder \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = UnitType
+ }
+ afterHook {
+ // \u8FD9\u91CC\u4E0D\u9700\u8981\u518D\u8C03\u7528 instanceClass.field \u8FDB\u884C\u67E5\u627E
+ field {
+ name = "isSweet"
+ type = BooleanType
+ }.get(instance).setTrue()
+ }
+}
+
inline fun HookParam.method(initiate: MethodConditions): MethodFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u4F7F\u7528\u5F53\u524D
hookClass
\u67E5\u627E\u5E76\u5F97\u5230Method
\u3002
inline fun HookParam.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.2
\u6DFB\u52A0
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u4F7F\u7528\u5F53\u524D
hookClass
\u67E5\u627E\u5E76\u5F97\u5230Constructor
\u3002
inline fun HookParam.injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.88
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6CE8\u5165\u8981 Hook \u7684
Method
\u3001Constructor
(\u5D4C\u5957 Hook)\u3002
fun beforeHook(initiate: HookParam.() -> Unit): HookCallback
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u65B0\u589E HookCallback
\u8FD4\u56DE\u7C7B\u578B
\u529F\u80FD\u63CF\u8FF0
\u5728
Member
\u6267\u884C\u5B8C\u6210\u524D Hook\u3002
fun afterHook(initiate: HookParam.() -> Unit): HookCallback
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.1.0
\u4FEE\u6539
\u65B0\u589E HookCallback
\u8FD4\u56DE\u7C7B\u578B
\u529F\u80FD\u63CF\u8FF0
\u5728
Member
\u6267\u884C\u5B8C\u6210\u540E Hook\u3002
fun replaceAny(initiate: HookParam.() -> Any?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u62E6\u622A\u5E76\u66FF\u6362\u6B64
Member
\u5185\u5BB9\uFF0C\u7ED9\u51FA\u8FD4\u56DE\u503C\u3002
fun replaceUnit(initiate: HookParam.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u62E6\u622A\u5E76\u66FF\u6362\u6B64
Member
\u5185\u5BB9\uFF0C\u6CA1\u6709\u8FD4\u56DE\u503C\uFF0C\u53EF\u4EE5\u79F0\u4E3AVoid
\u3002
fun replaceTo(any: Any?)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u62E6\u622A\u5E76\u66FF
Member
\u8FD4\u56DE\u503C\u3002
fun replaceToTrue()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u62E6\u622A\u5E76\u66FF\u6362
Member
\u8FD4\u56DE\u503C\u4E3Atrue
\u3002
\u7279\u522B\u6CE8\u610F
\u786E\u4FDD\u66FF\u6362 Member \u7684\u8FD4\u56DE\u5BF9\u8C61\u4E3A Boolean\u3002
fun replaceToFalse()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u62E6\u622A\u5E76\u66FF\u6362
Member
\u8FD4\u56DE\u503C\u4E3Afalse
\u3002
\u7279\u522B\u6CE8\u610F
\u786E\u4FDD\u66FF\u6362 Member \u7684\u8FD4\u56DE\u5BF9\u8C61\u4E3A Boolean\u3002
fun intercept()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u62E6\u622A\u6B64
Member
\u3002
\u8FD9\u5C06\u4F1A\u7981\u6B62\u6B64 Member
\u6267\u884C\u5E76\u8FD4\u56DE null
\u3002
\u7279\u522B\u6CE8\u610F
\u4F8B\u5982 Int\u3001Long\u3001Boolean \u5E38\u91CF\u8FD4\u56DE\u503C\u7684 Member \u4E00\u65E6\u88AB\u8BBE\u7F6E\u4E3A null \u53EF\u80FD\u4F1A\u9020\u6210 Hook APP \u629B\u51FA\u5F02\u5E38\u3002
fun removeSelf(result: (Boolean) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u79FB\u9664\u5F53\u524D\u6CE8\u5165\u7684 Hook
Method
\u3001Constructor
(\u89E3\u9664 Hook)\u3002
\u7279\u522B\u6CE8\u610F
\u4F60\u53EA\u80FD\u5728 Hook \u56DE\u8C03\u65B9\u6CD5\u4E2D\u4F7F\u7528\u6B64\u529F\u80FD\u3002
inner class HookCallback internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Hook \u65B9\u6CD5\u4F53\u56DE\u8C03\u5B9E\u73B0\u7C7B\u3002
fun onFailureThrowToApp()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5F53\u56DE\u8C03\u65B9\u6CD5\u4F53\u5185\u53D1\u751F\u5F02\u5E38\u65F6\u5C06\u5F02\u5E38\u629B\u51FA\u7ED9\u5F53\u524D Hook APP\u3002
inner class Result internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C Hook \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
v1.0.5
\u4FEE\u6539
\u4FEE\u6539\u4E3A failures
result
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u5931\u8D25\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u4F7F\u7528\u6B64\u65B9\u6CD5\u4E3A Result
\u7C7B\u521B\u5EFA lambda
\u65B9\u6CD5\u4F53\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // Your code here.
+}.result {
+ onHooked {}
+ onAlreadyHooked {}
+ ignoredConductFailure()
+ onHookingFailure {}
+ // ...
+}
+
inline fun by(condition: () -> Boolean): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u6DFB\u52A0\u6267\u884C Hook \u9700\u8981\u6EE1\u8DB3\u7684\u6761\u4EF6\uFF0C\u4E0D\u6EE1\u8DB3\u6761\u4EF6\u5C06\u76F4\u63A5\u505C\u6B62 Hook\u3002
fun onHooked(result: (Member) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C
members
Hook \u6210\u529F\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
\u5728\u9996\u6B21 Hook \u6210\u529F\u540E\u56DE\u8C03\u3002
\u5728\u91CD\u590D Hook \u65F6\u4F1A\u56DE\u8C03 onAlreadyHooked
\u3002
fun onAlreadyHooked(result: (Member) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.89
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C
members
\u91CD\u590D Hook \u7684\u56DE\u8C03\u65B9\u6CD5\u3002
\u6CE8\u610F
\u540C\u4E00\u4E2A hookClass \u4E2D\u7684\u540C\u4E00\u4E2A members \u4E0D\u4F1A\u88AB API \u91CD\u590D Hook\uFF0C\u82E5\u7531\u4E8E\u5404\u79CD\u539F\u56E0\u91CD\u590D Hook \u4F1A\u56DE\u8C03\u6B64\u65B9\u6CD5\u3002
fun onNoSuchMemberFailure(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C
members
\u4E0D\u5B58\u5728\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun onConductFailure(result: (HookParam, Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C Hook \u8FDB\u884C\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun onHookingFailure(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C Hook \u5F00\u59CB\u65F6\u53D1\u751F\u7684\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun onAllFailure(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5168\u90E8 Hook \u8FC7\u7A0B\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun ignoredNoSuchMemberFailure(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565
members
\u4E0D\u5B58\u5728\u53D1\u751F\u7684\u9519\u8BEF\u3002
fun ignoredConductFailure(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565 Hook \u8FDB\u884C\u8FC7\u7A0B\u4E2D\u53D1\u751F\u7684\u9519\u8BEF\u3002
fun ignoredHookingFailure(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565 Hook \u5F00\u59CB\u65F6\u53D1\u751F\u7684\u9519\u8BEF\u3002
fun ignoredAllFailure(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5FFD\u7565\u5168\u90E8 Hook \u8FC7\u7A0B\u53D1\u751F\u7684\u9519\u8BEF\u3002
fun remove(result: (Boolean) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u79FB\u9664\u5F53\u524D\u6CE8\u5165\u7684 Hook
Method
\u3001Constructor
(\u89E3\u9664 Hook)\u3002
\u6CE8\u610F
\u4F60\u53EA\u80FD\u5728 Hook \u6210\u529F\u540E\u624D\u80FD\u89E3\u9664 Hook\uFF0C\u53EF\u76D1\u542C onHooked \u4E8B\u4EF6\u3002
inner class Result internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.3
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5168\u90E8 Hook \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.3
\u65B0\u589E
v1.0.5
\u4FEE\u6539
\u4FEE\u6539\u4E3A failures
result
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
inline fun by(condition: () -> Boolean): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.5
\u65B0\u589E
v1.0.80
\u4FEE\u6539
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u529F\u80FD\u63CF\u8FF0
\u6DFB\u52A0\u6267\u884C Hook \u9700\u8981\u6EE1\u8DB3\u7684\u6761\u4EF6\uFF0C\u4E0D\u6EE1\u8DB3\u6761\u4EF6\u5C06\u76F4\u63A5\u505C\u6B62 Hook\u3002
fun onPrepareHook(callback: () -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.70
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C
hookClass
\u5B58\u5728\u65F6\u51C6\u5907\u5F00\u59CB Hook \u7684\u64CD\u4F5C\u3002
fun onHookClassNotFoundFailure(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.3
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C
hookClass
\u627E\u4E0D\u5230\u65F6\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun ignoredHookClassNotFoundFailure(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.3
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,398),p=[l];function c(r,t){return o(),n("div",null,p)}const i=s(a,[["render",c],["__file","YukiMemberHookCreator.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiMemberHookCreator.html.bacce7a8.js b/docs/assets/YukiMemberHookCreator.html.bacce7a8.js new file mode 100644 index 00000000..ea4c3c36 --- /dev/null +++ b/docs/assets/YukiMemberHookCreator.html.bacce7a8.js @@ -0,0 +1,121 @@ +import{_ as s,o,c as e,a as n}from"./app.fb8271cf.js";const a={},l=n(`\u5FFD\u7565
hookClass
\u627E\u4E0D\u5230\u65F6\u51FA\u73B0\u7684\u9519\u8BEF\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class YukiMemberHookCreator(internal val packageParam: PackageParam, internal val hookClass: HookClass)
+
Change Records
v1.0
first
v1.0.80
modified
\u5BF9 hookClass
\u8FDB\u884C inline \u5904\u7406
v1.1.0
modified
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 Creater \u547D\u540D\u5230 Creator
Function Illustrate
YukiHookAPI
\u7684Member
\u6838\u5FC3 Hook \u5B9E\u73B0\u7C7B\u3002
val PRIORITY_DEFAULT: Int
+
Change Records
v1.0.80
added
Function Illustrate
\u9ED8\u8BA4 Hook \u56DE\u8C03\u4F18\u5148\u7EA7\u3002
val PRIORITY_LOWEST: Int
+
Change Records
v1.0.80
added
Function Illustrate
\u5EF6\u8FDF\u56DE\u8C03 Hook \u65B9\u6CD5\u7ED3\u679C\u3002
val PRIORITY_HIGHEST: Int
+
Change Records
v1.0.80
added
Function Illustrate
\u66F4\u5FEB\u56DE\u8C03 Hook \u65B9\u6CD5\u7ED3\u679C\u3002
val instanceClass: Class<*>
+
Change Records
v1.0
first
v1.0.2
modified
\u66F4\u540D\u4E3A thisClass
instanceClass
Function Illustrate
\u5F97\u5230\u5F53\u524D\u88AB Hook \u7684
Class
\u3002
Pay Attention
\u4E0D\u63A8\u8350\u76F4\u63A5\u4F7F\u7528\uFF0C\u4E07\u4E00\u5F97\u4E0D\u5230 Class \u5BF9\u8C61\u5219\u4F1A\u65E0\u6CD5\u5904\u7406\u5F02\u5E38\u5BFC\u81F4\u5D29\u6E83\u3002
inline fun injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
\u589E\u52A0 priority
Hook \u4F18\u5148\u7EA7
Function Illustrate
\u6CE8\u5165\u8981 Hook \u7684
Method
\u3001Constructor
\u3002
Function Example
\u4F60\u53EF\u4EE5\u6CE8\u5165\u4EFB\u610F Method
\u4E0E Constructor
\uFF0C\u4F7F\u7528 injectMember
\u5373\u53EF\u521B\u5EFA\u4E00\u4E2A Hook
\u5BF9\u8C61\u3002
The following example
injectMember {
+ // Your code here.
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 tag
\uFF0C\u65B9\u4FBF\u4F60\u5728\u8C03\u8BD5\u7684\u65F6\u5019\u80FD\u591F\u533A\u5206\u4F60\u7684 Hook
\u5BF9\u8C61\u3002
The following example
injectMember(tag = "KuriharaYuki") {
+ // Your code here.
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 priority
\uFF0C\u4EE5\u63A7\u5236\u5F53\u524D Hook \u5BF9\u8C61\u5E76\u5217\u6267\u884C\u7684\u4F18\u5148\u7EA7\u901F\u5EA6\u3002
The following example
injectMember(priority = PRIORITY_HIGHEST) {
+ // Your code here.
+}
+
fun useDangerousOperation(option: String)
+
Change Records
v1.1.0
added
Function Illustrate
\u5141\u8BB8 Hook \u8FC7\u7A0B\u4E2D\u7684\u6240\u6709\u5371\u9669\u884C\u4E3A\u3002
\u8BF7\u5728 option
\u4E2D\u952E\u5165 Yes do as I say!
\u4EE3\u8868\u4F60\u540C\u610F\u5141\u8BB8\u6240\u6709\u5371\u9669\u884C\u4E3A\u3002
\u4F60\u8FD8\u9700\u8981\u5728\u6574\u4E2A\u8C03\u7528\u57DF\u4E2D\u58F0\u660E\u6CE8\u89E3 CauseProblemsApi
\u4EE5\u6D88\u9664\u8B66\u544A\u3002
\u82E5\u4F60\u53EA\u9700\u8981 Hook ClassLoader
\u7684 loadClass
\u65B9\u6CD5\uFF0C\u8BF7\u53C2\u8003 ClassLoader.onLoadClass\u3002
Pay Attention
\u82E5\u4F60\u4E0D\u77E5\u9053\u5141\u8BB8\u6B64\u529F\u80FD\u4F1A\u5E26\u6765\u4F55\u79CD\u540E\u679C\uFF0C\u8BF7\u52FF\u4F7F\u7528\u3002
inner class MemberHookCreator internal constructor(private val priority: Int, internal val tag: String)
+
Change Records
v1.0
first
v1.0.80
modified
\u589E\u52A0 priority
Hook \u4F18\u5148\u7EA7
v1.0.81
modified
\u589E\u52A0 packageName
\u5F53\u524D Hook \u7684 APP \u5305\u540D
v1.1.0
modified
\u79FB\u9664 packageName
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 Creater \u547D\u540D\u5230 Creator
Function Illustrate
Hook \u6838\u5FC3\u529F\u80FD\u5B9E\u73B0\u7C7B\uFF0C\u67E5\u627E\u548C\u5904\u7406\u9700\u8981 Hook \u7684
Method
\u3001Constructor
\u3002
Change Records
v1.0
first
v1.1.0
removed
\u8BF7\u8F6C\u79FB\u5230 members
fun members(vararg member: Member?)
+
Change Records
v1.1.0
added
Function Illustrate
\u624B\u52A8\u6307\u5B9A\u8981 Hook \u7684
Method
\u3001Constructor
\u3002
Notice
\u4E0D\u5EFA\u8BAE\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u7F6E\u76EE\u6807\u9700\u8981 Hook \u7684 Member \u5BF9\u8C61\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 method \u6216 constructor \u65B9\u6CD5\u3002
Function Example
\u4F60\u53EF\u4EE5\u8C03\u7528 instanceClass
\u6765\u624B\u52A8\u67E5\u627E\u8981 Hook \u7684 Method
\u3001Constructor
\u3002
The following example
injectMember {
+ members(instanceClass.getDeclaredMethod("test", StringType))
+ beforeHook {}
+ afterHook {}
+}
+
\u540C\u6837\u5730\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u4F20\u5165\u4E00\u7EC4 Member
\u540C\u65F6\u8FDB\u884C Hook\u3002
The following example
injectMember {
+ members(
+ instanceClass.getDeclaredMethod("test1", StringType),
+ instanceClass.getDeclaredMethod("test2", StringType),
+ instanceClass.getDeclaredMethod("test3", StringType)
+ )
+ beforeHook {}
+ afterHook {}
+}
+
Change Records
v1.0
first
v1.1.0
deprecated
\u8BF7\u4F7F\u7528 method { name = /** name */ }.all()
\u6765\u53D6\u4EE3\u5B83
Change Records
v1.0
first
v1.1.0
deprecated
\u8BF7\u4F7F\u7528 allMembers(MembersType.CONSTRUCTOR)
\u6765\u53D6\u4EE3\u5B83
fun allMembers(type: MembersType)
+
Change Records
v1.1.0
added
Function Illustrate
\u67E5\u627E\u5E76 Hook
hookClass
\u4E2D\u7684\u5168\u90E8Method
\u3001Constructor
\u3002
Notice
\u65E0\u6CD5\u51C6\u786E\u5904\u7406\u6BCF\u4E2A Member \u7684\u8FD4\u56DE\u503C\u548C param\uFF0C\u5EFA\u8BAE\u4F7F\u7528 method or constructor \u5BF9\u6BCF\u4E2A Member \u5355\u72EC Hook\u3002
inline fun method(initiate: MethodConditions): MethodFinder.Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u67E5\u627E\u5F53\u524D
Class
\u9700\u8981 Hook \u7684Method
\u3002
Function Example
\u4F60\u53EF\u53C2\u8003 MethodFinder \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5\u3002
The following example
injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = UnitType
+ }
+ beforeHook {}
+ afterHook {}
+}
+
\u82E5\u60F3 Hook \u5F53\u524D\u67E5\u627E method { ... }
\u6761\u4EF6\u7684\u5168\u90E8\u7ED3\u679C\uFF0C\u4F60\u53EA\u9700\u8981\u5728\u6700\u540E\u52A0\u5165 all
\u5373\u53EF\u3002
The following example
injectMember {
+ method {
+ name = "test"
+ paramCount(1..5)
+ }.all()
+ beforeHook {}
+ afterHook {}
+}
+
\u6B64\u65F6 beforeHook
\u4E0E afterHook
\u4F1A\u5728\u6BCF\u4E2A\u67E5\u627E\u5230\u7684\u7ED3\u679C\u4E2D\u591A\u6B21\u56DE\u8C03 Hook \u65B9\u6CD5\u4F53\u3002
Notice
\u82E5\u6CA1\u6709 all\uFF0C\u9ED8\u8BA4\u53EA\u4F1A Hook \u5F53\u524D\u6761\u4EF6\u67E5\u627E\u5230\u7684\u6570\u7EC4\u4E0B\u6807\u7ED3\u679C\u7B2C\u4E00\u4F4D\u3002
inline fun constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u67E5\u627E\u5F53\u524D
Class
\u9700\u8981 Hook \u7684Constructor
\u3002
Function Example
\u4F60\u53EF\u53C2\u8003 ConstructorFinder \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5\u3002
The following example
injectMember {
+ constructor { param(StringType) }
+ beforeHook {}
+ afterHook {}
+}
+
\u82E5\u60F3 Hook \u5F53\u524D\u67E5\u627E constructor { ... }
\u6761\u4EF6\u7684\u5168\u90E8\u7ED3\u679C\uFF0C\u4F60\u53EA\u9700\u8981\u5728\u6700\u540E\u52A0\u5165 all
\u5373\u53EF\u3002
The following example
injectMember {
+ constructor { paramCount(1..5) }.all()
+ beforeHook {}
+ afterHook {}
+}
+
\u6B64\u65F6 beforeHook
\u4E0E afterHook
\u4F1A\u5728\u6BCF\u4E2A\u67E5\u627E\u5230\u7684\u7ED3\u679C\u4E2D\u591A\u6B21\u56DE\u8C03 Hook \u65B9\u6CD5\u4F53\u3002
Notice
\u82E5\u6CA1\u6709 all\uFF0C\u9ED8\u8BA4\u53EA\u4F1A Hook \u5F53\u524D\u6761\u4EF6\u67E5\u627E\u5230\u7684\u6570\u7EC4\u4E0B\u6807\u7ED3\u679C\u7B2C\u4E00\u4F4D\u3002
inline fun HookParam.field(initiate: FieldConditions): FieldFinder.Result
+
Change Records
v1.0
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u4F7F\u7528\u5F53\u524D
hookClass
\u67E5\u627E\u5E76\u5F97\u5230Field
\u3002
Function Example
\u4F60\u53EF\u53C2\u8003 FieldFinder \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5\u3002
The following example
injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = UnitType
+ }
+ afterHook {
+ // \u8FD9\u91CC\u4E0D\u9700\u8981\u518D\u8C03\u7528 instanceClass.field \u8FDB\u884C\u67E5\u627E
+ field {
+ name = "isSweet"
+ type = BooleanType
+ }.get(instance).setTrue()
+ }
+}
+
inline fun HookParam.method(initiate: MethodConditions): MethodFinder.Result
+
Change Records
v1.0.2
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u4F7F\u7528\u5F53\u524D
hookClass
\u67E5\u627E\u5E76\u5F97\u5230Method
\u3002
inline fun HookParam.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
Change Records
v1.0.2
first
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u4F7F\u7528\u5F53\u524D
hookClass
\u67E5\u627E\u5E76\u5F97\u5230Constructor
\u3002
inline fun HookParam.injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
+
Change Records
v1.0.88
added
Function Illustrate
\u6CE8\u5165\u8981 Hook \u7684
Method
\u3001Constructor
(\u5D4C\u5957 Hook)\u3002
fun beforeHook(initiate: HookParam.() -> Unit): HookCallback
+
Change Records
v1.0
first
v1.1.0
modified
\u65B0\u589E HookCallback
\u8FD4\u56DE\u7C7B\u578B
Function Illustrate
\u5728
Member
\u6267\u884C\u5B8C\u6210\u524D Hook\u3002
fun afterHook(initiate: HookParam.() -> Unit): HookCallback
+
Change Records
v1.0
first
v1.1.0
modified
\u65B0\u589E HookCallback
\u8FD4\u56DE\u7C7B\u578B
Function Illustrate
\u5728
Member
\u6267\u884C\u5B8C\u6210\u540E Hook\u3002
fun replaceAny(initiate: HookParam.() -> Any?)
+
Change Records
v1.0
first
Function Illustrate
\u62E6\u622A\u5E76\u66FF\u6362\u6B64
Member
\u5185\u5BB9\uFF0C\u7ED9\u51FA\u8FD4\u56DE\u503C\u3002
fun replaceUnit(initiate: HookParam.() -> Unit)
+
Change Records
v1.0
first
Function Illustrate
\u62E6\u622A\u5E76\u66FF\u6362\u6B64
Member
\u5185\u5BB9\uFF0C\u6CA1\u6709\u8FD4\u56DE\u503C\uFF0C\u53EF\u4EE5\u79F0\u4E3AVoid
\u3002
fun replaceTo(any: Any?)
+
Change Records
v1.0
first
Function Illustrate
\u62E6\u622A\u5E76\u66FF
Member
\u8FD4\u56DE\u503C\u3002
fun replaceToTrue()
+
Change Records
v1.0
first
Function Illustrate
\u62E6\u622A\u5E76\u66FF\u6362
Member
\u8FD4\u56DE\u503C\u4E3Atrue
\u3002
Pay Attention
\u786E\u4FDD\u66FF\u6362 Member \u7684\u8FD4\u56DE\u5BF9\u8C61\u4E3A Boolean\u3002
fun replaceToFalse()
+
Change Records
v1.0
first
Function Illustrate
\u62E6\u622A\u5E76\u66FF\u6362
Member
\u8FD4\u56DE\u503C\u4E3Afalse
\u3002
Pay Attention
\u786E\u4FDD\u66FF\u6362 Member \u7684\u8FD4\u56DE\u5BF9\u8C61\u4E3A Boolean\u3002
fun intercept()
+
Change Records
v1.0
first
Function Illustrate
\u62E6\u622A\u6B64
Member
\u3002
\u8FD9\u5C06\u4F1A\u7981\u6B62\u6B64 Member
\u6267\u884C\u5E76\u8FD4\u56DE null
\u3002
Pay Attention
\u4F8B\u5982 Int\u3001Long\u3001Boolean \u5E38\u91CF\u8FD4\u56DE\u503C\u7684 Member \u4E00\u65E6\u88AB\u8BBE\u7F6E\u4E3A null \u53EF\u80FD\u4F1A\u9020\u6210 Hook APP \u629B\u51FA\u5F02\u5E38\u3002
fun removeSelf(result: (Boolean) -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u79FB\u9664\u5F53\u524D\u6CE8\u5165\u7684 Hook
Method
\u3001Constructor
(\u89E3\u9664 Hook)\u3002
Pay Attention
\u4F60\u53EA\u80FD\u5728 Hook \u56DE\u8C03\u65B9\u6CD5\u4E2D\u4F7F\u7528\u6B64\u529F\u80FD\u3002
inner class HookCallback internal constructor()
+
Change Records
v1.1.0
added
Function Illustrate
Hook \u65B9\u6CD5\u4F53\u56DE\u8C03\u5B9E\u73B0\u7C7B\u3002
fun onFailureThrowToApp()
+
Change Records
v1.1.0
added
Function Illustrate
\u5F53\u56DE\u8C03\u65B9\u6CD5\u4F53\u5185\u53D1\u751F\u5F02\u5E38\u65F6\u5C06\u5F02\u5E38\u629B\u51FA\u7ED9\u5F53\u524D Hook APP\u3002
inner class Result internal constructor()
+
Change Records
v1.0
first
Function Illustrate
\u76D1\u542C Hook \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0
first
v1.0.5
modified
\u4FEE\u6539\u4E3A failures
result
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u5931\u8D25\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
Function Example
\u4F60\u53EF\u4EE5\u4F7F\u7528\u6B64\u65B9\u6CD5\u4E3A Result
\u7C7B\u521B\u5EFA lambda
\u65B9\u6CD5\u4F53\u3002
The following example
injectMember {
+ // Your code here.
+}.result {
+ onHooked {}
+ onAlreadyHooked {}
+ ignoredConductFailure()
+ onHookingFailure {}
+ // ...
+}
+
inline fun by(condition: () -> Boolean): Result
+
Change Records
v1.0.5
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u6DFB\u52A0\u6267\u884C Hook \u9700\u8981\u6EE1\u8DB3\u7684\u6761\u4EF6\uFF0C\u4E0D\u6EE1\u8DB3\u6761\u4EF6\u5C06\u76F4\u63A5\u505C\u6B62 Hook\u3002
fun onHooked(result: (Member) -> Unit): Result
+
Change Records
v1.0.70
added
Function Illustrate
\u76D1\u542C
members
Hook \u6210\u529F\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
\u5728\u9996\u6B21 Hook \u6210\u529F\u540E\u56DE\u8C03\u3002
\u5728\u91CD\u590D Hook \u65F6\u4F1A\u56DE\u8C03 onAlreadyHooked
\u3002
fun onAlreadyHooked(result: (Member) -> Unit): Result
+
Change Records
v1.0.89
added
Function Illustrate
\u76D1\u542C
members
\u91CD\u590D Hook \u7684\u56DE\u8C03\u65B9\u6CD5\u3002
Notice
\u540C\u4E00\u4E2A hookClass \u4E2D\u7684\u540C\u4E00\u4E2A members \u4E0D\u4F1A\u88AB API \u91CD\u590D Hook\uFF0C\u82E5\u7531\u4E8E\u5404\u79CD\u539F\u56E0\u91CD\u590D Hook \u4F1A\u56DE\u8C03\u6B64\u65B9\u6CD5\u3002
fun onNoSuchMemberFailure(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.5
added
Function Illustrate
\u76D1\u542C
members
\u4E0D\u5B58\u5728\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun onConductFailure(result: (HookParam, Throwable) -> Unit): Result
+
Change Records
v1.0
first
Function Illustrate
\u76D1\u542C Hook \u8FDB\u884C\u8FC7\u7A0B\u4E2D\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun onHookingFailure(result: (Throwable) -> Unit): Result
+
Change Records
v1.0
first
Function Illustrate
\u76D1\u542C Hook \u5F00\u59CB\u65F6\u53D1\u751F\u7684\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun onAllFailure(result: (Throwable) -> Unit): Result
+
Change Records
v1.0
first
Function Illustrate
\u76D1\u542C\u5168\u90E8 Hook \u8FC7\u7A0B\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun ignoredNoSuchMemberFailure(): Result
+
Change Records
v1.0.5
added
Function Illustrate
\u5FFD\u7565
members
\u4E0D\u5B58\u5728\u53D1\u751F\u7684\u9519\u8BEF\u3002
fun ignoredConductFailure(): Result
+
Change Records
v1.0
first
Function Illustrate
\u5FFD\u7565 Hook \u8FDB\u884C\u8FC7\u7A0B\u4E2D\u53D1\u751F\u7684\u9519\u8BEF\u3002
fun ignoredHookingFailure(): Result
+
Change Records
v1.0
first
Function Illustrate
\u5FFD\u7565 Hook \u5F00\u59CB\u65F6\u53D1\u751F\u7684\u9519\u8BEF\u3002
fun ignoredAllFailure(): Result
+
Change Records
v1.0
first
Function Illustrate
\u5FFD\u7565\u5168\u90E8 Hook \u8FC7\u7A0B\u53D1\u751F\u7684\u9519\u8BEF\u3002
fun remove(result: (Boolean) -> Unit)
+
Change Records
v1.1.0
added
Function Illustrate
\u79FB\u9664\u5F53\u524D\u6CE8\u5165\u7684 Hook
Method
\u3001Constructor
(\u89E3\u9664 Hook)\u3002
Notice
\u4F60\u53EA\u80FD\u5728 Hook \u6210\u529F\u540E\u624D\u80FD\u89E3\u9664 Hook\uFF0C\u53EF\u76D1\u542C onHooked \u4E8B\u4EF6\u3002
inner class Result internal constructor()
+
Change Records
v1.0.3
added
Function Illustrate
\u76D1\u542C\u5168\u90E8 Hook \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.3
added
v1.0.5
modified
\u4FEE\u6539\u4E3A failures
result
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
inline fun by(condition: () -> Boolean): Result
+
Change Records
v1.0.5
added
v1.0.80
modified
\u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline
Function Illustrate
\u6DFB\u52A0\u6267\u884C Hook \u9700\u8981\u6EE1\u8DB3\u7684\u6761\u4EF6\uFF0C\u4E0D\u6EE1\u8DB3\u6761\u4EF6\u5C06\u76F4\u63A5\u505C\u6B62 Hook\u3002
fun onPrepareHook(callback: () -> Unit): Result
+
Change Records
v1.0.70
added
Function Illustrate
\u76D1\u542C
hookClass
\u5B58\u5728\u65F6\u51C6\u5907\u5F00\u59CB Hook \u7684\u64CD\u4F5C\u3002
fun onHookClassNotFoundFailure(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.3
added
Function Illustrate
\u76D1\u542C
hookClass
\u627E\u4E0D\u5230\u65F6\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun ignoredHookClassNotFoundFailure(): Result
+
Change Records
v1.0.3
added
Function Illustrate
`,399),p=[l];function c(t,r){return o(),e("div",null,p)}const i=s(a,[["render",c],["__file","YukiMemberHookCreator.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiMemberHookCreator.html.d3b181da.js b/docs/assets/YukiMemberHookCreator.html.d3b181da.js new file mode 100644 index 00000000..85e380ac --- /dev/null +++ b/docs/assets/YukiMemberHookCreator.html.d3b181da.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-71147891","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html","title":"YukiMemberHookCreator - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"PRIORITY_DEFAULT - field","slug":"priority-default-field","link":"#priority-default-field","children":[]},{"level":2,"title":"PRIORITY_LOWEST - field","slug":"priority-lowest-field","link":"#priority-lowest-field","children":[]},{"level":2,"title":"PRIORITY_HIGHEST - field","slug":"priority-highest-field","link":"#priority-highest-field","children":[]},{"level":2,"title":"instanceClass - field","slug":"instanceclass-field","link":"#instanceclass-field","children":[]},{"level":2,"title":"injectMember - method","slug":"injectmember-method","link":"#injectmember-method","children":[]},{"level":2,"title":"useDangerousOperation - method","slug":"usedangerousoperation-method","link":"#usedangerousoperation-method","children":[]},{"level":2,"title":"MemberHookCreator - class","slug":"memberhookcreator-class","link":"#memberhookcreator-class","children":[{"level":3,"title":"members - method","slug":"members-method","link":"#members-method","children":[]},{"level":3,"title":"allMembers - method","slug":"allmembers-method","link":"#allmembers-method","children":[]},{"level":3,"title":"method - method","slug":"method-method","link":"#method-method","children":[]},{"level":3,"title":"constructor - method","slug":"constructor-method","link":"#constructor-method","children":[]},{"level":3,"title":"HookParam.field - i-ext-method","slug":"hookparam-field-i-ext-method","link":"#hookparam-field-i-ext-method","children":[]},{"level":3,"title":"HookParam.method - i-ext-method","slug":"hookparam-method-i-ext-method","link":"#hookparam-method-i-ext-method","children":[]},{"level":3,"title":"HookParam.constructor - i-ext-method","slug":"hookparam-constructor-i-ext-method","link":"#hookparam-constructor-i-ext-method","children":[]},{"level":3,"title":"HookParam.injectMember - i-ext-method","slug":"hookparam-injectmember-i-ext-method","link":"#hookparam-injectmember-i-ext-method","children":[]},{"level":3,"title":"beforeHook - method","slug":"beforehook-method","link":"#beforehook-method","children":[]},{"level":3,"title":"afterHook - method","slug":"afterhook-method","link":"#afterhook-method","children":[]},{"level":3,"title":"replaceAny - method","slug":"replaceany-method","link":"#replaceany-method","children":[]},{"level":3,"title":"replaceUnit - method","slug":"replaceunit-method","link":"#replaceunit-method","children":[]},{"level":3,"title":"replaceTo - method","slug":"replaceto-method","link":"#replaceto-method","children":[]},{"level":3,"title":"replaceToTrue - method","slug":"replacetotrue-method","link":"#replacetotrue-method","children":[]},{"level":3,"title":"replaceToFalse - method","slug":"replacetofalse-method","link":"#replacetofalse-method","children":[]},{"level":3,"title":"intercept - method","slug":"intercept-method","link":"#intercept-method","children":[]},{"level":3,"title":"removeSelf - method","slug":"removeself-method","link":"#removeself-method","children":[]},{"level":3,"title":"HookCallback - class","slug":"hookcallback-class","link":"#hookcallback-class","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]}]},{"level":2,"title":"Result - class","slug":"result-class-1","link":"#result-class-1","children":[{"level":3,"title":"result - method","slug":"result-method-1","link":"#result-method-1","children":[]},{"level":3,"title":"by - method","slug":"by-method-1","link":"#by-method-1","children":[]},{"level":3,"title":"onPrepareHook - method","slug":"onpreparehook-method","link":"#onpreparehook-method","children":[]},{"level":3,"title":"onHookClassNotFoundFailure - method","slug":"onhookclassnotfoundfailure-method","link":"#onhookclassnotfoundfailure-method","children":[]},{"level":3,"title":"ignoredHookClassNotFoundFailure - method","slug":"ignoredhookclassnotfoundfailure-method","link":"#ignoredhookclassnotfoundfailure-method","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md"}');export{e as data}; diff --git a/docs/assets/YukiModuleResources.html.581abd4c.js b/docs/assets/YukiModuleResources.html.581abd4c.js new file mode 100644 index 00000000..69af4d4c --- /dev/null +++ b/docs/assets/YukiModuleResources.html.581abd4c.js @@ -0,0 +1,3 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const n={},l=a(`\u5FFD\u7565
hookClass
\u627E\u4E0D\u5230\u65F6\u51FA\u73B0\u7684\u9519\u8BEF\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class YukiModuleResources private constructor(private val baseInstance: XModuleResources) : Resources
+
Change Records
v1.0.80
added
Function Illustrate
\u5BF9\u63A5
XModuleResources
\u7684\u4E2D\u95F4\u5C42\u5B9E\u4F8B\u3002
fun fwd(resId: Int): YukiResForwarder
+
Change Records
v1.0.80
added
Function Illustrate
\u5BF9\u63A5
XModuleResources.fwd
\u65B9\u6CD5\u3002
\u521B\u5EFA YukiResForwarder
\u4E0E XResForwarder
\u5B9E\u4F8B\u3002
class YukiModuleResources private constructor(private val baseInstance: XModuleResources) : Resources
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5BF9\u63A5
XModuleResources
\u7684\u4E2D\u95F4\u5C42\u5B9E\u4F8B\u3002
fun fwd(resId: Int): YukiResForwarder
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5BF9\u63A5
XModuleResources.fwd
\u65B9\u6CD5\u3002
\u521B\u5EFA YukiResForwarder
\u4E0E XResForwarder
\u5B9E\u4F8B\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class YukiResForwarder private constructor(private val baseInstance: XResForwarder)
+
Change Records
v1.0.80
added
Function Illustrate
\u5BF9\u63A5
XResForwarder
\u7684\u4E2D\u95F4\u5C42\u5B9E\u4F8B\u3002
Change Records
v1.0.80
added
v1.1.0
deprecated
\u4E0D\u518D\u5BF9\u5916\u516C\u5F00 instance
\u53C2\u6570
val id: Int
+
Change Records
v1.0.80
added
Function Illustrate
\u83B7\u5F97\u5F53\u524D APP \u7684 Resources Id\u3002
val resources: Resources
+
Change Records
v1.0.80
added
Function Illustrate
`,24),c=[r];function l(t,p){return e(),o("div",null,c)}const i=s(n,[["render",l],["__file","YukiResForwarder.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiResForwarder.html.4e23df75.js b/docs/assets/YukiResForwarder.html.4e23df75.js new file mode 100644 index 00000000..c6eb7cc3 --- /dev/null +++ b/docs/assets/YukiResForwarder.html.4e23df75.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-35faec91","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html","title":"YukiResForwarder - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"id - field","slug":"id-field","link":"#id-field","children":[]},{"level":2,"title":"resources - field","slug":"resources-field","link":"#resources-field","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.md"}');export{e as data}; diff --git a/docs/assets/YukiResForwarder.html.ef96ef7b.js b/docs/assets/YukiResForwarder.html.ef96ef7b.js new file mode 100644 index 00000000..6b56edd9 --- /dev/null +++ b/docs/assets/YukiResForwarder.html.ef96ef7b.js @@ -0,0 +1,4 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const n={},c=a(`\u83B7\u5F97\u5F53\u524D APP \u7684 Resources\u3002
class YukiResForwarder private constructor(private val baseInstance: XResForwarder)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5BF9\u63A5
XResForwarder
\u7684\u4E2D\u95F4\u5C42\u5B9E\u4F8B\u3002
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
v1.1.0
\u4F5C\u5E9F
\u4E0D\u518D\u5BF9\u5916\u516C\u5F00 instance
\u53C2\u6570
val id: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u5F97\u5F53\u524D APP \u7684 Resources Id\u3002
val resources: Resources
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,23),l=[c];function r(p,t){return e(),o("div",null,l)}const i=s(n,[["render",r],["__file","YukiResForwarder.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiResources.html.7b0a4824.js b/docs/assets/YukiResources.html.7b0a4824.js new file mode 100644 index 00000000..4bd70ba6 --- /dev/null +++ b/docs/assets/YukiResources.html.7b0a4824.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-68541dca","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html","title":"YukiResources - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"LayoutInflatedParam - class","slug":"layoutinflatedparam-class","link":"#layoutinflatedparam-class","children":[{"level":3,"title":"variantName - field","slug":"variantname-field","link":"#variantname-field","children":[]},{"level":3,"title":"currentView - field","slug":"currentview-field","link":"#currentview-field","children":[]},{"level":3,"title":"findViewByIdentifier - method","slug":"findviewbyidentifier-method","link":"#findviewbyidentifier-method","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.md"}');export{e as data}; diff --git a/docs/assets/YukiResources.html.afb6fb92.js b/docs/assets/YukiResources.html.afb6fb92.js new file mode 100644 index 00000000..7459706b --- /dev/null +++ b/docs/assets/YukiResources.html.afb6fb92.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2c04b82a","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html","title":"YukiResources - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"LayoutInflatedParam - class","slug":"layoutinflatedparam-class","link":"#layoutinflatedparam-class","children":[{"level":3,"title":"variantName - field","slug":"variantname-field","link":"#variantname-field","children":[]},{"level":3,"title":"currentView - field","slug":"currentview-field","link":"#currentview-field","children":[]},{"level":3,"title":"findViewByIdentifier - method","slug":"findviewbyidentifier-method","link":"#findviewbyidentifier-method","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.md"}');export{e as data}; diff --git a/docs/assets/YukiResources.html.b3a31d94.js b/docs/assets/YukiResources.html.b3a31d94.js new file mode 100644 index 00000000..15d74cbc --- /dev/null +++ b/docs/assets/YukiResources.html.b3a31d94.js @@ -0,0 +1,7 @@ +import{_ as s,o as a,c as n,a as o}from"./app.fb8271cf.js";const e={},l=o(`\u83B7\u5F97\u5F53\u524D APP \u7684 Resources\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class YukiResources private constructor(private val baseInstance: XResources) : Resources
+
Change Records
v1.0.80
added
Function Illustrate
\u5BF9\u63A5
XResources
\u7684\u4E2D\u95F4\u5C42\u5B9E\u4F8B\u3002
class LayoutInflatedParam(internal val baseParam: XC_LayoutInflated.LayoutInflatedParam)
+
Change Records
v1.0.80
added
Function Illustrate
\u88C5\u8F7D Hook APP \u7684\u76EE\u6807\u5E03\u5C40 Resources \u5B9E\u73B0\u7C7B\u3002
val variantName: String
+
Change Records
v1.0.80
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D\u88AB Hook \u7684\u5E03\u5C40\u88C5\u8F7D\u76EE\u5F55\u540D\u79F0\u3002
\u4F8B\u5982\uFF1Alayout
\u3001layout-land
\u3001layout-sw600dp
\u3002
val currentView: View
+
Change Records
v1.0.80
added
Function Illustrate
\u83B7\u53D6\u5F53\u524D\u88AB Hook \u7684\u5E03\u5C40\u5B9E\u4F8B\u3002
inline fun <reified T : View> View.findViewByIdentifier(name: String): T?
+
inline fun <reified T : View> findViewByIdentifier(name: String): T?
+
Change Records
v1.0.80
added
Function Illustrate
\u4F7F\u7528 Identifier \u67E5\u627E Hook APP \u6307\u5B9A Id \u7684
View
\u3002
\u6269\u5C55\u65B9\u6CD5\u53EF\u4EE5\u4F7F\u7528 Identifier \u67E5\u627E Hook APP \u5F53\u524D\u88C5\u8F7D\u5E03\u5C40\u4E2D\u6307\u5B9A Id \u7684 View
\u3002
class YukiResources private constructor(private val baseInstance: XResources) : Resources
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5BF9\u63A5
XResources
\u7684\u4E2D\u95F4\u5C42\u5B9E\u4F8B\u3002
class LayoutInflatedParam(internal val baseParam: XC_LayoutInflated.LayoutInflatedParam)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u88C5\u8F7D Hook APP \u7684\u76EE\u6807\u5E03\u5C40 Resources \u5B9E\u73B0\u7C7B\u3002
val variantName: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D\u88AB Hook \u7684\u5E03\u5C40\u88C5\u8F7D\u76EE\u5F55\u540D\u79F0\u3002
\u4F8B\u5982\uFF1Alayout
\u3001layout-land
\u3001layout-sw600dp
\u3002
val currentView: View
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u83B7\u53D6\u5F53\u524D\u88AB Hook \u7684\u5E03\u5C40\u5B9E\u4F8B\u3002
inline fun <reified T : View> View.findViewByIdentifier(name: String): T?
+
inline fun <reified T : View> findViewByIdentifier(name: String): T?
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4F7F\u7528 Identifier \u67E5\u627E Hook APP \u6307\u5B9A Id \u7684
View
\u3002
\u6269\u5C55\u65B9\u6CD5\u53EF\u4EE5\u4F7F\u7528 Identifier \u67E5\u627E Hook APP \u5F53\u524D\u88C5\u8F7D\u5E03\u5C40\u4E2D\u6307\u5B9A Id \u7684 View
\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
class YukiResourcesHookCreator(internal val packageParam: PackageParam, internal val hookResources: HookResources)
+
Change Records
v1.0.80
added
v1.1.0
modified
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 Creater \u547D\u540D\u5230 Creator
Function Illustrate
YukiHookAPI
\u7684Resources
\u6838\u5FC3 Hook \u5B9E\u73B0\u7C7B\u3002
inline fun injectResource(tag: String, initiate: ResourceHookCreator.() -> Unit): ResourceHookCreator.Result
+
Change Records
v1.0.80
added
Function Illustrate
\u6CE8\u5165\u8981 Hook \u7684 Resources\u3002
Function Example
\u4F60\u53EF\u4EE5\u6CE8\u5165\u4EFB\u610F Resources\uFF0C\u4F7F\u7528 injectResource
\u5373\u53EF\u521B\u5EFA\u4E00\u4E2A Hook
\u5BF9\u8C61\u3002
The following example
injectResource {
+ // Your code here.
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 tag
\uFF0C\u65B9\u4FBF\u4F60\u5728\u8C03\u8BD5\u7684\u65F6\u5019\u80FD\u591F\u533A\u5206\u4F60\u7684 Hook
\u5BF9\u8C61\u3002
The following example
injectResource(tag = "KuriharaYuki") {
+ // Your code here.
+}
+
inner class ResourcesHookCreator internal constructor(private val tag: String)
+
Change Records
v1.0.80
added
v1.1.0
modified
\u79FB\u9664 packageName
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 Creater \u547D\u540D\u5230 Creator
Function Illustrate
Hook \u6838\u5FC3\u529F\u80FD\u5B9E\u73B0\u7C7B\u3002
\u67E5\u627E\u548C\u5904\u7406\u9700\u8981 Hook \u7684 Resources\u3002
var resourceId: Int
+
Change Records
v1.0.80
added
Function Illustrate
\u76F4\u63A5\u8BBE\u7F6E\u9700\u8981\u66FF\u6362\u7684 Resources Id\u3002
Notice
\u4E0D\u5EFA\u8BAE\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u7F6E\u76EE\u6807\u9700\u8981 Hook \u7684 Resources Id\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 conditions \u65B9\u6CD5\u3002
Function Example
\u4F60\u53EF\u4EE5\u76F4\u63A5\u8BBE\u7F6E\u5E76\u6307\u5B9A\u76EE\u6807 Hook APP \u7684 Resources Id\u3002
The following example
injectResource {
+ resourceId = 0x7f060001.toInt()
+ replaceTo(...)
+}
+
inline fun conditions(initiate: ConditionFinder.() -> Unit)
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u67E5\u627E\u6761\u4EF6\u3002
\u82E5\u4F60\u8BBE\u7F6E\u4E86 resourceId
\u5219\u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u4F7F\u7528\u3002
Function Example
\u4F60\u53EF\u53C2\u8003 ConditionFinder \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5\u3002
The following example
injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceTo(...)
+}
+
fun replaceTo(any: Any)
+
Change Records
v1.0.80
added
Function Illustrate
\u66FF\u6362\u6307\u5B9A Resources \u4E3A\u6307\u5B9A\u7684\u503C\u3002
Function Example
\u4F60\u53EF\u4EE5\u66FF\u6362\u627E\u5230\u7684 Resources \u4E3A\u4F60\u60F3\u8981\u7684\u503C\uFF0C\u53EF\u4EE5\u662F String
\u3001Drawable
\u7B49\u3002
\u6BD4\u5982\u6211\u4EEC\u8981\u66FF\u6362\u4E00\u4E2A\u627E\u5230\u7684\u5B57\u7B26\u4E32 Resources\u3002
The following example
injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceTo("replace string")
+}
+
\u6216\u662F\u66FF\u6362\u4E3A\u4E00\u4E2A Drawable
\uFF0C\u4F60\u65E0\u9700\u5BF9\u76EE\u6807 Resources \u5B9E\u73B0 fwd
\u65B9\u6CD5\u6216 DrawableLoader
\u3002
The following example
injectResource {
+ conditions {
+ name = "test_drawable"
+ drawable()
+ }
+ replaceTo(ColorDrawable(Color.RED))
+}
+
fun replaceToTrue()
+
Change Records
v1.0.80
added
Function Illustrate
\u66FF\u6362\u6307\u5B9A Resources \u4E3A
true
\u3002
Pay Attention
\u786E\u4FDD\u76EE\u6807\u66FF\u6362 Resources \u7684\u7C7B\u578B\u4E3A Boolean\u3002
fun replaceToFalse()
+
Change Records
v1.0.80
added
Function Illustrate
\u66FF\u6362\u6307\u5B9A Resources \u4E3A
false
\u3002
Pay Attention
\u786E\u4FDD\u76EE\u6807\u66FF\u6362 Resources \u7684\u7C7B\u578B\u4E3A Boolean\u3002
fun replaceToModuleResource(resId: Int)
+
Change Records
v1.0.80
added
Function Illustrate
\u66FF\u6362\u4E3A\u5F53\u524D Xposed \u6A21\u5757\u7684 Resources\u3002
\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u6A21\u5757\u7684 R.string.xxx
\u3001R.mipmap.xxx
\u3001R.drawable.xxx
\u66FF\u6362 Hook APP \u7684 Resources\u3002
Function Example
\u4F7F\u7528\u6B64\u65B9\u6CD5\u53EF\u975E\u5E38\u65B9\u4FBF\u5730\u4F7F\u7528\u5F53\u524D\u6A21\u5757\u7684 Resources \u53BB\u66FF\u6362\u76EE\u6807 Hook APP \u7684 Resources\u3002
\u8FD9\u4E2A\u8FC7\u7A0B\u4F60\u65E0\u9700\u5BF9\u76EE\u6807 Resources \u5B9E\u73B0 fwd
\u65B9\u6CD5\u3002
\u6BD4\u5982\u6211\u4EEC\u8981\u66FF\u6362\u4E00\u4E2A\u5B57\u7B26\u4E32\u3002
The following example
injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceToModuleResource(R.string.module_string)
+}
+
\u8FD8\u53EF\u4EE5\u66FF\u6362\u4E00\u4E9B\u590D\u6742\u7684 Resources\uFF0C\u6BD4\u5982 xml
\u521B\u5EFA\u7684 drawable
\u3002
The following example
injectResource {
+ conditions {
+ name = "test_drawable"
+ drawable()
+ }
+ replaceToModuleResource(R.drawable.module_drawable)
+}
+
fun injectAsLayout(initiate: YukiResources.LayoutInflatedParam.() -> Unit)
+
Change Records
v1.0.80
added
Function Illustrate
\u4F5C\u4E3A\u88C5\u8F7D\u7684\u5E03\u5C40\u6CE8\u5165\u3002
Function Example
\u4F60\u53EF\u4EE5\u76F4\u63A5\u6CE8\u5165\u4E00\u4E2A\u5E03\u5C40\u76D1\u542C\u5E76\u4FEE\u6539\u5B83\u7684\u5185\u90E8 View
\u3002
The following example
injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ findViewByIdentifier<View>(name = "test_view")?.isVisible = false
+ findViewByIdentifier<TextView>(name = "test_text_view")?.text = "Hook this"
+ }
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u901A\u8FC7 currentView
\u62FF\u5230 Context
\u3002
The following example
injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ Toast.makeText(currentView.context, "Hook this", Toast.LENGTH_SHORT).show()
+ }
+}
+
inner class ConditionFinder internal constructor()
+
Change Records
v1.0.80
added
Function Illustrate
Resources \u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
var name: String
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u540D\u79F0\u3002
fun anim()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u52A8\u753B\u3002
fun animator()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5C5E\u6027\u52A8\u753B\u3002
fun bool()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5E03\u6717(Boolean)\u3002
fun color()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u989C\u8272(Color)\u3002
fun dimen()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5C3A\u5BF8(Dimention)\u3002
fun drawable()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Drawable\u3002
fun integer()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u6574\u578B(Integer)\u3002
fun layout()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5E03\u5C40(Layout)\u3002
fun plurals()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Plurals\u3002
fun string()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5B57\u7B26\u4E32(String)\u3002
fun xml()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Xml\u3002
fun mipmap()
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u4F4D\u56FE(Mipmap)\u3002
fun array()
+
Change Records
v1.1.0
added
Function Illustrate
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u6570\u7EC4(Array)\u3002
inner class Result internal constructor()
+
Change Records
v1.0.80
added
Function Illustrate
\u76D1\u542C\u5168\u90E8 Hook \u7ED3\u679C\u5B9E\u73B0\u7C7B\uFF0C\u53EF\u5728\u8FD9\u91CC\u5904\u7406\u5931\u8D25\u4E8B\u4EF6\u76D1\u542C\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
Change Records
v1.0.80
added
Function Illustrate
\u521B\u5EFA\u76D1\u542C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
inline fun by(condition: () -> Boolean): Result
+
Change Records
v1.0.80
added
Function Illustrate
\u6DFB\u52A0\u6267\u884C Hook \u9700\u8981\u6EE1\u8DB3\u7684\u6761\u4EF6\uFF0C\u4E0D\u6EE1\u8DB3\u6761\u4EF6\u5C06\u76F4\u63A5\u505C\u6B62 Hook\u3002
fun onHookingFailure(result: (Throwable) -> Unit): Result
+
Change Records
v1.0.80
added
Function Illustrate
\u76D1\u542C Hook \u8FC7\u7A0B\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun ignoredHookingFailure(): Result
+
Change Records
v1.0.80
added
Function Illustrate
`,231),p=[l];function c(r,t){return n(),e("div",null,p)}const d=s(o,[["render",c],["__file","YukiResourcesHookCreator.html.vue"]]);export{d as default}; diff --git a/docs/assets/YukiResourcesHookCreator.html.ddbc430b.js b/docs/assets/YukiResourcesHookCreator.html.ddbc430b.js new file mode 100644 index 00000000..61d7319e --- /dev/null +++ b/docs/assets/YukiResourcesHookCreator.html.ddbc430b.js @@ -0,0 +1,95 @@ +import{_ as s,o as n,c as a,a as o}from"./app.fb8271cf.js";const e={},l=o(`\u5FFD\u7565 Hook \u8FC7\u7A0B\u51FA\u73B0\u7684\u9519\u8BEF\u3002
class YukiResourcesHookCreator(internal val packageParam: PackageParam, internal val hookResources: HookResources)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 Creater \u547D\u540D\u5230 Creator
\u529F\u80FD\u63CF\u8FF0
YukiHookAPI
\u7684Resources
\u6838\u5FC3 Hook \u5B9E\u73B0\u7C7B\u3002
inline fun injectResource(tag: String, initiate: ResourceHookCreator.() -> Unit): ResourceHookCreator.Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6CE8\u5165\u8981 Hook \u7684 Resources\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u6CE8\u5165\u4EFB\u610F Resources\uFF0C\u4F7F\u7528 injectResource
\u5373\u53EF\u521B\u5EFA\u4E00\u4E2A Hook
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ // Your code here.
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u81EA\u5B9A\u4E49 tag
\uFF0C\u65B9\u4FBF\u4F60\u5728\u8C03\u8BD5\u7684\u65F6\u5019\u80FD\u591F\u533A\u5206\u4F60\u7684 Hook
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource(tag = "KuriharaYuki") {
+ // Your code here.
+}
+
inner class ResourcesHookCreator internal constructor(private val tag: String)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
v1.1.0
\u4FEE\u6539
\u79FB\u9664 packageName
\u4FEE\u6B63\u62FC\u5199\u9519\u8BEF\u7684 Creater \u547D\u540D\u5230 Creator
\u529F\u80FD\u63CF\u8FF0
Hook \u6838\u5FC3\u529F\u80FD\u5B9E\u73B0\u7C7B\u3002
\u67E5\u627E\u548C\u5904\u7406\u9700\u8981 Hook \u7684 Resources\u3002
var resourceId: Int
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76F4\u63A5\u8BBE\u7F6E\u9700\u8981\u66FF\u6362\u7684 Resources Id\u3002
\u6CE8\u610F
\u4E0D\u5EFA\u8BAE\u4F7F\u7528\u6B64\u65B9\u6CD5\u8BBE\u7F6E\u76EE\u6807\u9700\u8981 Hook \u7684 Resources Id\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 conditions \u65B9\u6CD5\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u76F4\u63A5\u8BBE\u7F6E\u5E76\u6307\u5B9A\u76EE\u6807 Hook APP \u7684 Resources Id\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ resourceId = 0x7f060001.toInt()
+ replaceTo(...)
+}
+
inline fun conditions(initiate: ConditionFinder.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u67E5\u627E\u6761\u4EF6\u3002
\u82E5\u4F60\u8BBE\u7F6E\u4E86 resourceId
\u5219\u6B64\u65B9\u6CD5\u5C06\u4E0D\u4F1A\u88AB\u4F7F\u7528\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u53C2\u8003 ConditionFinder \u67E5\u770B\u8BE6\u7EC6\u7528\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceTo(...)
+}
+
fun replaceTo(any: Any)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u66FF\u6362\u6307\u5B9A Resources \u4E3A\u6307\u5B9A\u7684\u503C\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u66FF\u6362\u627E\u5230\u7684 Resources \u4E3A\u4F60\u60F3\u8981\u7684\u503C\uFF0C\u53EF\u4EE5\u662F String
\u3001Drawable
\u7B49\u3002
\u6BD4\u5982\u6211\u4EEC\u8981\u66FF\u6362\u4E00\u4E2A\u627E\u5230\u7684\u5B57\u7B26\u4E32 Resources\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceTo("replace string")
+}
+
\u6216\u662F\u66FF\u6362\u4E3A\u4E00\u4E2A Drawable
\uFF0C\u4F60\u65E0\u9700\u5BF9\u76EE\u6807 Resources \u5B9E\u73B0 fwd
\u65B9\u6CD5\u6216 DrawableLoader
\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ conditions {
+ name = "test_drawable"
+ drawable()
+ }
+ replaceTo(ColorDrawable(Color.RED))
+}
+
fun replaceToTrue()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u66FF\u6362\u6307\u5B9A Resources \u4E3A
true
\u3002
\u7279\u522B\u6CE8\u610F
\u786E\u4FDD\u76EE\u6807\u66FF\u6362 Resources \u7684\u7C7B\u578B\u4E3A Boolean\u3002
fun replaceToFalse()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u66FF\u6362\u6307\u5B9A Resources \u4E3A
false
\u3002
\u7279\u522B\u6CE8\u610F
\u786E\u4FDD\u76EE\u6807\u66FF\u6362 Resources \u7684\u7C7B\u578B\u4E3A Boolean\u3002
fun replaceToModuleResource(resId: Int)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u66FF\u6362\u4E3A\u5F53\u524D Xposed \u6A21\u5757\u7684 Resources\u3002
\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u6A21\u5757\u7684 R.string.xxx
\u3001R.mipmap.xxx
\u3001R.drawable.xxx
\u66FF\u6362 Hook APP \u7684 Resources\u3002
\u529F\u80FD\u793A\u4F8B
\u4F7F\u7528\u6B64\u65B9\u6CD5\u53EF\u975E\u5E38\u65B9\u4FBF\u5730\u4F7F\u7528\u5F53\u524D\u6A21\u5757\u7684 Resources \u53BB\u66FF\u6362\u76EE\u6807 Hook APP \u7684 Resources\u3002
\u8FD9\u4E2A\u8FC7\u7A0B\u4F60\u65E0\u9700\u5BF9\u76EE\u6807 Resources \u5B9E\u73B0 fwd
\u65B9\u6CD5\u3002
\u6BD4\u5982\u6211\u4EEC\u8981\u66FF\u6362\u4E00\u4E2A\u5B57\u7B26\u4E32\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceToModuleResource(R.string.module_string)
+}
+
\u8FD8\u53EF\u4EE5\u66FF\u6362\u4E00\u4E9B\u590D\u6742\u7684 Resources\uFF0C\u6BD4\u5982 xml
\u521B\u5EFA\u7684 drawable
\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ conditions {
+ name = "test_drawable"
+ drawable()
+ }
+ replaceToModuleResource(R.drawable.module_drawable)
+}
+
fun injectAsLayout(initiate: YukiResources.LayoutInflatedParam.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u4F5C\u4E3A\u88C5\u8F7D\u7684\u5E03\u5C40\u6CE8\u5165\u3002
\u529F\u80FD\u793A\u4F8B
\u4F60\u53EF\u4EE5\u76F4\u63A5\u6CE8\u5165\u4E00\u4E2A\u5E03\u5C40\u76D1\u542C\u5E76\u4FEE\u6539\u5B83\u7684\u5185\u90E8 View
\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ findViewByIdentifier<View>(name = "test_view")?.isVisible = false
+ findViewByIdentifier<TextView>(name = "test_text_view")?.text = "Hook this"
+ }
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u901A\u8FC7 currentView
\u62FF\u5230 Context
\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ Toast.makeText(currentView.context, "Hook this", Toast.LENGTH_SHORT).show()
+ }
+}
+
inner class ConditionFinder internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
Resources \u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002
var name: String
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u540D\u79F0\u3002
fun anim()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u52A8\u753B\u3002
fun animator()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5C5E\u6027\u52A8\u753B\u3002
fun bool()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5E03\u6717(Boolean)\u3002
fun color()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u989C\u8272(Color)\u3002
fun dimen()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5C3A\u5BF8(Dimention)\u3002
fun drawable()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Drawable\u3002
fun integer()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u6574\u578B(Integer)\u3002
fun layout()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5E03\u5C40(Layout)\u3002
fun plurals()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Plurals\u3002
fun string()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5B57\u7B26\u4E32(String)\u3002
fun xml()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Xml\u3002
fun mipmap()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u4F4D\u56FE(Mipmap)\u3002
fun array()
+
\u53D8\u66F4\u8BB0\u5F55
v1.1.0
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u6570\u7EC4(Array)\u3002
inner class Result internal constructor()
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C\u5168\u90E8 Hook \u7ED3\u679C\u5B9E\u73B0\u7C7B\uFF0C\u53EF\u5728\u8FD9\u91CC\u5904\u7406\u5931\u8D25\u4E8B\u4EF6\u76D1\u542C\u3002
inline fun result(initiate: Result.() -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u521B\u5EFA\u76D1\u542C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002
inline fun by(condition: () -> Boolean): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u6DFB\u52A0\u6267\u884C Hook \u9700\u8981\u6EE1\u8DB3\u7684\u6761\u4EF6\uFF0C\u4E0D\u6EE1\u8DB3\u6761\u4EF6\u5C06\u76F4\u63A5\u505C\u6B62 Hook\u3002
fun onHookingFailure(result: (Throwable) -> Unit): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u76D1\u542C Hook \u8FC7\u7A0B\u53D1\u751F\u9519\u8BEF\u7684\u56DE\u8C03\u65B9\u6CD5\u3002
fun ignoredHookingFailure(): Result
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,230),p=[l];function c(r,t){return n(),a("div",null,p)}const d=s(e,[["render",c],["__file","YukiResourcesHookCreator.html.vue"]]);export{d as default}; diff --git a/docs/assets/YukiXposedEvent.html.560fa41c.js b/docs/assets/YukiXposedEvent.html.560fa41c.js new file mode 100644 index 00000000..d3a84633 --- /dev/null +++ b/docs/assets/YukiXposedEvent.html.560fa41c.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-19e7277e","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html","title":"YukiXposedEvent - object","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"events - method","slug":"events-method","link":"#events-method","children":[]},{"level":2,"title":"onInitZygote - method","slug":"oninitzygote-method","link":"#oninitzygote-method","children":[]},{"level":2,"title":"onHandleLoadPackage - method","slug":"onhandleloadpackage-method","link":"#onhandleloadpackage-method","children":[]},{"level":2,"title":"onHandleInitPackageResources - method","slug":"onhandleinitpackageresources-method","link":"#onhandleinitpackageresources-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.md"}');export{e as data}; diff --git a/docs/assets/YukiXposedEvent.html.a93ee4ef.js b/docs/assets/YukiXposedEvent.html.a93ee4ef.js new file mode 100644 index 00000000..545829fb --- /dev/null +++ b/docs/assets/YukiXposedEvent.html.a93ee4ef.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0a4de82f","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html","title":"YukiXposedEvent - object","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"events - method","slug":"events-method","link":"#events-method","children":[]},{"level":2,"title":"onInitZygote - method","slug":"oninitzygote-method","link":"#oninitzygote-method","children":[]},{"level":2,"title":"onHandleLoadPackage - method","slug":"onhandleloadpackage-method","link":"#onhandleloadpackage-method","children":[]},{"level":2,"title":"onHandleInitPackageResources - method","slug":"onhandleinitpackageresources-method","link":"#onhandleinitpackageresources-method","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.md"}');export{e as data}; diff --git a/docs/assets/YukiXposedEvent.html.ae210e6f.js b/docs/assets/YukiXposedEvent.html.ae210e6f.js new file mode 100644 index 00000000..ba19d7c6 --- /dev/null +++ b/docs/assets/YukiXposedEvent.html.ae210e6f.js @@ -0,0 +1,6 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const n={},t=a(`\u5FFD\u7565 Hook \u8FC7\u7A0B\u51FA\u73B0\u7684\u9519\u8BEF\u3002
Notice
The English translation of this page has not been completed, you are welcome to contribute translations to us.
You can use the Chrome Translation Plugin to translate entire pages for reference.
object YukiXposedEvent
+
Change Records
v1.0.80
first
Function Illustrate
\u5B9E\u73B0\u5BF9\u539F\u751F Xposed API \u7684\u88C5\u8F7D\u4E8B\u4EF6\u76D1\u542C\u3002
inline fun events(initiate: YukiXposedEvent.() -> Unit)
+
Change Records
v1.0.80
added
Function Illustrate
\u5BF9
YukiXposedEvent
\u521B\u5EFA\u4E00\u4E2A\u65B9\u6CD5\u4F53\u3002
fun onInitZygote(result: (StartupParam) -> Unit)
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E initZygote \u4E8B\u4EF6\u76D1\u542C\u3002
fun onHandleLoadPackage(result: (LoadPackageParam) -> Unit)
+
Change Records
v1.0.80
added
Function Illustrate
\u8BBE\u7F6E handleLoadPackage \u4E8B\u4EF6\u76D1\u542C\u3002
fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
+
Change Records
v1.0.80
added
Function Illustrate
`,31),l=[t];function p(c,r){return e(),o("div",null,l)}const i=s(n,[["render",p],["__file","YukiXposedEvent.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiXposedEvent.html.e00ead3e.js b/docs/assets/YukiXposedEvent.html.e00ead3e.js new file mode 100644 index 00000000..fd82a397 --- /dev/null +++ b/docs/assets/YukiXposedEvent.html.e00ead3e.js @@ -0,0 +1,6 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},l=e(`\u8BBE\u7F6E handleInitPackageResources \u4E8B\u4EF6\u76D1\u542C\u3002
object YukiXposedEvent
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u6DFB\u52A0
\u529F\u80FD\u63CF\u8FF0
\u5B9E\u73B0\u5BF9\u539F\u751F Xposed API \u7684\u88C5\u8F7D\u4E8B\u4EF6\u76D1\u542C\u3002
inline fun events(initiate: YukiXposedEvent.() -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u5BF9
YukiXposedEvent
\u521B\u5EFA\u4E00\u4E2A\u65B9\u6CD5\u4F53\u3002
fun onInitZygote(result: (StartupParam) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E initZygote \u4E8B\u4EF6\u76D1\u542C\u3002
fun onHandleLoadPackage(result: (LoadPackageParam) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
\u8BBE\u7F6E handleLoadPackage \u4E8B\u4EF6\u76D1\u542C\u3002
fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
+
\u53D8\u66F4\u8BB0\u5F55
v1.0.80
\u65B0\u589E
\u529F\u80FD\u63CF\u8FF0
`,30),p=[l];function t(c,r){return o(),a("div",null,p)}const i=s(n,[["render",t],["__file","YukiXposedEvent.html.vue"]]);export{i as default}; diff --git a/docs/assets/about.html.7638d3a2.js b/docs/assets/about.html.7638d3a2.js new file mode 100644 index 00000000..f8aac98e --- /dev/null +++ b/docs/assets/about.html.7638d3a2.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-7a15fe3b","path":"/en/about/about.html","title":"About this Document","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"License","slug":"license","link":"#license","children":[]}],"git":{"updatedTime":1664281711000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/about/about.md"}');export{e as data}; diff --git a/docs/assets/about.html.7d8b24a5.js b/docs/assets/about.html.7d8b24a5.js new file mode 100644 index 00000000..19ed7257 --- /dev/null +++ b/docs/assets/about.html.7d8b24a5.js @@ -0,0 +1,22 @@ +import{_ as o,r as t,o as l,c,b as s,d as e,e as a,a as p}from"./app.fb8271cf.js";const i={},r=s("h1",{id:"about-this-document",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#about-this-document","aria-hidden":"true"},"#"),a(" About this Document")],-1),d=a("This document is powered by "),h={href:"https://v2.vuepress.vuejs.org/en",target:"_blank",rel:"noopener noreferrer"},b=a("VuePress"),T=a("."),u=s("h2",{id:"license",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#license","aria-hidden":"true"},"#"),a(" License")],-1),I={href:"https://github.com/fankes/YukiHookAPI/blob/master/LICENSE",target:"_blank",rel:"noopener noreferrer"},E=a("The MIT License (MIT)"),O=p(`\u8BBE\u7F6E handleInitPackageResources \u4E8B\u4EF6\u76D1\u542C\u3002
MIT License
+
+Copyright (C) 2019-2022 HighCapable
+
+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.
+
Copyright \xA9 2019-2022 HighCapable
`,2);function N(R,_){const n=t("ExternalLinkIcon");return l(),c("div",null,[r,s("blockquote",null,[s("p",null,[d,s("a",h,[b,e(n)]),T])]),u,s("p",null,[s("a",I,[E,e(n)])]),O])}const A=o(i,[["render",N],["__file","about.html.vue"]]);export{A as default}; diff --git a/docs/assets/about.html.c0115524.js b/docs/assets/about.html.c0115524.js new file mode 100644 index 00000000..5af4a7e5 --- /dev/null +++ b/docs/assets/about.html.c0115524.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-41967128","path":"/zh-cn/about/about.html","title":"\u5173\u4E8E\u6B64\u6587\u6863","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"License","slug":"license","link":"#license","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/about/about.md"}');export{e as data}; diff --git a/docs/assets/about.html.f4c8582a.js b/docs/assets/about.html.f4c8582a.js new file mode 100644 index 00000000..786ce8b8 --- /dev/null +++ b/docs/assets/about.html.f4c8582a.js @@ -0,0 +1,22 @@ +import{_ as o,r as t,o as l,c,b as s,d as e,e as a,a as p}from"./app.fb8271cf.js";const i={},r=s("h1",{id:"\u5173\u4E8E\u6B64\u6587\u6863",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#\u5173\u4E8E\u6B64\u6587\u6863","aria-hidden":"true"},"#"),a(" \u5173\u4E8E\u6B64\u6587\u6863")],-1),d=a("\u6B64\u6587\u6863\u7531 "),h={href:"https://v2.vuepress.vuejs.org/zh",target:"_blank",rel:"noopener noreferrer"},b=a("VuePress"),T=a(" \u5F3A\u529B\u9A71\u52A8\u3002"),I=s("h2",{id:"license",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#license","aria-hidden":"true"},"#"),a(" License")],-1),E={href:"https://github.com/fankes/YukiHookAPI/blob/master/LICENSE",target:"_blank",rel:"noopener noreferrer"},u=a("The MIT License (MIT)"),O=p(`MIT License
+
+Copyright (C) 2019-2022 HighCapable
+
+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.
+
\u7248\u6743\u6240\u6709 \xA9 2019-2022 HighCapable
`,2);function N(R,_){const n=t("ExternalLinkIcon");return l(),c("div",null,[r,s("blockquote",null,[s("p",null,[d,s("a",h,[b,e(n)]),T])]),I,s("p",null,[s("a",E,[u,e(n)])]),O])}const f=o(i,[["render",N],["__file","about.html.vue"]]);export{f as default}; diff --git a/docs/assets/api-example.html.47c311e0.js b/docs/assets/api-example.html.47c311e0.js new file mode 100644 index 00000000..eb0bb6e4 --- /dev/null +++ b/docs/assets/api-example.html.47c311e0.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-9cfea7fc","path":"/en/config/api-example.html","title":"API Basic Configs","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Function Configs","slug":"function-configs","link":"#function-configs","children":[{"level":3,"title":"configs Method","slug":"configs-method","link":"#configs-method","children":[]}]},{"level":2,"title":"Hooker Configs","slug":"hooker-configs","link":"#hooker-configs","children":[{"level":3,"title":"Created by lambda","slug":"created-by-lambda","link":"#created-by-lambda","children":[]},{"level":3,"title":"Created by Custom Hooker","slug":"created-by-custom-hooker","link":"#created-by-custom-hooker","children":[]},{"level":3,"title":"Expansion Features","slug":"expansion-features","link":"#expansion-features","children":[]},{"level":3,"title":"Precautions","slug":"precautions","link":"#precautions","children":[]}]},{"level":2,"title":"Precautions when using as Hook API","slug":"precautions-when-using-as-hook-api","link":"#precautions-when-using-as-hook-api","children":[]}],"git":{"updatedTime":1664300349000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"en/config/api-example.md"}');export{e as data}; diff --git a/docs/assets/api-example.html.63409bed.js b/docs/assets/api-example.html.63409bed.js new file mode 100644 index 00000000..8b561025 --- /dev/null +++ b/docs/assets/api-example.html.63409bed.js @@ -0,0 +1,180 @@ +import{_ as s,o as n,c as a,a as l}from"./app.fb8271cf.js";const o={},e=l(`\u8FD9\u91CC\u4ECB\u7ECD\u4E86
YukiHookAPI
\u7684\u57FA\u672C\u914D\u7F6E\u65B9\u6CD5\u3002
\u65E0\u8BBA\u662F \u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528 \u8FD8\u662F \u4F5C\u4E3A Hook API \u4F7F\u7528\uFF0C\u4F60\u90FD\u53EF\u4EE5\u5728 API \u88C5\u8F7D\u4E4B\u524D\u6216\u88C5\u8F7D\u8FC7\u7A0B\u4E2D\u5BF9
YukiHookAPI
\u8FDB\u884C\u914D\u7F6E\u3002
fun configs(initiate: Configs.() -> Unit)
+
configs
\u65B9\u6CD5\u5BF9 Configs
\u7C7B\u5B9E\u73B0\u4E86\u4E00\u4E2A lambda
\u65B9\u6CD5\u4F53\uFF0C\u4F60\u53EF\u4EE5\u8F7B\u677E\u5730\u8C03\u7528\u5B83\u8FDB\u884C\u914D\u7F6E\u3002
\u5C0F\u63D0\u793A
\u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiHookAPI.configs \u65B9\u6CD5\u3002
\u4E00\u4E2A Xposed \u6A21\u5757\u6216 Hook API \u6700\u91CD\u8981\u7684\u5730\u65B9\u5C31\u662F Hooker \u7684\u521B\u5EFA\u4E0E\u4F7F\u7528\uFF0C
YukiHookAPI
\u63D0\u4F9B\u4E86\u4E24\u79CD\u4F7F\u7528\u65B9\u6CD5\u3002
\u8FD9\u79CD\u65B9\u6848\u662F\u6700\u7B80\u5355\u7684\uFF0C\u5982\u679C\u4F60\u7684\u6A21\u5757\u529F\u80FD\u4E0D\u591A\uFF0C\u4EE3\u7801\u6570\u91CF\u4E0D\u5927\uFF0C\u4E0D\u9700\u8981\u8FDB\u884C\u5206\u7C7B\u5904\u7406\uFF0C\u63A8\u8350\u4F7F\u7528\u8FD9\u79CD\u65B9\u5F0F\u8FDB\u884C\u521B\u5EFA\u3002
fun encase(initiate: PackageParam.() -> Unit)
+
encase
\u65B9\u6CD5\u662F Hook \u4E00\u5207\u751F\u547D\u7684\u5F00\u59CB\uFF0C\u5728\u4E00\u4E2A\u6A21\u5757\u6216\u4E00\u4E2A Hook \u8FC7\u7A0B\u4E2D\uFF0Cencase
\u65B9\u6CD5\u53EA\u80FD\u4F5C\u7528\u4E00\u6B21\uFF0C\u7528\u4E8E\u521B\u5EFA Hooker\u3002
PackageParam
\u4E3A\u5BBF\u4E3B(\u76EE\u6807 APP)\u7684\u91CD\u8981\u5B9E\u4F8B\u5BF9\u8C61\uFF0C\u901A\u8FC7 PackageParam
\u6765\u5B9E\u73B0\u5BF9\u5F53\u524D Hook \u4F5C\u7528\u5BF9\u8C61\u7684\u5168\u90E8 Hook \u64CD\u4F5C\u3002
\u5C0F\u63D0\u793A
\u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 PackageParam\u3002
encase
\u65B9\u6CD5\u53EF\u4EE5\u5728 onHook
\u65B9\u6CD5\u4E2D\u4F7F\u7528\u4E24\u79CD\u65B9\u6848\u521B\u5EFA\u3002
\u793A\u4F8B\u4EE3\u7801 1
YukiHookAPI.encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
\u793A\u4F8B\u4EE3\u7801 2
encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
\u5728 encase
\u65B9\u6CD5\u4E2D\u8FDB\u884C\u4F60\u7684 Hook \u64CD\u4F5C\u3002
\u8FD9\u79CD\u65B9\u6848\u66F4\u52A0\u9002\u7528\u4E8E\u5927\u578B\u9879\u76EE\uFF0C\u4F8B\u5982\u9700\u8981\u5BF9 Hooker \u8FDB\u884C\u5206\u7C7B\u6216\u5BF9 Hook \u7684\u4F5C\u7528\u5BF9\u8C61\u8FDB\u884C\u5206\u7C7B\u3002
fun encase(vararg hooker: YukiBaseHooker)
+
\u540C\u6837\u4E3A encase
\u65B9\u6CD5\uFF0C\u8FD9\u91CC\u7684\u65B9\u6CD5\u53EF\u53D8\u6570\u7EC4\u53C2\u6570 hooker
\u4E3A\u521B\u5EFA\u5165\u53E3\u63D0\u4F9B\u4E86\u4E00\u4E2A\u5BF9\u8C61\uFF0C\u4F60\u53EF\u4EE5\u5C06\u6240\u6709\u7EE7\u627F\u4E8E YukiBaseHooker
\u7684 Hooker \u4E00\u6B21\u6027\u8FDB\u884C\u88C5\u8F7D\u3002
YukiBaseHooker
\u7EE7\u627F\u4E8E PackageParam
\uFF0C\u4F60\u9700\u8981\u5C06\u4F60\u7684\u5B50 Hooker \u7EE7\u627F\u4E8E YukiBaseHooker
\u3002
\u5C0F\u63D0\u793A
\u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiBaseHooker\u3002
\u793A\u4F8B\u5982\u4E0B
object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
\u5B50 Hooker \u5EFA\u8BAE\u4F7F\u7528\u5355\u4F8B object
\u521B\u5EFA\uFF0C\u4F60\u4E5F\u53EF\u4EE5\u4F7F\u7528 class
\u4F46\u4E0D\u63A8\u8350\u3002
\u6CE8\u610F
\u4F60\u65E0\u9700\u518D\u5728\u7EE7\u627F\u4E8E YukiBaseHooker \u7684 onHook \u65B9\u6CD5\u4E2D\u91CD\u65B0\u8C03\u7528 encase\uFF0C\u8FD9\u662F\u9519\u8BEF\u7684\uFF0C\u4E14\u4E0D\u4F1A\u751F\u6548\uFF0C\u4F60\u5E94\u8BE5\u76F4\u63A5\u5F00\u59CB\u7F16\u5199\u4F60\u7684 Hook \u4EE3\u7801\u3002
\u793A\u4F8B\u5982\u4E0B
object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ loadApp(name = "com.example.demo1") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+ loadApp(name = "com.example.demo2") {
+ findClass(name = "$packageName.CustomClass").hook {
+ // Your code here.
+ }
+ }
+ }
+}
+
\u4F5C\u4E3A\u5B50 Hooker \u4F7F\u7528\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u5916\u90E8\u8C03\u7528 loadApp
\u65B9\u6CD5\uFF0C\u7136\u540E\u5728\u5185\u90E8\u76F4\u63A5\u5F00\u59CB Hook\u3002
\u793A\u4F8B\u5982\u4E0B
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase {
+ loadApp(name = "com.example.demo", ChildCustomHooker)
+ }
+}
+
+object ChildCustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
\u4F60\u53EF\u4EE5\u4F7F\u7528 loadHooker
\u65B9\u6CD5\u5728\u5B50 Hooker \u4E2D\u591A\u5C42\u88C5\u8F7D\u53E6\u4E00\u4E2A Hooker\uFF0C\u8BF7\u6309\u7167\u4F60\u7684\u559C\u597D\u8FDB\u884C\u5373\u53EF\u3002
\u793A\u4F8B\u5982\u4E0B
object FirstHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ loadHooker(SecondHooker)
+ loadHooker(ThirdHooker)
+ }
+}
+
\u642D\u5EFA\u5B8C\u5168\u90E8 Hooker \u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u5728\u4F60\u7684 HookEntryClass
\u5165\u53E3\u7C7B\u4E2D\u7684 onHook
\u65B9\u6CD5\u4E2D\u88C5\u8F7D\u4F60\u7684 Hooker \u4E86\u3002
\u793A\u4F8B\u5982\u4E0B
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() =
+ YukiHookAPI.encase(FirstHooker, SecondHooker, ThirdHooker ...)
+}
+
\u5F53\u7136\uFF0C\u6211\u4EEC\u540C\u6837\u53EF\u4EE5\u5BF9\u5176\u8FDB\u884C\u7B80\u5199\u3002
\u793A\u4F8B\u5982\u4E0B
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase(FirstHooker, SecondHooker, ThirdHooker ...)
+}
+
\u5982\u679C\u4F60\u5F53\u524D\u4F7F\u7528\u7684 Hook Framework \u652F\u6301\u5E76\u542F\u7528\u4E86\u8D44\u6E90\u94A9\u5B50(Resources Hook)\u529F\u80FD\uFF0C\u4F60\u73B0\u5728\u53EF\u4EE5\u76F4\u63A5\u5728 encase
\u4E2D\u521B\u5EFA Resources Hook\u3002
\u4F60\u5B8C\u5168\u4E0D\u9700\u8981\u4E0E\u4E4B\u524D\u5728\u4F7F\u7528 Xposed API \u90A3\u6837\u533A\u5206 initZygote
\u3001handleLoadPackage
\u3001handleInitPackageResources
\u65B9\u6CD5\u6765\u6267\u884C\u4E0D\u540C\u7684\u529F\u80FD\u3002
\u5728 YukiHookAPI
\u4E2D\uFF0C\u8FD9\u4E9B\u529F\u80FD\u662F\u65E0\u7F1D\u7684\u3002
\u793A\u4F8B\u5982\u4E0B
encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ // \u521B\u5EFA\u4E00\u4E2A Resources Hook (\u56FA\u5B9A\u7528\u6CD5)
+ resources().hook {
+ // Your code here.
+ }
+ }
+}
+
\u4F60\u8FD8\u53EF\u4EE5\u540C\u65F6\u4F7F\u7528 loadZygote
\u65B9\u6CD5\u6765\u88C5\u8F7D\u65B0\u7684\u8FDB\u7A0B\u88AB fork \u540E\u7684\u7B2C\u4E00\u4E2A\u4E8B\u4EF6 initZygote
\u3002
\u793A\u4F8B\u5982\u4E0B
encase {
+ loadZygote {
+ ActivityClass.hook {
+ // Your code here.
+ }
+ // \u5728 Zygote \u4E2D\u521B\u5EFA Resources Hook
+ resources().hook {
+ // Your code here.
+ }
+ }
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ // \u5728 APP \u4E2D\u521B\u5EFA Resources Hook
+ resources().hook {
+ // Your code here.
+ }
+ }
+}
+
\u76F4\u63A5\u88C5\u8F7D Hooker \u6216\u76F4\u63A5\u5F00\u59CB Hook \u662F\u9519\u8BEF\u7684\uFF0Cencase
\u4E8B\u4EF6\u5728\u88AB Hook Framework \u88C5\u8F7D\u540E\uFF0C\u4F1A\u7ECF\u5386\u4E09\u6B21\u56DE\u8C03\u3002
\u88C5\u8F7D initZygote
\u2192 encase
\u88C5\u8F7D handleLoadPackage
\u2192 encase
\u88C5\u8F7D handleInitPackageResources
\u2192 encase
\u5728\u8FD9\u4E2A\u8FC7\u7A0B\u4E2D\uFF0C\u4F60\u9700\u8981\u4F7F\u7528 loadApp
\u3001loadSystem
\u3001loadZygote
\u6765\u533A\u5206\u6BCF\u4E00\u6B21\u88C5\u8F7D\u4EE3\u7801\u7684\u8C03\u7528\u57DF\uFF0C\u5426\u5219\u4F60\u7684\u4EE3\u7801\u5C31\u4F1A\u88AB\u591A\u6B21\u6267\u884C\u9020\u6210\u9519\u8BEF\u3002
\u6CE8\u610F
\u65E0\u8BBA\u4F7F\u7528 encase \u521B\u5EFA lambda \u65B9\u6CD5\u4F53\u8FD8\u662F\u76F4\u63A5\u4F7F\u7528 Hooker \u5F62\u5F0F\uFF0C\u4F60\u90FD\u4E0D\u5E94\u8BE5\u76F4\u63A5\u5728\u9996\u4E2A onHook \u4E8B\u4EF6\u4E2D\u76F4\u63A5\u88C5\u8F7D Hooker \u6216\u76F4\u63A5\u5F00\u59CB Hook\u3002
\u4E0B\u9762\u662F\u4E24\u4E2A\u9519\u8BEF\u793A\u4F8B\u3002
\u793A\u4F8B\u4EE3\u7801 1
encase {
+ // \u2757\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u4E0D\u80FD\u76F4\u63A5\u5F00\u59CB Hook
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ // \u2757\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u4E0D\u80FD\u76F4\u63A5\u5F00\u59CB Hook
+ resources().hook {
+ // ...
+ }
+}
+
\u793A\u4F8B\u4EE3\u7801 2
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() {
+ // <\u60C5\u666F1>
+ encase {
+ loadHooker(CustomHooker)
+ }
+ // <\u60C5\u666F2>
+ encase(CustomHooker)
+ }
+}
+
+object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // \u2757\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u7531\u4E8E\u5916\u5C42\u6CA1\u6709\u4EFB\u4F55\u5224\u65AD\u5BF9\u8C61\uFF0C\u4E0D\u80FD\u76F4\u63A5\u5F00\u59CB Hook
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ }
+}
+
\u4E0B\u9762\u662F\u4E0A\u8FF0\u9519\u8BEF\u793A\u4F8B\u7684\u6B63\u786E\u793A\u4F8B\u3002
\u793A\u4F8B\u4EE3\u7801 1
encase {
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5728 Zygote \u4E2D\u88C5\u8F7D
+ loadZygote(CustomHooker)
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5728 Zygote \u4E2D\u88C5\u8F7D
+ loadZygote {
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5728 Zygote \u5185 Hook
+ resources().hook {
+ // ...
+ }
+ }
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u4F7F\u7528 APP \u4F5C\u7528\u57DF\u88C5\u8F7D
+ loadApp(/** name \u53C2\u6570\u53EF\u9009 */, hooker = CustomHooker)
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5224\u65AD APP \u4F5C\u7528\u57DF\u540E\u518D\u88C5\u8F7D Hooker
+ loadApp(/** name \u53C2\u6570\u53EF\u9009 */) {
+ loadHooker(CustomHooker)
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5728 APP \u4F5C\u7528\u57DF\u5185 Hook
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5728 APP \u4F5C\u7528\u57DF\u5185 Hook
+ resources().hook {
+ // ...
+ }
+ }
+}
+
\u793A\u4F8B\u4EE3\u7801 2
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() {
+ encase(CustomHooker)
+ }
+}
+
+object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u7531\u4E8E\u5916\u5C42\u6CA1\u6709\u4EFB\u4F55\u5224\u65AD\u5BF9\u8C61\uFF0C\u9700\u8981\u5224\u65AD APP \u4F5C\u7528\u57DF\u540E\u518D\u8FDB\u884C Hook
+ loadApp(/** name \u53C2\u6570\u53EF\u9009 */) {
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ }
+ }
+}
+
\u82E5\u4F60\u4F5C\u4E3A Hook API \u4F7F\u7528\uFF0C\u90A3\u4E48\u4F60\u53EA\u9700\u8981\u5728\u5165\u53E3\u5904\u5BF9 encase
\u65B9\u6CD5\u8FDB\u884C\u533A\u5206\u3002
\u6CE8\u610F
encase \u65B9\u6CD5\u5BF9\u4F5C\u4E3A Hook API \u4F7F\u7528\u63D0\u4F9B\u4E86\u4E24\u4E2A\u5B8C\u5168\u4E00\u6837\u7684\u65B9\u6CD5\uFF0C\u4F46\u662F\u6BD4\u524D\u4E24\u8005\u4EC5\u591A\u51FA\u4E00\u4E2A\u53C2\u6570 baseContext\u3002
\u65B9\u6CD5 1
fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
+
\u65B9\u6CD5 2
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
+
\u6B64\u5904\u7684 baseContext
\u53EA\u9700\u586B\u5165\u4F60\u5728 attachBaseContext
\u5904\u5F97\u5230\u7684 Context
\u5373\u53EF\uFF0C\u5176\u5B83\u7528\u6CD5\u4E0E\u4E0A\u8FF0\u5185\u5BB9\u5B8C\u5168\u4E00\u81F4\u3002
\u7279\u522B\u6CE8\u610F
\u5207\u52FF\u4EE5 Xposed \u65B9\u5F0F\u4F7F\u7528 encase \u65B9\u6CD5\u800C\u6F0F\u6389 baseContext \u53C2\u6570\uFF0C\u5426\u5219\u4F60\u7684 Hook \u5C06\u5B8C\u5168\u4E0D\u5DE5\u4F5C\u3002
Resources Hook \u529F\u80FD\u4E0D\u652F\u6301\u4F5C\u4E3A Hook API \u4F7F\u7528\u3002
The basic configuration method of
YukiHookAPI
is introduced here.
Either Use as Xposed Module Configs or Use as Hook API Configs, you can specify
YukiHookAPI
for configuration.
fun configs(initiate: Configs.() -> Unit)
+
The configs
method implements a lambda
method body on the Configs
class, which you can easily call for configuration.
Tips
For more functions, please refer to the YukiHookAPI.configs method.
The most important part of an Xposed Module or Hook API is the creation and use of Hooker.
YukiHookAPI
provides two ways to use it.
This solution is the simplest. If your module has few functions and a small amount of code, and does not need to be classified, it is recommended to create it in this way.
fun encase(initiate: PackageParam.() -> Unit)
+
The encase
method is the beginning of all Hook life. In a Module App or a Hook process, the encase
method can only be used once to create a Hooker.
PackageParam
is an important instance object of the Host App, and PackageParam
is used to implement all Hook operations on the current Hook object.
Tips
For more functions, please refer to PackageParam.
The encase
method can be created in the onHook
method using two schemes.
Sample Code 1
YukiHookAPI.encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
Sample Code 2
encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
Do your Hook operations in the encase
method.
This scheme is more suitable for large-scale projects, such as the need to classify Hooker or classify the role of Hook.
fun encase(vararg hooker: YukiBaseHooker)
+
Also for the encase
method, the variable array parameter hooker
of the method here provides an object for creating an entry, you can load all Hookers extends YukiBaseHooker
at one time.
YukiBaseHooker
extends PackageParam
, you need to extends your child Hooker from YukiBaseHooker
.
Tips
For more functions, please refer to YukiBaseHooker.
The following example
object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
Child Hooker recommended singleton object
creation, you can also use class
but not recommended.
Notice
You don't need to re-call encase in the onHook method extends YukiBaseHooker, this is wrong and will not take effect, you should start writing your Hook code directly .
The following example
object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ loadApp(name = "com.example.demo1") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+ loadApp(name = "com.example.demo2") {
+ findClass(name = "$packageName.CustomClass").hook {
+ // Your code here.
+ }
+ }
+ }
+}
+
As a child hooker, you can also call the loadApp
method externally, and then directly start the Hook internally.
The following example
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase {
+ loadApp(name = "com.example.demo", ChildCustomHooker)
+ }
+}
+
+object ChildCustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
You can use the loadHooker
method to load another Hooker in multiple layers in the child Hooker, please do as you like.
The following example
object FirstHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ loadHooker(SecondHooker)
+ loadHooker(ThirdHooker)
+ }
+}
+
Once all Hookers are set up, you can load your Hooker in the onHook
method of your HookEntryClass
.
The following example
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() =
+ YukiHookAPI.encase(FirstHooker, SecondHooker, ThirdHooker ...)
+}
+
Of course, we can also abbreviate it.
The following example
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase(FirstHooker, SecondHooker, ThirdHooker ...)
+}
+
If your current Hook Framework supports and enables the Resources Hook feature, you can now create Resources Hooks directly in encase
.
You don't need to separate the initZygote
, handleLoadPackage
, handleInitPackageResources
methods to perform different functions as before using the Xposed API.
In YukiHookAPI
, these functions are seamless.
The following example
encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ // Create a Resources Hook (fixed usage)
+ resources().hook {
+ // Your code here.
+ }
+ }
+}
+
You can also use the loadZygote
method to load the first event initZygote
after a new process has been forked.
The following example
encase {
+ loadZygote {
+ ActivityClass.hook {
+ // Your code here.
+ }
+ // Create a Resources Hook in Zygote
+ resources().hook {
+ // Your code here.
+ }
+ }
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ // Create a Resources Hook in the app
+ resources().hook {
+ // Your code here.
+ }
+ }
+}
+
It is wrong to load Hooker directly or start Hook directly, encase
event will go through three callbacks after being loaded by Hook Framework.
load initZygote
\u2192 encase
load handleLoadPackage
\u2192 encase
load handleInitPackageResources
\u2192 encase
In this process, you need to use loadApp
, loadSystem
, loadZygote
to distinguish the calling domain of each loading code, otherwise your code will be executed multiple times and cause errors.
Notice
Whether you use encase to create the lambda method body or use the Hooker form directly, you should not directly load the Hooker or start the Hook directly in the first onHook event.
Below are two error examples.
Sample Code 1
encase {
+ // \u2757 Wrong usage, can't start Hook directly
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ // \u2757 Wrong usage, can't start Hook directly
+ resources().hook {
+ // ...
+ }
+}
+
Sample Code 2
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() {
+ // <Scenario 1>
+ encase {
+ loadHooker(CustomHooker)
+ }
+ // <Scenario 2>
+ encase(CustomHooker)
+ }
+}
+
+object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // \u2757 Wrong method of use
+ // Because there is no judgment object in the outer layer, you cannot start Hook directly
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ }
+}
+
Below is a correct example of the wrong example above.
Sample Code 1
encase {
+ // \u2705 Correct usage, load in Zygote
+ loadZygote(CustomHooker)
+ // \u2705 Correct usage, load in Zygote
+ loadZygote {
+ // \u2705 Correct usage, Hook in Zygote
+ resources().hook {
+ // ...
+ }
+ }
+ // \u2705 The correct way to use it, use the app scope to load
+ loadApp(/** name parameter optional */, hooker = CustomHooker)
+ // \u2705 The correct way to use it, load the Hooker after judging the scope of the app
+ loadApp(/** name parameter optional */) {
+ loadHooker(CustomHooker)
+ // \u2705 Correct usage, Hook in app scope
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ // \u2705 Correct usage, Hook in app scope
+ resources().hook {
+ // ...
+ }
+ }
+}
+
Sample Code 2
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() {
+ encase(CustomHooker)
+ }
+}
+
+object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // \u2705 The correct method of use, since there is no judgment object in the outer layer
+ // it is necessary to judge the scope of the app before performing Hook
+ loadApp(/** name parameter optional */) {
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ }
+ }
+}
+
If you are using it as a Hook API, then you only need to differentiate the encase
method at the entry point.
Notice
The encase method provides two identical methods for use as a Hook API, but with only one more parameter baseContext than the previous two.
Method 1
fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
+
Method 2
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
+
The baseContext
here only needs to fill in the Context
you got at attachBaseContext
, and other usages are exactly the same as the above.
Pay Attention
Never use the encase method in an Xposed way without omitting the baseContext parameter, this will lead to your Hook not work at all.
The Resources Hook feature is not supported as Hook API.
Exceptions are the main problems often encountered in the development process. Here are some common exceptions that may be encountered during the use of
YukiHookAPI
and how to deal with them.
The exception description here will only synchronize the latest API version, and the exception of the older API version will not be described again, please always keep the API version up-to-date.
These exceptions will not cause the app to stop running (FC), but will print
E
level logs on the console, and may also stop continuing to execute related functions.
loggerE
Could not found XposedBridge in current space! Aborted
Abnormal
Your Hook Framework is not working or XposedBridge
has not been successfully loaded.
Solution
Please make sure you have loaded the encase
method of YukiHookAPI
in the correct place. For details, please refer to Use as Xposed Module Configs and Use as Hook API Configs.
loggerE
You cannot load a hooker in "onInit" or "onXposedEvent" method! Aborted
Abnormal
You try to load the encase
method in the onInit
or onXposedEvent
method of the Hook entry class that implements IYukiHookXposedInit
.
The following example
class HookEntry : IYukiHookXposedInit {
+
+ override fun onInit() {
+ // \u2757 Wrong usage
+ YukiHookAPI.encase {
+ // Your code here.
+ }
+ }
+
+ override fun onXposedEvent() {
+ // \u2757 Wrong usage
+ YukiHookAPI.encase {
+ // Your code here.
+ }
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
Solution
Please load the encase
method in the onHook
method.
The following example
class HookEntry : IYukiHookXposedInit {
+
+ override fun onInit() {
+ // Only the configs method can be loaded here
+ YukiHookAPI.configs {
+ // Your code here.
+ }
+ }
+
+ override fun onHook() {
+ // \u2705 Correct usage
+ YukiHookAPI.encase {
+ // Your code here.
+ }
+ }
+}
+
loggerE
Hooking Process exception occurred
Abnormal
YukiHookAPI
throws an exception during its own initialization hook.
Solution
Usually, this kind of error does not happen easily. If this error occurs, you can directly submit the log for feedback.
loggerE
YukiHookAPI try to load HookEntryClass failed
Abnormal
YukiHookAPI
encountered an unhandled exception or the entry class could not be found when trying to load the hook entry class onInit
or onHook
method.
Solution
Usually, this kind of error does not occur easily.
If this error occurs, please check the log printed on the console to locate the problem.
After confirming that the problem is not caused by your own code, you can submit the log for feedback.
loggerE
YukiHookAPI bind initZygote failed
Abnormal
YukiHookAPI
encountered an unhandled exception when trying to load the Xposed native interface initZygote
method.
Solution
Usually, this kind of error does not occur easily.
If this error occurs, please check the log printed on the console to locate the problem.
After confirming that the problem is not caused by your own code, you can submit the log for feedback.
loggerE
Failed to execute method "NAME", maybe your Hook Framework not support Resources Hook
Abnormal
YukiHookAPI
An error occurred while trying to do a Resources Hook.
Solution
Please double check the error log for details.
If a Resources$NotFoundException
occurs, you may be looking for an incorrect Resources Id.
If ClassNotFound
or NoClassDefFoundError
occurs, it may be that Hook Framework does not support Resources Hook.
loggerE
HookClass [NAME] not found
Abnormal
The Class
currently being hooked was not found.
Solution
Please check if the target Class
exists, to ignore this error use the ignoredHookClassNotFoundFailure
method.
loggerE
Hook Member [NAME] failed
Abnormal
An error occurred while hooking the target method, constructor.
Solution
This problem is usually caused by Hook Framework.
Please check the corresponding log content.
If the problem persists, please bring detailed logs for feedback.
loggerE
Hooked Member with a finding error by CLASS
Abnormal
After the Hook is executed, the member
of the Hook is null
and the target Hook method and constructed class have been set.
Solution
Please check the previous error log before this error occurs, maybe there is an error that the method and constructor cannot be found when searching for methods and constructors.
loggerE
Hooked Member cannot be non-null by CLASS
Abnormal
After the Hook is executed, the member
of the Hook is null
and the target Hook method and constructed class are not set.
The following example
injectMember {
+ // There are no search conditions for methods and constructors that require hooks
+ afterHook {
+ // ...
+ }
+}
+
Solution
Please confirm that you have correctly set the method to be hooked and the way to find the constructor before hooking.
The following example
injectMember {
+ // \u2705 Examples of correct usage
+ method {
+ // Your code here.
+ }
+ afterHook {
+ // ...
+ }
+}
+
loggerE
Hooked method return type match failed, required [TYPE] but got [TYPE]
Abnormal
HookParam.result
is set in the Hook callback method body or replaceHook
is used but the return value type of the hooked method does not match the original return value type.
The following example
Suppose this is the method being Hooked.
private boolean test()
+
Below is an error case.
injectMember {
+ method {
+ name = "test"
+ emptyParam()
+ }
+ // <Scenario 1> Set the wrong type, the original type is Boolean
+ beforeHook {
+ result = 0
+ }
+ // <Scenario 2> Return the wrong type, the original type is Boolean
+ replaceAny {
+ 0
+ }
+ // <Scenario 3> Use the wrong type directly, the original type is Boolean
+ replaceTo(any = 0)
+}
+
Notice
If the above scenario occurs in beforeHook or afterHook, it will cause the Host App to throw an exception from XposedBridge (which will expose the fact of being Hooked).
Solution
Please confirm the correct return value type of the current Hook method, modify it and try again.
loggerE
Hook initialization failed because got an Exception
Abnormal
An arbitrary exception occurred while preparing the Hook.
Solution
This is a reminder that an exception occurred during the Hook preparation stage, please carefully check what the specific exception is to re-determine the problem.
loggerE
Try to hook NAME[NAME] got an Exception
Abnormal
An arbitrary exception occurred at the start of the Hook.
Solution
This is a reminder that an exception occurred at the beginning of the Hook, please check carefully what the specific exception is to re-determine the problem.
loggerE
Method/Constructor/Field match type "TYPE" not allowed
Abnormal
A disallowed parameter type was set when looking up methods, constructors, and variables.
The following example
// Find a method
+method {
+ // \u2757 Invalid type example is set
+ param(false, 1, 0)
+ // \u2757 Invalid type example is set
+ returnType = false
+}
+
+// Find a variable
+field {
+ // \u2757 Invalid type example is set
+ type = false
+}
+
Solution
In the search, param
, returnType
, type
only accept Class
, String
, VariousClass
types, and parameter instances cannot be passed in.
The following example
// Find a method
+method {
+ // \u2705 Examples of correct usage
+ param(BooleanType, IntType, IntType)
+ // \u2705 Examples of correct usage
+ returnType = BooleanType
+ // \u2705 The following scheme is also correct
+ returnType = "java.lang.Boolean"
+}
+
+// Find a variable
+field {
+ // \u2705 Examples of correct usage
+ type = BooleanType
+}
+
loggerE
NoSuchMethod/NoSuchConstructor/NoSuchField happend in [NAME]
Abnormal
The target method, constructor, and variable were not found when looking for methods, constructors, and variables.
Solution
Please confirm that your search criteria can correctly match the specified methods, constructors and variables in the target Class
.
loggerE
Trying COUNT times and all failure by RemedyPlan
Abnormal
When using RemedyPlan
to search for methods, constructors, and variables, the methods, constructors, and variables are still not found.
Solution
Please confirm the RemedyPlan
parameter you set and the Class
that exists in the Host App, and try again.
loggerE
You must set a condition when finding a Method/Constructor/Field
Abnormal
No conditions are set when looking for methods, constructors, and variables.
The following example
method {
+ // No conditions are set here
+}
+
Solution
Please complete your search criteria and try again.
loggerE
Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiHookAPI#ReflectionTool
Abnormal
The Class
object to be searched for was not found via ClassLoader.searchClass
or PackageParam.searchClass
.
The following example
customClassLoader?.searchClass {
+ from(...)
+ // ...
+}.get()
+
Solution
This is a security exception, please check the conditions you set, use the relevant tools to view the Class
and bytecode object characteristics in the Dex and try again.
loggerE
Can't find this Method/Constructor/Field in [CLASS]: CONTENT Generated by YukiHookAPI#ReflectionTool
Abnormal
The methods, constructors, and variables that need to be found cannot be found by specifying conditions.
The following example
TargetClass.method {
+ name = "test"
+ param(BooleanType)
+}
+
Solution
This is a security exception, please check the conditions you set, use the relevant tools to view the bytecode object characteristics in the Class
, and try again.
loggerE
The number of VagueType must be at least less than the count of paramTypes
Abnormal
Incorrect use of VagueType
in Method
, Constructor
lookup conditions.
The following example
TargetClass.method {
+ name = "test"
+ // <Scenario 1>
+ param(VagueType)
+ // <Scenario 2>
+ param(VagueType, VagueType ...)
+}
+
Solution
VagueType
cannot be completely filled in method and constructor parameters. If there is such a requirement, please use paramCount
.
loggerE
Field match type class is not found
Abnormal
An instance of Class
for type
was not found in the lookup criteria set when looking up the variable.
The following example
field {
+ name = "test"
+ // Assume that the Class of the type set here does not exist
+ type = "com.example.TestClass"
+}
+
Solution
Please check if Class
of type
in the lookup condition exists and try again.
loggerE
Method match returnType class is not found
Abnormal
An instance of Class
of returnType
was not found in the search criteria set when looking up the method.
The following example
method {
+ name = "test"
+ // Assume that the Class of returnType set here does not exist
+ returnType = "com.example.TestClass"
+}
+
Solution
Please check if Class
of returnType
in the lookup condition exists and try again.
loggerE
Method/Constructor match paramType[INDEX] class is not found
Abnormal
The Class
instance subscripted by the index
number of param
was not found in the search conditions set when searching for methods and constructors.
method {
+ name = "test"
+ // Assume that the Class with subscript "No.1" set here does not exist
+ param(StringType, "com.example.TestClass", BooleanType)
+}
+
Solution
Please check if the Class
subscripted by the index
number of param
in the lookup condition exists and try again.
loggerE
Resources Hook condition name/type cannot be empty [TAG]
Abnormal
No conditions were set when looking for Resources.
The following example
// Case 1
+conditions {
+ // No conditions are set here
+}
+// Case 2
+conditions {
+ name = "test"
+ // The type condition is missing here
+}
+
Solution
The Hook of Resources is not a Hook similar to a method.
It must have a complete name and type description in order to find it successfully.
Please complete the search conditions and try again.
loggerE
Resources Hook type is invalid [TAG]
Abnormal
An exception of the wrong type occurred while Hooking Resources.
Solution
YukiHookAPI
will try to load Resources Hook in initZygote
and handleInitPackageResources
.
If all loading fails, this exception may occur.
The current Hook Framework needs to support and enable the Resources Hook function, please check and try again.
loggerE
Resources Hook got an Exception [TAG]
Abnormal
An arbitrary exception occurred while Hooking Resources.
Solution
This is a summary of exceptions, please check down the log for the specific exception, such as the problem that the Resources Id cannot be found.
loggerE
Received action "ACTION" failed
Abnormal
Callback broadcast event exception when using YukiHookDataChannel
.
Solution
Under normal circumstances, this error basically does not occur.
Once an error occurs, after eliminating the problem of your own code, please bring detailed logs for feedback.
loggerE
Failed to sendBroadcast like "KEY", because got null context in "PACKAGENAME"
Abnormal
Sending a broadcast when using YukiHookDataChannel
got an empty context instance.
Solution
Under normal circumstances, this error basically does not occur.
In the latest version, the problems that may occur when the host is used have been fixed.
If the latest version still has errors, after eliminating the problem of your own code, please bring detailed logs for feedback.
loggerE
Failed to inject module resources into [RESOURCES]
Abnormal
An exception occurred when injecting Module App's Resources using injectModuleAppResources
in a (Xposed) Host environment.
Solution
Under normal circumstances, this error basically does not occur. After eliminating the problem of your own code, please bring detailed logs for feedback.
loggerE
Activity Proxy initialization failed because got an Exception
Abnormal
An exception occurred when injecting a Module App's Activity
using registerModuleAppActivities
in a (Xposed) Host environment.
Solution
Please check the next error log after this error occurs.
Maybe some problems may have occurred in the configuration parameters.
If you cannot find the description of the relevant error log, after eliminating the problem of your own code, please bring the detailed log for feedback.
loggerE
Activity Proxy got an Exception in msg.what [WHAT]
Abnormal
An exception occurred when injecting a Module App's Activity
using registerModuleAppActivities
in a (Xposed) Host environment.
Solution
Under normal circumstances, this error basically does not occur, but according to the difference of the system version, no detailed testing has been done.
After eliminating the problem of your own code, please bring detailed logs for feedback.
loggerE
This proxy [TYPE] type is not allowed
Abnormal
Invalid parameters were filled in when injecting Module App's Activity
using registerModuleAppActivities
in a (Xposed) Host environment.
The following example
// \u2757 The content filled in here is just an example
+// And the proxy is filled with invalid parameters that cannot be understood
+registerModuleAppActivities(proxy = false)
+
Solution
The proxy
parameter in the method only accepts String
, CharSequence
, Class
types, please refer to the related usage method to fill in the method parameters correctly.
loggerE
Cound not got launch intent for package "NAME"
Abnormal
When injecting Module App's Activity
using registerModuleAppActivities
in a (Xposed) Host environment, the Host App's launching Activity
cannot be found.
The following example
// Register directly with default parameters
+registerModuleAppActivities()
+
Solution
The default parameter (no parameter) can only be used for the app that can be launched.
If the app does not declare the startup entry Activity
, you need to manually specify the proxy
parameter of the method.
loggerE
Could not found "NAME" or Class is not a type of Activity
Abnormal
When injecting Module App's Activity
with registerModuleAppActivities
in a (Xposed) Host environment, the Activity
filled with the parameter proxy
cannot be found.
The following example
registerModuleAppActivities(proxy = "com.demo.test.TestActivity")
+
Solution
Please make sure that the Activity
name you fill in really and effectively exists in the Host App, and the target Class
extends Activity
.
These exceptions will directly cause the app to stop running (FC), at the same time print
E
level logs on the console, and also cause the Hook process to "die".
RuntimeException
!!!DO NOT ALLOWED!!! You cannot hook or reflection to call the internal class of the YukiHookAPI itself, The called class is [CLASS]
Abnormal
You have invoked the Class
object of the API itself using YukiHookAPI
related reflection or Hook function.
The following example
// <Scenario 1>
+YukiHookAPI.current()
+// <Scenario 2>
+PackageParam::class.java.hook {
+ // ...
+}
+// <Scenario 3>
+MethodFinder::class.java.method {
+ name = "name"
+ param(StringType)
+}.get().call("name")
+// ...
+
Solution
Please check the code section for errors, such as the case below.
The following example
YourClass.method {
+ // ...
+ // \u2757 The method execution is not called
+ // The actual method is called here is the MethodFinder.Result object
+}.get(instance).current()
+YourClass.method {
+ // ...
+ // \u2705 The correct way to use it, assuming this method has no parameters
+}.get(instance).call().current()
+
Inlining, reflection, Hook YukiHookAPI
's own Class
and internal functions are not allowed to prevent errors.
UnsupportedOperationException
!!!DANGEROUS!!! Hook [CLASS] Class is a dangerous behavior! [CONTENT] [SOLVE]
Abnormal
You tried to hook a Class
object in the list of dangerous behaviors, such as Class
, ClassLoader
, Method
.
The following example
// <Scenario 1>
+JavaClassLoader.hook {
+ // ...
+}
+// <Scenario 2>
+JavaClass.hook {
+ // ...
+}
+// <Scenario 3>
+JavaMethod.hook {
+ // ...
+}
+// ...
+
Solution
These functions are internal to the system, they should not be hooked, may not be supported on some Hook Frameworks, and may cause other errors, please try to replace the hook point.
Tips
If you still want to use this feature, please refer to YukiMemberHookCreator.useDangerousOperation.
But It is strongly recommended not to do this, please do not report any problems, all the consequences will be borne by yourself.
NoClassDefFoundError
Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiHookAPI#ReflectionTool
Abnormal
The Class
object you were looking for was not found via String.toClass(...)
or classOf<...>()
.
The following example
"com.demo.Test".toClass()
+
Solution
Please check if the Class
matched by the current string or entity exists in the current ClassLoader
and try again.
IllegalStateException
ClassLoader [CLASSLOADER] is not a DexClassLoader
Abnormal
Use ClassLoader.searchClass
or PackageParam.searchClass
to find Class
but currently ClassLoader
does not extends BaseDexClassLoader
.
Solution
This situation basically does not exist, unless the current app references a Non-ART platform executable (which not realistic) or the current ClassLoader
is null.
IllegalStateException
Failed to got SystemContext
Abnormal
systemContext
was called in the Host App but the instance object was not successfully obtained.
The following example
encase {
+ // This variable is called
+ systemContext...
+}
+
Solution
This situation should not exist, since systemContext
is obtained from ActivityThread
through reflection, unless the system process fails, the obtained object will not be null.
IllegalStateException
App is dead, You cannot call to appContext
Abnormal
The first case
The appContext
of the ModuleApplication
is called within the Hook App.
The following example
encase {
+ // This variable is called
+ ModuleApplication.appContext...
+}
+
The second case
appContext
was called when using ModuleApplication
but the app may have been destroyed or not started correctly.
The following example
// This variable is called but the app may have been destroyed or not started correctly
+ModuleApplication.appContext...
+
Solution
The first case
You can only use the appContext
of ModuleApplication
in the Module App, please use the appContext
in the PackageParam
in the Host App, please make sure you use it correctly.
The second case
This situation basically does not exist, because appContext
is assigned in onCreate
, unless the onCreate
method of the parent class is called by reflection before multi-process concurrent startup or app is not started and completed.
IllegalStateException
YukiHookModulePrefs not allowed in Custom Hook API
Abnormal
YukiHookModulePrefs
is used in Hook's own app (not Xposed Module).
The following example
class MyApplication : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ YukiHookAPI.encase(base) {
+ // \u2757 Can't use prefs in this case
+ prefs.getBoolean("test_data")
+ }
+ super.attachBaseContext(base)
+ }
+}
+
Solution
You can only use YukiHookModulePrefs
when Use as Xposed Module Configs, please use the native Sp
storage in the Hook's own app.
IllegalStateException
Cannot load the XSharedPreferences, maybe is your Hook Framework not support it
Abnormal
Using YukiHookModulePrefs
in (Xposed) Host environment but unable to get XSharedPreferences
object.
The following example
encase {
+ // This variable is called
+ prefs...
+}
+
Solution
Under normal circumstances, this problem does not occur.
If you continue to fail to obtain the XSharedPreferences
object, it may be that the Hook Framework you are using does not support this function or has an error.
IllegalStateException
YukiHookDataChannel not allowed in Custom Hook API
Abnormal
YukiHookDataChannel
is used in Hook's own app (not Xposed Module).
The following example
class MyApplication : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ YukiHookAPI.encase(base) {
+ // \u2757 dataChannel cannot be used in this case
+ dataChannel.wait(key = "test_data") {
+ // ...
+ }
+ }
+ super.attachBaseContext(base)
+ }
+}
+
Solution
You can only use YukiHookDataChannel
when Use as Xposed Module Configs.
IllegalStateException
YukiHookDataChannel only support used on an Activity, but this current context is "CLASSNAME"
Abnormal
YukiHookDataChannel
is used in a non-Activity
context of a Module App.
Solution
You can only use YukiHookDataChannel
in Activity
or Fragment
.
IllegalStateException
Xposed modulePackageName load failed, please reset and rebuild it
Abnormal
When using YukiHookModulePrefs
or YukiHookDataChannel
in the Hook process, the modulePackageName
at load time cannot be read, resulting in the package name of the own Module App cannot be determined.
Solution
Please read the help document here carefully, and configure the Module App's Hook entry class package name correctly.
IllegalStateException
YukiHookModulePrefs missing Context instance
Abnormal
YukiHookModulePrefs
is used in the Module App to store data but no Context
instance is passed in.
The following example
class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // \u2757 Wrong usage
+ // Constructor has been set to private in API 1.0.88 and later
+ YukiHookModulePrefs().getBoolean("test_data")
+ }
+}
+
Solution
It is recommended to use the modulePrefs
method to load YukiHookModulePrefs
in Activity
.
The following example
class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // \u2705 Correct usage
+ modulePrefs.getBoolean("test_data")
+ }
+}
+
IllegalStateException
Key-Value type TYPE is not allowed
Abnormal
An unsupported storage type was passed in when using the get
or put
methods of YukiHookModulePrefs
or the wait
or put
methods of YukiHookDataChannel
.
Solution
The supported types of YukiHookModulePrefs
are only String
, Set<String>
, Int
, Float
, Long
, Boolean
, please pass in the supported types.
The supported types of YukiHookDataChannel
are the types restricted by Intent.putExtra
, please pass in the supported types.
IllegalStateException
YukiHookDataChannel cannot be used in zygote
Abnormal
YukiHookDataChannel
is used in loadZygote
.
The following example
loadZygote {
+ // This variable is called
+ dataChannel...
+}
+
Solution
YukiHookDataChannel
can only be used in loadSystem
, loadApp
.
IllegalStateException
Custom Hooking Members is empty
Abnormal
members()
is called in MemberHookCreator
but the Member
instance that requires the Hook is not set.
The following example
injectMember {
+ // Method parameters in parentheses are left blank
+ members()
+ afterHook {
+ // ...
+ }
+}
+
Solution
To use members()
to set a custom Hook method, you must ensure that the Member
array object in its method parameter cannot be empty.
IllegalStateException
HookParam Method args index must be >= 0
Abnormal
args().last()
is called in HookParam
but the target param
is empty or the index
in args
is set to a value less than 0.
The following example
injectMember {
+ // ...
+ afterHook {
+ // Assume param is empty
+ args().last()...
+ // Set an index less than 0
+ args(index = -5)...
+ }
+}
+
Solution
Please make sure that the number of method parameters of the target method and constructor of your Hook is not empty, and the subscript of args
cannot be set to a value less than 0.
IllegalStateException
HookParam instance got null! Is this a static member?
Abnormal
An object that calls an instance
variable or instance
method in a HookParam
but cannot get the current instance.
The following example
injectMember {
+ // ...
+ afterHook {
+ // This variable is called
+ instance...
+ // This method is called
+ instance<Any>()...
+ }
+}
+
Solution
Please confirm whether the method of your Hook is a static type.
The static type method has no instance and cannot use this function.
If it is not a static method, please check whether the instance has been destroyed.
IllegalStateException
Current hooked Member args is null
Abnormal
The args
variable is called in HookParam
, but the parameter array of the current instance method and constructor cannot be obtained.
The following example
injectMember {
+ // ...
+ afterHook {
+ // This variable is called
+ args...
+ }
+}
+
Solution
This kind of problem generally does not occur.
If this problem does occur, please bring detailed logs for feedback.
IllegalStateException
Current hooked Member is null
Abnormal
Call the member
variable in HookParam
but cannot get the method and constructor instance of the current instance.
The following example
injectMember {
+ // ...
+ afterHook {
+ // This variable is called
+ member...
+ }
+}
+
Solution
This kind of problem generally does not occur.
If this problem does occur, please bring detailed logs for feedback.
IllegalStateException
Current hooked Member is not a Method
Abnormal
Calling the method
variable in HookParam
but not getting the method instance of the current instance.
The following example
injectMember {
+ // ...
+ afterHook {
+ // This variable is called
+ method...
+ }
+}
+
Solution
Please confirm whether the method of your Hook is a constructor or a common method and use the method of the corresponding type to obtain the specified instance.
If you do not know the type of the bytecode, you can directly use member
to obtain it.
IllegalStateException
Current hooked Member is not a Constructor
Abnormal
A method instance for calling a constructor
variable in a HookParam
but not getting the current instance.
The following example
injectMember {
+ // ...
+ afterHook {
+ // This variable is called
+ constructor...
+ }
+}
+
Solution
Please confirm whether the method of your Hook is a common method or a constructor method and use the method of the corresponding type to obtain the specified instance.
If you do not know the type of the bytecode, you can directly use member
to obtain it.
IllegalStateException
HookParam instance cannot cast to TYPE
Abnormal
Invoking the instance
method in a HookParam
specifies the wrong type.
The following example
injectMember {
+ // ...
+ afterHook {
+ // The type is cast to Activity
+ // But assumes the current instance's type is not this type
+ instance<Activity>()...
+ }
+}
+
Solution
Please confirm the correct type of the current Hook instance and refill the type in the generic.
If you are not sure, please use Any
or directly use the instance
variable.
IllegalStateException
HookParam Method args is empty, mabe not has args
Abnormal
The ArgsModifyer.set
method is called in HookParam
but the method parameter array for the current instance is empty.
The following example
injectMember {
+ // ...
+ afterHook {
+ // This method is called
+ args(...).set(...)
+ }
+}
+
Solution
Please make sure that the number of method parameters of the target method and constructor of your Hook is not empty, otherwise you cannot use this function.
IllegalStateException
HookParam Method args index out of bounds, max is NUMBER
Abnormal
Calling the ArgsModifyer.set
method in HookParam
specifies an array number beyond the subscript of the method parameter.
The following example
injectMember {
+ // ...
+ afterHook {
+ // The subscript starts from 0
+ // Assuming the original parameter subscript is 5, but fill in 6 here
+ args(index = 6).set(...)
+ }
+}
+
Solution
Please confirm the target method of your Hook, the number of method parameters of the constructor, and reset the array subscript.
IllegalStateException
PackageParam got null ClassLoader
Abnormal
The appClassLoader
variable was called in PackageParam
but the instance object could not be obtained.
The following example
encase {
+ // This variable is called
+ appClassLoader...
+}
+
Solution
This situation hardly exists, unless there is a problem with the Host App where the Module App is loaded or the target Hook Framework itself.
If this problem does occur, please provide feedback with detailed logs.
IllegalStateException
Current Hook Framework not support moduleAppResources
Abnormal
The moduleAppResources
variable was called in PackageParam
but the instance object could not be obtained.
The following example
encase {
+ // This variable is called
+ moduleAppResources...
+}
+
Solution
moduleAppResources
requires the current Hook Framework to support the initZygote
function, please check and try again.
IllegalStateException
VariousClass match failed of those CLASSES
Abnormal
All Class
were not found when creating indeterminate Class
objects using VariousClass
.
Solution
After checking whether there is a matching Class
in the Host App of the current Hook, try again.
IllegalStateException
Cannot get hook class "NAME" cause THROWABLE
Abnormal
The instanceClass
variable is called in the hook
method body other than the onPrepareHook
method and the Class
of the current Hook does not exist.
The following example
TargetClass.hook {
+ // The possible case is that the instanceClass variable
+ // Who is called in the body of the non-onPrepareHook method to print the log
+ loggerD(msg = "$instanceClass hook start")
+}
+
Solution
Using instanceClass
directly in hook
is very dangerous, if the Class does not exist, it will directly cause the Hook process to "die".
For details, please refer to Status Monitor.
IllegalStateException
LayoutInflatedParam View instance got null
Abnormal
currentView
was called in the layout hook callback but no instance object was obtained.
The following example
injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ // This variable is called
+ currentView...
+ }
+}
+
Solution
This situation basically does not exist, unless the current Activity
of the Host App has been destroyed or there is a problem with the Hook Framework itself.
IllegalStateException
XResForwarder is invalid
Abnormal
resources
was called in YukiResForwarder
but no instance object was obtained.
The following example
// This variable is called
+moduleAppResources.fwd(...).resources
+
Solution
This basically doesn't exist unless there is a problem with the Hook Framework itself.
IllegalStateException
paramTypes is empty, please use emptyParam() instead
Abnormal
The empty param
method is preserved when looking up methods, constructors.
The following example
method {
+ name = "test"
+ // No parameters are filled in parentheses
+ param()
+}
+
Solution
To identify this method, the constructor has no parameters, you can have a setter method as follows.
The first way, set emptyParam
(recommended)
The following example
method {
+ name = "test"
+ emptyParam()
+}
+
The second way, set paramCount = 0
The following example
method {
+ name = "test"
+ paramCount = 0
+}
+
IllegalStateException
Invalid YukiHookCallback type
Abnormal
The core Hook functionality of YukiHookAPI
is broken.
Solution
This situation basically does not exist.
If the above problem occurs, after confirming that the problem is not in your own code, you can submit a log for feedback.
IllegalStateException
ModuleContextThemeWrapper already loaded
Abnormal
Called repeatedly when using the applyModuleTheme
method in the Context
.
The following example
// Assume this is the current Context object
+context.applyModuleTheme(R.style.Theme_AppCompat).applyModuleTheme(R.style.Theme_AppCompat)
+
Solution
The ModuleContextThemeWrapper
can only be created once in the Context
, please check the code for loop call problems.
IllegalStateException
Cannot create classes cache for "android", please remove "name" param
Abnormal
The DexClassFinder
cache function searchClass(name = ...)
is used in the System Framework ("android") Host App.
The following example
loadSystem {
+ searchClass(name = "test") {
+ from(...)
+ // ...
+ }.get()
+}
+
Solution
Since the cache will store the found Class
name in SharedPreferences
, but the data directory does not exist in the System Framework, so please do not use this function in the System Framework.
\u5F02\u5E38\u662F\u5728\u5F00\u53D1\u8FC7\u7A0B\u7ECF\u5E38\u9047\u5230\u7684\u4E3B\u8981\u95EE\u9898\uFF0C\u8FD9\u91CC\u4ECB\u7ECD\u4E86
YukiHookAPI
\u5728\u4F7F\u7528\u8FC7\u7A0B\u4E2D\u53EF\u80FD\u9047\u5230\u7684\u5E38\u89C1\u5F02\u5E38\u4EE5\u53CA\u5904\u7406\u65B9\u5F0F\u3002
\u8FD9\u91CC\u7684\u5F02\u5E38\u8BF4\u660E\u53EA\u4F1A\u540C\u6B65\u6700\u65B0\u7684 API \u7248\u672C\uFF0C\u8F83\u65E7\u7684 API \u7248\u672C\u7684\u5F02\u5E38\u5C06\u4E0D\u4F1A\u518D\u8FDB\u884C\u8BF4\u660E\uFF0C\u8BF7\u59CB\u7EC8\u4FDD\u6301 API \u7248\u672C\u4E3A\u6700\u65B0\u3002
\u8FD9\u4E9B\u5F02\u5E38\u4E0D\u4F1A\u5BFC\u81F4 APP \u505C\u6B62\u8FD0\u884C(FC)\uFF0C\u4F46\u662F\u4F1A\u5728\u63A7\u5236\u53F0\u6253\u5370
E
\u7EA7\u522B\u7684\u65E5\u5FD7\uFF0C\u4E5F\u53EF\u80FD\u4F1A\u505C\u6B62\u7EE7\u7EED\u6267\u884C\u76F8\u5173\u529F\u80FD\u3002
loggerE
Could not found XposedBridge in current space! Aborted
\u5F02\u5E38\u539F\u56E0
\u4F60\u7684 Hook Framework \u672A\u5728\u5DE5\u4F5C\u6216\u5E76\u672A\u6210\u529F\u88C5\u8F7D XposedBridge
\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60\u5728\u6B63\u786E\u7684\u5730\u65B9\u88C5\u8F7D\u4E86 YukiHookAPI
\u7684 encase
\u65B9\u6CD5\uFF0C\u8BE6\u60C5\u8BF7\u53C2\u8003 \u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E \u4EE5\u53CA \u4F5C\u4E3A Hook API \u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E\u3002
loggerE
You cannot load a hooker in "onInit" or "onXposedEvent" method! Aborted
\u5F02\u5E38\u539F\u56E0
\u4F60\u5C1D\u8BD5\u5728\u7EE7\u627F IYukiHookXposedInit
\u7684 Hook \u5165\u53E3\u7C7B\u7684 onInit
\u6216 onXposedEvent
\u65B9\u6CD5\u4E2D\u88C5\u8F7D\u4E86 encase
\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
class HookEntry : IYukiHookXposedInit {
+
+ override fun onInit() {
+ // \u2757\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5
+ YukiHookAPI.encase {
+ // Your code here.
+ }
+ }
+
+ override fun onXposedEvent() {
+ // \u2757\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5
+ YukiHookAPI.encase {
+ // Your code here.
+ }
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u5728 onHook
\u65B9\u6CD5\u4E2D\u88C5\u8F7D encase
\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
class HookEntry : IYukiHookXposedInit {
+
+ override fun onInit() {
+ // \u8FD9\u91CC\u53EA\u80FD\u88C5\u8F7D configs \u65B9\u6CD5
+ YukiHookAPI.configs {
+ // Your code here.
+ }
+ }
+
+ override fun onHook() {
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5
+ YukiHookAPI.encase {
+ // Your code here.
+ }
+ }
+}
+
loggerE
Hooking Process exception occurred
\u5F02\u5E38\u539F\u56E0
YukiHookAPI
\u5728\u8FDB\u884C\u81EA\u8EAB\u521D\u59CB\u5316 Hook \u8FC7\u7A0B\u4E2D\u53D1\u751F\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u901A\u5E38\u60C5\u51B5\u4E0B\u8FD9\u79CD\u9519\u8BEF\u4E0D\u4F1A\u8F7B\u6613\u53D1\u751F\uFF0C\u82E5\u4E00\u65E6\u53D1\u751F\u6B64\u9519\u8BEF\uFF0C\u53EF\u76F4\u63A5\u63D0\u4EA4\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
YukiHookAPI try to load HookEntryClass failed
\u5F02\u5E38\u539F\u56E0
YukiHookAPI
\u5728\u5C1D\u8BD5\u88C5\u8F7D Hook \u5165\u53E3\u7C7B onInit
\u6216 onHook
\u65B9\u6CD5\u65F6\u53D1\u751F\u4E86\u4E0D\u80FD\u5904\u7406\u7684\u5F02\u5E38\u6216\u627E\u4E0D\u5230\u5165\u53E3\u7C7B\u3002
\u89E3\u51B3\u65B9\u6848
\u901A\u5E38\u60C5\u51B5\u4E0B\u8FD9\u79CD\u9519\u8BEF\u4E0D\u4F1A\u8F7B\u6613\u53D1\u751F\uFF0C\u82E5\u4E00\u65E6\u53D1\u751F\u6B64\u9519\u8BEF\uFF0C\u8BF7\u81EA\u884C\u67E5\u770B\u63A7\u5236\u53F0\u6253\u5370\u7684\u65E5\u5FD7\u5B9A\u4F4D\u95EE\u9898\uFF0C\u786E\u5B9A\u5E76\u975E\u81EA\u5DF1\u7684\u4EE3\u7801\u53D1\u751F\u7684\u95EE\u9898\u540E\uFF0C\u53EF\u63D0\u4EA4\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
YukiHookAPI bind initZygote failed
\u5F02\u5E38\u539F\u56E0
YukiHookAPI
\u5728\u5C1D\u8BD5\u88C5\u8F7D Xposed \u539F\u751F\u63A5\u53E3 initZygote
\u65B9\u6CD5\u65F6\u53D1\u751F\u4E86\u4E0D\u80FD\u5904\u7406\u7684\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u901A\u5E38\u60C5\u51B5\u4E0B\u8FD9\u79CD\u9519\u8BEF\u4E0D\u4F1A\u8F7B\u6613\u53D1\u751F\uFF0C\u82E5\u4E00\u65E6\u53D1\u751F\u6B64\u9519\u8BEF\uFF0C\u8BF7\u81EA\u884C\u67E5\u770B\u63A7\u5236\u53F0\u6253\u5370\u7684\u65E5\u5FD7\u5B9A\u4F4D\u95EE\u9898\uFF0C\u786E\u5B9A\u5E76\u975E\u81EA\u5DF1\u7684\u4EE3\u7801\u53D1\u751F\u7684\u95EE\u9898\u540E\uFF0C\u53EF\u63D0\u4EA4\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
Failed to execute method "NAME", maybe your Hook Framework not support Resources Hook
\u5F02\u5E38\u539F\u56E0
YukiHookAPI
\u5728\u5C1D\u8BD5\u8FDB\u884C Resources Hook \u65F6\u53D1\u751F\u9519\u8BEF\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u4ED4\u7EC6\u68C0\u67E5\u9519\u8BEF\u65E5\u5FD7\u7684\u8BE6\u7EC6\u4FE1\u606F\u3002
\u82E5\u53D1\u751F Resources$NotFoundException
\u5219\u53EF\u80FD\u4E3A\u4F60\u67E5\u627E\u7684 Resources Id \u4E0D\u6B63\u786E\u3002
\u82E5\u53D1\u751F ClassNotFound
\u6216 NoClassDefFoundError
\u53EF\u80FD\u662F Hook Framework \u4E0D\u652F\u6301 Resources Hook(\u8D44\u6E90\u94A9\u5B50)\u3002
loggerE
HookClass [NAME] not found
\u5F02\u5E38\u539F\u56E0
\u5F53\u524D\u88AB Hook \u7684 Class
\u6CA1\u6709\u88AB\u627E\u5230\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u68C0\u67E5\u76EE\u6807 Class
\u662F\u5426\u5B58\u5728\uFF0C\u82E5\u60F3\u5FFD\u7565\u6B64\u9519\u8BEF\u8BF7\u4F7F\u7528 ignoredHookClassNotFoundFailure
\u65B9\u6CD5\u3002
loggerE
Hook Member [NAME] failed
\u5F02\u5E38\u539F\u56E0
Hook \u76EE\u6807\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u65F6\u53D1\u751F\u9519\u8BEF\u3002
\u89E3\u51B3\u65B9\u6848
\u6B64\u95EE\u9898\u901A\u5E38\u7531 Hook Framework \u4EA7\u751F\uFF0C\u8BF7\u68C0\u67E5\u5BF9\u5E94\u7684\u65E5\u5FD7\u5185\u5BB9\uFF0C\u82E5\u95EE\u9898\u6301\u7EED\u51FA\u73B0\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
Hooked Member with a finding error by CLASS
\u5F02\u5E38\u539F\u56E0
\u5728 Hook \u6267\u884C\u540E\u88AB Hook \u7684 member
\u4E3A null
\u4E14\u5DF2\u7ECF\u8BBE\u7F6E\u76EE\u6807 Hook \u65B9\u6CD5\u3001\u6784\u9020\u7C7B\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u68C0\u67E5\u6B64\u9519\u8BEF\u53D1\u751F\u524D\u7684\u4E0A\u4E00\u4E2A\u9519\u8BEF\u65E5\u5FD7\uFF0C\u6216\u8BB8\u5728\u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u65F6\u5019\u53D1\u751F\u4E86\u627E\u4E0D\u5230\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u9519\u8BEF\u3002
loggerE
Hooked Member cannot be non-null by CLASS
\u5F02\u5E38\u539F\u56E0
\u5728 Hook \u6267\u884C\u540E\u88AB Hook \u7684 member
\u4E3A null
\u4E14\u6CA1\u6709\u8BBE\u7F6E\u76EE\u6807 Hook \u65B9\u6CD5\u3001\u6784\u9020\u7C7B\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // \u8FD9\u91CC\u5E76\u6CA1\u6709\u8BBE\u7F6E\u9700\u8981 Hook \u7684\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u67E5\u627E\u6761\u4EF6
+ afterHook {
+ // ...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60\u5DF2\u7ECF\u5728 Hook \u4E4B\u524D\u6B63\u786E\u8BBE\u7F6E\u4E86\u8981 Hook \u7684\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u67E5\u627E\u65B9\u5F0F\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\u4E3E\u4F8B
+ method {
+ // Your code here.
+ }
+ afterHook {
+ // ...
+ }
+}
+
loggerE
Hooked method return type match failed, required [TYPE] but got [TYPE]
\u5F02\u5E38\u539F\u56E0
\u5728 Hook \u56DE\u8C03\u65B9\u6CD5\u4F53\u4E2D\u8BBE\u7F6E\u4E86 HookParam.result
\u6216\u4F7F\u7528\u4E86 replaceHook
\u4F46\u662F\u88AB Hook \u7684\u65B9\u6CD5\u8FD4\u56DE\u503C\u7C7B\u578B\u4E0E\u539F\u8FD4\u56DE\u503C\u7C7B\u578B\u4E0D\u5339\u914D\u3002
\u793A\u4F8B\u5982\u4E0B
\u5047\u8BBE\u8FD9\u4E2A\u662F\u88AB Hook \u7684\u65B9\u6CD5\u3002
private boolean test()
+
\u4E0B\u9762\u662F\u4E00\u4E2A\u9519\u8BEF\u7684\u6848\u5217\u3002
injectMember {
+ method {
+ name = "test"
+ emptyParam()
+ }
+ // <\u60C5\u666F1> \u8BBE\u7F6E\u4E86\u9519\u8BEF\u7684\u7C7B\u578B\uFF0C\u539F\u7C7B\u578B\u4E3A Boolean
+ beforeHook {
+ result = 0
+ }
+ // <\u60C5\u666F2> \u8FD4\u56DE\u4E86\u9519\u8BEF\u7684\u7C7B\u578B\uFF0C\u539F\u7C7B\u578B\u4E3A Boolean
+ replaceAny {
+ 0
+ }
+ // <\u60C5\u666F3> \u76F4\u63A5\u4F7F\u7528\u4E86\u9519\u8BEF\u7684\u7C7B\u578B\uFF0C\u539F\u7C7B\u578B\u4E3A Boolean
+ replaceTo(any = 0)
+}
+
\u6CE8\u610F
\u82E5\u4E0A\u8FF0\u573A\u666F\u5728 beforeHook \u6216 afterHook \u4E2D\u53D1\u751F\uFF0C\u5219\u4F1A\u9020\u6210\u88AB Hook \u7684 APP (\u5BBF\u4E3B) \u7531 XposedBridge \u629B\u51FA\u5F02\u5E38 (\u4F1A\u5BF9\u5176\u66B4\u9732\u88AB Hook \u7684\u4E8B\u5B9E)\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u5F53\u524D\u88AB Hook \u65B9\u6CD5\u7684\u6B63\u786E\u8FD4\u56DE\u503C\u7C7B\u578B\uFF0C\u4FEE\u6539\u540E\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
Hook initialization failed because got an Exception
\u5F02\u5E38\u539F\u56E0
\u5728\u51C6\u5907 Hook \u65F6\u53D1\u751F\u4E86\u4EFB\u610F\u7684\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u8FD9\u662F\u4E00\u4E2A\u51C6\u5907 Hook \u9636\u6BB5\u5C31\u53D1\u751F\u5F02\u5E38\u7684\u63D0\u9192\uFF0C\u8BF7\u4ED4\u7EC6\u67E5\u770B\u5177\u4F53\u7684\u5F02\u5E38\u662F\u4EC0\u4E48\u4EE5\u91CD\u65B0\u786E\u5B9A\u95EE\u9898\u3002
loggerE
Try to hook NAME[NAME] got an Exception
\u5F02\u5E38\u539F\u56E0
\u5728 Hook \u5F00\u59CB\u65F6\u53D1\u751F\u4E86\u4EFB\u610F\u7684\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u8FD9\u662F\u4E00\u4E2A Hook \u5F00\u59CB\u5C31\u53D1\u751F\u5F02\u5E38\u7684\u63D0\u9192\uFF0C\u8BF7\u4ED4\u7EC6\u67E5\u770B\u5177\u4F53\u7684\u5F02\u5E38\u662F\u4EC0\u4E48\u4EE5\u91CD\u65B0\u786E\u5B9A\u95EE\u9898\u3002
loggerE
Method/Constructor/Field match type "TYPE" not allowed
\u5F02\u5E38\u539F\u56E0
\u5728\u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u4EE5\u53CA\u53D8\u91CF\u65F6\u8BBE\u7F6E\u4E86\u4E0D\u5141\u8BB8\u7684\u53C2\u6570\u7C7B\u578B\u3002
\u793A\u4F8B\u5982\u4E0B
// \u67E5\u627E\u4E00\u4E2A\u65B9\u6CD5
+method {
+ // \u2757\u8BBE\u7F6E\u4E86\u65E0\u6548\u7684\u7C7B\u578B\u4E3E\u4F8B
+ param(false, 1, 0)
+ // \u2757\u8BBE\u7F6E\u4E86\u65E0\u6548\u7684\u7C7B\u578B\u4E3E\u4F8B
+ returnType = false
+}
+
+// \u67E5\u627E\u4E00\u4E2A\u53D8\u91CF
+field {
+ // \u2757\u8BBE\u7F6E\u4E86\u65E0\u6548\u7684\u7C7B\u578B\u4E3E\u4F8B
+ type = false
+}
+
\u89E3\u51B3\u65B9\u6848
\u5728\u67E5\u627E\u4E2D param
\u3001returnType
\u3001type
\u4E2D\u4EC5\u63A5\u53D7 Class
\u3001String
\u3001VariousClass
\u7C7B\u578B\u7684\u4F20\u503C\uFF0C\u4E0D\u53EF\u4F20\u5165\u53C2\u6570\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
// \u67E5\u627E\u4E00\u4E2A\u65B9\u6CD5
+method {
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\u4E3E\u4F8B
+ param(BooleanType, IntType, IntType)
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\u4E3E\u4F8B
+ returnType = BooleanType
+ // \u2705 \u4EE5\u4E0B\u65B9\u6848\u4E5F\u662F\u6B63\u786E\u7684
+ returnType = "java.lang.Boolean"
+}
+
+// \u67E5\u627E\u4E00\u4E2A\u53D8\u91CF
+field {
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\u4E3E\u4F8B
+ type = BooleanType
+}
+
loggerE
NoSuchMethod/NoSuchConstructor/NoSuchField happend in [NAME]
\u5F02\u5E38\u539F\u56E0
\u5728\u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u4EE5\u53CA\u53D8\u91CF\u65F6\u5E76\u672A\u627E\u5230\u76EE\u6807\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u4EE5\u53CA\u53D8\u91CF\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60\u7684\u67E5\u627E\u6761\u4EF6\u662F\u5426\u80FD\u6B63\u786E\u5339\u914D\u5230\u76EE\u6807 Class
\u4E2D\u7684\u6307\u5B9A\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u4EE5\u53CA\u53D8\u91CF\u3002
loggerE
Trying COUNT times and all failure by RemedyPlan
\u5F02\u5E38\u539F\u56E0
\u4F7F\u7528 RemedyPlan
\u91CD\u65B0\u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u3001\u53D8\u91CF\u65F6\u4F9D\u7136\u6CA1\u6709\u627E\u5230\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u3001\u53D8\u91CF\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60\u8BBE\u7F6E\u7684 RemedyPlan
\u53C2\u6570\u4EE5\u53CA\u5BBF\u4E3B\u5185\u5B58\u5728\u7684 Class
\uFF0C\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
You must set a condition when finding a Method/Constructor/Field
\u5F02\u5E38\u539F\u56E0
\u5728\u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u4EE5\u53CA\u53D8\u91CF\u65F6\u5E76\u672A\u8BBE\u7F6E\u4EFB\u4F55\u6761\u4EF6\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ // \u8FD9\u91CC\u6CA1\u6709\u8BBE\u7F6E\u4EFB\u4F55\u6761\u4EF6
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u5C06\u67E5\u627E\u6761\u4EF6\u8865\u5145\u5B8C\u6574\u5E76\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiHookAPI#ReflectionTool
\u5F02\u5E38\u539F\u56E0
\u901A\u8FC7 ClassLoader.searchClass
\u6216 PackageParam.searchClass
\u627E\u4E0D\u5230\u9700\u8981\u67E5\u627E\u7684 Class
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
customClassLoader?.searchClass {
+ from(...)
+ // ...
+}.get()
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u662F\u4E00\u4E2A\u5B89\u5168\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u4F60\u8BBE\u7F6E\u7684\u6761\u4EF6\uFF0C\u4F7F\u7528\u76F8\u5173\u5DE5\u5177\u67E5\u770B\u6240\u5728 Dex \u4E2D\u7684 Class
\u4EE5\u53CA\u5B57\u8282\u7801\u5BF9\u8C61\u7279\u5F81\uFF0C\u5E76\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
Can't find this Method/Constructor/Field in [CLASS]: CONTENT Generated by YukiHookAPI#ReflectionTool
\u5F02\u5E38\u539F\u56E0
\u901A\u8FC7\u6307\u5B9A\u6761\u4EF6\u627E\u4E0D\u5230\u9700\u8981\u67E5\u627E\u7684\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u4EE5\u53CA\u53D8\u91CF\u3002
\u793A\u4F8B\u5982\u4E0B
TargetClass.method {
+ name = "test"
+ param(BooleanType)
+}
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u662F\u4E00\u4E2A\u5B89\u5168\u5F02\u5E38\uFF0C\u8BF7\u68C0\u67E5\u4F60\u8BBE\u7F6E\u7684\u6761\u4EF6\uFF0C\u4F7F\u7528\u76F8\u5173\u5DE5\u5177\u67E5\u770B\u6240\u5728 Class
\u4E2D\u7684\u5B57\u8282\u7801\u5BF9\u8C61\u7279\u5F81\uFF0C\u5E76\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
The number of VagueType must be at least less than the count of paramTypes
\u5F02\u5E38\u539F\u56E0
\u5728 Method
\u3001Constructor
\u67E5\u627E\u6761\u4EF6\u4E2D\u9519\u8BEF\u5730\u4F7F\u7528\u4E86 VagueType
\u3002
\u793A\u4F8B\u5982\u4E0B
TargetClass.method {
+ name = "test"
+ // <\u60C5\u666F1>
+ param(VagueType)
+ // <\u60C5\u666F2>
+ param(VagueType, VagueType ...)
+}
+
\u89E3\u51B3\u65B9\u6848
VagueType
\u4E0D\u80FD\u5728\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u53C2\u6570\u4E2D\u5B8C\u5168\u586B\u5145\uFF0C\u82E5\u5B58\u5728\u8FD9\u6837\u7684\u9700\u6C42\u8BF7\u4F7F\u7528 paramCount
\u3002
loggerE
Field match type class is not found
\u5F02\u5E38\u539F\u56E0
\u5728\u67E5\u627E\u53D8\u91CF\u65F6\u6240\u8BBE\u7F6E\u7684\u67E5\u627E\u6761\u4EF6\u4E2D type
\u7684 Class
\u5B9E\u4F8B\u672A\u88AB\u627E\u5230\u3002
\u793A\u4F8B\u5982\u4E0B
field {
+ name = "test"
+ // \u5047\u8BBE\u8FD9\u91CC\u8BBE\u7F6E\u7684 type \u7684 Class \u5E76\u4E0D\u5B58\u5728
+ type = "com.example.TestClass"
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u68C0\u67E5\u67E5\u627E\u6761\u4EF6\u4E2D type
\u7684 Class
\u662F\u5426\u5B58\u5728\uFF0C\u7136\u540E\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
Method match returnType class is not found
\u5F02\u5E38\u539F\u56E0
\u5728\u67E5\u627E\u65B9\u6CD5\u65F6\u6240\u8BBE\u7F6E\u7684\u67E5\u627E\u6761\u4EF6\u4E2D returnType
\u7684 Class
\u5B9E\u4F8B\u672A\u88AB\u627E\u5230\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ name = "test"
+ // \u5047\u8BBE\u8FD9\u91CC\u8BBE\u7F6E\u7684 returnType \u7684 Class \u5E76\u4E0D\u5B58\u5728
+ returnType = "com.example.TestClass"
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u68C0\u67E5\u67E5\u627E\u6761\u4EF6\u4E2D returnType
\u7684 Class
\u662F\u5426\u5B58\u5728\uFF0C\u7136\u540E\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
Method/Constructor match paramType[INDEX] class is not found
\u5F02\u5E38\u539F\u56E0
\u5728\u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u65F6\u6240\u8BBE\u7F6E\u7684\u67E5\u627E\u6761\u4EF6\u4E2D param
\u7684 index
\u53F7\u4E0B\u6807\u7684 Class
\u5B9E\u4F8B\u672A\u88AB\u627E\u5230\u3002
method {
+ name = "test"
+ // \u5047\u8BBE\u8FD9\u91CC\u8BBE\u7F6E\u7684 1 \u53F7\u4E0B\u6807\u7684 Class \u5E76\u4E0D\u5B58\u5728
+ param(StringType, "com.example.TestClass", BooleanType)
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u68C0\u67E5\u67E5\u627E\u6761\u4EF6\u4E2D param
\u7684 index
\u53F7\u4E0B\u6807\u7684 Class
\u662F\u5426\u5B58\u5728\uFF0C\u7136\u540E\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
Resources Hook condition name/type cannot be empty [TAG]
\u5F02\u5E38\u539F\u56E0
\u5728\u67E5\u627E Resources \u65F6\u5E76\u672A\u8BBE\u7F6E\u4EFB\u4F55\u6761\u4EF6\u3002
\u793A\u4F8B\u5982\u4E0B
// \u60C5\u51B5 1
+conditions {
+ // \u8FD9\u91CC\u6CA1\u6709\u8BBE\u7F6E\u4EFB\u4F55\u6761\u4EF6
+}
+// \u60C5\u51B5 2
+conditions {
+ name = "test"
+ // \u8FD9\u91CC\u7F3A\u5C11\u4E86 type \u6761\u4EF6
+}
+
\u89E3\u51B3\u65B9\u6848
Resources \u7684 Hook \u5E76\u975E\u7C7B\u4F3C\u65B9\u6CD5\u7684 Hook\uFF0C\u5176\u5FC5\u987B\u62E5\u6709\u5B8C\u6574\u7684\u540D\u79F0\u548C\u7C7B\u578B\u63CF\u8FF0\u624D\u80FD\u67E5\u627E\u6210\u529F\uFF0C\u8BF7\u5C06\u67E5\u627E\u6761\u4EF6\u8865\u5145\u5B8C\u6574\u5E76\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
Resources Hook type is invalid [TAG]
\u5F02\u5E38\u539F\u56E0
\u5728 Hook Resources \u65F6\u53D1\u751F\u4E86\u7C7B\u578B\u9519\u8BEF\u7684\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
YukiHookAPI
\u4F1A\u5C1D\u8BD5\u5728 initZygote
\u4E0E handleInitPackageResources
\u4E2D\u88C5\u8F7D Resources Hook\uFF0C\u82E5\u5168\u90E8\u88C5\u8F7D\u5931\u8D25\u53EF\u80FD\u4F1A\u53D1\u751F\u6B64\u5F02\u5E38\uFF0C\u5F53\u524D Hook Framework \u9700\u8981\u652F\u6301\u5E76\u542F\u7528\u8D44\u6E90\u94A9\u5B50(Resources Hook)\u529F\u80FD\uFF0C\u8BF7\u68C0\u67E5\u540E\u518D\u8BD5\u4E00\u6B21\u3002
loggerE
Resources Hook got an Exception [TAG]
\u5F02\u5E38\u539F\u56E0
\u5728 Hook Resources \u65F6\u53D1\u751F\u4E86\u4EFB\u610F\u7684\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u8FD9\u662F\u4E00\u4E2A\u5F02\u5E38\u6C47\u603B\uFF0C\u8BF7\u81EA\u884C\u5411\u4E0B\u67E5\u770B\u65E5\u5FD7\u5177\u4F53\u7684\u5F02\u5E38\u662F\u4EC0\u4E48\uFF0C\u4F8B\u5982\u627E\u4E0D\u5230 Resources Id \u7684\u95EE\u9898\u3002
loggerE
Received action "ACTION" failed
\u5F02\u5E38\u539F\u56E0
\u4F7F\u7528 YukiHookDataChannel
\u65F6\u56DE\u8C03\u5E7F\u64AD\u4E8B\u4EF6\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u4E00\u822C\u60C5\u51B5\u4E0B\uFF0C\u6B64\u9519\u8BEF\u57FA\u672C\u4E0A\u4E0D\u4F1A\u53D1\u751F\uFF0C\u4E00\u65E6\u53D1\u751F\u9519\u8BEF\uFF0C\u6392\u9664\u81EA\u8EAB\u4EE3\u7801\u7684\u95EE\u9898\u540E\uFF0C\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
Failed to sendBroadcast like "KEY", because got null context in "PACKAGENAME"
\u5F02\u5E38\u539F\u56E0
\u4F7F\u7528 YukiHookDataChannel
\u65F6\u53D1\u9001\u5E7F\u64AD\u53D6\u5230\u4E86\u7A7A\u7684\u4E0A\u4E0B\u6587\u5B9E\u4F8B\u3002
\u89E3\u51B3\u65B9\u6848
\u4E00\u822C\u60C5\u51B5\u4E0B\uFF0C\u6B64\u9519\u8BEF\u57FA\u672C\u4E0A\u4E0D\u4F1A\u53D1\u751F\uFF0C\u5728\u6700\u65B0\u7248\u672C\u4E2D\u5DF2\u7ECF\u4FEE\u590D\u5BBF\u4E3B\u4F7F\u7528\u65F6\u53EF\u80FD\u53D1\u751F\u7684\u95EE\u9898\uFF0C\u82E5\u6700\u65B0\u7248\u672C\u4F9D\u7136\u53D1\u751F\u9519\u8BEF\uFF0C\u6392\u9664\u81EA\u8EAB\u4EE3\u7801\u7684\u95EE\u9898\u540E\uFF0C\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
Failed to inject module resources into [RESOURCES]
\u5F02\u5E38\u539F\u56E0
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528 injectModuleAppResources
\u6CE8\u5165\u6A21\u5757\u8D44\u6E90\u65F6\u53D1\u751F\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u4E00\u822C\u60C5\u51B5\u4E0B\uFF0C\u6B64\u9519\u8BEF\u57FA\u672C\u4E0A\u4E0D\u4F1A\u53D1\u751F\uFF0C\u6392\u9664\u81EA\u8EAB\u4EE3\u7801\u7684\u95EE\u9898\u540E\uFF0C\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
Activity Proxy initialization failed because got an Exception
\u5F02\u5E38\u539F\u56E0
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528 registerModuleAppActivities
\u6CE8\u5165\u6A21\u5757 Activity
\u65F6\u53D1\u751F\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u68C0\u67E5\u6B64\u9519\u8BEF\u53D1\u751F\u540E\u7684\u4E0B\u4E00\u4E2A\u9519\u8BEF\u65E5\u5FD7\uFF0C\u6216\u8BB8\u5728\u914D\u7F6E\u53C2\u6570\u4E0A\u53EF\u80FD\u53D1\u751F\u4E86\u4E00\u4E9B\u95EE\u9898\uFF0C\u82E5\u627E\u4E0D\u5230\u76F8\u5173\u9519\u8BEF\u65E5\u5FD7\u7684\u8BF4\u660E\uFF0C\u6392\u9664\u81EA\u8EAB\u4EE3\u7801\u7684\u95EE\u9898\u540E\uFF0C\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
Activity Proxy got an Exception in msg.what [WHAT]
\u5F02\u5E38\u539F\u56E0
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528 registerModuleAppActivities
\u6CE8\u5165\u6A21\u5757 Activity
\u65F6\u53D1\u751F\u5F02\u5E38\u3002
\u89E3\u51B3\u65B9\u6848
\u4E00\u822C\u60C5\u51B5\u4E0B\uFF0C\u6B64\u9519\u8BEF\u57FA\u672C\u4E0A\u4E0D\u4F1A\u53D1\u751F\uFF0C\u4F46\u6839\u636E\u7CFB\u7EDF\u7248\u672C\u5DEE\u5F02\u6027\u5E76\u672A\u505A\u8BE6\u7EC6\u6D4B\u8BD5\uFF0C\u6392\u9664\u81EA\u8EAB\u4EE3\u7801\u7684\u95EE\u9898\u540E\uFF0C\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
loggerE
This proxy [TYPE] type is not allowed
\u5F02\u5E38\u539F\u56E0
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528 registerModuleAppActivities
\u6CE8\u5165\u6A21\u5757 Activity
\u65F6\u586B\u5165\u4E86\u65E0\u6548\u7684\u53C2\u6570\u3002
\u793A\u4F8B\u5982\u4E0B
// \u2757 \u8FD9\u91CC\u586B\u5165\u7684\u5185\u5BB9\u4EC5\u4E3A\u4E3E\u4F8B\uFF0C\u5176\u4E2D proxy \u586B\u5165\u4E86\u4E0D\u80FD\u7406\u89E3\u7684\u65E0\u6548\u53C2\u6570
+registerModuleAppActivities(proxy = false)
+
\u89E3\u51B3\u65B9\u6848
\u65B9\u6CD5\u4E2D\u7684 proxy
\u53C2\u6570\u53EA\u63A5\u53D7 String
\u3001CharSequence
\u3001Class
\u7C7B\u578B\uFF0C\u8BF7\u67E5\u770B\u76F8\u5173\u4F7F\u7528\u65B9\u6CD5\u6B63\u786E\u586B\u5165\u65B9\u6CD5\u53C2\u6570\u3002
loggerE
Cound not got launch intent for package "NAME"
\u5F02\u5E38\u539F\u56E0
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528 registerModuleAppActivities
\u6CE8\u5165\u6A21\u5757 Activity
\u65F6\u627E\u4E0D\u5230\u5BBF\u4E3B\u7684\u542F\u52A8 Activity
\u3002
\u793A\u4F8B\u5982\u4E0B
// \u4F7F\u7528\u4E86\u9ED8\u8BA4\u53C2\u6570\u76F4\u63A5\u8FDB\u884C\u6CE8\u518C
+registerModuleAppActivities()
+
\u89E3\u51B3\u65B9\u6848
\u9ED8\u8BA4\u53C2\u6570 (\u65E0\u53C2) \u53EA\u80FD\u7528\u4E8E\u53EF\u88AB\u542F\u52A8\u7684 APP\uFF0C\u82E5 APP \u5E76\u672A\u58F0\u660E\u542F\u52A8\u5165\u53E3 Activity
\uFF0C\u4F60\u5C31\u9700\u8981\u624B\u52A8\u6307\u5B9A\u65B9\u6CD5\u7684 proxy
\u53C2\u6570\u3002
loggerE
Could not found "NAME" or Class is not a type of Activity
\u5F02\u5E38\u539F\u56E0
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E2D\u4F7F\u7528 registerModuleAppActivities
\u6CE8\u5165\u6A21\u5757 Activity
\u65F6\u65E0\u6CD5\u627E\u5230\u88AB\u586B\u5165\u53C2\u6570 proxy
\u7684 Activity
\u3002
\u793A\u4F8B\u5982\u4E0B
registerModuleAppActivities(proxy = "com.demo.test.TestActivity")
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60\u586B\u5165\u7684 Activity
\u540D\u79F0\u771F\u5B9E\u6709\u6548\u5730\u5B58\u5728\u4E8E\u5BBF\u4E3B\u4E2D\uFF0C\u4E14\u76EE\u6807 Class
\u7EE7\u627F\u4E8E Activity
\u3002
\u8FD9\u4E9B\u5F02\u5E38\u4F1A\u76F4\u63A5\u5BFC\u81F4 APP \u505C\u6B62\u8FD0\u884C(FC)\uFF0C\u540C\u65F6\u4F1A\u5728\u63A7\u5236\u53F0\u6253\u5370
E
\u7EA7\u522B\u7684\u65E5\u5FD7\uFF0C\u8FD8\u4F1A\u9020\u6210 Hook \u8FDB\u7A0B\u201C\u6B7B\u6389\u201D\u3002
RuntimeException
!!!DO NOT ALLOWED!!! You cannot hook or reflection to call the internal class of the YukiHookAPI itself, The called class is [CLASS]
\u5F02\u5E38\u539F\u56E0
\u4F60\u4F7F\u7528 YukiHookAPI
\u7684\u76F8\u5173\u53CD\u5C04\u6216 Hook \u529F\u80FD\u8C03\u7528\u4E86 API \u81EA\u8EAB\u7684 Class
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
// <\u60C5\u666F1>
+YukiHookAPI.current()
+// <\u60C5\u666F2>
+PackageParam::class.java.hook {
+ // ...
+}
+// <\u60C5\u666F3>
+MethodFinder::class.java.method {
+ name = "name"
+ param(StringType)
+}.get().call("name")
+// ...
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u68C0\u67E5\u4EE3\u7801\u90E8\u5206\u662F\u5426\u6709\u9519\u8BEF\uFF0C\u4F8B\u5982\u4E0B\u9762\u7684\u60C5\u51B5\u3002
\u793A\u4F8B\u5982\u4E0B
YourClass.method {
+ // ...
+ // \u2757 \u6CA1\u6709\u8C03\u7528\u65B9\u6CD5\u6267\u884C\uFF0C\u8FD9\u91CC\u5B9E\u9645\u8C03\u7528\u7684\u662F MethodFinder.Result \u5BF9\u8C61
+}.get(instance).current()
+YourClass.method {
+ // ...
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5047\u8BBE\u6B64\u65B9\u6CD5\u65E0\u53C2
+}.get(instance).call().current()
+
\u4E0D\u5141\u8BB8\u5185\u8054\u3001\u53CD\u5C04\u3001Hook YukiHookAPI
\u81EA\u8EAB\u7684 Class
\u4EE5\u53CA\u5185\u90E8\u529F\u80FD\uFF0C\u9632\u6B62\u53D1\u751F\u9519\u8BEF\u3002
UnsupportedOperationException
!!!DANGEROUS!!! Hook [CLASS] Class is a dangerous behavior! [CONTENT] [SOLVE]
\u5F02\u5E38\u539F\u56E0
\u4F60\u5C1D\u8BD5 Hook \u4E86\u5904\u4E8E\u5371\u9669\u884C\u4E3A\u5217\u8868\u4E2D\u7684 Class
\u5BF9\u8C61\uFF0C\u4F8B\u5982 Class
\u3001ClassLoader
\u3001Method
\u3002
\u793A\u4F8B\u5982\u4E0B
// <\u60C5\u666F1>
+JavaClassLoader.hook {
+ // ...
+}
+// <\u60C5\u666F2>
+JavaClass.hook {
+ // ...
+}
+// <\u60C5\u666F3>
+JavaMethod.hook {
+ // ...
+}
+// ...
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u4E9B\u529F\u80FD\u662F\u7CFB\u7EDF\u5185\u90E8\u7684\uFF0C\u5B83\u4EEC\u4E0D\u5E94\u8BE5\u88AB Hook\uFF0C\u5728\u90E8\u5206 Hook Framework \u4E0A\u53EF\u80FD\u4E0D\u88AB\u652F\u6301\uFF0C\u8FD8\u4F1A\u5F15\u53D1\u5176\u5B83\u9519\u8BEF\uFF0C\u8BF7\u5C1D\u8BD5\u66F4\u6362 Hook \u70B9\u3002
\u5C0F\u63D0\u793A
\u82E5\u4F60\u4ECD\u8981\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u8BF7\u53C2\u8003 YukiMemberHookCreator.useDangerousOperation\u3002
\u4F46\u662F\u5F3A\u70C8\u5EFA\u8BAE\u4E0D\u8981\u8FD9\u6837\u505A\uFF0C\u53D1\u751F\u95EE\u9898\u8BF7\u4E0D\u8981\u53CD\u9988\uFF0C\u81EA\u884C\u627F\u62C5\u4E00\u5207\u540E\u679C\u3002
NoClassDefFoundError
Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiHookAPI#ReflectionTool
\u5F02\u5E38\u539F\u56E0
\u901A\u8FC7 String.toClass(...)
\u6216 classOf<...>()
\u627E\u4E0D\u5230\u9700\u8981\u67E5\u627E\u7684 Class
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
"com.demo.Test".toClass()
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u68C0\u67E5\u5F53\u524D\u5B57\u7B26\u4E32\u6216\u5B9E\u4F53\u5339\u914D\u5230\u7684 Class
\u662F\u5426\u5B58\u5728\u4E8E\u5F53\u524D ClassLoader
\uFF0C\u5E76\u518D\u8BD5\u4E00\u6B21\u3002
IllegalStateException
ClassLoader [CLASSLOADER] is not a DexClassLoader
\u5F02\u5E38\u539F\u56E0
\u4F7F\u7528 ClassLoader.searchClass
\u6216 PackageParam.searchClass
\u67E5\u627E Class
\u4F46\u662F\u5F53\u524D ClassLoader
\u5E76\u4E0D\u7EE7\u627F\u4E8E BaseDexClassLoader
\u3002
\u89E3\u51B3\u65B9\u6848
\u8FD9\u79CD\u60C5\u51B5\u57FA\u672C\u4E0D\u5B58\u5728\uFF0C\u9664\u975E\u5F53\u524D APP \u5F15\u7528\u4E86\u975E ART \u5E73\u53F0\u7684\u53EF\u6267\u884C\u6587\u4EF6 (\u4F46\u662F\u8FD9\u79CD\u60C5\u51B5\u8FD8\u662F\u4E0D\u4F1A\u5B58\u5728) \u6216\u5F53\u524D ClassLoader
\u4E3A\u7A7A\u3002
IllegalStateException
Failed to got SystemContext
\u5F02\u5E38\u539F\u56E0
\u5728\u88AB Hook \u7684\u5BBF\u4E3B\u5185\u8C03\u7528\u4E86 systemContext
\u4F46\u5E76\u672A\u6210\u529F\u83B7\u53D6\u5230\u5B9E\u4F8B\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
encase {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ systemContext...
+}
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u79CD\u60C5\u51B5\u4E0D\u5E94\u8BE5\u5B58\u5728\uFF0C\u7531\u4E8E systemContext
\u901A\u8FC7\u53CD\u5C04\u4ECE ActivityThread
\u4E2D\u5F97\u5230\uFF0C\u9664\u975E\u7CFB\u7EDF\u8FDB\u7A0B\u53D1\u751F\u5F02\u5E38\uFF0C\u5426\u5219\u83B7\u53D6\u5230\u7684\u5BF9\u8C61\u4E0D\u4F1A\u4E3A\u7A7A\u3002
IllegalStateException
App is dead, You cannot call to appContext
\u5F02\u5E38\u539F\u56E0
\u7B2C\u4E00\u79CD\u60C5\u51B5
\u5728\u88AB Hook \u7684\u5BBF\u4E3B\u5185\u8C03\u7528\u4E86 ModuleApplication
\u7684 appContext
\u3002
\u793A\u4F8B\u5982\u4E0B
encase {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ ModuleApplication.appContext...
+}
+
\u7B2C\u4E8C\u79CD\u60C5\u51B5
\u4F7F\u7528 ModuleApplication
\u65F6\u8C03\u7528\u4E86 appContext
\u4F46\u662F APP \u53EF\u80FD\u5DF2\u7ECF\u88AB\u9500\u6BC1\u6216\u6CA1\u6709\u6B63\u786E\u542F\u52A8\u3002
\u793A\u4F8B\u5982\u4E0B
// \u8C03\u7528\u4E86\u6B64\u53D8\u91CF\u4F46\u662F APP \u53EF\u80FD\u5DF2\u88AB\u9500\u6BC1\u6216\u6CA1\u6709\u6B63\u786E\u542F\u52A8
+ModuleApplication.appContext...
+
\u89E3\u51B3\u65B9\u6848
\u7B2C\u4E00\u79CD\u60C5\u51B5
\u4F60\u53EA\u80FD\u5728\u6A21\u5757\u5185\u4F7F\u7528 ModuleApplication
\u7684 appContext
\uFF0C\u5728\u5BBF\u4E3B\u5185\u8BF7\u4F7F\u7528 PackageParam
\u4E2D\u7684 appContext
\uFF0C\u8BF7\u786E\u8BA4\u4F60\u4F7F\u7528\u7684\u662F\u5426\u6B63\u786E\u3002
\u7B2C\u4E8C\u79CD\u60C5\u51B5
\u8FD9\u79CD\u60C5\u51B5\u57FA\u672C\u4E0D\u5B58\u5728\uFF0C\u7531\u4E8E appContext
\u662F\u5728 onCreate
\u4E2D\u88AB\u8D4B\u503C\u7684\uFF0C\u9664\u975E\u9047\u5230\u591A\u8FDB\u7A0B\u5E76\u53D1\u542F\u52A8\u6216 APP \u6CA1\u6709\u542F\u52A8\u5B8C\u6210\u524D\u88AB\u53CD\u5C04\u8C03\u7528\u4E86\u7236\u7C7B\u7684 onCreate
\u65B9\u6CD5\u3002
IllegalStateException
YukiHookModulePrefs not allowed in Custom Hook API
\u5F02\u5E38\u539F\u56E0
\u5728 Hook \u81EA\u8EAB APP(\u975E Xposed \u6A21\u5757) \u4E2D\u4F7F\u7528\u4E86 YukiHookModulePrefs
\u3002
\u793A\u4F8B\u5982\u4E0B
class MyApplication : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ YukiHookAPI.encase(base) {
+ // \u2757\u4E0D\u80FD\u5728\u8FD9\u79CD\u60C5\u51B5\u4E0B\u4F7F\u7528 prefs
+ prefs.getBoolean("test_data")
+ }
+ super.attachBaseContext(base)
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u4F60\u53EA\u80FD\u5728 \u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528 \u65F6\u4F7F\u7528 YukiHookModulePrefs
\uFF0C\u5728 Hook \u81EA\u8EAB APP \u4E2D\u8BF7\u4F7F\u7528\u539F\u751F\u7684 Sp
\u5B58\u50A8\u3002
IllegalStateException
Cannot load the XSharedPreferences, maybe is your Hook Framework not support it
\u5F02\u5E38\u539F\u56E0
\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u4E86 YukiHookModulePrefs
\u4F46\u662F\u65E0\u6CD5\u5F97\u5230 XSharedPreferences
\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
encase {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ prefs...
+}
+
\u89E3\u51B3\u65B9\u6848
\u4E00\u822C\u60C5\u51B5\u4E0B\u4E0D\u4F1A\u53D1\u751F\u6B64\u95EE\u9898\uFF0C\u82E5\u6301\u7EED\u65E0\u6CD5\u83B7\u53D6 XSharedPreferences
\u5BF9\u8C61\u5219\u53EF\u80FD\u662F\u4F60\u4F7F\u7528\u7684 Hook Framework \u4E0D\u652F\u6301\u6B64\u529F\u80FD\u6216\u81EA\u8EAB\u5B58\u5728\u9519\u8BEF\u3002
IllegalStateException
YukiHookDataChannel not allowed in Custom Hook API
\u5F02\u5E38\u539F\u56E0
\u5728 Hook \u81EA\u8EAB APP(\u975E Xposed \u6A21\u5757) \u4E2D\u4F7F\u7528\u4E86 YukiHookDataChannel
\u3002
\u793A\u4F8B\u5982\u4E0B
class MyApplication : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ YukiHookAPI.encase(base) {
+ // \u2757\u4E0D\u80FD\u5728\u8FD9\u79CD\u60C5\u51B5\u4E0B\u4F7F\u7528 dataChannel
+ dataChannel.wait(key = "test_data") {
+ // ...
+ }
+ }
+ super.attachBaseContext(base)
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u4F60\u53EA\u80FD\u5728 \u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528 \u65F6\u4F7F\u7528 YukiHookDataChannel
\u3002
IllegalStateException
YukiHookDataChannel only support used on an Activity, but this current context is "CLASSNAME"
\u5F02\u5E38\u539F\u56E0
\u5728\u6A21\u5757\u7684\u975E Activity
\u73AF\u5883\u4E2D\u4F7F\u7528\u4E86 YukiHookDataChannel
\u3002
\u89E3\u51B3\u65B9\u6848
\u4F60\u53EA\u80FD\u5728 Activity
\u6216 Fragment
\u4E2D\u4F7F\u7528 YukiHookDataChannel
\u3002
IllegalStateException
Xposed modulePackageName load failed, please reset and rebuild it
\u5F02\u5E38\u539F\u56E0
\u5728 Hook \u8FC7\u7A0B\u4E2D\u4F7F\u7528 YukiHookModulePrefs
\u6216 YukiHookDataChannel
\u65F6\u65E0\u6CD5\u8BFB\u53D6\u88C5\u8F7D\u65F6\u7684 modulePackageName
\u5BFC\u81F4\u4E0D\u80FD\u786E\u5B9A\u81EA\u8EAB\u6A21\u5757\u7684\u5305\u540D\u3002
\u89E3\u51B3\u65B9\u6848
\u8BF7\u4ED4\u7EC6\u9605\u8BFB \u8FD9\u91CC \u7684\u5E2E\u52A9\u6587\u6863\uFF0C\u6B63\u786E\u914D\u7F6E\u6A21\u5757\u7684 Hook \u5165\u53E3\u7C7B\u5305\u540D\u3002
IllegalStateException
YukiHookModulePrefs missing Context instance
\u5F02\u5E38\u539F\u56E0
\u5728\u6A21\u5757\u4E2D\u4F7F\u7528\u4E86 YukiHookModulePrefs
\u5B58\u50A8\u6570\u636E\u4F46\u5E76\u672A\u4F20\u5165 Context
\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // \u2757\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5
+ // \u6784\u9020\u65B9\u6CD5\u5DF2\u5728 API 1.0.88 \u53CA\u4EE5\u540E\u7684\u7248\u672C\u4E2D\u8BBE\u7F6E\u4E3A private
+ YukiHookModulePrefs().getBoolean("test_data")
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u5728 Activity
\u4E2D\u63A8\u8350\u4F7F\u7528 modulePrefs
\u65B9\u6CD5\u6765\u88C5\u8F7D YukiHookModulePrefs
\u3002
\u793A\u4F8B\u5982\u4E0B
class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5
+ modulePrefs.getBoolean("test_data")
+ }
+}
+
IllegalStateException
Key-Value type TYPE is not allowed
\u5F02\u5E38\u539F\u56E0
\u5728\u4F7F\u7528 YukiHookModulePrefs
\u7684 get
\u6216 put
\u65B9\u6CD5\u6216 YukiHookDataChannel
\u7684 wait
\u6216 put
\u65B9\u6CD5\u65F6\u4F20\u5165\u4E86\u4E0D\u652F\u6301\u7684\u5B58\u50A8\u7C7B\u578B\u3002
\u89E3\u51B3\u65B9\u6848
YukiHookModulePrefs
\u652F\u6301\u7684\u7C7B\u578B\u53EA\u6709 String
\u3001Set<String>
\u3001Int
\u3001Float
\u3001Long
\u3001Boolean
\uFF0C\u8BF7\u4F20\u5165\u652F\u6301\u7684\u7C7B\u578B\u3002
YukiHookDataChannel
\u652F\u6301\u7684\u7C7B\u578B\u4E3A Intent.putExtra
\u9650\u5236\u7684\u7C7B\u578B\uFF0C\u8BF7\u4F20\u5165\u652F\u6301\u7684\u7C7B\u578B\u3002
IllegalStateException
YukiHookDataChannel cannot used in zygote
\u5F02\u5E38\u539F\u56E0
\u5728 loadZygote
\u4E2D\u4F7F\u7528\u4E86 YukiHookDataChannel
\u3002
\u793A\u4F8B\u5982\u4E0B
loadZygote {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ dataChannel...
+}
+
\u89E3\u51B3\u65B9\u6848
YukiHookDataChannel
\u53EA\u80FD\u5728 loadSystem
\u3001loadApp
\u4E2D\u4F7F\u7528\u3002
IllegalStateException
Custom Hooking Members is empty
\u5F02\u5E38\u539F\u56E0
\u5728 MemberHookCreator
\u4E2D\u8C03\u7528 members()
\u4F46\u662F\u672A\u8BBE\u7F6E\u9700\u8981 Hook \u7684 Member
\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // \u62EC\u53F7\u91CC\u7684\u65B9\u6CD5\u53C2\u6570\u88AB\u7559\u7A7A\u4E86
+ members()
+ afterHook {
+ // ...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u82E5\u8981\u4F7F\u7528 members()
\u8BBE\u7F6E\u81EA\u5B9A\u4E49 Hook \u65B9\u6CD5\uFF0C\u4F60\u5FC5\u987B\u4FDD\u8BC1\u5176\u65B9\u6CD5\u53C2\u6570\u91CC\u7684 Member
\u6570\u7EC4\u5BF9\u8C61\u4E0D\u80FD\u4E3A\u7A7A\u3002
IllegalStateException
HookParam Method args index must be >= 0
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 args().last()
\u4F46\u662F\u76EE\u6807 param
\u4E3A\u7A7A\u6216 args
\u4E2D\u7684 index
\u8BBE\u7F6E\u4E86\u5C0F\u4E8E 0 \u7684\u6570\u503C\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u5047\u8BBE param \u662F\u7A7A\u7684
+ args().last()...
+ // \u8BBE\u7F6E\u4E86\u5C0F\u4E8E 0 \u7684 index
+ args(index = -5)...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60 Hook \u7684\u76EE\u6807\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u65B9\u6CD5\u53C2\u6570\u6570\u91CF\u662F\u5426\u4E0D\u4E3A\u7A7A\uFF0C\u4E14\u4E0D\u80FD\u5BF9 args
\u7684\u4E0B\u6807\u8BBE\u7F6E\u5C0F\u4E8E 0 \u7684\u6570\u503C\u3002
IllegalStateException
HookParam instance got null! Is this a static member?
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 instance
\u53D8\u91CF\u6216 instance
\u65B9\u6CD5\u4F46\u83B7\u53D6\u4E0D\u5230\u5F53\u524D\u5B9E\u4F8B\u7684\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ instance...
+ // \u8C03\u7528\u4E86\u6B64\u65B9\u6CD5
+ instance<Any>()...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60 Hook \u7684\u65B9\u6CD5\u662F\u5426\u4E3A\u9759\u6001\u7C7B\u578B\uFF0C\u9759\u6001\u7C7B\u578B\u7684\u65B9\u6CD5\u6CA1\u6709\u5B9E\u4F8B\uFF0C\u4E0D\u80FD\u4F7F\u7528\u6B64\u529F\u80FD\uFF0C\u82E5\u975E\u9759\u6001\u65B9\u6CD5\uFF0C\u8BF7\u68C0\u67E5\u5B9E\u4F8B\u662F\u5426\u5DF2\u7ECF\u9500\u6BC1\u3002
IllegalStateException
Current hooked Member args is null
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 args
\u53D8\u91CF\u4F46\u83B7\u53D6\u4E0D\u5230\u5F53\u524D\u5B9E\u4F8B\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u53C2\u6570\u6570\u7EC4\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ args...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u79CD\u95EE\u9898\u4E00\u822C\u4E0D\u4F1A\u53D1\u751F\uFF0C\u771F\u7684\u53D1\u751F\u4E86\u6B64\u95EE\u9898\uFF0C\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
IllegalStateException
Current hooked Member is null
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 member
\u53D8\u91CF\u4F46\u83B7\u53D6\u4E0D\u5230\u5F53\u524D\u5B9E\u4F8B\u7684\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ member...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u79CD\u95EE\u9898\u4E00\u822C\u4E0D\u4F1A\u53D1\u751F\uFF0C\u771F\u7684\u53D1\u751F\u4E86\u6B64\u95EE\u9898\uFF0C\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
IllegalStateException
Current hooked Member is not a Method
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 method
\u53D8\u91CF\u4F46\u83B7\u53D6\u4E0D\u5230\u5F53\u524D\u5B9E\u4F8B\u7684\u65B9\u6CD5\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ method...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60 Hook \u7684\u65B9\u6CD5\u662F\u6784\u9020\u65B9\u6CD5\u8FD8\u662F\u666E\u901A\u65B9\u6CD5\u5E76\u4F7F\u7528\u5BF9\u5E94\u7C7B\u578B\u7684\u65B9\u6CD5\u83B7\u53D6\u6307\u5B9A\u7684\u5B9E\u4F8B\uFF0C\u82E5\u4E0D\u77E5\u9053\u5B57\u8282\u7801\u7684\u7C7B\u578B\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 member
\u6765\u83B7\u53D6\u3002
IllegalStateException
Current hooked Member is not a Constructor
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 constructor
\u53D8\u91CF\u4F46\u83B7\u53D6\u4E0D\u5230\u5F53\u524D\u5B9E\u4F8B\u7684\u65B9\u6CD5\u5B9E\u4F8B\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ constructor...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60 Hook \u7684\u65B9\u6CD5\u662F\u666E\u901A\u65B9\u6CD5\u8FD8\u662F\u6784\u9020\u65B9\u6CD5\u5E76\u4F7F\u7528\u5BF9\u5E94\u7C7B\u578B\u7684\u65B9\u6CD5\u83B7\u53D6\u6307\u5B9A\u7684\u5B9E\u4F8B\uFF0C\u82E5\u4E0D\u77E5\u9053\u5B57\u8282\u7801\u7684\u7C7B\u578B\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 member
\u6765\u83B7\u53D6\u3002
IllegalStateException
HookParam instance cannot cast to TYPE
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 instance
\u65B9\u6CD5\u6307\u5B9A\u4E86\u9519\u8BEF\u7684\u7C7B\u578B\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u7C7B\u578B\u88AB cast \u4E3A Activity \u4F46\u5047\u8BBE\u5F53\u524D\u5B9E\u4F8B\u7684\u7C7B\u578B\u5E76\u975E\u6B64\u7C7B\u578B
+ instance<Activity>()...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u6B63\u786E\u7C7B\u578B\u5E76\u91CD\u65B0\u586B\u5199\u6CDB\u578B\u4E2D\u7684\u7C7B\u578B\uFF0C\u82E5\u4E0D\u80FD\u786E\u5B9A\u8BF7\u4F7F\u7528 Any
\u6216\u76F4\u63A5\u4F7F\u7528 instance
\u53D8\u91CF\u3002
IllegalStateException
HookParam Method args is empty, mabe not has args
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 ArgsModifyer.set
\u65B9\u6CD5\u4F46\u662F\u5F53\u524D\u5B9E\u4F8B\u7684\u65B9\u6CD5\u53C2\u6570\u6570\u7EC4\u4E3A\u7A7A\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u8C03\u7528\u4E86\u6B64\u65B9\u6CD5
+ args(...).set(...)
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60 Hook \u7684\u76EE\u6807\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u65B9\u6CD5\u53C2\u6570\u6570\u91CF\u662F\u5426\u4E0D\u4E3A\u7A7A\uFF0C\u5426\u5219\u4F60\u65E0\u6CD5\u4F7F\u7528\u6B64\u529F\u80FD\u3002
IllegalStateException
HookParam Method args index out of bounds, max is NUMBER
\u5F02\u5E38\u539F\u56E0
\u5728 HookParam
\u4E2D\u8C03\u7528 ArgsModifyer.set
\u65B9\u6CD5\u6307\u5B9A\u4E86\u8D85\u51FA\u65B9\u6CD5\u53C2\u6570\u4E0B\u6807\u7684\u6570\u7EC4\u5E8F\u53F7\u3002
\u793A\u4F8B\u5982\u4E0B
injectMember {
+ // ...
+ afterHook {
+ // \u4E0B\u6807\u4ECE 0 \u5F00\u59CB\uFF0C\u5047\u8BBE\u539F\u59CB\u7684\u53C2\u6570\u4E0B\u6807\u662F 5 \u4E2A\uFF0C\u4F46\u662F\u8FD9\u91CC\u586B\u5199\u4E86 6
+ args(index = 6).set(...)
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8BF7\u786E\u8BA4\u4F60 Hook \u7684\u76EE\u6807\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u7684\u65B9\u6CD5\u53C2\u6570\u4E2A\u6570\uFF0C\u5E76\u91CD\u65B0\u8BBE\u7F6E\u6570\u7EC4\u4E0B\u6807\u3002
IllegalStateException
PackageParam got null ClassLoader
\u5F02\u5E38\u539F\u56E0
\u5728 PackageParam
\u4E2D\u8C03\u7528\u4E86 appClassLoader
\u53D8\u91CF\u4F46\u662F\u65E0\u6CD5\u83B7\u53D6\u5230\u5B9E\u4F8B\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
encase {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ appClassLoader...
+}
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u79CD\u60C5\u51B5\u51E0\u4E4E\u4E0D\u5B58\u5728\uFF0C\u9664\u975E\u6A21\u5757\u88AB\u88C5\u8F7D\u7684\u5BBF\u4E3B\u6216\u76EE\u6807 Hook Framework \u81EA\u8EAB\u5B58\u5728\u95EE\u9898\uFF0C\u82E5\u771F\u7684\u53D1\u751F\u4E86\u6B64\u95EE\u9898\uFF0C\u8BF7\u643A\u5E26\u8BE6\u7EC6\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
IllegalStateException
Current Hook Framework not support moduleAppResources
\u5F02\u5E38\u539F\u56E0
\u5728 PackageParam
\u4E2D\u8C03\u7528\u4E86 moduleAppResources
\u53D8\u91CF\u4F46\u662F\u65E0\u6CD5\u83B7\u53D6\u5230\u5B9E\u4F8B\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
encase {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ moduleAppResources...
+}
+
\u89E3\u51B3\u65B9\u6848
moduleAppResources
\u9700\u8981\u5F53\u524D Hook Framework \u652F\u6301 initZygote
\u529F\u80FD\uFF0C\u8BF7\u68C0\u67E5\u540E\u518D\u8BD5\u4E00\u6B21\u3002
IllegalStateException
VariousClass match failed of those CLASSES
\u5F02\u5E38\u539F\u56E0
\u5728\u4F7F\u7528 VariousClass
\u521B\u5EFA\u4E0D\u786E\u5B9A\u7684 Class
\u5BF9\u8C61\u65F6\u5168\u90E8\u7684 Class
\u90FD\u6CA1\u6709\u88AB\u627E\u5230\u3002
\u89E3\u51B3\u65B9\u6848
\u68C0\u67E5\u5F53\u524D Hook \u7684\u5BBF\u4E3B\u5185\u662F\u5426\u5B58\u5728\u5176\u4E2D\u80FD\u591F\u5339\u914D\u7684 Class
\u540E\uFF0C\u518D\u8BD5\u4E00\u6B21\u3002
IllegalStateException
Cannot get hook class "NAME" cause THROWABLE
\u5F02\u5E38\u539F\u56E0
\u5728 hook
\u65B9\u6CD5\u4F53\u975E onPrepareHook
\u65B9\u6CD5\u5185\u8C03\u7528\u4E86 instanceClass
\u53D8\u91CF\u4E14\u5F53\u524D Hook \u7684 Class
\u4E0D\u5B58\u5728\u3002
\u793A\u4F8B\u5982\u4E0B
TargetClass.hook {
+ // \u53EF\u80FD\u7684\u60C5\u51B5\u4E3A\u5728\u975E onPrepareHook \u65B9\u6CD5\u4F53\u5185\u8C03\u7528\u4E86 instanceClass \u53D8\u91CF\u7528\u4E8E\u6253\u5370\u65E5\u5FD7
+ loggerD(msg = "$instanceClass hook start")
+}
+
\u89E3\u51B3\u65B9\u6848
\u5728 hook
\u5185\u76F4\u63A5\u4F7F\u7528 instanceClass
\u662F\u5F88\u5371\u9669\u7684\uFF0C\u82E5 Class \u4E0D\u5B58\u5728\u5219\u4F1A\u76F4\u63A5\u5BFC\u81F4 Hook \u8FDB\u7A0B\u201C\u6B7B\u6389\u201D\u3002
\u8BE6\u60C5\u8BF7\u53C2\u8003 \u72B6\u6001\u76D1\u542C\u3002
IllegalStateException
LayoutInflatedParam View instance got null
\u5F02\u5E38\u539F\u56E0
\u5728\u5E03\u5C40 Hook \u56DE\u8C03\u4E2D\u8C03\u7528\u4E86 currentView
\u4F46\u6CA1\u53D6\u5230\u5B9E\u4F8B\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ // \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+ currentView...
+ }
+}
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u79CD\u60C5\u51B5\u57FA\u672C\u4E0A\u4E0D\u5B58\u5728\uFF0C\u9664\u975E\u88AB Hook \u7684\u5BBF\u4E3B\u5F53\u524D Activity
\u5DF2\u7ECF\u9500\u6BC1\u6216 Hook Framework \u81EA\u8EAB\u5B58\u5728\u95EE\u9898\u3002
IllegalStateException
XResForwarder is invalid
\u5F02\u5E38\u539F\u56E0
\u5728 YukiResForwarder
\u4E2D\u8C03\u7528\u4E86 resources
\u4F46\u6CA1\u53D6\u5230\u5B9E\u4F8B\u5BF9\u8C61\u3002
\u793A\u4F8B\u5982\u4E0B
// \u8C03\u7528\u4E86\u6B64\u53D8\u91CF
+moduleAppResources.fwd(...).resources
+
\u89E3\u51B3\u65B9\u6848
\u8FD9\u79CD\u60C5\u51B5\u57FA\u672C\u4E0A\u4E0D\u5B58\u5728\uFF0C\u9664\u975E Hook Framework \u81EA\u8EAB\u5B58\u5728\u95EE\u9898\u3002
IllegalStateException
paramTypes is empty, please use emptyParam() instead
\u5F02\u5E38\u539F\u56E0
\u5728\u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u65F6\u4FDD\u7559\u4E86\u7A7A\u7684 param
\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
method {
+ name = "test"
+ // \u62EC\u53F7\u5185\u6CA1\u6709\u586B\u5199\u4EFB\u4F55\u53C2\u6570
+ param()
+}
+
\u89E3\u51B3\u65B9\u6848
\u82E5\u8981\u6807\u8BC6\u6B64\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u6CA1\u6709\u53C2\u6570\uFF0C\u4F60\u53EF\u4EE5\u6709\u5982\u4E0B\u8BBE\u7F6E\u65B9\u6CD5\u3002
\u7B2C\u4E00\u79CD\uFF0C\u8BBE\u7F6E emptyParam
(\u63A8\u8350)
\u793A\u4F8B\u5982\u4E0B
method {
+ name = "test"
+ emptyParam()
+}
+
\u7B2C\u4E8C\u79CD\uFF0C\u8BBE\u7F6E paramCount = 0
\u793A\u4F8B\u5982\u4E0B
method {
+ name = "test"
+ paramCount = 0
+}
+
IllegalStateException
Invalid YukiHookCallback type
\u5F02\u5E38\u539F\u56E0
YukiHookAPI
\u7684\u6838\u5FC3 Hook \u529F\u80FD\u53D1\u751F\u6545\u969C\u3002
\u89E3\u51B3\u65B9\u6848
\u8FD9\u79CD\u60C5\u51B5\u57FA\u672C\u4E0A\u4E0D\u5B58\u5728\uFF0C\u82E5\u53D1\u751F\u4E0A\u8FF0\u95EE\u9898\uFF0C\u786E\u5B9A\u5E76\u975E\u81EA\u5DF1\u7684\u4EE3\u7801\u53D1\u751F\u7684\u95EE\u9898\u540E\uFF0C\u53EF\u63D0\u4EA4\u65E5\u5FD7\u8FDB\u884C\u53CD\u9988\u3002
IllegalStateException
ModuleContextThemeWrapper already loaded
\u5F02\u5E38\u539F\u56E0
\u5728 Context
\u4E2D\u4F7F\u7528 applyModuleTheme
\u65B9\u6CD5\u65F6\u91CD\u590D\u8FDB\u884C\u8C03\u7528\u3002
\u793A\u4F8B\u5982\u4E0B
// \u5047\u8BBE\u8FD9\u5C31\u662F\u5F53\u524D\u7684 Context \u5BF9\u8C61
+context.applyModuleTheme(R.style.Theme_AppCompat).applyModuleTheme(R.style.Theme_AppCompat)
+
\u89E3\u51B3\u65B9\u6848
\u5728 Context
\u4E2D\u53EA\u80FD\u521B\u5EFA\u4E00\u6B21 ModuleContextThemeWrapper
\uFF0C\u8BF7\u68C0\u67E5\u4EE3\u7801\u662F\u5426\u6709\u5FAA\u73AF\u8C03\u7528\u95EE\u9898\u3002
IllegalStateException
Cannot create classes cache for "android", please remove "name" param
\u5F02\u5E38\u539F\u56E0
\u5728\u7CFB\u7EDF\u6846\u67B6 (android) \u5BBF\u4E3B\u4F7F\u7528\u4E86 DexClassFinder
\u7684\u7F13\u5B58\u529F\u80FD searchClass(name = ...)
\u3002
\u793A\u4F8B\u5982\u4E0B
loadSystem {
+ searchClass(name = "test") {
+ from(...)
+ // ...
+ }.get()
+}
+
\u89E3\u51B3\u65B9\u6848
\u7531\u4E8E\u7F13\u5B58\u4F1A\u5C06\u627E\u5230\u7684 Class
\u540D\u79F0\u5B58\u5165 SharedPreferences
\uFF0C\u4F46\u662F\u7CFB\u7EDF\u6846\u67B6\u4E0D\u5B58\u5728 data \u76EE\u5F55\uFF0C\u6240\u4EE5\u8BF7\u4E0D\u8981\u5728\u7CFB\u7EDF\u6846\u67B6\u4E2D\u4F7F\u7528\u6B64\u529F\u80FD\u3002
As a Hook API, it is usually used for Hook operations for hot updates or functional needs of its own app and product testing.
You just need to integrate the com.highcapable.yukihookapi:api
dependency.
Then please integrate the Hook Framework
dependencies used by your target.
Create your custom Application
.
Add YukiHookAPI.encase
method to attachBaseContext
.
The following example
class MyApplication : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ // Load Hook Framework
+ //
+ // Your code here.
+ //
+ // Configure YukiHookAPI
+ YukiHookApi.configs {
+ // Your code here.
+ }
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+ }
+}
+
In this way, you have completed the relevant configuration of the API.
You can click here to see the similarities, differences and caveats.
Notice
You can no longer wrap with loadApp and start writing your Hook code directly.
`,15),d={id:"pine",tabindex:"-1"},A=s("a",{class:"header-anchor",href:"#pine","aria-hidden":"true"},"#",-1),y=n(),u={href:"https://github.com/canyie/pine",target:"_blank",rel:"noopener noreferrer"},h=n("Pine"),C=o(`Here are some related ways of how to connect the
Hook Framework
with theYukiHookAPI
, which is widely used.
Required Xposed API dependencies
top.canyie.pine:xposed
The following example
override fun attachBaseContext(base: Context?) {
+ // Load Pine
+ PineConfig.debug = true
+ PineConfig.debuggable = BuildConfig.DEBUG
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
Required Xposed API dependencies
com.swift.sandhook:xposedcompat
orcom.swift.sandhook:xposedcompat_new
The following example
override fun attachBaseContext(base: Context?) {
+ // Load SandHook
+ SandHookConfig.DEBUG = BuildConfig.DEBUG
+ XposedCompat.cacheDir = base?.cacheDir
+ XposedCompat.context = base
+ XposedCompat.classLoader = javaClass.classLoader
+ XposedCompat.isFirstApplication = base?.processName == base?.packageName
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
The following example
override fun attachBaseContext(base: Context?) {
+ // Loading Whale does not require any configuration
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
\u4F5C\u4E3A Hook API \u901A\u5E38\u4E3A\u505A\u81EA\u8EAB APP \u70ED\u66F4\u65B0\u6216\u529F\u80FD\u9700\u8981\u4EE5\u53CA\u4EA7\u54C1\u6D4B\u8BD5\u7684 Hook \u64CD\u4F5C\u3002
\u4F60\u53EA\u9700\u8981\u96C6\u6210 com.highcapable.yukihookapi:api
\u4F9D\u8D56\u5373\u53EF\u3002
\u7136\u540E\u8BF7\u96C6\u6210\u4F60\u76EE\u6807\u4F7F\u7528\u7684 Hook Framework
\u4F9D\u8D56\u3002
\u521B\u5EFA\u4F60\u7684\u81EA\u5B9A\u4E49 Application
\u3002
\u5728 attachBaseContext
\u4E2D\u6DFB\u52A0 YukiHookAPI.encase
\u65B9\u6CD5\u3002
\u793A\u4F8B\u5982\u4E0B
class MyApplication : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ // \u88C5\u8F7D Hook Framework
+ //
+ // Your code here.
+ //
+ // \u914D\u7F6E YukiHookAPI
+ YukiHookApi.configs {
+ // Your code here.
+ }
+ // \u88C5\u8F7D YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+ }
+}
+
\u8FD9\u6837\uFF0C\u4F60\u5C31\u5B8C\u6210\u4E86 API \u7684\u76F8\u5173\u914D\u7F6E\u3002
\u4F60\u53EF\u4EE5 \u70B9\u51FB\u8FD9\u91CC \u67E5\u770B\u5F02\u540C\u70B9\u548C\u6CE8\u610F\u4E8B\u9879\u3002
\u6CE8\u610F
\u4F60\u4E0D\u80FD\u518D\u4F7F\u7528 loadApp \u8FDB\u884C\u5305\u88C5\uFF0C\u53EF\u76F4\u63A5\u5F00\u59CB\u7F16\u5199\u4F60\u7684 Hook \u4EE3\u7801\u3002
`,15),d={id:"pine",tabindex:"-1"},A=s("a",{class:"header-anchor",href:"#pine","aria-hidden":"true"},"#",-1),y=n(),u={href:"https://github.com/canyie/pine",target:"_blank",rel:"noopener noreferrer"},B=n("Pine"),C=o(`\u8FD9\u91CC\u7ED9\u51FA\u4E86\u4E00\u4E9B\u8F83\u9AD8\u4F7F\u7528\u7387\u7684
Hook Framework
\u5982\u4F55\u5BF9\u63A5YukiHookAPI
\u7684\u76F8\u5173\u65B9\u5F0F\u3002
\u6240\u9700 Xposed API \u4F9D\u8D56
top.canyie.pine:xposed
\u793A\u4F8B\u5982\u4E0B
override fun attachBaseContext(base: Context?) {
+ // \u88C5\u8F7D Pine
+ PineConfig.debug = true
+ PineConfig.debuggable = BuildConfig.DEBUG
+ // \u88C5\u8F7D YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
\u6240\u9700 Xposed API \u4F9D\u8D56
com.swift.sandhook:xposedcompat
\u6216com.swift.sandhook:xposedcompat_new
\u793A\u4F8B\u5982\u4E0B
override fun attachBaseContext(base: Context?) {
+ // \u88C5\u8F7D SandHook
+ SandHookConfig.DEBUG = BuildConfig.DEBUG
+ XposedCompat.cacheDir = base?.cacheDir
+ XposedCompat.context = base
+ XposedCompat.classLoader = javaClass.classLoader
+ XposedCompat.isFirstApplication = base?.processName == base?.packageName
+ // \u88C5\u8F7D YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
\u793A\u4F8B\u5982\u4E0B
override fun attachBaseContext(base: Context?) {
+ // \u88C5\u8F7D Whale \u4E0D\u9700\u8981\u4EFB\u4F55\u914D\u7F6E
+ // \u88C5\u8F7D YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
-1||de(g,"default"))&&a.push(p)}}}const c=[r,a];return i.set(e,c),c}function cn(e){return e[0]!=="$"}function hn(e){const t=e&&e.toString().match(/^\s*function (\w+)/);return t?t[1]:e===null?"null":""}function dn(e,t){return hn(e)===hn(t)}function un(e,t){return te(t)?t.findIndex(l=>dn(l,e)):re(t)&&dn(t,e)?0:-1}const ea=e=>e[0]==="_"||e==="$stable",To=e=>te(e)?e.map(ot):[ot(e)],Ac=(e,t,l)=>{if(t._n)return t;const i=Me((...o)=>To(t(...o)),l);return i._c=!1,i},ta=(e,t,l)=>{const i=e._ctx;for(const o in e){if(ea(o))continue;const n=e[o];if(re(n))t[o]=Ac(o,n,i);else if(n!=null){const r=To(n);t[o]=()=>r}}},la=(e,t)=>{const l=To(t);e.slots.default=()=>l},Tc=(e,t)=>{if(e.vnode.shapeFlag&32){const l=t._;l?(e.slots=ke(t),ni(t,"_",l)):ta(t,e.slots={})}else e.slots={},t&&la(e,t);ni(e.slots,Ai,1)},Ic=(e,t,l)=>{const{vnode:i,slots:o}=e;let n=!0,r=Re;if(i.shapeFlag&32){const a=t._;a?l&&a===1?n=!1:(Se(o,t),!l&&a===1&&delete o._):(n=!t.$stable,ta(t,o)),r=t}else t&&(la(e,t),r={default:1});if(n)for(const a in o)!ea(a)&&!(a in r)&&delete o[a]};function ia(){return{app:null,config:{isNativeTag:rs,performance:!1,globalProperties:{},optionMergeStrategies:{},errorHandler:void 0,warnHandler:void 0,compilerOptions:{}},mixins:[],components:{},directives:{},provides:Object.create(null),optionsCache:new WeakMap,propsCache:new WeakMap,emitsCache:new WeakMap}}let wc=0;function Oc(e,t){return function(i,o=null){re(i)||(i=Object.assign({},i)),o!=null&&!Oe(o)&&(o=null);const n=ia(),r=new Set;let a=!1;const s=n.app={_uid:wc++,_component:i,_props:o,_container:null,_context:n,_instance:null,version:Qc,get config(){return n.config},set config(c){},use(c,...h){return r.has(c)||(c&&re(c.install)?(r.add(c),c.install(s,...h)):re(c)&&(r.add(c),c(s,...h))),s},mixin(c){return n.mixins.includes(c)||n.mixins.push(c),s},component(c,h){return h?(n.components[c]=h,s):n.components[c]},directive(c,h){return h?(n.directives[c]=h,s):n.directives[c]},mount(c,h,p){if(!a){const m=oe(i,o);return m.appContext=n,h&&t?t(m,c):e(m,c,p),a=!0,s._container=c,c.__vue_app__=s,Ti(m.component)||m.component.proxy}},unmount(){a&&(e(null,s._container),delete s._container.__vue_app__)},provide(c,h){return n.provides[c]=h,s}};return s}}function ui(e,t,l,i,o=!1){if(te(e)){e.forEach((m,g)=>ui(m,t&&(te(t)?t[g]:t),l,i,o));return}if(cl(i)&&!o)return;const n=i.shapeFlag&4?Ti(i.component)||i.component.proxy:i.el,r=o?null:n,{i:a,r:s}=e,c=t&&t.r,h=a.refs===Re?a.refs={}:a.refs,p=a.setupState;if(c!=null&&c!==s&&(be(c)?(h[c]=null,de(p,c)&&(p[c]=null)):De(c)&&(c.value=null)),re(s))wt(s,a,12,[r,h]);else{const m=be(s),g=De(s);if(m||g){const x=()=>{if(e.f){const P=m?h[s]:s.value;o?te(P)&&go(P,n):te(P)?P.includes(n)||P.push(n):m?(h[s]=[n],de(p,s)&&(p[s]=h[s])):(s.value=[n],e.k&&(h[e.k]=s.value))}else m?(h[s]=r,de(p,s)&&(p[s]=r)):g&&(s.value=r,e.k&&(h[e.k]=r))};r?(x.id=-1,Be(x,l)):x()}}}let Et=!1;const Zl=e=>/svg/.test(e.namespaceURI)&&e.tagName!=="foreignObject",Jl=e=>e.nodeType===8;function Fc(e){const{mt:t,p:l,o:{patchProp:i,createText:o,nextSibling:n,parentNode:r,remove:a,insert:s,createComment:c}}=e,h=(k,b)=>{if(!b.hasChildNodes()){l(null,k,b),ai(),b._vnode=k;return}Et=!1,p(b.firstChild,k,null,null,null),ai(),b._vnode=k,Et&&console.error("Hydration completed but contains mismatches.")},p=(k,b,L,M,U,ee=!1)=>{const w=Jl(k)&&k.data==="[",v=()=>P(k,b,L,M,U,w),{type:q,ref:B,shapeFlag:G,patchFlag:R}=b,S=k.nodeType;b.el=k,R===-2&&(ee=!1,b.dynamicChildren=null);let F=null;switch(q){case Dl:S!==3?b.children===""?(s(b.el=o(""),r(k),k),F=k):F=v():(k.data!==b.children&&(Et=!0,k.data=b.children),F=n(k));break;case Ge:S!==8||w?F=v():F=n(k);break;case Ll:if(S!==1&&S!==3)F=v();else{F=k;const ae=!b.children.length;for(let j=0;j The version update history of Pay Attention We will only maintain the latest API version, if you are using an outdate API version, you voluntarily renounce any possibility of maintenance. Notice To avoid translation time consumption, Changelog will use Google Translation from Chinese to English, please refer to the original text for actual reference. Time zone of version release date: UTC+8 \u8FD9\u91CC\u4ECB\u7ECD\u4E86 \u4E0B\u65B9\u7684\u7ED3\u6784\u63CF\u8FF0\u4E86 \u4E0A\u65B9\u7684\u7ED3\u6784\u6362\u505A\u4EE3\u7801\u5C06\u53EF\u5199\u4E3A\u5982\u4E0B\u5F62\u5F0F\u3002 \u4F60\u53EF\u4EE5\u5728\u4E0B\u65B9\u627E\u5230 API \u63D0\u4F9B\u7684 Demo \u6765\u5B66\u4E60 \u540C\u65F6\u5B89\u88C5\u5BBF\u4E3B\u548C\u6A21\u5757 Demo\uFF0C\u901A\u8FC7\u6FC0\u6D3B\u6A21\u5757\u6765\u6D4B\u8BD5\u5BBF\u4E3B\u4E2D\u88AB Hook \u7684\u529F\u80FD\u3002 \u8FD9\u91CC\u7ED9\u51FA\u4E86 Hook APP\u3001Hook \u7CFB\u7EDF\u6846\u67B6\u4E0E Hook Resources \u7B49\u4F8B\u5B50\uFF0C\u53EF\u4F9B\u53C2\u8003\u3002 \u5047\u8BBE\uFF0C\u6211\u4EEC\u8981 Hook \u5728 \u793A\u4F8B\u5982\u4E0B \u81F3\u6B64\uFF0C \u90A3\u4E48\uFF0C\u6211\u60F3\u7EE7\u7EED Hook \u5728\u521A\u521A\u7684\u4EE3\u7801\u4E2D\uFF0C\u7EE7\u7EED\u63D2\u5165\u4E00\u4E2A \u793A\u4F8B\u5982\u4E0B \u5BF9\u4E8E\u5F53\u524D\u9879\u76EE\u4E0B\u6CA1\u6709\u7684 \u6BD4\u5982\uFF0C\u6211\u8981\u5F97\u5230 \u793A\u4F8B\u5982\u4E0B \u82E5 \u793A\u4F8B\u5982\u4E0B \u5230\u8FD9\u91CC\u6709\u4E9B\u540C\u5B66\u53EF\u80FD\u5C31\u5F00\u59CB\u8BF4\u4E86\uFF0C\u5728\u67D0\u4E9B\u573A\u666F\u4E0B \u56E0\u4E3A\u53EF\u80FD\u6709\u4E9B\u540C\u5B66\u6709\u5982\u4E0B\u9700\u6C42\u3002 \u793A\u4F8B\u5982\u4E0B \u6CA1\u5173\u7CFB\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528\u5B57\u7B26\u4E32\u7C7B\u540D\u76F4\u63A5\u521B\u5EFA\u4E00\u4E2A Hook\u3002 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MemberHookCreator\u3002 \u5728 APP \u542F\u52A8\u65F6\uFF0C\u65B0\u7684\u8FDB\u7A0B\u88AB fork \u540E\u7684\u7B2C\u4E00\u4E2A\u4E8B\u4EF6 \u5047\u8BBE\u6211\u4EEC\u8981\u5168\u5C40 Hook \u4E00\u4E2A APP \u5728 \u793A\u4F8B\u5982\u4E0B \u6CE8\u610F \u5728 loadZygote \u4E2D\u8FDB\u884C\u7684\u529F\u80FD\u5341\u5206\u6709\u9650\uFF0C\u51E0\u4E4E\u5F88\u5C11\u7684\u60C5\u51B5\u4E0B\u9700\u8981\u7528\u5230 loadZygote \u65B9\u6CD5\u3002 \u5728 \u5047\u8BBE\uFF0C\u4F60\u8981\u5F97\u5230 \u5728 \u793A\u4F8B\u5982\u4E0B \u7279\u522B\u6CE8\u610F loadZygote \u4E0E loadSystem \u6709\u76F4\u63A5\u6027\u533A\u522B\uFF0CloadZygote \u4F1A\u5728 initZygote \u4E2D\u88C5\u8F7D\uFF0C\u7CFB\u7EDF\u6846\u67B6\u88AB\u89C6\u4E3A loadApp(name = "android") \u800C\u5B58\u5728\uFF0C\u82E5\u8981 Hook \u7CFB\u7EDF\u6846\u67B6\uFF0C\u53EF\u76F4\u63A5\u4F7F\u7528 loadSystem\u3002 \u5047\u8BBE\uFF0C\u6211\u4EEC\u8981 Hook \u5728 \u793A\u4F8B\u5982\u4E0B \u82E5\u5F53\u524D APP \u4F7F\u7528 \u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528\u5F53\u524D Xposed \u6A21\u5757\u7684 Resources \u66FF\u6362 Hook APP \u7684 Resources\u3002 \u5047\u8BBE\uFF0C\u6211\u4EEC\u8981\u7EE7\u7EED Hook \u793A\u4F8B\u5982\u4E0B \u81F3\u6B64\u76EE\u6807 APP \u7684\u56FE\u6807\u5C06\u4F1A\u88AB\u66FF\u6362\u4E3A\u6211\u4EEC\u8BBE\u7F6E\u7684\u56FE\u6807\u3002 \u82E5\u4F60\u60F3\u66FF\u6362\u7CFB\u7EDF\u6846\u67B6\u7684\u8D44\u6E90\uFF0C\u540C\u6837\u4E5F\u53EF\u4EE5\u8FD9\u6837\u5B9E\u73B0\uFF0C\u53EA\u9700\u8981\u628A \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ResourcesHookCreator\u3002 \u539F\u751F\u7684 Xposed \u4E3A\u6211\u4EEC\u63D0\u4F9B\u4E86\u4E00\u4E2A \u7B2C\u4E00\u79CD\u65B9\u6CD5\uFF0C\u4FDD\u5B58\u5F53\u524D\u6CE8\u5165\u5BF9\u8C61\u7684 \u793A\u4F8B\u5982\u4E0B \u7B2C\u4E8C\u79CD\u65B9\u6CD5\uFF0C\u5728 Hook \u56DE\u8C03\u65B9\u6CD5\u4E2D\u8C03\u7528 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MemberHookCreator\u3002 \u4F60\u53EF\u4EE5\u5904\u7406 Hook \u65B9\u6CD5\u8FC7\u7A0B\u53D1\u751F\u7684\u5F02\u5E38\u3002 \u793A\u4F8B\u5982\u4E0B \u5728 Resources Hook \u65F6\u6B64\u65B9\u6CD5\u540C\u6837\u9002\u7528\u3002 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u5904\u7406 Hook \u7684 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u5904\u7406\u67E5\u627E\u65B9\u6CD5\u65F6\u7684\u5F02\u5E38\u3002 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MemberHookCreator.Result\u3001ResourcesHookCreator.Result\u3002 \u8FD9\u91CC\u4ECB\u7ECD\u4E86\u53EF\u80FD\u53D1\u751F\u7684\u5E38\u89C1\u5F02\u5E38\uFF0C\u82E5\u8981\u4E86\u89E3\u66F4\u591A\u8BF7\u53C2\u8003 API \u5F02\u5E38\u5904\u7406\u3002 \u5728\u67D0\u4E9B\u60C5\u51B5\u4E0B\uFF0C\u4F60\u53EF\u4EE5\u624B\u52A8\u629B\u51FA\u5F02\u5E38\u6765\u8FBE\u5230\u63D0\u9192\u67D0\u4E9B\u529F\u80FD\u5B58\u5728\u95EE\u9898\u7684\u76EE\u7684\u3002 \u4E0A\u9762\u5DF2\u7ECF\u4ECB\u7ECD\u8FC7\uFF0C\u5728 \u4EE5\u4E0B\u662F \u793A\u4F8B\u5982\u4E0B \u4EE5\u4E0A\u60C5\u666F\u53EA\u4F1A\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u88AB\u5904\u7406\uFF0C\u4E0D\u4F1A\u5BF9\u5BBF\u4E3B\u81EA\u8EAB\u9020\u6210\u4EFB\u4F55\u5F71\u54CD\u3002 \u82E5\u6211\u4EEC\u60F3\u5C06\u8FD9\u4E9B\u5F02\u5E38\u76F4\u63A5\u629B\u7ED9\u5BBF\u4E3B\uFF0C\u539F\u751F\u7684 Xposed \u4E3A\u6211\u4EEC\u63D0\u4F9B\u4E86 \u82E5\u60F3\u5728 Hook \u56DE\u8C03\u65B9\u6CD5\u4F53\u4E2D\u5C06\u4E00\u4E2A\u5F02\u5E38\u76F4\u63A5\u629B\u7ED9\u5BBF\u4E3B\uFF0C\u53EF\u4EE5\u6709\u5982\u4E0B\u5B9E\u73B0\u65B9\u6CD5\u3002 \u793A\u4F8B\u5982\u4E0B \u4F60\u4E5F\u53EF\u4EE5\u76F4\u63A5\u5728 Hook \u56DE\u8C03\u65B9\u6CD5\u4F53\u4E2D\u629B\u51FA\u5F02\u5E38\uFF0C\u7136\u540E\u6807\u8BC6\u5C06\u5F02\u5E38\u629B\u7ED9\u5BBF\u4E3B\u3002 \u793A\u4F8B\u5982\u4E0B \u4EE5\u4E0A\u4E24\u79CD\u65B9\u6CD5\u5747\u53EF\u5728\u5BBF\u4E3B\u63A5\u6536\u5230\u5F02\u5E38\u4ECE\u800C\u4F7F\u5BBF\u4E3B\u8FDB\u7A0B\u5D29\u6E83\u3002 \u6CE8\u610F \u4E3A\u4E86\u4FDD\u8BC1 Hook \u8C03\u7528\u57DF\u4E0E\u5BBF\u4E3B\u5185\u8C03\u7528\u57DF\u76F8\u4E92\u9694\u79BB\uFF0C\u5F02\u5E38\u53EA\u6709\u5728 beforeHook \u4E0E afterHook \u56DE\u8C03\u65B9\u6CD5\u4F53\u4E2D\u624D\u80FD\u629B\u7ED9\u5BBF\u4E3B\u3002 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 Throwable.throwToApp\u3001YukiMemberHookCreator.MemberMookCreator.HookCallback\u3002 \u5728\u4F7F\u7528 \u5728 \u9996\u5148\u6211\u4EEC\u53EF\u4EE5\u76D1\u542C Hook \u5DF2\u7ECF\u51C6\u5907\u5F00\u59CB\u3002 \u793A\u4F8B\u5982\u4E0B \u7279\u522B\u6CE8\u610F instanceClass \u5EFA\u8BAE\u53EA\u5728 onPrepareHook \u4E2D\u4F7F\u7528\uFF0C\u5426\u5219\u88AB Hook \u7684 Class \u4E0D\u5B58\u5728\u4F1A\u629B\u51FA\u65E0\u6CD5\u62E6\u622A\u7684\u5F02\u5E38\u5BFC\u81F4 Hook \u8FDB\u7A0B\u201C\u6B7B\u6389\u201D\u3002 \u7136\u540E\uFF0C\u6211\u4EEC\u8FD8\u53EF\u4EE5\u5BF9 Hook \u7684\u65B9\u6CD5\u7ED3\u679C\u8FDB\u884C\u76D1\u542C\u662F\u5426\u6210\u529F\u3002 \u793A\u4F8B\u5982\u4E0B \u4F60\u53EF\u4EE5\u5728 Hook \u8FC7\u7A0B\u4E2D\u4F7F\u7528\u4E0B\u9762\u7684\u65B9\u6CD5\u65B9\u4FBF\u5730\u5B9E\u73B0\u5404\u79CD\u5224\u65AD\u548C\u529F\u80FD\u3002 \u5982\u679C\u4F60\u7684\u6A21\u5757\u9700\u8981\u540C\u65F6\u5904\u7406\u591A\u4E2A APP \u7684 Hook \u4E8B\u4EF6\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 PackageParam.loadApp\u3002 \u5982\u679C\u4F60 Hook \u7684\u5BBF\u4E3B APP \u6709\u591A\u4E2A\u8FDB\u7A0B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 PackageParam.withProcess\u3002 \u4E3A\u4E86\u4F7F\u4EE3\u7801\u66F4\u52A0\u7B80\u6D01\uFF0C\u4F60\u53EF\u4EE5\u5220\u53BB \u793A\u4F8B\u5982\u4E0B \u901A\u5E38\u60C5\u51B5\u4E0B\uFF0C\u6211\u4EEC\u4F1A\u9009\u62E9\u5199\u4E00\u4E2A\u65B9\u6CD5\uFF0C\u4F7F\u5176\u8FD4\u56DE \u5728 \u73B0\u5728\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u7531\u4E8E\u4E00\u4E9B\u7279\u6B8A\u539F\u56E0\uFF0C\u5728\u592A\u6781\u3001\u65E0\u6781\u4E2D\u7684\u6A21\u5757\u65E0\u6CD5\u4F7F\u7528\u6807\u51C6\u65B9\u6CD5\u68C0\u6D4B\u6FC0\u6D3B\u72B6\u6001\u3002 \u6B64\u65F6\u4F60\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u82E5\u4F60\u60F3\u4F7F\u7528\u4E24\u8005\u5F97\u517C\u7684\u5224\u65AD\u65B9\u6848\uFF0C \u6B64\u65F6\u4F60\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiHookAPI.Status\u3002 \u6CE8\u610F \u82E5\u6A21\u5757\u6FC0\u6D3B\u5224\u65AD\u4E2D\u5305\u542B\u592A\u6781\u3001\u65E0\u6781\u4E2D\u7684\u6FC0\u6D3B\u72B6\u6001\uFF0C\u5C31\u5FC5\u987B\u5C06\u6A21\u5757\u7684 Application \u7EE7\u627F\u4E8E ModuleApplication \u6216\u76F4\u63A5\u4F7F\u7528 ModuleApplication\uFF1B 1.0.91 \u7248\u672C\u540E\u7684 API \u4FEE\u6539\u4E86\u6FC0\u6D3B\u903B\u8F91\u5224\u65AD\u65B9\u5F0F\uFF0C\u73B0\u5728\u4F60\u53EF\u4EE5\u5728\u6A21\u5757\u4E0E Hook APP (\u5BBF\u4E3B) \u4E2D\u540C\u65F6\u4F7F\u7528\u6B64 API\uFF1B \u9700\u8981\u786E\u4FDD YukiHookAPI.Configs.isEnableHookModuleStatus \u662F\u542F\u7528\u72B6\u6001\uFF1B \u9664\u4E86\u63D0\u4F9B\u6807\u51C6 API \u7684 Hook \u6846\u67B6\u4E4B\u5916\uFF0C\u5176\u5B83\u60C5\u51B5\u4E0B\u6A21\u5757\u53EF\u80FD\u90FD\u5C06\u65E0\u6CD5\u5224\u65AD\u81EA\u5DF1\u662F\u5426\u88AB\u6FC0\u6D3B\u3002 Here is an introduction to the basic working method of The structure below describes the basic working and principle of The above structure can be written in the following form in code. You can find the demo provided by the API below to learn how to use Install the Host App and Module App Demo at the same time, and test the hooked function in the Host App by activating the Module App. Here are examples of Hook App, Hook System Framework and Hook Resources for reference. Suppose, we want to hook the Add code in the body of the The following example At this point, the So, what should I do if I want to continue the Hook In the code just now, continue to insert an The following example For the For example, I want to get The following example If The following example Some people may have started to say that Because some people may have the following needs. The following example That's okay, you can also create a Hook directly using the string class name. The following example Tips For more functions, please refer to MemberHookCreator. The first event Suppose we want to globally Hook the Add code in the body of the The following example Notice The functionality performed in loadZygote is very limited, and the loadZygote method is rarely needed. In Suppose, you want to get Add code in the body of the The following example Pay Attention loadZygote is directly different from loadSystem, loadZygote will be loaded in initZygote, and the System Framework is regarded as loadApp(name = "android") and exists, To Hook the System Framework, you can use loadSystem directly. Suppose, we want to replace the content of Add code in the body of the The following example If the current app has a title bar text set with You can also replace the Hook App's Resources with the current Xposed Module's Resources. Suppose, we want to continue to hook The following example At this point, the icon of the target app will be replaced with the icon we set. If you want to replace the Resources of the System Framework, you can do the same, just replace The following example Tips For more functions, please refer to ResourcesHookCreator. The native Xposed provides us with a The first way, save the The following example The second method, call The following example Tips For more functions, please refer to MemberHookCreator. You can handle exceptions that occur during the Hook method. The following example This method also works in the Resources Hook. The following example You can also handle exceptions that occur when the Hook's The following example You can also handle exceptions when looking up methods. The following example Tips For more functions, please refer to MemberHookCreator.Result, ResourcesHookCreator.Result. Common exceptions that may occur are described here. For more information, please refer to API Exception Handling. In some cases, you can manually throw exceptions to alert some functionality that there is a problem. As mentioned above, the exception thrown in the Here's how these exceptions work when The following example The above scenarios will only be processed in the (Xposed) Host App environment and will not have any impact on the host itself. If we want to throw these exceptions directly to the Host App, the native Xposed provides us with the If you want to throw an exception directly to the Host App in the Hook callback method body, you can implement the following methods. The following example You can also throw exceptions directly in the Hook callback method body, and then mark the exception to be thrown to the Host App. The following example The above two methods can receive an exception at the Host App and cause the Host App process to crash. Notice In order to ensure that the Hook calling domain and the calling domain within the Host App are isolated from each other, exceptions can only be thrown to the Host App in the beforeHook and afterHook callback method bodies. Tips For more functions, please refer to Throwable.throwToApp, YukiMemberHookCreator.MemberMookCreator.HookCallback. People who use In First we can monitor that the Hook is ready to start. The following example Pay Attention instanceClass is recommended to be used only in onPrepareHook, otherwise the Hook's Class does not exist and an uninterceptable exception will be thrown, causing the Hook process to "die". Then, we can also monitor the success of the method result of the Hook. The following example You can use the following methods to easily implement various judgments and functions in the Hook process. If your Module App needs to handle Hook events of multiple apps at the same time, you can use the The following example Tips For more functions, please refer to PackageParam.loadApp. If your Hook's Host App has multiple processes, you can use the The following example Tips For more functions, please refer to PackageParam.withProcess. To make the code more concise, you can omit the name of The following example Usually, we choose to write a method that return In Now, you can use The following example Due to some special reasons, Module Apps in TaiChi and Wuji cannot use standard methods to detect the activation state. At this point, you can use The following example If you want to use both judgment schemes, At this point, you can use The following example Tips For more functions, please refer to YukiHookAPI.Status. Notice If the activation state of TaiChi and Wuji is included in the Module App activation judgment, the Application of the Module App must be extends ModuleApplication or ModuleApplication must be used directly; The API after 1.0.91 has modified the activation logic judgment method, now you can use this API in the Module App and Host App at the same time; Need to make sure YukiHookAPI.Configs.isEnableHookModuleStatus is enabled; Except for Hook Frameworks that provide standard APIs, Module Apps may not be able to determine whether they are activated in other cases. \u672A\u6765\u662F\u7F8E\u597D\u7684\uFF0C\u4E5F\u662F\u4E0D\u786E\u5B9A\u7684\uFF0C\u8BA9\u6211\u4EEC\u5171\u540C\u671F\u5F85 \u8FD9\u91CC\u6536\u5F55\u4E86 \u76EE\u524D\u4EC5\u9650\u5B8C\u7F8E\u652F\u6301 LSPosed\uFF0C\u5176\u5B83 Xposed \u6846\u67B6\u9700\u8981\u964D\u7EA7\u6A21\u5757 API\u3002 \u53EF\u80FD\u5B8C\u5168\u4E0D\u652F\u6301\u592A\u6781\uFF0C\u592A\u6781\u5728\u9AD8\u7248\u672C\u7CFB\u7EDF\u4E0A\u9700\u8981\u66F4\u4F4E\u7684 API \u624D\u80FD\u9002\u914D\u3002 \u90E8\u5206 Xposed \u6A21\u5757\u5F00\u53D1\u8005\u76EE\u524D\u9009\u62E9 Hook \u76EE\u6807 APP \u5185\u7F6E Sp \u5B58\u50A8\u65B9\u6848\u89E3\u51B3\u6A21\u5757\u8BBE\u7F6E\u5171\u4EAB\u95EE\u9898\u3002 \u540E\u671F Android \u7CFB\u7EDF\u7684\u6743\u9650\u5C06\u8D8A\u6765\u8D8A\u4E25\u683C\uFF0C \u8FD9\u91CC\u6536\u5F55\u4E86 \u5F85\u8BA8\u8BBA \u76EE\u524D API \u53EA\u652F\u6301\u901A\u8FC7\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u7ED1\u5B9A\u5230 xposed_init\uFF0C\u82E5\u60A8\u4E0D\u559C\u6B22\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\uFF0C\u4E00\u5B9A\u8981\u81EA\u5DF1\u5B9E\u73B0\u6A21\u5757\u88C5\u8F7D\u5165\u53E3\uFF0C\u672A\u6765\u4F1A\u6309\u7167\u9700\u6C42\u4EBA\u6570\u63A8\u51FA\u4EC5\u6709 API \u529F\u80FD\u7684 Lite \u7248\u672C\uFF0C\u4F60\u53EF\u5411\u6211\u4EEC\u63D0\u51FA issues\u3002 API \u5DF2\u7ECF\u63D0\u4F9B\u4E86 Xposed \u539F\u751F API \u76D1\u542C\u63A5\u53E3\uFF0C\u4F60\u53EF\u4EE5 \u5728\u8FD9\u91CC \u627E\u5230\u6216\u67E5\u770B Demo \u7684\u5B9E\u73B0\u65B9\u6CD5\u3002 \u4F5C\u4E3A API \u6765\u8BB2\uFF0C\u76EE\u524D\u4EC5\u4EC5\u5BF9\u63A5 \u5927\u90E8\u5206 The future is bright and uncertain, let us look forward to the future development space of Here are the unresolved issues with Currently only supports LSPosed perfectly, other Xposed Framework need to downgrade the module target api. TaiChi may not be supported at all, and TaiChi needs a lower target api to adapt on high-version systems. Some Xposed Module developers currently choose the Hook target app self's SharedPreferences storage solution to solve the module settings sharing problem. In the later period, the permissions of the Android system will become more and more strict, and Features that To be Discussed At present, the API only supports binding to xposed_init through the automatic handler. If you don't like the automatic handler, you must implement the module loading entry yourself. In the future, the Lite version with only API functions will be launched according to the number of people required. You can submit issues with us. We have provided the Xposed native API listening interface, you can find or view the implementation method of the Demo here. As an API, currently only docking Most \u629B\u5F03\u539F\u59CB\u4E0D\u592A\u53CB\u597D\u7684 \u8BF7\u4F7F\u7528 \u6587\u6863\u5168\u90E8\u7684 Demo \u793A\u4F8B\u4EE3\u7801\u90FD\u5C06\u4F7F\u7528 \u4EE5\u524D\uFF0C\u6211\u4EEC\u5728\u6784\u5EFA Xposed \u6A21\u5757\u7684\u65F6\u5019\uFF0C\u9996\u5148\u9700\u8981\u5728 \u7136\u540E\uFF0C\u5C06\u81EA\u5DF1\u7684\u5165\u53E3\u7C7B\u540D\u624B\u52A8\u586B\u5165\u6587\u4EF6\u4E2D\uFF0C\u4F7F\u7528 \u81EA \u6709\u6CA1\u6709\u4EC0\u4E48 \u597D\u7528\u3001\u8F7B\u91CF\u3001\u4F18\u96C5 \u7684\u89E3\u51B3\u529E\u6CD5\u5462\uFF1F \u672C\u7740\u8FD9\u6837\u7684\u60F3\u6CD5\uFF0C \u73B0\u5728\uFF0C\u6211\u4EEC\u53EA\u9700\u8981\u7F16\u5199\u5C11\u91CF\u7684\u4EE3\u7801\uFF0C\u4E00\u5207\u65F6\u95F4\u5F00\u9500\u548C\u82B1\u8D39\u4EA4\u7ED9\u81EA\u52A8\u5316\u5904\u7406\u3002 \u501F\u52A9 \u793A\u4F8B\u5982\u4E0B Abandoning the original less friendly Please use All demo code in this document will be described using Previously, when we built an Xposed Module, we first needed to create an Then, manually fill in your own entry class name into the file and use Since Is there any easy to use, light, elegant solution? With this idea, Now, we only need to write a small amount of code, and all the time and expense are handed over to automation. With The following example \u8FD9\u91CC\u7684\u6587\u6863\u5C06\u540C\u6B65\u6700\u65B0 API \u7248\u672C\u7684\u76F8\u5173\u7528\u6CD5\uFF0C\u8BF7\u4FDD\u6301 \u529F\u80FD\u63CF\u8FF0\u4E3B\u8981\u4ECB\u7ECD\u5F53\u524D API \u7684\u76F8\u5173\u7528\u6CD5\u548C\u7528\u9014\u3002 \u529F\u80FD\u793A\u4F8B\u4E3B\u8981\u5C55\u793A\u4E86\u5F53\u524D API \u7684\u57FA\u672C\u7528\u6CD5\u793A\u4F8B\uFF0C\u53EF\u4F9B\u53C2\u8003\u3002 \u9996\u4E2A\u7248\u672C\u7684\u529F\u80FD\u5C06\u6807\u8BB0\u4E3A \u540E\u671F\u65B0\u589E\u52A0\u7684\u529F\u80FD\u5C06\u6807\u8BB0\u4E3A \u540E\u671F\u4FEE\u6539\u7684\u529F\u80FD\u5C06\u88AB\u8FFD\u52A0\u4E3A \u540E\u671F\u88AB\u4F5C\u5E9F\u7684\u529F\u80FD\u5C06\u6807\u8BB0\u4E3A \u540E\u671F\u88AB\u5220\u9664\u7684\u529F\u80FD\u5C06\u6807\u8BB0\u4E3A kt \xA0Kotlin Static File annotation \xA0\u6CE8\u89E3 interface \xA0\u63A5\u53E3 object \xA0\u7C7B (\u5355\u4F8B) class \xA0\u7C7B field \xA0\u53D8\u91CF\u6216 method \xA0\u65B9\u6CD5 enum \xA0Enum \u5E38\u91CF ext-field \xA0\u6269\u5C55\u7684\u53D8\u91CF (\u5168\u5C40) ext-method \xA0\u6269\u5C55\u7684\u65B9\u6CD5 (\u5168\u5C40) i-ext-field \xA0\u6269\u5C55\u7684\u53D8\u91CF (\u8C03\u7528\u57DF\u9650\u5236) i-ext-method \xA0\u6269\u5C55\u7684\u65B9\u6CD5 (\u8C03\u7528\u57DF\u9650\u5236) The document here will synchronize the relevant usage of the latest API version, please keep The function description mainly introduces the related usage and purpose of the current API. The function examples mainly show the basic usage examples of the current API for reference. The function of the first version will be marked as New function added later will be marked as Later modified function will be appended as Later deprecated function will be marked as Later removed function will be marked as kt \xA0Kotlin Static File annotation \xA0Annotation Class interface \xA0Interface Class object \xA0Class (Singleton) class \xA0Class field \xA0Field or method \xA0Method enum \xA0Enum constant ext-field \xA0Extension field (global) ext-method \xA0Extension method (global) i-ext-field \xA0Extension field (internal) i-ext-method \xA0Extension method (internal) \u8FD9\u662F\u4E00\u4E2A\u5C06\u6A21\u5757\u8D44\u6E90\u3001 \u5728\u4F7F\u7528\u4EE5\u4E0B\u529F\u80FD\u4E4B\u524D\uFF0C\u4E3A\u9632\u6B62\u8D44\u6E90 ID \u4E92\u76F8\u51B2\u7A81\uFF0C\u4F60\u9700\u8981\u5728\u5F53\u524D Xposed \u6A21\u5757\u9879\u76EE\u7684 \u6CE8\u610F \u63D0\u4F9B\u7684\u793A\u4F8B\u8D44\u6E90 ID \u503C\u4EC5\u4F9B\u53C2\u8003\uFF0C\u4E0D\u53EF\u4F7F\u7528 0x7f\uFF0C\u9ED8\u8BA4\u4E3A 0x64\uFF0C\u4E3A\u4E86\u9632\u6B62\u5F53\u524D\u5BBF\u4E3B\u5B58\u5728\u591A\u4E2A Xposed \u6A21\u5757\uFF0C\u5EFA\u8BAE\u81EA\u5B9A\u4E49\u4F60\u81EA\u5DF1\u7684\u8D44\u6E90 ID\u3002 \u5728 Hook \u5BBF\u4E3B\u4E4B\u540E\uFF0C\u6211\u4EEC\u53EF\u4EE5\u76F4\u63A5\u5728 Hooker \u4E2D\u5F97\u5230\u7684 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u76F4\u63A5\u5728 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 Context+Resources.injectModuleAppResources \u65B9\u6CD5\u3002 \u5728 Android \u7CFB\u7EDF\u4E2D\u6240\u6709\u5E94\u7528\u7684 \u5728 Hook \u5BBF\u4E3B\u4E4B\u540E\uFF0C\u6211\u4EEC\u53EF\u4EE5\u76F4\u63A5\u5728 Hooker \u4E2D\u5F97\u5230\u7684 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u76F4\u63A5\u5728 \u793A\u4F8B\u5982\u4E0B \u5982\u679C\u6CA1\u6709\u586B\u5199 \u901A\u5E38\u60C5\u51B5\u4E0B\uFF0C\u5B83\u662F\u6709\u6548\u7684\uFF0C\u4F46\u662F\u4EE5\u4E0A\u60C5\u51B5\u5728\u4E00\u4E9B APP \u4E2D\u4F1A\u5931\u6548\uFF0C\u4F8B\u5982\u4E00\u4E9B \u82E5\u672A\u6CE8\u518C\u7684 \u4F60\u9700\u8981\u9009\u62E9\u4E00\u4E2A\u5F53\u524D\u5BBF\u4E3B\u53EF\u80FD\u7528\u4E0D\u5230\u7684\u3001\u4E0D\u9700\u8981\u7684 \u6BD4\u5982\u6211\u4EEC\u5DF2\u7ECF\u627E\u5230\u4E86\u80FD\u591F\u88AB\u4EE3\u7406\u7684\u5408\u9002 \u793A\u4F8B\u5982\u4E0B \u6839\u636E\u5176\u4E2D\u7684 \u793A\u4F8B\u5982\u4E0B \u53E6\u4E00\u79CD\u60C5\u51B5\uFF0C\u5982\u679C\u4F60\u5BF9\u5BBF\u4E3B\u7684\u7C7B\u7F16\u5199\u4E86\u4E00\u4E2A \u793A\u4F8B\u5982\u4E0B \u6CE8\u518C\u5B8C\u6210\u540E\uFF0C\u8BF7\u5C06\u4F60\u9700\u8981\u4F7F\u7528\u5BBF\u4E3B\u542F\u52A8\u7684\u6A21\u5757\u4E2D\u7684 \u8FD9\u4E9B \u793A\u4F8B\u5982\u4E0B \u82E5\u4F60\u9700\u8981\u7EE7\u627F\u4E8E \u793A\u4F8B\u5982\u4E0B \u4EE5\u4E0A\u6B65\u9AA4\u5168\u90E8\u5B8C\u6210\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4EFB\u610F\u5B58\u5728 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 Context.registerModuleAppActivities \u65B9\u6CD5\u3002 \u6709\u65F6\u5019\uFF0C\u6211\u4EEC\u9700\u8981\u4F7F\u7528 \u8FD9\u65F6\uFF0C\u6211\u4EEC\u60F3\u5728\u5BBF\u4E3B\u88AB Hook \u7684\u5F53\u524D \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u5BF9\u5F53\u524D \u793A\u4F8B\u5982\u4E0B \u8FD9\u6837\uFF0C\u6211\u4EEC\u5C31\u53EF\u4EE5\u5728\u5BBF\u4E3B\u4E2D\u975E\u5E38\u7B80\u5355\u5730\u4F7F\u7528 This is an extension that injects Module App's Resources, Before using the following functions, in order to prevent Resource Id from conflicting with each other, you need to modify the Resource Id in the Notice The sample Resource Id value provided is for reference only, 0x7f cannot be used, the default is 0x64. In order to prevent the existence of multiple Xposed Modules in the current Host App, it is recommended to customize your own Resource Id. After the Host App is hooked, we can directly inject the The following example You can also inject current Module App's Resources directly in The following example Tips For more functions, please refer to the Context+Resources.injectModuleAppResources method. When the During the Hook process, if we want to directly start the unregistered After the Host App is hooked, we can directly register the The following example You can also register the current Module App's The following example If the Usually, it works, but the above situation will fail in some apps, for example, some If the unregistered You need to choose an unneeded For example, we have found a suitable The following example According to the The following example Alternatively, if you write a The following example After the registration is complete, extends the These The following example If you need to extends The following example After all the above steps are completed, you can happily call The following example Tips For more functions, please refer to the Context.registerModuleAppActivities method. Sometimes, we need to use At this time, we want to use The following example You can also set the system (native) night mode and day mode on the current Which requires at least Android 10 and above system version support and the current theme contains night mode related elements. The following example This way, we can create dialogs in the Host App very simply using \u8FD9\u662F\u4E00\u4E2A\u81EA\u52A8 Hook \u5BBF\u4E3B APP \u751F\u547D\u5468\u671F\u7684\u6269\u5C55\u529F\u80FD\u3002 \u901A\u8FC7\u81EA\u52A8\u5316 Hook \u5BBF\u4E3B APP \u7684\u751F\u547D\u5468\u671F\u65B9\u6CD5\uFF0C\u6765\u5B9E\u73B0\u76D1\u542C\u529F\u80FD\u3002 \u6211\u4EEC\u9700\u8981\u76D1\u542C\u5BBF\u4E3B \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 AppLifecycle\u3002 \u901A\u8FC7 \u6211\u4EEC\u8FD8\u53EF\u4EE5\u5728\u5BBF\u4E3B \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 AppLifecycle\u3002 This is an extension of the lifecycle of an automatic hooking Host App. Implement the monitoring function by automating the lifecycle method of the Host App. We need to listen to the startup and lifecycle methods of the Host App's The following example Tips For more functions, please refer to AppLifecycle. Register system broadcast through the We can also register system broadcast in the Host App's The following example Tips For more functions, please refer to AppLifecycle. Here is a collection of Xposed-related introductions and the key points of knowledge that need to be grasped before start. Anyone who already knows can skip it. The basic knowledge content not necessarily completely accurate, please read it according to your own opinion. If you find any errors in this page, please correct it and help us improve. Here's an introduction to Xposed and how Hooks work. Xposed Framework (Xposed Framework) is a set of open source framework services that run in Android high-privilege mode. It can affect program operation (modify the system) without modifying the APK file. Based on it, many Powerful modules that operate simultaneously without conflicting functions. The above content is copied from Baidu Encyclopedia. The structure below describes the basic workings and principles of Xposed. We can achieve the ultimate goal of controlling its behavior by injecting the Host (App) when the Host (App) is running. This mode of operation of Xposed is called parasitism. The Xposed Module follows the lifecycle of the host and completes its own life course within the lifecycle of the Host. We can call the Host's methods, fields, and constructors through reflection, and use the Hook operation provided by Today's Xposed Manager has been completely replaced by its derivative works, and the era of SuperSU has ended, and now, with Magisk, everything behind is possible again. Its development history can be roughly divided into Xposed(Dalvik) \u2192 Xposed(ART) \u2192 Xposed(Magisk) \u2192 EdXposed(Riru)/LSPosed(Riru/ Zygisk) The structure below describes how and how the Xposed-like Hook Framework works. Through the operation principle of Xposed, many frameworks of the same type have been derived. As mobile devices in today's era are more and more difficult to obtain Root permissions or even flash, and when they are not just needed, some Root-free frameworks are also produced, such as Tai Chi. These Hook Frameworks at the ART level can also complete the Hook process with the same principle as Xposed without using the Xposed API. The operating principle of Root-free is to modify the APK and inject the Hook process into the Host, and control it through external modules. Another product is to use the existing functions of the Android operating environment to virtualize an environment that is completely the same as the current device system, and run App in it. This is the virtual App technology VirtualApp, which was later derived as VirtualXposed . The Root-free frameworks mentioned above are Tai Chi/Wuji, VirtualXposed/SandVXposed. Since Xposed appeared until now, apart from The birth of this API framework is to hope that in the current era of Xposed, more capable Xposed Module developers can avoid detours and complete the entire development process more easily and simply. In the future, Before starting, you need to have the following basics to better use \u8FD9\u91CC\u6536\u96C6\u4E86 Xposed \u76F8\u5173\u7684\u4ECB\u7ECD\u4EE5\u53CA\u5F00\u542F\u524D\u9700\u8981\u638C\u63E1\u7684\u77E5\u8BC6\u8981\u70B9\uFF0C\u5DF2\u7ECF\u4E86\u89E3\u7684\u540C\u5B66\u53EF\u4EE5\u7565\u8FC7\u3002 \u57FA\u7840\u77E5\u8BC6\u5185\u5BB9\u5E76\u4E0D\u4E00\u5B9A\u5B8C\u5168\u51C6\u786E\uFF0C\u8BF7\u6839\u636E\u81EA\u5DF1\u7684\u89C1\u89E3\u914C\u60C5\u9605\u8BFB\uFF0C\u82E5\u53D1\u73B0\u5185\u5BB9\u6709\u9519\u8BEF\u6B22\u8FCE\u6307\u6B63\u5E76\u5E2E\u52A9\u6211\u4EEC\u5B8C\u5584\u548C\u6539\u8FDB\u3002 \u8FD9\u91CC\u4ECB\u7ECD\u4E86 Xposed \u4EE5\u53CA Hook \u7684\u5DE5\u4F5C\u539F\u7406\u3002 Xposed \u6846\u67B6(Xposed Framework)\u662F\u4E00\u5957\u5F00\u6E90\u7684\u3001\u5728 Android \u9AD8\u6743\u9650\u6A21\u5F0F\u4E0B\u8FD0\u884C\u7684\u6846\u67B6\u670D\u52A1\uFF0C\u53EF\u4EE5\u5728\u4E0D\u4FEE\u6539 APK \u6587\u4EF6\u7684\u60C5\u51B5\u4E0B\u5F71\u54CD\u7A0B\u5E8F\u8FD0\u884C\uFF08\u4FEE\u6539\u7CFB\u7EDF\uFF09\u7684\u6846\u67B6\u670D\u52A1\uFF0C\u57FA\u4E8E\u5B83\u53EF\u4EE5\u5236\u4F5C\u51FA\u8BB8\u591A\u529F\u80FD\u5F3A\u5927\u7684\u6A21\u5757\uFF0C\u4E14\u5728\u529F\u80FD\u4E0D\u51B2\u7A81\u7684\u60C5\u51B5\u4E0B\u540C\u65F6\u8FD0\u4F5C\u3002 \u4E0A\u8FF0\u5185\u5BB9\u590D\u5236\u81EA\u767E\u5EA6\u767E\u79D1\u3002 \u4E0B\u65B9\u7684\u7ED3\u6784\u63CF\u8FF0\u4E86 Xposed \u7684\u57FA\u672C\u5DE5\u4F5C\u65B9\u5F0F\u548C\u539F\u7406\u3002 \u6211\u4EEC\u53EF\u4EE5\u5728\u5BBF\u4E3B (APP) \u8FD0\u884C\u65F6\u901A\u8FC7\u6CE8\u5165\u5BBF\u4E3B (APP) \u6765\u8FBE\u5230\u63A7\u5236\u5176\u884C\u4E3A\u7684\u6700\u7EC8\u76EE\u7684\u3002 Xposed \u7684\u8FD9\u79CD\u8FD0\u884C\u65B9\u5F0F\u88AB\u79F0\u4E3A\u5BC4\u751F\uFF0CXposed \u6A21\u5757\u8DDF\u968F\u5BBF\u4E3B\u7684\u751F\u547D\u5468\u671F\uFF0C\u5728\u5BBF\u4E3B\u7684\u751F\u547D\u5468\u671F\u5185\u5B8C\u6210\u81EA\u5DF1\u7684\u751F\u547D\u5386\u7A0B\u3002 \u6211\u4EEC\u53EF\u4EE5\u901A\u8FC7\u53CD\u5C04\u7684\u65B9\u5F0F\u8C03\u7528\u5BBF\u4E3B\u7684\u65B9\u6CD5\u3001\u53D8\u91CF\u3001\u6784\u9020\u65B9\u6CD5\uFF0C\u4EE5\u53CA\u4F7F\u7528 \u5982\u4ECA\u7684 Xposed \u7BA1\u7406\u5668\u5DF2\u5B8C\u5168\u88AB\u5176\u884D\u751F\u4F5C\u54C1\u66FF\u4EE3\uFF0C\u800C SuperSU \u7684\u65F6\u4EE3\u4E5F\u5DF2\u7ECF\u843D\u5E55\u4E86\uFF0C\u73B0\u5728\uFF0C\u501F\u52A9 Magisk \u4F7F\u540E\u9762\u7684\u4E00\u5207\u53C8\u6210\u4E3A\u4E86\u53EF\u80FD\u3002 \u5176\u53D1\u5C55\u53F2\u5927\u81F4\u53EF\u5206\u4E3A Xposed(Dalvik) \u2192 Xposed(ART) \u2192 Xposed(Magisk) \u2192 EdXposed(Riru)/LSPosed(Riru/Zygisk) \u4E0B\u65B9\u7684\u7ED3\u6784\u63CF\u8FF0\u4E86\u7C7B\u4F3C Xposed \u7684 Hook Framework \u7684\u5DE5\u4F5C\u65B9\u5F0F\u548C\u539F\u7406\u3002 \u901A\u8FC7 Xposed \u7684\u8FD0\u884C\u539F\u7406\uFF0C\u4ECE\u800C\u884D\u751F\u4E86\u5F88\u591A\u540C\u7C7B\u578B\u6846\u67B6\uFF0C\u968F\u7740\u5F53\u4ECA\u65F6\u4EE3\u7684\u79FB\u52A8\u8BBE\u5907\u83B7\u53D6 Root \u6743\u9650\u751A\u81F3\u5237\u673A\u8D8A\u6765\u8D8A\u56F0\u96BE\u4E14\u4E0D\u662F\u521A\u9700\u7684\u65F6\u5019\uFF0C\u4E00\u4E9B\u514D Root \u6846\u67B6\u4E5F\u968F\u4E4B\u4EA7\u751F\uFF0C\u4F8B\u5982\u592A\u6781\u3002 \u8FD9\u4E9B\u5728 ART \u5C42\u9762\u4E0A\u7684 Hook \u6846\u67B6\u540C\u6837\u4E5F\u53EF\u4E0D\u501F\u52A9 Xposed API \u5B8C\u6210\u5176\u548C Xposed \u539F\u7406\u4E00\u6837\u7684 Hook \u6D41\u7A0B\uFF0C\u514D Root \u7684\u8FD0\u884C\u539F\u7406\u4E3A\u4FEE\u6539 APK \u5E76\u5C06 Hook \u8FDB\u7A0B\u6CE8\u5165\u5BBF\u4E3B\uFF0C\u901A\u8FC7\u5916\u90E8\u6A21\u5757\u5BF9\u5176\u8FDB\u884C\u63A7\u5236\u3002 \u53E6\u5916\u4E00\u79CD\u4EA7\u54C1\u5C31\u662F\u5229\u7528 Android \u8FD0\u884C\u73AF\u5883\u73B0\u6709\u7684\u529F\u80FD\u865A\u62DF\u51FA\u4E00\u4E2A\u5B8C\u5168\u4E0E\u5F53\u524D\u8BBE\u5907\u7CFB\u7EDF\u4E00\u6837\u7684\u73AF\u5883\uFF0C\u5E76\u5728\u5176\u4E2D\u8FD0\u884C APP\uFF0C\u8FD9\u4E2A\u5C31\u662F\u865A\u62DF APP \u6280\u672F VirtualApp\uFF0C\u540E\u6765\u884D\u751F\u4E3A VirtualXposed\u3002 \u4E0A\u8FF0\u63D0\u5230\u7684\u514D Root \u6846\u67B6\u5206\u522B\u4E3A\u592A\u6781/\u65E0\u6781\u3001VirtualXposed/SandVXposed\u3002 \u81EA\u4ECE Xposed \u51FA\u73B0\u5230\u73B0\u5728\u4E3A\u6B62\uFF0C\u9664\u4E86\u5F00\u53D1\u8005\u4EBA\u4EBA\u7686\u77E5\u7684 \u672C API \u6846\u67B6\u7684\u8BDE\u751F\u5C31\u662F\u5E0C\u671B\u5728 Xposed \u7684\u5982\u4ECA\u65F6\u4EE3\uFF0C\u80FD\u8BA9\u66F4\u591A\u6709\u52A8\u624B\u80FD\u529B\u7684 Xposed \u6A21\u5757\u5F00\u53D1\u8005\u5C11\u8D70\u5F2F\u8DEF\uFF0C\u66F4\u5BB9\u6613\u3001\u66F4\u7B80\u5355\u5730\u5B8C\u6210\u6574\u4E2A\u5F00\u53D1\u6D41\u7A0B\u3002 \u672A\u6765\uFF0C \u5728\u5F00\u59CB\u4E4B\u524D\uFF0C\u4F60\u9700\u8981\u62E5\u6709\u4EE5\u4E0B\u57FA\u7840\u624D\u80FD\u66F4\u597D\u5730\u4F7F\u7528 Log is the most important part of the debugging process, You can call The usage method is as follows. The following example At this point, The default You can also customize this value dynamically, but it is not recommended to modify The following example The printed result is as shown below. The following example You can also use You can choose to use The default type is For example we only use The following example Or just use The following example If you want to intelligently distinguish the (Xposed) Host environment from the Module environment, you can write it in the following form. The following example In this way, the API will intelligently select the specified method type to print this log in different environments. You can call The usage method is as follows. The following example The error log is the highest level, regardless of whether you have filtered only For error-level logging, you can also append an exception stack. The printed result is as shown below. The following example At the same time, the log will help you print the entire exception stack. The following example In the error log, you can also use Tips For more functions, please refer to the loggerE method. You can save all currently printed logs directly to a file using the The following example You can also use The following example The above features require You can also use This function requires The following example Tips For more functions, please refer to YukiHookLogger.contents, YukiHookLogger.saveToFile methods and YukiHookLogger.Configs. \u65E5\u5FD7\u662F\u8C03\u8BD5\u8FC7\u7A0B\u6700\u91CD\u8981\u7684\u4E00\u73AF\uFF0C \u4F60\u53EF\u4EE5\u8C03\u7528 \u4F7F\u7528\u65B9\u6CD5\u5982\u4E0B\u6240\u793A\u3002 \u793A\u4F8B\u5982\u4E0B \u6B64\u65F6\uFF0C \u65E5\u5FD7\u9ED8\u8BA4\u7684 \u4F60\u4E5F\u53EF\u4EE5\u52A8\u6001\u81EA\u5B9A\u4E49\u8FD9\u4E2A\u503C\uFF0C\u4F46\u662F\u4E0D\u5EFA\u8BAE\u8F7B\u6613\u4FEE\u6539 \u793A\u4F8B\u5982\u4E0B \u6253\u5370\u7684\u7ED3\u679C\u4E3A\u5982\u4E0B\u6240\u793A\u3002 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 \u9ED8\u8BA4\u7C7B\u578B\u4E3A \u6BD4\u5982\u6211\u4EEC\u4EC5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u6216\u53C8\u4EC5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u82E5\u4F60\u60F3\u667A\u80FD\u533A\u5206 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4E0E\u6A21\u5757\u73AF\u5883\uFF0C\u53EF\u4EE5\u5199\u4E3A\u5982\u4E0B\u5F62\u5F0F\u3002 \u793A\u4F8B\u5982\u4E0B \u8FD9\u6837 API \u5C31\u4F1A\u5728\u4E0D\u540C\u73AF\u5883\u667A\u80FD\u9009\u62E9\u6307\u5B9A\u7684\u65B9\u6CD5\u7C7B\u578B\u53BB\u6253\u5370\u8FD9\u6761\u65E5\u5FD7\u3002 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 loggerD\u3001loggerI \u53CA loggerW \u65B9\u6CD5\u3002 \u4F60\u53EF\u4EE5\u8C03\u7528 \u4F7F\u7528\u65B9\u6CD5\u5982\u4E0B\u6240\u793A\u3002 \u793A\u4F8B\u5982\u4E0B \u9519\u8BEF\u65E5\u5FD7\u7684\u7EA7\u522B\u662F\u6700\u9AD8\u7684\uFF0C\u65E0\u8BBA\u4F60\u6709\u6CA1\u6709\u8FC7\u6EE4\u4EC5\u4E3A \u5BF9\u4E8E\u9519\u8BEF\u7EA7\u522B\u7684\u65E5\u5FD7\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u540E\u9762\u52A0\u4E0A\u4E00\u4E2A\u5F02\u5E38\u5806\u6808\u3002 \u6253\u5370\u7684\u7ED3\u679C\u4E3A\u5982\u4E0B\u6240\u793A\u3002 \u793A\u4F8B\u5982\u4E0B \u540C\u65F6\uFF0C\u65E5\u5FD7\u4F1A\u5E2E\u4F60\u6253\u5370\u6574\u4E2A\u5F02\u5E38\u5806\u6808\u3002 \u793A\u4F8B\u5982\u4E0B \u5728\u9519\u8BEF\u65E5\u5FD7\u4E2D\uFF0C\u4F60\u540C\u6837\u4E5F\u53EF\u4EE5\u4F7F\u7528 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 loggerE \u65B9\u6CD5\u3002 \u4F60\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u4EE5\u4E0A\u529F\u80FD\u9700\u8981\u542F\u7528 \u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 \u6B64\u529F\u80FD\u9700\u8981\u5728 Hook \u5165\u53E3\u7C7B\u7684 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiHookLogger.contents\u3001YukiHookLogger.saveToFile \u65B9\u6CD5\u4EE5\u53CA YukiHookLogger.Configs\u3002 \u82E5\u4F60\u719F\u6089 Xposed API\uFF0C\u4F60\u53EF\u4EE5\u53C2\u8003\u4E0B\u65B9\u7684\u76F8\u540C\u70B9\u5C06\u81EA\u5DF1\u7684 API \u5FEB\u901F\u8FC1\u79FB\u5230 \u4ECE API \u529F\u80FD\u5DEE\u5F02\u5BF9\u6BD4\u5982\u4E0B \u4ECE API \u529F\u80FD\u5DEE\u5F02\u5BF9\u6BD4\u5982\u4E0B If you are familiar with Xposed API, you can refer to the same point below to quickly migrate your API to Migrated from The API function differences are compared as follows Migrated from The API function differences are compared as follows \u96C6\u6210 Windows 7 \u53CA\u4EE5\u4E0A/macOS 10.14 \u53CA\u4EE5\u4E0A/Linux \u53D1\u884C\u7248(Arch/Debian) Android Studio 2021.1 \u53CA\u4EE5\u4E0A IntelliJ IDEA 2021.1 \u53CA\u4EE5\u4E0A Kotlin 1.7.0 \u53CA\u4EE5\u4E0A Android Gradle Plugin 7.0 \u53CA\u4EE5\u4E0A Gradle 7.0 \u53CA\u4EE5\u4E0A Jvm 11 \u53CA\u4EE5\u4E0A (Since API \u4F60\u53EF\u4EE5 \u70B9\u51FB\u8FD9\u91CC \u8FDB\u884C\u67E5\u770B\u3002 \u82E5\u4F60\u4E0D\u60F3\u4F7F\u7528\u81EA\u52A8\u5316\u6784\u5EFA\u5DE5\u5177\uFF0C\u4F60\u4F9D\u7136\u53EF\u4EE5\u6309\u7167\u4EE5\u4E0B\u65B9\u5F0F\u624B\u52A8\u914D\u7F6E\u9879\u76EE\u4F9D\u8D56\u3002 \u4F7F\u7528 \u5728\u4F60\u7684\u9879\u76EE \u793A\u4F8B\u5982\u4E0B \u5728\u4F60\u7684 app \u793A\u4F8B\u5982\u4E0B \u5728\u4F60\u7684 app \u793A\u4F8B\u5982\u4E0B \u8BF7\u5C06 <yuki-version> \u4FEE\u6539\u4E3A \u8FD9\u91CC \u7684\u6700\u65B0\u7248\u672C\u3002 \u7279\u522B\u6CE8\u610F YukiHookAPI \u7684 api \u4E0E ksp-xposed \u4F9D\u8D56\u7684\u7248\u672C\u5FC5\u987B\u4E00\u4E00\u5BF9\u5E94\uFF0C\u5426\u5219\u5C06\u4F1A\u9020\u6210\u7248\u672C\u4E0D\u5339\u914D\u9519\u8BEF\u3002 \u5728\u4F60\u7684 app \u793A\u4F8B\u5982\u4E0B \u6CE8\u610F \u81EA API 1.0.80 \u7248\u672C\u540E Jvm \u7248\u672C\u9ED8\u8BA4\u4E3A 11\uFF0C\u4E0D\u518D\u652F\u6301 1.8 \u53CA\u4EE5\u4E0B\u7248\u672C\u3002 \u5728\u4F60\u7684 \u793A\u4F8B\u5982\u4E0B \u5728\u4F60\u7684\u9879\u76EE\u4E2D\u521B\u5EFA\u4E00\u4E2A Hook \u5165\u53E3\u7C7B\uFF0C\u7EE7\u627F\u4E8E \u793A\u4F8B\u5982\u4E0B \u5EFA\u8BAE \u4F60\u53EF\u4EE5\u5C06\u4F60\u7684\u6A21\u5757 APP \u7684 Application \u7EE7\u627F\u4E8E ModuleApplication \u4EE5\u5B9E\u73B0\u5B8C\u6574\u4F7F\u7528\u4F53\u9A8C\u3002 \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ModuleApplication\u3002 \u7136\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u5F00\u59CB\u7F16\u5199 Hook \u4EE3\u7801\u4E86\u3002 \u6709\u5173\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E\u8BE6\u7EC6\u5185\u5BB9\uFF0C\u4F60\u53EF\u4EE5 \u70B9\u51FB\u8FD9\u91CC \u7EE7\u7EED\u9605\u8BFB\u3002 \u82E5\u4F60\u76EE\u524D\u6B63\u5728\u4F7F\u7528 Xposed API\uFF0C\u4F60\u53EF\u4EE5\u53C2\u8003 \u4ECE Xposed API \u8FC1\u79FB\u3002 \u521B\u5EFA\u4F60\u7684\u81EA\u5B9A\u4E49 \u7279\u522B\u6CE8\u610F \u65E0\u8BBA\u4F7F\u7528\u4EFB\u4F55 Hook Framework\uFF0C\u4F60\u90FD\u9700\u8981\u52A0\u5165\u5176\u5BF9\u63A5\u7684 Xposed \u4F9D\u8D56\u652F\u6301\u3002 \u82E5\u76EE\u6807 Hook Framework \u6CA1\u6709\u96C6\u6210 Xposed API \u4F60\u9700\u8981\u81EA\u884C\u5B9E\u73B0\u5E76\u5BF9\u63A5 XposedBridge\u3002 \u5728 \u793A\u4F8B\u5982\u4E0B \u7136\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u5F00\u59CB\u7F16\u5199 Hook \u4EE3\u7801\u4E86\uFF0C\u65B9\u5F0F\u4E0E\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u57FA\u672C\u4E00\u81F4\u3002 \u6709\u5173\u4F5C\u4E3A Hook API \u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E\u8BE6\u7EC6\u5185\u5BB9\uFF0C\u4F60\u53EF\u4EE5 \u70B9\u51FB\u8FD9\u91CC \u7EE7\u7EED\u9605\u8BFB\u3002 \u6CE8\u610F \u4F7F\u7528\u81EA\u5B9A\u4E49\u7684 Hook \u6846\u67B6\u800C\u5E76\u975E\u5B8C\u6574\u7684 Xposed \u6A21\u5757\u65F6\uFF0CYukiHookModuleStatus\u3001YukiHookModulePrefs\u3001YukiHookDataChannel \u4EE5\u53CA Resources Hook \u529F\u80FD\u5C06\u5931\u6548\u3002 Integrate Windows 7 and above / macOS 10.14 and above / Linux distributions (Arch/Debian) Android Studio 2021.1 and above IntelliJ IDEA 2021.1 and above Kotlin 1.7.0 and above Android Gradle Plugin 7.0 and above Gradle 7.0 and above JVM 11 and above (Since API You can click here to check it out. If you don't want to use automated build tools, you can still manually configure project dependencies as follows. Use Add dependencies to your project The following example Add The following example Add dependencies to your app The following example Please modify <yuki-version> to the latest version here. Pay Attention The api of YukiHookAPI and the versions that ksp-xposed depend on must correspond one by one, otherwise a version mismatch error will occur. Modify the JVM version of The following example Notice Since API 1.0.80 version, the default JVM version is 11, and 1.8 and below are no longer supported. Add the base code to your The following example Create a Hook entry class in your project, implements The following example Suggestion You can extends Application of your Module App from ModuleApplication to achieve a complete user experience. For more functions, please refer to ModuleApplication. Then, you can start writing Hook code. For configuration details related to use as an Xposed Module, you can click here to continue reading. If you are currently using Xposed API, you can refer to Migrate from Xposed API. Create your custom Pay Attention Regardless of the Hook Framework you use, you need to add its docking Xposed dependency support. If the target Hook Framework does not integrate Xposed API, you need to implement and connect XposedBridge by yourself. Add The following example Then, you can start writing Hook code in much the same way you would use it as an Xposed Module. For configuration details related to use as a Hook API, you can click here to continue reading. Notice YukiHookModuleStatus, YukiHookModulePrefs, YukiHookDataChannel and Resources Hook functionality will not work when using a custom Hook Framework instead of the full Xposed Module. In most scenarios, the Xposed Module can be compressed by native obfuscation. Here is the configuration method of obfuscation. If you are using Pay Attention Proguard rules have been deprecated, please don't use them anymore. Since Android Gradle Plugin 4.2, the obfuscator with the latest version of the Android Jetpack default is R8, and you no longer need to consider obfuscation. To enable \u5927\u90E8\u5206\u573A\u666F\u4E0B Xposed \u6A21\u5757\u53EF\u901A\u8FC7\u539F\u751F\u6DF7\u6DC6\u538B\u7F29\u4F53\u79EF\uFF0C\u8FD9\u91CC\u4ECB\u7ECD\u4E86\u6DF7\u6DC6\u7684\u914D\u7F6E\u65B9\u6CD5\u3002 \u5982\u679C\u4F60\u4F7F\u7528\u7684\u662F \u7279\u522B\u6CE8\u610F Proguard \u89C4\u5219\u5DF2\u88AB\u5F03\u7528\uFF0C\u8BF7\u4E0D\u8981\u518D\u4F7F\u7528\uFF0C\u81EA\u4ECE Android Gradle Plugin 4.2 \u540E\uFF0C\u62E5\u6709 Android Jetpack \u5957\u4EF6\u6700\u65B0\u7248\u672C\u7684\u6DF7\u6DC6\u5904\u7406\u7A0B\u5E8F\u9ED8\u8BA4\u5747\u4E3A R8\uFF0C\u4E0D\u518D\u9700\u8981\u8003\u8651\u6DF7\u6DC6\u7684\u95EE\u9898\u3002 \u82E5\u8981\u5728\u4EFB\u4F55\u7248\u672C\u4E0B\u542F\u7528 \u8FD9\u91CC\u662F Class \u5BF9\u8C61\u81EA\u8EAB\u76F8\u5173\u7684\u6269\u5C55\u529F\u80FD\u3002 \u5047\u8BBE\u6211\u4EEC\u8981\u5F97\u5230\u4E00\u4E2A\u4E0D\u80FD\u76F4\u63A5\u8C03\u7528\u7684 \u793A\u4F8B\u5982\u4E0B \u8FD9\u79CD\u5199\u6CD5\u5927\u6982\u4E0D\u662F\u5F88\u53CB\u597D\uFF0C\u6B64\u65F6 \u4EE5\u4E0A\u5199\u6CD5\u6362\u505A \u793A\u4F8B\u5982\u4E0B \u5982\u679C\u5F53\u524D \u793A\u4F8B\u5982\u4E0B \u6211\u4EEC\u8FD8\u53EF\u4EE5\u901A\u8FC7\u6620\u5C04\u6765\u5F97\u5230\u4E00\u4E2A\u5B58\u5728\u7684 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 classOf\u3001String.toClass\u3001String.toClassOrNull\u3001PackageParam \u2192 String+VariousClass.toClass\u3001PackageParam \u2192 String+VariousClass.toClassOrNull \u65B9\u6CD5\u3002 \u5047\u8BBE\u6211\u4EEC\u8981\u5224\u65AD\u4E00\u4E2A \u793A\u4F8B\u5982\u4E0B \u8FD9\u79CD\u5199\u6CD5\u5927\u6982\u4E0D\u662F\u5F88\u53CB\u597D\uFF0C\u6B64\u65F6 \u4EE5\u4E0A\u5199\u6CD5\u6362\u505A \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 String.hasClass\u3001PackageParam \u2192 String.hasClass \u65B9\u6CD5\u3002 \u5728 R8 \u7B49\u5DE5\u5177\u6DF7\u6DC6\u540E\u7684\u5BBF\u4E3B Dex \u4E2D\u7684 \u6B64\u65F6\u5C31\u6709\u4E86 \u6CE8\u610F \u76EE\u524D DexClassFinder \u7684\u529F\u80FD\u5C1A\u5728\u8BD5\u9A8C\u9636\u6BB5\uFF0C\u7531\u4E8E\u4EC5\u901A\u8FC7 Java \u5C42\u5B9E\u73B0\u67E5\u627E\u529F\u80FD\uFF0C\u5728\u5BBF\u4E3B Class \u8FC7\u591A\u65F6\u6027\u80FD\u53EF\u80FD\u4E0D\u80FD\u8FBE\u5230\u6700\u4F73\u6C34\u5E73\uFF0C\u5982\u679C\u53D1\u751F\u67E5\u627E\u4E0D\u5230\u3001\u5B9A\u4F4D\u6709\u8BEF\u7684\u95EE\u9898\u6B22\u8FCE\u5411\u6211\u4EEC\u53CD\u9988\u3002 \u7531\u4E8E\u662F\u53CD\u5C04\u5C42\u9762\u7684 API\uFF0C\u76EE\u524D\u5B83\u53EA\u80FD\u901A\u8FC7\u7C7B\u4E0E\u6210\u5458\u7684\u7279\u5F81\u6765\u5B9A\u4F4D\u6307\u5B9A\u7684 Class\uFF0C\u4E0D\u80FD\u901A\u8FC7\u6307\u5B9A\u5B57\u8282\u7801\u4E2D\u7684\u5B57\u7B26\u4E32\u548C\u65B9\u6CD5\u5185\u5BB9\u7279\u5F81\u6765\u8FDB\u884C\u5B9A\u4F4D\u3002 \u67E5\u627E Class \u7684\u901F\u5EA6\u53D6\u51B3\u4E8E\u5F53\u524D\u8BBE\u5907\u7684\u6027\u80FD\uFF0C\u76EE\u524D\u4E3B\u6D41\u7684\u79FB\u52A8\u7AEF\u5904\u7406\u5668\u5728 10~15w \u6570\u91CF\u7684 Class \u4E2D\u6761\u4EF6\u4E0D\u7B97\u590D\u6742\u7684\u60C5\u51B5\u4E0B\u5927\u6982\u5728 3~10s \u533A\u95F4\uFF0C\u6761\u4EF6\u7A0D\u5FAE\u590D\u6742\u7684\u60C5\u51B5\u4E0B\u6700\u5FEB\u901F\u5EA6\u80FD\u8FBE\u5230 25s \u4EE5\u5185\uFF0C\u5339\u914D\u5230\u7684\u540C\u7C7B\u578B Class \u8D8A\u591A\u901F\u5EA6\u8D8A\u6162\u3002 \u4E0B\u9762\u662F\u4E00\u4E2A\u7B80\u5355\u7684\u7528\u6CD5\u793A\u4F8B\u3002 \u5047\u8BBE\u4E0B\u9762\u8FD9\u4E2A \u793A\u4F8B\u5982\u4E0B \u6B64\u65F6\uFF0C\u6211\u4EEC\u60F3\u5F97\u5230\u8FD9\u4E2A \u5728 \u4E0B\u65B9\u6F14\u793A\u7684\u6761\u4EF6\u4E2D\u6BCF\u4E00\u4E2A\u90FD\u662F\u53EF\u9009\u7684\uFF0C\u6761\u4EF6\u8D8A\u590D\u6742\u5B9A\u4F4D\u8D8A\u7CBE\u786E\uFF0C\u540C\u65F6\u6027\u80FD\u4E5F\u4F1A\u8D8A\u5DEE\u3002 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u4E0A\u8FF0\u7528\u6CD5\u4E2D\u5BF9\u4E8E Field\u3001Method\u3001Constructor \u7684\u6761\u4EF6\u7528\u6CD5\u4E0E Member \u6269\u5C55 \u4E2D\u7684\u76F8\u5173\u7528\u6CD5\u662F\u4E00\u81F4\u7684\uFF0C\u4EC5\u6709\u5C0F\u90E8\u5206\u533A\u522B\u3002 \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MemberRules\u3001FieldRules\u3001MethodRules\u3001ConstructorRules\u3002 \u9ED8\u8BA4\u60C5\u51B5\u4E0B \u9488\u5BF9\u4E0A\u8FF0\u95EE\u9898\uFF0C\u6211\u4EEC\u53EF\u4EE5\u542F\u7528\u5F02\u6B65\uFF0C\u53EA\u9700\u8981\u52A0\u5165\u53C2\u6570 \u6CE8\u610F \u5BF9\u4E8E\u5F02\u6B65\u60C5\u51B5\u4E0B\u4F60\u9700\u8981\u4F7F\u7528 wait \u65B9\u6CD5\u6765\u5F97\u5230\u7ED3\u679C\uFF0Cget \u65B9\u6CD5\u5C06\u4E0D\u518D\u8D77\u4F5C\u7528\u3002 \u793A\u4F8B\u5982\u4E0B \u8FD9\u6837\u6211\u4EEC\u7684\u67E5\u627E\u8FC7\u7A0B\u5C31\u662F\u5F02\u6B65\u8FD0\u884C\u4E86\uFF0C\u5B83\u5C06\u4E0D\u4F1A\u963B\u585E\u4E3B\u7EBF\u7A0B\uFF0C\u6BCF\u4E2A\u67E5\u627E\u90FD\u5C06\u5728\u5355\u72EC\u7684\u7EBF\u7A0B\u540C\u65F6\u8FDB\u884C\uFF0C\u53EF\u8FBE\u5230\u5E76\u884C\u4EFB\u52A1\u7684\u6548\u679C\u3002 \u7531\u4E8E\u6BCF\u6B21\u91CD\u65B0\u6253\u5F00\u5BBF\u4E3B\u90FD\u4F1A\u91CD\u65B0\u8FDB\u884C\u67E5\u627E\uFF0C\u5728\u5BBF\u4E3B\u7248\u672C\u4E0D\u53D8\u7684\u60C5\u51B5\u4E0B\u8FD9\u662F\u4E00\u79CD\u91CD\u590D\u6027\u80FD\u6D6A\u8D39\u3002 \u6B64\u65F6\u6211\u4EEC\u53EF\u4EE5\u901A\u8FC7\u6307\u5B9A \u672C\u5730\u7F13\u5B58\u4F7F\u7528\u7684\u662F \u542F\u7528\u672C\u5730\u7F13\u5B58\u540E\uFF0C\u5C06\u540C\u65F6\u8BBE\u7F6E \u793A\u4F8B\u5982\u4E0B \u5982\u679C\u4F60\u60F3\u624B\u52A8\u6E05\u9664\u672C\u5730\u7F13\u5B58\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u65B9\u6CD5\u6E05\u9664\u5F53\u524D\u7248\u672C\u7684\u5BBF\u4E3B\u7F13\u5B58\u3002 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u6E05\u9664\u6307\u5B9A\u7248\u672C\u7684\u5BBF\u4E3B\u7F13\u5B58\u3002 \u793A\u4F8B\u5982\u4E0B \u5982\u679C\u4F60\u9700\u8981\u4F7F\u7528\u56FA\u5B9A\u7684\u6761\u4EF6\u540C\u65F6\u67E5\u627E\u4E00\u7EC4 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ClassLoader.searchClass\u3001PackageParam.searchClass \u65B9\u6CD5\u3002 \u8FD9\u91CC\u662F Class \u5B57\u8282\u7801\u6210\u5458\u53D8\u91CF Field\u3001Method\u3001Constructor \u76F8\u5173\u7684\u6269\u5C55\u529F\u80FD\u3002 \u5C0F\u63D0\u793A Member \u662F Field\u3001Method\u3001Constructor \u7684\u63A5\u53E3\u63CF\u8FF0\u5BF9\u8C61\uFF0C\u5B83\u5728 Java \u53CD\u5C04\u4E2D\u4E3A Class \u4E2D\u5B57\u8282\u7801\u6210\u5458\u7684\u603B\u79F0\u3002 \u5047\u8BBE\u6709\u4E00\u4E2A\u8FD9\u6837\u7684 \u793A\u4F8B\u5982\u4E0B \u5047\u8BBE\u6211\u4EEC\u8981\u5F97\u5230 \u793A\u4F8B\u5982\u4E0B \u8FD9\u79CD\u5199\u6CD5\u5927\u6982\u4E0D\u662F\u5F88\u53CB\u597D\uFF0C\u6B64\u65F6 \u4EE5\u4E0A\u5199\u6CD5\u6362\u505A \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MethodFinder\u3002 \u540C\u6837\u5730\uFF0C\u6211\u4EEC\u9700\u8981\u5F97\u5230 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 FieldFinder\u3002 \u4E5F\u8BB8\u4F60\u8FD8\u60F3\u5F97\u5230\u5F53\u524D \u793A\u4F8B\u5982\u4E0B \u82E5\u60F3\u5F97\u5230\u7684\u662F \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ConstructorFinder\u3002 \u5047\u8BBE\u6211\u4EEC\u8981\u5F97\u5230 \u793A\u4F8B\u5982\u4E0B \u901A\u8FC7\u89C2\u5BDF\u53D1\u73B0\uFF0C\u8FD9\u4E2A \u793A\u4F8B\u5982\u4E0B \u662F\u7684\uFF0C\u5BF9\u4E8E\u786E\u5207\u4E0D\u4F1A\u53D8\u5316\u7684\u65B9\u6CD5\uFF0C\u4F60\u53EF\u4EE5\u7CBE\u7B80\u67E5\u627E\u6761\u4EF6\u3002 \u5728\u53EA\u4F7F\u7528 \u95EE\u9898\u53C8\u6765\u4E86\uFF0C\u8FD9\u4E2A \u901A\u5E38\u60C5\u51B5\u4E0B\u6211\u4EEC\u4F1A\u4F7F\u7528 \u6B64\u65F6\uFF0C\u5728\u786E\u5B9A\u65B9\u6CD5\u552F\u4E00\u6027\u540E\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u4E0A\u8FF0\u793A\u4F8B\u867D\u7136\u80FD\u591F\u5339\u914D\u6210\u529F\uFF0C\u4F46\u662F\u4E0D\u7CBE\u786E\uFF0C\u6B64\u65F6\u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u4F60\u4F1A\u6CE8\u610F\u5230 \u53C2\u7167\u4E0A\u9762\u7684\u67E5\u627E\u6761\u4EF6\uFF0C\u6211\u4EEC\u53EA\u9700\u8981\u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u52A0\u5165\u4E00\u4E2A \u793A\u4F8B\u5982\u4E0B \u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u5C31\u53EF\u4EE5\u5728\u7236\u7C7B\u4E2D\u53D6\u5230\u8FD9\u4E2A\u65B9\u6CD5\u4E86\u3002 \u7531\u4E8E\u6211\u4EEC\u73B0\u5728\u5DF2\u77E5 \u793A\u4F8B\u5982\u4E0B \u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u540C\u6837\u53EF\u4EE5\u5F97\u5230\u7236\u7C7B\u4E2D\u7684\u8FD9\u4E2A\u65B9\u6CD5\u3002 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MethodFinder.superClass\u3001ConstructorFinder.superClass\u3001FieldFinder.superClass \u65B9\u6CD5\u3002 \u7279\u522B\u6CE8\u610F \u5F53\u524D\u67E5\u627E\u7684 Method \u9664\u975E\u6307\u5B9A superClass \u6761\u4EF6\uFF0C\u5426\u5219\u53EA\u80FD\u67E5\u627E\u5230\u5F53\u524D Class \u7684 Method\uFF0C\u8FD9\u662F Java \u53CD\u5C04 API \u7684\u9ED8\u8BA4\u884C\u4E3A\u3002 \u5982\u679C\u6211\u4EEC\u60F3\u67E5\u627E\u4E00\u4E2A\u65B9\u6CD5\u540D\u79F0\uFF0C\u4F46\u662F\u53C8\u4E0D\u786E\u5B9A\u5B83\u5728\u6BCF\u4E2A\u7248\u672C\u4E2D\u662F\u5426\u53D1\u751F\u53D8\u5316\uFF0C\u6B64\u65F6\u6211\u4EEC\u5C31\u53EF\u4EE5\u4F7F\u7528\u6A21\u7CCA\u67E5\u627E\u529F\u80FD\u3002 \u5047\u8BBE\u6211\u4EEC\u8981\u5F97\u5230 \u793A\u4F8B\u5982\u4E0B \u5DF2\u77E5\u5F53\u524D \u793A\u4F8B\u5982\u4E0B \u6211\u4EEC\u8FD8\u53EF\u4EE5\u6839\u636E\u9996\u5C3E\u5B57\u7B26\u4E32\u8FDB\u884C\u5224\u65AD\u3002 \u793A\u4F8B\u5982\u4E0B \u901A\u8FC7\u89C2\u5BDF\u53D1\u73B0\u8FD9\u4E2A\u65B9\u6CD5\u540D\u79F0\u4E2D\u53EA\u5305\u542B\u5B57\u6BCD\uFF0C\u6211\u4EEC\u8FD8\u53EF\u4EE5\u518D\u589E\u52A0\u4E00\u4E2A\u7CBE\u786E\u7684\u67E5\u627E\u6761\u4EF6\u3002 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u4F7F\u7528 name { ... } \u521B\u5EFA\u4E00\u4E2A\u6761\u4EF6\u65B9\u6CD5\u4F53\uFF0C\u5176\u4E2D\u7684\u53D8\u91CF it \u5373\u5F53\u524D\u540D\u79F0\u7684\u5B57\u7B26\u4E32\uFF0C\u6B64\u65F6\u4F60\u5C31\u53EF\u4EE5\u5728 NameRules \u7684\u6269\u5C55\u65B9\u6CD5\u4E2D\u81EA\u7531\u4F7F\u7528\u5176\u4E2D\u7684\u529F\u80FD\u3002 \u65B9\u6CD5\u4F53\u672B\u5C3E\u6761\u4EF6\u9700\u8981\u8FD4\u56DE\u4E00\u4E2A Boolean\uFF0C\u5373\u6700\u7EC8\u7684\u6761\u4EF6\u5224\u65AD\u7ED3\u679C\u3002 \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 NameRules\u3002 \u6709\u4E9B\u65F6\u5019\uFF0C\u6211\u4EEC\u53EF\u80FD\u9700\u8981\u67E5\u627E\u4E00\u4E2A \u5728\u67E5\u627E\u6761\u4EF6\u7ED3\u679C\u7684\u57FA\u7840\u4E0A\uFF0C\u6211\u4EEC\u53EA\u9700\u8981\u628A \u5047\u8BBE\u8FD9\u6B21\u6211\u4EEC\u8981\u5F97\u5230 \u793A\u4F8B\u5982\u4E0B \u4E0A\u8FF0\u793A\u4F8B\u53EF\u5B8C\u7F8E\u5339\u914D\u5230\u5982\u4E0B 3 \u4E2A\u65B9\u6CD5\u3002 \u5982\u679C\u4F60\u60F3\u66F4\u52A0\u81EA\u7531\u5730\u5B9A\u4E49\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u7684\u6761\u4EF6\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5B9E\u73B0\u3002 \u793A\u4F8B\u5982\u4E0B \u4E0A\u8FF0\u793A\u4F8B\u53EF\u5B8C\u7F8E\u5339\u914D\u5230\u5982\u4E0B 6 \u4E2A\u65B9\u6CD5\u3002 \u901A\u8FC7\u89C2\u5BDF \u793A\u4F8B\u5982\u4E0B \u4E0A\u8FF0\u793A\u4F8B\u53EF\u5B8C\u7F8E\u5339\u914D\u5230\u5982\u4E0B 2 \u4E2A\u65B9\u6CD5\u3002 \u5C0F\u63D0\u793A \u4F7F\u7528 paramCount { ... } \u521B\u5EFA\u4E00\u4E2A\u6761\u4EF6\u65B9\u6CD5\u4F53\uFF0C\u5176\u4E2D\u7684\u53D8\u91CF it \u5373\u5F53\u524D\u53C2\u6570\u4E2A\u6570\u7684\u6574\u6570\uFF0C\u6B64\u65F6\u4F60\u5C31\u53EF\u4EE5\u5728 CountRules \u7684\u6269\u5C55\u65B9\u6CD5\u4E2D\u81EA\u7531\u4F7F\u7528\u5176\u4E2D\u7684\u529F\u80FD\u3002 \u65B9\u6CD5\u4F53\u672B\u5C3E\u6761\u4EF6\u9700\u8981\u8FD4\u56DE\u4E00\u4E2A Boolean\uFF0C\u5373\u6700\u7EC8\u7684\u6761\u4EF6\u5224\u65AD\u7ED3\u679C\u3002 \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 CountRules\u3002 \u6709\u4E9B\u65B9\u6CD5\u548C\u53D8\u91CF\u5728 \u5047\u8BBE\u6211\u4EEC\u8FD9\u6B21\u8981\u5F97\u5230\u9759\u6001\u53D8\u91CF \u793A\u4F8B\u5982\u4E0B \u5047\u8BBE \u52A0\u5165\u4E00\u4E2A\u7B5B\u9009\u6761\u4EF6\u5373\u53EF\u3002 \u793A\u4F8B\u5982\u4E0B \u6211\u4EEC\u8FD8\u53EF\u4EE5\u8C03\u7528\u540D\u4E3A \u793A\u4F8B\u5982\u4E0B \u540C\u6837\u5730\uFF0C\u4F60\u53EF\u4EE5\u6807\u8BC6\u5B83\u662F\u4E00\u4E2A\u9759\u6001\u3002 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u4F7F\u7528 modifiers { ... } \u521B\u5EFA\u4E00\u4E2A\u6761\u4EF6\u65B9\u6CD5\u4F53\uFF0C\u6B64\u65F6\u4F60\u5C31\u53EF\u4EE5\u5728 ModifierRules \u4E2D\u81EA\u7531\u4F7F\u7528\u5176\u4E2D\u7684\u529F\u80FD\u3002 \u65B9\u6CD5\u4F53\u672B\u5C3E\u6761\u4EF6\u9700\u8981\u8FD4\u56DE\u4E00\u4E2A Boolean\uFF0C\u5373\u6700\u7EC8\u7684\u6761\u4EF6\u5224\u65AD\u7ED3\u679C\u3002 \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ModifierRules\u3002 \u4F60\u53EF\u80FD\u5DF2\u7ECF\u6CE8\u610F\u5230\u4E86\uFF0C\u8FD9\u91CC\u7ED9\u51FA\u7684\u793A\u4F8B \u6709\u4E24\u79CD\u65B9\u6848\u3002 \u7B2C\u4E00\u79CD\u65B9\u6848\uFF0C\u786E\u5B9A\u53D8\u91CF\u7684\u540D\u79F0\u548C\u7C7B\u578B\u3002 \u793A\u4F8B\u5982\u4E0B \u7B2C\u4E8C\u79CD\u65B9\u6848\uFF0C\u786E\u5B9A\u53D8\u91CF\u7684\u7C7B\u578B\u6240\u5728\u7684\u4F4D\u7F6E\u3002 \u793A\u4F8B\u5982\u4E0B \u4EE5\u4E0A\u4E24\u79CD\u60C5\u51B5\u5747\u53EF\u5F97\u5230\u5BF9\u5E94\u7684\u53D8\u91CF \u540C\u6837\u5730\uFF0C\u8FD9\u4E2A \u4F60\u4E5F\u53EF\u4EE5\u6709\u4E24\u79CD\u65B9\u6848\u6765\u5F97\u5230\u5B83\u4EEC\u3002 \u7B2C\u4E00\u79CD\u65B9\u6848\uFF0C\u786E\u5B9A\u65B9\u6CD5\u7684\u540D\u79F0\u548C\u65B9\u6CD5\u53C2\u6570\u3002 \u793A\u4F8B\u5982\u4E0B \u7B2C\u4E8C\u79CD\u65B9\u6848\uFF0C\u786E\u5B9A\u65B9\u6CD5\u7684\u53C2\u6570\u6240\u5728\u7684\u4F4D\u7F6E\u3002 \u793A\u4F8B\u5982\u4E0B \u7531\u4E8E\u89C2\u5BDF\u5230\u8FD9\u4E2A\u65B9\u6CD5\u5728 \u793A\u4F8B\u5982\u4E0B \u6CE8\u610F \u8BF7\u5C3D\u91CF\u907F\u514D\u4F7F\u7528 order \u6765\u7B5B\u9009\u5B57\u8282\u7801\u7684\u4E0B\u6807\uFF0C\u5B83\u4EEC\u53EF\u80FD\u662F\u4E0D\u786E\u5B9A\u7684\uFF0C\u9664\u975E\u4F60\u786E\u5B9A\u5B83\u5728\u8FD9\u4E2A Class \u4E2D\u7684\u4F4D\u7F6E\u4E00\u5B9A\u4E0D\u4F1A\u53D8\u3002 \u4E0A\u9762\u4ECB\u7ECD\u7684\u8C03\u7528\u5B57\u8282\u7801\u7684\u65B9\u6CD5\u90FD\u9700\u8981\u4F7F\u7528 \u6B64\u65F6\uFF0C\u4F60\u53EF\u4EE5\u5728\u4EFB\u610F\u5B9E\u4F8B\u4E0A\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u6211\u4EEC\u8FD8\u53EF\u4EE5\u7528 \u793A\u4F8B\u5982\u4E0B \u5982\u679C\u4F60\u4E0D\u559C\u6B22\u4F7F\u7528\u4E00\u4E2A\u5927\u62EC\u53F7\u7684\u8C03\u7528\u57DF\u6765\u521B\u5EFA\u5F53\u524D\u5B9E\u4F8B\u7684\u547D\u540D\u7A7A\u95F4\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u540C\u6837\u5730\uFF0C\u5B83\u4EEC\u4E4B\u95F4\u53EF\u4EE5\u8FDE\u7EED\u8C03\u7528\uFF0C\u4F46\u4E0D\u5141\u8BB8\u5185\u8054\u8C03\u7528\u3002 \u793A\u4F8B\u5982\u4E0B \u9488\u5BF9 \u793A\u4F8B\u5982\u4E0B \u6CE8\u610F \u4E0A\u8FF0 current \u65B9\u6CD5\u76F8\u5F53\u4E8E\u5E2E\u4F60\u8C03\u7528\u4E86 CurrentClass \u4E2D\u7684 field { ... }.any()?.current() \u65B9\u6CD5\u3002 \u82E5\u4E0D\u5B58\u5728 CurrentClass \u8C03\u7528\u57DF\uFF0C\u4F60\u9700\u8981\u4F7F\u7528 field { ... }.get(instance).current() \u6765\u8FDB\u884C\u8C03\u7528\u3002 \u95EE\u9898\u53C8\u6765\u4E86\uFF0C\u6211\u60F3\u4F7F\u7528\u53CD\u5C04\u7684\u65B9\u5F0F\u521B\u5EFA\u5982\u4E0B\u7684\u5B9E\u4F8B\u5E76\u8C03\u7528\u5176\u4E2D\u7684\u65B9\u6CD5\uFF0C\u8BE5\u600E\u4E48\u505A\u5462\uFF1F \u793A\u4F8B\u5982\u4E0B \u901A\u5E38\u60C5\u51B5\u4E0B\uFF0C\u6211\u4EEC\u53EF\u4EE5\u4F7F\u7528\u6807\u51C6\u7684\u53CD\u5C04 API \u6765\u8C03\u7528\u3002 \u793A\u4F8B\u5982\u4E0B \u4F46\u662F\u611F\u89C9\u8FD9\u79CD\u505A\u6CD5\u597D\u9EBB\u70E6\uFF0C\u6709\u6CA1\u6709\u66F4\u7B80\u6D01\u7684\u8C03\u7528\u65B9\u6CD5\u5462\uFF1F \u8FD9\u4E2A\u65F6\u5019\uFF0C\u6211\u4EEC\u8FD8\u53EF\u4EE5\u501F\u52A9 \u793A\u4F8B\u5982\u4E0B \u82E5\u4F60\u5E0C\u671B \u8FD9\u79CD\u60C5\u51B5\u591A\u7528\u4E8E\u5B9E\u4F8B\u672C\u8EAB\u7684\u6784\u9020\u65B9\u6CD5\u662F\u79C1\u6709\u7684\uFF0C\u4F46\u662F\u91CC\u9762\u7684\u65B9\u6CD5\u662F\u516C\u6709\u7684\uFF0C\u8FD9\u6837\u6211\u4EEC\u53EA\u9700\u8981\u5BF9\u5176\u6784\u9020\u65B9\u6CD5\u8FDB\u884C\u53CD\u5C04\u521B\u5EFA\u5373\u53EF\u3002 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 CurrentClass \u4EE5\u53CA Class.buildOf \u65B9\u6CD5\u3002 \u82E5\u4F60\u6B63\u5728\u4F7F\u7528\u53CD\u5C04\u8C03\u7528\u7684\u4E00\u4E2A\u65B9\u6CD5\u662F\u88AB Hook \u8FC7\u7684\uFF0C\u6B64\u65F6\u6211\u4EEC\u5982\u4F55\u8C03\u7528\u5176\u539F\u59CB\u65B9\u6CD5\u5462\uFF1F \u539F\u751F\u7684 \u73B0\u5728\uFF0C\u5728 \u5047\u8BBE\u4E0B\u9762\u662F\u6211\u4EEC\u8981\u6F14\u793A\u7684 \u793A\u4F8B\u5982\u4E0B \u4E0B\u9762\u662F Hook \u8FD9\u4E2A \u793A\u4F8B\u5982\u4E0B \u6B64\u65F6\uFF0C\u6211\u4EEC\u518D\u4F7F\u7528\u53CD\u5C04\u8C03\u7528\u8FD9\u4E2A\u65B9\u6CD5\uFF0C\u5219\u4F1A\u5F97\u5230 Hook \u540E\u7684\u7ED3\u679C \u793A\u4F8B\u5982\u4E0B \u5982\u679C\u6211\u4EEC\u60F3\u5F97\u5230\u8FD9\u4E2A\u65B9\u6CD5\u672A\u7ECF Hook \u7684\u539F\u59CB\u65B9\u6CD5\u53CA\u7ED3\u679C\uFF0C\u53EA\u9700\u8981\u5728\u7ED3\u679C\u4E2D\u52A0\u5165 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MethodFinder.Result.original \u65B9\u6CD5\u3002 \u5047\u8BBE\u6709\u4E09\u4E2A\u4E0D\u540C\u7248\u672C\u7684 \u8FD9\u91CC\u9762\u540C\u6837\u90FD\u6709\u4E00\u4E2A\u65B9\u6CD5 \u7248\u672C A \u793A\u4F8B\u5982\u4E0B \u7248\u672C B \u793A\u4F8B\u5982\u4E0B \u7248\u672C C \u793A\u4F8B\u5982\u4E0B \u6211\u4EEC\u9700\u8981\u5728\u4E0D\u540C\u7684\u7248\u672C\u4E2D\u5F97\u5230\u8FD9\u4E2A\u76F8\u540C\u529F\u80FD\u7684 \u6B64\u65F6\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u7279\u522B\u6CE8\u610F \u4F7F\u7528\u4E86 RemedyPlan \u7684\u65B9\u6CD5\u67E5\u627E\u7ED3\u679C\u4E0D\u80FD\u518D\u4F7F\u7528 get \u7684\u65B9\u5F0F\u5F97\u5230\u65B9\u6CD5\u5B9E\u4F8B\uFF0C\u5E94\u5F53\u4F7F\u7528 wait \u65B9\u6CD5\u3002 \u53E6\u5916\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u5728\u4F7F\u7528 \u591A\u91CD\u67E5\u627E \u7684\u60C5\u51B5\u4E0B\u7EE7\u7EED\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u4EE5\u5F53\u524D \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u5728\u521B\u5EFA Hook \u7684\u65F6\u5019\u4F7F\u7528\u53EF\u53C2\u8003 MethodFinder.Process.all\u3001ConstructorFinder.Process.all \u65B9\u6CD5\u3002 \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MethodFinder.RemedyPlan\u3001ConstructorFinder.RemedyPlan\u3001FieldFinder.RemedyPlan\u3002 \u5047\u8BBE\u5BBF\u4E3B\u4E2D\u4E0D\u540C\u7248\u672C\u4E2D\u5B58\u5728\u529F\u80FD\u76F8\u540C\u7684 \u7248\u672C A \u793A\u4F8B\u5982\u4E0B \u7248\u672C B \u793A\u4F8B\u5982\u4E0B \u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u60F3\u5728\u6BCF\u4E2A\u7248\u672C\u90FD\u8C03\u7528\u8FD9\u4E2A \u901A\u5E38\u505A\u6CD5\u662F\u5224\u65AD \u793A\u4F8B\u5982\u4E0B \u611F\u89C9\u8FD9\u79CD\u65B9\u6848\u975E\u5E38\u7684\u4E0D\u4F18\u96C5\u4E14\u7E41\u7410\uFF0C\u90A3\u4E48\u6B64\u65F6 \u73B0\u5728\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u83B7\u53D6\u5230\u8FD9\u4E2A \u793A\u4F8B\u5982\u4E0B \u82E5\u5F53\u524D \u793A\u4F8B\u5982\u4E0B \u82E5\u4F60\u4E0D\u786E\u5B9A\u6240\u6709\u7684 \u793A\u4F8B\u5982\u4E0B \u82E5\u4F60\u6B63\u5728 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 VariousClass\u3002 \u82E5\u5728\u521B\u5EFA Hook \u7684\u65F6\u5019\u4F7F\u7528\uFF0C\u53EF\u4EE5\u66F4\u52A0\u65B9\u4FBF\uFF0C\u8FD8\u53EF\u4EE5\u81EA\u52A8\u62E6\u622A\u627E\u4E0D\u5230 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u628A\u8FD9\u4E2A \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 PackageParam.findClass \u65B9\u6CD5\u3002 \u5728\u53CD\u5C04\u8FC7\u7A0B\u4E2D\uFF0C\u6211\u4EEC\u53EF\u80FD\u4F1A\u9047\u5230\u6CDB\u578B\u95EE\u9898\uFF0C\u5728\u6CDB\u578B\u7684\u53CD\u5C04\u5904\u7406\u4E0A\uFF0C \u4F8B\u5982\u6211\u4EEC\u6709\u5982\u4E0B\u7684\u6CDB\u578B\u7C7B\u3002 \u793A\u4F8B\u5982\u4E0B \u5F53\u6211\u4EEC\u60F3\u5728\u5F53\u524D \u793A\u4F8B\u5982\u4E0B \u5F53\u6211\u4EEC\u60F3\u5728\u5916\u90E8\u8C03\u7528\u8FD9\u4E2A \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 CurrentClass.generic\u3001Class.generic \u65B9\u6CD5\u4EE5\u53CA GenericClass\u3002 \u8FD9\u91CC\u5217\u4E3E\u4E86\u4F7F\u7528\u65F6\u53EF\u80FD\u4F1A\u9047\u5230\u7684\u8BEF\u533A\u90E8\u5206\uFF0C\u53EF\u4F9B\u53C2\u8003\u3002 \u7279\u522B\u6CE8\u610F \u5728\u67E5\u627E\u6761\u4EF6\u4E2D\uFF0C\u9664\u4E86 order \u4F60\u53EA\u80FD\u4F7F\u7528\u4E00\u6B21 index \u529F\u80FD\u3002 \u793A\u4F8B\u5982\u4E0B \u4EE5\u4E0B\u67E5\u627E\u6761\u4EF6\u7684\u4F7F\u7528\u662F\u6CA1\u6709\u4EFB\u4F55\u95EE\u9898\u7684\u3002 \u793A\u4F8B\u5982\u4E0B \u7279\u522B\u6CE8\u610F \u5728\u666E\u901A\u65B9\u6CD5\u67E5\u627E\u6761\u4EF6\u4E2D\uFF0C\u5373\u4F7F\u662F\u65E0\u53C2\u7684\u65B9\u6CD5\u4E5F\u9700\u8981\u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\u3002 \u5047\u8BBE\u6211\u4EEC\u6709\u5982\u4E0B\u7684 \u793A\u4F8B\u5982\u4E0B \u6211\u4EEC\u8981\u5F97\u5230\u5176\u4E2D\u7684 \u793A\u4F8B\u5982\u4E0B \u4F46\u662F\uFF0C\u4E0A\u9762\u7684\u4F8B\u5B50\u662F\u9519\u8BEF\u7684\u3002 \u4F60\u4F1A\u53D1\u73B0\u8FD9\u4E2A \u7531\u4E8E\u4E0A\u8FF0\u4F8B\u5B50\u6CA1\u6709\u8BBE\u7F6E \u8FD9\u662F\u4E00\u4E2A\u7ECF\u5E38\u4F1A\u51FA\u73B0\u7684\u9519\u8BEF\uFF0C\u6CA1\u6709\u65B9\u6CD5\u53C2\u6570\u5C31\u4F1A\u4E22\u5931\u65B9\u6CD5\u53C2\u6570\u67E5\u627E\u6761\u4EF6\u7684\u4F7F\u7528\u95EE\u9898\u3002 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\u5982\u4E0B\u3002 \u793A\u4F8B\u5982\u4E0B \u81F3\u6B64\uFF0C\u4E0A\u8FF0\u7684\u793A\u4F8B\u5C06\u53EF\u4EE5\u5B8C\u7F8E\u5730\u5339\u914D\u5230 \u517C\u5BB9\u6027\u8BF4\u660E \u5728\u8FC7\u5F80\u5386\u53F2\u7248\u672C\u7684 API \u4E2D\u662F\u5141\u8BB8\u5339\u914D\u4E0D\u5199\u9ED8\u8BA4\u5339\u914D\u65E0\u53C2\u65B9\u6CD5\u7684\u505A\u6CD5\u7684\uFF0C\u4F46\u662F\u6700\u65B0\u7248\u672C\u66F4\u6B63\u4E86\u8FD9\u4E00\u95EE\u9898\uFF0C\u8BF7\u786E\u4FDD\u4F60\u4F7F\u7528\u7684\u662F\u6700\u65B0\u7684 API \u7248\u672C\u3002 \u5728\u6784\u9020\u65B9\u6CD5\u67E5\u627E\u6761\u4EF6\u4E2D\uFF0C\u65E0\u53C2\u7684\u6784\u9020\u65B9\u6CD5\u53EF\u4EE5\u4E0D\u9700\u8981\u586B\u5199\u67E5\u627E\u6761\u4EF6\u3002 \u5047\u8BBE\u6211\u4EEC\u6709\u5982\u4E0B\u7684 \u793A\u4F8B\u5982\u4E0B \u6211\u4EEC\u8981\u5F97\u5230\u5176\u4E2D\u7684 \u793A\u4F8B\u5982\u4E0B \u4E0A\u9762\u7684\u4F8B\u5B50\u53EF\u4EE5\u6210\u529F\u83B7\u53D6\u5230 \u4E0E\u666E\u901A\u65B9\u6CD5\u4E0D\u540C\uFF0C\u7531\u4E8E\u6784\u9020\u65B9\u6CD5\u4E0D\u9700\u8981\u8003\u8651 \u793A\u4F8B\u5982\u4E0B \u517C\u5BB9\u6027\u8BF4\u660E \u5728\u8FC7\u5F80\u5386\u53F2\u7248\u672C\u7684 API \u4E2D\u6784\u9020\u65B9\u6CD5\u4E0D\u586B\u5199\u4EFB\u4F55\u67E5\u627E\u53C2\u6570\u4F1A\u76F4\u63A5\u627E\u4E0D\u5230\u6784\u9020\u65B9\u6CD5\uFF0C\u8FD9\u662F\u4E00\u4E2A BUG\uFF0C\u6700\u65B0\u7248\u672C\u5DF2\u7ECF\u8FDB\u884C\u4FEE\u590D\uFF0C\u8BF7\u786E\u4FDD\u4F60\u4F7F\u7528\u7684\u662F\u6700\u65B0\u7684 API \u7248\u672C\u3002 \u7279\u522B\u6CE8\u610F \u5728\u5B57\u8282\u7801\u8C03\u7528\u7ED3\u679C\u4E2D\uFF0Ccast \u65B9\u6CD5\u53EA\u80FD\u6307\u5B9A\u5B57\u8282\u7801\u5BF9\u5E94\u7684\u7C7B\u578B\u3002 \u4F8B\u5982\u6211\u4EEC\u60F3\u5F97\u5230\u4E00\u4E2A \u4EE5\u4E0B\u662F\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5\u3002 \u793A\u4F8B\u5982\u4E0B \u4EE5\u4E0B\u662F\u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\u3002 \u793A\u4F8B\u5982\u4E0B \u5728\u67E5\u627E\u65B9\u6CD5\u3001\u53D8\u91CF\u7684\u65F6\u5019\u6211\u4EEC\u901A\u5E38\u9700\u8981\u6307\u5B9A\u6240\u67E5\u627E\u7684\u7C7B\u578B\u3002 \u793A\u4F8B\u5982\u4E0B \u5728 \u56E0\u6B64\uFF0C \u8FD9\u4E2A\u65F6\u5019\u4E0A\u9762\u7684\u7C7B\u578B\u5C31\u53EF\u4EE5\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u4E86\u3002 \u793A\u4F8B\u5982\u4E0B \u5728 Java \u4E2D\u5E38\u89C1\u7684\u57FA\u672C\u7C7B\u578B\u90FD\u5DF2\u88AB\u5C01\u88C5\u4E3A \u7C7B\u578B + Type \u7684\u65B9\u5F0F\uFF0C\u4F8B\u5982 \u76F8\u5E94\u5730\uFF0C\u6570\u7EC4\u7C7B\u578B\u4E5F\u6709\u65B9\u4FBF\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5047\u8BBE\u6211\u4EEC\u8981\u83B7\u5F97 \u9700\u8981\u5199\u505A \u611F\u89C9\u662F\u4E0D\u662F\u5F88\u9EBB\u70E6\uFF0C\u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u53EF\u4EE5\u4F7F\u7528\u6269\u5C55\u65B9\u6CD5 \u540C\u65F6\u7531\u4E8E \u4E00\u4E9B\u5E38\u89C1\u7684 Hook \u4E2D\u67E5\u627E\u7684\u65B9\u6CD5\uFF0C\u90FD\u6709\u5176\u5BF9\u5E94\u7684\u5C01\u88C5\u7C7B\u578B\u4EE5\u4F9B\u4F7F\u7528\uFF0C\u683C\u5F0F\u4E3A \u7C7B\u578B + Class\u3002 \u4F8B\u5982 Hook \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u7C7B\u578B\u53EF\u67E5\u770B ComponentTypeFactory\u3001GraphicsTypeFactory\u3001ViewTypeFactory\u3001VariableTypeFactory\u3002 \u540C\u65F6\uFF0C\u6B22\u8FCE\u4F60\u80FD\u8D21\u732E\u66F4\u591A\u7684\u5E38\u7528\u7C7B\u578B\u3002 Here are the extension functions related to the Class object itself. Suppose we want to get a Normally, we can use the standard reflection API to find this The following example This is probably not very friendly, and The above writing can be written as The following example If the current If you are not sure whether the The following example We can also get an existing The following example Tips For more functions, please refer to classOf, String.toClass, String.toClassOrNull, PackageParam \u2192 String+ VariousClass.toClass, PackageParam \u2192 String+VariousClass.toClassOrNull methods. Suppose we want to determine whether a Usually, we can use the standard reflection API to find this The following example This is probably not very friendly, and The above writing can be written as The following example Tips For more functions, please refer to String.hasClass, PackageParam \u2192 String.hasClass methods. The Its correct position is uncertain, and cannot be obtained directly through Object Conversion. At this point, there is Notice At present, the function of DexClassFinder is still in the experimental stage. Since the search function is only implemented through the Java layer, the performance may not reach the optimal level when there are too many Host App's Class. If something got wrong welcome to feedback. Since it is a reflection-level API, currently it can only locate the specified Class through the characteristics of Class and Member, and cannot locate it by specifying the string and method content characteristics in the bytecode. The speed of searching Class depends on the performance of the current device. At present, the mainstream mobile processors are in the 3~10s range when the conditions are not complicated in the 10~15w number of Class, the fastest speed can reach within 25s under slightly complex conditions. Please note that the more the same type Class is matched, the slower the speed. Below is a simple usage example. Suppose the following The following example At this point, we want to get this In Each of the conditions demonstrated below is optional, and the more complex the conditions, the more accurate the positioning and the worse the performance. The following example Tips The conditional usage of Field, Method, Constructor in the above usage is consistent with the related usage in Member Extensions, with only minor differences. For more functions, please refer to MemberRules, FieldRules, MethodRules, ConstructorRules. By default, If the search takes too long, it may cause ANR problems to the Host App. In response to the above problems, we can enable asynchronous, just add the parameter Notice For the asynchronous case you need to use the wait method to get the result, the get method will no longer work. The following example In this way, our search process runs asynchronously, it will not block the main thread, and each search will be performed in a separate thread at the same time, which can achieve the effect of parallel tasks. Since the search is performed again every time the Host App is reopened, this is a waste of repetitive performance when the Host App's version is unchanged. At this point, we can locally cache the search results of the current Host App's version by specifying the Next time, the found class name will be directly read from the local cache. The local cache uses After enabling the local cache, The following example If you want to clear the local cache manually, you can use the following method to clear the current version of the Host App's cache. The following example You can also clear the Host App's cache for a specific version. The following example If you need to search a set of Tips For more functions, please refer to ClassLoader.searchClass, PackageParam.searchClass methods. Here are the extension functions related to the Class bytecode member variables Field, Method, Constructor. Tips Member is the interface description object of Field, Method, Constructor, which is the general term for the bytecode members in Class in Java reflection. Suppose there is such a The following example Suppose we want to get the Normally, we can use the standard reflection API to find this method. The following example This is probably not very friendly, and The above writing can be written as The following example Tips For more features, please refer to MethodFinder. Similarly, we need to get the The following example Tips For more features, please refer to FieldFinder. Maybe you also want to get the current The following example If you want to get the no-argument constructor of The following example Tips For more features, please refer to ConstructorFinder. Suppose we want to get the The following example Through observation, it is found that there is only one method named The following example Yes, you can refine your find criteria for methods that do not change exactly. When using only The problem comes again, this Normally we would use At this point, after determining the uniqueness of the method, you can use The following example Although the above example can be successfully matched, it is not accurate. At this time, you can also use The following example You will notice that Referring to the above find conditions, we only need to add a The following example At this time, we can get this method in the super class. Since we now know that the The following example At this time, we can also get this method in the super class. Once Tips For more functions, please refer to MethodFinder.superClass, ConstructorFinder.superClass, FieldFinder.superClass methods. Pay Attention The currently founded Method can only find the Method of the current Class unless the superClass condition is specified, which is the default behavior of the Java Reflection API. If we want to find a method name, but are not sure if it has changed in each release, we can use vague find. Suppose we want to get the The following example Knowing that there is currently only one The following example We can also judge based on the first and last strings. The following example By observing that this method name contains only letters, we can add a precise search condition. The following example Tips Use name { ... } to create a conditional method body, where the variable it is the string of the current name, and you can freely use it in the extension method of NameRules function. The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result. For more functions, please refer to NameRules. Sometimes, we may need to find a set of methods, constructors, and fields with the same characteristics in a At this time, we can use relative condition matching to complete. Based on the result of the find condition, we only need to replace Suppose this time we want to get all methods in The following example The above example can be perfectly matched to the following 3 methods. If you want to define the conditions for the range of the number of parameters more freely, you can use the following implementation. The following example The above example can be perfectly matched to the following 6 methods. By observing that there are two methods named The following example The above example can be perfectly matched to the following 2 methods. Tips Use paramCount { ... } to create a conditional method body, where the variable it is the integer of the current number of parameters, and you can use it freely in the extension method of CountRules function in it. The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result. For more functions, please refer to CountRules. Some methods and fields are statically implemented in Suppose we want to get the contents of the static field The following example Assuming that there is a non-static Just add a filter. The following example We can also call a static method called The following example Likewise, you can identify it as a static. The following example Tips Use modifiers { ... } to create a conditional method body, at which point you can freely use its functionality in ModifierRules. The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result. For more features, please refer to ModifierRules. You may have noticed that the example There are two options. The first option is to determine the name and type of the field. The following example The second option is to determine where the type of the field is located. The following example In the above two cases, the corresponding field Likewise, there are two obfuscated method names in this You can also have two options to get them. The first option is to determine the method name and method parameters. The following example The second option is to determine where the parameters of the method are located. The following example Since it is observed that this method is last in The following example Notice Please try to avoid using order to filter bytecode subscripts, they may be indeterminate unless you are sure that its position in this Class must not change. The methods of calling bytecode described above all need to use Is there a simpler way? At this point, you can use the The following example We can also use The following example If you don't like to use a lambda to create the namespace of the current instance, you can use the The following example Likewise, consecutive calls can be made between them, but inline calls are not allowed. The following example For The following example Notice The above current method is equivalent to calling the field { ... }.any()?.current() method in CurrentClass for you. If there is no CurrentClass calling field, you need to use field { ... }.get(instance).current() to call it. The problem comes again, I want to use reflection to create the following instance and call the method in it, how to do it? The following example Usually, we can use the standard reflection API to call. The following example But I feel that this approach is very troublesome. Is there a more concise way to call it? At this time, we can also use the The following example If you want the In this case, the constructor of the instance itself is private, but the method inside is public, so we only need to create its constructor by reflection. The following example Tips For more functions, please refer to CurrentClass and Class.buildOf method. If you are using reflection to call a method that has been hooked, how do we call its original method? The native Now, in Suppose below is the The following example Here's how the The following example At this point, we use reflection to call this method, and we will get the result of Hook The following example If we want to get the original method and result of this method without hooking, we just need to add The following example Tips For more functions, please refer to the MethodFinder.Result.original method. Suppose there are three different versions of There is also a method The following example of version A The following example of version B The following example of version C We need to get this same functionality of the At this point, you can use The following example Pay Attention The method lookup result using RemedyPlan can no longer use get to get method instance, you should use wait method. Also, you can continue to use The following example Take the current The following example Tips When creating a Hook, please refer to MethodFinder.Process.all, ConstructorFinder.Process.all methods. For more functions, please refer to MethodFinder.RemedyPlan, ConstructorFinder.RemedyPlan, FieldFinder.RemedyPlan . Suppose there is a The following example of version A The following example of version B At this time, what should we do if we want to call the The usual practice is to check if The following example I feel that this solution is very inelegant and cumbersome, then Now, you can get this The following example If the current The following example If you are not sure that all The following example If you are using the The following example Tips For more functions, please refer to VariousClass. If it is used when creating a Hook, it can be more convenient, and it can also automatically intercept the exception that The following example You can also define this The following example Tips For more functions, please refer to the PackageParam.findClass method. In the process of reflection, we may encounter generic problems. In the reflection processing of generics, For example we have the following generic class. The following example When we want to get a The following example When we want to call this The following example Tips For more functions, please refer to CurrentClass.generic, Class.generic methods and GenericClass. Here are some misunderstandings that may be encountered during use for reference. Pay Attention In find conditions you can only use index function once except order. The following example The following find conditions can be used without any problems. The following example Pay Attention In common method find conditions, even methods without parameters need to set find conditions. Suppose we have the following The following example We want to get the The following example However, the above example is wrong. You will find two Since the above example does not set the find conditions for This is a frequent error, without method parameters, you will lose the use of method parameter find conditions. The correct usage is as follows. The following example At this point, the above example will perfectly match the Compatibility Notes In the past historical versions of the API, it was allowed to match the method without writing the default matching no-parameter method, but the latest version has corrected this problem, please make sure that you are using the latest API version. In the construction method find conditions, constructors without parameters do not need to fill in the find conditions. Suppose we have the following The following example We want to get the The following example The above example can successfully obtain the Unlike normal methods, since the constructor does not need to consider the The following example Compatibility Notes In the past historical versions of the API, if the constructor does not fill in any find conditions, the constructor will not be found directly. This is a bug, the latest version has been fixed, please make sure you are using the latest API version. Pay Attention In the bytecode call result, the cast method can only specify the type corresponding to the bytecode. For example we want to get a field of type The following is the wrong way to use it. The following example The following is the correct way to use it. The following example When find methods and fields, we usually need to specify the type in find conditions. The following example Expressing the type Therefore, At this time, the above type can be written in the following form. The following example Common basic types in Java have been encapsulated as Name + Type, such as Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type You need to write Does it feel very troublesome? At this time, we can use the extension method At the same time, since Some common methods found in Hook have their corresponding encapsulation types for use, in the format Name + Class. For example, the Hook The following example Tips For more types, see ComponentTypeFactory, GraphicsTypeFactory, ViewTypeFactory, VariableTypeFactory. At the same time, you are welcome to contribute more commonly used types. \u8FD9\u662F\u4E00\u4E2A\u4F7F\u7528\u7CFB\u7EDF\u65E0\u5E8F\u5E7F\u64AD\u5728\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E4B\u95F4\u53D1\u9001\u548C\u63A5\u6536\u6570\u636E\u7684\u89E3\u51B3\u65B9\u6848\u3002 \u9700\u8981\u6EE1\u8DB3\u7684\u6761\u4EF6 \u6A21\u5757\u4E0E\u5BBF\u4E3B\u9700\u8981\u4FDD\u6301\u5B58\u6D3B\u72B6\u6001\uFF0C\u5426\u5219\u65E0\u6CD5\u5EFA\u7ACB\u901A\u8BAF\u3002 \u8FD9\u91CC\u63CF\u8FF0\u4E86 \u901A\u8FC7\u4F7F\u7528 \u6A21\u5757\u793A\u4F8B\u5982\u4E0B \u5BBF\u4E3B\u793A\u4F8B\u5982\u4E0B \u4F60\u53EF\u4EE5\u4E0D\u8BBE\u7F6E \u6A21\u5757\u793A\u4F8B\u5982\u4E0B \u5BBF\u4E3B\u793A\u4F8B\u5982\u4E0B \u7279\u522B\u6CE8\u610F \u63A5\u6536\u65B9\u9700\u8981\u4FDD\u6301\u5B58\u6D3B\u72B6\u6001\u624D\u80FD\u6536\u5230\u901A\u8BAF\u6570\u636E\u3002 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiHookDataChannel\u3002 \u901A\u8FC7\u901A\u8BAF\u6865\u529F\u80FD\uFF0C \u6211\u4EEC\u53EA\u9700\u8981\u8C03\u7528 \u5728\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E2D\u53EF\u8FDB\u884C\u53CC\u5411\u5224\u65AD\u3002 \u4F60\u53EF\u4EE5\u5728\u6A21\u5757\u4E2D\u5224\u65AD\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u662F\u5426\u4E0E\u5F53\u524D\u6A21\u5757\u7684\u7248\u672C\u5339\u914D\u3002 \u793A\u4F8B\u5982\u4E0B \u4F60\u8FD8\u53EF\u4EE5\u5728\u5BBF\u4E3B\u4E2D\u5224\u65AD\u662F\u5426\u81EA\u8EAB\u4E0E\u5F53\u524D\u6A21\u5757\u7684\u7248\u672C\u5339\u914D\u3002 \u793A\u4F8B\u5982\u4E0B \u65B9\u6CD5\u56DE\u8C03\u7684\u6761\u4EF6 \u5BBF\u4E3B\u3001\u6A21\u5757\u4FDD\u6301\u5B58\u6D3B\u72B6\u6001\uFF0C\u5E76\u5728\u6FC0\u6D3B\u6A21\u5757\u540E\u91CD\u542F\u4E86\u4F5C\u7528\u57DF\u4E2D\u7684 Hook \u76EE\u6807\u5BBF\u4E3B\u5BF9\u8C61\u3002 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiHookDataChannel\u3002 \u8FD9\u91CC\u53EA\u5217\u51FA\u4E86\u5728\u6A21\u5757\u4E2D\u4F7F\u7528\u7684\u4F8B\u5B50\uFF0C\u5728\u5BBF\u4E3B\u4E2D\u76F8\u540C\u7684 \u7279\u522B\u6CE8\u610F \u5728\u6A21\u5757\u548C\u5BBF\u4E3B\u4E2D\uFF0C\u6BCF\u4E00\u4E2A dataChannel \u5BF9\u5E94\u7684 key \u7684\u56DE\u8C03\u4E8B\u4EF6\u90FD\u4E0D\u5141\u8BB8\u91CD\u590D\u521B\u5EFA\uFF0C\u82E5\u91CD\u590D\uFF0C\u4E4B\u524D\u7684\u56DE\u8C03\u4E8B\u4EF6\u4F1A\u88AB\u65B0\u589E\u52A0\u7684\u56DE\u8C03\u4E8B\u4EF6\u66FF\u6362\uFF0C\u82E5\u5728\u6A21\u5757\u4E2D\u4F7F\u7528\uFF0C\u5728\u540C\u4E00\u4E2A Activity \u4E2D\u4E0D\u53EF\u4EE5\u91CD\u590D\uFF0C\u4E0D\u540C\u7684 Activity \u4E2D\u76F8\u540C\u7684 key \u5141\u8BB8\u91CD\u590D\u3002 \u793A\u4F8B\u5982\u4E0B \u5728\u4E0A\u8FF0\u793A\u4F8B\u4E2D\uFF0C\u56DE\u8C03\u4E8B\u4EF6 A \u4F1A\u88AB\u56DE\u8C03\u4E8B\u4EF6 B \u66FF\u6362\u6389\uFF0C\u56DE\u8C03\u4E8B\u4EF6 C \u7684 \u7279\u522B\u6CE8\u610F \u4E00\u4E2A\u76F8\u540C key \u7684\u56DE\u8C03\u4E8B\u4EF6\u53EA\u4F1A\u56DE\u8C03\u5F53\u524D\u6A21\u5757\u6B63\u5728\u663E\u793A\u7684 Activity \u4E2D\u6CE8\u518C\u7684\u56DE\u8C03\u4E8B\u4EF6\uFF0C\u4F8B\u5982\u4E0A\u8FF0\u4E2D\u7684 test_key\uFF0C\u5982\u679C OtherActivity \u6B63\u5728\u663E\u793A\uFF0C\u90A3\u4E48 MainActivity \u4E2D\u7684 test_key \u5C31\u4E0D\u4F1A\u88AB\u56DE\u8C03\u3002 \u76F8\u540C\u7684 key \u5728\u540C\u4E00\u4E2A Activity \u4E0D\u540C\u7684 Fragment \u4E2D\u6CE8\u518C dataChannel\uFF0C\u5B83\u4EEC\u4F9D\u7136\u4F1A\u5728\u5F53\u524D Activity \u4E2D\u540C\u65F6\u88AB\u56DE\u8C03\u3002 \u5728\u6A21\u5757\u4E2D\uFF0C\u4F60\u53EA\u80FD\u4F7F\u7528 Activity \u7684 Context \u6CE8\u518C dataChannel\uFF0C\u4F60\u4E0D\u80FD\u5728 Application \u4EE5\u53CA Service \u7B49\u5730\u65B9\u4F7F\u7528 dataChannel\u3002 \u82E5\u8981\u5728 Fragment \u4E2D\u4F7F\u7528 dataChannel\uFF0C\u8BF7\u4F7F\u7528 activity?.dataChannel(...)\u3002 \u5728\u6A21\u5757\u73AF\u5883\u4E2D\uFF0C\u4F60\u53EA\u80FD\u63A5\u6536\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u53D1\u9001\u7684\u901A\u8BAF\u6570\u636E\u4E14\u53EA\u80FD\u53D1\u9001\u7ED9\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u3002 \u7279\u522B\u6CE8\u610F \u4E3A\u4E86\u8FDB\u4E00\u6B65\u9632\u6B62\u5E7F\u64AD\u6EE5\u7528\uFF0C\u901A\u8BAF\u6570\u636E\u4E2D API \u4F1A\u81EA\u52A8\u6307\u5B9A\u5BBF\u4E3B\u548C\u6A21\u5757\u7684\u5305\u540D\uFF0C\u9632\u6B62\u5176\u5B83 APP \u76D1\u542C\u5E76\u5229\u7528\u5E7F\u64AD\u505A\u51FA\u8D85\u9650\u884C\u4E3A\u3002 This is a solution that uses system out-of-order broadcasting to send and receive data between the Module App and the Host App. Condition that needs to be met The Module App and the Host App need to remain alive, otherwise communication cannot be established. The basic usage of the By using The Module App example is as follows The Host App example is as follows You can leave the The Module App example is as follows The Host App example is as follows Pay Attention The receiver needs to stay alive to receive the communication data. Tips For more functions, please refer to YukiHookDataChannel. Through the communication bridge function, We only need to call the Bidirectional judgment can be performed between the Module App and the Host App. You can check in the Module App whether the Host App of the specified package name matches the version of the current Module App. The following example You can also determine in the Host App whether it matches the current Module App version. The following example Condition of method callback The Host App and Module App must be stay alive, and after activating the Module App restart the Hook target Host App object in scope. Tips For more functions, please refer to YukiHookDataChannel. Only examples used in Module App are listed here, the same Pay Attention In the Module App and Host App, each key callback event corresponding to dataChannel is not allowed to be repeatedly created, if repeated, the previous callback event will be replaced by the newly added callback event. When used in the Module App, it cannot be repeated in the same Activity, and the same key in different Activity is allowed to be repeated. The following example In the above example, the callback event A will be replaced by the callback event B, the Pay Attention A callback event with the same key will only call back the callback event registered in the Activity that the current Module App is displaying, such as test_key in the above, if OtherActivity is being displayed, then test_key in MainActivity will not be called back. The same key registers dataChannel in the same Activity but different Fragment, they will still be called back in the current Activity at the same time. In a Module App, you can only use Context of Activity to register dataChannel, you cannot use dataChannel in Application and Service. If you want to use dataChannel in Fragment, use activity?.dataChannel(...). In the Module environment, you can only receive communication data sent by the Host App with the specified package name and only send it to the Host App with the specified package name. Pay Attention In order to further prevent broadcast abuse, the API in the communication data will automatically specify the package name of the Host App and Module App to prevent other apps from monitoring and using broadcast to make overrun behaviors. \u8FD9\u662F\u4E00\u4E2A\u81EA\u52A8\u5BF9\u63A5 \u6211\u4EEC\u9700\u8981\u5B58\u50A8\u6A21\u5757\u7684\u6570\u636E\uFF0C\u4EE5\u4F9B\u5BBF\u4E3B\u8C03\u7528\uFF0C\u8FD9\u4E2A\u65F6\u5019\u4F1A\u9047\u5230\u539F\u751F \u539F\u751F\u7684 \u8FD9\u91CC\u63CF\u8FF0\u4E86\u5728 \u901A\u5E38\u60C5\u51B5\u4E0B\u6211\u4EEC\u53EF\u4EE5\u8FD9\u6837\u5728 Hook APP (\u5BBF\u4E3B) \u5185\u5BF9\u5176\u8FDB\u884C\u521D\u59CB\u5316\u3002 \u793A\u4F8B\u5982\u4E0B \u6709\u6CA1\u6709\u65B9\u4FBF\u5FEB\u6377\u7684\u89E3\u51B3\u65B9\u6848\u5462\uFF0C\u6B64\u65F6\u4F60\u5C31\u53EF\u4EE5\u4F7F\u7528 \u5F53\u4F60\u5728\u6A21\u5757\u4E2D\u5B58\u50A8\u6570\u636E\u7684\u65F6\u5019\uFF0C\u82E5\u5F53\u524D\u5904\u4E8E \u793A\u4F8B\u5982\u4E0B \u5F53\u4F60\u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u8BFB\u53D6\u6570\u636E\u65F6\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u65B9\u6CD5\u3002 \u793A\u4F8B\u5982\u4E0B \u4F60\u4E0D\u9700\u8981\u8003\u8651\u4F20\u5165\u6A21\u5757\u7684\u5305\u540D\u4EE5\u53CA\u4E00\u7CFB\u5217\u590D\u6742\u7684\u6743\u9650\u914D\u7F6E\uFF0C\u4E00\u5207\u90FD\u4EA4\u7ED9 \u82E5\u8981\u5B9E\u73B0\u5B58\u50A8\u7684\u533A\u57DF\u5212\u5206\uFF0C\u4F60\u53EF\u4EE5\u6307\u5B9A\u6BCF\u4E2A \u5728\u6A21\u5757\u7684 \u793A\u4F8B\u5982\u4E0B \u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u8FD9\u6837\u8BFB\u53D6\u3002 \u793A\u4F8B\u5982\u4E0B \u82E5\u4F60\u7684\u9879\u76EE\u4E2D\u6709\u5927\u91CF\u7684\u56FA\u5B9A\u6570\u636E\u9700\u8981\u5B58\u50A8\u548C\u8BFB\u53D6\uFF0C\u63A8\u8350\u4F7F\u7528 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiHookModulePrefs\u3001PrefsData\u3002 \u8FD9\u91CC\u63CF\u8FF0\u4E86\u5728 \u82E5\u4F60\u7684\u6A21\u5757\u4F7F\u7528\u4E86 \u7279\u522B\u6CE8\u610F \u4F60\u5FC5\u987B\u7EE7\u627F ModulePreferenceFragment \u624D\u80FD\u5B9E\u73B0 YukiHookModulePrefs \u7684\u6A21\u5757\u5B58\u50A8\u529F\u80FD\u3002 \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ModulePreferenceFragment\u3002 This is an efficient Module App data storage solution that automatically connects We need to store the data of the Module App for the Host App to call. At this time, we will encounter the data exchange obstacle of the native The native Loading Usually we can initialize it in Host App like this. The following example Is there a convenient and quick solution? At this point, you can use the extension capability of When you store data in a Module App, you can use the following methods if you are currently in an The following example When you read data in a Host App, you can use the following methods. The following example You don't need to consider the module package name and a series of complicated permission configurations, everything is handled by To achieve localization of storage, you can specify the name of each This is used in the The following example Read like this in Host App. The following example If your project has a lot of fixed data that needs to be stored and read, it is recommended to use Tips For more functions, please refer to YukiHookModulePrefs, PrefsData. Loading If your Module App uses Pay Attention You must extends ModulePreferenceFragment to implement the module storage function of YukiHookModulePrefs. Tips For more functions, please refer to ModulePreferenceFragment. \u8FD9\u91CC\u4ECB\u7ECD\u4E86 \u4F5C\u4E3A Xposed \u6A21\u5757\uFF0C \u4F60\u9700\u8981\u5728\u4F60\u7684 \u4F60\u53EF\u4EE5\u5BF9 \u7279\u522B\u6CE8\u610F @InjectYukiHookWithXposed \u6CE8\u89E3\u7684 Class \u5FC5\u987B\u5B9E\u73B0 IYukiHookXposedInit \u63A5\u53E3\u3002 \u5728\u4F60\u5F53\u524D\u9879\u76EE\u4E2D\u7684\u6240\u6709 Class \u6807\u8BB0\u4E2D\u53EA\u80FD\u5B58\u5728\u4E00\u6B21\uFF0C\u82E5\u5B58\u5728\u591A\u4E2A\u58F0\u660E\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u4F1A\u5728\u7F16\u8BD1\u65F6\u629B\u51FA\u5F02\u5E38\uFF0C\u4F60\u53EF\u4EE5\u81EA\u5B9A\u4E49\u5176\u76F8\u5173\u53C2\u6570\u3002 \u7279\u522B\u6CE8\u610F \u5982\u679C\u4F60\u7684\u9879\u76EE\u4E0D\u5728 ../src/main.. \u6216\u4F60\u624B\u52A8\u4F7F\u7528 sourceSets \u8BBE\u7F6E\u4E86\u9879\u76EE\u8DEF\u5F84\uFF0C\u4F60\u5C31\u9700\u8981\u624B\u52A8\u8BBE\u7F6E sourcePath \u53C2\u6570\uFF0C\u5426\u5219\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u5C06\u65E0\u6CD5\u8BC6\u522B\u4F60\u7684\u9879\u76EE\u8DEF\u5F84\u5E76\u4F1A\u5728\u7F16\u8BD1\u65F6\u629B\u51FA\u5F02\u5E38\u3002 \u793A\u4F8B\u5982\u4E0B \u6CE8\u610F \u82E5\u4F60\u60F3\u4F7F\u7528\u6A21\u5757\u5305\u540D\u81EA\u52A8\u751F\u6210\uFF0C\u4F60\u9700\u8981\u786E\u4FDD\u4F60\u7684\u9879\u76EE\u547D\u540D\u7A7A\u95F4\u5728 AndroidManifest.xml\u3001build.gradle \u6216 build.gradle.kts \u4E2D\u5B58\u5728\u5982\u4E0B\u4EFB\u610F\u5B9A\u4E49\u65B9\u5F0F\u3002 \u793A\u4F8B\u547D\u540D\u7A7A\u95F4 \u4EE5\u4E0B\u5B9A\u4E49\u65B9\u5F0F\u4EC5\u4F9B\u53C2\u8003\uFF0C\u901A\u5E38\u60C5\u51B5\u4E0B\u53EA\u8981\u4F60\u7684\u9879\u76EE\u80FD\u591F\u6B63\u5E38\u751F\u6210 \u82E5\u4F60\u7684\u6A21\u5757\u5305\u540D\u662F\u975E\u5E38\u89C4\u624B\u6BB5\u8FDB\u884C\u81EA\u52A8\u751F\u6210\u7684\uFF0C\u6216\u4F60\u8BA4\u4E3A\u6709\u5FC5\u8981\u624B\u52A8\u5B9A\u4E49\u6A21\u5757\u5305\u540D\uFF0C\u90A3\u4E48\u4F60\u53EF\u4EE5\u76F4\u63A5\u8BBE\u7F6E \u793A\u4F8B\u5982\u4E0B \u53EA\u8981\u4F60\u81EA\u5B9A\u4E49\u4E86 \u793A\u4F8B\u5982\u4E0B \u6CE8\u610F \u624B\u52A8\u5B9A\u4E49\u7684\u6A21\u5757\u5305\u540D\u9664\u4E86\u683C\u5F0F\u4E4B\u5916\uFF0C\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u5C06\u4E0D\u4F1A\u518D\u68C0\u67E5\u6A21\u5757\u5305\u540D\u662F\u5426\u6B63\u786E\uFF0C\u9700\u8981\u4F60\u81EA\u884C\u786E\u8BA4\u5176\u6709\u6548\u6027\u3002 \u5047\u8BBE\u8FD9\u662F\u4F60\u7684\u5165\u53E3\u7C7B\u3002 \u793A\u4F8B\u5982\u4E0B Xposed \u5165\u53E3\u7C7B\u5904\u7406\u5982\u4E0B\u3002 \u793A\u4F8B\u5982\u4E0B \u7F16\u8BD1\u540E\u7684\u7C7B\u540D\u7ED3\u6784\u5982\u4E0B\u3002 \u793A\u4F8B\u5982\u4E0B \u6211\u4EEC\u73B0\u5728\u5B9A\u4E49\u5165\u53E3\u7C7B\u540D\u79F0\u4E3A \u793A\u4F8B\u5982\u4E0B Xposed \u5165\u53E3\u7C7B\u5904\u7406\u5982\u4E0B\u3002 \u793A\u4F8B\u5982\u4E0B \u7F16\u8BD1\u540E\u7684\u7C7B\u540D\u7ED3\u6784\u5982\u4E0B\u3002 \u793A\u4F8B\u5982\u4E0B \u7279\u522B\u6CE8\u610F \u4F60\u5B9A\u4E49\u7684 entryClassName \u4E0D\u53EF\u4E0E xposed_init \u4E2D\u7684\u7C7B\u540D\u76F8\u540C\uFF0C\u5426\u5219\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u4F1A\u5728\u7F16\u8BD1\u65F6\u629B\u51FA\u5F02\u5E38\u3002 \u542F\u7528\u540E\u751F\u6210\u7684\u5165\u53E3\u7C7B\u5C06\u4E3A\u5982\u4E0B\u6240\u793A\u3002 \u793A\u4F8B\u5982\u4E0B \u82E5\u4F60\u5F53\u524D\u7684\u9879\u76EE\u5E76\u4E0D\u9700\u8981\u7528\u5230 Reources Hook\uFF0C\u53EF\u4EE5\u8BBE\u7F6E \u793A\u4F8B\u5982\u4E0B \u5173\u95ED\u540E\u751F\u6210\u7684\u5165\u53E3\u7C7B\u5C06\u4E3A\u5982\u4E0B\u6240\u793A\u3002 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 IYukiHookXposedInit\u3002 \u5F53\u4F60\u7684\u6A21\u5757\u88AB Xposed \u88C5\u8F7D\u540E\uFF0C \u57FA\u672C\u7684\u8C03\u7528\u6D41\u7A0B\u4E3A \u8BE6\u60C5\u8BF7\u53C2\u8003 API \u57FA\u672C\u914D\u7F6E\u3002 \u82E5\u4F60\u5F53\u524D\u7684 Xposed \u6A21\u5757\u4F7F\u7528\u4E86\u7B2C\u4E09\u65B9\u7684\u8D44\u6E90\uFF0C\u4F46\u662F\u77ED\u65F6\u95F4\u5185\u53EF\u80FD\u65E0\u6CD5\u8F6C\u79FB\u5B83\u4EEC\uFF0C\u6B64\u65F6\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 \u793A\u4F8B\u5982\u4E0B \u5C0F\u63D0\u793A \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 IYukiHookXposedInit.onXposedEvent \u65B9\u6CD5\u3002 Here are the related configuration methods used by As an Xposed Module, You need to integrate the latest version of the You can configure how The Pay Attention The Class of the @InjectYukiHookWithXposed annotation must implements IYukiHookXposedInit interface. All Class tags in your current project can only exist once, if there are multiple declaration automatic builder will throw an exception at compile time, you can customize its related parameters. The The content of this parameter is a relative path match, and the default parameter is Pay Attention If your project is not in ../src/main.. or you set the project path manually using sourceSets, you need to set the sourcePath parameter manually, otherwise the automatic builder will not recognize your project path and will throw an exception at compile time. The following example The file path separator used by If left blank or not filled, the automatic builder will analyze and generate the current project file. Notice If you want to use the module package name to be automatically generated, you need to ensure that your project namespace has any of the following definitions in AndroidManifest.xml, build.gradle or build.gradle.kts. Example namespace The following definitions are for reference only, usually as long as your project can generate the If your module package name is automatically generated by unconventional means, or you think it is necessary to manually define the module package name, then you can directly set the The following example As long as you customize the The following example Notice In addition to the format of the manually defined module package name, the automatic builder will no longer check whether the module package name is correct, and you need to confirm its validity by yourself. By default, it will use your entry class package name to insert the Suppose this is your entry class. The following example The Xposed entry class is handled as follows. The following example The compiled class name structure is as follows. The following example We now define the entry class name as The following example The Xposed entry class is handled as follows. The following example The compiled class name structure is as follows. The following example Pay Attention The entryClassName you define must not be the same as the class name in xposed_init, otherwise the automatic builder throws an exception at compile time. The generated entry class after enabling it will look like the following. The following example If your current project does not need to use Reources Hook, you can set The following example The resulting entry class after closing will look like the following. The following example The Tips For more functions, please refer to IYukiHookXposedInit. When your Module App is loaded by Xposed, the The basic calling process is For details, please refer to API Basic Configs. If your current Xposed Module uses third-party resources, but may not be able to transfer them in a short time, you can use The following example Tips For more functions, please refer to the IYukiHookXposedInit.onXposedEvent method. \u8FD9\u662F\u4E00\u4E2A\u4F7F\u7528 \u5B9E\u73B0\u81EA\u52A8\u5316\u641C\u7D22\u4F9D\u8D56\u5FEB\u901F\u642D\u5EFA\u4E00\u4E2A\u5305\u542B Xposed \u6A21\u5757\u73AF\u5883\u7684 Android \u9879\u76EE\u6A21\u677F\u3002 \u672C\u9879\u76EE\u5B8C\u5168\u5F00\u6E90\u514D\u8D39\uFF0C\u4E14\u4F1A\u6839\u636E\u5927\u5BB6\u7684\u4F7F\u7528\u60C5\u51B5\u6301\u7EED\u7EF4\u62A4\uFF0C\u521D\u4EE3\u7248\u672C\u53EF\u80FD\u5B58\u5728\u4E0D\u5B8C\u5584\u6216 BUG\uFF0C\u6B22\u8FCE\u53CD\u9988\u3002 \u8FD9\u91CC\u5305\u542B\u4E86\u57FA\u672C\u7684\u4F7F\u7528\u65B9\u6CD5\u548C\u529F\u80FD\u8BB2\u89E3\u3002 \u8F6F\u4EF6\u4F7F\u7528\u8FC7\u7A0B\u9700\u8981\u5F53\u524D\u8BBE\u5907\u5DF2\u8FDE\u63A5\u4E92\u8054\u7F51\uFF0C\u82E5\u9879\u76EE\u4F9D\u8D56\u65E0\u6CD5\u641C\u7D22\u8BF7\u5C1D\u8BD5 \u79D1\u5B66\u4E0A\u7F51 \u3002 \u542F\u52A8\u8F6F\u4EF6\u540E\uFF0C\u5BF9\u4F60\u671F\u671B\u521B\u5EFA\u7684\u9879\u76EE\u8FDB\u884C\u7B80\u5355\u914D\u7F6E\uFF0C\u70B9\u51FB\u53F3\u4E0B\u89D2\u7684 \u6309\u94AE \u6216\u83DC\u5355\u680F\u9009\u62E9 \u9879\u76EE > \u5F00\u59CB\u521B\u5EFA \u5373\u53EF\u5F00\u59CB\u4EFB\u52A1\u3002 \u7B49\u5F85\u4F9D\u8D56\u81EA\u52A8\u641C\u7D22\u5B8C\u6210\u540E\uFF0C\u4F60\u53EF\u4EE5\u5BF9\u9879\u76EE\u4F9D\u8D56\u8FDB\u884C\u914D\u7F6E\uFF0C\u5EFA\u8BAE\u4F7F\u7528\u6700\u65B0\u4F9D\u8D56\u4FDD\u8BC1\u9879\u76EE\u7684\u7A33\u5B9A\u6027\uFF0C\u6784\u5EFA\u5DE5\u5177\u4E5F\u4EC5\u5BF9\u6700\u65B0\u4F9D\u8D56\u8FDB\u884C\u652F\u6301\u3002 \u9009\u62E9\u4F60\u9700\u8981\u521B\u5EFA\u9879\u76EE\u7684\u76EE\u5F55\uFF0C\u5F00\u59CB\u540E\u9879\u76EE\u4F1A\u5728\u4F60\u9009\u62E9\u7684\u4F4D\u7F6E\u4E2D\u521B\u5EFA\uFF0C\u5E76\u7B49\u5F85\u6574\u4E2A\u8FC7\u7A0B\u5B8C\u6210\uFF0C\u9879\u76EE\u5C31\u521B\u5EFA\u597D\u4E86\u3002 \u914D\u7F6E\u6A21\u677F\u662F\u4E00\u4E2A\u6269\u5C55\u529F\u80FD\uFF0C\u4F60\u53EF\u4EE5\u9009\u62E9\u83DC\u5355\u680F \u9879\u76EE > \u914D\u7F6E\u6A21\u677F > \u65B0\u5EFA\u6A21\u677F\uFF0C\u5373\u53EF\u4F7F\u7528\u5F53\u524D\u586B\u5199\u7684\u914D\u7F6E\u521B\u5EFA\u4E00\u4EFD\u6A21\u677F\uFF0C\u4E0B\u6B21\u53EF\u4EE5\u4ECE \u5DF2\u4FDD\u5B58\u7684\u6A21\u677F \u4E2D\u91CD\u65B0\u8F7D\u5165\u6A21\u677F\uFF0C\u5373\u53EF\u8FD8\u539F\u5F53\u524D\u914D\u7F6E\u3002 \u8F6F\u4EF6\u8BED\u8A00\u8DDF\u968F\u5F53\u524D\u7CFB\u7EDF\uFF0C\u4F60\u53EF\u4EE5\u5728\u83DC\u5355\u680F \u8BED\u8A00 (Language) \u4E00\u680F\u624B\u52A8\u9009\u62E9\u8F6F\u4EF6\u7684\u754C\u9762\u8BED\u8A00\u3002 This is an automatic building tool for Xposed Modules using Implementing automated search relies on quickly building an Android project template that includes a Xposed Module environment. This project is open source and free, and will be maintained continuously according to your usage. The original version may have imperfections or bugs. We welcome to your feedback. Here contains the basic usage and function explanation. The software use process requires your device connected to the Internet. After starting the software, simply configure the project you want to create, click the button in the lower right corner or select Project > Run Build from the menu bar to start the task. After waiting for the automatic dependency search to complete, you can configure the project dependencies. It is recommended to use the latest dependencies to ensure the stability of the project, and the build tools only support the latest dependencies. Select the folder where you need to create the project. After starting, the project will be created in the location you selected, and wait for the whole process to complete and the project will be created. Config template is an extension function, you can select menu bar Project > Config Template > New Template. And then, you can create a template with the current config, and you can re-create it from Saved Template next time Load the template to restore the current config. The software language follows the current system, and you can manually select the software interface language in the Language column of the menu bar. This document is powered by VuePress. Copyright © 2019-2022 HighCapable The version update history of Pay Attention We will only maintain the latest API version, if you are using an outdate API version, you voluntarily renounce any possibility of maintenance. Notice To avoid translation time consumption, Changelog will use Google Translation from Chinese to English, please refer to the original text for actual reference. Time zone of version release date: UTC+8 If you have any questions in use, or have any constructive suggestions, you can contact us. Join us Click to join Telegram group Find me on Twitter @fankesyooni Thank you for choosing and using If you have code-related suggestions and requests, you can submit a Pull Request on Github. The future is bright and uncertain, let us look forward to the future development space of Here are the unresolved issues with Currently only supports LSPosed perfectly, other Xposed Framework need to downgrade the module target api. TaiChi may not be supported at all, and TaiChi needs a lower target api to adapt on high-version systems. Some Xposed Module developers currently choose the Hook target app self's SharedPreferences storage solution to solve the module settings sharing problem. In the later period, the permissions of the Android system will become more and more strict, and Features that To be Discussed At present, the API only supports binding to xposed_init through the automatic handler. If you don't like the automatic handler, you must implement the module loading entry yourself. In the future, the Lite version with only API functions will be launched according to the number of people required. You can submit issues with us. We have provided the Xposed native API listening interface, you can find or view the implementation method of the Demo here. As an API, currently only docking Most The document here will synchronize the relevant usage of the latest API version, please keep The function description mainly introduces the related usage and purpose of the current API. The function examples mainly show the basic usage examples of the current API for reference. The function of the first version will be marked as New function added later will be marked as Later modified function will be appended as Later deprecated function will be marked as Later removed function will be marked as kt Kotlin Static File annotation Annotation Class interface Interface Class object Class (Singleton) class Class field Field or method Method enum Enum constant ext-field Extension field (global) ext-method Extension method (global) i-ext-field Extension field (internal) i-ext-method Extension method (internal) Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是 Change Records Function Illustrate 获取当前 Change Records Function Illustrate 获取当前 Change Records 请转移到 Change Records 请转移到 Change Records Function Illustrate 当前 Change Records Function Illustrate 获取项目编译完成的时间戳 (当前本地时间)。 Change Records Function Illustrate 获取当前是否为 (Xposed) 宿主环境。 Change Records Function Illustrate 获取当前 Hook 框架的名称。 无法获取会返回 Notice 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 Change Records Function Illustrate 获取当前 Hook 框架的版本。 无法获取会返回 Notice 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 Change Records Function Illustrate 判断模块是否在 Xposed 或太极、无极中激活。 Notice 在模块环境中你需要将 Application 继承于 ModuleApplication。 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 在 (Xposed) 宿主环境中仅返回非 isTaiChiModuleActive 的激活状态。 Change Records Function Illustrate 仅判断模块是否在 Xposed 中激活。 Notice 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 在 (Xposed) 宿主环境中始终返回 true。 Change Records Function Illustrate 仅判断模块是否在太极、无极中激活。 Notice 在模块环境中你需要将 Application 继承于 ModuleApplication。 在 (Xposed) 宿主环境中始终返回 false。 Change Records Function Illustrate 判断当前 Hook Framework 是否支持资源钩子(Resources Hook)。 Notice 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 在 (Xposed) 宿主环境中可能会延迟等待事件回调后才会返回 true。 请注意你需要确保 InjectYukiHookWithXposed.isUsingResourcesHook 已启用,否则始终返回 false。 Change Records Function Illustrate 对 API 相关功能的配置类。 Change Records Function Illustrate 配置 Change Records 请转移到 Change Records Function Illustrate 是否启用 DEBUG 模式。 默认为开启状态,开启后模块将会向 Change Records 请转移到 Change Records Function Illustrate 是否启用 为防止内存复用过高问题,此功能默认启用。 你可以手动在 Change Records Function Illustrate 是否启用当前 Xposed 模块自身 为防止内存复用过高问题,此功能默认启用。 你可以手动调用 Notice 关闭后每次使用 PackageParam.moduleAppResources 都会重新创建,可能会造成运行缓慢。 Change Records Function Illustrate 是否启用 Hook Xposed 模块激活等状态功能. 为原生支持 Xposed 模块激活状态检测,此功能默认启用。 Notice 关闭后你将不能再在模块环境中使用 YukiHookAPI.Status 中的激活状态判断功能。 Change Records Function Illustrate 是否启用 Hook 启用后将在模块启动时强制将 Notice 这是一个可选的实验性功能,此功能默认不启用。 仅用于修复某些系统可能会出现在启用了 New XSharedPreferences 后依然出现文件权限错误问题,若你能正常使用 YukiHookModulePrefs 就不建议启用此功能。 Change Records Function Illustrate 是否启用当前 Xposed 模块与宿主交互的 请确保 Xposed 模块的 此功能默认启用,关闭后将不会在功能初始化的时候装载 Change Records 将方法体进行 inline Function Illustrate 是否启用 为防止 启用后会缓存已经找到的 缓存的 推荐使用 除非缓存的 Change Records Function Illustrate 对 你可以轻松的调用它进行配置。 Function Example 你可以在 The following example 若觉得上面的写法不美观,你还可以写得更加简洁。 The following example 你也可以不通过 The following example Change Records Function Illustrate 装载 Hook 入口的核心方法。 Function Example 详情请参考 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 新增 新增 Function Illustrate 标识 Function Example Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 调整了构造方法的参数名称 Function Illustrate 当前实例的类操作对象。 Change Records Function Illustrate 获得当前 Change Records Function Illustrate 获得当前 Change Records Function Illustrate 获得当前实例中的泛型父类。 如果当前实例不存在泛型将返回 Change Records Function Illustrate 获得当前实例中的泛型父类。 如果当前实例不存在泛型将返回 Change Records Function Illustrate 调用父类实例。 Change Records Function Illustrate 调用当前实例中的变量。 Change Records Function Illustrate 调用当前实例中的方法。 Change Records 新增 Function Illustrate 当前类的父类实例的类操作对象。 Change Records Function Illustrate 获得当前 Change Records Function Illustrate 获得当前 Change Records Function Illustrate 获得当前实例父类中的泛型父类。 如果当前实例不存在泛型将返回 Change Records Function Illustrate 获得当前实例父类中的泛型父类。 如果当前实例不存在泛型将返回 Change Records Function Illustrate 调用父类实例中的变量。 Change Records Function Illustrate 调用父类实例中的方法。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 当前 Change Records Function Illustrate 获得泛型参数数组下标的 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 创建一个当前 Hook 的 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 创建一个当前 Hook 的 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是一个不确定性 Change Records Function Illustrate 获取匹配的实体类。 使用当前 Change Records Function Illustrate 获取匹配的实体类。 使用当前 匹配不到 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 对 修正拼写错误的 Creater 命名到 Creator Function Illustrate Change Records Function Illustrate 默认 Hook 回调优先级。 Change Records Function Illustrate 延迟回调 Hook 方法结果。 Change Records Function Illustrate 更快回调 Hook 方法结果。 Change Records Function Illustrate 得到当前被 Hook 的 Pay Attention 不推荐直接使用,万一得不到 Class 对象则会无法处理异常导致崩溃。 Change Records 将方法体进行 inline 增加 Function Illustrate 注入要 Hook 的 Function Example 你可以注入任意 The following example 你还可以自定义 The following example 你还可以自定义 The following example Change Records Function Illustrate 允许 Hook 过程中的所有危险行为。 请在 你还需要在整个调用域中声明注解 若你只需要 Hook Pay Attention 若你不知道允许此功能会带来何种后果,请勿使用。 Change Records 增加 增加 移除 修正拼写错误的 Creater 命名到 Creator Function Illustrate Hook 核心功能实现类,查找和处理需要 Hook 的 Change Records 请转移到 Change Records Function Illustrate 手动指定要 Hook 的 Notice 不建议使用此方法设置目标需要 Hook 的 Member 对象,你可以使用 method 或 constructor 方法。 Function Example 你可以调用 The following example 同样地,你也可以传入一组 The following example Change Records 请使用 Change Records 请使用 Change Records Function Illustrate 查找并 Hook Notice 无法准确处理每个 Member 的返回值和 param,建议使用 method or constructor 对每个 Member 单独 Hook。 Change Records 将方法体进行 inline Function Illustrate 查找当前 Function Example 你可参考 MethodFinder 查看详细用法。 The following example 若想 Hook 当前查找 The following example 此时 Notice 若没有 all,默认只会 Hook 当前条件查找到的数组下标结果第一位。 Change Records 将方法体进行 inline Function Illustrate 查找当前 Function Example 你可参考 ConstructorFinder 查看详细用法。 The following example 若想 Hook 当前查找 The following example 此时 Notice 若没有 all,默认只会 Hook 当前条件查找到的数组下标结果第一位。 Change Records 将方法体进行 inline Function Illustrate 使用当前 Function Example 你可参考 FieldFinder 查看详细用法。 The following example Change Records 将方法体进行 inline Function Illustrate 使用当前 Change Records 将方法体进行 inline Function Illustrate 使用当前 Change Records Function Illustrate 注入要 Hook 的 Change Records 新增 Function Illustrate 在 Change Records 新增 Function Illustrate 在 Change Records Function Illustrate 拦截并替换此 Change Records Function Illustrate 拦截并替换此 Change Records Function Illustrate 拦截并替 Change Records Function Illustrate 拦截并替换 Pay Attention 确保替换 Member 的返回对象为 Boolean。 Change Records Function Illustrate 拦截并替换 Pay Attention 确保替换 Member 的返回对象为 Boolean。 Change Records Function Illustrate 拦截此 这将会禁止此 Pay Attention 例如 Int、Long、Boolean 常量返回值的 Member 一旦被设置为 null 可能会造成 Hook APP 抛出异常。 Change Records Function Illustrate 移除当前注入的 Hook Pay Attention 你只能在 Hook 回调方法中使用此功能。 Change Records Function Illustrate Hook 方法体回调实现类。 Change Records Function Illustrate 当回调方法体内发生异常时将异常抛出给当前 Hook APP。 Change Records Function Illustrate 监听 Hook 结果实现类。 Change Records 将方法体进行 inline Function Illustrate 创建监听失败事件方法体。 Function Example 你可以使用此方法为 The following example Change Records 将方法体进行 inline Function Illustrate 添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。 Change Records Function Illustrate 监听 在首次 Hook 成功后回调。 在重复 Hook 时会回调 Change Records Function Illustrate 监听 Notice 同一个 hookClass 中的同一个 members 不会被 API 重复 Hook,若由于各种原因重复 Hook 会回调此方法。 Change Records Function Illustrate 监听 Change Records Function Illustrate 监听 Hook 进行过程中发生错误的回调方法。 Change Records Function Illustrate 监听 Hook 开始时发生的错误的回调方法。 Change Records Function Illustrate 监听全部 Hook 过程发生错误的回调方法。 Change Records Function Illustrate 忽略 Change Records Function Illustrate 忽略 Hook 进行过程中发生的错误。 Change Records Function Illustrate 忽略 Hook 开始时发生的错误。 Change Records Function Illustrate 忽略全部 Hook 过程发生的错误。 Change Records Function Illustrate 移除当前注入的 Hook Notice 你只能在 Hook 成功后才能解除 Hook,可监听 onHooked 事件。 Change Records Function Illustrate 监听全部 Hook 结果实现类。 Change Records 将方法体进行 inline Function Illustrate 创建监听事件方法体。 Change Records 将方法体进行 inline Function Illustrate 添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。 Change Records Function Illustrate 监听 Change Records Function Illustrate 监听 Change Records Function Illustrate 忽略 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 修正拼写错误的 Creater 命名到 Creator Function Illustrate Change Records Function Illustrate 注入要 Hook 的 Resources。 Function Example 你可以注入任意 Resources,使用 The following example 你还可以自定义 The following example Change Records 移除 修正拼写错误的 Creater 命名到 Creator Function Illustrate Hook 核心功能实现类。 查找和处理需要 Hook 的 Resources。 Change Records Function Illustrate 直接设置需要替换的 Resources Id。 Notice 不建议使用此方法设置目标需要 Hook 的 Resources Id,你可以使用 conditions 方法。 Function Example 你可以直接设置并指定目标 Hook APP 的 Resources Id。 The following example Change Records Function Illustrate 设置 Resources 查找条件。 若你设置了 Function Example 你可参考 ConditionFinder 查看详细用法。 The following example Change Records Function Illustrate 替换指定 Resources 为指定的值。 Function Example 你可以替换找到的 Resources 为你想要的值,可以是 比如我们要替换一个找到的字符串 Resources。 The following example 或是替换为一个 The following example Change Records Function Illustrate 替换指定 Resources 为 Pay Attention 确保目标替换 Resources 的类型为 Boolean。 Change Records Function Illustrate 替换指定 Resources 为 Pay Attention 确保目标替换 Resources 的类型为 Boolean。 Change Records Function Illustrate 替换为当前 Xposed 模块的 Resources。 你可以直接使用模块的 Function Example 使用此方法可非常方便地使用当前模块的 Resources 去替换目标 Hook APP 的 Resources。 这个过程你无需对目标 Resources 实现 比如我们要替换一个字符串。 The following example 还可以替换一些复杂的 Resources,比如 The following example Change Records Function Illustrate 作为装载的布局注入。 Function Example 你可以直接注入一个布局监听并修改它的内部 The following example 你还可以通过 The following example Change Records Function Illustrate Resources 查找条件实现类。 Change Records Function Illustrate 设置 Resources 名称。 Change Records Function Illustrate 设置 Resources 类型为动画。 Change Records Function Illustrate 设置 Resources 类型为属性动画。 Change Records Function Illustrate 设置 Resources 类型为布朗(Boolean)。 Change Records Function Illustrate 设置 Resources 类型为颜色(Color)。 Change Records Function Illustrate 设置 Resources 类型为尺寸(Dimention)。 Change Records Function Illustrate 设置 Resources 类型为 Drawable。 Change Records Function Illustrate 设置 Resources 类型为整型(Integer)。 Change Records Function Illustrate 设置 Resources 类型为布局(Layout)。 Change Records Function Illustrate 设置 Resources 类型为 Plurals。 Change Records Function Illustrate 设置 Resources 类型为字符串(String)。 Change Records Function Illustrate 设置 Resources 类型为 Xml。 Change Records Function Illustrate 设置 Resources 类型为位图(Mipmap)。 Change Records Function Illustrate 设置 Resources 类型为数组(Array)。 Change Records Function Illustrate 监听全部 Hook 结果实现类,可在这里处理失败事件监听。 Change Records Function Illustrate 创建监听事件方法体。 Change Records Function Illustrate 添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。 Change Records Function Illustrate 监听 Hook 过程发生错误的回调方法。 Change Records Function Illustrate 忽略 Hook 过程出现的错误。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 分离原始命名 Function Illustrate 这是 Change Records Function Illustrate 字节码下标筛选实现类。 Change Records Function Illustrate 设置下标。 若 可使用 Change Records Function Illustrate 得到下标。 Change Records Function Illustrate 字节码下标排序实现类。 Change Records Function Illustrate 设置满足条件的第一个。 Change Records Function Illustrate 设置满足条件的最后一个。 Change Records Function Illustrate 设置倒序下标。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是一个模糊 可对 R8 混淆后的 Change Records Function Illustrate 是否为 0。 Change Records Function Illustrate 大于 Change Records Function Illustrate 小于 Change Records Function Illustrate 在 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 新增 作为 lambda 整体判断条件使用 移动到 base 包名 私有化构造方法 Function Illustrate 这是一个 可对 R8 混淆后的 Change Records 统一合并到扩展方法并改名 Function Illustrate Change Records 统一合并到扩展方法并改名 Function Illustrate Change Records 统一合并到扩展方法并改名 Function Illustrate Change Records 统一合并到扩展方法并改名 Function Illustrate 对于任意的静态 Notice Kotlin → Jvm 后的 object 类中的方法并不是静态的。 Change Records 统一合并到扩展方法并改名 Function Illustrate Notice Kotlin → Jvm 后没有 open 符号标识的 Class、Member 和没有任何关联的 Class、Member 都将为 final。 Change Records 统一合并到扩展方法并改名 Function Illustrate Change Records 统一合并到扩展方法并改名 Function Illustrate Change Records 统一合并到扩展方法并改名 Function Illustrate Change Records 统一合并到扩展方法并改名 Function Illustrate 对于任意 JNI 对接的 Change Records 统一合并到扩展方法并改名 Function Illustrate Change Records 统一合并到扩展方法并改名 Function Illustrate 对于任意的抽象 Change Records 统一合并到扩展方法并改名 Function Illustrate Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 作为 lambda 整体判断条件使用 移动到 base 包名 私有化构造方法 Function Illustrate 这是一个模糊 可对 R8 混淆后的 Change Records 统一合并到扩展方法并改名 Function Illustrate 是否为匿名类的主类调用对象。 Change Records 统一合并到扩展方法并改名 Function Illustrate 是否只有符号。 Change Records 统一合并到扩展方法并改名 Function Illustrate 是否只有字母。 Change Records 统一合并到扩展方法并改名 Function Illustrate 是否只有数字。 Change Records 统一合并到扩展方法并改名 Function Illustrate 是否只有字母或数字。 Change Records 统一合并到扩展方法并改名 Function Illustrate 是否只有小写字母。 在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。 Change Records 统一合并到扩展方法并改名 Function Illustrate 是否只有大写字母。 在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 可使用 Notice 此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。 Change Records Change Records Function Illustrate 清除当前 适用于全部通过 ClassLoader.searchClass 或 PackageParam.searchClass 获取的 Change Records Function Illustrate 设置 只会查找匹配到的 例如 Change Records Function Illustrate 设置 只会查找匹配到的 例如 对于匿名类例如 Change Records Function Illustrate 设置 设置后将首先使用 例如 对于匿名类例如 Change Records Function Illustrate 设置在指定包名范围查找当前 设置后仅会在当前 例如 ↓ Notice 建议设置此参数指定查找范围,否则 Class 过多时将会非常慢。 Change Records Function Illustrate 设置 可不设置筛选条件。 Change Records Function Illustrate 设置 只会查找匹配到的 例如 Change Records Function Illustrate 设置 只会查找匹配到的 例如 对于匿名类例如 Change Records Function Illustrate 设置 设置后将首先使用 例如 对于匿名类例如 Change Records Function Illustrate 设置 只会查找匹配到的 Change Records Function Illustrate 设置 只会查找匹配到的 Change Records Function Illustrate 设置 设置后将首先使用 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 会同时查找 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 会同时查找 Change Records Function Illustrate 标识 例如 标识后你可以使用 enclosing 来进一步指定匿名类的 (封闭类) 主类。 Change Records Function Illustrate 设置 此时 Notice 设置此条件后 extends 将失效。 Change Records Function Illustrate 设置 Notice 设置此条件后 implements 将失效。 Change Records Function Illustrate 设置 此时 Notice 设置此条件后 extends 与 implements 将失效。 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 会同时查找 Change Records Function Illustrate 包名范围名称过滤匹配条件实现类。 Change Records Function Illustrate 设置包名绝对匹配。 例如有如下包名 ↓ 若包名条件为 相反地,不设置以上示例会全部匹配。 Change Records Function Illustrate 类名匹配条件实现类。 Change Records Function Illustrate 设置类名可选。 例如有如下类名 ↓ 这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。 此时可设置类名为 这样就可在完全匹配类名情况下使用类名而忽略其它查找条件,否则忽略此条件继续使用其它查找条件。 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 Change Records Function Illustrate Change Records Function Illustrate 创建监听结果事件方法体。 Change Records Function Illustrate 得到 若有多个 在查找条件找不到任何结果的时候将返回 若你设置了 Change Records Function Illustrate 得到 返回全部查找条件匹配的多个 在查找条件找不到任何结果的时候将返回空的 若你设置了 Change Records Function Illustrate 得到 回调全部查找条件匹配的多个 在查找条件找不到任何结果的时候将不会执行。 若你设置了 Change Records Function Illustrate 得到 若有多个 在查找条件找不到任何结果的时候将回调 null。 你需要设置 Change Records Function Illustrate 得到 回调全部查找条件匹配的多个 在查找条件找不到任何结果的时候将回调空的 你需要设置 Change Records Function Illustrate 监听找不到 Change Records Function Illustrate 忽略异常并停止打印任何错误日志。 此时若要监听异常结果,你需要手动实现 onNoClassDefFoundError 方法。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate Change Records Function Illustrate 设置 你可以不使用 若参数个数小于零则忽略并使用 Change Records Function Illustrate 设置 可不设置筛选条件。 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 如果同时使用了 如果 Pay Attention 无参 Constructor 请使用 emptyParam 设置查找条件。 有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。 Change Records Function Illustrate 设置 你可以不使用 Change Records Function Illustrate 设置 你可以不使用 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 可不填写类型。 Change Records Function Illustrate 设置 可不设置筛选条件。 Change Records Function Illustrate 设置 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate Change Records Function Illustrate 设置 可不设置筛选条件。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 你可以不使用 若参数个数小于零则忽略并使用 Change Records Function Illustrate 设置 可不填写返回值。 Change Records Function Illustrate 设置 可不设置筛选条件。 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 如果同时使用了 如果 Pay Attention 无参 Method 请使用 emptyParam 设置查找条件。 有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 你可以不使用 Change Records Function Illustrate 设置 你可以不使用 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 当前 Change Records Function Illustrate 设置当前 Change Records Function Illustrate 设置当前 Change Records Function Illustrate 设置当前 Change Records Function Illustrate 设置当前 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 合并到 合并到 Function Illustrate 可通过指定类型查找指定 Change Records Function Illustrate 设置 你可以不使用 若参数个数小于零则忽略并使用 Change Records 将方法体进行 inline 合并到 Function Illustrate 设置 可不设置筛选条件,默认模糊查找并取第一个匹配的 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 如果同时使用了 如果 Pay Attention 无参 Constructor 请使用 emptyParam 设置查找条件。 有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 你可以不使用 若参数个数小于零则忽略并使用 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 你可以不使用 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 你可以不使用 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置在 Notice 若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。 Change Records Function Illustrate Change Records 将方法体进行 inline Function Illustrate 创建需要重新查找的 你可以添加多个备选 Change Records Function Illustrate Change Records Function Illustrate 当在 Function Example 你可以方便地对重查找的 The following example Change Records Function Illustrate Change Records Function Illustrate 创建监听结果事件方法体。 Function Example 你可以使用 The following example Change Records Function Illustrate 设置全部查找条件匹配的多个 Change Records Function Illustrate 创建 Function Example 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 The following example Change Records Function Illustrate 监听找不到 只会返回第一次的错误信息,不会返回 Change Records 继承到接口 Function Illustrate Change Records 将方法体进行 inline Function Illustrate 创建监听结果事件方法体。 Function Example 你可以使用 The following example Change Records Function Illustrate 获得 若有多个 Pay Attention 若你设置了 remedys 请使用 wait 回调结果方法。 Function Example 你可以通过获得方法所在实例来执行构造方法创建新的实例对象。 The following example 你可以 The following example Pay Attention 若构造方法含有参数则后方参数必填。 The following example Change Records Function Illustrate 获得 返回全部查找条件匹配的多个 Function Example 你可以通过此方法来获得当前条件结果中匹配的全部 The following example Change Records Function Illustrate 得到 若有多个 在查找条件找不到任何结果的时候将返回 Change Records Function Illustrate 得到 返回全部查找条件匹配的多个 在查找条件找不到任何结果的时候将返回空的 Change Records Function Illustrate 获得 若有多个 Pay Attention 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 Change Records Function Illustrate 获得 返回全部查找条件匹配的多个 Pay Attention 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 Change Records 将方法体进行 inline Function Illustrate 创建 Function Example 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 The following example Change Records 将方法体进行 inline Function Illustrate 监听找不到 只会返回第一次的错误信息,不会返回 Change Records Function Illustrate 忽略异常并停止打印任何错误日志。 若 Notice 此时若要监听异常结果,你需要手动实现 onNoSuchConstructor 方法。 Change Records 请转移到新方法 Change Records 新增 Function Illustrate Change Records Function Illustrate 执行 Change Records Function Illustrate 执行 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 合并到 合并到 Function Illustrate 可通过指定类型查找指定 Change Records Change Records 允许不填写名称 Function Illustrate 设置 Pay Attention 若不填写名称则必须存在一个其它条件。 Change Records Function Illustrate 设置 可不填写类型。 Change Records 将方法体进行 inline 合并到 Function Illustrate 设置 可不设置筛选条件。 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 顺序筛选字节码的下标。 Change Records Function Illustrate 设置 Pay Attention 若不填写名称则必须存在一个其它条件。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records 合并到 Function Illustrate 设置 Pay Attention 若不填写名称则必须存在一个其它条件。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 Pay Attention 可不填写类型。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置在 Notice 若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。 Change Records Function Illustrate Change Records Function Illustrate 创建需要重新查找的 你可以添加多个备选 Change Records Function Illustrate Change Records Function Illustrate 当在 Function Example 你可以方便地对重查找的 The following example Change Records 继承到接口 Function Illustrate Change Records 将方法体进行 inline Function Illustrate 创建监听结果事件方法体。 Function Example 你可以使用 The following example Change Records Function Illustrate 获得 若有多个 Function Example 你可以轻松地得到 The following example 如果你取到的是静态 The following example Change Records Function Illustrate 获得 返回全部查找条件匹配的多个 Function Example 你可以通过此方法来获得当前条件结果中匹配的全部 The following example Change Records Function Illustrate 得到 若有多个 Field 结果只会返回第一个。 在查找条件找不到任何结果的时候将返回 Change Records Function Illustrate 得到 返回全部查找条件匹配的多个 在查找条件找不到任何结果的时候将返回空的 Change Records Function Illustrate 获得 若有多个 Pay Attention 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 Change Records Function Illustrate 获得 返回全部查找条件匹配的多个 Pay Attention 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 Change Records Function Illustrate 创建 Function Example 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 The following example Change Records Function Illustrate 监听找不到 Change Records Function Illustrate 忽略异常并停止打印任何错误日志。 若 Notice 此时若要监听异常结果,你需要手动实现 onNoSuchField 方法。 Change Records 请转移到新方法 Change Records 新增 不再对外公开 Function Illustrate Change Records 请直接使用 Change Records Function Illustrate 获得当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records Function Illustrate 得到当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records Function Illustrate 得到当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records 修改 移动方法到 Function Illustrate 得到当前 Change Records Function Illustrate 得到当前 Change Records Function Illustrate 得到当前 Change Records Function Illustrate 设置当前 Change Records Function Illustrate 设置当前 Pay Attention 请确保实例对象类型为 Boolean。 Change Records Function Illustrate 设置当前 Pay Attention 请确保实例对象类型为 Boolean。 Change Records Function Illustrate 设置当前 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 合并到 合并到 Function Illustrate 可通过指定类型查找指定 Change Records 允许不填写名称 Function Illustrate 设置 Pay Attention 若不填写名称则必须存在一个其它条件。 Change Records Function Illustrate 设置 你可以不使用 若参数个数小于零则忽略并使用 Change Records Function Illustrate 设置 Change Records 将方法体进行 inline 合并到 Function Illustrate 设置 可不设置筛选条件。 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 Change Records Function Illustrate 设置 如果同时使用了 如果 Pay Attention 无参 Method 请使用 emptyParam 设置查找条件。 有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 顺序筛选字节码的下标。 Change Records Function Illustrate 设置 Pay Attention 若不填写名称则必须存在一个其它条件。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records 合并到 Function Illustrate 设置 Pay Attention 若不填写名称则必须存在一个其它条件。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 你可以不使用 若参数个数小于零则忽略并使用 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 你可以不使用 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 你可以不使用 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置 可不填写返回值。 Pay Attention 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 Change Records Function Illustrate 设置在 Notice 若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。 Change Records Function Illustrate Change Records 将方法体进行 inline Function Illustrate 创建需要重新查找的 你可以添加多个备选 Change Records Function Illustrate Change Records Function Illustrate 当在 Function Example 你可以方便地对重查找的 The following example Change Records Function Illustrate Change Records Function Illustrate 创建监听结果事件方法体。 Function Example 你可以使用 The following example Change Records Function Illustrate 设置全部查找条件匹配的多个 Change Records Function Illustrate 创建 Function Example 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 The following example Change Records Function Illustrate 监听找不到 只会返回第一次的错误信息,不会返回 Change Records 继承到接口 Function Illustrate Change Records 将方法体进行 inline Function Illustrate 创建监听结果事件方法体。 Function Example 你可以使用 The following example Change Records Function Illustrate 获得 若有多个 Pay Attention 若你设置了 remedys 请使用 wait 回调结果方法。 Function Example 你可以通过获得方法所在实例来执行 The following example 若当前为静态方法,你可以不设置实例。 The following example Change Records Function Illustrate 获得 返回全部查找条件匹配的多个 Function Example 你可以通过此方法来获得当前条件结果中匹配的全部 The following example Change Records Function Illustrate 得到 若有多个 在查找条件找不到任何结果的时候将返回 Change Records Function Illustrate 得到 返回全部查找条件匹配的多个 在查找条件找不到任何结果的时候将返回空的 Change Records Function Illustrate 获得 若有多个 Pay Attention 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 Change Records Function Illustrate 获得 返回全部查找条件匹配的多个 Pay Attention 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 Change Records 将方法体进行 inline Function Illustrate 创建 Function Example 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 The following example Change Records 将方法体进行 inline Function Illustrate 监听找不到 只会返回第一次的错误信息,不会返回 Change Records Function Illustrate 忽略异常并停止打印任何错误日志。 若 Notice 此时若要监听异常结果,你需要手动实现 onNoSuchMethod 方法。 Change Records 请转移到新方法 Change Records 新增 Function Illustrate Change Records Function Illustrate 标识需要调用当前 若当前 Pay Attention 你只能在 (Xposed) 宿主环境中使用此功能。 Change Records Function Illustrate 执行 Change Records Function Illustrate 执行 Change Records Function Illustrate 执行 Change Records 修改 Function Illustrate 执行 Change Records 修改 Function Illustrate 执行 Change Records 修改 Function Illustrate 执行 Change Records 修改 Function Illustrate 执行 Change Records 修改 Function Illustrate 执行 Change Records 修改 Function Illustrate 执行 Change Records Function Illustrate 执行 Change Records 修改 Function Illustrate 执行 Change Records Function Illustrate 执行 Change Records Function Illustrate 执行 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate Change Records Function Illustrate 子类 Hook 开始。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是自定义 Change Records Function Illustrate 定义一个 Change Records Function Illustrate 全部 Change Records Function Illustrate 全部 Change Records Function Illustrate 全部 Change Records Function Illustrate 通过当前 Pay Attention 此方法在 Class 数量过多及查找条件复杂时会非常耗时。 建议启用 async 或设置 name 参数,name 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。 此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。 Change Records Function Illustrate 监听当前 Pay Attention 只有当前 ClassLoader 有主动使用 ClassLoader.loadClass 事件时才能被捕获。 这是一个实验性功能,一般情况下不会用到此方法,不保证不会发生错误。 只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。 Function Example 针对一些使用特定 Notice 为了防止发生问题,你需要得到一个存在的 ClassLoader 实例来使用此功能。 比如我们在 The following example 或使用你得到的存在的 The following example 在判断到这个 The following example Change Records Change Records Change Records 请直接使用 Change Records Function Illustrate 当前 Change Records 请转到 Change Records Function Illustrate 通过字符串类名转换为 Function Example 你可以直接填写你要查找的目标 The following example 你还可以自定义 The following example Change Records Function Illustrate 通过字符串类名转换为 找不到 Function Example 用法请参考 String.toClass 方法。 Change Records Function Illustrate 通过 Function Example 我们要获取一个 The following example 现在,你可以直接 The following example 若目标存在的 The following example Change Records 支持直接使用空参数方法使用默认 Function Illustrate 通过字符串类名使用指定的 Function Example 你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 The following example 填入方法中的 The following example Change Records 合并到 将方法体进行 inline Function Illustrate 查找变量是否存在。 Change Records 新增 合并到 将方法体进行 inline Function Illustrate 查找方法是否存在。 Change Records 合并到 将方法体进行 inline Function Illustrate 查找构造方法是否存在。 Change Records 将方法体进行 inline 合并到 Function Illustrate 查找 Change Records Function Illustrate 查找 Change Records Change Records Change Records Change Records Change Records 将方法体进行 inline Function Illustrate 查找并得到变量。 Change Records 新增 合并到 将方法体进行 inline Function Illustrate 查找并得到方法。 Change Records 合并到 将方法体进行 inline Function Illustrate 查找并得到构造方法。 Change Records Change Records Change Records Function Illustrate 获得当前 如果当前实例不存在泛型将返回 Change Records Function Illustrate 获得当前 如果当前实例不存在泛型将返回 Change Records 新增 新增不使用 Function Illustrate 获得当前实例的类操作对象。 Change Records 将方法体进行 inline 请转移到 Change Records 将方法体进行 inline 加入无泛型方法 Function Illustrate 通过构造方法创建新实例,指定类型 Change Records 将方法体进行 inline Function Illustrate 遍历当前类中的所有方法。 Change Records 将方法体进行 inline Function Illustrate 遍历当前类中的所有构造方法。 Change Records 将方法体进行 inline Function Illustrate 遍历当前类中的所有变量。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 合并到 Function Illustrate 这是 Change Records 合并到 Function Illustrate 在 Change Records 合并到 Function Illustrate 在 Change Records Function Illustrate 获取模块的存取对象。 Change Records Function Illustrate 获取模块的存取对象,可设置 Change Records Function Illustrate 获取模块的数据通讯桥命名空间对象。 Pay Attention 只能在模块环境使用此功能,其它环境下使用将不起作用。 Change Records Function Illustrate 获取当前进程名称。 Change Records Function Illustrate 向 Hook APP (宿主) 注入成功后,你就可以直接使用例如 注入的资源作用域仅限当前 Pay Attention 只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。 Change Records Function Illustrate 向 Hook APP (宿主) 注册当前 Xposed 模块的 注册成功后,你就可以直接使用 使用此方法会在未注册的 你要将需要在宿主启动的 Pay Attention 只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。 Change Records Function Illustrate 生成一个 在 Hook APP (宿主) 中使用此方法会自动调用 如果在 Hook APP (宿主) 中使用此方法发生 Change Records 请转移到 Change Records 请转移到 Change Records 请转移到 Change Records 请转移到 Change Records 请转移到 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是 Change Records Function Illustrate 需要打印的日志类型。 决定于模块与 (Xposed) 宿主环境使用的打印方式。 Change Records Function Illustrate 仅使用 Change Records Function Illustrate 仅使用 Pay Attention 只能在 (Xposed) 宿主环境中使用,模块环境将不生效。 Change Records Function Illustrate 分区使用。 (Xposed) 宿主环境仅使用 模块环境仅使用 Change Records Function Illustrate 同时使用。 (Xposed) 宿主环境使用 模块环境仅使用 Change Records Function Illustrate 调试日志实现类。 Change Records Function Illustrate 获取当前日志文件内容。 如果当前没有已记录的日志会返回空字符串。 Change Records Function Illustrate 清除全部已记录的日志。 Change Records Function Illustrate 保存当前日志到文件。 若当前未开启 日志文件会追加到 Pay Attention 文件读写权限取决于当前宿主已获取的权限。 Change Records Function Illustrate 配置 Change Records Function Illustrate 标签。 Change Records Function Illustrate 优先级。 Change Records Function Illustrate 当前宿主的包名。 Change Records Function Illustrate 当前宿主的用户 ID (主用户不显示)。 Change Records Function Illustrate 是否启用调试日志的输出功能。 关闭后将会停用 但是不影响当你手动调用下面这些方法输出日志。 当 Change Records Function Illustrate 是否启用调试日志的记录功能。 开启后将会在内存中记录全部可用的日志和异常堆栈。 需要同时启用 isEnable 才能有效。 Pay Attention 过量的日志可能会导致宿主运行缓慢或造成频繁 GC。 开启后你可以调用 YukiHookLogger.saveToFile 实时保存日志到文件或使用 YukiHookLogger.contents 获取实时日志文件。 Change Records Function Illustrate 这是一个调试日志的全局标识。 默认文案为 你可以修改为你自己的文案。 Change Records Function Illustrate 自定义调试日志对外显示的元素。 只对日志记录和 日志元素的排列将按照你在 你还可以留空 可用的元素有: Function Example 打印的日志样式将按照你设置的排列顺序和元素内容进行。 The following example 以上内容定义的日志将显示为如下样式。 The following example 如果我们调整元素顺序以及减少个数,那么结果又会不一样。 The following example 以上内容定义的日志将显示为如下样式。 The following example Change Records 新增 Function Illustrate 向 Change Records 新增 Function Illustrate 向 Change Records 新增 Function Illustrate 向 Change Records 新增 Function Illustrate 向 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 移动 修正拼写错误的 creater 命名到 creator Function Illustrate Hook 方法、构造方法的目标对象实现类。 Change Records 在 Function Illustrate 获取当前 Hook 对象 这里的数组每项类型默认为 Change Records 请使用 Change Records 请使用 Change Records Function Illustrate 获取当前 Hook 实例的对象。 Pay Attention 如果你当前 Hook 的对象是一个静态,那么它将不存在实例的对象。 Change Records Function Illustrate 获取当前 Hook 实例的类对象。 Change Records Function Illustrate 获取当前 Hook 对象的 在不确定 Change Records Function Illustrate 获取当前 Hook 对象的方法。 Change Records Function Illustrate 获取当前 Hook 对象的构造方法。 Change Records Function Illustrate 获取、设置当前 Hook 对象的 Change Records Function Illustrate 判断是否存在设置过的方法调用抛出异常。 Change Records Function Illustrate 获取设置的方法调用抛出异常。 Change Records Function Illustrate 向 Hook APP 抛出异常。 使用 使用 仅会在回调方法的 Pay Attention 设置后会同时执行 resultNull 方法并将异常抛出给当前 Hook APP。 Function Example Hook 过程中的异常仅会作用于 (Xposed) 宿主环境,目标 Hook APP 不会受到影响。 若想将异常抛给 Hook APP,可以直接使用如下方法。 The following example Pay Attention 向 Hook APP 抛出异常会对其暴露被 Hook 的事实,是不安全的,容易被检测,请按实际场景合理使用。 Change Records Function Illustrate 获取当前 Hook 对象的 Change Records Change Records Change Records Function Illustrate 获取当前 Hook 实例的对象 Function Example 你可以通过 The following example Change Records Function Illustrate 获取当前 Hook 对象的 Change Records 默认值 Function Illustrate 获取当前 Hook 对象的 Function Example 你可以通过 你可以直接使用 Pay Attention 请确保 param 类型为你的目标实例类型。 The following example 你可以这样直接设置第一位 The following example 你还可以直接设置最后一位 The following example 你还可以使用 The following example 你还可以使用 Pay Attention 请确保 param 类型为 Boolean。 The following example 你还可以使用 Pay Attention 请确保 param 类型为 Boolean。 The following example Change Records Function Illustrate 执行原始 调用自身未进行 Hook 的原始 功能实例 此方法可以 调用自身原始的方法不会再经过当前 比如我们 Hook 的这个方法被这样调用 The following example Change Records 不再需要使用 Function Illustrate 执行原始 调用自身未进行 Hook 的原始 功能实例 此方法可以 调用自身原始的方法不会再经过当前 比如我们 Hook 的这个方法被这样调用 The following example Change Records Function Illustrate 设置当前 Hook 对象方法的 Pay Attention 请确保 result 类型为 Boolean。 Change Records Function Illustrate 设置当前 Hook 对象方法的 Pay Attention 请确保 result 类型为 Boolean。 Change Records Function Illustrate Notice 此方法将强制设置 Hook 对象方法的 result 为 null。 Change Records Function Illustrate 对方法参数的数组下标进行实例化类。 Change Records Function Illustrate 获取当前 Hook 对象的 Change Records Function Illustrate 获取当前 Hook 对象的 Change Records Function Illustrate 对方法参数的修改进行实例化类。 Change Records 修改 Function Illustrate 得到方法参数的实例对象 Change Records Function Illustrate 得到方法参数的实例对象 Byte。 Change Records 修改 Function Illustrate 得到方法参数的实例对象 Int。 Change Records 修改 Function Illustrate 得到方法参数的实例对象 Long。 Change Records 修改 Function Illustrate 得到方法参数的实例对象 Short。 Change Records 修改 Function Illustrate 得到方法参数的实例对象 Double。 Change Records 修改 Function Illustrate 得到方法参数的实例对象 Float。 Change Records 修改 Function Illustrate 得到方法参数的实例对象 String。 Change Records Function Illustrate 得到方法参数的实例对象 Char。 Change Records 修改 Function Illustrate 得到方法参数的实例对象 Boolean。 Change Records Function Illustrate 得到方法参数的实例对象 Any。 Change Records Function Illustrate 得到方法参数的实例对象 Array。 Change Records Function Illustrate 得到方法参数的实例对象 List。 Change Records Function Illustrate 设置方法参数的实例对象。 Change Records Function Illustrate 设置方法参数的实例对象为 Change Records Function Illustrate 设置方法参数的实例对象为 Pay Attention 请确保目标对象的类型是 Boolean。 Change Records Function Illustrate 设置方法参数的实例对象为 Pay Attention 请确保目标对象的类型是 Boolean。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 装载 Hook 的目标 APP 入口对象实现类。 Change Records Function Illustrate 获取当前 Hook APP 的 Change Records Function Illustrate 获取当前 Hook APP 的 Change Records Function Illustrate 获取当前 Hook APP 的用户 ID。 机主为 Change Records 加入可空类型 (空安全) Function Illustrate 获取当前 Hook APP 的 Pay Attention 首次装载可能是空的,请延迟一段时间再获取或使用 onAppLifecycle 监听来完成。 Change Records 加入可空类型 (空安全) Function Illustrate 获取当前 Hook APP 的 Resources。 Pay Attention 你只能在 HookResources.hook 方法体内或 appContext 装载完毕时进行调用。 Change Records Function Illustrate 获取当前系统框架的 Change Records Function Illustrate 获取当前 Hook APP 的进程名称。 Change Records Function Illustrate 获取当前 Hook APP 的包名。 Change Records Function Illustrate 获取当前 Hook APP 是否为第一个 Change Records Function Illustrate 获取当前 Hook APP 的主进程名称。 其对应的就是 Change Records Function Illustrate 获取当前 Xposed 模块自身 APK 文件路径。 Pay Attention 作为 Hook API 装载时无法使用,会获取到空字符串。 Change Records Function Illustrate 获取当前 Xposed 模块自身 Pay Attention 作为 Hook API 或不支持的 Hook Framework 装载时无法使用,会抛出异常。 Change Records Function Illustrate 获得当前使用的存取数据对象缓存实例。 Pay Attention 作为 Hook API 装载时无法使用,会抛出异常。 Change Records 将方法体进行 inline Function Illustrate 获得当前使用的存取数据对象缓存实例。 你可以通过 Pay Attention 作为 Hook API 装载时无法使用,会抛出异常。 Change Records Function Illustrate 获得当前使用的数据通讯桥命名空间对象。 Pay Attention 作为 Hook API 装载时无法使用,会抛出异常。 Change Records Function Illustrate 获得当前 Hook APP 的 请调用 Change Records Function Illustrate 刷新当前 Xposed 模块自身 Change Records Function Illustrate 监听当前 Hook APP 生命周期装载事件。 Notice 在 loadZygote 中不会被装载,仅会在 loadSystem、loadApp 中装载。 作为 Hook API 装载时请使用原生的 Application 实现生命周期监听。 Change Records 将方法体进行 inline Function Illustrate 装载并 Hook 指定包名的 APP。 装载并 Hook 指定、全部包名的 APP。 若要装载 APP Zygote 事件,请使用 若要 Hook 系统框架,请使用 Function Example 你可以使用 The following example 若不指定 The following example Change Records Function Illustrate 装载 APP Zygote 事件。 方法中的两个参数一个可作为 Change Records Function Illustrate 装载并 Hook 系统框架。 方法中的两个参数一个可作为 Change Records Function Illustrate 装载并 Hook APP 的指定进程。 Change Records Function Illustrate 装载 Hook 子类。 你可以填入 Change Records Function Illustrate 通过 Pay Attention 此方法在 Class 数量过多及查找条件复杂时会非常耗时。 建议启用 async 或设置 name 参数,name 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。 此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。 Change Records 请转移到 Change Records 请转移到 Change Records Function Illustrate 通过字符串类名、 默认使用当前 Function Example 你可以轻松地将 The following example 你还可以向 The following example 你还可以创建一个 The following example 同样地,你还可以向 The following example Change Records Function Illustrate 通过字符串类名、 默认使用当前 找不到 Function Example 用法请参考 String+VariousClass.toClass 方法。 Change Records Function Illustrate 通过字符串类名查找是否存在。 默认使用当前 Function Example 你可以轻松的使用此方法判断字符串中的类是否存在。 The following example 你还可以自定义其中的 The following example Change Records 移除了 新增 Function Illustrate 通过完整包名+名称查找需要被 Hook 的 Notice 使用此方法会得到一个 HookClass 仅用于 Hook,若想查找 Class 请使用 toClass 功能。 Function Example 你可以使用三种方式查找你需要 Hook 的目标 你可以直接将被查找的 The following example 若你不确定多个版本的 The following example 你还可以创建一个 The following example 若你当前需要查找的 The following example 同样地,在不确定多个版本的 The following example Change Records 新增 新增 新增 新增 将方法体进行 inline 移除了 添加了 Function Illustrate 这是一切 Hook 的入口创建方法,Hook 方法、构造方法。 Function Example 如你所见,Hook 方法体的创建可使用 4 种方式。 通过字符串类名得到 The following example 通过 The following example 使用 默认情况下 API 会将 The following example 若当前 The following example 使用 The following example 或者直接使用可变字符串数组进行创建。 The following example Change Records Function Illustrate Hook APP 的 Resources。 Pay Attention 请注意你需要确保当前 Hook Framework 支持且 InjectYukiHookWithXposed.isUsingResourcesHook 已启用。 Function Example Resources Hook 为固定用法,获取 The following example Pay Attention 这是固定用法,为了防止发生问题,你不可手动实现任何 HookResources 实例执行 hook 调用。 将 Resources 的 Hook 设置为这样是为了与 Change Records Function Illustrate 当前 Hook APP 的生命周期实例处理类。 Change Records Function Illustrate 监听当前 Hook APP 装载 Change Records Function Illustrate 监听当前 Hook APP 装载 Change Records Function Illustrate 监听当前 Hook APP 装载 Change Records Function Illustrate 监听当前 Hook APP 装载 Change Records Function Illustrate 监听当前 Hook APP 装载 Change Records Function Illustrate 监听当前 Hook APP 装载 Change Records Function Illustrate 注册系统广播监听。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是一个预置 Hook 类型的常量类,主要为 详情可 点击这里 进行查看。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是一个预置 Hook 类型的常量类,主要为 详情可 点击这里 进行查看。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是一个预置 Hook 类型的常量类,主要为 详情可 点击这里 进行查看。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。 Change Records Function Illustrate 得到模糊类型。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是一个预置 Hook 类型的常量类,主要为 详情可 点击这里 进行查看。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是对使用 在你的 Xposed 模块的 或在 目前可实现功能如下 全局共享模块中静态的 在模块与宿主中装载 在模块与宿主中使用 在模块中使用系统隐藏 API,核心技术引用了开源项目 FreeReflection 在模块中使用 Function Example 将此类继承到你的自定义 The following example 在 The following example 如果你不需要自定义 The following example Change Records Function Illustrate 获取全局静态 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 对接 Change Records Function Illustrate 对接 创建 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 对接 Change Records 不再对外公开 Change Records Function Illustrate 获得当前 APP 的 Resources Id。 Change Records Function Illustrate 获得当前 APP 的 Resources。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 对接 Change Records Function Illustrate 装载 Hook APP 的目标布局 Resources 实现类。 Change Records Function Illustrate 获取当前被 Hook 的布局装载目录名称。 例如: Change Records Function Illustrate 获取当前被 Hook 的布局实例。 Change Records Function Illustrate 使用 Identifier 查找 Hook APP 指定 Id 的 扩展方法可以使用 Identifier 查找 Hook APP 当前装载布局中指定 Id 的 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 实现对原生 Xposed API 的装载事件监听。 Change Records Function Illustrate 对 Change Records Function Illustrate 设置 initZygote 事件监听。 Change Records Function Illustrate 设置 handleLoadPackage 事件监听。 Change Records Function Illustrate 设置 handleInitPackageResources 事件监听。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 实现 Xposed 模块的数据通讯桥。 通过模块与宿主相互注册 模块需要将 Pay Attention 模块与宿主需要保持存活状态,否则无法建立通讯。 Change Records 新增 Function Illustrate Change Records Function Illustrate 创建一个调用空间。 Change Records Function Illustrate 发送键值数据。 Change Records Function Illustrate 仅发送键值监听,使用默认值 Change Records 移除默认值 Function Illustrate 获取键值数据。 Change Records Function Illustrate 仅获取监听结果,不获取键值数据。 Pay Attention 仅限使用 VALUE_WAIT_FOR_LISTENER 发送的监听才能被接收。 Change Records Function Illustrate 获取模块与宿主的版本是否匹配。 通过此方法可原生判断 Xposed 模块更新后宿主并未重新装载造成两者不匹配的情况。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 数据通讯桥键值构造类。 这个类是对 Function Example 建立一个模板类定义模块与宿主需要发送的键值数据。 The following example 键值数据定义后,你就可以方便地在模块和宿主中调用所需要发送的数据。 模块示例如下 宿主示例如下 你依然可以不使用模板定义的默认值,随时修改你的默认值。 The following example Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 代理 继承于此类的 在 (Xposed) 宿主环境需要在宿主启动时调用 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 代理 继承于此类的 在 (Xposed) 宿主环境需要在宿主启动时调用 在 (Xposed) 宿主环境需要重写 Change Records Function Illustrate 设置当前代理的 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 代理 通过包装,你可以轻松在 (Xposed) 宿主环境使用来自模块的主题资源。 Change Records Function Illustrate 设置当前 设置后会自动调用 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 实现 Xposed 模块的数据存取,对接 在不同环境智能选择存取使用的对象。 Pay Attention 此功能为实验性功能,仅在 LSPosed 环境测试通过,EdXposed 理论也可以使用但不再推荐。 使用 LSPosed 环境请在 若你在按照规定配置后依然无法使用或出现文件权限错误问题,可以参考 isEnableHookSharedPreferences。 未使用 LSPosed 环境请将你的模块 太极请参阅 文件权限/配置/XSharedPreference。 Pay Attention 当你在 Xposed 模块中存取数据的时候 context 必须不能是空的。 若你正在使用 可选配置 若你不想将你的模块的 The following example Change Records Function Illustrate 获取 Pay Attention 只能在 (Xposed) 宿主环境中使用,模块环境中始终返回 false。 Change Records Function Illustrate 获取 前提条件为当前 Xposed 模块已被激活。 Pay Attention 只能在模块环境中使用,(Xposed) 宿主环境中始终返回 false。 Change Records Function Illustrate 自定义 Sp 存储名称。 Function Example 在 The following example 在 (Xposed) 宿主环境 The following example Change Records Function Illustrate 忽略缓存直接读取键值。 无论是否开启 仅在 Change Records Function Illustrate 获取 Change Records Function Illustrate 获取 Change Records Function Illustrate 获取 Change Records Function Illustrate 获取 Change Records Function Illustrate 获取 Change Records Function Illustrate 获取 Change Records Function Illustrate 获取全部存储的键值数据。 智能识别对应环境读取键值数据。 Pay Attention 每次调用都会获取实时的数据,不受缓存控制,请勿在高并发场景中使用。 Change Records Function Illustrate 移除全部包含 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 移除 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 移除全部存储数据。 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 存储 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 存储 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 存储 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 存储 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 存储 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 存储 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 智能获取指定类型的键值。 Change Records Function Illustrate 智能存储指定类型的键值。 Notice 在 (Xposed) 宿主环境下只读,无法使用。 Change Records Function Illustrate 清除 无论是否开启 调用此方法将清除当前存储的全部键值缓存。 下次将从 在 (Xposed) 宿主环境中使用。 Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 键值对存储构造类。 这个类是对 Function Example 建立一个模板类定义模块与宿主需要使用的键值数据。 The following example 键值数据定义后,你就可以方便地在模块和宿主中调用所需要的数据。 模块示例如下 宿主示例如下 你依然可以不使用模板定义的默认值,随时修改你的默认值。 The following example Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records Function Illustrate 这是对使用 此类接管了 在你使用 然后请将重写方法由 Function Example 使用 The following example 其余用法与 Change Records Function Illustrate 对接原始方法 Change Records Function Illustrate 实现了 Function Example Notice 在使用 onSharedPreferenceChanged 时请保留 super 方法。 The following example Notice The English translation of this page has not been completed, you are welcome to contribute translations to us. You can use the Chrome Translation Plugin to translate entire pages for reference. Change Records 作废了 转移到 Function Illustrate YukiHookAPI 的 Xposed 装载 API 调用接口。 Change Records Function Illustrate 配置 Pay Attention 在这里只能进行初始化配置,不能进行 Hook 操作。 此方法可选,你也可以选择不对 YukiHookAPI.Configs 进行配置。 Change Records Function Illustrate Xposed API 的模块装载调用入口方法。 Change Records Function Illustrate 监听 Xposed 原生装载事件。 若你的 Hook 事件中存在需要兼容的原生 Xposed 功能,可在这里实现。 请在这里使用 YukiXposedEvent 创建回调事件监听。 可监听的事件如下: Pay Attention 此接口仅供监听和实现原生 Xposed API 的功能,请不要在这里操作 YukiHookAPI。 Change Records 请转移到 This is an extension that injects Module App's Resources, Before using the following functions, in order to prevent Resource Id from conflicting with each other, you need to modify the Resource Id in the Notice The sample Resource Id value provided is for reference only, 0x7f cannot be used, the default is 0x64. In order to prevent the existence of multiple Xposed Modules in the current Host App, it is recommended to customize your own Resource Id. After the Host App is hooked, we can directly inject the The following example You can also inject current Module App's Resources directly in The following example Tips For more functions, please refer to the Context+Resources.injectModuleAppResources method. When the During the Hook process, if we want to directly start the unregistered After the Host App is hooked, we can directly register the The following example You can also register the current Module App's The following example If the Usually, it works, but the above situation will fail in some apps, for example, some If the unregistered You need to choose an unneeded For example, we have found a suitable The following example According to the The following example Alternatively, if you write a The following example After the registration is complete, extends the These The following example If you need to extends The following example After all the above steps are completed, you can happily call The following example Tips For more functions, please refer to the Context.registerModuleAppActivities method. Sometimes, we need to use At this time, we want to use The following example You can also set the system (native) night mode and day mode on the current Which requires at least Android 10 and above system version support and the current theme contains night mode related elements. The following example This way, we can create dialogs in the Host App very simply using Possible Problems Because some androidx dependent libraries or custom themes used by some apps may interfere with the actual style of the current MaterialAlertDialog, such as the button style of the dialog. You can refer to the Module App Demo in this case and see here is the sample code to fix this problem. ClassCastException may occur when some apps are created, please manually specify a new Configuration instance to fix. Tips For more functions, please refer to the Context.applyModuleTheme method. This is an extension of the lifecycle of an automatic hooking Host App. Implement the monitoring function by automating the lifecycle method of the Host App. We need to listen to the startup and lifecycle methods of the Host App's The following example Tips For more functions, please refer to AppLifecycle. Register system broadcast through the We can also register system broadcast in the Host App's The following example Tips For more functions, please refer to AppLifecycle. Log is the most important part of the debugging process, You can call The usage method is as follows. The following example At this point, The default You can also customize this value dynamically, but it is not recommended to modify The following example The printed result is as shown below. The following example You can also use You can choose to use The default type is For example we only use The following example Or just use The following example If you want to intelligently distinguish the (Xposed) Host environment from the Module environment, you can write it in the following form. The following example In this way, the API will intelligently select the specified method type to print this log in different environments. You can call The usage method is as follows. The following example The error log is the highest level, regardless of whether you have filtered only For error-level logging, you can also append an exception stack. The printed result is as shown below. The following example At the same time, the log will help you print the entire exception stack. The following example In the error log, you can also use Tips For more functions, please refer to the loggerE method. You can save all currently printed logs directly to a file using the The following example You can also use The following example The above features require You can also use This function requires The following example Tips For more functions, please refer to YukiHookLogger.contents, YukiHookLogger.saveToFile methods and YukiHookLogger.Configs. Here are the extension functions related to the Class object itself. Suppose we want to get a Normally, we can use the standard reflection API to find this The following example This is probably not very friendly, and The above writing can be written as The following example If the current If you are not sure whether the The following example We can also get an existing The following example Tips For more functions, please refer to classOf, String.toClass, String.toClassOrNull, PackageParam → String+ VariousClass.toClass, PackageParam → String+VariousClass.toClassOrNull methods. Suppose we want to determine whether a Usually, we can use the standard reflection API to find this The following example This is probably not very friendly, and The above writing can be written as The following example Tips For more functions, please refer to String.hasClass, PackageParam → String.hasClass methods. The Its correct position is uncertain, and cannot be obtained directly through Object Conversion. At this point, there is Notice At present, the function of DexClassFinder is still in the experimental stage. Since the search function is only implemented through the Java layer, the performance may not reach the optimal level when there are too many Host App's Class. If something got wrong welcome to feedback. Since it is a reflection-level API, currently it can only locate the specified Class through the characteristics of Class and Member, and cannot locate it by specifying the string and method content characteristics in the bytecode. The speed of searching Class depends on the performance of the current device. At present, the mainstream mobile processors are in the 3~10s range when the conditions are not complicated in the 10~15w number of Class, the fastest speed can reach within 25s under slightly complex conditions. Please note that the more the same type Class is matched, the slower the speed. Below is a simple usage example. Suppose the following The following example At this point, we want to get this In Each of the conditions demonstrated below is optional, and the more complex the conditions, the more accurate the positioning and the worse the performance. The following example Tips The conditional usage of Field, Method, Constructor in the above usage is consistent with the related usage in Member Extensions, with only minor differences. For more functions, please refer to MemberRules, FieldRules, MethodRules, ConstructorRules. By default, If the search takes too long, it may cause ANR problems to the Host App. In response to the above problems, we can enable asynchronous, just add the parameter Notice For the asynchronous case you need to use the wait method to get the result, the get method will no longer work. The following example In this way, our search process runs asynchronously, it will not block the main thread, and each search will be performed in a separate thread at the same time, which can achieve the effect of parallel tasks. Since the search is performed again every time the Host App is reopened, this is a waste of repetitive performance when the Host App's version is unchanged. At this point, we can locally cache the search results of the current Host App's version by specifying the Next time, the found class name will be directly read from the local cache. The local cache uses After enabling the local cache, The following example If you want to clear the local cache manually, you can use the following method to clear the current version of the Host App's cache. The following example You can also clear the Host App's cache for a specific version. The following example If you need to search a set of Tips For more functions, please refer to ClassLoader.searchClass, PackageParam.searchClass methods. Here are the extension functions related to the Class bytecode member variables Field, Method, Constructor. Tips Member is the interface description object of Field, Method, Constructor, which is the general term for the bytecode members in Class in Java reflection. Suppose there is such a The following example Suppose we want to get the Normally, we can use the standard reflection API to find this method. The following example This is probably not very friendly, and The above writing can be written as The following example Tips For more features, please refer to MethodFinder. Similarly, we need to get the The following example Tips For more features, please refer to FieldFinder. Maybe you also want to get the current The following example If you want to get the no-argument constructor of The following example Tips For more features, please refer to ConstructorFinder. Suppose we want to get the The following example Through observation, it is found that there is only one method named The following example Yes, you can refine your find criteria for methods that do not change exactly. When using only The problem comes again, this Normally we would use At this point, after determining the uniqueness of the method, you can use The following example Although the above example can be successfully matched, it is not accurate. At this time, you can also use The following example You will notice that Referring to the above find conditions, we only need to add a The following example At this time, we can get this method in the super class. Since we now know that the The following example At this time, we can also get this method in the super class. Once Tips For more functions, please refer to MethodFinder.superClass, ConstructorFinder.superClass, FieldFinder.superClass methods. Pay Attention The currently founded Method can only find the Method of the current Class unless the superClass condition is specified, which is the default behavior of the Java Reflection API. If we want to find a method name, but are not sure if it has changed in each release, we can use vague find. Suppose we want to get the The following example Knowing that there is currently only one The following example We can also judge based on the first and last strings. The following example By observing that this method name contains only letters, we can add a precise search condition. The following example Tips Use name { ... } to create a conditional method body, where the variable it is the string of the current name, and you can freely use it in the extension method of NameRules function. The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result. For more functions, please refer to NameRules. Sometimes, we may need to find a set of methods, constructors, and fields with the same characteristics in a At this time, we can use relative condition matching to complete. Based on the result of the find condition, we only need to replace Suppose this time we want to get all methods in The following example The above example can be perfectly matched to the following 3 methods. If you want to define the conditions for the range of the number of parameters more freely, you can use the following implementation. The following example The above example can be perfectly matched to the following 6 methods. By observing that there are two methods named The following example The above example can be perfectly matched to the following 2 methods. Tips Use paramCount { ... } to create a conditional method body, where the variable it is the integer of the current number of parameters, and you can use it freely in the extension method of CountRules function in it. The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result. For more functions, please refer to CountRules. Some methods and fields are statically implemented in Suppose we want to get the contents of the static field The following example Assuming that there is a non-static Just add a filter. The following example We can also call a static method called The following example Likewise, you can identify it as a static. The following example Tips Use modifiers { ... } to create a conditional method body, at which point you can freely use its functionality in ModifierRules. The condition at the end of the method body needs to return a Boolean, which is the final condition judgment result. For more features, please refer to ModifierRules. You may have noticed that the example There are two options. The first option is to determine the name and type of the field. The following example The second option is to determine where the type of the field is located. The following example In the above two cases, the corresponding field Likewise, there are two obfuscated method names in this You can also have two options to get them. The first option is to determine the method name and method parameters. The following example The second option is to determine where the parameters of the method are located. The following example Since it is observed that this method is last in The following example Notice Please try to avoid using order to filter bytecode subscripts, they may be indeterminate unless you are sure that its position in this Class must not change. The methods of calling bytecode described above all need to use Is there a simpler way? At this point, you can use the The following example We can also use The following example If you don't like to use a lambda to create the namespace of the current instance, you can use the The following example Likewise, consecutive calls can be made between them, but inline calls are not allowed. The following example For The following example Notice The above current method is equivalent to calling the field { ... }.any()?.current() method in CurrentClass for you. If there is no CurrentClass calling field, you need to use field { ... }.get(instance).current() to call it. The problem comes again, I want to use reflection to create the following instance and call the method in it, how to do it? The following example Usually, we can use the standard reflection API to call. The following example But I feel that this approach is very troublesome. Is there a more concise way to call it? At this time, we can also use the The following example If you want the In this case, the constructor of the instance itself is private, but the method inside is public, so we only need to create its constructor by reflection. The following example Tips For more functions, please refer to CurrentClass and Class.buildOf method. If you are using reflection to call a method that has been hooked, how do we call its original method? The native Now, in Suppose below is the The following example Here's how the The following example At this point, we use reflection to call this method, and we will get the result of Hook The following example If we want to get the original method and result of this method without hooking, we just need to add The following example Tips For more functions, please refer to the MethodFinder.Result.original method. Suppose there are three different versions of There is also a method The following example of version A The following example of version B The following example of version C We need to get this same functionality of the At this point, you can use The following example Pay Attention The method lookup result using RemedyPlan can no longer use get to get method instance, you should use wait method. Also, you can continue to use The following example Take the current The following example Tips When creating a Hook, please refer to MethodFinder.Process.all, ConstructorFinder.Process.all methods. For more functions, please refer to MethodFinder.RemedyPlan, ConstructorFinder.RemedyPlan, FieldFinder.RemedyPlan . Suppose there is a The following example of version A The following example of version B At this time, what should we do if we want to call the The usual practice is to check if The following example I feel that this solution is very inelegant and cumbersome, then Now, you can get this The following example If the current The following example If you are not sure that all The following example If you are using the The following example Tips For more functions, please refer to VariousClass. If it is used when creating a Hook, it can be more convenient, and it can also automatically intercept the exception that The following example You can also define this The following example Tips For more functions, please refer to the PackageParam.findClass method. In the process of reflection, we may encounter generic problems. In the reflection processing of generics, For example we have the following generic class. The following example When we want to get a The following example When we want to call this The following example Tips For more functions, please refer to CurrentClass.generic, Class.generic methods and GenericClass. Here are some misunderstandings that may be encountered during use for reference. Pay Attention In find conditions you can only use index function once except order. The following example The following find conditions can be used without any problems. The following example Pay Attention In common method find conditions, even methods without parameters need to set find conditions. Suppose we have the following The following example We want to get the The following example However, the above example is wrong. You will find two Since the above example does not set the find conditions for This is a frequent error, without method parameters, you will lose the use of method parameter find conditions. The correct usage is as follows. The following example At this point, the above example will perfectly match the Compatibility Notes In the past historical versions of the API, it was allowed to match the method without writing the default matching no-parameter method, but the latest version has corrected this problem, please make sure that you are using the latest API version. In the construction method find conditions, constructors without parameters do not need to fill in the find conditions. Suppose we have the following The following example We want to get the The following example The above example can successfully obtain the Unlike normal methods, since the constructor does not need to consider the The following example Compatibility Notes In the past historical versions of the API, if the constructor does not fill in any find conditions, the constructor will not be found directly. This is a bug, the latest version has been fixed, please make sure you are using the latest API version. Pay Attention In the bytecode call result, the cast method can only specify the type corresponding to the bytecode. For example we want to get a field of type The following is the wrong way to use it. The following example The following is the correct way to use it. The following example When find methods and fields, we usually need to specify the type in find conditions. The following example Expressing the type Therefore, At this time, the above type can be written in the following form. The following example Common basic types in Java have been encapsulated as Name + Type, such as Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type You need to write Does it feel very troublesome? At this time, we can use the extension method At the same time, since Some common methods found in Hook have their corresponding encapsulation types for use, in the format Name + Class. For example, the Hook The following example Tips For more types, see ComponentTypeFactory, GraphicsTypeFactory, ViewTypeFactory, VariableTypeFactory. At the same time, you are welcome to contribute more commonly used types. This is a solution that uses system out-of-order broadcasting to send and receive data between the Module App and the Host App. Condition that needs to be met The Module App and the Host App need to remain alive, otherwise communication cannot be established. The basic usage of the By using The Module App example is as follows The Host App example is as follows You can leave the The Module App example is as follows The Host App example is as follows Pay Attention The receiver needs to stay alive to receive the communication data. Tips For more functions, please refer to YukiHookDataChannel. Through the communication bridge function, We only need to call the Bidirectional judgment can be performed between the Module App and the Host App. You can check in the Module App whether the Host App of the specified package name matches the version of the current Module App. The following example You can also determine in the Host App whether it matches the current Module App version. The following example Condition of method callback The Host App and Module App must be stay alive, and after activating the Module App restart the Hook target Host App object in scope. Tips For more functions, please refer to YukiHookDataChannel. Only examples used in Module App are listed here, the same Pay Attention In the Module App and Host App, each key callback event corresponding to dataChannel is not allowed to be repeatedly created, if repeated, the previous callback event will be replaced by the newly added callback event. When used in the Module App, it cannot be repeated in the same Activity, and the same key in different Activity is allowed to be repeated. The following example In the above example, the callback event A will be replaced by the callback event B, the Pay Attention A callback event with the same key will only call back the callback event registered in the Activity that the current Module App is displaying, such as test_key in the above, if OtherActivity is being displayed, then test_key in MainActivity will not be called back. The same key registers dataChannel in the same Activity but different Fragment, they will still be called back in the current Activity at the same time. In a Module App, you can only use Context of Activity to register dataChannel, you cannot use dataChannel in Application and Service. If you want to use dataChannel in Fragment, use activity?.dataChannel(...). In the Module environment, you can only receive communication data sent by the Host App with the specified package name and only send it to the Host App with the specified package name. Pay Attention In order to further prevent broadcast abuse, the API in the communication data will automatically specify the package name of the Host App and Module App to prevent other apps from monitoring and using broadcast to make overrun behaviors. This is an efficient Module App data storage solution that automatically connects We need to store the data of the Module App for the Host App to call. At this time, we will encounter the data exchange obstacle of the native The native Loading Usually we can initialize it in Host App like this. The following example Is there a convenient and quick solution? At this point, you can use the extension capability of When you store data in a Module App, you can use the following methods if you are currently in an The following example When you read data in a Host App, you can use the following methods. The following example You don't need to consider the module package name and a series of complicated permission configurations, everything is handled by To achieve localization of storage, you can specify the name of each This is used in the The following example Read like this in Host App. The following example If your project has a lot of fixed data that needs to be stored and read, it is recommended to use Tips For more functions, please refer to YukiHookModulePrefs, PrefsData. Loading If your Module App uses Pay Attention You must extends ModulePreferenceFragment to implement the module storage function of YukiHookModulePrefs. Tips For more functions, please refer to ModulePreferenceFragment. The basic configuration method of Either Use as Xposed Module Configs or Use as Hook API Configs, you can specify The Tips For more functions, please refer to the YukiHookAPI.configs method. The most important part of an Xposed Module or Hook API is the creation and use of Hooker. This solution is the simplest. If your module has few functions and a small amount of code, and does not need to be classified, it is recommended to create it in this way. The Tips For more functions, please refer to PackageParam. The Sample Code 1 Sample Code 2 Do your Hook operations in the This scheme is more suitable for large-scale projects, such as the need to classify Hooker or classify the role of Hook. Also for the Tips For more functions, please refer to YukiBaseHooker. The following example Child Hooker recommended singleton Notice You don't need to re-call encase in the onHook method extends YukiBaseHooker, this is wrong and will not take effect, you should start writing your Hook code directly . The following example As a child hooker, you can also call the The following example You can use the The following example Once all Hookers are set up, you can load your Hooker in the The following example Of course, we can also abbreviate it. The following example If your current Hook Framework supports and enables the Resources Hook feature, you can now create Resources Hooks directly in You don't need to separate the In The following example You can also use the The following example It is wrong to load Hooker directly or start Hook directly, load load load In this process, you need to use Notice Whether you use encase to create the lambda method body or use the Hooker form directly, you should not directly load the Hooker or start the Hook directly in the first onHook event. Below are two error examples. Sample Code 1 Sample Code 2 Below is a correct example of the wrong example above. Sample Code 1 Sample Code 2 If you are using it as a Hook API, then you only need to differentiate the Notice The encase method provides two identical methods for use as a Hook API, but with only one more parameter baseContext than the previous two. Method 1 Method 2 The Pay Attention Never use the encase method in an Xposed way without omitting the baseContext parameter, this will lead to your Hook not work at all. The Resources Hook feature is not supported as Hook API. As a Hook API, it is usually used for Hook operations for hot updates or functional needs of its own app and product testing. You just need to integrate the Then please integrate the Create your custom Add The following example In this way, you have completed the relevant configuration of the API. You can click here to see the similarities, differences and caveats. Notice You can no longer wrap with loadApp and start writing your Hook code directly. Here are some related ways of how to connect the Required Xposed API dependencies The following example Required Xposed API dependencies The following example Required Xposed API dependencies Please refer to xposed-hook-based-on-whale. The following example In most scenarios, the Xposed Module can be compressed by native obfuscation. Here is the configuration method of obfuscation. If you are using Pay Attention Proguard rules have been deprecated, please don't use them anymore. Since Android Gradle Plugin 4.2, the obfuscator with the latest version of the Android Jetpack default is R8, and you no longer need to consider obfuscation. To enable Here are the related configuration methods used by As an Xposed Module, You need to integrate the latest version of the You can configure how The Pay Attention The Class of the @InjectYukiHookWithXposed annotation must implements IYukiHookXposedInit interface. All Class tags in your current project can only exist once, if there are multiple declaration automatic builder will throw an exception at compile time, you can customize its related parameters. The The content of this parameter is a relative path match, and the default parameter is Pay Attention If your project is not in ../src/main.. or you set the project path manually using sourceSets, you need to set the sourcePath parameter manually, otherwise the automatic builder will not recognize your project path and will throw an exception at compile time. The following example The file path separator used by If left blank or not filled, the automatic builder will analyze and generate the current project file. Notice If you want to use the module package name to be automatically generated, you need to ensure that your project namespace has any of the following definitions in AndroidManifest.xml, build.gradle or build.gradle.kts. Example namespace The following definitions are for reference only, usually as long as your project can generate the If your module package name is automatically generated by unconventional means, or you think it is necessary to manually define the module package name, then you can directly set the The following example As long as you customize the The following example Notice In addition to the format of the manually defined module package name, the automatic builder will no longer check whether the module package name is correct, and you need to confirm its validity by yourself. By default, it will use your entry class package name to insert the Suppose this is your entry class. The following example The Xposed entry class is handled as follows. The following example The compiled class name structure is as follows. The following example We now define the entry class name as The following example The Xposed entry class is handled as follows. The following example The compiled class name structure is as follows. The following example Pay Attention The entryClassName you define must not be the same as the class name in xposed_init, otherwise the automatic builder throws an exception at compile time. The generated entry class after enabling it will look like the following. The following example If your current project does not need to use Reources Hook, you can set The following example The resulting entry class after closing will look like the following. The following example The Tips For more functions, please refer to IYukiHookXposedInit. When your Module App is loaded by Xposed, the The basic calling process is For details, please refer to API Basic Configs. If your current Xposed Module uses third-party resources, but may not be able to transfer them in a short time, you can use The following example Tips For more functions, please refer to the IYukiHookXposedInit.onXposedEvent method. Here is an introduction to the basic working method of The structure below describes the basic working and principle of The above structure can be written in the following form in code. You can find the demo provided by the API below to learn how to use Host App Demo click here to view Module App Demo click here to view Install the Host App and Module App Demo at the same time, and test the hooked function in the Host App by activating the Module App. Here are examples of Hook App, Hook System Framework and Hook Resources for reference. Suppose, we want to hook the Add code in the body of the The following example At this point, the So, what should I do if I want to continue the Hook In the code just now, continue to insert an The following example For the For example, I want to get The following example If The following example Some people may have started to say that Because some people may have the following needs. The following example That's okay, you can also create a Hook directly using the string class name. The following example Tips For more functions, please refer to MemberHookCreator. The first event Suppose we want to globally Hook the Add code in the body of the The following example Notice The functionality performed in loadZygote is very limited, and the loadZygote method is rarely needed. In Suppose, you want to get Add code in the body of the The following example Pay Attention loadZygote is directly different from loadSystem, loadZygote will be loaded in initZygote, and the System Framework is regarded as loadApp(name = "android") and exists, To Hook the System Framework, you can use loadSystem directly. Suppose, we want to replace the content of Add code in the body of the The following example If the current app has a title bar text set with You can also replace the Hook App's Resources with the current Xposed Module's Resources. Suppose, we want to continue to hook The following example At this point, the icon of the target app will be replaced with the icon we set. If you want to replace the Resources of the System Framework, you can do the same, just replace The following example Tips For more functions, please refer to ResourcesHookCreator. The native Xposed provides us with a The first way, save the The following example The second method, call The following example Tips For more functions, please refer to MemberHookCreator. You can handle exceptions that occur during the Hook method. The following example This method also works in the Resources Hook. The following example You can also handle exceptions that occur when the Hook's The following example You can also handle exceptions when looking up methods. The following example Tips For more functions, please refer to MemberHookCreator.Result, ResourcesHookCreator.Result. Common exceptions that may occur are described here. For more information, please refer to API Exception Handling. In some cases, you can manually throw exceptions to alert some functionality that there is a problem. As mentioned above, the exception thrown in the Here's how these exceptions work when The following example The above scenarios will only be processed in the (Xposed) Host App environment and will not have any impact on the host itself. If we want to throw these exceptions directly to the Host App, the native Xposed provides us with the If you want to throw an exception directly to the Host App in the Hook callback method body, you can implement the following methods. The following example You can also throw exceptions directly in the Hook callback method body, and then mark the exception to be thrown to the Host App. The following example The above two methods can receive an exception at the Host App and cause the Host App process to crash. Notice In order to ensure that the Hook calling domain and the calling domain within the Host App are isolated from each other, exceptions can only be thrown to the Host App in the beforeHook and afterHook callback method bodies. Tips For more functions, please refer to Throwable.throwToApp, YukiMemberHookCreator.MemberMookCreator.HookCallback. People who use In First we can monitor that the Hook is ready to start. The following example Pay Attention instanceClass is recommended to be used only in onPrepareHook, otherwise the Hook's Class does not exist and an uninterceptable exception will be thrown, causing the Hook process to "die". Then, we can also monitor the success of the method result of the Hook. The following example You can use the following methods to easily implement various judgments and functions in the Hook process. If your Module App needs to handle Hook events of multiple apps at the same time, you can use the The following example Tips For more functions, please refer to PackageParam.loadApp. If your Hook's Host App has multiple processes, you can use the The following example Tips For more functions, please refer to PackageParam.withProcess. To make the code more concise, you can omit the name of The following example Usually, we choose to write a method that return In Now, you can use The following example Due to some special reasons, Module Apps in TaiChi and Wuji cannot use standard methods to detect the activation state. At this point, you can use The following example If you want to use both judgment schemes, At this point, you can use The following example Tips For more functions, please refer to YukiHookAPI.Status. Notice If the activation state of TaiChi and Wuji is included in the Module App activation judgment, the Application of the Module App must be extends ModuleApplication or ModuleApplication must be used directly; The API after 1.0.91 has modified the activation logic judgment method, now you can use this API in the Module App and Host App at the same time; Need to make sure YukiHookAPI.Configs.isEnableHookModuleStatus is enabled; Except for Hook Frameworks that provide standard APIs, Module Apps may not be able to determine whether they are activated in other cases. This is a Hook API Framework, it does not provide any Hook function itself, it needs the support of basic Xposed API. This is an efficient Xposed Hook API rebuilt in The name is taken from "ももくり" heroine Yuki Kurihara. Formerly the Innocent Xposed API used in Development Learning Project, now renamed and open sourced. Abandoning the original less friendly Please use All demo code in this document will be described using Part of the Java Demo code can be found here, but not recommended. Previously, when we built an Xposed Module, we first needed to create an Then, manually fill in your own entry class name into the file and use Since Is there any easy to use, light, elegant solution? With this idea, Now, we only need to write a small amount of code, and all the time and expense are handed over to automation. With The following example Yes, you read that right, just needing these codes can completely replace the Xposed API to achieve the same function. Now, with the help of the efficient and powerful The following are the Here is a collection of Xposed-related introductions and the key points of knowledge that need to be grasped before start. Anyone who already knows can skip it. The basic knowledge content not necessarily completely accurate, please read it according to your own opinion. If you find any errors in this page, please correct it and help us improve. Here's an introduction to Xposed and how Hooks work. Xposed Framework (Xposed Framework) is a set of open source framework services that run in Android high-privilege mode. It can affect program operation (modify the system) without modifying the APK file. Based on it, many Powerful modules that operate simultaneously without conflicting functions. The above content is copied from Baidu Encyclopedia. The structure below describes the basic workings and principles of Xposed. We can achieve the ultimate goal of controlling its behavior by injecting the Host (App) when the Host (App) is running. This mode of operation of Xposed is called parasitism. The Xposed Module follows the lifecycle of the host and completes its own life course within the lifecycle of the Host. We can call the Host's methods, fields, and constructors through reflection, and use the Hook operation provided by Today's Xposed Manager has been completely replaced by its derivative works, and the era of SuperSU has ended, and now, with Magisk, everything behind is possible again. Its development history can be roughly divided into Xposed(Dalvik) → Xposed(ART) → Xposed(Magisk) → EdXposed(Riru)/LSPosed(Riru/ Zygisk) The structure below describes how and how the Xposed-like Hook Framework works. Through the operation principle of Xposed, many frameworks of the same type have been derived. As mobile devices in today's era are more and more difficult to obtain Root permissions or even flash, and when they are not just needed, some Root-free frameworks are also produced, such as Tai Chi. These Hook Frameworks at the ART level can also complete the Hook process with the same principle as Xposed without using the Xposed API. The operating principle of Root-free is to modify the APK and inject the Hook process into the Host, and control it through external modules. Another product is to use the existing functions of the Android operating environment to virtualize an environment that is completely the same as the current device system, and run App in it. This is the virtual App technology VirtualApp, which was later derived as VirtualXposed . The Root-free frameworks mentioned above are Tai Chi/Wuji, VirtualXposed/SandVXposed. Since Xposed appeared until now, apart from The birth of this API framework is to hope that in the current era of Xposed, more capable Xposed Module developers can avoid detours and complete the entire development process more easily and simply. In the future, Before starting, you need to have the following basics to better use Grasp and understand Android development and simple system operation principles To grasp and understand the internal structure of Android APK and simple decompilation knowledge, you can refer to Jadx and ApkTool Grasp and proficient in using Java reflection, understand simple Smali syntax, understand Dex file structure, and use reverse analysis to locate method locations Grasp the basic native Xposed API usage, understand the operation principle of Xposed Grasp Kotlin language and learn to use Kotlin lambda Grasp and understand Kotlin and Java mixing, calling each other, and Java bytecode generated by Kotlin If you are familiar with Xposed API, you can refer to the same point below to quickly migrate your API to Migrated from The API function differences are compared as follows Migrated from The API function differences are compared as follows The The API function differences are compared as follows Integrate Windows 7 and above / macOS 10.14 and above / Linux distributions (Arch/Debian) Android Studio 2021.1 and above IntelliJ IDEA 2021.1 and above Kotlin 1.7.0 and above Android Gradle Plugin 7.0 and above Gradle 7.0 and above JVM 11 and above (Since API You can click here to check it out. If you don't want to use automated build tools, you can still manually configure project dependencies as follows. Use Add dependencies to your project The following example Add The following example Add dependencies to your app The following example Please modify <ksp-version> to the latest version from here (Please choose your current corresponding Kotlin version). Please modify <yuki-version> to the latest version here. Pay Attention The api of YukiHookAPI and the versions that ksp-xposed depend on must correspond one by one, otherwise a version mismatch error will occur. Modify the JVM version of The following example Notice Since API 1.0.80 version, the default JVM version is 11, and 1.8 and below are no longer supported. Add the base code to your The following example Create a Hook entry class in your project, implements The following example Suggestion You can extends Application of your Module App from ModuleApplication to achieve a complete user experience. For more functions, please refer to ModuleApplication. Then, you can start writing Hook code. For configuration details related to use as an Xposed Module, you can click here to continue reading. If you are currently using Xposed API, you can refer to Migrate from Xposed API. Create your custom Pay Attention Regardless of the Hook Framework you use, you need to add its docking Xposed dependency support. If the target Hook Framework does not integrate Xposed API, you need to implement and connect XposedBridge by yourself. Add The following example Then, you can start writing Hook code in much the same way you would use it as an Xposed Module. For configuration details related to use as a Hook API, you can click here to continue reading. Notice YukiHookModuleStatus, YukiHookModulePrefs, YukiHookDataChannel and Resources Hook functionality will not work when using a custom Hook Framework instead of the full Xposed Module. This is an automatic building tool for Xposed Modules using Implementing automated search relies on quickly building an Android project template that includes a Xposed Module environment. This project is open source and free, and will be maintained continuously according to your usage. The original version may have imperfections or bugs. We welcome to your feedback. Project Address YukiHookAPI-ProjectBuilder。 If you want to download directly, you can click here to go to the Release address. Here contains the basic usage and function explanation. The software use process requires your device connected to the Internet. After starting the software, simply configure the project you want to create, click the button in the lower right corner or select Project > Run Build from the menu bar to start the task. After waiting for the automatic dependency search to complete, you can configure the project dependencies. It is recommended to use the latest dependencies to ensure the stability of the project, and the build tools only support the latest dependencies. Select the folder where you need to create the project. After starting, the project will be created in the location you selected, and wait for the whole process to complete and the project will be created. Config template is an extension function, you can select menu bar Project > Config Template > New Template. And then, you can create a template with the current config, and you can re-create it from Saved Template next time Load the template to restore the current config. The software language follows the current system, and you can manually select the software interface language in the Language column of the menu bar. 此文档由 VuePress 强力驱动。 版权所有 © 2019-2022 HighCapable 这里记录了 特别注意 我们只会对最新的 API 版本进行维护,若你正在使用过时的 API 版本则代表你自愿放弃一切维护的可能性。 如在使用中有任何问题,或有任何建设性的建议,都可以联系我们。 加入我们 点击加入 Telegram 群组 在 酷安 找到我 @星夜不荟 感谢您选择并使用 未来是美好的,也是不确定的,让我们共同期待 这里收录了 目前仅限完美支持 LSPosed,其它 Xposed 框架需要降级模块 API。 可能完全不支持太极,太极在高版本系统上需要更低的 API 才能适配。 部分 Xposed 模块开发者目前选择 Hook 目标 APP 内置 Sp 存储方案解决模块设置共享问题。 后期 Android 系统的权限将越来越严格, 这里收录了 待讨论 目前 API 只支持通过自动处理程序绑定到 xposed_init,若您不喜欢自动处理程序,一定要自己实现模块装载入口,未来会按照需求人数推出仅有 API 功能的 Lite 版本,你可向我们提出 issues。 API 已经提供了 Xposed 原生 API 监听接口,你可以 在这里 找到或查看 Demo 的实现方法。 作为 API 来讲,目前仅仅对接 大部分 这里的文档将同步最新 API 版本的相关用法,请保持 功能描述主要介绍当前 API 的相关用法和用途。 功能示例主要展示了当前 API 的基本用法示例,可供参考。 首个版本的功能将标记为 后期新增加的功能将标记为 后期修改的功能将被追加为 后期被作废的功能将标记为 后期被删除的功能将标记为 kt Kotlin Static File annotation 注解 interface 接口 object 类 (单例) class 类 field 变量或 method 方法 enum Enum 常量 ext-field 扩展的变量 (全局) ext-method 扩展的方法 (全局) i-ext-field 扩展的变量 (调用域限制) i-ext-method 扩展的方法 (调用域限制) 变更记录 功能描述 这是 变更记录 功能描述 获取当前 变更记录 功能描述 获取当前 变更记录 请转移到 变更记录 请转移到 变更记录 功能描述 当前 变更记录 功能描述 获取项目编译完成的时间戳 (当前本地时间)。 变更记录 功能描述 获取当前是否为 (Xposed) 宿主环境。 变更记录 功能描述 获取当前 Hook 框架的名称。 无法获取会返回 注意 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 变更记录 功能描述 获取当前 Hook 框架的版本。 无法获取会返回 注意 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 变更记录 功能描述 判断模块是否在 Xposed 或太极、无极中激活。 注意 在模块环境中你需要将 Application 继承于 ModuleApplication。 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 在 (Xposed) 宿主环境中仅返回非 isTaiChiModuleActive 的激活状态。 变更记录 功能描述 仅判断模块是否在 Xposed 中激活。 注意 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 在 (Xposed) 宿主环境中始终返回 true。 变更记录 功能描述 仅判断模块是否在太极、无极中激活。 注意 在模块环境中你需要将 Application 继承于 ModuleApplication。 在 (Xposed) 宿主环境中始终返回 false。 变更记录 功能描述 判断当前 Hook Framework 是否支持资源钩子(Resources Hook)。 注意 在模块环境中需要启用 Configs.isEnableHookModuleStatus。 在 (Xposed) 宿主环境中可能会延迟等待事件回调后才会返回 true。 请注意你需要确保 InjectYukiHookWithXposed.isUsingResourcesHook 已启用,否则始终返回 false。 变更记录 功能描述 对 API 相关功能的配置类。 变更记录 功能描述 配置 变更记录 请转移到 变更记录 功能描述 是否启用 DEBUG 模式。 默认为开启状态,开启后模块将会向 变更记录 请转移到 变更记录 功能描述 是否启用 为防止内存复用过高问题,此功能默认启用。 你可以手动在 变更记录 功能描述 是否启用当前 Xposed 模块自身 为防止内存复用过高问题,此功能默认启用。 你可以手动调用 注意 关闭后每次使用 PackageParam.moduleAppResources 都会重新创建,可能会造成运行缓慢。 变更记录 功能描述 是否启用 Hook Xposed 模块激活等状态功能. 为原生支持 Xposed 模块激活状态检测,此功能默认启用。 注意 关闭后你将不能再在模块环境中使用 YukiHookAPI.Status 中的激活状态判断功能。 变更记录 功能描述 是否启用 Hook 启用后将在模块启动时强制将 注意 这是一个可选的实验性功能,此功能默认不启用。 仅用于修复某些系统可能会出现在启用了 New XSharedPreferences 后依然出现文件权限错误问题,若你能正常使用 YukiHookModulePrefs 就不建议启用此功能。 变更记录 功能描述 是否启用当前 Xposed 模块与宿主交互的 请确保 Xposed 模块的 此功能默认启用,关闭后将不会在功能初始化的时候装载 变更记录 将方法体进行 inline 功能描述 是否启用 为防止 启用后会缓存已经找到的 缓存的 推荐使用 除非缓存的 变更记录 功能描述 对 你可以轻松的调用它进行配置。 功能示例 你可以在 示例如下 若觉得上面的写法不美观,你还可以写得更加简洁。 示例如下 你也可以不通过 示例如下 变更记录 功能描述 装载 Hook 入口的核心方法。 功能示例 详情请参考 变更记录 新增 新增 功能描述 标识 功能示例 详情请参考 InjectYukiHookWithXposed 注解。 变更记录 调整了构造方法的参数名称 功能描述 当前实例的类操作对象。 变更记录 功能描述 获得当前 变更记录 功能描述 获得当前 变更记录 功能描述 获得当前实例中的泛型父类。 如果当前实例不存在泛型将返回 变更记录 功能描述 获得当前实例中的泛型父类。 如果当前实例不存在泛型将返回 变更记录 功能描述 调用父类实例。 变更记录 功能描述 调用当前实例中的变量。 变更记录 功能描述 调用当前实例中的方法。 变更记录 新增 功能描述 当前类的父类实例的类操作对象。 变更记录 功能描述 获得当前 变更记录 功能描述 获得当前 变更记录 功能描述 获得当前实例父类中的泛型父类。 如果当前实例不存在泛型将返回 变更记录 功能描述 获得当前实例父类中的泛型父类。 如果当前实例不存在泛型将返回 变更记录 功能描述 调用父类实例中的变量。 变更记录 功能描述 调用父类实例中的方法。 变更记录 功能描述 当前 变更记录 功能描述 获得泛型参数数组下标的 变更记录 功能描述 创建一个当前 Hook 的 变更记录 功能描述 创建一个当前 Hook 的 变更记录 功能描述 这是一个不确定性 变更记录 功能描述 获取匹配的实体类。 使用当前 变更记录 功能描述 获取匹配的实体类。 使用当前 匹配不到 变更记录 对 修正拼写错误的 Creater 命名到 Creator 功能描述 变更记录 功能描述 默认 Hook 回调优先级。 变更记录 功能描述 延迟回调 Hook 方法结果。 变更记录 功能描述 更快回调 Hook 方法结果。 变更记录 功能描述 得到当前被 Hook 的 特别注意 不推荐直接使用,万一得不到 Class 对象则会无法处理异常导致崩溃。 变更记录 将方法体进行 inline 增加 功能描述 注入要 Hook 的 功能示例 你可以注入任意 示例如下 你还可以自定义 示例如下 你还可以自定义 示例如下 变更记录 功能描述 允许 Hook 过程中的所有危险行为。 请在 你还需要在整个调用域中声明注解 若你只需要 Hook 特别注意 若你不知道允许此功能会带来何种后果,请勿使用。 变更记录 增加 增加 移除 修正拼写错误的 Creater 命名到 Creator 功能描述 Hook 核心功能实现类,查找和处理需要 Hook 的 变更记录 请转移到 变更记录 功能描述 手动指定要 Hook 的 注意 不建议使用此方法设置目标需要 Hook 的 Member 对象,你可以使用 method 或 constructor 方法。 功能示例 你可以调用 示例如下 同样地,你也可以传入一组 示例如下 变更记录 请使用 变更记录 请使用 变更记录 功能描述 查找并 Hook 注意 无法准确处理每个 Member 的返回值和 param,建议使用 method or constructor 对每个 Member 单独 Hook。 变更记录 将方法体进行 inline 功能描述 查找当前 功能示例 你可参考 MethodFinder 查看详细用法。 示例如下 若想 Hook 当前查找 示例如下 此时 注意 若没有 all,默认只会 Hook 当前条件查找到的数组下标结果第一位。 变更记录 将方法体进行 inline 功能描述 查找当前 功能示例 你可参考 ConstructorFinder 查看详细用法。 示例如下 若想 Hook 当前查找 示例如下 此时 注意 若没有 all,默认只会 Hook 当前条件查找到的数组下标结果第一位。 变更记录 将方法体进行 inline 功能描述 使用当前 功能示例 你可参考 FieldFinder 查看详细用法。 示例如下 变更记录 将方法体进行 inline 功能描述 使用当前 变更记录 将方法体进行 inline 功能描述 使用当前 变更记录 功能描述 注入要 Hook 的 变更记录 新增 功能描述 在 变更记录 新增 功能描述 在 变更记录 功能描述 拦截并替换此 变更记录 功能描述 拦截并替换此 变更记录 功能描述 拦截并替 变更记录 功能描述 拦截并替换 特别注意 确保替换 Member 的返回对象为 Boolean。 变更记录 功能描述 拦截并替换 特别注意 确保替换 Member 的返回对象为 Boolean。 变更记录 功能描述 拦截此 这将会禁止此 特别注意 例如 Int、Long、Boolean 常量返回值的 Member 一旦被设置为 null 可能会造成 Hook APP 抛出异常。 变更记录 功能描述 移除当前注入的 Hook 特别注意 你只能在 Hook 回调方法中使用此功能。 变更记录 功能描述 Hook 方法体回调实现类。 变更记录 功能描述 当回调方法体内发生异常时将异常抛出给当前 Hook APP。 变更记录 功能描述 监听 Hook 结果实现类。 变更记录 将方法体进行 inline 功能描述 创建监听失败事件方法体。 功能示例 你可以使用此方法为 示例如下 变更记录 将方法体进行 inline 功能描述 添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。 变更记录 功能描述 监听 在首次 Hook 成功后回调。 在重复 Hook 时会回调 变更记录 功能描述 监听 注意 同一个 hookClass 中的同一个 members 不会被 API 重复 Hook,若由于各种原因重复 Hook 会回调此方法。 变更记录 功能描述 监听 变更记录 功能描述 监听 Hook 进行过程中发生错误的回调方法。 变更记录 功能描述 监听 Hook 开始时发生的错误的回调方法。 变更记录 功能描述 监听全部 Hook 过程发生错误的回调方法。 变更记录 功能描述 忽略 变更记录 功能描述 忽略 Hook 进行过程中发生的错误。 变更记录 功能描述 忽略 Hook 开始时发生的错误。 变更记录 功能描述 忽略全部 Hook 过程发生的错误。 变更记录 功能描述 移除当前注入的 Hook 注意 你只能在 Hook 成功后才能解除 Hook,可监听 onHooked 事件。 变更记录 功能描述 监听全部 Hook 结果实现类。 变更记录 将方法体进行 inline 功能描述 创建监听事件方法体。 变更记录 将方法体进行 inline 功能描述 添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。 变更记录 功能描述 监听 变更记录 功能描述 监听 变更记录 功能描述 忽略 变更记录 修正拼写错误的 Creater 命名到 Creator 功能描述 变更记录 功能描述 注入要 Hook 的 Resources。 功能示例 你可以注入任意 Resources,使用 示例如下 你还可以自定义 示例如下 变更记录 移除 修正拼写错误的 Creater 命名到 Creator 功能描述 Hook 核心功能实现类。 查找和处理需要 Hook 的 Resources。 变更记录 功能描述 直接设置需要替换的 Resources Id。 注意 不建议使用此方法设置目标需要 Hook 的 Resources Id,你可以使用 conditions 方法。 功能示例 你可以直接设置并指定目标 Hook APP 的 Resources Id。 示例如下 变更记录 功能描述 设置 Resources 查找条件。 若你设置了 功能示例 你可参考 ConditionFinder 查看详细用法。 示例如下 变更记录 功能描述 替换指定 Resources 为指定的值。 功能示例 你可以替换找到的 Resources 为你想要的值,可以是 比如我们要替换一个找到的字符串 Resources。 示例如下 或是替换为一个 示例如下 变更记录 功能描述 替换指定 Resources 为 特别注意 确保目标替换 Resources 的类型为 Boolean。 变更记录 功能描述 替换指定 Resources 为 特别注意 确保目标替换 Resources 的类型为 Boolean。 变更记录 功能描述 替换为当前 Xposed 模块的 Resources。 你可以直接使用模块的 功能示例 使用此方法可非常方便地使用当前模块的 Resources 去替换目标 Hook APP 的 Resources。 这个过程你无需对目标 Resources 实现 比如我们要替换一个字符串。 示例如下 还可以替换一些复杂的 Resources,比如 示例如下 变更记录 功能描述 作为装载的布局注入。 功能示例 你可以直接注入一个布局监听并修改它的内部 示例如下 你还可以通过 示例如下 变更记录 功能描述 Resources 查找条件实现类。 变更记录 功能描述 设置 Resources 名称。 变更记录 功能描述 设置 Resources 类型为动画。 变更记录 功能描述 设置 Resources 类型为属性动画。 变更记录 功能描述 设置 Resources 类型为布朗(Boolean)。 变更记录 功能描述 设置 Resources 类型为颜色(Color)。 变更记录 功能描述 设置 Resources 类型为尺寸(Dimention)。 变更记录 功能描述 设置 Resources 类型为 Drawable。 变更记录 功能描述 设置 Resources 类型为整型(Integer)。 变更记录 功能描述 设置 Resources 类型为布局(Layout)。 变更记录 功能描述 设置 Resources 类型为 Plurals。 变更记录 功能描述 设置 Resources 类型为字符串(String)。 变更记录 功能描述 设置 Resources 类型为 Xml。 变更记录 功能描述 设置 Resources 类型为位图(Mipmap)。 变更记录 功能描述 设置 Resources 类型为数组(Array)。 变更记录 功能描述 监听全部 Hook 结果实现类,可在这里处理失败事件监听。 变更记录 功能描述 创建监听事件方法体。 变更记录 功能描述 添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。 变更记录 功能描述 监听 Hook 过程发生错误的回调方法。 变更记录 功能描述 忽略 Hook 过程出现的错误。 变更记录 分离原始命名 功能描述 这是 变更记录 功能描述 字节码下标筛选实现类。 变更记录 功能描述 设置下标。 若 可使用 变更记录 功能描述 得到下标。 变更记录 功能描述 字节码下标排序实现类。 变更记录 功能描述 设置满足条件的第一个。 变更记录 功能描述 设置满足条件的最后一个。 变更记录 功能描述 设置倒序下标。 变更记录 功能描述 这是一个模糊 可对 R8 混淆后的 变更记录 功能描述 是否为 0。 变更记录 功能描述 大于 变更记录 功能描述 小于 变更记录 功能描述 在 变更记录 新增 作为 lambda 整体判断条件使用 移动到 base 包名 私有化构造方法 功能描述 这是一个 可对 R8 混淆后的 变更记录 统一合并到扩展方法并改名 功能描述 变更记录 统一合并到扩展方法并改名 功能描述 变更记录 统一合并到扩展方法并改名 功能描述 变更记录 统一合并到扩展方法并改名 功能描述 对于任意的静态 注意 Kotlin → Jvm 后的 object 类中的方法并不是静态的。 变更记录 统一合并到扩展方法并改名 功能描述 注意 Kotlin → Jvm 后没有 open 符号标识的 Class、Member 和没有任何关联的 Class、Member 都将为 final。 变更记录 统一合并到扩展方法并改名 功能描述 变更记录 统一合并到扩展方法并改名 功能描述 变更记录 统一合并到扩展方法并改名 功能描述 变更记录 统一合并到扩展方法并改名 功能描述 对于任意 JNI 对接的 变更记录 统一合并到扩展方法并改名 功能描述 变更记录 统一合并到扩展方法并改名 功能描述 对于任意的抽象 变更记录 统一合并到扩展方法并改名 功能描述 变更记录 作为 lambda 整体判断条件使用 移动到 base 包名 私有化构造方法 功能描述 这是一个模糊 可对 R8 混淆后的 变更记录 统一合并到扩展方法并改名 功能描述 是否为匿名类的主类调用对象。 变更记录 统一合并到扩展方法并改名 功能描述 是否只有符号。 变更记录 统一合并到扩展方法并改名 功能描述 是否只有字母。 变更记录 统一合并到扩展方法并改名 功能描述 是否只有数字。 变更记录 统一合并到扩展方法并改名 功能描述 是否只有字母或数字。 变更记录 统一合并到扩展方法并改名 功能描述 是否只有小写字母。 在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。 变更记录 统一合并到扩展方法并改名 功能描述 是否只有大写字母。 在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。 变更记录 功能描述 可使用 注意 此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。 变更记录 变更记录 功能描述 清除当前 适用于全部通过 ClassLoader.searchClass 或 PackageParam.searchClass 获取的 变更记录 功能描述 设置 只会查找匹配到的 例如 变更记录 功能描述 设置 只会查找匹配到的 例如 对于匿名类例如 变更记录 功能描述 设置 设置后将首先使用 例如 对于匿名类例如 变更记录 功能描述 设置在指定包名范围查找当前 设置后仅会在当前 例如 ↓ 注意 建议设置此参数指定查找范围,否则 Class 过多时将会非常慢。 变更记录 功能描述 设置 可不设置筛选条件。 变更记录 功能描述 设置 只会查找匹配到的 例如 变更记录 功能描述 设置 只会查找匹配到的 例如 对于匿名类例如 变更记录 功能描述 设置 设置后将首先使用 例如 对于匿名类例如 变更记录 功能描述 设置 只会查找匹配到的 变更记录 功能描述 设置 只会查找匹配到的 变更记录 功能描述 设置 设置后将首先使用 变更记录 功能描述 设置 变更记录 功能描述 设置 会同时查找 变更记录 功能描述 设置 变更记录 功能描述 设置 会同时查找 变更记录 功能描述 标识 例如 标识后你可以使用 enclosing 来进一步指定匿名类的 (封闭类) 主类。 变更记录 功能描述 设置 此时 注意 设置此条件后 extends 将失效。 变更记录 功能描述 设置 注意 设置此条件后 implements 将失效。 变更记录 功能描述 设置 此时 注意 设置此条件后 extends 与 implements 将失效。 变更记录 功能描述 设置 变更记录 功能描述 设置 会同时查找 变更记录 功能描述 包名范围名称过滤匹配条件实现类。 变更记录 功能描述 设置包名绝对匹配。 例如有如下包名 ↓ 若包名条件为 相反地,不设置以上示例会全部匹配。 变更记录 功能描述 类名匹配条件实现类。 变更记录 功能描述 设置类名可选。 例如有如下类名 ↓ 这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。 此时可设置类名为 这样就可在完全匹配类名情况下使用类名而忽略其它查找条件,否则忽略此条件继续使用其它查找条件。 变更记录 功能描述 设置 变更记录 功能描述 设置 变更记录 功能描述 设置 变更记录 功能描述 设置 变更记录 功能描述 变更记录 功能描述 创建监听结果事件方法体。 变更记录 功能描述 得到 若有多个 在查找条件找不到任何结果的时候将返回 若你设置了 变更记录 功能描述 得到 返回全部查找条件匹配的多个 在查找条件找不到任何结果的时候将返回空的 若你设置了 变更记录 功能描述 得到 回调全部查找条件匹配的多个 在查找条件找不到任何结果的时候将不会执行。 若你设置了 变更记录 功能描述 得到 若有多个 在查找条件找不到任何结果的时候将回调 null。 你需要设置 变更记录 功能描述 得到 回调全部查找条件匹配的多个 在查找条件找不到任何结果的时候将回调空的 你需要设置 变更记录 功能描述 监听找不到 变更记录 功能描述 忽略异常并停止打印任何错误日志。 此时若要监听异常结果,你需要手动实现 onNoClassDefFoundError 方法。 变更记录 功能描述 变更记录 功能描述 设置 你可以不使用 若参数个数小于零则忽略并使用 变更记录 功能描述 设置 可不设置筛选条件。 变更记录 功能描述 设置 变更记录 功能描述 设置 如果同时使用了 如果 特别注意 无参 Constructor 请使用 emptyParam 设置查找条件。 有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。 变更记录 功能描述 设置 你可以不使用 变更记录 功能描述 设置 你可以不使用 变更记录 功能描述 变更记录 功能描述 设置 变更记录 功能描述 设置 可不填写类型。 变更记录 功能描述 设置 可不设置筛选条件。 变更记录 功能描述 设置 变更记录 功能描述 变更记录 功能描述 设置 可不设置筛选条件。 变更记录 功能描述 变更记录 功能描述 设置 变更记录 功能描述 设置 你可以不使用 若参数个数小于零则忽略并使用 变更记录 功能描述 设置 可不填写返回值。 变更记录 功能描述 设置 可不设置筛选条件。 变更记录 功能描述 设置 变更记录 功能描述 设置 如果同时使用了 如果 特别注意 无参 Method 请使用 emptyParam 设置查找条件。 有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。 变更记录 功能描述 设置 变更记录 功能描述 设置 你可以不使用 变更记录 功能描述 设置 你可以不使用 变更记录 功能描述 当前 变更记录 功能描述 设置当前 变更记录 功能描述 设置当前 变更记录 功能描述 设置当前 变更记录 功能描述 设置当前 变更记录 合并到 合并到 功能描述 可通过指定类型查找指定 变更记录 功能描述 设置 你可以不使用 若参数个数小于零则忽略并使用 变更记录 将方法体进行 inline 合并到 功能描述 设置 可不设置筛选条件,默认模糊查找并取第一个匹配的 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 变更记录 功能描述 设置 如果同时使用了 如果 特别注意 无参 Constructor 请使用 emptyParam 设置查找条件。 有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 你可以不使用 若参数个数小于零则忽略并使用 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 你可以不使用 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 你可以不使用 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置在 注意 若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。 变更记录 功能描述 变更记录 将方法体进行 inline 功能描述 创建需要重新查找的 你可以添加多个备选 变更记录 功能描述 变更记录 功能描述 当在 功能示例 你可以方便地对重查找的 示例如下 变更记录 功能描述 变更记录 功能描述 创建监听结果事件方法体。 功能示例 你可以使用 示例如下 变更记录 功能描述 设置全部查找条件匹配的多个 变更记录 功能描述 创建 功能示例 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 示例如下 变更记录 功能描述 监听找不到 只会返回第一次的错误信息,不会返回 变更记录 继承到接口 功能描述 变更记录 将方法体进行 inline 功能描述 创建监听结果事件方法体。 功能示例 你可以使用 示例如下 变更记录 功能描述 获得 若有多个 特别注意 若你设置了 remedys 请使用 wait 回调结果方法。 功能示例 你可以通过获得方法所在实例来执行构造方法创建新的实例对象。 示例如下 你可以 示例如下 特别注意 若构造方法含有参数则后方参数必填。 示例如下 变更记录 功能描述 获得 返回全部查找条件匹配的多个 功能示例 你可以通过此方法来获得当前条件结果中匹配的全部 示例如下 变更记录 功能描述 得到 若有多个 在查找条件找不到任何结果的时候将返回 变更记录 功能描述 得到 返回全部查找条件匹配的多个 在查找条件找不到任何结果的时候将返回空的 变更记录 功能描述 获得 若有多个 特别注意 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 变更记录 功能描述 获得 返回全部查找条件匹配的多个 特别注意 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 变更记录 将方法体进行 inline 功能描述 创建 功能示例 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 示例如下 变更记录 将方法体进行 inline 功能描述 监听找不到 只会返回第一次的错误信息,不会返回 变更记录 功能描述 忽略异常并停止打印任何错误日志。 若 注意 此时若要监听异常结果,你需要手动实现 onNoSuchConstructor 方法。 变更记录 请转移到新方法 变更记录 新增 功能描述 变更记录 功能描述 执行 变更记录 功能描述 执行 变更记录 合并到 合并到 功能描述 可通过指定类型查找指定 变更记录 变更记录 允许不填写名称 功能描述 设置 特别注意 若不填写名称则必须存在一个其它条件。 变更记录 功能描述 设置 可不填写类型。 变更记录 将方法体进行 inline 合并到 功能描述 设置 可不设置筛选条件。 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 顺序筛选字节码的下标。 变更记录 功能描述 设置 特别注意 若不填写名称则必须存在一个其它条件。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 合并到 功能描述 设置 特别注意 若不填写名称则必须存在一个其它条件。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 特别注意 可不填写类型。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置在 注意 若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。 变更记录 功能描述 变更记录 功能描述 创建需要重新查找的 你可以添加多个备选 变更记录 功能描述 变更记录 功能描述 当在 功能示例 你可以方便地对重查找的 示例如下 变更记录 继承到接口 功能描述 变更记录 将方法体进行 inline 功能描述 创建监听结果事件方法体。 功能示例 你可以使用 示例如下 变更记录 功能描述 获得 若有多个 功能示例 你可以轻松地得到 示例如下 如果你取到的是静态 示例如下 变更记录 功能描述 获得 返回全部查找条件匹配的多个 功能示例 你可以通过此方法来获得当前条件结果中匹配的全部 示例如下 变更记录 功能描述 得到 若有多个 Field 结果只会返回第一个。 在查找条件找不到任何结果的时候将返回 变更记录 功能描述 得到 返回全部查找条件匹配的多个 在查找条件找不到任何结果的时候将返回空的 变更记录 功能描述 获得 若有多个 特别注意 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 变更记录 功能描述 获得 返回全部查找条件匹配的多个 特别注意 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 变更记录 功能描述 创建 功能示例 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 示例如下 变更记录 功能描述 监听找不到 变更记录 功能描述 忽略异常并停止打印任何错误日志。 若 注意 此时若要监听异常结果,你需要手动实现 onNoSuchField 方法。 变更记录 请转移到新方法 变更记录 新增 不再对外公开 功能描述 变更记录 请直接使用 变更记录 功能描述 获得当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 功能描述 得到当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 功能描述 得到当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 修改 移动方法到 功能描述 得到当前 变更记录 功能描述 得到当前 变更记录 功能描述 得到当前 变更记录 功能描述 设置当前 变更记录 功能描述 设置当前 特别注意 请确保实例对象类型为 Boolean。 变更记录 功能描述 设置当前 特别注意 请确保实例对象类型为 Boolean。 变更记录 功能描述 设置当前 变更记录 合并到 合并到 功能描述 可通过指定类型查找指定 变更记录 允许不填写名称 功能描述 设置 特别注意 若不填写名称则必须存在一个其它条件。 变更记录 功能描述 设置 你可以不使用 若参数个数小于零则忽略并使用 变更记录 功能描述 设置 变更记录 将方法体进行 inline 合并到 功能描述 设置 可不设置筛选条件。 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 变更记录 功能描述 设置 如果同时使用了 如果 特别注意 无参 Method 请使用 emptyParam 设置查找条件。 有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 顺序筛选字节码的下标。 变更记录 功能描述 设置 特别注意 若不填写名称则必须存在一个其它条件。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 合并到 功能描述 设置 特别注意 若不填写名称则必须存在一个其它条件。 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 你可以不使用 若参数个数小于零则忽略并使用 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 你可以不使用 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 你可以不使用 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置 可不填写返回值。 特别注意 存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。 变更记录 功能描述 设置在 注意 若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。 变更记录 功能描述 变更记录 将方法体进行 inline 功能描述 创建需要重新查找的 你可以添加多个备选 变更记录 功能描述 变更记录 功能描述 当在 功能示例 你可以方便地对重查找的 示例如下 变更记录 功能描述 变更记录 功能描述 创建监听结果事件方法体。 功能示例 你可以使用 示例如下 变更记录 功能描述 设置全部查找条件匹配的多个 变更记录 功能描述 创建 功能示例 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 示例如下 变更记录 功能描述 监听找不到 只会返回第一次的错误信息,不会返回 变更记录 继承到接口 功能描述 变更记录 将方法体进行 inline 功能描述 创建监听结果事件方法体。 功能示例 你可以使用 示例如下 变更记录 功能描述 获得 若有多个 特别注意 若你设置了 remedys 请使用 wait 回调结果方法。 功能示例 你可以通过获得方法所在实例来执行 示例如下 若当前为静态方法,你可以不设置实例。 示例如下 变更记录 功能描述 获得 返回全部查找条件匹配的多个 功能示例 你可以通过此方法来获得当前条件结果中匹配的全部 示例如下 变更记录 功能描述 得到 若有多个 在查找条件找不到任何结果的时候将返回 变更记录 功能描述 得到 返回全部查找条件匹配的多个 在查找条件找不到任何结果的时候将返回空的 变更记录 功能描述 获得 若有多个 特别注意 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 变更记录 功能描述 获得 返回全部查找条件匹配的多个 特别注意 若你设置了 remedys 必须使用此方法才能获得结果。 若你没有设置 remedys 此方法将不会被回调。 变更记录 将方法体进行 inline 功能描述 创建 功能示例 当你遇到一种 若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。 示例如下 变更记录 将方法体进行 inline 功能描述 监听找不到 只会返回第一次的错误信息,不会返回 变更记录 功能描述 忽略异常并停止打印任何错误日志。 若 注意 此时若要监听异常结果,你需要手动实现 onNoSuchMethod 方法。 变更记录 请转移到新方法 变更记录 新增 功能描述 变更记录 功能描述 标识需要调用当前 若当前 特别注意 你只能在 (Xposed) 宿主环境中使用此功能。 变更记录 功能描述 执行 变更记录 功能描述 执行 变更记录 功能描述 执行 变更记录 修改 功能描述 执行 变更记录 修改 功能描述 执行 变更记录 修改 功能描述 执行 变更记录 修改 功能描述 执行 变更记录 修改 功能描述 执行 变更记录 修改 功能描述 执行 变更记录 功能描述 执行 变更记录 修改 功能描述 执行 变更记录 功能描述 执行 变更记录 功能描述 执行 变更记录 功能描述 变更记录 功能描述 子类 Hook 开始。 变更记录 功能描述 这是自定义 变更记录 功能描述 定义一个 变更记录 功能描述 全部 变更记录 功能描述 全部 变更记录 功能描述 全部 变更记录 功能描述 通过当前 特别注意 此方法在 Class 数量过多及查找条件复杂时会非常耗时。 建议启用 async 或设置 name 参数,name 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。 此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。 变更记录 功能描述 监听当前 特别注意 只有当前 ClassLoader 有主动使用 ClassLoader.loadClass 事件时才能被捕获。 这是一个实验性功能,一般情况下不会用到此方法,不保证不会发生错误。 只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。 功能示例 针对一些使用特定 注意 为了防止发生问题,你需要得到一个存在的 ClassLoader 实例来使用此功能。 比如我们在 示例如下 或使用你得到的存在的 示例如下 在判断到这个 示例如下 变更记录 变更记录 变更记录 请直接使用 变更记录 功能描述 当前 变更记录 请转到 变更记录 功能描述 通过字符串类名转换为 功能示例 你可以直接填写你要查找的目标 示例如下 你还可以自定义 示例如下 变更记录 功能描述 通过字符串类名转换为 找不到 功能示例 用法请参考 String.toClass 方法。 变更记录 功能描述 通过 功能示例 我们要获取一个 示例如下 现在,你可以直接 示例如下 若目标存在的 示例如下 变更记录 支持直接使用空参数方法使用默认 功能描述 通过字符串类名使用指定的 功能示例 你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 示例如下 填入方法中的 示例如下 变更记录 合并到 将方法体进行 inline 功能描述 查找变量是否存在。 变更记录 新增 合并到 将方法体进行 inline 功能描述 查找方法是否存在。 变更记录 合并到 将方法体进行 inline 功能描述 查找构造方法是否存在。 变更记录 将方法体进行 inline 合并到 功能描述 查找 变更记录 功能描述 查找 变更记录 变更记录 变更记录 变更记录 变更记录 将方法体进行 inline 功能描述 查找并得到变量。 变更记录 新增 合并到 将方法体进行 inline 功能描述 查找并得到方法。 变更记录 合并到 将方法体进行 inline 功能描述 查找并得到构造方法。 变更记录 变更记录 变更记录 功能描述 获得当前 如果当前实例不存在泛型将返回 变更记录 功能描述 获得当前 如果当前实例不存在泛型将返回 变更记录 新增 新增不使用 功能描述 获得当前实例的类操作对象。 变更记录 将方法体进行 inline 请转移到 变更记录 将方法体进行 inline 加入无泛型方法 功能描述 通过构造方法创建新实例,指定类型 变更记录 将方法体进行 inline 功能描述 遍历当前类中的所有方法。 变更记录 将方法体进行 inline 功能描述 遍历当前类中的所有构造方法。 变更记录 将方法体进行 inline 功能描述 遍历当前类中的所有变量。 变更记录 合并到 功能描述 这是 变更记录 合并到 功能描述 在 变更记录 合并到 功能描述 在 变更记录 功能描述 获取模块的存取对象。 变更记录 功能描述 获取模块的存取对象,可设置 变更记录 功能描述 获取模块的数据通讯桥命名空间对象。 特别注意 只能在模块环境使用此功能,其它环境下使用将不起作用。 变更记录 功能描述 获取当前进程名称。 变更记录 功能描述 向 Hook APP (宿主) 注入成功后,你就可以直接使用例如 注入的资源作用域仅限当前 特别注意 只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。 变更记录 功能描述 向 Hook APP (宿主) 注册当前 Xposed 模块的 注册成功后,你就可以直接使用 使用此方法会在未注册的 你要将需要在宿主启动的 特别注意 只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。 变更记录 功能描述 生成一个 在 Hook APP (宿主) 中使用此方法会自动调用 如果在 Hook APP (宿主) 中使用此方法发生 变更记录 请转移到 变更记录 请转移到 变更记录 请转移到 变更记录 请转移到 变更记录 请转移到 变更记录 功能描述 这是 变更记录 功能描述 需要打印的日志类型。 决定于模块与 (Xposed) 宿主环境使用的打印方式。 变更记录 功能描述 仅使用 变更记录 功能描述 仅使用 特别注意 只能在 (Xposed) 宿主环境中使用,模块环境将不生效。 变更记录 功能描述 分区使用。 (Xposed) 宿主环境仅使用 模块环境仅使用 变更记录 功能描述 同时使用。 (Xposed) 宿主环境使用 模块环境仅使用 变更记录 功能描述 调试日志实现类。 变更记录 功能描述 获取当前日志文件内容。 如果当前没有已记录的日志会返回空字符串。 变更记录 功能描述 清除全部已记录的日志。 变更记录 功能描述 保存当前日志到文件。 若当前未开启 日志文件会追加到 特别注意 文件读写权限取决于当前宿主已获取的权限。 变更记录 功能描述 配置 变更记录 功能描述 标签。 变更记录 功能描述 优先级。 变更记录 功能描述 当前宿主的包名。 变更记录 功能描述 当前宿主的用户 ID (主用户不显示)。 变更记录 功能描述 是否启用调试日志的输出功能。 关闭后将会停用 但是不影响当你手动调用下面这些方法输出日志。 当 变更记录 功能描述 是否启用调试日志的记录功能。 开启后将会在内存中记录全部可用的日志和异常堆栈。 需要同时启用 isEnable 才能有效。 特别注意 过量的日志可能会导致宿主运行缓慢或造成频繁 GC。 开启后你可以调用 YukiHookLogger.saveToFile 实时保存日志到文件或使用 YukiHookLogger.contents 获取实时日志文件。 变更记录 功能描述 这是一个调试日志的全局标识。 默认文案为 你可以修改为你自己的文案。 变更记录 功能描述 自定义调试日志对外显示的元素。 只对日志记录和 日志元素的排列将按照你在 你还可以留空 可用的元素有: 功能示例 打印的日志样式将按照你设置的排列顺序和元素内容进行。 示例如下 以上内容定义的日志将显示为如下样式。 示例如下 如果我们调整元素顺序以及减少个数,那么结果又会不一样。 示例如下 以上内容定义的日志将显示为如下样式。 示例如下 变更记录 新增 功能描述 向 变更记录 新增 功能描述 向 变更记录 新增 功能描述 向 变更记录 新增 功能描述 向 变更记录 移动 修正拼写错误的 creater 命名到 creator 功能描述 Hook 方法、构造方法的目标对象实现类。 变更记录 在 功能描述 获取当前 Hook 对象 这里的数组每项类型默认为 变更记录 请使用 变更记录 请使用 变更记录 功能描述 获取当前 Hook 实例的对象。 特别注意 如果你当前 Hook 的对象是一个静态,那么它将不存在实例的对象。 变更记录 功能描述 获取当前 Hook 实例的类对象。 变更记录 功能描述 获取当前 Hook 对象的 在不确定 变更记录 功能描述 获取当前 Hook 对象的方法。 变更记录 功能描述 获取当前 Hook 对象的构造方法。 变更记录 功能描述 获取、设置当前 Hook 对象的 变更记录 功能描述 判断是否存在设置过的方法调用抛出异常。 变更记录 功能描述 获取设置的方法调用抛出异常。 变更记录 功能描述 向 Hook APP 抛出异常。 使用 使用 仅会在回调方法的 特别注意 设置后会同时执行 resultNull 方法并将异常抛出给当前 Hook APP。 功能示例 Hook 过程中的异常仅会作用于 (Xposed) 宿主环境,目标 Hook APP 不会受到影响。 若想将异常抛给 Hook APP,可以直接使用如下方法。 示例如下 特别注意 向 Hook APP 抛出异常会对其暴露被 Hook 的事实,是不安全的,容易被检测,请按实际场景合理使用。 变更记录 功能描述 获取当前 Hook 对象的 变更记录 变更记录 变更记录 功能描述 获取当前 Hook 实例的对象 功能示例 你可以通过 示例如下 变更记录 功能描述 获取当前 Hook 对象的 变更记录 默认值 功能描述 获取当前 Hook 对象的 功能示例 你可以通过 你可以直接使用 特别注意 请确保 param 类型为你的目标实例类型。 示例如下 你可以这样直接设置第一位 示例如下 你还可以直接设置最后一位 示例如下 你还可以使用 示例如下 你还可以使用 特别注意 请确保 param 类型为 Boolean。 示例如下 你还可以使用 特别注意 请确保 param 类型为 Boolean。 示例如下 变更记录 功能描述 执行原始 调用自身未进行 Hook 的原始 功能实例 此方法可以 调用自身原始的方法不会再经过当前 比如我们 Hook 的这个方法被这样调用 示例如下 变更记录 不再需要使用 功能描述 执行原始 调用自身未进行 Hook 的原始 功能实例 此方法可以 调用自身原始的方法不会再经过当前 比如我们 Hook 的这个方法被这样调用 示例如下 变更记录 功能描述 设置当前 Hook 对象方法的 特别注意 请确保 result 类型为 Boolean。 变更记录 功能描述 设置当前 Hook 对象方法的 特别注意 请确保 result 类型为 Boolean。 变更记录 功能描述 注意 此方法将强制设置 Hook 对象方法的 result 为 null。 变更记录 功能描述 对方法参数的数组下标进行实例化类。 变更记录 功能描述 获取当前 Hook 对象的 变更记录 功能描述 获取当前 Hook 对象的 变更记录 功能描述 对方法参数的修改进行实例化类。 变更记录 修改 功能描述 得到方法参数的实例对象 变更记录 功能描述 得到方法参数的实例对象 Byte。 变更记录 修改 功能描述 得到方法参数的实例对象 Int。 变更记录 修改 功能描述 得到方法参数的实例对象 Long。 变更记录 修改 功能描述 得到方法参数的实例对象 Short。 变更记录 修改 功能描述 得到方法参数的实例对象 Double。 变更记录 修改 功能描述 得到方法参数的实例对象 Float。 变更记录 修改 功能描述 得到方法参数的实例对象 String。 变更记录 功能描述 得到方法参数的实例对象 Char。 变更记录 修改 功能描述 得到方法参数的实例对象 Boolean。 变更记录 功能描述 得到方法参数的实例对象 Any。 变更记录 功能描述 得到方法参数的实例对象 Array。 变更记录 功能描述 得到方法参数的实例对象 List。 变更记录 功能描述 设置方法参数的实例对象。 变更记录 功能描述 设置方法参数的实例对象为 变更记录 功能描述 设置方法参数的实例对象为 特别注意 请确保目标对象的类型是 Boolean。 变更记录 功能描述 设置方法参数的实例对象为 特别注意 请确保目标对象的类型是 Boolean。 变更记录 功能描述 装载 Hook 的目标 APP 入口对象实现类。 变更记录 功能描述 获取当前 Hook APP 的 变更记录 功能描述 获取当前 Hook APP 的 变更记录 功能描述 获取当前 Hook APP 的用户 ID。 机主为 变更记录 加入可空类型 (空安全) 功能描述 获取当前 Hook APP 的 特别注意 首次装载可能是空的,请延迟一段时间再获取或使用 onAppLifecycle 监听来完成。 变更记录 加入可空类型 (空安全) 功能描述 获取当前 Hook APP 的 Resources。 特别注意 你只能在 HookResources.hook 方法体内或 appContext 装载完毕时进行调用。 变更记录 功能描述 获取当前系统框架的 变更记录 功能描述 获取当前 Hook APP 的进程名称。 变更记录 功能描述 获取当前 Hook APP 的包名。 变更记录 功能描述 获取当前 Hook APP 是否为第一个 变更记录 功能描述 获取当前 Hook APP 的主进程名称。 其对应的就是 变更记录 功能描述 获取当前 Xposed 模块自身 APK 文件路径。 特别注意 作为 Hook API 装载时无法使用,会获取到空字符串。 变更记录 功能描述 获取当前 Xposed 模块自身 特别注意 作为 Hook API 或不支持的 Hook Framework 装载时无法使用,会抛出异常。 变更记录 功能描述 获得当前使用的存取数据对象缓存实例。 特别注意 作为 Hook API 装载时无法使用,会抛出异常。 变更记录 将方法体进行 inline 功能描述 获得当前使用的存取数据对象缓存实例。 你可以通过 特别注意 作为 Hook API 装载时无法使用,会抛出异常。 变更记录 功能描述 获得当前使用的数据通讯桥命名空间对象。 特别注意 作为 Hook API 装载时无法使用,会抛出异常。 变更记录 功能描述 获得当前 Hook APP 的 请调用 变更记录 功能描述 刷新当前 Xposed 模块自身 变更记录 功能描述 监听当前 Hook APP 生命周期装载事件。 注意 在 loadZygote 中不会被装载,仅会在 loadSystem、loadApp 中装载。 作为 Hook API 装载时请使用原生的 Application 实现生命周期监听。 变更记录 将方法体进行 inline 功能描述 装载并 Hook 指定包名的 APP。 装载并 Hook 指定、全部包名的 APP。 若要装载 APP Zygote 事件,请使用 若要 Hook 系统框架,请使用 功能示例 你可以使用 示例如下 若不指定 示例如下 变更记录 功能描述 装载 APP Zygote 事件。 方法中的两个参数一个可作为 变更记录 功能描述 装载并 Hook 系统框架。 方法中的两个参数一个可作为 变更记录 功能描述 装载并 Hook APP 的指定进程。 变更记录 功能描述 装载 Hook 子类。 你可以填入 变更记录 功能描述 通过 特别注意 此方法在 Class 数量过多及查找条件复杂时会非常耗时。 建议启用 async 或设置 name 参数,name 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。 此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。 变更记录 请转移到 变更记录 请转移到 变更记录 功能描述 通过字符串类名、 默认使用当前 功能示例 你可以轻松地将 示例如下 你还可以向 示例如下 你还可以创建一个 示例如下 同样地,你还可以向 示例如下 变更记录 功能描述 通过字符串类名、 默认使用当前 找不到 功能示例 用法请参考 String+VariousClass.toClass 方法。 变更记录 功能描述 通过字符串类名查找是否存在。 默认使用当前 功能示例 你可以轻松的使用此方法判断字符串中的类是否存在。 示例如下 你还可以自定义其中的 示例如下 变更记录 移除了 新增 功能描述 通过完整包名+名称查找需要被 Hook 的 注意 使用此方法会得到一个 HookClass 仅用于 Hook,若想查找 Class 请使用 toClass 功能。 功能示例 你可以使用三种方式查找你需要 Hook 的目标 你可以直接将被查找的 示例如下 若你不确定多个版本的 示例如下 你还可以创建一个 示例如下 若你当前需要查找的 示例如下 同样地,在不确定多个版本的 示例如下 变更记录 新增 新增 新增 新增 将方法体进行 inline 移除了 添加了 功能描述 这是一切 Hook 的入口创建方法,Hook 方法、构造方法。 功能示例 如你所见,Hook 方法体的创建可使用 4 种方式。 通过字符串类名得到 示例如下 通过 示例如下 使用 默认情况下 API 会将 示例如下 若当前 示例如下 使用 示例如下 或者直接使用可变字符串数组进行创建。 示例如下 变更记录 功能描述 Hook APP 的 Resources。 特别注意 请注意你需要确保当前 Hook Framework 支持且 InjectYukiHookWithXposed.isUsingResourcesHook 已启用。 功能示例 Resources Hook 为固定用法,获取 示例如下 特别注意 这是固定用法,为了防止发生问题,你不可手动实现任何 HookResources 实例执行 hook 调用。 将 Resources 的 Hook 设置为这样是为了与 变更记录 功能描述 当前 Hook APP 的生命周期实例处理类。 变更记录 功能描述 监听当前 Hook APP 装载 变更记录 功能描述 监听当前 Hook APP 装载 变更记录 功能描述 监听当前 Hook APP 装载 变更记录 功能描述 监听当前 Hook APP 装载 变更记录 功能描述 监听当前 Hook APP 装载 变更记录 功能描述 监听当前 Hook APP 装载 变更记录 功能描述 注册系统广播监听。 变更记录 功能描述 这是一个预置 Hook 类型的常量类,主要为 详情可 点击这里 进行查看。 变更记录 功能描述 这是一个预置 Hook 类型的常量类,主要为 详情可 点击这里 进行查看。 变更记录 功能描述 这是一个预置 Hook 类型的常量类,主要为 详情可 点击这里 进行查看。 变更记录 功能描述 这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。 变更记录 功能描述 得到模糊类型。 变更记录 功能描述 这是一个预置 Hook 类型的常量类,主要为 详情可 点击这里 进行查看。 变更记录 功能描述 这是对使用 在你的 Xposed 模块的 或在 目前可实现功能如下 全局共享模块中静态的 在模块与宿主中装载 在模块与宿主中使用 在模块中使用系统隐藏 API,核心技术引用了开源项目 FreeReflection 在模块中使用 功能示例 将此类继承到你的自定义 示例如下 在 示例如下 如果你不需要自定义 示例如下 变更记录 功能描述 获取全局静态 变更记录 功能描述 对接 变更记录 功能描述 对接 创建 变更记录 功能描述 对接 变更记录 不再对外公开 变更记录 功能描述 获得当前 APP 的 Resources Id。 变更记录 功能描述 获得当前 APP 的 Resources。 变更记录 功能描述 对接 变更记录 功能描述 装载 Hook APP 的目标布局 Resources 实现类。 变更记录 功能描述 获取当前被 Hook 的布局装载目录名称。 例如: 变更记录 功能描述 获取当前被 Hook 的布局实例。 变更记录 功能描述 使用 Identifier 查找 Hook APP 指定 Id 的 扩展方法可以使用 Identifier 查找 Hook APP 当前装载布局中指定 Id 的 变更记录 功能描述 实现对原生 Xposed API 的装载事件监听。 变更记录 功能描述 对 变更记录 功能描述 设置 initZygote 事件监听。 变更记录 功能描述 设置 handleLoadPackage 事件监听。 变更记录 功能描述 设置 handleInitPackageResources 事件监听。 变更记录 功能描述 实现 Xposed 模块的数据通讯桥。 通过模块与宿主相互注册 模块需要将 特别注意 模块与宿主需要保持存活状态,否则无法建立通讯。 变更记录 新增 功能描述 变更记录 功能描述 创建一个调用空间。 变更记录 功能描述 发送键值数据。 变更记录 功能描述 仅发送键值监听,使用默认值 变更记录 移除默认值 功能描述 获取键值数据。 变更记录 功能描述 仅获取监听结果,不获取键值数据。 特别注意 仅限使用 VALUE_WAIT_FOR_LISTENER 发送的监听才能被接收。 变更记录 功能描述 获取模块与宿主的版本是否匹配。 通过此方法可原生判断 Xposed 模块更新后宿主并未重新装载造成两者不匹配的情况。 变更记录 功能描述 数据通讯桥键值构造类。 这个类是对 功能示例 建立一个模板类定义模块与宿主需要发送的键值数据。 示例如下 键值数据定义后,你就可以方便地在模块和宿主中调用所需要发送的数据。 模块示例如下 宿主示例如下 你依然可以不使用模板定义的默认值,随时修改你的默认值。 示例如下 变更记录 功能描述 代理 继承于此类的 在 (Xposed) 宿主环境需要在宿主启动时调用 变更记录 功能描述 代理 继承于此类的 在 (Xposed) 宿主环境需要在宿主启动时调用 在 (Xposed) 宿主环境需要重写 变更记录 功能描述 设置当前代理的 变更记录 功能描述 代理 通过包装,你可以轻松在 (Xposed) 宿主环境使用来自模块的主题资源。 变更记录 功能描述 设置当前 设置后会自动调用 变更记录 功能描述 实现 Xposed 模块的数据存取,对接 在不同环境智能选择存取使用的对象。 特别注意 此功能为实验性功能,仅在 LSPosed 环境测试通过,EdXposed 理论也可以使用但不再推荐。 使用 LSPosed 环境请在 若你在按照规定配置后依然无法使用或出现文件权限错误问题,可以参考 isEnableHookSharedPreferences。 未使用 LSPosed 环境请将你的模块 太极请参阅 文件权限/配置/XSharedPreference。 特别注意 当你在 Xposed 模块中存取数据的时候 context 必须不能是空的。 若你正在使用 可选配置 若你不想将你的模块的 示例如下 变更记录 功能描述 获取 特别注意 只能在 (Xposed) 宿主环境中使用,模块环境中始终返回 false。 变更记录 功能描述 获取 前提条件为当前 Xposed 模块已被激活。 特别注意 只能在模块环境中使用,(Xposed) 宿主环境中始终返回 false。 变更记录 功能描述 自定义 Sp 存储名称。 功能示例 在 示例如下 在 (Xposed) 宿主环境 示例如下 变更记录 功能描述 忽略缓存直接读取键值。 无论是否开启 仅在 变更记录 功能描述 获取 变更记录 功能描述 获取 变更记录 功能描述 获取 变更记录 功能描述 获取 变更记录 功能描述 获取 变更记录 功能描述 获取 变更记录 功能描述 获取全部存储的键值数据。 智能识别对应环境读取键值数据。 特别注意 每次调用都会获取实时的数据,不受缓存控制,请勿在高并发场景中使用。 变更记录 功能描述 移除全部包含 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 移除 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 移除全部存储数据。 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 存储 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 存储 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 存储 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 存储 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 存储 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 存储 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 智能获取指定类型的键值。 变更记录 功能描述 智能存储指定类型的键值。 注意 在 (Xposed) 宿主环境下只读,无法使用。 变更记录 功能描述 清除 无论是否开启 调用此方法将清除当前存储的全部键值缓存。 下次将从 在 (Xposed) 宿主环境中使用。 变更记录 功能描述 键值对存储构造类。 这个类是对 功能示例 建立一个模板类定义模块与宿主需要使用的键值数据。 示例如下 键值数据定义后,你就可以方便地在模块和宿主中调用所需要的数据。 模块示例如下 宿主示例如下 你依然可以不使用模板定义的默认值,随时修改你的默认值。 示例如下 变更记录 功能描述 这是对使用 此类接管了 在你使用 然后请将重写方法由 功能示例 使用 示例如下 其余用法与 变更记录 功能描述 对接原始方法 变更记录 功能描述 实现了 功能示例 注意 在使用 onSharedPreferenceChanged 时请保留 super 方法。 示例如下 变更记录 作废了 转移到 功能描述 YukiHookAPI 的 Xposed 装载 API 调用接口。 变更记录 功能描述 配置 特别注意 在这里只能进行初始化配置,不能进行 Hook 操作。 此方法可选,你也可以选择不对 YukiHookAPI.Configs 进行配置。 变更记录 功能描述 Xposed API 的模块装载调用入口方法。 变更记录 功能描述 监听 Xposed 原生装载事件。 若你的 Hook 事件中存在需要兼容的原生 Xposed 功能,可在这里实现。 请在这里使用 YukiXposedEvent 创建回调事件监听。 可监听的事件如下: 特别注意 此接口仅供监听和实现原生 Xposed API 的功能,请不要在这里操作 YukiHookAPI。 变更记录 请转移到 这是一个将模块资源、 在使用以下功能之前,为防止资源 ID 互相冲突,你需要在当前 Xposed 模块项目的 注意 提供的示例资源 ID 值仅供参考,不可使用 0x7f,默认为 0x64,为了防止当前宿主存在多个 Xposed 模块,建议自定义你自己的资源 ID。 在 Hook 宿主之后,我们可以直接在 Hooker 中得到的 示例如下 你还可以直接在 示例如下 小提示 更多功能请参考 Context+Resources.injectModuleAppResources 方法。 在 Android 系统中所有应用的 在 Hook 宿主之后,我们可以直接在 Hooker 中得到的 示例如下 你还可以直接在 示例如下 如果没有填写 通常情况下,它是有效的,但是以上情况在一些 APP 中会失效,例如一些 若未注册的 你需要选择一个当前宿主可能用不到的、不需要的 比如我们已经找到了能够被代理的合适 示例如下 根据其中的 示例如下 另一种情况,如果你对宿主的类编写了一个 示例如下 注册完成后,请将你需要使用宿主启动的模块中的 这些 示例如下 若你需要继承于 示例如下 以上步骤全部完成后,你就可以在 (Xposed) 宿主环境任意存在 示例如下 小提示 更多功能请参考 Context.registerModuleAppActivities 方法。 有时候,我们需要使用 这时,我们想在宿主被 Hook 的当前 示例如下 你还可以对当前 示例如下 这样,我们就可以在宿主中非常简单地使用 可能存在的问题 由于一些 APP 自身使用的 androidx 依赖库或自定义主题可能会对当前 MaterialAlertDialog 实际样式造成干扰,例如对话框的按钮样式,这种情况你可以参考 模块 Demo 中 这里的示例代码 来修复这个问题。 某些 APP 在创建时可能会发生 ClassCastException 异常,请手动指定新的 Configuration 实例来进行修复。 小提示 更多功能请参考 Context.applyModuleTheme 方法。 这是一个自动 Hook 宿主 APP 生命周期的扩展功能。 通过自动化 Hook 宿主 APP 的生命周期方法,来实现监听功能。 我们需要监听宿主 示例如下 小提示 更多功能请参考 AppLifecycle。 通过 我们还可以在宿主 示例如下 小提示 更多功能请参考 AppLifecycle。 日志是调试过程最重要的一环, 你可以调用 使用方法如下所示。 示例如下 此时, 日志默认的 你也可以动态自定义这个值,但是不建议轻易修改 示例如下 打印的结果为如下所示。 示例如下 你还可以使用 默认类型为 比如我们仅使用 示例如下 或又仅使用 示例如下 若你想智能区分 (Xposed) 宿主环境与模块环境,可以写为如下形式。 示例如下 这样 API 就会在不同环境智能选择指定的方法类型去打印这条日志。 你可以调用 使用方法如下所示。 示例如下 错误日志的级别是最高的,无论你有没有过滤仅为 对于错误级别的日志,你还可以在后面加上一个异常堆栈。 打印的结果为如下所示。 示例如下 同时,日志会帮你打印整个异常堆栈。 示例如下 在错误日志中,你同样也可以使用 小提示 更多功能请参考 loggerE 方法。 你可以使用 示例如下 你还可以使用 示例如下 以上功能需要启用 你还可以使用 此功能需要在 Hook 入口类的 示例如下 小提示 更多功能请参考 YukiHookLogger.contents、YukiHookLogger.saveToFile 方法以及 YukiHookLogger.Configs。 这里是 Class 对象自身相关的扩展功能。 假设我们要得到一个不能直接调用的 示例如下 这种写法大概不是很友好,此时 以上写法换做 示例如下 如果当前 示例如下 我们还可以通过映射来得到一个存在的 示例如下 小提示 更多功能请参考 classOf、String.toClass、String.toClassOrNull、PackageParam → String+VariousClass.toClass、PackageParam → String+VariousClass.toClassOrNull 方法。 假设我们要判断一个 示例如下 这种写法大概不是很友好,此时 以上写法换做 示例如下 小提示 更多功能请参考 String.hasClass、PackageParam → String.hasClass 方法。 在 R8 等工具混淆后的宿主 Dex 中的 此时就有了 注意 目前 DexClassFinder 的功能尚在试验阶段,由于仅通过 Java 层实现查找功能,在宿主 Class 过多时性能可能不能达到最佳水平,如果发生查找不到、定位有误的问题欢迎向我们反馈。 由于是反射层面的 API,目前它只能通过类与成员的特征来定位指定的 Class,不能通过指定字节码中的字符串和方法内容特征来进行定位。 查找 Class 的速度取决于当前设备的性能,目前主流的移动端处理器在 10~15w 数量的 Class 中条件不算复杂的情况下大概在 3~10s 区间,条件稍微复杂的情况下最快速度能达到 25s 以内,匹配到的同类型 Class 越多速度越慢。 下面是一个简单的用法示例。 假设下面这个 示例如下 此时,我们想得到这个 在 下方演示的条件中每一个都是可选的,条件越复杂定位越精确,同时性能也会越差。 示例如下 小提示 上述用法中对于 Field、Method、Constructor 的条件用法与 Member 扩展 中的相关用法是一致的,仅有小部分区别。 更多功能请参考 MemberRules、FieldRules、MethodRules、ConstructorRules。 默认情况下 针对上述问题,我们可以启用异步,只需要加入参数 注意 对于异步情况下你需要使用 wait 方法来得到结果,get 方法将不再起作用。 示例如下 这样我们的查找过程就是异步运行了,它将不会阻塞主线程,每个查找都将在单独的线程同时进行,可达到并行任务的效果。 由于每次重新打开宿主都会重新进行查找,在宿主版本不变的情况下这是一种重复性能浪费。 此时我们可以通过指定 本地缓存使用的是 启用本地缓存后,将同时设置 示例如下 如果你想手动清除本地缓存,可以使用如下方法清除当前版本的宿主缓存。 示例如下 你还可以清除指定版本的宿主缓存。 示例如下 如果你需要使用固定的条件同时查找一组 小提示 更多功能请参考 ClassLoader.searchClass、PackageParam.searchClass 方法。 这里是 Class 字节码成员变量 Field、Method、Constructor 相关的扩展功能。 小提示 Member 是 Field、Method、Constructor 的接口描述对象,它在 Java 反射中为 Class 中字节码成员的总称。 假设有一个这样的 示例如下 假设我们要得到 示例如下 这种写法大概不是很友好,此时 以上写法换做 示例如下 小提示 更多功能请参考 MethodFinder。 同样地,我们需要得到 示例如下 小提示 更多功能请参考 FieldFinder。 也许你还想得到当前 示例如下 若想得到的是 示例如下 小提示 更多功能请参考 ConstructorFinder。 假设我们要得到 示例如下 通过观察发现,这个 示例如下 是的,对于确切不会变化的方法,你可以精简查找条件。 在只使用 问题又来了,这个 通常情况下我们会使用 此时,在确定方法唯一性后,你可以使用 示例如下 上述示例虽然能够匹配成功,但是不精确,此时你还可以使用 示例如下 你会注意到 参照上面的查找条件,我们只需要在查找条件中加入一个 示例如下 这个时候我们就可以在父类中取到这个方法了。 由于我们现在已知 示例如下 这个时候我们同样可以得到父类中的这个方法。 特别注意 当前查找的 Method 除非指定 superClass 条件,否则只能查找到当前 Class 的 Method,这是 Java 反射 API 的默认行为。 如果我们想查找一个方法名称,但是又不确定它在每个版本中是否发生变化,此时我们就可以使用模糊查找功能。 假设我们要得到 示例如下 已知当前 示例如下 我们还可以根据首尾字符串进行判断。 示例如下 通过观察发现这个方法名称中只包含字母,我们还可以再增加一个精确的查找条件。 示例如下 小提示 使用 name { ... } 创建一个条件方法体,其中的变量 it 即当前名称的字符串,此时你就可以在 NameRules 的扩展方法中自由使用其中的功能。 方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。 更多功能请参考 NameRules。 有些时候,我们可能需要查找一个 在查找条件结果的基础上,我们只需要把 假设这次我们要得到 示例如下 上述示例可完美匹配到如下 3 个方法。 如果你想更加自由地定义参数个数范围的条件,可以使用如下实现。 示例如下 上述示例可完美匹配到如下 6 个方法。 通过观察 示例如下 上述示例可完美匹配到如下 2 个方法。 小提示 使用 paramCount { ... } 创建一个条件方法体,其中的变量 it 即当前参数个数的整数,此时你就可以在 CountRules 的扩展方法中自由使用其中的功能。 方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。 更多功能请参考 CountRules。 有些方法和变量在 假设我们这次要得到静态变量 示例如下 假设 加入一个筛选条件即可。 示例如下 我们还可以调用名为 示例如下 同样地,你可以标识它是一个静态。 示例如下 小提示 使用 modifiers { ... } 创建一个条件方法体,此时你就可以在 ModifierRules 中自由使用其中的功能。 方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。 更多功能请参考 ModifierRules。 你可能已经注意到了,这里给出的示例 有两种方案。 第一种方案,确定变量的名称和类型。 示例如下 第二种方案,确定变量的类型所在的位置。 示例如下 以上两种情况均可得到对应的变量 同样地,这个 你也可以有两种方案来得到它们。 第一种方案,确定方法的名称和方法参数。 示例如下 第二种方案,确定方法的参数所在的位置。 示例如下 由于观察到这个方法在 示例如下 注意 请尽量避免使用 order 来筛选字节码的下标,它们可能是不确定的,除非你确定它在这个 Class 中的位置一定不会变。 上面介绍的调用字节码的方法都需要使用 此时,你可以在任意实例上使用 示例如下 我们还可以用 示例如下 如果你不喜欢使用一个大括号的调用域来创建当前实例的命名空间,你可以直接使用 示例如下 同样地,它们之间可以连续调用,但不允许内联调用。 示例如下 针对 示例如下 注意 上述 current 方法相当于帮你调用了 CurrentClass 中的 field { ... }.any()?.current() 方法。 若不存在 CurrentClass 调用域,你需要使用 field { ... }.get(instance).current() 来进行调用。 问题又来了,我想使用反射的方式创建如下的实例并调用其中的方法,该怎么做呢? 示例如下 通常情况下,我们可以使用标准的反射 API 来调用。 示例如下 但是感觉这种做法好麻烦,有没有更简洁的调用方法呢? 这个时候,我们还可以借助 示例如下 若你希望 这种情况多用于实例本身的构造方法是私有的,但是里面的方法是公有的,这样我们只需要对其构造方法进行反射创建即可。 示例如下 小提示 更多功能请参考 CurrentClass 以及 Class.buildOf 方法。 若你正在使用反射调用的一个方法是被 Hook 过的,此时我们如何调用其原始方法呢? 原生的 现在,在 假设下面是我们要演示的 示例如下 下面是 Hook 这个 示例如下 此时,我们再使用反射调用这个方法,则会得到 Hook 后的结果 示例如下 如果我们想得到这个方法未经 Hook 的原始方法及结果,只需要在结果中加入 示例如下 小提示 更多功能请参考 MethodFinder.Result.original 方法。 假设有三个不同版本的 这里面同样都有一个方法 版本 A 示例如下 版本 B 示例如下 版本 C 示例如下 我们需要在不同的版本中得到这个相同功能的 此时,你可以使用 示例如下 特别注意 使用了 RemedyPlan 的方法查找结果不能再使用 get 的方式得到方法实例,应当使用 wait 方法。 另外,你还可以在使用 多重查找 的情况下继续使用 示例如下 以当前 示例如下 小提示 在创建 Hook 的时候使用可参考 MethodFinder.Process.all、ConstructorFinder.Process.all 方法。 更多功能请参考 MethodFinder.RemedyPlan、ConstructorFinder.RemedyPlan、FieldFinder.RemedyPlan。 假设宿主中不同版本中存在功能相同的 版本 A 示例如下 版本 B 示例如下 这个时候我们想在每个版本都调用这个 通常做法是判断 示例如下 感觉这种方案非常的不优雅且繁琐,那么此时 现在,你可以直接使用以下方式获取到这个 示例如下 若当前 示例如下 若你不确定所有的 示例如下 若你正在 示例如下 小提示 更多功能请参考 VariousClass。 若在创建 Hook 的时候使用,可以更加方便,还可以自动拦截找不到 示例如下 你还可以把这个 示例如下 小提示 更多功能请参考 PackageParam.findClass 方法。 在反射过程中,我们可能会遇到泛型问题,在泛型的反射处理上, 例如我们有如下的泛型类。 示例如下 当我们想在当前 示例如下 当我们想在外部调用这个 示例如下 小提示 更多功能请参考 CurrentClass.generic、Class.generic 方法以及 GenericClass。 这里列举了使用时可能会遇到的误区部分,可供参考。 特别注意 在查找条件中,除了 order 你只能使用一次 index 功能。 示例如下 以下查找条件的使用是没有任何问题的。 示例如下 特别注意 在普通方法查找条件中,即使是无参的方法也需要设置查找条件。 假设我们有如下的 示例如下 我们要得到其中的 示例如下 但是,上面的例子是错误的。 你会发现这个 由于上述例子没有设置 这是一个经常会出现的错误,没有方法参数就会丢失方法参数查找条件的使用问题。 正确的使用方法如下。 示例如下 至此,上述的示例将可以完美地匹配到 兼容性说明 在过往历史版本的 API 中是允许匹配不写默认匹配无参方法的做法的,但是最新版本更正了这一问题,请确保你使用的是最新的 API 版本。 在构造方法查找条件中,无参的构造方法可以不需要填写查找条件。 假设我们有如下的 示例如下 我们要得到其中的 示例如下 上面的例子可以成功获取到 与普通方法不同,由于构造方法不需要考虑 示例如下 兼容性说明 在过往历史版本的 API 中构造方法不填写任何查找参数会直接找不到构造方法,这是一个 BUG,最新版本已经进行修复,请确保你使用的是最新的 API 版本。 特别注意 在字节码调用结果中,cast 方法只能指定字节码对应的类型。 例如我们想得到一个 以下是错误的使用方法。 示例如下 以下是正确的使用方法。 示例如下 在查找方法、变量的时候我们通常需要指定所查找的类型。 示例如下 在 因此, 这个时候上面的类型就可以写作如下形式了。 示例如下 在 Java 中常见的基本类型都已被封装为 类型 + Type 的方式,例如 相应地,数组类型也有方便的使用方法,假设我们要获得 需要写做 感觉是不是很麻烦,这个时候我们可以使用扩展方法 同时由于 一些常见的 Hook 中查找的方法,都有其对应的封装类型以供使用,格式为 类型 + Class。 例如 Hook 示例如下 同时,欢迎你能贡献更多的常用类型。 这是一个使用系统无序广播在模块与宿主之间发送和接收数据的解决方案。 需要满足的条件 模块与宿主需要保持存活状态,否则无法建立通讯。 这里描述了 通过使用 模块示例如下 宿主示例如下 你可以不设置 模块示例如下 宿主示例如下 特别注意 接收方需要保持存活状态才能收到通讯数据。 小提示 更多功能请参考 YukiHookDataChannel。 通过通讯桥功能, 我们只需要调用 在模块与宿主中可进行双向判断。 你可以在模块中判断指定包名的宿主是否与当前模块的版本匹配。 示例如下 你还可以在宿主中判断是否自身与当前模块的版本匹配。 示例如下 方法回调的条件 宿主、模块保持存活状态,并在激活模块后重启了作用域中的 Hook 目标宿主对象。 小提示 更多功能请参考 YukiHookDataChannel。 这里只列出了在模块中使用的例子,在宿主中相同的 特别注意 在模块和宿主中,每一个 dataChannel 对应的 key 的回调事件都不允许重复创建,若重复,之前的回调事件会被新增加的回调事件替换,若在模块中使用,在同一个 Activity 中不可以重复,不同的 Activity 中相同的 key 允许重复。 示例如下 在上述示例中,回调事件 A 会被回调事件 B 替换掉,回调事件 C 的 特别注意 一个相同 key 的回调事件只会回调当前模块正在显示的 Activity 中注册的回调事件,例如上述中的 test_key,如果 OtherActivity 正在显示,那么 MainActivity 中的 test_key 就不会被回调。 相同的 key 在同一个 Activity 不同的 Fragment 中注册 dataChannel,它们依然会在当前 Activity 中同时被回调。 在模块中,你只能使用 Activity 的 Context 注册 dataChannel,你不能在 Application 以及 Service 等地方使用 dataChannel。 若要在 Fragment 中使用 dataChannel,请使用 activity?.dataChannel(...)。 在模块环境中,你只能接收指定包名的宿主发送的通讯数据且只能发送给指定包名的宿主。 特别注意 为了进一步防止广播滥用,通讯数据中 API 会自动指定宿主和模块的包名,防止其它 APP 监听并利用广播做出超限行为。 这是一个自动对接 我们需要存储模块的数据,以供宿主调用,这个时候会遇到原生 原生的 这里描述了在 通常情况下我们可以这样在 Hook APP (宿主) 内对其进行初始化。 示例如下 有没有方便快捷的解决方案呢,此时你就可以使用 当你在模块中存储数据的时候,若当前处于 示例如下 当你在 Hook APP (宿主) 中读取数据时,可以使用如下方法。 示例如下 你不需要考虑传入模块的包名以及一系列复杂的权限配置,一切都交给 若要实现存储的区域划分,你可以指定每个 在模块的 示例如下 在 Hook APP (宿主) 中这样读取。 示例如下 若你的项目中有大量的固定数据需要存储和读取,推荐使用 小提示 更多功能请参考 YukiHookModulePrefs、PrefsData。 这里描述了在 若你的模块使用了 特别注意 你必须继承 ModulePreferenceFragment 才能实现 YukiHookModulePrefs 的模块存储功能。 小提示 更多功能请参考 ModulePreferenceFragment。 这里介绍了 无论是 作为 Xposed 模块使用 还是 作为 Hook API 使用,你都可以在 API 装载之前或装载过程中对 小提示 更多功能请参考 YukiHookAPI.configs 方法。 一个 Xposed 模块或 Hook API 最重要的地方就是 Hooker 的创建与使用, 这种方案是最简单的,如果你的模块功能不多,代码数量不大,不需要进行分类处理,推荐使用这种方式进行创建。 小提示 更多功能请参考 PackageParam。 示例代码 1 示例代码 2 在 这种方案更加适用于大型项目,例如需要对 Hooker 进行分类或对 Hook 的作用对象进行分类。 同样为 小提示 更多功能请参考 YukiBaseHooker。 示例如下 子 Hooker 建议使用单例 注意 你无需再在继承于 YukiBaseHooker 的 onHook 方法中重新调用 encase,这是错误的,且不会生效,你应该直接开始编写你的 Hook 代码。 示例如下 作为子 Hooker 使用,你还可以在外部调用 示例如下 你可以使用 示例如下 搭建完全部 Hooker 后,你就可以在你的 示例如下 当然,我们同样可以对其进行简写。 示例如下 如果你当前使用的 Hook Framework 支持并启用了资源钩子(Resources Hook)功能,你现在可以直接在 你完全不需要与之前在使用 Xposed API 那样区分 在 示例如下 你还可以同时使用 示例如下 直接装载 Hooker 或直接开始 Hook 是错误的, 装载 装载 装载 在这个过程中,你需要使用 注意 无论使用 encase 创建 lambda 方法体还是直接使用 Hooker 形式,你都不应该直接在首个 onHook 事件中直接装载 Hooker 或直接开始 Hook。 下面是两个错误示例。 示例代码 1 示例代码 2 下面是上述错误示例的正确示例。 示例代码 1 示例代码 2 若你作为 Hook API 使用,那么你只需要在入口处对 注意 encase 方法对作为 Hook API 使用提供了两个完全一样的方法,但是比前两者仅多出一个参数 baseContext。 方法 1 方法 2 此处的 特别注意 切勿以 Xposed 方式使用 encase 方法而漏掉 baseContext 参数,否则你的 Hook 将完全不工作。 Resources Hook 功能不支持作为 Hook API 使用。 作为 Hook API 通常为做自身 APP 热更新或功能需要以及产品测试的 Hook 操作。 你只需要集成 然后请集成你目标使用的 创建你的自定义 在 示例如下 这样,你就完成了 API 的相关配置。 你可以 点击这里 查看异同点和注意事项。 注意 你不能再使用 loadApp 进行包装,可直接开始编写你的 Hook 代码。 这里给出了一些较高使用率的 所需 Xposed API 依赖 示例如下 所需 Xposed API 依赖 示例如下 所需 Xposed API 依赖 请参考 xposed-hook-based-on-whale。 示例如下 大部分场景下 Xposed 模块可通过原生混淆压缩体积,这里介绍了混淆的配置方法。 如果你使用的是 特别注意 Proguard 规则已被弃用,请不要再使用,自从 Android Gradle Plugin 4.2 后,拥有 Android Jetpack 套件最新版本的混淆处理程序默认均为 R8,不再需要考虑混淆的问题。 若要在任何版本下启用 这里介绍了 作为 Xposed 模块, 你需要在你的 你可以对 特别注意 @InjectYukiHookWithXposed 注解的 Class 必须实现 IYukiHookXposedInit 接口。 在你当前项目中的所有 Class 标记中只能存在一次,若存在多个声明自动处理程序会在编译时抛出异常,你可以自定义其相关参数。 特别注意 如果你的项目不在 ../src/main.. 或你手动使用 sourceSets 设置了项目路径,你就需要手动设置 sourcePath 参数,否则自动处理程序将无法识别你的项目路径并会在编译时抛出异常。 示例如下 注意 若你想使用模块包名自动生成,你需要确保你的项目命名空间在 AndroidManifest.xml、build.gradle 或 build.gradle.kts 中存在如下任意定义方式。 示例命名空间 以下定义方式仅供参考,通常情况下只要你的项目能够正常生成 若你的模块包名是非常规手段进行自动生成的,或你认为有必要手动定义模块包名,那么你可以直接设置 示例如下 只要你自定义了 示例如下 注意 手动定义的模块包名除了格式之外,自动处理程序将不会再检查模块包名是否正确,需要你自行确认其有效性。 假设这是你的入口类。 示例如下 Xposed 入口类处理如下。 示例如下 编译后的类名结构如下。 示例如下 我们现在定义入口类名称为 示例如下 Xposed 入口类处理如下。 示例如下 编译后的类名结构如下。 示例如下 特别注意 你定义的 entryClassName 不可与 xposed_init 中的类名相同,否则自动处理程序会在编译时抛出异常。 启用后生成的入口类将为如下所示。 示例如下 若你当前的项目并不需要用到 Reources Hook,可以设置 示例如下 关闭后生成的入口类将为如下所示。 示例如下 小提示 更多功能请参考 IYukiHookXposedInit。 当你的模块被 Xposed 装载后, 基本的调用流程为 详情请参考 API 基本配置。 若你当前的 Xposed 模块使用了第三方的资源,但是短时间内可能无法转移它们,此时,你可以使用 示例如下 小提示 更多功能请参考 IYukiHookXposedInit.onXposedEvent 方法。 这里介绍了 下方的结构描述了 上方的结构换做代码将可写为如下形式。 你可以在下方找到 API 提供的 Demo 来学习 同时安装宿主和模块 Demo,通过激活模块来测试宿主中被 Hook 的功能。 这里给出了 Hook APP、Hook 系统框架与 Hook Resources 等例子,可供参考。 假设,我们要 Hook 在 示例如下 至此, 那么,我想继续 Hook 在刚刚的代码中,继续插入一个 示例如下 对于当前项目下没有的 比如,我要得到 示例如下 若 示例如下 到这里有些同学可能就开始说了,在某些场景下 因为可能有些同学有如下需求。 示例如下 没关系,你还可以使用字符串类名直接创建一个 Hook。 示例如下 小提示 更多功能请参考 MemberHookCreator。 在 APP 启动时,新的进程被 fork 后的第一个事件 假设我们要全局 Hook 一个 APP 在 示例如下 注意 在 loadZygote 中进行的功能十分有限,几乎很少的情况下需要用到 loadZygote 方法。 在 假设,你要得到 在 示例如下 特别注意 loadZygote 与 loadSystem 有直接性区别,loadZygote 会在 initZygote 中装载,系统框架被视为 loadApp(name = "android") 而存在,若要 Hook 系统框架,可直接使用 loadSystem。 假设,我们要 Hook 在 示例如下 若当前 APP 使用 你还可以使用当前 Xposed 模块的 Resources 替换 Hook APP 的 Resources。 假设,我们要继续 Hook 示例如下 至此目标 APP 的图标将会被替换为我们设置的图标。 若你想替换系统框架的资源,同样也可以这样实现,只需要把 示例如下 小提示 更多功能请参考 ResourcesHookCreator。 原生的 Xposed 为我们提供了一个 第一种方法,保存当前注入对象的 示例如下 第二种方法,在 Hook 回调方法中调用 示例如下 小提示 更多功能请参考 MemberHookCreator。 你可以处理 Hook 方法过程发生的异常。 示例如下 在 Resources Hook 时此方法同样适用。 示例如下 你还可以处理 Hook 的 示例如下 你还可以处理查找方法时的异常。 示例如下 小提示 更多功能请参考 MemberHookCreator.Result、ResourcesHookCreator.Result。 这里介绍了可能发生的常见异常,若要了解更多请参考 API 异常处理。 在某些情况下,你可以手动抛出异常来达到提醒某些功能存在问题的目的。 上面已经介绍过,在 以下是 示例如下 以上情景只会在 (Xposed) 宿主环境被处理,不会对宿主自身造成任何影响。 若我们想将这些异常直接抛给宿主,原生的 Xposed 为我们提供了 若想在 Hook 回调方法体中将一个异常直接抛给宿主,可以有如下实现方法。 示例如下 你也可以直接在 Hook 回调方法体中抛出异常,然后标识将异常抛给宿主。 示例如下 以上两种方法均可在宿主接收到异常从而使宿主进程崩溃。 注意 为了保证 Hook 调用域与宿主内调用域相互隔离,异常只有在 beforeHook 与 afterHook 回调方法体中才能抛给宿主。 在使用 在 首先我们可以监听 Hook 已经准备开始。 示例如下 特别注意 instanceClass 建议只在 onPrepareHook 中使用,否则被 Hook 的 Class 不存在会抛出无法拦截的异常导致 Hook 进程“死掉”。 然后,我们还可以对 Hook 的方法结果进行监听是否成功。 示例如下 你可以在 Hook 过程中使用下面的方法方便地实现各种判断和功能。 如果你的模块需要同时处理多个 APP 的 Hook 事件,你可以使用 示例如下 小提示 更多功能请参考 PackageParam.loadApp。 如果你 Hook 的宿主 APP 有多个进程,你可以使用 示例如下 小提示 更多功能请参考 PackageParam.withProcess。 为了使代码更加简洁,你可以删去 示例如下 通常情况下,我们会选择写一个方法,使其返回 在 现在,你可以直接使用 示例如下 由于一些特殊原因,在太极、无极中的模块无法使用标准方法检测激活状态。 此时你可以使用 示例如下 若你想使用两者得兼的判断方案, 此时你可以使用 示例如下 小提示 更多功能请参考 YukiHookAPI.Status。 注意 若模块激活判断中包含太极、无极中的激活状态,就必须将模块的 Application 继承于 ModuleApplication 或直接使用 ModuleApplication; 1.0.91 版本后的 API 修改了激活逻辑判断方式,现在你可以在模块与 Hook APP (宿主) 中同时使用此 API; 需要确保 YukiHookAPI.Configs.isEnableHookModuleStatus 是启用状态; 除了提供标准 API 的 Hook 框架之外,其它情况下模块可能都将无法判断自己是否被激活。 这是一个 Hook API 框架,本身不提供任何 Hook 功能,需要 Xposed 基础 API 的支持。 这是一个使用 名称取自 《ももくり》女主 栗原 雪(Yuki)。 前身为 开发学习项目 中使用的 Innocent Xposed API,现在重新命名并开源。 抛弃原始不太友好的 请使用 文档全部的 Demo 示例代码都将使用 部分 Java Demo 代码可在 这里 找到,但不推荐使用。 以前,我们在构建 Xposed 模块的时候,首先需要在 然后,将自己的入口类名手动填入文件中,使用 自 有没有什么 好用、轻量、优雅 的解决办法呢? 本着这样的想法, 现在,我们只需要编写少量的代码,一切时间开销和花费交给自动化处理。 借助 示例如下 是的,你没有看错,仅仅就需要这些代码,就能完全取代 Xposed API 实现同样的功能。 现在,借助高效强大的 以下是 这里收集了 Xposed 相关的介绍以及开启前需要掌握的知识要点,已经了解的同学可以略过。 基础知识内容并不一定完全准确,请根据自己的见解酌情阅读,若发现内容有错误欢迎指正并帮助我们完善和改进。 这里介绍了 Xposed 以及 Hook 的工作原理。 Xposed 框架(Xposed Framework)是一套开源的、在 Android 高权限模式下运行的框架服务,可以在不修改 APK 文件的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。 上述内容复制自百度百科。 下方的结构描述了 Xposed 的基本工作方式和原理。 我们可以在宿主 (APP) 运行时通过注入宿主 (APP) 来达到控制其行为的最终目的。 Xposed 的这种运行方式被称为寄生,Xposed 模块跟随宿主的生命周期,在宿主的生命周期内完成自己的生命历程。 我们可以通过反射的方式调用宿主的方法、变量、构造方法,以及使用 如今的 Xposed 管理器已完全被其衍生作品替代,而 SuperSU 的时代也已经落幕了,现在,借助 Magisk 使后面的一切又成为了可能。 其发展史大致可分为 Xposed(Dalvik) → Xposed(ART) → Xposed(Magisk) → EdXposed(Riru)/LSPosed(Riru/Zygisk) 下方的结构描述了类似 Xposed 的 Hook Framework 的工作方式和原理。 通过 Xposed 的运行原理,从而衍生了很多同类型框架,随着当今时代的移动设备获取 Root 权限甚至刷机越来越困难且不是刚需的时候,一些免 Root 框架也随之产生,例如太极。 这些在 ART 层面上的 Hook 框架同样也可不借助 Xposed API 完成其和 Xposed 原理一样的 Hook 流程,免 Root 的运行原理为修改 APK 并将 Hook 进程注入宿主,通过外部模块对其进行控制。 另外一种产品就是利用 Android 运行环境现有的功能虚拟出一个完全与当前设备系统一样的环境,并在其中运行 APP,这个就是虚拟 APP 技术 VirtualApp,后来衍生为 VirtualXposed。 上述提到的免 Root 框架分别为太极/无极、VirtualXposed/SandVXposed。 自从 Xposed 出现到现在为止,除了开发者人人皆知的 本 API 框架的诞生就是希望在 Xposed 的如今时代,能让更多有动手能力的 Xposed 模块开发者少走弯路,更容易、更简单地完成整个开发流程。 未来, 在开始之前,你需要拥有以下基础才能更好地使用 掌握并了解 Android 开发及简单的系统运行原理 掌握并熟练使用 Java 反射,了解简单的 Smali 语法,了解 DEX 文件结构,会使用逆向分析定位方法位置 掌握基础的原生 Xposed API 用法,了解 Xposed 的运行原理,可参考本文以及 这里 (友情链接) 掌握 Kotlin 语言,学会灵活运用 Kotlin lambda (友情链接) 掌握并了解 Kotlin 与 Java 混编、互相调用以及 Kotlin 生成的 Java 字节码 若你熟悉 Xposed API,你可以参考下方的相同点将自己的 API 快速迁移到 从 API 功能差异对比如下 从 API 功能差异对比如下 API 功能差异对比如下 集成 Windows 7 及以上/macOS 10.14 及以上/Linux 发行版(Arch/Debian) Android Studio 2021.1 及以上 IntelliJ IDEA 2021.1 及以上 Kotlin 1.7.0 及以上 Android Gradle Plugin 7.0 及以上 Gradle 7.0 及以上 Jvm 11 及以上 (Since API 你可以 点击这里 进行查看。 若你不想使用自动化构建工具,你依然可以按照以下方式手动配置项目依赖。 使用 在你的项目 示例如下 在你的 app 示例如下 在你的 app 示例如下 请将 <ksp-version> 修改为 这里 的最新版本 (请注意选择你当前对应的 Kotlin 版本)。 请将 <yuki-version> 修改为 这里 的最新版本。 特别注意 YukiHookAPI 的 api 与 ksp-xposed 依赖的版本必须一一对应,否则将会造成版本不匹配错误。 在你的 app 示例如下 注意 自 API 1.0.80 版本后 Jvm 版本默认为 11,不再支持 1.8 及以下版本。 在你的 示例如下 在你的项目中创建一个 Hook 入口类,继承于 示例如下 然后,你就可以开始编写 Hook 代码了。 有关作为 Xposed 模块使用的相关配置详细内容,你可以 点击这里 继续阅读。 若你目前正在使用 Xposed API,你可以参考 从 Xposed API 迁移。 创建你的自定义 特别注意 无论使用任何 Hook Framework,你都需要加入其对接的 Xposed 依赖支持。 若目标 Hook Framework 没有集成 Xposed API 你需要自行实现并对接 XposedBridge。 在 示例如下 然后,你就可以开始编写 Hook 代码了,方式与作为 Xposed 模块使用基本一致。 有关作为 Hook API 使用的相关配置详细内容,你可以 点击这里 继续阅读。 注意 使用自定义的 Hook 框架而并非完整的 Xposed 模块时,YukiHookModuleStatus、YukiHookModulePrefs、YukiHookDataChannel 以及 Resources Hook 功能将失效。 这是一个使用 实现自动化搜索依赖快速搭建一个包含 Xposed 模块环境的 Android 项目模板。 本项目完全开源免费,且会根据大家的使用情况持续维护,初代版本可能存在不完善或 BUG,欢迎反馈。 项目地址 YukiHookAPI-ProjectBuilder。 若你想直接下载可以 点击这里 前往 Release 发布地址。 这里包含了基本的使用方法和功能讲解。 软件使用过程需要当前设备已连接互联网,若项目依赖无法搜索请尝试 科学上网 。 启动软件后,对你期望创建的项目进行简单配置,点击右下角的 按钮 或菜单栏选择 项目 > 开始创建 即可开始任务。 等待依赖自动搜索完成后,你可以对项目依赖进行配置,建议使用最新依赖保证项目的稳定性,构建工具也仅对最新依赖进行支持。 选择你需要创建项目的目录,开始后项目会在你选择的位置中创建,并等待整个过程完成,项目就创建好了。 配置模板是一个扩展功能,你可以选择菜单栏 项目 > 配置模板 > 新建模板,即可使用当前填写的配置创建一份模板,下次可以从 已保存的模板 中重新载入模板,即可还原当前配置。 软件语言跟随当前系统,你可以在菜单栏 语言 (Language) 一栏手动选择软件的界面语言。{const{slotScopeIds:w}=b;w&&(U=U?U.concat(w):w);const v=r(k),q=g(n(k),b,v,L,M,U,ee);return q&&Jl(q)&&q.data==="]"?n(b.anchor=q):(Et=!0,s(b.anchor=c("]"),v,q),q)},P=(k,b,L,M,U,ee)=>{if(Et=!0,b.el=null,ee){const q=E(k);for(;;){const B=n(k);if(B&&B!==q)a(B);else break}}const w=n(k),v=r(k);return a(k),l(null,b,v,w,L,M,Zl(v),U),w},E=k=>{let b=0;for(;k;)if(k=n(k),k&&Jl(k)&&(k.data==="["&&b++,k.data==="]")){if(b===0)return n(k);b--}return k};return[h,p]}const Be=Nr;function zc(e){return Dc(e,Fc)}function Dc(e,t){const l=us();l.__VUE__=!0;const{insert:i,remove:o,patchProp:n,createElement:r,createText:a,createComment:s,setText:c,setElementText:h,parentNode:p,nextSibling:m,setScopeId:g=at,cloneNode:x,insertStaticContent:P}=e,E=(u,f,y,T=null,A=null,z=null,$=!1,D=null,V=!!f.dynamicChildren)=>{if(u===f)return;u&&!Wt(u,f)&&(T=X(u),Ye(u,A,z,!0),u=null),f.patchFlag===-2&&(V=!1,f.dynamicChildren=null);const{type:I,ref:Q,shapeFlag:K}=f;switch(I){case Dl:k(u,f,y,T);break;case Ge:b(u,f,y,T);break;case Ll:u==null&&L(f,y,T,$);break;case Pe:S(u,f,y,T,A,z,$,D,V);break;default:K&1?ee(u,f,y,T,A,z,$,D,V):K&6?F(u,f,y,T,A,z,$,D,V):(K&64||K&128)&&I.process(u,f,y,T,A,z,$,D,V,_e)}Q!=null&&A&&ui(Q,u&&u.ref,z,f||u,!f)},k=(u,f,y,T)=>{if(u==null)i(f.el=a(f.children),y,T);else{const A=f.el=u.el;f.children!==u.children&&c(A,f.children)}},b=(u,f,y,T)=>{u==null?i(f.el=s(f.children||""),y,T):f.el=u.el},L=(u,f,y,T)=>{[u.el,u.anchor]=P(u.children,f,y,T,u.el,u.anchor)},M=({el:u,anchor:f},y,T)=>{let A;for(;u&&u!==f;)A=m(u),i(u,y,T),u=A;i(f,y,T)},U=({el:u,anchor:f})=>{let y;for(;u&&u!==f;)y=m(u),o(u),u=y;o(f)},ee=(u,f,y,T,A,z,$,D,V)=>{$=$||f.type==="svg",u==null?w(f,y,T,A,z,$,D,V):B(u,f,A,z,$,D,V)},w=(u,f,y,T,A,z,$,D)=>{let V,I;const{type:Q,props:K,shapeFlag:Z,transition:ne,patchFlag:pe,dirs:xe}=u;if(u.el&&x!==void 0&&pe===-1)V=u.el=x(u.el);else{if(V=u.el=r(u.type,z,K&&K.is,K),Z&8?h(V,u.children):Z&16&&q(u.children,V,null,T,A,z&&Q!=="foreignObject",$,D),xe&&ht(u,null,T,"created"),K){for(const Le in K)Le!=="value"&&!Rl(Le)&&n(V,Le,null,K[Le],z,u.children,T,A,H);"value"in K&&n(V,"value",null,K.value),(I=K.onVnodeBeforeMount)&&tt(I,T,u)}v(V,u,u.scopeId,$,T)}xe&&ht(u,null,T,"beforeMount");const Ee=(!A||A&&!A.pendingBranch)&&ne&&!ne.persisted;Ee&&ne.beforeEnter(V),i(V,f,y),((I=K&&K.onVnodeMounted)||Ee||xe)&&Be(()=>{I&&tt(I,T,u),Ee&&ne.enter(V),xe&&ht(u,null,T,"mounted")},A)},v=(u,f,y,T,A)=>{if(y&&g(u,y),T)for(let z=0;z
Z)for(;I<=K;)Ye(u[I],A,z,!0),I++;else{const ne=I,pe=I,xe=new Map;for(I=pe;I<=Z;I++){const We=f[I]=V?Lt(f[I]):ot(f[I]);We.key!=null&&xe.set(We.key,I)}let Ee,Le=0;const it=Z-pe+1;let el=!1,Bo=0;const kl=new Array(it);for(I=0;I
{const{el:z,type:$,transition:D,children:V,shapeFlag:I}=u;if(I&6){Je(u.component.subTree,f,y,T);return}if(I&128){u.suspense.move(f,y,T);return}if(I&64){$.move(u,f,y,_e);return}if($===Pe){i(z,f,y);for(let K=0;K
(l[x]||"").split(", "),o=i(Rt+"Delay"),n=i(Rt+"Duration"),r=Cn(o,n),a=i(vl+"Delay"),s=i(vl+"Duration"),c=Cn(a,s);let h=null,p=0,m=0;t===Rt?r>0&&(h=Rt,p=r,m=n.length):t===vl?c>0&&(h=vl,p=c,m=s.length):(p=Math.max(r,c),h=p>0?r>c?Rt:vl:null,m=h?h===Rt?n.length:s.length:0);const g=h===Rt&&/\b(transform|all)(,|$)/.test(l[Rt+"Property"]);return{type:h,timeout:p,propCount:m,hasTransform:g}}function Cn(e,t){for(;e.length=0&&(s=-1),s>-1&&(i=t.slice(0,s),n=t.slice(s+1,a>-1?a:t.length),o=e(n)),a>-1&&(i=i||t.slice(0,a),r=t.slice(a,t.length)),i=Vh(i!=null?i:t,l),{fullPath:i+(n&&"?")+n+r,path:i,query:o,hash:r}}function Hh(e,t){const l=t.query?e(t.query):"";return t.path+(l&&"?")+l+(t.hash||"")}function An(e,t){return!t||!e.toLowerCase().startsWith(t.toLowerCase())?e:e.slice(t.length)||"/"}function Mh(e,t,l){const i=t.matched.length-1,o=l.matched.length-1;return i>-1&&i===o&&ul(t.matched[i],l.matched[o])&&ga(t.params,l.params)&&e(t.query)===e(l.query)&&t.hash===l.hash}function ul(e,t){return(e.aliasOf||e)===(t.aliasOf||t)}function ga(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(const l in e)if(!Sh(e[l],t[l]))return!1;return!0}function Sh(e,t){return st(e)?Tn(e,t):st(t)?Tn(t,e):e===t}function Tn(e,t){return st(t)?e.length===t.length&&e.every((l,i)=>l===t[i]):e.length===1&&e[0]===t}function Vh(e,t){if(e.startsWith("/"))return e;if(!e)return t;const l=t.split("/"),i=e.split("/");let o=l.length-1,n,r;for(n=0;n Changelog
YukiHookAPI
is recorded here.XposedHelper
is misspelled and changed to XposedHelpers
Class
and Method
of Hook App Demo to Java to provide better demo effectHookParamWrapper
, it now interfaces directly with YukiBridgeFactory
YukiHookBridge
to AppParasitics
HookParam.args
and the underlying direct connection method setArgs
, directly get and set the object of the current arrayjar
into stub
projectCreater
naming to Creator
for all reflection and Hook classesYukiHookAPI.Status.compiledTimestamp
function, which can get the compilation completion timestamp when used as an Xposed moduleYukiHookAPI.Status.isXposedEnvironment
function, which can determine whether the current (Xposed) host environment or module environment isYukiHookAPI.Configs.debugTag
have been merged into YukiHookLogger.Configs
XposedBridge.log
or Logd
debugLog
configurationgeneric
function to reflect and call generics, you can use it in Class
or CurrentClass
buildOfAny
method, now use the buildOf
method directly (without generics) to use the constructor to create a new object and get the result Any
hasExtends
CurrentClass
added non-lambda
method of callingCurrentClass
adds name
and simpleName
functionsReflectionTool
, sorting and classifying different search conditionsMember
obtained by directly calling declared
in ReflectionTool
throws an exceptionUndefinedType
in ReflectionTool
is not correctly judged in Method
and Constructor
conditionsMember
cannot be found under specified conditionsVagueType
condition in Method
and Constructor
for reflection search, which can be used in param
condition to ignore parameters you don't want to fill inparamCount { ... }
condition in Method
and Constructor
of reflection search, now you can directly get it
in it to customize your judgment conditioncurrent
method is added to the FieldFinder
result, which can directly create a call space for the result instancemodifiers
condition and name
condition in the reflection lookup function, now you need to return a Boolean
at the end of the method body to make the condition trueRemedyPlan
feature in FieldFinder
Class
fuzzy search function (Beta) in Dex
, you can now directly use searchClass
function to fuzzy search Class
with specified conditionsYukiHookAPI.Configs.isEnableHookSharedPreferences
function, which is disabled by default and can be enabled if the permission of SharedPreferences
is incorrectConstructor
without filling in the search conditions, thanks B5 KAKA for the feedbackResult
instances located in method
, constructor
in injectMember
to Process
useDangerousOperation
method in the Hook process, which will automatically stop the Hook and print an error after the function in the Hook Dangerous List is not declaredActivity
proxy functions, you can call injectModuleAppResources
and registerModuleAppActivities
to useModuleContextThemeWrapper
function, you can call applyModuleTheme
to create the Context
of a module in any Activity
ClassLoader.onLoadClass
function, which can be used to listen for events when the loadClass
method of ClassLoader
is calledclassOf
and clazz
extension methods, add toClass
and toClassOrNull
usage, please move to the new method nowVariousClass
adds a getOrNull
method, which can return null
instead of throwing an exception when it can't match Class
isUseAppClassLoader
parameter in PackageParam.hook
, changed it to isForceUseAbsolute
and automatically matched the target Class
PackageParam
adds systemContext
function, you can call this function at any time to get a persistent Context
HookClass
throwToApp
function in HookParam
, which can throw exceptions directly to the hostonFailureThrowToApp
function is added to the Hook callback, which can be directly thrown to the host when an exception occursremove
and removeSelf
methods to remove the hook
",1),Se={id:"_1-0-91-2022-05-29",tabindex:"-1"},Ye=e("a",{class:"header-anchor",href:"#_1-0-91-2022-05-29","aria-hidden":"true"},"#",-1),Xe=o(" 1.0.91 | 2022.05.29 \u2002"),Te=o("Fixed the "),ze=e("code",null,"ClassLoader",-1),Le=o(" error when the customized system of some devices is booted in the LSPosed environment, thanks to "),We={href:"https://github.com/luckyzyx",target:"_blank",rel:"noopener noreferrer"},De=o("Luckyzyx"),je=o(" for the feedback"),Be=n("YukiHookDataChannel
cannot call back the current Activity
broadcast on devices lower than Android 12InjectYukiHookWithXposed
annotation adds the isUsingResourcesHook
function, now you can selectively disable the dependency interface that automatically generates IXposedHookInitPackageResources
YukiHookDataChannel
not being able to call back the current Activity
broadcast on ZUI and systems below Android 12YukiHookModuleStatus
function into YukiHookAPI.Status
, rewrite a lot of methods, now you can judge the status information such as module activation in the module and the host in both directions
",1),Ee={id:"_1-0-89-2022-05-26",tabindex:"-1"},Ve=e("a",{class:"header-anchor",href:"#_1-0-89-2022-05-26","aria-hidden":"true"},"#",-1),Ke=o(" 1.0.89 | 2022.05.26 \u2002"),Ze=n("YukiHookDataChannel
crashing when the module sets the listener callbackYukiHookDataChannel
still calling back when not in current Activity
YukiHookDataChannel
callback event, no callbackYukiHookModulePrefs
warning printed if XShare is unreadableisXSharePrefsReadable
method in YukiHookModulePrefs
to determine whether the current XShare is available
",1),Ge={id:"_1-0-88-2022-05-25",tabindex:"-1"},Je=e("a",{class:"header-anchor",href:"#_1-0-88-2022-05-25","aria-hidden":"true"},"#",-1),Qe=o(" 1.0.88 | 2022.05.25 \u2002"),$e=n("YukiHookDataChannel
cannot be repeatedly set to monitor, and added the function of repeating response in different Activity
modules and automatically following Activity
to destroy the monitor functionYukiHookDataChannel
repeated listening use case description documentonAlreadyHooked
method to determine whether the current method is repeated HookputIfAbsent
method, allow to override the addition
",1),eo={id:"_1-0-87-2022-05-10",tabindex:"-1"},oo=e("a",{class:"header-anchor",href:"#_1-0-87-2022-05-10","aria-hidden":"true"},"#",-1),to=o(" 1.0.87 | 2022.05.10 \u2002"),io=e("ul",null,[e("li",null,[o("Added "),e("code",null,"refreshModuleAppResources"),o(" function to adapt Resources refresh when the language region, font size, resolution changes, etc.")]),e("li",null,[o("Added "),e("code",null,"isEnableModuleAppResourcesCache"),o(" function, you can set whether to automatically cache the resources of the current module")])],-1),no={id:"_1-0-86-2022-05-06",tabindex:"-1"},co=e("a",{class:"header-anchor",href:"#_1-0-86-2022-05-06","aria-hidden":"true"},"#",-1),so=o(" 1.0.86 | 2022.05.06 \u2002"),ao=e("ul",null,[e("li",null,[o("Fixed the problem of continuous error reporting during "),e("code",null,"initZygote"),o(" when Resources Hook is not supported, reproduced in "),e("strong",null,"ZUI"),o("/"),e("strong",null,"LSPosed CI(1.8.3-6550)")]),e("li",null,"Optimize and handle exceptions for Resources Hook, only print errors and warnings if they are used and not supported")],-1),lo={id:"_1-0-85-2022-05-04",tabindex:"-1"},ro=e("a",{class:"header-anchor",href:"#_1-0-85-2022-05-04","aria-hidden":"true"},"#",-1),ho=o(" 1.0.85 | 2022.05.04 \u2002"),uo=e("ul",null,[e("li",null,[o("Fixed a serious problem of not being able to hook the system framework, since "),e("code",null,"1.0.80")]),e("li",null,[o("Added in the debug log to distinguish the package name loaded by "),e("code",null,"initZygote"),o(" as "),e("code",null,"android-zygote"),o(", "),e("code",null,"packageName"),o(" keeps "),e("code",null,"android"),o(" unchanged")])],-1),_o={id:"_1-0-83-2022-05-04",tabindex:"-1"},mo=e("a",{class:"header-anchor",href:"#_1-0-83-2022-05-04","aria-hidden":"true"},"#",-1),po=o(" 1.0.83 | 2022.05.04 \u2002"),fo=e("ul",null,[e("li",null,[o("Fixed "),e("code",null,"YukiHookModuleStatus"),o(" reporting a lot of errors after "),e("code",null,"loadSystem")]),e("li",null,[o("Added "),e("code",null,"android"),o(" type in "),e("code",null,"type")]),e("li",null,"Updated example descriptions in help documentation")],-1),go={id:"_1-0-82-2022-05-04",tabindex:"-1"},ko=e("a",{class:"header-anchor",href:"#_1-0-82-2022-05-04","aria-hidden":"true"},"#",-1),bo=o(" 1.0.82 | 2022.05.04 \u2002"),yo=e("ul",null,[e("li",null,[o("Fixed a concept confusion error, distinguishing the relationship between "),e("code",null,"initZygote"),o(" and the system framework, there are problems with the previous comments and documentation, I am very sorry")]),e("li",null,[e("code",null,"PackageParam"),o(" adds "),e("code",null,"loadSystem"),o(" method, no need to write "),e("code",null,'loadApp(name = "android")'),o(" to hook the system framework")])],-1),xo={id:"_1-0-81-2022-05-04",tabindex:"-1"},vo=e("a",{class:"header-anchor",href:"#_1-0-81-2022-05-04","aria-hidden":"true"},"#",-1),wo=o(" 1.0.81 | 2022.05.04 \u2002"),Ao=e("ul",null,[e("li",null,[o("Fix the problem that the method and constructor that cannot be found in the Hook method body still output the error log after setting the condition using the "),e("code",null,"by"),o(" method")]),e("li",null,"Added a global log to display the package name of the current Hook APP during the execution of the Hook, and fixed a problem with the printing style of the error log")],-1),Ho={id:"_1-0-80-2022-05-01",tabindex:"-1"},Po=e("a",{class:"header-anchor",href:"#_1-0-80-2022-05-01","aria-hidden":"true"},"#",-1),Fo=o(" 1.0.80 | 2022.05.01 \u2002"),Co=n("android
type in type
YukiHookModuleStatus
from auto-generated code and add isEnableHookModuleStatus
switch, it is up to you to enable or notYukiHookModulePrefs
to run as a singleton to prevent repeated creation and waste of system resources1.0.80
, and optimize the related functions of nested HookHookParam
methodMethodFinder
and FieldFinder
add the function of finding fuzzy methods and variable names, you can call name { ... }
to set search conditions, and support regular expressionsappContext
to reduce the possibility of getting emptyTAG
of logger
in the automatically generated code to default to your custom name, which is convenient for debuggingHooker
implementation of YukiHookBridge
to improve Hook performancePackageParam
adds the onAppLifecycle
method, which can natively monitor the life cycle of the host and implement the registration system broadcast functionYukiHookDataChannel
function to communicate using system out-of-order broadcast while the module and the host remain aliveYukiHookDataChannel
adds the checkingVersionEquals
method, which can be monitored to verify that the host has not updated the version mismatch problem after the module is updateddemo-module
for reference onlyInjectYukiHookWithXposed
annotation adds the entryClassName
function, which can customize the generated xposed_init
entry class name renamed to YukiHookXposedInitProxy
IYukiHookXposedInit
, the original interface name has been invalidated and will be deleted directly in subsequent versionsinitZygote
and Resources Hook functions to support Hook LayoutonXposedEvent
method to listen to all events of native Xposed APIinline
processing on the lambda
of the Hook function to avoid generating excessively broken anonymous classes and improve the running performance after compilationPrefsData
compiled method body copy is too largeXSharePreference
readability test, which will automatically print a warning log if it failsPackageParam
adds appResources
, moduleAppResources
, moduleAppFilePath
functionsloadApp
of PackageParam
adds the function of not writing name
, and all APPs are filtered by defaultPackageParam
adds the loadZygote
method, which can directly hook the system frameworkPackageParam
added resources().hook
functionhasExtends
extension method to determine whether the current Class
has an inheritance relationshipisSupportResourcesHook
function to determine whether resource hooks are currently supported (Resources Hook)current
function adds superClass
method to call superclasssuperClass
query conditions for search methods, construction methods and variables, you can continue to search in the parent classYukiHookAPI
lots of methods are decoupled from Xposed APIisFirstApplication
may be inaccurateYukiHookModulePrefs
adds isRunInNewXShareMode
method, which can be used to determine whether the module is currently in New XSharePreference
modeYukiHookModulePrefs
working in New XSharePreference
modeModulePreferenceFragment
, now you can completely replace PreferenceFragmentCompat
and start using the new functionalityYukiHookModulePrefs
added getStringSet
, putStringSet
, all
methodsany
method to args
of HookParam
ModuleApplication
, which can be inherited in modules to achieve more functionsfindClass
functions to the Xposed API, and continue to use native ClassLoader
in non-hosted environmentsfirstArgs
and lastArgs
methods have been removed from HookParam
, now you can use args().first()
and args().last()
instead of itindex = 0
in args()
in HookParam
, now you can use args().first()
or args(index = 0)
to replace itresult
function in HookParam
adds generic matching, now you can use result<T>
to match the known return value type of your target methodemptyParam
condition is added to the method and constructor query function, and the misunderstanding of the query condition that needs to be paid attention to in the document has been improvedandroid
type in type
",1),Td={id:"_1-0-67-2022-03-27",tabindex:"-1"},zd=e("a",{class:"header-anchor",href:"#_1-0-67-2022-03-27","aria-hidden":"true"},"#",-1),Ld=o(" 1.0.67 | 2022.03.27 \u2002"),Wd=n("Member
lookup cache and lookup cache configuration switchesMethodFinder
, FieldFinder
and HookParam
related method callscast
types in Finder
and support cast
as array
",1),Dd={id:"_1-0-66-2022-03-25",tabindex:"-1"},jd=e("a",{class:"header-anchor",href:"#_1-0-66-2022-03-25","aria-hidden":"true"},"#",-1),Bd=o(" 1.0.66 | 2022.03.25 \u2002"),Nd=e("ul",null,[e("li",null,[o("Fixed a serious bug in "),e("code",null,"MethodFinder")]),e("li",null,[o("Added "),e("code",null,"args"),o(" call method in "),e("code",null,"hookParam")]),e("li",null,"Fix other possible problems and fix some class annotation problems")],-1),Od={id:"_1-0-65-2022-03-25",tabindex:"-1"},Ud=e("a",{class:"header-anchor",href:"#_1-0-65-2022-03-25","aria-hidden":"true"},"#",-1),qd=o(" 1.0.65 | 2022.03.25 \u2002"),Ed=n("modifiers
functions in Finder
, which can filter static
, native
, public
, abstract
and many other description typeshasModifiers
extension for Member
give
method in MethodFinder
and ConstructorFinder
to get primitive typesPrefsData
template function in YukiHookModulePrefs
",1),Vd={id:"_1-0-6-2022-03-20",tabindex:"-1"},Kd=e("a",{class:"header-anchor",href:"#_1-0-6-2022-03-20","aria-hidden":"true"},"#",-1),Zd=o(" 1.0.6 | 2022.03.20 \u2002"),Gd=n("MethodFinder
and FieldFinder
new return value calling methodsandroid
type and java
type in type
",1),Jd={id:"_1-0-55-2022-03-18",tabindex:"-1"},Qd=e("a",{class:"header-anchor",href:"#_1-0-55-2022-03-18","aria-hidden":"true"},"#",-1),$d=o(" 1.0.55 | 2022.03.18 \u2002"),ei=e("ul",null,[e("li",null,"Fixed an annotation error"),e("li",null,"Temporarily fix a bug"),e("li",null,[o("Added a large number of "),e("code",null,"android"),o(" types in "),e("code",null,"type"),o(" and a small number of "),e("code",null,"java"),o(" types")]),e("li",null,"Fix compatibility issues between new and old Kotlin APIs")],-1),oi={id:"_1-0-5-2022-03-18",tabindex:"-1"},ti=e("a",{class:"header-anchor",href:"#_1-0-5-2022-03-18","aria-hidden":"true"},"#",-1),di=o(" 1.0.5 | 2022.03.18 \u2002"),ii=n("YukiHookModulePrefs
being ignored every time after using direct
once to ignore cacheisActive
to judge module activationField
ReflectionUtils
YukiHookModuleStatus
method name confusion to reduce the size of module generation
",1),ni={id:"_1-0-4-2022-03-06",tabindex:"-1"},ci=e("a",{class:"header-anchor",href:"#_1-0-4-2022-03-06","aria-hidden":"true"},"#",-1),si=o(" 1.0.4 | 2022.03.06 \u2002"),ai=n("onInit
method to configure YukiHookAPI
executorName
and executorVersion
to get the name and version number of the current hook frameworkby
method to set the timing and condition of HookYukiHookModulePrefs
adds a controllable key-value cache, which can dynamically update data when the host is running
",1),li={id:"_1-0-3-2022-03-02",tabindex:"-1"},ri=e("a",{class:"header-anchor",href:"#_1-0-3-2022-03-02","aria-hidden":"true"},"#",-1),hi=o(" 1.0.3 | 2022.03.02 \u2002"),ui=n("XposedBridge
after enabling "Only module classloader can use Xposed API" option in latest versionYukiHookAPI
hasField
method and isAllowPrintingLogs
configuration parameterisDebug
to enable the API to automatically print the welcome message to test whether the module is valid
",1),_i={id:"_1-0-2-2022-02-18",tabindex:"-1"},mi=e("a",{class:"header-anchor",href:"#_1-0-2-2022-02-18","aria-hidden":"true"},"#",-1),pi=o(" 1.0.2 | 2022.02.18 \u2002"),fi=e("ul",null,[e("li",null,"Fix the problem that the project path cannot be found under Windows"),e("li",null,[o("Remove part of reflection API, merge into "),e("code",null,"BaseFinder"),o(" for integration")]),e("li",null,"Add a method to create Hook directly using string")],-1),gi={id:"_1-0-1-2022-02-15",tabindex:"-1"},ki=e("a",{class:"header-anchor",href:"#_1-0-1-2022-02-15","aria-hidden":"true"},"#",-1),bi=o(" 1.0.1 | 2022.02.15 \u2002"),yi=e("ul",null,[e("li",null,[e("code",null,"RemedyPlan"),o(" adds "),e("code",null,"onFind"),o(" function")]),e("li",null,"Integrate and modify some reflection API code"),e("li",null,[o("Added "),e("code",null,"java"),o(" type in "),e("code",null,"type")]),e("li",null,"Fixed the issue that ignored errors still output in the console")],-1),xi={id:"_1-0-2022-02-14",tabindex:"-1"},vi=e("a",{class:"header-anchor",href:"#_1-0-2022-02-14","aria-hidden":"true"},"#",-1),wi=o(" 1.0 | 2022.02.14 \u2002"),Ai=e("ul",null,[e("li",null,"The first version is submitted to Maven")],-1);function Hi(Pi,Fi){const d=c("Badge"),i=c("ExternalLinkIcon");return a(),l("div",null,[h,e("h3",u,[_,m,t(d,{type:"tip",text:"latest",vertical:"middle"})]),e("ul",null,[p,e("li",null,[f,e("a",g,[k,t(i)])]),b,e("li",null,[y,e("a",x,[v,t(i)]),w]),A,e("li",null,[H,P,F,C,M,I,e("a",R,[S,t(i)]),Y]),X,e("li",null,[T,z,L,e("a",W,[D,t(i)]),j]),e("li",null,[B,N,O,e("a",U,[q,t(i)]),E]),V,e("li",null,[K,Z,G,J,Q,e("a",$,[ee,t(i)]),oe,e("a",te,[de,t(i)])]),ie,ne,ce,e("li",null,[se,ae,le,re,he,e("a",ue,[_e,t(i)]),me]),pe,e("li",null,[fe,ge,ke,e("a",be,[ye,t(i)]),xe,e("a",ve,[we,t(i)])]),Ae,He,Pe,Fe]),e("h3",Ce,[Me,Ie,t(d,{type:"warning",text:"stale",vertical:"middle"})]),Re,e("h3",Se,[Ye,Xe,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),e("ul",null,[e("li",null,[Te,ze,Le,e("a",We,[De,t(i)]),je]),Be]),e("h3",Ne,[Oe,Ue,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),qe,e("h3",Ee,[Ve,Ke,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),Ze,e("h3",Ge,[Je,Qe,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),$e,e("h3",eo,[oo,to,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),io,e("h3",no,[co,so,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),ao,e("h3",lo,[ro,ho,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),uo,e("h3",_o,[mo,po,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),fo,e("h3",go,[ko,bo,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),yo,e("h3",xo,[vo,wo,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),Ao,e("h3",Ho,[Po,Fo,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),e("ul",null,[Co,e("li",null,[Mo,Io,Ro,e("a",So,[Yo,t(i)]),Xo]),To,zo,Lo]),e("h3",Wo,[Do,jo,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),e("ul",null,[Bo,e("li",null,[No,Oo,Uo,e("a",qo,[Eo,t(i)]),Vo]),Ko,Zo]),e("h3",Go,[Jo,Qo,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),e("ul",null,[e("li",null,[$o,et,ot,tt,e("a",dt,[it,t(i)]),nt]),ct]),e("h3",st,[at,lt,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),e("ul",null,[e("li",null,[rt,e("a",ht,[ut,t(i)]),_t]),mt]),e("h3",pt,[ft,gt,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),e("ul",null,[e("li",null,[kt,e("a",bt,[yt,t(i)]),xt]),e("li",null,[vt,wt,At,e("a",Ht,[Pt,t(i)]),Ft]),Ct]),e("h3",Mt,[It,Rt,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),St,e("h3",Yt,[Xt,Tt,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),zt,e("h3",Lt,[Wt,Dt,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),e("ul",null,[jt,e("li",null,[Bt,Nt,Ot,e("a",Ut,[qt,t(i)]),Et]),Vt,Kt,Zt,Gt,e("li",null,[Jt,Qt,$t,e("a",ed,[od,t(i)]),td]),e("li",null,[dd,e("a",id,[nd,t(i)]),cd]),sd,e("li",null,[ad,ld,rd,e("a",hd,[ud,t(i)]),_d]),md,pd,e("li",null,[fd,e("a",gd,[kd,t(i)]),bd])]),e("h3",yd,[xd,vd,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),e("ul",null,[wd,Ad,e("li",null,[Hd,Pd,Fd,e("a",Cd,[Md,t(i)]),Id])]),e("h3",Rd,[Sd,Yd,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),Xd,e("h3",Td,[zd,Ld,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),Wd,e("h3",Dd,[jd,Bd,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),Nd,e("h3",Od,[Ud,qd,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),Ed,e("h3",Vd,[Kd,Zd,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),Gd,e("h3",Jd,[Qd,$d,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),ei,e("h3",oi,[ti,di,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),ii,e("h3",ni,[ci,si,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),ai,e("h3",li,[ri,hi,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),ui,e("h3",_i,[mi,pi,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),fi,e("h3",gi,[ki,bi,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),yi,e("h3",xi,[vi,wi,t(d,{type:"danger",text:"outdate",vertical:"middle"})]),Ai])}const Mi=s(r,[["render",Hi],["__file","changelog.html.vue"]]);export{Mi as default};
diff --git a/docs/assets/changelog.html.576ee237.js b/docs/assets/changelog.html.576ee237.js
new file mode 100644
index 00000000..b5880cf0
--- /dev/null
+++ b/docs/assets/changelog.html.576ee237.js
@@ -0,0 +1 @@
+import{_ as s,r as l,o as n,c as a,b as e,d,e as o,a as t}from"./app.fb8271cf.js";const r={},_=e("h1",{id:"\u66F4\u65B0\u65E5\u5FD7",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#\u66F4\u65B0\u65E5\u5FD7","aria-hidden":"true"},"#"),o(" \u66F4\u65B0\u65E5\u5FD7")],-1),h=e("blockquote",null,[e("p",null,[o("\u8FD9\u91CC\u8BB0\u5F55\u4E86 "),e("code",null,"YukiHookAPI"),o(" \u7684\u7248\u672C\u66F4\u65B0\u5386\u53F2\u3002")])],-1),u=e("div",{class:"custom-container danger"},[e("p",{class:"custom-container-title"},"\u7279\u522B\u6CE8\u610F"),e("p",null,"\u6211\u4EEC\u53EA\u4F1A\u5BF9\u6700\u65B0\u7684 API \u7248\u672C\u8FDB\u884C\u7EF4\u62A4\uFF0C\u82E5\u4F60\u6B63\u5728\u4F7F\u7528\u8FC7\u65F6\u7684 API \u7248\u672C\u5219\u4EE3\u8868\u4F60\u81EA\u613F\u653E\u5F03\u4E00\u5207\u7EF4\u62A4\u7684\u53EF\u80FD\u6027\u3002")],-1),k={id:"_1-1-0-2022-09-28",tabindex:"-1"},p=e("a",{class:"header-anchor",href:"#_1-1-0-2022-09-28","aria-hidden":"true"},"#",-1),g=o(" 1.1.0 | 2022.09.28 \u2002"),f=e("li",null,[o("\u8FD9\u662F\u4E00\u6B21\u5927\u7248\u672C\u66F4\u65B0\uFF0C\u6709\u5173\u66F4\u65B0\u65E5\u5FD7\u4E2D\u63D0\u5230\u7684\u53D8\u5316\u53CA\u7528\u6CD5\u8BF7\u53C2\u8003 "),e("a",{href:"../api/home"},"API \u6587\u6863"),o(" \u4EE5\u53CA "),e("a",{href:"../api/special-features/reflection"},"\u7279\u8272\u529F\u80FD")],-1),m=o("\u66F4\u6362\u5E2E\u52A9\u6587\u6863\u6846\u67B6\u5230 "),H={href:"https://v2.vuepress.vuejs.org",target:"_blank",rel:"noopener noreferrer"},P=o("VuePress"),b=t("ignoredError
functionandroid
type in type
ClassNotFound
function after listening to hook
XposedHelper
\u62FC\u5199\u9519\u8BEF\u4FEE\u6539\u4E3A\u4E86 XposedHelpers
Class
\u4E0E Method
\u8F6C\u4E3A Java \u4EE5\u63D0\u4F9B\u66F4\u597D\u7684\u6F14\u793A\u6548\u679CHookParamWrapper
\uFF0C\u73B0\u5DF2\u5C06\u5176\u76F4\u63A5\u4E0E YukiBridgeFactory
\u5BF9\u63A5YukiHookBridge
\u4E2D\u7684\u65B9\u6CD5\u5230 AppParasitics
HookParam.args
\u4E0E\u5E95\u5C42\u7684\u76F4\u63A5\u5BF9\u63A5\u65B9\u6CD5 setArgs
\uFF0C\u76F4\u63A5\u83B7\u53D6\u5E76\u8BBE\u7F6E\u5F53\u524D\u6570\u7EC4\u7684\u5BF9\u8C61jar
\u5408\u5E76\u5230 stub
\u9879\u76EECreater
\u547D\u540D\u5230 Creator
YukiHookAPI.Status.compiledTimestamp
\u529F\u80FD\uFF0C\u53EF\u4EE5\u5728\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u65F6\u83B7\u53D6\u7F16\u8BD1\u5B8C\u6210\u7684\u65F6\u95F4\u6233YukiHookAPI.Status.isXposedEnvironment
\u529F\u80FD\uFF0C\u53EF\u4EE5\u5224\u65AD\u5F53\u524D\u4E3A (Xposed) \u5BBF\u4E3B\u73AF\u5883\u8FD8\u662F\u6A21\u5757\u73AF\u5883YukiHookAPI.Configs.debugTag
\u7B49\u529F\u80FD\u5408\u5E76\u5230 YukiHookLogger.Configs
\u4E2DXposedBridge.log
\u6216 Logd
debugLog
\u914D\u7F6E\u4E2D\u81EA\u884C\u66F4\u6539generic
\u529F\u80FD\uFF0C\u53EF\u5BF9\u6CDB\u578B\u8FDB\u884C\u53CD\u5C04\u548C\u8C03\u7528\uFF0C\u4F60\u53EF\u4EE5\u5728 Class
\u6216 CurrentClass
\u4E2D\u4F7F\u7528\u5B83buildOfAny
\u65B9\u6CD5\uFF0C\u73B0\u5728\u8BF7\u76F4\u63A5\u4F7F\u7528 buildOf
\u65B9\u6CD5 (\u4E0D\u5E26\u6CDB\u578B) \u6765\u4F7F\u7528\u6784\u9020\u65B9\u6CD5\u521B\u5EFA\u65B0\u5BF9\u8C61\u5E76\u5F97\u5230\u7ED3\u679C Any
hasExtends
\u4F7F\u7528\u8FC7\u7A0B\u53D1\u751F\u7A7A\u6307\u9488\u5F02\u5E38\u7684\u95EE\u9898CurrentClass
\u65B0\u589E\u975E lambda
\u65B9\u5F0F\u7684\u8C03\u7528\u65B9\u6CD5CurrentClass
\u65B0\u589E name
\u4E0E simpleName
\u529F\u80FDReflectionTool
\u7684\u6838\u5FC3\u65B9\u6CD5\uFF0C\u5C06\u4E0D\u540C\u7684\u67E5\u627E\u6761\u4EF6\u8FDB\u884C\u4E86\u6574\u7406\u5206\u7C7BReflectionTool
\u4E2D\u53EF\u80FD\u7684\u76F4\u63A5\u8C03\u7528 declared
\u83B7\u53D6\u7684 Member
\u629B\u51FA\u5F02\u5E38\u7684\u95EE\u9898ReflectionTool
\u4E2D UndefinedType
\u672A\u5728 Method
\u4E0E Constructor
\u6761\u4EF6\u4E2D\u6B63\u786E\u5224\u65AD\u7684\u95EE\u9898Member
\u7684\u95EE\u9898Method
\u3001Constructor
\u4E2D\u65B0\u589E VagueType
\u6761\u4EF6\uFF0C\u53EF\u4F7F\u7528\u5728 param
\u6761\u4EF6\u4E2D\u7528\u4E8E\u5FFD\u7565\u4F60\u4E0D\u60F3\u586B\u5199\u7684\u53C2\u6570Method
\u3001Constructor
\u4E2D\u65B0\u589E paramCount { ... }
\u6761\u4EF6\uFF0C\u73B0\u5728\u4F60\u53EF\u4EE5\u76F4\u63A5\u62FF\u5230\u5176\u4E2D\u7684 it
\u6765\u81EA\u5B9A\u4E49\u4F60\u7684\u5224\u65AD\u6761\u4EF6FieldFinder
\u7ED3\u679C\u4E2D\u65B0\u589E current
\u65B9\u6CD5\uFF0C\u53EF\u76F4\u63A5\u5BF9\u7ED3\u679C\u5B9E\u4F8B\u521B\u5EFA\u8C03\u7528\u7A7A\u95F4modifiers
\u6761\u4EF6\u4EE5\u53CA name
\u6761\u4EF6\uFF0C\u73B0\u5728\u4F60\u9700\u8981\u5BF9\u6B64\u65B9\u6CD5\u4F53\u7ED3\u5C3E\u8FD4\u56DE\u4E00\u4E2A Boolean
\u4EE5\u4F7F\u6761\u4EF6\u6210\u7ACBFieldFinder
\u4E2D\u65B0\u589E RemedyPlan
\u529F\u80FDDex
\u4E2D\u7684 Class
\u6A21\u7CCA\u67E5\u627E\u529F\u80FD (Beta)\uFF0C\u4F60\u73B0\u5728\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 searchClass
\u529F\u80FD\u6765\u4F7F\u7528\u6307\u5B9A\u6761\u4EF6\u6A21\u7CCA\u67E5\u627E Class
YukiHookAPI.Configs.isEnableHookSharedPreferences
\u529F\u80FD\uFF0C\u9ED8\u8BA4\u5173\u95ED\uFF0C\u82E5 SharedPreferences
\u7684\u6743\u9650\u9519\u8BEF\u53EF\u8FDB\u884C\u542F\u7528Constructor
\u65F6\u65E0\u53C2\u6784\u9020\u65B9\u6CD5\u5728\u4E0D\u586B\u5199\u67E5\u627E\u6761\u4EF6\u65F6\u65E0\u6CD5\u627E\u5230\u7684 BUG\uFF0C\u611F\u8C22 B5 KAKA \u7684\u53CD\u9988injectMember
\u4E2D method
\u3001constructor
\u7684 Result
\u5B9E\u4F8B\u5230 Process
useDangerousOperation
\u65B9\u6CD5\uFF0C\u672A\u8FDB\u884C\u58F0\u660E\u65F6\u5728 Hook \u5371\u9669\u5217\u8868\u4E2D\u7684\u529F\u80FD\u540E\u4F1A\u81EA\u52A8\u505C\u6B62 Hook \u5E76\u6253\u5370\u9519\u8BEFActivity
\u4EE3\u7406\u529F\u80FD\uFF0C\u4F60\u53EF\u4EE5\u8C03\u7528 injectModuleAppResources
\u53CA registerModuleAppActivities
\u6765\u4F7F\u7528ModuleContextThemeWrapper
\u529F\u80FD\uFF0C\u4F60\u53EF\u4EE5\u8C03\u7528 applyModuleTheme
\u5728\u4EFB\u610F Activity
\u4E2D\u521B\u5EFA\u6A21\u5757\u7684 Context
ClassLoader.onLoadClass
\u529F\u80FD\uFF0C\u53EF\u7528\u4E8E\u76D1\u542C ClassLoader
\u7684 loadClass
\u65B9\u6CD5\u88AB\u8C03\u7528\u7684\u4E8B\u4EF6classOf
\u4E0E clazz
\u6269\u5C55\u65B9\u6CD5\uFF0C\u65B0\u589E toClass
\u4EE5\u53CA toClassOrNull
\u7528\u6CD5\uFF0C\u8BF7\u73B0\u5728\u8F6C\u79FB\u5230\u65B0\u7684\u65B9\u6CD5VariousClass
\u65B0\u589E getOrNull
\u65B9\u6CD5\uFF0C\u53EF\u5728\u5339\u914D\u4E0D\u5230 Class
\u7684\u65F6\u5019\u4E0D\u629B\u51FA\u5F02\u5E38\u800C\u662F\u8FD4\u56DE null
PackageParam.hook
\u4E2D\u79FB\u9664\u4E86 isUseAppClassLoader
\u53C2\u6570\uFF0C\u4FEE\u6539\u4E3A isForceUseAbsolute
\u5E76\u81EA\u52A8\u5339\u914D\u76EE\u6807 Class
PackageParam
\u65B0\u589E systemContext
\u529F\u80FD\uFF0C\u4F60\u53EF\u4EE5\u5728\u4EFB\u610F\u65F6\u95F4\u8C03\u7528\u6B64\u529F\u80FD\u83B7\u53D6\u4E00\u4E2A\u6301\u4E45\u5316\u7684 Context
HookClass
\u4E2D\u7684\u4EFB\u4F55\u65B9\u6CD5HookParam
\u4E2D\u65B0\u589E throwToApp
\u529F\u80FD\uFF0C\u53EF\u5C06\u5F02\u5E38\u76F4\u63A5\u629B\u7ED9\u5BBF\u4E3BonFailureThrowToApp
\u529F\u80FD\uFF0C\u53EF\u5728\u53D1\u751F\u5F02\u5E38\u65F6\u76F4\u63A5\u629B\u7ED9\u5BBF\u4E3Bremove
\u53CA removeSelf
\u65B9\u6CD5\u89E3\u9664 Hook
",1),Be={id:"_1-0-91-2022-05-29",tabindex:"-1"},Le=e("a",{class:"header-anchor",href:"#_1-0-91-2022-05-29","aria-hidden":"true"},"#",-1),We=o(" 1.0.91 | 2022.05.29 \u2002"),Ue=o("\u4FEE\u590D\u90E8\u5206\u8BBE\u5907\u7684\u5B9A\u5236\u7CFB\u7EDF\u5728 LSPosed \u73AF\u5883\u4E0B\u5F00\u673A\u542F\u52A8\u83B7\u53D6\u7684 "),De=e("code",null,"ClassLoader",-1),Ge=o(" \u9519\u8BEF\u7684\u95EE\u9898\uFF0C\u611F\u8C22 "),Te={href:"https://github.com/luckyzyx",target:"_blank",rel:"noopener noreferrer"},Ne=o("Luckyzyx"),Ee=o(" \u7684\u53CD\u9988"),je=t("YukiHookDataChannel
\u5728\u4F4E\u4E8E Android 12 \u7684\u8BBE\u5907\u4E0A\u4E0D\u80FD\u56DE\u8C03\u5F53\u524D Activity
\u5E7F\u64AD\u7684\u95EE\u9898InjectYukiHookWithXposed
\u6CE8\u89E3\u65B0\u589E isUsingResourcesHook
\u529F\u80FD\uFF0C\u73B0\u5728\u4F60\u53EF\u4EE5\u9009\u62E9\u6027\u5173\u95ED\u81EA\u52A8\u751F\u6210 IXposedHookInitPackageResources
\u7684\u4F9D\u8D56\u63A5\u53E3\u4E86YukiHookDataChannel
\u5728 ZUI \u4EE5\u53CA\u4F4E\u4E8E Android 12 \u7684\u7CFB\u7EDF\u4E0A\u4E0D\u80FD\u56DE\u8C03\u5F53\u524D Activity
\u5E7F\u64AD\u7684\u95EE\u9898YukiHookModuleStatus
\u529F\u80FD\u5230 YukiHookAPI.Status
\uFF0C\u91CD\u5199\u4E86\u5927\u91CF\u65B9\u6CD5\uFF0C\u73B0\u5728\u4F60\u53EF\u4EE5\u5728\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E2D\u53CC\u5411\u5224\u65AD\u6A21\u5757\u6FC0\u6D3B\u7B49\u72B6\u6001\u4FE1\u606F
",1),Ke={id:"_1-0-89-2022-05-26",tabindex:"-1"},Oe=e("a",{class:"header-anchor",href:"#_1-0-89-2022-05-26","aria-hidden":"true"},"#",-1),Je=o(" 1.0.89 | 2022.05.26 \u2002"),qe=t("YukiHookDataChannel
\u5728\u6A21\u5757\u8BBE\u7F6E\u76D1\u542C\u56DE\u8C03\u65F6\u95EA\u9000\u7684\u95EE\u9898YukiHookDataChannel
\u5728\u975E\u5F53\u524D Activity
\u60C5\u51B5\u4E0B\u4F9D\u7136\u4F1A\u56DE\u8C03\u7684\u95EE\u9898YukiHookDataChannel
\u56DE\u8C03\u4E8B\u4EF6\u7684\u9ED8\u8BA4\u503C\uFF0C\u6CA1\u6709\u5373\u4E0D\u56DE\u8C03YukiHookModulePrefs
\u5728 XShare \u4E0D\u53EF\u8BFB\u7684\u60C5\u51B5\u4E0B\u6253\u5370\u7684\u8B66\u544AYukiHookModulePrefs
\u4E2D\u7684 isXSharePrefsReadable
\u65B9\u6CD5\uFF0C\u53EF\u5224\u65AD\u5F53\u524D\u7684 XShare \u662F\u5426\u53EF\u7528
",1),Qe={id:"_1-0-88-2022-05-25",tabindex:"-1"},$e=e("a",{class:"header-anchor",href:"#_1-0-88-2022-05-25","aria-hidden":"true"},"#",-1),eo=o(" 1.0.88 | 2022.05.25 \u2002"),oo=t("YukiHookDataChannel
\u4E0D\u80FD\u91CD\u590D\u8BBE\u7F6E\u76D1\u542C\u7684\u95EE\u9898\uFF0C\u5E76\u52A0\u5165\u5728\u6A21\u5757\u4E0D\u540C Activity
\u4E2D\u91CD\u590D\u54CD\u5E94\u548C\u81EA\u52A8\u8DDF\u968F Activity
\u9500\u6BC1\u76D1\u542C\u529F\u80FDYukiHookDataChannel
\u91CD\u590D\u76D1\u542C\u7528\u4F8B\u8BF4\u660E\u6587\u6863onAlreadyHooked
\u65B9\u6CD5\uFF0C\u53EF\u5224\u65AD\u5F53\u524D\u65B9\u6CD5\u662F\u5426\u88AB\u91CD\u590D HookputIfAbsent
\u65B9\u6CD5\uFF0C\u5141\u8BB8\u8986\u76D6\u6DFB\u52A0
",1),co={id:"_1-0-87-2022-05-10",tabindex:"-1"},io=e("a",{class:"header-anchor",href:"#_1-0-87-2022-05-10","aria-hidden":"true"},"#",-1),to=o(" 1.0.87 | 2022.05.10 \u2002"),lo=e("ul",null,[e("li",null,[o("\u65B0\u589E "),e("code",null,"refreshModuleAppResources"),o(" \u529F\u80FD\uFF0C\u4EE5\u9002\u914D\u8BED\u8A00\u533A\u57DF\u3001\u5B57\u4F53\u5927\u5C0F\u3001\u5206\u8FA8\u7387\u6539\u53D8\u7B49\u60C5\u51B5\u4E0B\u7684 Resources \u5237\u65B0")]),e("li",null,[o("\u65B0\u589E "),e("code",null,"isEnableModuleAppResourcesCache"),o(" \u529F\u80FD\uFF0C\u53EF\u81EA\u884C\u8BBE\u7F6E\u662F\u5426\u81EA\u52A8\u7F13\u5B58\u5F53\u524D\u6A21\u5757\u7684 Resources")])],-1),so={id:"_1-0-86-2022-05-06",tabindex:"-1"},no=e("a",{class:"header-anchor",href:"#_1-0-86-2022-05-06","aria-hidden":"true"},"#",-1),ao=o(" 1.0.86 | 2022.05.06 \u2002"),ro=e("ul",null,[e("li",null,[o("\u4FEE\u590D\u4E0D\u652F\u6301 Resources Hook(\u8D44\u6E90\u94A9\u5B50) \u7684\u60C5\u51B5\u4E0B\u5728 "),e("code",null,"initZygote"),o(" \u65F6\u6301\u7EED\u62A5\u9519\u7684\u95EE\u9898\uFF0C\u590D\u73B0\u5728 "),e("strong",null,"ZUI"),o("/"),e("strong",null,"LSPosed CI(1.8.3-6550)")]),e("li",null,"\u4F18\u5316\u5E76\u5BF9 Resources Hook \u8FDB\u884C\u5F02\u5E38\u5904\u7406\uFF0C\u53EA\u6709\u88AB\u4F7F\u7528\u540E\u4E0D\u652F\u6301\u624D\u4F1A\u6253\u5370\u9519\u8BEF\u548C\u8B66\u544A")],-1),_o={id:"_1-0-85-2022-05-04",tabindex:"-1"},ho=e("a",{class:"header-anchor",href:"#_1-0-85-2022-05-04","aria-hidden":"true"},"#",-1),uo=o(" 1.0.85 | 2022.05.04 \u2002"),ko=t("type
\u4E2D\u7684 android
\u7C7B\u578BYukiHookModuleStatus
\u4ECE\u81EA\u52A8\u751F\u6210\u4EE3\u7801\u4E2D\u5206\u79BB\uFF0C\u5E76\u52A0\u5165 isEnableHookModuleStatus
\u7684\u5F00\u5173\uFF0C\u7531\u4F60\u51B3\u5B9A\u662F\u5426\u542F\u7528YukiHookModulePrefs
\u8BBE\u7F6E\u4E3A\u5355\u4F8B\u8FD0\u884C\uFF0C\u9632\u6B62\u91CD\u590D\u521B\u5EFA\u6D6A\u8D39\u7CFB\u7EDF\u8D44\u6E901.0.80
\u7248\u672C\u540E\u65E0\u6CD5\u5D4C\u5957 Hook \u7684 BUG\uFF0C\u5E76\u4F18\u5316\u5D4C\u5957 Hook \u76F8\u5173\u529F\u80FDHookParam
\u65B9\u6CD5MethodFinder
\u4E0E FieldFinder
\u52A0\u5165\u67E5\u627E\u6A21\u7CCA\u65B9\u6CD5\u3001\u53D8\u91CF\u540D\u79F0\u529F\u80FD\uFF0C\u53EF\u8C03\u7528 name { ... }
\u6765\u8BBE\u7F6E\u67E5\u627E\u6761\u4EF6\uFF0C\u652F\u6301\u6B63\u5219appContext
\u7684\u83B7\u53D6\u65B9\u5F0F\uFF0C\u964D\u4F4E\u4F1A\u53D6\u5230\u7A7A\u7684\u95EE\u9898\u7684\u53EF\u80FD\u6027logger
\u7684\u6253\u5370 TAG
\u9ED8\u8BA4\u4E3A\u4F60\u81EA\u5B9A\u4E49\u7684\u540D\u79F0\uFF0C\u65B9\u4FBF\u8FDB\u884C\u8C03\u8BD5YukiHookBridge
\u7684 Hooker
\u5B9E\u73B0\u65B9\u5F0F\uFF0C\u63D0\u5347 Hook \u6027\u80FDPackageParam
\u589E\u52A0 onAppLifecycle
\u65B9\u6CD5\uFF0C\u53EF\u539F\u751F\u76D1\u542C\u5BBF\u4E3B\u7684\u751F\u547D\u5468\u671F\u4EE5\u53CA\u5B9E\u73B0\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\u529F\u80FDYukiHookDataChannel
\u529F\u80FD\uFF0C\u53EF\u5728\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4FDD\u6301\u5B58\u6D3B\u7684\u60C5\u51B5\u4E0B\u4F7F\u7528\u7CFB\u7EDF\u65E0\u5E8F\u5E7F\u64AD\u8FDB\u884C\u901A\u8BAFYukiHookDataChannel
\u589E\u52A0 checkingVersionEquals
\u65B9\u6CD5\uFF0C\u53EF\u901A\u8FC7\u76D1\u542C\u6765\u9A8C\u8BC1\u6A21\u5757\u66F4\u65B0\u540E\u5BBF\u4E3B\u5E76\u672A\u66F4\u65B0\u7248\u672C\u4E0D\u5339\u914D\u95EE\u9898demo-module
\u7684\u793A\u4F8B\u4EE3\u7801\u4E2D\u65B0\u589E Java \u7248\u672C\u7684\u793A\u4F8B\uFF0C\u4EC5\u4F9B\u53C2\u8003
",1),po={id:"_1-0-83-2022-05-04",tabindex:"-1"},go=e("a",{class:"header-anchor",href:"#_1-0-83-2022-05-04","aria-hidden":"true"},"#",-1),fo=o(" 1.0.83 | 2022.05.04 \u2002"),mo=e("ul",null,[e("li",null,[o("\u4FEE\u590D "),e("code",null,"YukiHookModuleStatus"),o(" \u5728 "),e("code",null,"loadSystem"),o(" \u540E\u5927\u91CF\u62A5\u9519\u7684\u95EE\u9898")]),e("li",null,[o("\u65B0\u589E "),e("code",null,"type"),o(" \u4E2D\u7684 "),e("code",null,"android"),o(" \u7C7B\u578B")]),e("li",null,"\u66F4\u65B0\u5E2E\u52A9\u6587\u6863\u7684\u793A\u4F8B\u8BF4\u660E")],-1),Ho={id:"_1-0-82-2022-05-04",tabindex:"-1"},Po=e("a",{class:"header-anchor",href:"#_1-0-82-2022-05-04","aria-hidden":"true"},"#",-1),bo=o(" 1.0.82 | 2022.05.04 \u2002"),xo=e("ul",null,[e("li",null,[o("\u4FEE\u590D\u4E86\u4E00\u5904\u6982\u5FF5\u6DF7\u6DC6\u9519\u8BEF\uFF0C\u533A\u5206 "),e("code",null,"initZygote"),o(" \u4E0E\u7CFB\u7EDF\u6846\u67B6\u7684\u5173\u7CFB\uFF0C\u4E4B\u524D\u7684\u6CE8\u91CA\u548C\u6587\u6863\u6709\u95EE\u9898\uFF0C\u975E\u5E38\u62B1\u6B49")]),e("li",null,[e("code",null,"PackageParam"),o(" \u65B0\u589E "),e("code",null,"loadSystem"),o(" \u65B9\u6CD5\uFF0C\u4E0D\u9700\u8981\u518D\u5199 "),e("code",null,'loadApp(name = "android")'),o(" \u5373\u53EF Hook \u7CFB\u7EDF\u6846\u67B6")])],-1),yo={id:"_1-0-81-2022-05-04",tabindex:"-1"},Ao=e("a",{class:"header-anchor",href:"#_1-0-81-2022-05-04","aria-hidden":"true"},"#",-1),Co=o(" 1.0.81 | 2022.05.04 \u2002"),vo=e("ul",null,[e("li",null,[o("\u4FEE\u590D\u4F7F\u7528 "),e("code",null,"by"),o(" \u65B9\u6CD5\u8BBE\u7F6E\u6761\u4EF6\u540E Hook \u65B9\u6CD5\u4F53\u5185\u67E5\u627E\u4E0D\u5230\u7684\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u4F9D\u7136\u8F93\u51FA\u9519\u8BEF\u65E5\u5FD7\u7684\u95EE\u9898")]),e("li",null,"\u5728\u6267\u884C Hook \u8FC7\u7A0B\u4E2D\u52A0\u5165\u5168\u5C40\u65E5\u5FD7\u663E\u793A\u5F53\u524D Hook APP \u7684\u5305\u540D\uFF0C\u5E76\u4FEE\u590D\u4E00\u5904\u9519\u8BEF\u65E5\u5FD7\u6253\u5370\u6837\u5F0F\u7684\u95EE\u9898")],-1),Mo={id:"_1-0-80-2022-05-01",tabindex:"-1"},Io=e("a",{class:"header-anchor",href:"#_1-0-80-2022-05-01","aria-hidden":"true"},"#",-1),Ro=o(" 1.0.80 | 2022.05.01 \u2002"),Yo=t("1.0.80
\u5F00\u59CB\u51FA\u73B0initZygote
\u88C5\u8F7D\u7684\u5305\u540D\u4E3A android-zygote
\uFF0CpackageName
\u4FDD\u6301 android
\u4E0D\u53D8InjectYukiHookWithXposed
\u6CE8\u89E3\u65B0\u589E entryClassName
\u529F\u80FD\uFF0C\u53EF\u81EA\u5B9A\u4E49\u751F\u6210\u7684 xposed_init
\u5165\u53E3\u7C7B\u540D \u66F4\u540D\u4E3A YukiHookXposedInitProxy
IYukiHookXposedInit
\uFF0C\u539F\u63A5\u53E3\u540D\u79F0\u5DF2\u4F5C\u5E9F\uFF0C\u5C06\u5728\u540E\u7EED\u7248\u672C\u4E2D\u76F4\u63A5\u88AB\u5220\u9664initZygote
\u4E0E Resources Hook \u529F\u80FD\uFF0C\u652F\u6301 Hook LayoutonXposedEvent
\u65B9\u6CD5\uFF0C\u53EF\u76D1\u542C\u539F\u751F Xposed API \u7684\u5168\u90E8\u4E8B\u4EF6lambda
\u8FDB\u884C inline
\u5904\u7406\uFF0C\u907F\u514D\u751F\u6210\u8FC7\u788E\u7684\u533F\u540D\u7C7B\uFF0C\u63D0\u5347\u7F16\u8BD1\u540E\u7684\u8FD0\u884C\u6027\u80FDPrefsData
\u7F16\u8BD1\u540E\u7684\u65B9\u6CD5\u4F53\u590D\u5236\u8FC7\u5927\u7684\u95EE\u9898XSharePreference
\u53EF\u8BFB\u6027\u6D4B\u8BD5\uFF0C\u5931\u8D25\u540E\u4F1A\u81EA\u52A8\u6253\u5370\u8B66\u544A\u65E5\u5FD7PackageParam
\u65B0\u589E appResources
\u3001moduleAppResources
\u3001moduleAppFilePath
\u529F\u80FDPackageParam
\u7684 loadApp
\u65B0\u589E\u4E0D\u5199 name
\u529F\u80FD\uFF0C\u9ED8\u8BA4\u7B5B\u9009\u5168\u90E8 APPPackageParam
\u65B0\u589E loadZygote
\u65B9\u6CD5\uFF0C\u53EF\u76F4\u63A5 Hook \u7CFB\u7EDF\u6846\u67B6PackageParam
\u65B0\u589E resources().hook
\u529F\u80FDhasExtends
\u6269\u5C55\u65B9\u6CD5\uFF0C\u53EF\u5224\u65AD\u5F53\u524D Class
\u662F\u5426\u6709\u7EE7\u627F\u5173\u7CFBisSupportResourcesHook
\u529F\u80FD\uFF0C\u5224\u65AD\u5F53\u524D\u662F\u5426\u652F\u6301\u8D44\u6E90\u94A9\u5B50(Resources Hook)current
\u529F\u80FD\u65B0\u589E superClass
\u65B9\u6CD5\u8C03\u7528\u7236\u7C7BsuperClass
\u67E5\u627E\u6761\u4EF6\uFF0C\u53EF\u7EE7\u7EED\u5728\u7236\u7C7B\u4E2D\u67E5\u627EYukiHookAPI
\u5927\u91CF\u65B9\u6CD5\u4E0E Xposed API \u89E3\u8026\u5408isFirstApplication
\u53EF\u80FD\u5224\u65AD\u4E0D\u51C6\u786E\u7684\u95EE\u9898YukiHookModulePrefs
\u65B0\u589E isRunInNewXShareMode
\u65B9\u6CD5\uFF0C\u53EF\u7528\u4E8E\u5224\u65AD\u6A21\u5757\u5F53\u524D\u662F\u5426\u5904\u4E8E New XSharePreference
\u6A21\u5F0FYukiHookModulePrefs
\u5728 New XSharePreference
\u6A21\u5F0F\u4E0B\u5DE5\u4F5C\u7684\u90E8\u5206\u95EE\u9898ModulePreferenceFragment
\uFF0C\u73B0\u5728\uFF0C\u4F60\u53EF\u4EE5\u5B8C\u5168\u66FF\u6362\u6389 PreferenceFragmentCompat
\u5E76\u5F00\u59CB\u4F7F\u7528\u65B0\u7684\u529F\u80FDYukiHookModulePrefs
\u65B0\u589E getStringSet
\u3001putStringSet
\u3001all
\u65B9\u6CD5HookParam
\u7684 args
\u589E\u52A0 any
\u65B9\u6CD5ModuleApplication
\uFF0C\u53EF\u5728\u6A21\u5757\u4E2D\u7EE7\u627F\u6B64\u7C7B\u5B9E\u73B0\u66F4\u591A\u529F\u80FDfindClass
\u529F\u80FD\u5230 Xposed API\uFF0C\u5728\u975E\u5BBF\u4E3B\u73AF\u5883\u7EE7\u7EED\u4F7F\u7528\u539F\u751F ClassLoader
HookParam
\u4E2D\u5220\u9664\u4E86 firstArgs
\u4E0E lastArgs
\u65B9\u6CD5\uFF0C\u73B0\u5728\u4F60\u53EF\u4EE5\u4F7F\u7528 args().first()
\u4E0E args().last()
\u6765\u53D6\u4EE3\u5B83HookParam
\u4E2D\u5220\u9664\u4E86 args()
\u4E2D\u7684\u9ED8\u8BA4\u53C2\u6570 index = 0
\uFF0C\u73B0\u5728\u4F60\u53EF\u4EE5\u4F7F\u7528 args().first()
\u6216 args(index = 0)
\u6765\u53D6\u4EE3\u5B83HookParam
\u4E2D result
\u529F\u80FD\u589E\u52A0\u4E86\u6CDB\u578B\u5339\u914D\uFF0C\u73B0\u5728\u4F60\u53EF\u4EE5\u4F7F\u7528 result<T>
\u6765\u5339\u914D\u4F60\u7684\u76EE\u6807\u65B9\u6CD5\u5DF2\u77E5\u8FD4\u56DE\u503C\u7C7B\u578B\u4E86emptyParam
\u6761\u4EF6\uFF0C\u5E76\u5B8C\u5584\u4E86\u6587\u6863\u76F8\u5173\u9700\u8981\u6CE8\u610F\u7684\u67E5\u627E\u6761\u4EF6\u8BEF\u533Atype
\u4E2D\u7684 android
\u7C7B\u578B
",1),Lc={id:"_1-0-67-2022-03-27",tabindex:"-1"},Wc=e("a",{class:"header-anchor",href:"#_1-0-67-2022-03-27","aria-hidden":"true"},"#",-1),Uc=o(" 1.0.67 | 2022.03.27 \u2002"),Dc=t("Member
\u67E5\u627E\u7F13\u5B58\u548C\u67E5\u627E\u7F13\u5B58\u914D\u7F6E\u5F00\u5173MethodFinder
\u3001FieldFinder
\u4EE5\u53CA HookParam
\u76F8\u5173\u65B9\u6CD5\u7684\u8C03\u7528Finder
\u4E2D\u7684 cast
\u7C7B\u578B\u5E76\u652F\u6301 cast
\u4E3A\u6570\u7EC4
",1),Gc={id:"_1-0-66-2022-03-25",tabindex:"-1"},Tc=e("a",{class:"header-anchor",href:"#_1-0-66-2022-03-25","aria-hidden":"true"},"#",-1),Nc=o(" 1.0.66 | 2022.03.25 \u2002"),Ec=e("ul",null,[e("li",null,[o("\u4FEE\u590D "),e("code",null,"MethodFinder"),o(" \u4E2D\u7684\u4E00\u4E2A\u4E25\u91CD\u95EE\u9898")]),e("li",null,[o("\u589E\u52A0 "),e("code",null,"hookParam"),o(" \u4E2D\u7684 "),e("code",null,"args"),o(" \u8C03\u7528\u65B9\u6CD5")]),e("li",null,"\u4FEE\u590D\u5176\u5B83\u53EF\u80FD\u5B58\u5728\u7684\u95EE\u9898\u4EE5\u53CA\u4FEE\u590D\u90E8\u5206\u7C7B\u7684\u6CE8\u91CA\u95EE\u9898")],-1),jc={id:"_1-0-65-2022-03-25",tabindex:"-1"},wc=e("a",{class:"header-anchor",href:"#_1-0-65-2022-03-25","aria-hidden":"true"},"#",-1),zc=o(" 1.0.65 | 2022.03.25 \u2002"),Vc=t("Finder
\u4E2D\u7684 modifiers
\u529F\u80FD\uFF0C\u53EF\u7B5B\u9009 static
\u3001native
\u3001public
\u3001abstract
\u7B49\u8BF8\u591A\u63CF\u8FF0\u7C7B\u578BMember
\u7684 hasModifiers
\u6269\u5C55\u529F\u80FDMethodFinder
\u548C ConstructorFinder
\u4E2D\u7684 give
\u65B9\u6CD5\uFF0C\u53EF\u83B7\u5F97\u539F\u59CB\u7C7B\u578BYukiHookModulePrefs
\u4E2D\u7684 PrefsData
\u6A21\u677F\u529F\u80FD
",1),Zc={id:"_1-0-6-2022-03-20",tabindex:"-1"},Kc=e("a",{class:"header-anchor",href:"#_1-0-6-2022-03-20","aria-hidden":"true"},"#",-1),Oc=o(" 1.0.6 | 2022.03.20 \u2002"),Jc=t("MethodFinder
\u4E0E FieldFinder
\u65B0\u7684\u8FD4\u56DE\u503C\u8C03\u7528\u65B9\u6CD5type
\u4E2D\u7684 android
\u7C7B\u578B\u4EE5\u53CA java
\u7C7B\u578B
",1),qc={id:"_1-0-55-2022-03-18",tabindex:"-1"},Qc=e("a",{class:"header-anchor",href:"#_1-0-55-2022-03-18","aria-hidden":"true"},"#",-1),$c=o(" 1.0.55 | 2022.03.18 \u2002"),ei=e("ul",null,[e("li",null,"\u4FEE\u6B63\u4E00\u5904\u6CE8\u91CA\u9519\u8BEF"),e("li",null,"\u4E34\u65F6\u4FEE\u590D\u4E00\u4E2A BUG"),e("li",null,[o("\u589E\u52A0\u4E86 "),e("code",null,"type"),o(" \u4E2D\u7684\u5927\u91CF "),e("code",null,"android"),o(" \u7C7B\u578B\u4EE5\u53CA\u5C11\u91CF "),e("code",null,"java"),o(" \u7C7B\u578B")]),e("li",null,"\u4FEE\u590D\u65B0\u7248\u4E0E\u65E7\u7248 Kotlin APIs \u7684\u517C\u5BB9\u6027\u95EE\u9898")],-1),oi={id:"_1-0-5-2022-03-18",tabindex:"-1"},di=e("a",{class:"header-anchor",href:"#_1-0-5-2022-03-18","aria-hidden":"true"},"#",-1),ci=o(" 1.0.5 | 2022.03.18 \u2002"),ii=t("YukiHookModulePrefs
\u5728\u4F7F\u7528\u4E00\u6B21 direct
\u5FFD\u7565\u7F13\u5B58\u540E\u6BCF\u6B21\u90FD\u5FFD\u7565\u7684 BUGisActive
\u5224\u65AD\u6A21\u5757\u6FC0\u6D3B\u7684\u4F20\u7EDF\u7528\u6CD5Field
\u65F6\u7684\u65E5\u5FD7\u8F93\u51FA\u95EE\u9898\u548C\u672A\u62E6\u622A\u7684\u5F02\u5E38\u95EE\u9898ReflectionUtils
\u4E2D\u7684 Xposed APIYukiHookModuleStatus
\u65B9\u6CD5\u540D\u79F0\u7684\u6DF7\u6DC6\uFF0C\u4EE5\u7CBE\u7B80\u6A21\u5757\u751F\u6210\u7684\u4F53\u79EF
",1),ti={id:"_1-0-4-2022-03-06",tabindex:"-1"},li=e("a",{class:"header-anchor",href:"#_1-0-4-2022-03-06","aria-hidden":"true"},"#",-1),si=o(" 1.0.4 | 2022.03.06 \u2002"),ni=t("onInit
\u65B9\u6CD5\u6765\u914D\u7F6E YukiHookAPI
executorName
\u548C executorVersion
\u6765\u83B7\u53D6\u5F53\u524D Hook \u6846\u67B6\u7684\u540D\u79F0\u548C\u7248\u672C\u53F7by
\u65B9\u6CD5\u6765\u8BBE\u7F6E Hook \u7684\u65F6\u673A\u548C\u6761\u4EF6YukiHookModulePrefs
\u65B0\u589E\u53EF\u63A7\u5236\u7684\u952E\u503C\u7F13\u5B58\uFF0C\u53EF\u5728\u5BBF\u4E3B\u8FD0\u884C\u65F6\u6A21\u5757\u52A8\u6001\u66F4\u65B0\u6570\u636E
",1),ai={id:"_1-0-3-2022-03-02",tabindex:"-1"},ri=e("a",{class:"header-anchor",href:"#_1-0-3-2022-03-02","aria-hidden":"true"},"#",-1),_i=o(" 1.0.3 | 2022.03.02 \u2002"),hi=t("XposedBridge
\u7684\u95EE\u9898YukiHookAPI
\u7684\u5E38\u91CF\u7248\u672C\u540D\u79F0\u548C\u7248\u672C\u53F7hasField
\u65B9\u6CD5\u4EE5\u53CA isAllowPrintingLogs
\u914D\u7F6E\u53C2\u6570isDebug
\u5F00\u542F\u7684\u60C5\u51B5\u4E0B API \u5C06\u81EA\u52A8\u6253\u5370\u6B22\u8FCE\u4FE1\u606F\u6D4B\u8BD5\u6A21\u5757\u662F\u5426\u751F\u6548
",1),ui={id:"_1-0-2-2022-02-18",tabindex:"-1"},ki=e("a",{class:"header-anchor",href:"#_1-0-2-2022-02-18","aria-hidden":"true"},"#",-1),pi=o(" 1.0.2 | 2022.02.18 \u2002"),gi=e("ul",null,[e("li",null,"\u4FEE\u590D Windows \u4E0B\u65E0\u6CD5\u627E\u5230\u9879\u76EE\u8DEF\u5F84\u7684\u95EE\u9898"),e("li",null,[o("\u79FB\u9664\u90E8\u5206\u53CD\u5C04 API\uFF0C\u5408\u5E76\u81F3 "),e("code",null,"BaseFinder"),o(" \u8FDB\u884C\u6574\u5408")]),e("li",null,"\u589E\u52A0\u76F4\u63A5\u4F7F\u7528\u5B57\u7B26\u4E32\u521B\u5EFA Hook \u7684\u65B9\u6CD5")],-1),fi={id:"_1-0-1-2022-02-15",tabindex:"-1"},mi=e("a",{class:"header-anchor",href:"#_1-0-1-2022-02-15","aria-hidden":"true"},"#",-1),Hi=o(" 1.0.1 | 2022.02.15 \u2002"),Pi=t("ignoredError
\u529F\u80FDtype
\u4E2D\u7684 android
\u7C7B\u578Bhook
\u540E\u7684 ClassNotFound
\u529F\u80FD
",1),bi={id:"_1-0-2022-02-14",tabindex:"-1"},xi=e("a",{class:"header-anchor",href:"#_1-0-2022-02-14","aria-hidden":"true"},"#",-1),yi=o(" 1.0 | 2022.02.14 \u2002"),Ai=e("ul",null,[e("li",null,"\u9996\u4E2A\u7248\u672C\u63D0\u4EA4\u81F3 Maven")],-1);function Ci(vi,Mi){const c=l("Badge"),i=l("ExternalLinkIcon");return n(),a("div",null,[_,h,u,e("h3",k,[p,g,d(c,{type:"tip",text:"\u6700\u65B0",vertical:"middle"})]),e("ul",null,[f,e("li",null,[m,e("a",H,[P,d(i)])]),b,e("li",null,[x,e("a",y,[A,d(i)]),C]),v,e("li",null,[M,I,R,Y,S,X,e("a",F,[B,d(i)]),L]),W,e("li",null,[U,D,G,e("a",T,[N,d(i)]),E]),e("li",null,[j,w,z,e("a",V,[Z,d(i)]),K]),O,e("li",null,[J,q,Q,$,ee,e("a",oe,[de,d(i)]),ce,e("a",ie,[te,d(i)])]),le,se,ne,e("li",null,[ae,re,_e,he,ue,e("a",ke,[pe,d(i)]),ge]),fe,e("li",null,[me,He,Pe,e("a",be,[xe,d(i)]),ye,e("a",Ae,[Ce,d(i)])]),ve,Me,Ie,Re]),e("h3",Ye,[Se,Xe,d(c,{type:"warning",text:"\u8FC7\u65E7",vertical:"middle"})]),Fe,e("h3",Be,[Le,We,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),e("ul",null,[e("li",null,[Ue,De,Ge,e("a",Te,[Ne,d(i)]),Ee]),je]),e("h3",we,[ze,Ve,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Ze,e("h3",Ke,[Oe,Je,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),qe,e("h3",Qe,[$e,eo,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),oo,e("h3",co,[io,to,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),lo,e("h3",so,[no,ao,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),ro,e("h3",_o,[ho,uo,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),ko,e("h3",po,[go,fo,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),mo,e("h3",Ho,[Po,bo,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),xo,e("h3",yo,[Ao,Co,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),vo,e("h3",Mo,[Io,Ro,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),e("ul",null,[Yo,e("li",null,[So,Xo,Fo,e("a",Bo,[Lo,d(i)]),Wo]),Uo,Do,Go]),e("h3",To,[No,Eo,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),e("ul",null,[jo,e("li",null,[wo,zo,Vo,e("a",Zo,[Ko,d(i)]),Oo]),Jo,qo]),e("h3",Qo,[$o,ed,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),e("ul",null,[e("li",null,[od,dd,cd,id,e("a",td,[ld,d(i)]),sd]),nd]),e("h3",ad,[rd,_d,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),e("ul",null,[e("li",null,[hd,e("a",ud,[kd,d(i)]),pd]),gd]),fd,e("ul",null,[e("li",null,[md,e("a",Hd,[Pd,d(i)]),bd]),e("li",null,[xd,yd,Ad,e("a",Cd,[vd,d(i)]),Md]),Id]),e("h3",Rd,[Yd,Sd,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Xd,e("h3",Fd,[Bd,Ld,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Wd,e("h3",Ud,[Dd,Gd,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),e("ul",null,[Td,e("li",null,[Nd,Ed,jd,e("a",wd,[zd,d(i)]),Vd]),Zd,Kd,Od,Jd,e("li",null,[qd,Qd,$d,e("a",ec,[oc,d(i)]),dc]),e("li",null,[cc,e("a",ic,[tc,d(i)]),lc]),sc,e("li",null,[nc,ac,rc,e("a",_c,[hc,d(i)]),uc]),kc,pc,e("li",null,[gc,e("a",fc,[mc,d(i)]),Hc])]),e("h3",Pc,[bc,xc,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),e("ul",null,[yc,Ac,e("li",null,[Cc,vc,Mc,e("a",Ic,[Rc,d(i)]),Yc])]),e("h3",Sc,[Xc,Fc,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Bc,e("h3",Lc,[Wc,Uc,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Dc,e("h3",Gc,[Tc,Nc,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Ec,e("h3",jc,[wc,zc,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Vc,e("h3",Zc,[Kc,Oc,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Jc,e("h3",qc,[Qc,$c,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),ei,e("h3",oi,[di,ci,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),ii,e("h3",ti,[li,si,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),ni,e("h3",ai,[ri,_i,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),hi,e("h3",ui,[ki,pi,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),gi,e("h3",fi,[mi,Hi,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Pi,e("h3",bi,[xi,yi,d(c,{type:"danger",text:"\u8FC7\u671F",vertical:"middle"})]),Ai])}const Ri=s(r,[["render",Ci],["__file","changelog.html.vue"]]);export{Ri as default};
diff --git a/docs/assets/changelog.html.86d916d5.js b/docs/assets/changelog.html.86d916d5.js
new file mode 100644
index 00000000..107e6e81
--- /dev/null
+++ b/docs/assets/changelog.html.86d916d5.js
@@ -0,0 +1 @@
+const l=JSON.parse('{"key":"v-3f851d14","path":"/en/about/changelog.html","title":"Changelog","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":3,"title":"1.1.0 | 2022.09.28","slug":"_1-1-0-2022-09-28","link":"#_1-1-0-2022-09-28","children":[]},{"level":3,"title":"1.0.92 | 2022.05.31","slug":"_1-0-92-2022-05-31","link":"#_1-0-92-2022-05-31","children":[]},{"level":3,"title":"1.0.91 | 2022.05.29","slug":"_1-0-91-2022-05-29","link":"#_1-0-91-2022-05-29","children":[]},{"level":3,"title":"1.0.90 | 2022.05.27","slug":"_1-0-90-2022-05-27","link":"#_1-0-90-2022-05-27","children":[]},{"level":3,"title":"1.0.89 | 2022.05.26","slug":"_1-0-89-2022-05-26","link":"#_1-0-89-2022-05-26","children":[]},{"level":3,"title":"1.0.88 | 2022.05.25","slug":"_1-0-88-2022-05-25","link":"#_1-0-88-2022-05-25","children":[]},{"level":3,"title":"1.0.87 | 2022.05.10","slug":"_1-0-87-2022-05-10","link":"#_1-0-87-2022-05-10","children":[]},{"level":3,"title":"1.0.86 | 2022.05.06","slug":"_1-0-86-2022-05-06","link":"#_1-0-86-2022-05-06","children":[]},{"level":3,"title":"1.0.85 | 2022.05.04","slug":"_1-0-85-2022-05-04","link":"#_1-0-85-2022-05-04","children":[]},{"level":3,"title":"1.0.83 | 2022.05.04","slug":"_1-0-83-2022-05-04","link":"#_1-0-83-2022-05-04","children":[]},{"level":3,"title":"1.0.82 | 2022.05.04","slug":"_1-0-82-2022-05-04","link":"#_1-0-82-2022-05-04","children":[]},{"level":3,"title":"1.0.81 | 2022.05.04","slug":"_1-0-81-2022-05-04","link":"#_1-0-81-2022-05-04","children":[]},{"level":3,"title":"1.0.80 | 2022.05.01","slug":"_1-0-80-2022-05-01","link":"#_1-0-80-2022-05-01","children":[]},{"level":3,"title":"1.0.78 | 2022.04.18","slug":"_1-0-78-2022-04-18","link":"#_1-0-78-2022-04-18","children":[]},{"level":3,"title":"1.0.77 | 2022.04.15","slug":"_1-0-77-2022-04-15","link":"#_1-0-77-2022-04-15","children":[]},{"level":3,"title":"1.0.75 | 2022.04.13","slug":"_1-0-75-2022-04-13","link":"#_1-0-75-2022-04-13","children":[]},{"level":3,"title":"1.0.73 | 2022.04.10","slug":"_1-0-73-2022-04-10","link":"#_1-0-73-2022-04-10","children":[]},{"level":3,"title":"1.0.72 | 2022.04.09","slug":"_1-0-72-2022-04-09","link":"#_1-0-72-2022-04-09","children":[]},{"level":3,"title":"1.0.71 | 2022.04.04","slug":"_1-0-71-2022-04-04","link":"#_1-0-71-2022-04-04","children":[]},{"level":3,"title":"1.0.70 | 2022.04.04","slug":"_1-0-70-2022-04-04","link":"#_1-0-70-2022-04-04","children":[]},{"level":3,"title":"1.0.69 | 2022.03.30","slug":"_1-0-69-2022-03-30","link":"#_1-0-69-2022-03-30","children":[]},{"level":3,"title":"1.0.68 | 2022.03.29","slug":"_1-0-68-2022-03-29","link":"#_1-0-68-2022-03-29","children":[]},{"level":3,"title":"1.0.67 | 2022.03.27","slug":"_1-0-67-2022-03-27","link":"#_1-0-67-2022-03-27","children":[]},{"level":3,"title":"1.0.66 | 2022.03.25","slug":"_1-0-66-2022-03-25","link":"#_1-0-66-2022-03-25","children":[]},{"level":3,"title":"1.0.65 | 2022.03.25","slug":"_1-0-65-2022-03-25","link":"#_1-0-65-2022-03-25","children":[]},{"level":3,"title":"1.0.6 | 2022.03.20","slug":"_1-0-6-2022-03-20","link":"#_1-0-6-2022-03-20","children":[]},{"level":3,"title":"1.0.55 | 2022.03.18","slug":"_1-0-55-2022-03-18","link":"#_1-0-55-2022-03-18","children":[]},{"level":3,"title":"1.0.5 | 2022.03.18","slug":"_1-0-5-2022-03-18","link":"#_1-0-5-2022-03-18","children":[]},{"level":3,"title":"1.0.4 | 2022.03.06","slug":"_1-0-4-2022-03-06","link":"#_1-0-4-2022-03-06","children":[]},{"level":3,"title":"1.0.3 | 2022.03.02","slug":"_1-0-3-2022-03-02","link":"#_1-0-3-2022-03-02","children":[]},{"level":3,"title":"1.0.2 | 2022.02.18","slug":"_1-0-2-2022-02-18","link":"#_1-0-2-2022-02-18","children":[]},{"level":3,"title":"1.0.1 | 2022.02.15","slug":"_1-0-1-2022-02-15","link":"#_1-0-1-2022-02-15","children":[]},{"level":3,"title":"1.0 | 2022.02.14","slug":"_1-0-2022-02-14","link":"#_1-0-2022-02-14","children":[]}],"git":{"updatedTime":1664309975000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/about/changelog.md"}');export{l as data};
diff --git a/docs/assets/contacts.html.0e0a7262.js b/docs/assets/contacts.html.0e0a7262.js
new file mode 100644
index 00000000..fe63660e
--- /dev/null
+++ b/docs/assets/contacts.html.0e0a7262.js
@@ -0,0 +1 @@
+import{_ as s,r,o as c,c as a,b as e,d as n,e as o}from"./app.fb8271cf.js";const _={},l=e("h1",{id:"\u8054\u7CFB\u6211\u4EEC",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#\u8054\u7CFB\u6211\u4EEC","aria-hidden":"true"},"#"),o(" \u8054\u7CFB\u6211\u4EEC")],-1),d=e("blockquote",null,[e("p",null,"\u5982\u5728\u4F7F\u7528\u4E2D\u6709\u4EFB\u4F55\u95EE\u9898\uFF0C\u6216\u6709\u4EFB\u4F55\u5EFA\u8BBE\u6027\u7684\u5EFA\u8BAE\uFF0C\u90FD\u53EF\u4EE5\u8054\u7CFB\u6211\u4EEC\u3002")],-1),h=o("\u52A0\u5165\u6211\u4EEC "),i={href:"https://t.me/YukiHookAPI",target:"_blank",rel:"noopener noreferrer"},u=o("\u70B9\u51FB\u52A0\u5165 Telegram \u7FA4\u7EC4"),p=o("\u5728 "),f=e("strong",null,"\u9177\u5B89",-1),k=o(" \u627E\u5230\u6211 "),m={href:"http://www.coolapk.com/u/876977",target:"_blank",rel:"noopener noreferrer"},x=o("@\u661F\u591C\u4E0D\u835F"),b=e("h2",{id:"\u52A9\u529B\u7EF4\u62A4",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#\u52A9\u529B\u7EF4\u62A4","aria-hidden":"true"},"#"),o(" \u52A9\u529B\u7EF4\u62A4")],-1),g=e("p",null,[o("\u611F\u8C22\u60A8\u9009\u62E9\u5E76\u4F7F\u7528 "),e("code",null,"YukiHookAPI"),o("\uFF0C\u5982\u6709\u4EE3\u7801\u76F8\u5173\u7684\u5EFA\u8BAE\u548C\u8BF7\u6C42\uFF0C\u53EF\u5728 Github \u63D0\u4EA4 Pull Request\u3002")],-1);function I(v,w){const t=r("ExternalLinkIcon");return c(),a("div",null,[l,d,e("p",null,[h,e("a",i,[u,n(t)])]),e("p",null,[p,f,k,e("a",m,[x,n(t)])]),b,g])}const E=s(_,[["render",I],["__file","contacts.html.vue"]]);export{E as default};
diff --git a/docs/assets/contacts.html.3df7cacf.js b/docs/assets/contacts.html.3df7cacf.js
new file mode 100644
index 00000000..15e8418a
--- /dev/null
+++ b/docs/assets/contacts.html.3df7cacf.js
@@ -0,0 +1 @@
+const t=JSON.parse('{"key":"v-6cf86266","path":"/zh-cn/about/contacts.html","title":"\u8054\u7CFB\u6211\u4EEC","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u52A9\u529B\u7EF4\u62A4","slug":"\u52A9\u529B\u7EF4\u62A4","link":"#\u52A9\u529B\u7EF4\u62A4","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/about/contacts.md"}');export{t as data};
diff --git a/docs/assets/contacts.html.5dc8225c.js b/docs/assets/contacts.html.5dc8225c.js
new file mode 100644
index 00000000..2b97abbd
--- /dev/null
+++ b/docs/assets/contacts.html.5dc8225c.js
@@ -0,0 +1 @@
+const t=JSON.parse('{"key":"v-193cf592","path":"/en/about/contacts.html","title":"Contact Us","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Help with Maintenance","slug":"help-with-maintenance","link":"#help-with-maintenance","children":[]}],"git":{"updatedTime":1664300349000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/about/contacts.md"}');export{t as data};
diff --git a/docs/assets/contacts.html.8946c067.js b/docs/assets/contacts.html.8946c067.js
new file mode 100644
index 00000000..52c73490
--- /dev/null
+++ b/docs/assets/contacts.html.8946c067.js
@@ -0,0 +1 @@
+import{_ as s,r as a,o as c,c as r,b as e,d as o,e as t}from"./app.fb8271cf.js";const i={},l=e("h1",{id:"contact-us",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#contact-us","aria-hidden":"true"},"#"),t(" Contact Us")],-1),_=e("blockquote",null,[e("p",null,"If you have any questions in use, or have any constructive suggestions, you can contact us.")],-1),h=t("Join us "),u={href:"https://t.me/YukiHookAPI",target:"_blank",rel:"noopener noreferrer"},d=t("Click to join Telegram group"),p=t("Find me on "),f=e("strong",null,"Twitter",-1),k=t(),m={href:"https://twitter.com/fankesyooni",target:"_blank",rel:"noopener noreferrer"},g=t("@fankesyooni"),y=e("h2",{id:"help-with-maintenance",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#help-with-maintenance","aria-hidden":"true"},"#"),t(" Help with Maintenance")],-1),b=e("p",null,[t("Thank you for choosing and using "),e("code",null,"YukiHookAPI"),t(".")],-1),x=e("p",null,"If you have code-related suggestions and requests, you can submit a Pull Request on Github.",-1);function v(I,w){const n=a("ExternalLinkIcon");return c(),r("div",null,[l,_,e("p",null,[h,e("a",u,[d,o(n)])]),e("p",null,[p,f,k,e("a",m,[g,o(n)])]),y,b,x])}const T=s(i,[["render",v],["__file","contacts.html.vue"]]);export{T as default};
diff --git a/docs/assets/example.html.13ac887a.js b/docs/assets/example.html.13ac887a.js
new file mode 100644
index 00000000..51bfd97e
--- /dev/null
+++ b/docs/assets/example.html.13ac887a.js
@@ -0,0 +1 @@
+const l=JSON.parse('{"key":"v-13b430a0","path":"/zh-cn/guide/example.html","title":"\u7528\u6CD5\u793A\u4F8B","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u7ED3\u6784\u56FE\u89E3","slug":"\u7ED3\u6784\u56FE\u89E3","link":"#\u7ED3\u6784\u56FE\u89E3","children":[]},{"level":2,"title":"Demo","slug":"demo","link":"#demo","children":[]},{"level":2,"title":"\u4E00\u4E2A\u7B80\u5355\u7684 Hook \u4F8B\u5B50","slug":"\u4E00\u4E2A\u7B80\u5355\u7684-hook-\u4F8B\u5B50","link":"#\u4E00\u4E2A\u7B80\u5355\u7684-hook-\u4F8B\u5B50","children":[{"level":3,"title":"Hook APP","slug":"hook-app","link":"#hook-app","children":[]},{"level":3,"title":"Hook Zygote","slug":"hook-zygote","link":"#hook-zygote","children":[]},{"level":3,"title":"Hook \u7CFB\u7EDF\u6846\u67B6","slug":"hook-\u7CFB\u7EDF\u6846\u67B6","link":"#hook-\u7CFB\u7EDF\u6846\u67B6","children":[]},{"level":3,"title":"Hook Resources","slug":"hook-resources","link":"#hook-resources","children":[]},{"level":3,"title":"\u89E3\u9664 Hook","slug":"\u89E3\u9664-hook","link":"#\u89E3\u9664-hook","children":[]}]},{"level":2,"title":"\u5F02\u5E38\u5904\u7406","slug":"\u5F02\u5E38\u5904\u7406","link":"#\u5F02\u5E38\u5904\u7406","children":[{"level":3,"title":"\u76D1\u542C\u5F02\u5E38","slug":"\u76D1\u542C\u5F02\u5E38","link":"#\u76D1\u542C\u5F02\u5E38","children":[]},{"level":3,"title":"\u629B\u51FA\u5F02\u5E38","slug":"\u629B\u51FA\u5F02\u5E38","link":"#\u629B\u51FA\u5F02\u5E38","children":[]}]},{"level":2,"title":"\u72B6\u6001\u76D1\u542C","slug":"\u72B6\u6001\u76D1\u542C","link":"#\u72B6\u6001\u76D1\u542C","children":[]},{"level":2,"title":"\u6269\u5C55\u7528\u6CD5","slug":"\u6269\u5C55\u7528\u6CD5","link":"#\u6269\u5C55\u7528\u6CD5","children":[{"level":3,"title":"\u591A\u4E2A\u5BBF\u4E3B","slug":"\u591A\u4E2A\u5BBF\u4E3B","link":"#\u591A\u4E2A\u5BBF\u4E3B","children":[]},{"level":3,"title":"\u591A\u4E2A\u8FDB\u7A0B","slug":"\u591A\u4E2A\u8FDB\u7A0B","link":"#\u591A\u4E2A\u8FDB\u7A0B","children":[]}]},{"level":2,"title":"\u5199\u6CD5\u4F18\u5316","slug":"\u5199\u6CD5\u4F18\u5316","link":"#\u5199\u6CD5\u4F18\u5316","children":[]},{"level":2,"title":"Xposed \u6A21\u5757\u5224\u65AD\u81EA\u8EAB\u6FC0\u6D3B\u72B6\u6001","slug":"xposed-\u6A21\u5757\u5224\u65AD\u81EA\u8EAB\u6FC0\u6D3B\u72B6\u6001","link":"#xposed-\u6A21\u5757\u5224\u65AD\u81EA\u8EAB\u6FC0\u6D3B\u72B6\u6001","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/guide/example.md"}');export{l as data};
diff --git a/docs/assets/example.html.a036bda1.js b/docs/assets/example.html.a036bda1.js
new file mode 100644
index 00000000..1e4a5cf7
--- /dev/null
+++ b/docs/assets/example.html.a036bda1.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-7b22efaf","path":"/en/guide/example.html","title":"Usage Example","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Structure Diagram","slug":"structure-diagram","link":"#structure-diagram","children":[]},{"level":2,"title":"Demo","slug":"demo","link":"#demo","children":[]},{"level":2,"title":"A Simple Hook Example","slug":"a-simple-hook-example","link":"#a-simple-hook-example","children":[{"level":3,"title":"Hook App","slug":"hook-app","link":"#hook-app","children":[]},{"level":3,"title":"Hook Zygote","slug":"hook-zygote","link":"#hook-zygote","children":[]},{"level":3,"title":"Hook System Framework","slug":"hook-system-framework","link":"#hook-system-framework","children":[]},{"level":3,"title":"Hook Resources","slug":"hook-resources","link":"#hook-resources","children":[]},{"level":3,"title":"Remove Hook","slug":"remove-hook","link":"#remove-hook","children":[]}]},{"level":2,"title":"Exception Handling","slug":"exception-handling","link":"#exception-handling","children":[{"level":3,"title":"Listen for Exceptions","slug":"listen-for-exceptions","link":"#listen-for-exceptions","children":[]},{"level":3,"title":"Throw an Exception","slug":"throw-an-exception","link":"#throw-an-exception","children":[]}]},{"level":2,"title":"Status Monitor","slug":"status-monitor","link":"#status-monitor","children":[]},{"level":2,"title":"Expansion Usage","slug":"expansion-usage","link":"#expansion-usage","children":[{"level":3,"title":"Multiple Hosts","slug":"multiple-hosts","link":"#multiple-hosts","children":[]},{"level":3,"title":"Multiple Processes","slug":"multiple-processes","link":"#multiple-processes","children":[]}]},{"level":2,"title":"Writing Optimization","slug":"writing-optimization","link":"#writing-optimization","children":[]},{"level":2,"title":"Xposed Module own Active State","slug":"xposed-module-own-active-state","link":"#xposed-module-own-active-state","children":[]}],"git":{"updatedTime":1663940587000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/guide/example.md"}');export{e as data};
diff --git a/docs/assets/example.html.be2f529d.js b/docs/assets/example.html.be2f529d.js
new file mode 100644
index 00000000..99eb51d5
--- /dev/null
+++ b/docs/assets/example.html.be2f529d.js
@@ -0,0 +1,286 @@
+import{_ as o,r as p,o as c,c as i,b as s,d as e,a as l,e as n}from"./app.fb8271cf.js";const r={},t=l(`RemedyPlan
\u589E\u52A0 onFind
\u529F\u80FDtype
\u4E2D\u7684 java
\u7C7B\u578B \u7528\u6CD5\u793A\u4F8B
YukiHookAPI
\u7684\u57FA\u672C\u5DE5\u4F5C\u65B9\u5F0F\u4EE5\u53CA\u5217\u4E3E\u4E86\u7B80\u5355\u7684 Hook \u4F8B\u5B50\u548C\u5E38\u7528\u529F\u80FD\u3002 \u7ED3\u6784\u56FE\u89E3
YukiHookAPI
\u7684\u57FA\u672C\u5DE5\u4F5C\u65B9\u5F0F\u548C\u539F\u7406\u3002Host Environment
+\u2514\u2500\u2500 YukiMemberHookCreator
+ \u2514\u2500\u2500 Class
+ \u2514\u2500\u2500 MemberHookCreator
+ \u2514\u2500\u2500 Member
+ \u251C\u2500\u2500 Before
+ \u2514\u2500\u2500 After
+ MemberHookCreator
+ \u2514\u2500\u2500 Member
+ \u251C\u2500\u2500 Before
+ \u2514\u2500\u2500 After
+ ...
+ YukiResourcesHookCreator
+ \u2514\u2500\u2500 Resources
+ \u2514\u2500\u2500 ResourcesHookCreator
+ \u2514\u2500\u2500 Drawable
+ \u2514\u2500\u2500 Replace
+ ResourcesHookCreator
+ \u2514\u2500\u2500 Layout
+ \u2514\u2500\u2500 Inject
+ ...
+
TargetClass.hook {
+ injectMember {
+ method {
+ // Your code here.
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+}
+resources().hook {
+ injectResource {
+ conditions {
+ // Your code here.
+ }
+ replaceTo(...)
+ }
+}
+
Demo
`,9),d=n("\u5BBF\u4E3B APP Demo "),u={href:"https://github.com/fankes/YukiHookAPI/tree/master/demo-app",target:"_blank",rel:"noopener noreferrer"},A=n("\u70B9\u51FB\u8FD9\u91CC\u67E5\u770B"),v=n("\u6A21\u5757 APP Demo "),y={href:"https://github.com/fankes/YukiHookAPI/tree/master/demo-module",target:"_blank",rel:"noopener noreferrer"},m=n("\u70B9\u51FB\u8FD9\u91CC\u67E5\u770B"),b=l(`YukiHookAPI
\u7684\u4F7F\u7528\u65B9\u6CD5\u3002 \u4E00\u4E2A\u7B80\u5355\u7684 Hook \u4F8B\u5B50
Hook APP
com.android.browser
\u4E2D\u7684 onCreate
\u65B9\u6CD5\u5E76\u5F39\u51FA\u4E00\u4E2A\u5BF9\u8BDD\u6846\u3002encase
\u65B9\u6CD5\u4F53\u4E2D\u6DFB\u52A0\u4EE3\u7801\u3002loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ AlertDialog.Builder(instance())
+ .setTitle("Hooked")
+ .setMessage("I am hook!")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+ }
+ }
+}
+
onCreate
\u65B9\u6CD5\u5C06\u88AB\u6210\u529F Hook \u5E76\u5728 com.android.browser
\u4E2D\u7684\u6BCF\u4E2A Activity
\u542F\u52A8\u65F6\u5F39\u51FA\u6B64\u5BF9\u8BDD\u6846\u3002onStart
\u65B9\u6CD5\u8981\u600E\u4E48\u505A\u5462\uFF1FinjectMember
\u65B9\u6CD5\u4F53\u5373\u53EF\u3002loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ AlertDialog.Builder(instance())
+ .setTitle("Hooked")
+ .setMessage("I am hook!")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+ }
+ injectMember {
+ method {
+ name = "onStart"
+ emptyParam()
+ returnType = UnitType
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+}
+
Class
\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 stub
\u65B9\u5F0F\u6216 findClass
\u65B9\u6CD5\u6765\u5F97\u5230\u9700\u8981 Hook \u7684\u7C7B\u3002com.example.demo.TestClass
\u3002findClass(name = "com.example.demo.TestClass").hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
com.example.demo
\u662F\u4F60\u8981 Hook \u7684 APP\uFF0C\u90A3\u4E48\u5199\u6CD5\u53EF\u4EE5\u66F4\u7B80\u5355\u3002findClass(name = "$packageName.TestClass").hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
findClass
\u663E\u5F97\u6709\u4E9B\u7E41\u7410\u3002const val TestClass = "com.example.demo.TestClass"
+
+TestClass.hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
"$packageName.TestClass".hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
Hook Zygote
initZygote
\u3002Activity
\u7684 onCreate
\u4E8B\u4EF6encase
\u65B9\u6CD5\u4F53\u4E2D\u6DFB\u52A0\u4EE3\u7801\u3002loadZygote {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+}
+
Hook \u7CFB\u7EDF\u6846\u67B6
YukiHookAPI
\u4E2D\uFF0CHook \u7CFB\u7EDF\u6846\u67B6\u7684\u5B9E\u73B0\u975E\u5E38\u7B80\u5355\u3002ApplicationInfo
\u4E0E PackageInfo
\u5E76\u5BF9\u5B83\u4EEC\u8FDB\u884C\u4E00\u4E9B\u64CD\u4F5C\u3002encase
\u65B9\u6CD5\u4F53\u4E2D\u6DFB\u52A0\u4EE3\u7801\u3002loadSystem {
+ ApplicationInfoClass.hook {
+ // Your code here.
+ }
+ PackageInfoClass.hook {
+ // Your code here.
+ }
+}
+
Hook Resources
com.android.browser
\u4E2D string
\u7C7B\u578B\u7684 app_name
\u5185\u5BB9\u66FF\u6362\u4E3A 123
\u3002encase
\u65B9\u6CD5\u4F53\u4E2D\u6DFB\u52A0\u4EE3\u7801\u3002loadApp(name = "com.android.browser") {
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "app_name"
+ string()
+ }
+ replaceTo("123")
+ }
+ }
+}
+
app_name
\u8BBE\u7F6E\u4E86\u6807\u9898\u680F\u6587\u672C\uFF0C\u5219\u5B83\u5C31\u4F1A\u53D8\u6210\u6211\u4EEC\u7684 123
\u3002com.android.browser
\u4E2D mipmap
\u7C7B\u578B\u7684 ic_launcher
\u3002loadApp(name = "com.android.browser") {
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+}
+
loadApp
\u6362\u6210 loadZygote
\u5373\u53EF\u3002loadZygote {
+ resources().hook {
+ // Your code here.
+ }
+}
+
\u89E3\u9664 Hook
XC_MethodHook.Unhook
\u529F\u80FD\uFF0C\u53EF\u4EE5\u4ECE Hook \u961F\u5217\u4E2D\u5C06\u5F53\u524D Hook \u79FB\u9664\uFF0CYukiHookAPI
\u540C\u6837\u53EF\u4EE5\u5B9E\u73B0\u6B64\u529F\u80FD\u3002Result
\u5B9E\u4F8B\uFF0C\u5728\u9002\u5F53\u7684\u65F6\u5019\u548C\u5730\u65B9\u8C03\u7528 remove
\u5373\u53EF\u89E3\u9664\u8BE5\u6CE8\u5165\u5BF9\u8C61\u3002// \u8BBE\u7F6E\u4E00\u4E2A\u53D8\u91CF\u4FDD\u5B58\u5F53\u524D\u5B9E\u4F8B
+val hookResult = injectMember {
+ method {
+ name = "test"
+ returnType = UnitType
+ }
+ afterHook {
+ // ...
+ }
+}
+// \u5728\u9002\u5F53\u7684\u65F6\u5019\u8C03\u7528\u5982\u4E0B\u65B9\u6CD5\u5373\u53EF
+hookResult.remove()
+
removeSelf
\u79FB\u9664\u81EA\u8EAB\u3002injectMember {
+ method {
+ name = "test"
+ returnType = UnitType
+ }
+ afterHook {
+ // \u76F4\u63A5\u8C03\u7528\u5982\u4E0B\u65B9\u6CD5\u5373\u53EF
+ removeSelf()
+ }
+}
+
\u5F02\u5E38\u5904\u7406
YukiHookAPI
\u91CD\u65B0\u8BBE\u8BA1\u4E86\u5BF9\u5F02\u5E38\u7684\u76D1\u542C\uFF0C\u4EFB\u4F55\u5F02\u5E38\u90FD\u4E0D\u4F1A\u5728 Hook \u8FC7\u7A0B\u4E2D\u629B\u51FA\uFF0C\u907F\u514D\u6253\u65AD\u4E0B\u4E00\u4E2A Hook \u6D41\u7A0B\u5BFC\u81F4 Hook \u8FDB\u7A0B\u201C\u6B7B\u6389\u201D\u3002 \u76D1\u542C\u5F02\u5E38
injectMember {
+ // Your code here.
+}.result {
+ // \u5904\u7406 Hook \u5F00\u59CB\u65F6\u7684\u5F02\u5E38
+ onHookingFailure {}
+ // \u5904\u7406 Hook \u8FC7\u7A0B\u4E2D\u7684\u5F02\u5E38
+ onConductFailure { param, throwable -> }
+ // \u5904\u7406\u5168\u90E8\u5F02\u5E38
+ onAllFailure {}
+ // ...
+}
+
injectResource {
+ // Your code here.
+}.result {
+ // \u5904\u7406 Hook \u65F6\u7684\u4EFB\u610F\u5F02\u5E38
+ onHookingFailure {}
+ // ...
+}
+
Class
\u4E0D\u5B58\u5728\u65F6\u53D1\u751F\u7684\u5F02\u5E38\u3002TargetClass.hook {
+ injectMember {
+ // Your code here.
+ }
+}.onHookClassNotFoundFailure {
+ // Your code here.
+}
+
method {
+ // Your code here.
+}.onNoSuchMethod {
+ // Your code here.
+}
+
\u629B\u51FA\u5F02\u5E38
hook
\u65B9\u6CD5\u4F53\u5185\u629B\u51FA\u7684\u5F02\u5E38\u4F1A\u88AB YukiHookAPI
\u63A5\u7BA1\uFF0C\u907F\u514D\u6253\u65AD\u4E0B\u4E00\u4E2A Hook \u6D41\u7A0B\u5BFC\u81F4 Hook \u8FDB\u7A0B\u201C\u6B7B\u6389\u201D\u3002YukiHookAPI
\u63A5\u7BA1\u65F6\u8FD9\u4E9B\u5F02\u5E38\u7684\u8FD0\u4F5C\u65B9\u5F0F\u3002// <\u60C5\u666F1>
+injectMember {
+ method {
+ throw RuntimeException("Exception Test")
+ }
+ afterHook {
+ // ...
+ }
+}.result {
+ // \u80FD\u591F\u6355\u83B7\u5230 RuntimeException
+ onHookingFailure {}
+}
+// <\u60C5\u666F2>
+injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ throw RuntimeException("Exception Test")
+ }
+}.result {
+ // \u80FD\u591F\u6355\u83B7\u5230 RuntimeException
+ onConductFailure { param, throwable -> }
+}
+
param.throwable
\u65B9\u6CD5\uFF0CYukiHookAPI
\u540C\u6837\u53EF\u4EE5\u5B9E\u73B0\u6B64\u529F\u80FD\u3002injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ RuntimeException("Exception Test").throwToApp()
+ }
+}
+
injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ throw RuntimeException("Exception Test")
+ }.onFailureThrowToApp()
+}
+
\u72B6\u6001\u76D1\u542C
XposedHelpers
\u7684\u540C\u5B66\u5F80\u5F80\u4F1A\u5728 Hook \u540E\u6253\u5370 Unhook
\u7684\u65B9\u6CD5\u786E\u5B9A\u662F\u5426 Hook \u6210\u529F\u3002YukiHookAPI
\u4E2D\uFF0C\u4F60\u53EF\u4EE5\u7528\u4EE5\u4E0B\u65B9\u6CD5\u65B9\u4FBF\u5730\u91CD\u65B0\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002YourClass.hook {
+ // Your code here.
+}.onPrepareHook {
+ loggerD(msg = "$instanceClass hook start")
+}
+
injectMember {
+ // Your code here.
+}.onHooked { member ->
+ loggerD(msg = "$member has hooked")
+}
+
\u6269\u5C55\u7528\u6CD5
\u591A\u4E2A\u5BBF\u4E3B
loadApp
\u65B9\u6CD5\u4F53\u6765\u533A\u5206\u4F60\u8981 Hook \u7684 APP\u3002loadApp(name = "com.android.browser") {
+ // Your code here.
+}
+loadApp(name = "com.android.phone") {
+ // Your code here.
+}
+
\u591A\u4E2A\u8FDB\u7A0B
withProcess
\u65B9\u6CD5\u4F53\u6765\u5BF9\u5B83\u4EEC\u5206\u522B\u8FDB\u884C Hook\u3002withProcess(mainProcessName) {
+ // Your code here.
+}
+withProcess(name = "$packageName:tool") {
+ // Your code here.
+}
+
\u5199\u6CD5\u4F18\u5316
YukiHookAPI
\u7684\u540D\u79F0\uFF0C\u5C06\u4F60\u7684 onHook
\u5165\u53E3\u5199\u4F5C lambda
\u5F62\u5F0F\u3002override fun onHook() = encase {
+ // Your code here.
+}
+
Xposed \u6A21\u5757\u5224\u65AD\u81EA\u8EAB\u6FC0\u6D3B\u72B6\u6001
false
\uFF0C\u7136\u540E Hook \u6389\u8FD9\u4E2A\u65B9\u6CD5\u4F7F\u5176\u8FD4\u56DE true
\u6765\u8BC1\u660E Hook \u5DF2\u7ECF\u751F\u6548\u3002YukiHookAPI
\u4E2D\u4F60\u5B8C\u5168\u4E0D\u9700\u8981\u518D\u8FD9\u4E48\u505A\u4E86\uFF0CYukiHookAPI
\u5DF2\u7ECF\u5E2E\u4F60\u5C01\u88C5\u597D\u4E86\u8FD9\u4E2A\u64CD\u4F5C\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u8FDB\u884C\u4F7F\u7528\u3002YukiHookAPI.Status.isXposedModuleActive
\u5728\u6A21\u5757\u4E2D\u5224\u65AD\u81EA\u8EAB\u662F\u5426\u88AB\u6FC0\u6D3B\u3002if(YukiHookAPI.Status.isXposedModuleActive) {
+ // Your code here.
+}
+
YukiHookAPI.Status.isTaiChiModuleActive
\u5224\u65AD\u81EA\u8EAB\u662F\u5426\u88AB\u6FC0\u6D3B\u3002if(YukiHookAPI.Status.isTaiChiModuleActive) {
+ // Your code here.
+}
+
YukiHookAPI
\u540C\u6837\u4E3A\u4F60\u5C01\u88C5\u4E86\u4FBF\u6377\u7684\u65B9\u5F0F\u3002YukiHookAPI.Status.isModuleActive
\u5224\u65AD\u81EA\u8EAB\u662F\u5426\u5728 Xposed \u6216\u592A\u6781\u3001\u65E0\u6781\u4E2D\u88AB\u6FC0\u6D3B\u3002if(YukiHookAPI.Status.isModuleActive) {
+ // Your code here.
+}
+
Usage Example
YukiHookAPI
and a list of simple Hook examples and common functions. Structure Diagram
YukiHookAPI
.Host Environment
+\u2514\u2500\u2500 YukiMemberHookCreator
+ \u2514\u2500\u2500 Class
+ \u2514\u2500\u2500 MemberHookCreator
+ \u2514\u2500\u2500 Member
+ \u251C\u2500\u2500 Before
+ \u2514\u2500\u2500 After
+ MemberHookCreator
+ \u2514\u2500\u2500 Member
+ \u251C\u2500\u2500 Before
+ \u2514\u2500\u2500 After
+ ...
+ YukiResourcesHookCreator
+ \u2514\u2500\u2500 Resources
+ \u2514\u2500\u2500 ResourcesHookCreator
+ \u2514\u2500\u2500 Drawable
+ \u2514\u2500\u2500 Replace
+ ResourcesHookCreator
+ \u2514\u2500\u2500 Layout
+ \u2514\u2500\u2500 Inject
+ ...
+
TargetClass.hook {
+ injectMember {
+ method {
+ // Your code here.
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+}
+resources().hook {
+ injectResource {
+ conditions {
+ // Your code here.
+ }
+ replaceTo(...)
+ }
+}
+
Demo
`,9),d=n("Host App Demo "),u={href:"https://github.com/fankes/YukiHookAPI/tree/master/demo-app",target:"_blank",rel:"noopener noreferrer"},A=n("click here to view"),m=n("Module App Demo "),v={href:"https://github.com/fankes/YukiHookAPI/tree/master/demo-module",target:"_blank",rel:"noopener noreferrer"},y=n("click here to view"),h=l(`YukiHookAPI
. A Simple Hook Example
Hook App
onCreate
method in com.android.browser
and show a dialog.encase
method.loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ AlertDialog.Builder(instance())
+ .setTitle("Hooked")
+ .setMessage("I am hook!")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+ }
+ }
+}
+
onCreate
method will be successfully hooked and this dialog will show when every Activity
in com.android.browser
starts.onStart
method?injectMember
method body.loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ AlertDialog.Builder(instance())
+ .setTitle("Hooked")
+ .setMessage("I am hook!")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+ }
+ injectMember {
+ method {
+ name = "onStart"
+ emptyParam()
+ returnType = UnitType
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+}
+
Class
that does not exist in the current project, you can use the stub
method or the findClass
method to get the class that needs to be hooked.com.example.demo.TestClass
.findClass(name = "com.example.demo.TestClass").hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
com.example.demo
is the app you want to hook, then the writing method can be simpler.findClass(name = "$packageName.TestClass").hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
findClass
is a bit cumbersome in some scenarios.const val TestClass = "com.example.demo.TestClass"
+
+TestClass.hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
"$packageName.TestClass".hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
Hook Zygote
initZygote
after the new process is forked when the app starts.onCreate
event of an app Activity
encase
method.loadZygote {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+}
+
Hook System Framework
YukiHookAPI
, the implementation of the Hook System Framework is very simple.ApplicationInfo
and PackageInfo
and do something with them.encase
method.loadSystem {
+ ApplicationInfoClass.hook {
+ // Your code here.
+ }
+ PackageInfoClass.hook {
+ // Your code here.
+ }
+}
+
Hook Resources
app_name
of type string
in Hook com.android.browser
with 123
.encase
method.loadApp(name = "com.android.browser") {
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "app_name"
+ string()
+ }
+ replaceTo("123")
+ }
+ }
+}
+
app_name
, it will become our 123
.ic_launcher
of type mipmap
in com.android.browser
.loadApp(name = "com.android.browser") {
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+}
+
loadApp
with loadZygote
.loadZygote {
+ resources().hook {
+ // Your code here.
+ }
+}
+
Remove Hook
XC_MethodHook.Unhook
function, which can remove the current Hook from the Hook queue, and YukiHookAPI
can also implement this function.Result
instance of the current injected object, and call remove
at the appropriate time and place to remove the injected object.// Set a variable to save the current instance
+val hookResult = injectMember {
+ method {
+ name = "test"
+ returnType = UnitType
+ }
+ afterHook {
+ // ...
+ }
+}
+// Call the following method when appropriate
+hookResult.remove()
+
removeSelf
in the Hook callback method to remove itself.injectMember {
+ method {
+ name = "test"
+ returnType = UnitType
+ }
+ afterHook {
+ // Just call the following method directly
+ removeSelf()
+ }
+}
+
Exception Handling
YukiHookAPI
has redesigned the monitoring of exceptions, any exception will not be thrown during the hook process, to avoid interrupting the next hook process and causing the hook process to "die". Listen for Exceptions
injectMember {
+ // Your code here.
+}.result {
+ // Handle the exception at the start of the hook
+ onHookingFailure {}
+ // Handle exceptions in the hook process
+ onConductFailure { param, throwable -> }
+ // Handle all exceptions
+ onAllFailure {}
+ // ...
+}
+
injectResource {
+ // Your code here.
+}.result {
+ // Handle arbitrary exceptions when hooking
+ onHookingFailure {}
+ // ...
+}
+
Class
does not exist.TargetClass.hook {
+ injectMember {
+ // Your code here.
+ }
+}.onHookClassNotFoundFailure {
+ // Your code here.
+}
+
method {
+ // Your code here.
+}.onNoSuchMethod {
+ // Your code here.
+}
+
Throw an Exception
hook
method body will be taken over by the YukiHookAPI
to avoid interrupting the next Hook process and causing the Hook process to "die".YukiHookAPI
takes over.// <Scenario 1>
+injectMember {
+ method {
+ throw RuntimeException("Exception Test")
+ }
+ afterHook {
+ // ...
+ }
+}.result {
+ // Can catch RuntimeException
+ onHookingFailure {}
+}
+// <Scenario 2>
+injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ throw RuntimeException("Exception Test")
+ }
+}.result {
+ // Can catch RuntimeException
+ onConductFailure { param, throwable -> }
+}
+
param.throwable
method, and YukiHookAPI
can also implement this function.injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ RuntimeException("Exception Test").throwToApp()
+ }
+}
+
injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ throw RuntimeException("Exception Test")
+ }.onFailureThrowToApp()
+}
+
Status Monitor
XposedHelpers
often print Unhook
after the Hook to determine whether the Hook is successful.YukiHookAPI
, you can easily reimplement this functionality with the following methods.YourClass.hook {
+ // Your code here.
+}.onPrepareHook {
+ loggerD(msg = "$instanceClass hook start")
+}
+
injectMember {
+ // Your code here.
+}.onHooked { member ->
+ loggerD(msg = "$member has hooked")
+}
+
Expansion Usage
Multiple Hosts
loadApp
method body to distinguish the app you want to hook.loadApp(name = "com.android.browser") {
+ // Your code here.
+}
+loadApp(name = "com.android.phone") {
+ // Your code here.
+}
+
Multiple Processes
withProcess
method body to hook them separately.withProcess(mainProcessName) {
+ // Your code here.
+}
+withProcess(name = "$packageName:tool") {
+ // Your code here.
+}
+
Writing Optimization
YukiHookAPI
and write your onHook
entry as lambda
.override fun onHook() = encase {
+ // Your code here.
+}
+
Xposed Module own Active State
false
, and then Hook this method to return true
to prove that the Hook has taken effect.YukiHookAPI
, you don't need to do this at all. YukiHookAPI
has already encapsulated this operation for you, and you can use it directly.YukiHookAPI.Status.isXposedModuleActive
directly in the Module App to determine whether it is active.if(YukiHookAPI.Status.isXposedModuleActive) {
+ // Your code here.
+}
+
YukiHookAPI.Status.isTaiChiModuleActive
to determine whether it is activated.if(YukiHookAPI.Status.isTaiChiModuleActive) {
+ // Your code here.
+}
+
YukiHookAPI
also encapsulates a convenient way for you.YukiHookAPI.Status.isModuleActive
to determine whether you are activated in Xposed or TaiChi and Promise.if(YukiHookAPI.Status.isModuleActive) {
+ // Your code here.
+}
+
\u5C55\u671B\u672A\u6765
YukiHookAPI
\u5728\u672A\u6765\u7684\u53D1\u5C55\u7A7A\u95F4\u3002 \u672A\u89E3\u51B3\u7684\u95EE\u9898
YukiHookAPI
\u5C1A\u672A\u89E3\u51B3\u7684\u95EE\u9898\u3002 YukiHookModulePrefs
selinux
\u5C31\u662F\u76EE\u524D\u9762\u4E34\u7684\u4E00\u4E2A\u5927\u95EE\u9898\uFF0C\u6709\u5F85\u8BA8\u8BBA\u548C\u7814\u7A76\u3002 \u672A\u6765\u7684\u8BA1\u5212
YukiHookAPI
\u53EF\u80FD\u4F1A\u5728\u540E\u671F\u6DFB\u52A0\u7684\u529F\u80FD\u3002 \u652F\u6301\u72EC\u7ACB\u4F7F\u7528\u7684 Lite \u7248\u672C
\u652F\u6301\u66F4\u591A Hook Framework
XposedBridge
\u4F5C\u4E3A\u517C\u5BB9\u5C42\uFF0C\u8FD8\u662F\u6709\u4E00\u5B9A\u7684\u5C40\u9650\u6027\u3002inline hook
\u6CA1\u6709 Java
\u517C\u5BB9\u5C42\uFF0C\u540E\u671F\u53EF\u80FD\u4F1A\u8003\u8651 native hook
\u7684 Java
\u517C\u5BB9\u5C42\u9002\u914D\u3002 Looking for Future
YukiHookAPI
. Unresolved Issues
YukiHookAPI
. YukiHookModulePrefs
selinux
is a big problem currently facing, which needs to be discussed and studied. Future Plans
YukiHookAPI
may add later are included here. Lite Version Supported for Standalone Use
Support for More Hook Framework
XposedBridge
as a compatibility layer still has certain limitations.inline hook
do not have a Java
compatibility layer, and the Java
compatibility layer adaptation of native hook
may be considered later. \u7528\u9014
YukiHookAPI
\u5B8C\u5168\u91C7\u7528 Kotlin
lambda
\u8BED\u6CD5\u6784\u5EFA\u3002XposedHelpers
\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528\u5B83\u6765\u8F7B\u677E\u521B\u5EFA Xposed \u6A21\u5757\u4EE5\u53CA\u8F7B\u677E\u5B9E\u73B0\u81EA\u5B9A\u4E49 Hook API\u3002 \u8BED\u8A00\u8981\u6C42
Kotlin
\uFF0C\u6846\u67B6\u90E8\u5206\u4EE3\u7801\u6784\u6210\u540C\u6837\u517C\u5BB9 Java
\u4F46\u57FA\u7840 Hook \u573A\u666F\u7684\u5B9E\u73B0\u53EF\u80FD\u5B8C\u5168\u65E0\u6CD5\u4F7F\u7528\u3002Kotlin
\u8FDB\u884C\u63CF\u8FF0\uFF0C\u5982\u679C\u4F60\u5B8C\u5168\u4E0D\u4F1A\u4F7F\u7528 Kotlin
\u90A3\u4F60\u5C06\u6709\u53EF\u80FD\u65E0\u6CD5\u4F7F\u7528 YukiHookAPI
\u3002 \u7075\u611F\u6765\u6E90
assets
\u4E0B\u521B\u5EFA xposed_init
\u6587\u4EF6\u3002XposedHelpers
\u53BB\u5B9E\u73B0\u6211\u4EEC\u7684 Hook \u903B\u8F91\u3002Kotlin
\u4F5C\u4E3A Android \u4E3B\u8981\u5F00\u53D1\u8BED\u8A00\u4EE5\u6765\uFF0C\u8FD9\u5957 API \u7528\u8D77\u6765\u786E\u5B9E\u5DF2\u7ECF\u4E0D\u662F\u5F88\u4F18\u96C5\u4E86\u3002YukiHookAPI
\u8BDE\u751F\u4E86\u3002Kotlin
\u4F18\u96C5\u7684 lambda
\u5199\u6CD5\u4EE5\u53CA YukiHookAPI
\uFF0C\u53EF\u4EE5\u8BA9\u4F60\u7684 Hook \u903B\u8F91\u66F4\u52A0\u7F8E\u89C2\u6E05\u6670\u3002
',9),x=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"@InjectYukiHookWithXposed")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"class"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"HookEntry"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"IYukiHookXposedInit"),s("span",{style:{color:"#ADBAC7"}}," {")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"onHook"),s("span",{style:{color:"#ADBAC7"}},"() "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," encase {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," loadZygote {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"ActivityClass"),s("span",{style:{color:"#ADBAC7"}},".hook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectMember {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," method {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"onCreate"')]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param("),s("span",{style:{color:"#F69D50"}},"BundleClass"),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," beforeHook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your code here.")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," afterHook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your code here.")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resources().hook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectResource {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," conditions {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"sym_def_app_icon"')]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," mipmap()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," replaceToModuleResource("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," loadApp(name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.android.browser"'),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"ActivityClass"),s("span",{style:{color:"#ADBAC7"}},".hook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectMember {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," method {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"onCreate"')]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param("),s("span",{style:{color:"#F69D50"}},"BundleClass"),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," beforeHook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your code here.")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," afterHook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your code here.")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resources().hook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectResource {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," conditions {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"ic_launcher"')]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," mipmap()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," replaceToModuleResource("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),R=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"class"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"HookEntry"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"IXposedHookZygoteInit"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#F69D50"}},"IXposedHookLoadPackage"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#F69D50"}},"IXposedHookInitPackageResources"),s("span",{style:{color:"#ADBAC7"}}," {")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"private"),s("span",{style:{color:"#ADBAC7"}}," lateinit "),s("span",{style:{color:"#F47067"}},"var"),s("span",{style:{color:"#ADBAC7"}}," moduleResources"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XModuleResources")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"initZygote"),s("span",{style:{color:"#ADBAC7"}},"(sparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"IXposedHookZygoteInit"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"StartupParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XModuleResources"),s("span",{style:{color:"#ADBAC7"}},".createInstance(sparam.modulePath, "),s("span",{style:{color:"#6CB6FF"}},"null"),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XResources"),s("span",{style:{color:"#ADBAC7"}},".setSystemWideReplacement(")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"android"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"mipmap"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"sym_def_app_icon"'),s("span",{style:{color:"#ADBAC7"}},",")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources.fwd("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," )")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XposedHelpers"),s("span",{style:{color:"#ADBAC7"}},".findAndHookMethod(")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," Activity::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java.name,")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"null"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"onCreate"'),s("span",{style:{color:"#ADBAC7"}},",")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," Bundle::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java,")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"object"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_MethodHook"),s("span",{style:{color:"#ADBAC7"}},"() {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun beforeHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam?"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Your"),s("span",{style:{color:"#ADBAC7"}}," code here.")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun afterHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam?"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Your"),s("span",{style:{color:"#ADBAC7"}}," code here.")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," })")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"handleLoadPackage"),s("span",{style:{color:"#ADBAC7"}},"(lpparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_LoadPackage"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"LoadPackageParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"if"),s("span",{style:{color:"#ADBAC7"}}," (lpparam.packageName "),s("span",{style:{color:"#F47067"}},"=="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.android.browser"'),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XposedHelpers"),s("span",{style:{color:"#ADBAC7"}},".findAndHookMethod(")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," Activity::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java.name,")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," lpparam.classLoader, "),s("span",{style:{color:"#96D0FF"}},'"onCreate"'),s("span",{style:{color:"#ADBAC7"}},",")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," Bundle::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java,")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"object"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_MethodHook"),s("span",{style:{color:"#ADBAC7"}},"() {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun beforeHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam?"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Your"),s("span",{style:{color:"#ADBAC7"}}," code here.")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun afterHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam?"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Your"),s("span",{style:{color:"#ADBAC7"}}," code here.")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," })")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"handleInitPackageResources"),s("span",{style:{color:"#ADBAC7"}},"(resparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_InitPackageResources"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"InitPackageResourcesParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"if"),s("span",{style:{color:"#ADBAC7"}}," (resparam.packageName "),s("span",{style:{color:"#F47067"}},"=="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.android.browser"'),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resparam.res.setReplacement(")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.android.browser"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"mipmap"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"ic_launcher"'),s("span",{style:{color:"#ADBAC7"}},",")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources.fwd("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," )")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),Y=s("p",null,"\u662F\u7684\uFF0C\u4F60\u6CA1\u6709\u770B\u9519\uFF0C\u4EC5\u4EC5\u5C31\u9700\u8981\u8FD9\u4E9B\u4EE3\u7801\uFF0C\u5C31\u80FD\u5B8C\u5168\u53D6\u4EE3 Xposed API \u5B9E\u73B0\u540C\u6837\u7684\u529F\u80FD\u3002",-1),M=s("p",null,[l("\u73B0\u5728\uFF0C\u501F\u52A9\u9AD8\u6548\u5F3A\u5927\u7684 "),s("code",null,"YukiHookAPI"),l("\uFF0C\u4F60\u5C31\u53EF\u4EE5\u5B9E\u73B0\u4E00\u4E2A\u975E\u5E38\u7B80\u5355\u7684 Xposed \u6A21\u5757\u3002")],-1),w=s("h2",{id:"\u652F\u6301\u7684-hook-\u6846\u67B6",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#\u652F\u6301\u7684-hook-\u6846\u67B6","aria-hidden":"true"},"#"),l(" \u652F\u6301\u7684 Hook \u6846\u67B6")],-1),L=s("p",null,[l("\u4EE5\u4E0B\u662F "),s("code",null,"YukiHookAPI"),l(" \u652F\u6301\u7684 "),s("code",null,"Hook Framework"),l(" \u4EE5\u53CA Xposed \u6846\u67B6\u3002")],-1),j=s("thead",null,[s("tr",null,[s("th",null,"Hook Framework"),s("th",null,"ST"),s("th",null,"Description")])],-1),S={href:"https://github.com/LSPosed/LSPosed",target:"_blank",rel:"noopener noreferrer"},E=l("LSPosed"),K=s("td",null,"\u2705",-1),T=s("td",null,"\u591A\u573A\u666F\u4E0B\u7A33\u5B9A\u4F7F\u7528",-1),N={href:"https://github.com/LSPosed/LSPatch",target:"_blank",rel:"noopener noreferrer"},G=l("LSPatch"),V=s("td",null,"\u2B55",-1),W=s("td",null,"\u5C06\u5728\u6B64\u9879\u76EE\u5B8C\u5584\u540E\u9010\u6E10\u52A0\u5165 API \u652F\u6301",-1),Z={href:"https://github.com/ElderDrivers/EdXposed",target:"_blank",rel:"noopener noreferrer"},q=l("EdXposed"),J=s("td",null,"\u274E",-1),z=s("td",null,"\u5DF2\u505C\u6B62\u7EF4\u62A4\uFF0C\u4E0D\u518D\u63A8\u8350\u4F7F\u7528",-1),O={href:"https://github.com/canyie/pine",target:"_blank",rel:"noopener noreferrer"},Q=l("Pine"),U=s("td",null,"\u2B55",-1),$=s("td",null,"\u53EF\u4EE5\u4F7F\u7528",-1),ss={href:"https://github.com/asLody/SandHook",target:"_blank",rel:"noopener noreferrer"},ls=l("SandHook"),es=s("td",null,"\u2B55",-1),ns=s("td",null,"\u53EF\u4EE5\u4F7F\u7528",-1),os={href:"https://github.com/asLody/whale",target:"_blank",rel:"noopener noreferrer"},as=l("Whale"),cs=s("td",null,"\u2B55",-1),rs=l("\u9700\u8981 "),ts={href:"https://github.com/WindySha/xposed-hook-based-on-whale",target:"_blank",rel:"noopener noreferrer"},is=l("xposed-hook-based-on-whale"),ps={href:"https://github.com/PAGalaxyLab/YAHFA",target:"_blank",rel:"noopener noreferrer"},ds=l("YAHFA"),As=s("td",null,"\u2757",-1),ys=s("td",null,"\u9700\u8981\u81EA\u884C\u5B9E\u73B0 Xposed API",-1),us={href:"https://github.com/turing-technician/FastHook",target:"_blank",rel:"noopener noreferrer"},Ds=l("FastHook"),Cs=s("td",null,"\u2757",-1),hs=s("td",null,"\u9700\u8981\u81EA\u884C\u5B9E\u73B0 Xposed API",-1),ms={href:"https://github.com/tiann/epic",target:"_blank",rel:"noopener noreferrer"},Bs=l("Epic"),_s=s("td",null,"\u2757",-1),bs=l("\u9700\u8981\u81EA\u884C\u5BF9\u63A5 "),vs={href:"https://github.com/alibaba/dexposed",target:"_blank",rel:"noopener noreferrer"},Fs=l("Dexposed"),ks={href:"https://github.com/taichi-framework/TaiChi",target:"_blank",rel:"noopener noreferrer"},fs=l("TaiChi"),gs=s("td",null,"\u2B55",-1),Hs=s("td",null,"\u53EF\u4EE5\u4F5C\u4E3A\u6A21\u5757\u4F7F\u7528",-1),Ps={href:"https://github.com/rovo89/Xposed",target:"_blank",rel:"noopener noreferrer"},Is=l("Xposed"),Xs=s("td",null,"\u274E",-1),xs=s("td",null,"\u672A\u6D4B\u8BD5\uFF0C\u4E0D\u518D\u63A8\u8350\u4F7F\u7528",-1);function Rs(Ys,Ms){const n=o("ExternalLinkIcon"),c=o("CodeGroupItem"),t=o("CodeGroup");return p(),d("div",null,[y,u,D,C,s("p",null,[h,s("a",m,[B,e(n)]),_]),s("p",null,[b,s("a",v,[F,e(n)]),k]),f,s("p",null,[g,s("a",H,[P,e(n)]),I]),X,e(t,null,{default:a(()=>[e(c,{title:"Yuki Hook API"},{default:a(()=>[x]),_:1}),e(c,{title:"Xposed API"},{default:a(()=>[R]),_:1})]),_:1}),Y,M,w,L,s("table",null,[j,s("tbody",null,[s("tr",null,[s("td",null,[s("a",S,[E,e(n)])]),K,T]),s("tr",null,[s("td",null,[s("a",N,[G,e(n)])]),V,W]),s("tr",null,[s("td",null,[s("a",Z,[q,e(n)])]),J,z]),s("tr",null,[s("td",null,[s("a",O,[Q,e(n)])]),U,$]),s("tr",null,[s("td",null,[s("a",ss,[ls,e(n)])]),es,ns]),s("tr",null,[s("td",null,[s("a",os,[as,e(n)])]),cs,s("td",null,[rs,s("a",ts,[is,e(n)])])]),s("tr",null,[s("td",null,[s("a",ps,[ds,e(n)])]),As,ys]),s("tr",null,[s("td",null,[s("a",us,[Ds,e(n)])]),Cs,hs]),s("tr",null,[s("td",null,[s("a",ms,[Bs,e(n)])]),_s,s("td",null,[bs,s("a",vs,[Fs,e(n)])])]),s("tr",null,[s("td",null,[s("a",ks,[fs,e(n)])]),gs,Hs]),s("tr",null,[s("td",null,[s("a",Ps,[Is,e(n)])]),Xs,xs])])])])}const Ls=i(A,[["render",Rs],["__file","home.html.vue"]]);export{Ls as default};
diff --git a/docs/assets/home.html.4d8cac8a.js b/docs/assets/home.html.4d8cac8a.js
new file mode 100644
index 00000000..13b460a8
--- /dev/null
+++ b/docs/assets/home.html.4d8cac8a.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-6a609e09","path":"/zh-cn/guide/home.html","title":"\u4ECB\u7ECD","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u80CC\u666F","slug":"\u80CC\u666F","link":"#\u80CC\u666F","children":[]},{"level":2,"title":"\u7528\u9014","slug":"\u7528\u9014","link":"#\u7528\u9014","children":[]},{"level":2,"title":"\u8BED\u8A00\u8981\u6C42","slug":"\u8BED\u8A00\u8981\u6C42","link":"#\u8BED\u8A00\u8981\u6C42","children":[]},{"level":2,"title":"\u7075\u611F\u6765\u6E90","slug":"\u7075\u611F\u6765\u6E90","link":"#\u7075\u611F\u6765\u6E90","children":[]},{"level":2,"title":"\u652F\u6301\u7684 Hook \u6846\u67B6","slug":"\u652F\u6301\u7684-hook-\u6846\u67B6","link":"#\u652F\u6301\u7684-hook-\u6846\u67B6","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/guide/home.md"}');export{e as data};
diff --git a/docs/assets/home.html.6cc8b4b8.js b/docs/assets/home.html.6cc8b4b8.js
new file mode 100644
index 00000000..6409bb37
--- /dev/null
+++ b/docs/assets/home.html.6cc8b4b8.js
@@ -0,0 +1,107 @@
+import{_ as i,r as o,o as p,c as d,b as s,d as l,w as a,e,a as r}from"./app.fb8271cf.js";const A={},u=s("h1",{id:"introduce",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#introduce","aria-hidden":"true"},"#"),e(" Introduce")],-1),y=s("blockquote",null,[s("p",null,"This is a Hook API Framework, it does not provide any Hook function itself, it needs the support of basic Xposed API.")],-1),m=s("h2",{id:"background",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#background","aria-hidden":"true"},"#"),e(" Background")],-1),h=s("p",null,[e("This is an efficient Xposed Hook API rebuilt in "),s("code",null,"Kotlin"),e(".")],-1),D=e("The name is taken from "),C={href:"https://www.bilibili.com/bangumi/play/ss5016",target:"_blank",rel:"noopener noreferrer"},B=e('"\u3082\u3082\u304F\u308A" heroine Yuki Kurihara'),_=e("."),b=e("Formerly the Innocent Xposed API used in "),v={href:"https://github.com/fankes/TMore",target:"_blank",rel:"noopener noreferrer"},F=e("Development Learning Project"),k=e(", now renamed and open sourced."),f=r(' Usage
YukiHookAPI
is built entirely with Kotlin
lambda
syntax.XposedHelpers
, you can use it to easily create Xposed Modules and easily implement custom Hook API. Language Requirement
Kotlin
, the framework part of the code composition is also compatible with Java
but the implementation of the basic Hook scene may not work at all.Kotlin
, if you don't know how to use Kotlin
then you may not be able to use YukiHookAPI
. Source of Inspiration
xposed_init
file under assets
.XposedHelpers
to implement our Hook logic.Kotlin
is the main Android development language, this API is really not very elegant to use.YukiHookAPI
was born.Kotlin
's elegant lambda
writing and YukiHookAPI
, you can make your Hook logic more beautiful and clear.
',9),X=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"@InjectYukiHookWithXposed")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"class"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"HookEntry"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"IYukiHookXposedInit"),s("span",{style:{color:"#ADBAC7"}}," {")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"onHook"),s("span",{style:{color:"#ADBAC7"}},"() "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," encase {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," loadZygote {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"ActivityClass"),s("span",{style:{color:"#ADBAC7"}},".hook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectMember {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," method {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"onCreate"')]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param("),s("span",{style:{color:"#F69D50"}},"BundleClass"),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," beforeHook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your code here.")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," afterHook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your code here.")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resources().hook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectResource {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," conditions {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"sym_def_app_icon"')]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," mipmap()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," replaceToModuleResource("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," loadApp(name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.android.browser"'),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"ActivityClass"),s("span",{style:{color:"#ADBAC7"}},".hook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectMember {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," method {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"onCreate"')]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param("),s("span",{style:{color:"#F69D50"}},"BundleClass"),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," beforeHook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your code here.")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," afterHook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Your code here.")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resources().hook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectResource {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," conditions {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"ic_launcher"')]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," mipmap()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," replaceToModuleResource("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),x=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"class"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"HookEntry"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"IXposedHookZygoteInit"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#F69D50"}},"IXposedHookLoadPackage"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#F69D50"}},"IXposedHookInitPackageResources"),s("span",{style:{color:"#ADBAC7"}}," {")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"private"),s("span",{style:{color:"#ADBAC7"}}," lateinit "),s("span",{style:{color:"#F47067"}},"var"),s("span",{style:{color:"#ADBAC7"}}," moduleResources"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XModuleResources")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"initZygote"),s("span",{style:{color:"#ADBAC7"}},"(sparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"IXposedHookZygoteInit"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"StartupParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XModuleResources"),s("span",{style:{color:"#ADBAC7"}},".createInstance(sparam.modulePath, "),s("span",{style:{color:"#6CB6FF"}},"null"),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XResources"),s("span",{style:{color:"#ADBAC7"}},".setSystemWideReplacement(")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"android"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"mipmap"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"sym_def_app_icon"'),s("span",{style:{color:"#ADBAC7"}},",")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources.fwd("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," )")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XposedHelpers"),s("span",{style:{color:"#ADBAC7"}},".findAndHookMethod(")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," Activity::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java.name,")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"null"),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"onCreate"'),s("span",{style:{color:"#ADBAC7"}},",")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," Bundle::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java,")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"object"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_MethodHook"),s("span",{style:{color:"#ADBAC7"}},"() {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun beforeHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam?"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Your"),s("span",{style:{color:"#ADBAC7"}}," code here.")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun afterHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam?"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Your"),s("span",{style:{color:"#ADBAC7"}}," code here.")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," })")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"handleLoadPackage"),s("span",{style:{color:"#ADBAC7"}},"(lpparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_LoadPackage"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"LoadPackageParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"if"),s("span",{style:{color:"#ADBAC7"}}," (lpparam.packageName "),s("span",{style:{color:"#F47067"}},"=="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.android.browser"'),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XposedHelpers"),s("span",{style:{color:"#ADBAC7"}},".findAndHookMethod(")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," Activity::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java.name,")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," lpparam.classLoader, "),s("span",{style:{color:"#96D0FF"}},'"onCreate"'),s("span",{style:{color:"#ADBAC7"}},",")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," Bundle::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java,")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"object"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_MethodHook"),s("span",{style:{color:"#ADBAC7"}},"() {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun beforeHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam?"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Your"),s("span",{style:{color:"#ADBAC7"}}," code here.")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun afterHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam?"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Your"),s("span",{style:{color:"#ADBAC7"}}," code here.")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," })")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"handleInitPackageResources"),s("span",{style:{color:"#ADBAC7"}},"(resparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_InitPackageResources"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"InitPackageResourcesParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"if"),s("span",{style:{color:"#ADBAC7"}}," (resparam.packageName "),s("span",{style:{color:"#F47067"}},"=="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.android.browser"'),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resparam.res.setReplacement(")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.android.browser"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"mipmap"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"ic_launcher"'),s("span",{style:{color:"#ADBAC7"}},",")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources.fwd("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," )")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),M=s("p",null,"Yes, you read that right, just needing these codes can completely replace the Xposed API to achieve the same function.",-1),R=s("p",null,[e("Now, with the help of the efficient and powerful "),s("code",null,"YukiHookAPI"),e(", you can implement a very simple Xposed Module.")],-1),Y=s("h2",{id:"suppored-hook-framework",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#suppored-hook-framework","aria-hidden":"true"},"#"),e(" Suppored Hook Framework")],-1),L=s("p",null,[e("The following are the "),s("code",null,"Hook Framework"),e(" and Xposed framework supported by "),s("code",null,"YukiHookAPI"),e(".")],-1),S=s("thead",null,[s("tr",null,[s("th",null,"Hook Framework"),s("th",null,"ST"),s("th",null,"Description")])],-1),j={href:"https://github.com/LSPosed/LSPosed",target:"_blank",rel:"noopener noreferrer"},N=e("LSPosed"),T=s("td",null,"\u2705",-1),E=s("td",null,"Stable use in multiple scenarios",-1),K={href:"https://github.com/LSPosed/LSPatch",target:"_blank",rel:"noopener noreferrer"},W=e("LSPatch"),q=s("td",null,"\u2B55",-1),G=s("td",null,"WIP after this project is improved",-1),V={href:"https://github.com/ElderDrivers/EdXposed",target:"_blank",rel:"noopener noreferrer"},Z=e("EdXposed"),O=s("td",null,"\u274E",-1),J=s("td",null,"Maintenance has stopped, no longer recommended",-1),U={href:"https://github.com/canyie/pine",target:"_blank",rel:"noopener noreferrer"},z=e("Pine"),Q=s("td",null,"\u2B55",-1),$=s("td",null,"Only available",-1),ss={href:"https://github.com/asLody/SandHook",target:"_blank",rel:"noopener noreferrer"},es=e("SandHook"),ls=s("td",null,"\u2B55",-1),ns=s("td",null,"Only available",-1),os={href:"https://github.com/asLody/whale",target:"_blank",rel:"noopener noreferrer"},as=e("Whale"),ts=s("td",null,"\u2B55",-1),rs=e("Need "),cs={href:"https://github.com/WindySha/xposed-hook-based-on-whale",target:"_blank",rel:"noopener noreferrer"},is=e("xposed-hook-based-on-whale"),ps={href:"https://github.com/PAGalaxyLab/YAHFA",target:"_blank",rel:"noopener noreferrer"},ds=e("YAHFA"),As=s("td",null,"\u2757",-1),us=s("td",null,"Need to implement the Xposed API yourself",-1),ys={href:"https://github.com/turing-technician/FastHook",target:"_blank",rel:"noopener noreferrer"},ms=e("FastHook"),hs=s("td",null,"\u2757",-1),Ds=s("td",null,"Need to implement the Xposed API yourself",-1),Cs={href:"https://github.com/tiann/epic",target:"_blank",rel:"noopener noreferrer"},Bs=e("Epic"),_s=s("td",null,"\u2757",-1),bs=e("Need "),vs={href:"https://github.com/alibaba/dexposed",target:"_blank",rel:"noopener noreferrer"},Fs=e("Dexposed"),ks=e(" by yourself"),fs={href:"https://github.com/taichi-framework/TaiChi",target:"_blank",rel:"noopener noreferrer"},gs=e("TaiChi"),Hs=s("td",null,"\u2B55",-1),Ps=s("td",null,"Only available for Xposed Module",-1),ws={href:"https://github.com/rovo89/Xposed",target:"_blank",rel:"noopener noreferrer"},Is=e("Xposed"),Xs=s("td",null,"\u274E",-1),xs=s("td",null,"Not test, no longer recommended",-1);function Ms(Rs,Ys){const n=o("ExternalLinkIcon"),t=o("CodeGroupItem"),c=o("CodeGroup");return p(),d("div",null,[u,y,m,h,s("p",null,[D,s("a",C,[B,l(n)]),_]),s("p",null,[b,s("a",v,[F,l(n)]),k]),f,s("p",null,[g,s("a",H,[P,l(n)]),w]),I,l(c,null,{default:a(()=>[l(t,{title:"Yuki Hook API"},{default:a(()=>[X]),_:1}),l(t,{title:"Xposed API"},{default:a(()=>[x]),_:1})]),_:1}),M,R,Y,L,s("table",null,[S,s("tbody",null,[s("tr",null,[s("td",null,[s("a",j,[N,l(n)])]),T,E]),s("tr",null,[s("td",null,[s("a",K,[W,l(n)])]),q,G]),s("tr",null,[s("td",null,[s("a",V,[Z,l(n)])]),O,J]),s("tr",null,[s("td",null,[s("a",U,[z,l(n)])]),Q,$]),s("tr",null,[s("td",null,[s("a",ss,[es,l(n)])]),ls,ns]),s("tr",null,[s("td",null,[s("a",os,[as,l(n)])]),ts,s("td",null,[rs,s("a",cs,[is,l(n)])])]),s("tr",null,[s("td",null,[s("a",ps,[ds,l(n)])]),As,us]),s("tr",null,[s("td",null,[s("a",ys,[ms,l(n)])]),hs,Ds]),s("tr",null,[s("td",null,[s("a",Cs,[Bs,l(n)])]),_s,s("td",null,[bs,s("a",vs,[Fs,l(n)]),ks])]),s("tr",null,[s("td",null,[s("a",fs,[gs,l(n)])]),Hs,Ps]),s("tr",null,[s("td",null,[s("a",ws,[Is,l(n)])]),Xs,xs])])])])}const Ss=i(A,[["render",Ms],["__file","home.html.vue"]]);export{Ss as default};
diff --git a/docs/assets/home.html.cad3998c.js b/docs/assets/home.html.cad3998c.js
new file mode 100644
index 00000000..1032cad0
--- /dev/null
+++ b/docs/assets/home.html.cad3998c.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-c8deafb2","path":"/zh-cn/api/home.html","title":"\u6587\u6863\u4ECB\u7ECD","lang":"zh-CN","frontmatter":{"next":{"text":"Public API","link":"/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI"}},"excerpt":"","headers":[{"level":2,"title":"\u529F\u80FD\u63CF\u8FF0\u8BF4\u660E","slug":"\u529F\u80FD\u63CF\u8FF0\u8BF4\u660E","link":"#\u529F\u80FD\u63CF\u8FF0\u8BF4\u660E","children":[]},{"level":2,"title":"\u529F\u80FD\u793A\u4F8B\u8BF4\u660E","slug":"\u529F\u80FD\u793A\u4F8B\u8BF4\u660E","link":"#\u529F\u80FD\u793A\u4F8B\u8BF4\u660E","children":[]},{"level":2,"title":"\u53D8\u66F4\u8BB0\u5F55\u8BF4\u660E","slug":"\u53D8\u66F4\u8BB0\u5F55\u8BF4\u660E","link":"#\u53D8\u66F4\u8BB0\u5F55\u8BF4\u660E","children":[]},{"level":2,"title":"\u76F8\u5173\u7B26\u53F7\u8BF4\u660E","slug":"\u76F8\u5173\u7B26\u53F7\u8BF4\u660E","link":"#\u76F8\u5173\u7B26\u53F7\u8BF4\u660E","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/home.md"}');export{e as data};
diff --git a/docs/assets/home.html.e164d825.js b/docs/assets/home.html.e164d825.js
new file mode 100644
index 00000000..f86b188b
--- /dev/null
+++ b/docs/assets/home.html.e164d825.js
@@ -0,0 +1 @@
+import{_ as e,o,c as i,a as d}from"./app.fb8271cf.js";const c={},t=d(' \u6587\u6863\u4ECB\u7ECD
YukiHookAPI
\u4E3A\u6700\u65B0\u7248\u672C\u4EE5\u4F7F\u7528\u6700\u65B0\u7248\u672C\u7684\u529F\u80FD\u3002 \u529F\u80FD\u63CF\u8FF0\u8BF4\u660E
\u529F\u80FD\u793A\u4F8B\u8BF4\u660E
\u53D8\u66F4\u8BB0\u5F55\u8BF4\u660E
v<version>
\u6DFB\u52A0
\uFF1Bv<version>
\u65B0\u589E
\uFF1Bv<version>
\u4FEE\u6539
\uFF1Bv<version>
\u4F5C\u5E9F
\u5E76\u4F1A\u6807\u6CE8\u5220\u9664\u7EBF\uFF1Bv<version>
\u79FB\u9664
\u5E76\u4F1A\u6807\u6CE8\u5220\u9664\u7EBF\u3002 \u76F8\u5173\u7B26\u53F7\u8BF4\u660E
',14),a=[t];function l(p,r){return o(),i("div",null,a)}const n=e(c,[["render",l],["__file","home.html.vue"]]);export{n as default};
diff --git a/docs/assets/home.html.f6b9c2a4.js b/docs/assets/home.html.f6b9c2a4.js
new file mode 100644
index 00000000..259cee03
--- /dev/null
+++ b/docs/assets/home.html.f6b9c2a4.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-64fc7bb8","path":"/en/api/home.html","title":"Document Introduce","lang":"en-US","frontmatter":{"next":{"text":"Public API","link":"/en/api/public/com/highcapable/yukihookapi/YukiHookAPI"}},"excerpt":"","headers":[{"level":2,"title":"Function Description","slug":"function-description","link":"#function-description","children":[]},{"level":2,"title":"Function Example Description","slug":"function-example-description","link":"#function-example-description","children":[]},{"level":2,"title":"Change Record Description","slug":"change-record-description","link":"#change-record-description","children":[]},{"level":2,"title":"Related Symbols Description","slug":"related-symbols-description","link":"#related-symbols-description","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/home.md"}');export{e as data};
diff --git a/docs/assets/home.html.f6f658d0.js b/docs/assets/home.html.f6f658d0.js
new file mode 100644
index 00000000..5431897b
--- /dev/null
+++ b/docs/assets/home.html.f6f658d0.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-efb45d4c","path":"/en/guide/home.html","title":"Introduce","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Background","slug":"background","link":"#background","children":[]},{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[]},{"level":2,"title":"Language Requirement","slug":"language-requirement","link":"#language-requirement","children":[]},{"level":2,"title":"Source of Inspiration","slug":"source-of-inspiration","link":"#source-of-inspiration","children":[]},{"level":2,"title":"Suppored Hook Framework","slug":"suppored-hook-framework","link":"#suppored-hook-framework","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/guide/home.md"}');export{e as data};
diff --git a/docs/assets/home.html.fd8a27c6.js b/docs/assets/home.html.fd8a27c6.js
new file mode 100644
index 00000000..34fb22c9
--- /dev/null
+++ b/docs/assets/home.html.fd8a27c6.js
@@ -0,0 +1 @@
+import{_ as e,o,c as t,a as i}from"./app.fb8271cf.js";const n={},d=i('get
\u3001set
\u65B9\u6CD5\u6216\u53EA\u8BFB\u7684 get
\u65B9\u6CD5 Document Introduce
YukiHookAPI
as the latest version to use the latest version of the function. Function Description
Function Example Description
Change Record Description
v<version>
first
;v<version>
added
;v<version>
modified
;v<version>
deprecated
and strikethrough;v<version>
removed
and strikethrough. Related Symbols Description
',14),a=[d];function c(r,l){return o(),t("div",null,a)}const p=e(n,[["render",c],["__file","home.html.vue"]]);export{p as default};
diff --git a/docs/assets/host-inject.html.83f072dc.js b/docs/assets/host-inject.html.83f072dc.js
new file mode 100644
index 00000000..73fa0fda
--- /dev/null
+++ b/docs/assets/host-inject.html.83f072dc.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-6ac5be8e","path":"/zh-cn/api/special-features/host-inject.html","title":"\u5BBF\u4E3B\u8D44\u6E90\u6CE8\u5165\u6269\u5C55","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u6CE8\u5165\u6A21\u5757\u8D44\u6E90 (Resources)","slug":"\u6CE8\u5165\u6A21\u5757\u8D44\u6E90-resources","link":"#\u6CE8\u5165\u6A21\u5757\u8D44\u6E90-resources","children":[]},{"level":2,"title":"\u6CE8\u518C\u6A21\u5757 Activity","slug":"\u6CE8\u518C\u6A21\u5757-activity","link":"#\u6CE8\u518C\u6A21\u5757-activity","children":[]},{"level":2,"title":"\u521B\u5EFA ContextThemeWrapper \u4EE3\u7406","slug":"\u521B\u5EFA-contextthemewrapper-\u4EE3\u7406","link":"#\u521B\u5EFA-contextthemewrapper-\u4EE3\u7406","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/special-features/host-inject.md"}');export{e as data};
diff --git a/docs/assets/host-inject.html.acabeb56.js b/docs/assets/host-inject.html.acabeb56.js
new file mode 100644
index 00000000..8cb1da0b
--- /dev/null
+++ b/docs/assets/host-inject.html.acabeb56.js
@@ -0,0 +1,118 @@
+import{_ as l,r as e,o,c as p,b as s,d as c,a as t,e as n}from"./app.fb8271cf.js";const i={},r=t(`get
/ set
method or read-only get
method \u5BBF\u4E3B\u8D44\u6E90\u6CE8\u5165\u6269\u5C55
Activity
\u7EC4\u4EF6\u4EE5\u53CA Context
\u4E3B\u9898\u6CE8\u5165\u5230\u5BBF\u4E3B\u7684\u6269\u5C55\u529F\u80FD\u3002build.gradle
\u4E2D\u4FEE\u6539\u8D44\u6E90 ID\u3002android {
+ androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
+}
+
android {
+ aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
+}
+
\u6CE8\u5165\u6A21\u5757\u8D44\u6E90 (Resources)
Context
\u6CE8\u5165\u5F53\u524D\u6A21\u5757\u8D44\u6E90\u3002injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ instance<Activity>().also {
+ // <\u65B9\u68481> \u901A\u8FC7 Context \u6CE8\u5165\u6A21\u5757\u8D44\u6E90
+ it.injectModuleAppResources()
+ // <\u65B9\u68482> \u76F4\u63A5\u5F97\u5230\u5BBF\u4E3B Resources \u6CE8\u5165\u6A21\u5757\u8D44\u6E90
+ it.resources.injectModuleAppResources()
+ // \u76F4\u63A5\u4F7F\u7528\u6A21\u5757\u8D44\u6E90 ID
+ it.getString(R.id.app_name)
+ }
+ }
+}
+
AppLifecycle
\u4E2D\u6CE8\u5165\u5F53\u524D\u6A21\u5757\u8D44\u6E90\u3002onAppLifecycle {
+ onCreate {
+ // \u5168\u5C40\u6CE8\u5165\u6A21\u5757\u8D44\u6E90\uFF0C\u4F46\u4EC5\u9650\u4E8E\u5168\u5C40\u751F\u547D\u5468\u671F
+ // \u7C7B\u4F3C ImageView.setImageResource \u8FD9\u6837\u7684\u65B9\u6CD5\u5728 Activity \u4E2D\u9700\u8981\u5355\u72EC\u6CE8\u5165
+ // <\u65B9\u68481> \u901A\u8FC7 Context \u6CE8\u5165\u6A21\u5757\u8D44\u6E90
+ injectModuleAppResources()
+ // <\u65B9\u68482> \u76F4\u63A5\u5F97\u5230\u5BBF\u4E3B Resources \u6CE8\u5165\u6A21\u5757\u8D44\u6E90
+ resources.injectModuleAppResources()
+ // \u76F4\u63A5\u4F7F\u7528\u6A21\u5757\u8D44\u6E90 ID
+ getString(R.id.app_name)
+ }
+}
+
\u6CE8\u518C\u6A21\u5757 Activity
Activity
\u542F\u52A8\u65F6\uFF0C\u90FD\u9700\u8981\u5728 AndroidManifest.xml
\u4E2D\u8FDB\u884C\u6CE8\u518C\uFF0C\u5728 Hook \u8FC7\u7A0B\u4E2D\uFF0C\u5982\u679C\u6211\u4EEC\u60F3\u901A\u8FC7\u5BBF\u4E3B\u6765\u76F4\u63A5\u542F\u52A8\u6A21\u5757\u4E2D\u672A\u6CE8\u518C\u7684 Activity
\u8981\u600E\u4E48\u505A\u5462\uFF1FContext
\u6CE8\u518C\u5F53\u524D\u6A21\u5757\u7684 Activity
\u4EE3\u7406\u3002injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ instance<Activity>().registerModuleAppActivities()
+ }
+}
+
AppLifecycle
\u4E2D\u6CE8\u518C\u5F53\u524D\u6A21\u5757\u7684 Activity
\u4EE3\u7406\u3002onAppLifecycle {
+ onCreate {
+ registerModuleAppActivities()
+ }
+}
+
proxy
\u53C2\u6570\uFF0CAPI \u5C06\u4F1A\u6839\u636E\u5F53\u524D Context
\u81EA\u52A8\u83B7\u53D6\u5F53\u524D\u5BBF\u4E3B\u7684\u542F\u52A8\u5165\u53E3 Activity
\u8FDB\u884C\u4EE3\u7406\u3002Activity
\u4F1A\u5728\u6CE8\u518C\u6E05\u5355\u4E0A\u52A0\u5165\u542F\u52A8\u53C2\u6570\uFF0C\u90A3\u4E48\u6211\u4EEC\u5C31\u9700\u8981\u4F7F\u7528\u53E6\u4E00\u79CD\u89E3\u51B3\u65B9\u6848\u3002Activity
\u4E0D\u80FD\u88AB\u6B63\u786E\u542F\u52A8\uFF0C\u6211\u4EEC\u53EF\u4EE5\u624B\u52A8\u62FF\u5230\u5BBF\u4E3B\u7684 AndroidManifest.xml
\u8FDB\u884C\u5206\u6790\uFF0C\u6765\u5F97\u5230\u4E00\u4E2A\u6CE8\u518C\u8FC7\u7684 Activity
\u6807\u7B7E\uFF0C\u83B7\u53D6\u5176\u4E2D\u7684 name
\u3002Activity
\u4F5C\u4E3A\u4E00\u4E2A\u201C\u5080\u5121\u201D\u5C06\u5176\u8FDB\u884C\u4EE3\u7406\uFF0C\u901A\u5E38\u662F\u6709\u6548\u7684\u3002Activity
\u3002<activity
+ android:name="com.demo.test.activity.TestActivity"
+ ...>
+
name
\uFF0C\u6211\u4EEC\u53EA\u9700\u8981\u5728\u65B9\u6CD5\u4E2D\u52A0\u5165\u8FD9\u4E2A\u53C2\u6570\u8FDB\u884C\u6CE8\u518C\u5373\u53EF\u3002registerModuleAppActivities(proxy = "com.demo.test.activity.TestActivity")
+
stub
\uFF0C\u90A3\u4E48\u4F60\u53EF\u4EE5\u76F4\u63A5\u901A\u8FC7 Class
\u5BF9\u8C61\u6765\u8FDB\u884C\u6CE8\u518C\u3002registerModuleAppActivities(TestActivity::class.java)
+
Activity
\u7EE7\u627F\u4E8E ModuleAppActivity
\u6216 ModuleAppCompatActivity
\u3002Activity
\u73B0\u5728\u65E0\u9700\u6CE8\u518C\u5373\u53EF\u65E0\u7F1D\u5B58\u6D3B\u4E8E\u5BBF\u4E3B\u4E2D\u3002class HostTestActivity : ModuleAppActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // \u6A21\u5757\u8D44\u6E90\u5DF2\u88AB\u81EA\u52A8\u6CE8\u5165\uFF0C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 xml \u88C5\u8F7D\u5E03\u5C40
+ setContentView(R.layout.activity_main)
+ }
+}
+
ModuleAppCompatActivity
\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u8BBE\u7F6E AppCompat \u4E3B\u9898\u3002class HostTestActivity : ModuleAppCompatActivity() {
+
+ // \u8FD9\u91CC\u7684\u4E3B\u9898\u540D\u79F0\u4EC5\u4F9B\u53C2\u8003\uFF0C\u8BF7\u586B\u5199\u4F60\u6A21\u5757\u4E2D\u5DF2\u6709\u7684\u4E3B\u9898\u540D\u79F0
+ override val moduleTheme get() = R.style.Theme_AppCompat
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // \u6A21\u5757\u8D44\u6E90\u5DF2\u88AB\u81EA\u52A8\u6CE8\u5165\uFF0C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 xml \u88C5\u8F7D\u5E03\u5C40
+ setContentView(R.layout.activity_main)
+ }
+}
+
Context
\u7684\u5730\u65B9\u6109\u5FEB\u5730\u8C03\u7528 startActivity
\u4E86\u3002val context: Context = ... // \u5047\u8BBE\u8FD9\u5C31\u662F\u4F60\u7684 Context
+context.startActivity(context, HostTestActivity::class.java)
+
\u521B\u5EFA ContextThemeWrapper \u4EE3\u7406
MaterialAlertDialogBuilder
\u6765\u7F8E\u5316\u81EA\u5DF1\u5728\u5BBF\u4E3B\u4E2D\u7684\u5BF9\u8BDD\u6846\uFF0C\u4F46\u662F\u62FF\u4E0D\u5230 AppCompat \u4E3B\u9898\u5C31\u65E0\u6CD5\u521B\u5EFA\u3002The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
+
Activity
\u4E2D\u4F7F\u7528 MaterialAlertDialogBuilder
\u6765\u521B\u5EFA\u5BF9\u8BDD\u6846\uFF0C\u5C31\u53EF\u4EE5\u6709\u5982\u4E0B\u65B9\u6CD5\u3002injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ // \u4F7F\u7528 applyModuleTheme \u521B\u5EFA\u4E00\u4E2A\u5F53\u524D\u6A21\u5757\u4E2D\u7684\u4E3B\u9898\u8D44\u6E90
+ val appCompatContext = instance<Activity>().applyModuleTheme(R.style.Theme_AppCompat)
+ // \u76F4\u63A5\u4F7F\u7528\u8FD9\u4E2A\u5305\u88C5\u4E86\u6A21\u5757\u4E3B\u9898\u540E\u7684 Context \u521B\u5EFA\u5BF9\u8BDD\u6846
+ MaterialAlertDialogBuilder(appCompatContext)
+ .setTitle("AppCompat \u4E3B\u9898\u5BF9\u8BDD\u6846")
+ .setMessage("\u6211\u662F\u4E00\u4E2A\u5728\u5BBF\u4E3B\u4E2D\u663E\u793A\u7684 AppCompat \u4E3B\u9898\u5BF9\u8BDD\u6846\u3002")
+ .setPositiveButton("\u786E\u5B9A", null)
+ .show()
+ }
+}
+
Context
\u901A\u8FC7 uiMode
\u8BBE\u7F6E\u539F\u751F\u7684\u591C\u95F4\u6A21\u5F0F\u548C\u65E5\u95F4\u6A21\u5F0F\uFF0C\u81F3\u5C11\u9700\u8981 Android 10 \u53CA\u4EE5\u4E0A\u7CFB\u7EDF\u7248\u672C\u652F\u6301\u4E14\u5F53\u524D\u4E3B\u9898\u5305\u542B\u591C\u95F4\u6A21\u5F0F\u76F8\u5173\u5143\u7D20\u3002injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ // \u5B9A\u4E49\u5F53\u524D\u6A21\u5757\u4E2D\u7684\u4E3B\u9898\u8D44\u6E90
+ var appCompatContext: ModuleContextThemeWrapper
+ // <\u65B9\u68481> \u76F4\u63A5\u5F97\u5230 Configuration \u5BF9\u8C61\u8FDB\u884C\u8BBE\u7F6E
+ appCompatContext = instance<Activity>()
+ .applyModuleTheme(R.style.Theme_AppCompat)
+ .applyConfiguration { uiMode = Configuration.UI_MODE_NIGHT_YES }
+ // <\u65B9\u68482> \u521B\u5EFA\u4E00\u4E2A\u65B0\u7684 Configuration \u5BF9\u8C61
+ // \u6B64\u65B9\u6848\u4F1A\u7834\u574F\u5F53\u524D\u5BBF\u4E3B\u4E2D\u539F\u6709\u7684\u5B57\u4F53\u7F29\u653E\u5927\u5C0F\u7B49\u8BBE\u7F6E\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u91CD\u65B0\u4F20\u9012 densityDpi \u7B49\u53C2\u6570
+ appCompatContext = instance<Activity>().applyModuleTheme(
+ theme = R.style.Theme_AppCompat,
+ configuration = Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES }
+ )
+ // \u76F4\u63A5\u4F7F\u7528\u8FD9\u4E2A\u5305\u88C5\u4E86\u6A21\u5757\u4E3B\u9898\u540E\u7684 Context \u521B\u5EFA\u5BF9\u8BDD\u6846
+ MaterialAlertDialogBuilder(appCompatContext)
+ .setTitle("AppCompat \u4E3B\u9898\u5BF9\u8BDD\u6846")
+ .setMessage("\u6211\u662F\u4E00\u4E2A\u5728\u5BBF\u4E3B\u4E2D\u663E\u793A\u7684 AppCompat \u4E3B\u9898\u5BF9\u8BDD\u6846\u3002")
+ .setPositiveButton("\u786E\u5B9A", null)
+ .show()
+ }
+}
+
MaterialAlertDialogBuilder
\u521B\u5EFA\u5BF9\u8BDD\u6846\u4E86\u3002 Host Resource Injection Extension
Activity
components, and Context
topics into the Host App.build.gradle
of the current Xposed Module project.android {
+ androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
+}
+
android {
+ aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
+}
+
Inject Module App's Resources
Context
obtained in the Hooker into the current Module App's Resources.injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ instance<Activity>().also {
+ // <Scenario 1> Inject Module App's Resources through Context
+ it.injectModuleAppResources()
+ // <Scenario 2> Get the Host App's Resources directly and inject the Module App's Resources
+ it.resources.injectModuleAppResources()
+ // Use the Module App's Resource Id directly
+ it.getString(R.id.app_name)
+ }
+ }
+}
+
AppLifecycle
.onAppLifecycle {
+ onCreate {
+ // Globally inject Module App's Resources, but only in the global lifecycle
+ // Methods like ImageView.setImageResource need to be injected separately in Activity
+ // <Scenario 1> Inject Module App's Resources through Context
+ injectModuleAppResources()
+ // <Scenario 2> Get the Host App's Resources directly and inject the Module App's Resources
+ resources.injectModuleAppResources()
+ // Use the Module App's Resource Id directly
+ getString(R.id.app_name)
+ }
+}
+
Register Module App's Activity
Activity
of all applications in the Android system starts, it needs to be registered in AndroidManifest.xml
.Activity
in the Module App through the Host App, what should we do?Activity
proxy of the current Module App in the Context
obtained in the Hooker.injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ instance<Activity>().registerModuleAppActivities()
+ }
+}
+
Activity
proxy directly in AppLifecycle
.onAppLifecycle {
+ onCreate {
+ registerModuleAppActivities()
+ }
+}
+
proxy
parameter is not filled in, the API will automatically obtain the current Host App's launching entry Activity
for proxying according to the current Context
.Activity
will add launching parameters to the registration list, so we need to use another solution.Activity
cannot be launched correctly, we can manually get the Host App's AndroidManifest.xml
for analysis to get a registered Activity
tag and get the name
.Activity
that may not be used by the current Host App as a "puppet" to proxy it, which usually works.Activity
that can be proxied.<activity
+ android:name="com.demo.test.activity.TestActivity"
+ ...>
+
name
, we only need to add this parameter to the method for registration.registerModuleAppActivities(proxy = "com.demo.test.activity.TestActivity")
+
stub
for the Host App's class, you can register it directly through the Class
object.registerModuleAppActivities(TestActivity::class.java)
+
Activity
in the Module App you need to use the Host App to start by ModuleAppActivity
or ModuleAppCompatActivity
.Activity
now live seamlessly in the Host App without registration.class HostTestActivity : ModuleAppActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Module App's Resources have been injected automatically
+ // You can directly use xml to load the layout
+ setContentView(R.layout.activity_main)
+ }
+}
+
ModuleAppCompatActivity
, you need to set the AppCompat theme manually.class HostTestActivity : ModuleAppCompatActivity() {
+
+ // The theme name here is for reference only
+ // Please fill in the theme name already in your Module App
+ override val moduleTheme get() = R.style.Theme_AppCompat
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Module App's Resources have been injected automatically
+ // You can directly use xml to load the layout
+ setContentView(R.layout.activity_main)
+ }
+}
+
startActivity
anywhere in the (Xposed) Host environment where a Context
exists.val context: Context = ... // Assume this is your Context
+context.startActivity(context, HostTestActivity::class.java)
+
Create ContextThemeWrapper Proxy
MaterialAlertDialogBuilder
to beautify our own dialogs in the Host App, but we can't create them without the AppCompat theme.The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
+
MaterialAlertDialogBuilder
to create a dialog in the current Activity
of the Host App being hooked, you can have the following methods.injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ // Use applyModuleTheme to create a theme resource in the current Module App
+ val appCompatContext = instance<Activity>().applyModuleTheme(R.style.Theme_AppCompat)
+ // Directly use this Context that wraps the Module App's theme to create a dialog
+ MaterialAlertDialogBuilder(appCompatContext)
+ .setTitle("AppCompat Theme Dialog")
+ .setMessage("I am an AppCompat theme dialog displayed in the Host App.")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+}
+
Context
through uiMode
.injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ // Define the theme resource in the current Module App
+ var appCompatContext: ModuleContextThemeWrapper
+ // <Scenario 1> Get the Configuration object directly to set
+ appCompatContext = instance<Activity>()
+ .applyModuleTheme(R.style.Theme_AppCompat)
+ .applyConfiguration { uiMode = Configuration.UI_MODE_NIGHT_YES }
+ // <Scenario 2> Create a new Configuration object
+ // This solution will destroy the original font scaling and other settings in the current Host App
+ // You need to manually re-pass parameters such as densityDpi
+ appCompatContext = instance<Activity>().applyModuleTheme(
+ theme = R.style.Theme_AppCompat,
+ configuration = Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES }
+ )
+ // Directly use this Context that wraps the Module App's theme to create a dialog
+ MaterialAlertDialogBuilder(appCompatContext)
+ .setTitle("AppCompat Theme Dialog")
+ .setMessage("I am an AppCompat theme dialog displayed in the Host App.")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+}
+
MaterialAlertDialogBuilder
. \u5BBF\u4E3B\u751F\u547D\u5468\u671F\u6269\u5C55
\u76D1\u542C\u751F\u547D\u5468\u671F
Application
\u7684\u542F\u52A8\u548C\u751F\u547D\u5468\u671F\u65B9\u6CD5\uFF0C\u53EA\u9700\u8981\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u5B9E\u73B0\u3002loadApp(name = "com.example.demo") {
+ // \u6CE8\u518C\u751F\u547D\u5468\u671F\u76D1\u542C
+ onAppLifecycle {
+ // \u4F60\u53EF\u4EE5\u5728\u8FD9\u91CC\u5B9E\u73B0 Application \u4E2D\u7684\u751F\u547D\u5468\u671F\u65B9\u6CD5\u76D1\u542C
+ attachBaseContext { baseContext, hasCalledSuper ->
+ // \u901A\u8FC7\u5224\u65AD hasCalledSuper \u6765\u786E\u5B9A\u662F\u5426\u5DF2\u6267\u884C super.attachBaseContext(base) \u65B9\u6CD5
+ // ...
+ }
+ onCreate {
+ // \u901A\u8FC7 this \u5F97\u5230\u5F53\u524D Application \u5B9E\u4F8B
+ // ...
+ }
+ onTerminate {
+ // \u901A\u8FC7 this \u5F97\u5230\u5F53\u524D Application \u5B9E\u4F8B
+ // ...
+ }
+ onLowMemory {
+ // \u901A\u8FC7 this \u5F97\u5230\u5F53\u524D Application \u5B9E\u4F8B
+ // ...
+ }
+ onTrimMemory { self, level ->
+ // \u53EF\u5728\u8FD9\u91CC\u5224\u65AD APP \u662F\u5426\u5DF2\u5207\u6362\u5230\u540E\u53F0
+ if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+ // ...
+ }
+ // ...
+ }
+ onConfigurationChanged { self, config ->
+ // ...
+ }
+ }
+}
+
\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD
Application.onCreate
\u65B9\u6CD5\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\uFF0C\u6765\u5B9E\u73B0\u5BF9\u7CFB\u7EDF\u5E7F\u64AD\u7684\u76D1\u542C\u3002Application
\u4E2D\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\u3002loadApp(name = "com.example.demo") {
+ // \u6CE8\u518C\u751F\u547D\u5468\u671F\u76D1\u542C
+ onAppLifecycle {
+ // \u6CE8\u518C\u7528\u6237\u89E3\u9501\u65F6\u7684\u5E7F\u64AD\u76D1\u542C
+ registerReceiver(Intent.ACTION_USER_PRESENT) { context, intent ->
+ // ...
+ }
+ // \u6CE8\u518C\u591A\u4E2A\u5E7F\u64AD\u76D1\u542C\uFF0C\u4F1A\u540C\u65F6\u56DE\u8C03\u591A\u6B21
+ registerReceiver(Intent.ACTION_PACKAGE_CHANGED, Intent.ACTION_TIME_TICK) { context, intent ->
+ // ...
+ }
+ }
+}
+
Host Lifecycle Extension
Monitor Lifecycle
Application
, just use the following methods.loadApp(name = "com.example.demo") {
+ // Register lifecycle listeners
+ onAppLifecycle {
+ // You can implement lifecycle method listeners in Application here
+ attachBaseContext { baseContext, hasCalledSuper ->
+ // Determine whether
+ // The super.attachBaseContext(base) method has been executed by judging hasCalledSuper
+ // ...
+ }
+ onCreate {
+ // Get the current Application instance through this
+ // ...
+ }
+ onTerminate {
+ // Get the current Application instance through this
+ // ...
+ }
+ onLowMemory {
+ // Get the current Application instance through this
+ // ...
+ }
+ onTrimMemory { self, level ->
+ // Here you can judge whether the app has switched to the background
+ if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+ // ...
+ }
+ // ...
+ }
+ onConfigurationChanged { self, config ->
+ // ...
+ }
+ }
+}
+
Register System Broadcast
Application.onCreate
method to monitor system broadcast.Application
.loadApp(name = "com.example.demo") {
+ // Register lifecycle listeners
+ onAppLifecycle {
+ // Broadcast monitoring when the registered user is unlocked
+ registerReceiver(Intent.ACTION_USER_PRESENT) { context, intent ->
+ // ...
+ }
+ // Register multiple broadcast listeners, will call back multiple times at the same time
+ registerReceiver(Intent.ACTION_PACKAGE_CHANGED, Intent.ACTION_TIME_TICK) { context, intent ->
+ // ...
+ }
+ }
+}
+
All Hook process in one step, everything is simplified
loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+}
+
\u6240\u6709 Hook \u6D41\u7A0B\u4E00\u6B65\u5230\u4F4D\uFF0C\u62D2\u7EDD\u7E41\u7410
loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+}
+
Basic Knowledge
Related Introduction
What is Xposed
What can Xposed do
Xposed Framework
+\u2514\u2500\u2500 App's Environment
+ \u2514\u2500\u2500 Hooker (Hooked)
+ ...
+ App's Environment
+ \u2514\u2500\u2500 Hooker (Hooked)
+ ...
+ ...
+
XposedBridge
to dynamically insert our own code before and after the method to be executed by the Host (App), or completely replace the target, or even intercept. Development Process
Derivatives
App's Environment
+\u2514\u2500\u2500 Hook Framework
+ \u2514\u2500\u2500 Hooker (Hooked)
+ ...
+
What YukiHookAPI does
XposedHelpers
, which is well known to developers, there is still no set of syntactic sugar for Kotlin
and API with complete usage encapsulation.YukiHookAPI
will adapt to more third-party Hook Frameworks based on the goal of using the Xposed API, so as to improve the entire ecosystem and help more developers make Xposed Module development simpler and easier to understand. Let's Started
YukiHookAPI
. \u57FA\u7840\u77E5\u8BC6
\u76F8\u5173\u4ECB\u7ECD
Xposed \u662F\u4EC0\u4E48
Xposed \u80FD\u505A\u4EC0\u4E48
Xposed Framework
+\u2514\u2500\u2500 App's Environment
+ \u2514\u2500\u2500 Hooker (Hooked)
+ ...
+ App's Environment
+ \u2514\u2500\u2500 Hooker (Hooked)
+ ...
+ ...
+
XposedBridge
\u6240\u63D0\u4F9B\u7684 Hook \u64CD\u4F5C\u52A8\u6001\u5730\u5728\u5BBF\u4E3B (APP) \u8981\u6267\u884C\u7684\u65B9\u6CD5\u524D\u540E\u63D2\u5165\u81EA\u5DF1\u7684\u4EE3\u7801\uFF0C\u6216\u5B8C\u5168\u66FF\u6362\u76EE\u6807\uFF0C\u751A\u81F3\u662F\u62E6\u622A\u3002 \u53D1\u5C55\u8FC7\u7A0B
\u884D\u751F\u4EA7\u54C1
App's Environment
+\u2514\u2500\u2500 Hook Framework
+ \u2514\u2500\u2500 Hooker (Hooked)
+ ...
+
YukiHookAPI \u505A\u4E86\u4EC0\u4E48
XposedHelpers
\uFF0C\u4F9D\u7136\u6CA1\u6709\u4E00\u5957\u9488\u5BF9 Kotlin
\u6253\u9020\u7684\u8BED\u6CD5\u7CD6\u4EE5\u53CA\u7528\u6CD5\u5C01\u88C5\u5341\u5206\u5B8C\u5584\u7684 API\u3002YukiHookAPI
\u5C06\u5728\u4F7F\u7528 Xposed API \u7684\u76EE\u6807\u57FA\u7840\u4E0A\u9002\u914D\u66F4\u591A\u7B2C\u4E09\u65B9 Hook \u6846\u67B6\uFF0C\u4F7F\u5F97\u6574\u4E2A\u751F\u6001\u5F97\u5230\u5B8C\u5584\uFF0C\u5E76\u5E2E\u52A9\u66F4\u591A\u5F00\u53D1\u8005\u8BA9 Xposed \u6A21\u5757\u5F00\u53D1\u53D8\u5F97\u66F4\u52A0\u7B80\u5355\u548C\u6613\u61C2\u3002 \u8BA9\u6211\u4EEC\u5F00\u59CB\u5427
YukiHookAPI
\u3002 Debug Logs
YukiHookAPI
encapsulates a set of stable and efficient debugging log functions for developers. Normal Logs
loggerD
, loggerI
, loggerW
to print normal logs to the console.loggerD(msg = "This is a log")
+
YukiHookAPI
will call android.util.Log
and XposedBridge.log
to print this log at the same time.TAG
of the log is the value you set in YukiHookLogger.Configs.tag
.TAG
easily to prevent logs from being filtered.loggerD(tag = "YukiHookAPI", msg = "This is a log")
+
[YukiHookAPI][D][host package name]--> This is a log
+
LoggerType
to customize the type of log printing.android.util.Log
or XposedBridge.log
to print logs.LoggerType.BOTH
, which means that both methods are used to print logs.android.util.Log
to print logs.loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.LOGD)
+
XposedBridge.log
to print the log, this method can only be used in the (Xposed) Host environment.loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.XPOSEDBRIDGE)
+
loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
+
Error Logs
loggerE
to print E
level logs to the console.loggerE(msg = "This is an error")
+
E
level logs.// Assume this is the exception that was thrown
+val throwable = Throwable(...)
+// Print log
+loggerE(msg = "This is an error", e = throwable)
+
[YukiHookAPI][E][host package name]--> This is an error
+
java.lang.Throwable
+ at com.demo.Test.<init>(...)
+ at com.demo.Test.doTask(...)
+ at com.demo.Test.stop(...)
+ at com.demo.Test.init(...)
+ at a.a.a(...)
+ ... 3 more
+
LoggerType
to specify the method type currently used to print the log. Save Logs and Custom Elements
YukiHookLogger.saveToFile
method.// Please note
+// The saved file path must have read and write permissions
+// Otherwise an exception will be thrown
+YukiHookLogger.saveToFile("/sdcard/Documents/debug_log.log")
+
YukiHookLogger.contents
to get all the log file contents that have been printed so far.// Get the contents of all log files that have been printed so far
+val fileContent = YukiHookLogger.contents
+
YukiHookLogger.Configs.isRecord
to be enabled.YukiHookLogger.Configs.elements
to customize the elements that debug logs display externally.YukiHookAPI.Configs
to be configured in onInit
of the Hook entry class.override fun onInit() = configs {
+ debugLog {
+ // ...
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ // ...
+}
+
\u8C03\u8BD5\u65E5\u5FD7
YukiHookAPI
\u4E3A\u5F00\u53D1\u8005\u5C01\u88C5\u4E86\u4E00\u5957\u7A33\u5B9A\u9AD8\u6548\u7684\u8C03\u8BD5\u65E5\u5FD7\u529F\u80FD\u3002 \u666E\u901A\u65E5\u5FD7
loggerD
\u3001loggerI
\u3001loggerW
\u6765\u5411\u63A7\u5236\u53F0\u6253\u5370\u666E\u901A\u65E5\u5FD7\u3002loggerD(msg = "This is a log")
+
YukiHookAPI
\u4F1A\u8C03\u7528 android.util.Log
\u4E0E XposedBridge.log
\u540C\u65F6\u6253\u5370\u8FD9\u6761\u65E5\u5FD7\u3002TAG
\u4E3A\u4F60\u5728 YukiHookLogger.Configs.tag
\u4E2D\u8BBE\u7F6E\u7684\u503C\u3002TAG
\u9632\u6B62\u8FC7\u6EE4\u4E0D\u5230\u65E5\u5FD7\u3002loggerD(tag = "YukiHookAPI", msg = "This is a log")
+
[YukiHookAPI][D][\u5BBF\u4E3B\u5305\u540D]--> This is a log
+
LoggerType
\u81EA\u5B9A\u4E49\u65E5\u5FD7\u6253\u5370\u7684\u7C7B\u578B\uFF0C\u53EF\u9009\u62E9\u4F7F\u7528 android.util.Log
\u8FD8\u662F XposedBridge.log
\u6765\u6253\u5370\u65E5\u5FD7\u3002LoggerType.BOTH
\uFF0C\u542B\u4E49\u4E3A\u540C\u65F6\u4F7F\u7528\u8FD9\u4E24\u4E2A\u65B9\u6CD5\u6765\u6253\u5370\u65E5\u5FD7\u3002android.util.Log
\u6765\u6253\u5370\u65E5\u5FD7\u3002loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.LOGD)
+
XposedBridge.log
\u6765\u6253\u5370\u65E5\u5FD7\uFF0C\u6B64\u65B9\u6CD5\u4EC5\u53EF\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u3002loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.XPOSEDBRIDGE)
+
loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
+
\u9519\u8BEF\u65E5\u5FD7
loggerE
\u6765\u5411\u63A7\u5236\u53F0\u6253\u5370 E
\u7EA7\u522B\u7684\u65E5\u5FD7\u3002loggerE(msg = "This is an error")
+
E
\u7EA7\u522B\u7684\u65E5\u5FD7\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u88AB\u629B\u51FA\u7684\u5F02\u5E38
+val throwable = Throwable(...)
+// \u6253\u5370\u65E5\u5FD7
+loggerE(msg = "This is an error", e = throwable)
+
[YukiHookAPI][E][\u5BBF\u4E3B\u5305\u540D]--> This is an error
+
java.lang.Throwable
+ at com.demo.Test.<init>(...)
+ at com.demo.Test.doTask(...)
+ at com.demo.Test.stop(...)
+ at com.demo.Test.init(...)
+ at a.a.a(...)
+ ... 3 more
+
LoggerType
\u6765\u6307\u5B9A\u5F53\u524D\u6253\u5370\u65E5\u5FD7\u6240\u7528\u5230\u7684\u65B9\u6CD5\u7C7B\u578B\u3002 \u4FDD\u5B58\u65E5\u5FD7\u4E0E\u81EA\u5B9A\u4E49\u5143\u7D20
YukiHookLogger.saveToFile
\u65B9\u6CD5\u76F4\u63A5\u4FDD\u5B58\u5F53\u524D\u5DF2\u6253\u5370\u7684\u5168\u90E8\u65E5\u5FD7\u5230\u6587\u4EF6\u3002// \u8BF7\u6CE8\u610F\u4FDD\u5B58\u7684\u6587\u4EF6\u8DEF\u5F84\u5FC5\u987B\u62E5\u6709\u8BFB\u5199\u6743\u9650\uFF0C\u5426\u5219\u4F1A\u629B\u51FA\u5F02\u5E38
+YukiHookLogger.saveToFile("/sdcard/Documents/debug_log.log")
+
YukiHookLogger.contents
\u83B7\u53D6\u5F53\u524D\u5DF2\u6253\u5370\u7684\u5168\u90E8\u65E5\u5FD7\u6587\u4EF6\u5185\u5BB9\u3002// \u83B7\u53D6\u5F53\u524D\u5DF2\u6253\u5370\u7684\u5168\u90E8\u65E5\u5FD7\u6587\u4EF6\u5185\u5BB9
+val fileContent = YukiHookLogger.contents
+
YukiHookLogger.Configs.isRecord
\u3002YukiHookLogger.Configs.elements
\u81EA\u5B9A\u4E49\u8C03\u8BD5\u65E5\u5FD7\u5BF9\u5916\u663E\u793A\u7684\u5143\u7D20\u3002onInit
\u4E2D\u5BF9 YukiHookAPI.Configs
\u8FDB\u884C\u914D\u7F6E\u3002override fun onInit() = configs {
+ debugLog {
+ // ...
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ // ...
+}
+
\u4ECE Xposed API \u8FC1\u79FB
YukiHookAPI
\u3002 \u8FC1\u79FB Hook \u5165\u53E3\u70B9
XC_LoadPackage.LoadPackageParam
\u8FC1\u79FB\u81F3 PackageParam
\u3002YukiHookAPI
\u5BF9 PackageParam
\u5B9E\u73B0\u4E86 lambda
\u65B9\u6CD5\u4F53 this
\u7528\u6CD5\uFF0C\u5728 encase
\u65B9\u6CD5\u4F53\u5185\u5373\u53EF\u5168\u5C40\u5F97\u5230 PackageParam
\u5BF9\u8C61\u3002
',6),d=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"onHook"),s("span",{style:{color:"#ADBAC7"}},"() "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," encase {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684\u5305\u540D")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," packageName")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684 ApplicationInfo")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," appInfo")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u7CFB\u7EDF\u4E0A\u4E0B\u6587\u5BF9\u8C61")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," systemContext")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5BBF\u4E3B Application \u751F\u547D\u5468\u671F")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," appContext")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Hook \u6307\u5B9A\u7684 APP")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," loadApp(name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.demo.test"'),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Class Hook")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," findClass("),s("span",{style:{color:"#96D0FF"}},'"com.demo.test.TestClass"'),s("span",{style:{color:"#ADBAC7"}},").hook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectMember {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," method {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"test"')]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param("),s("span",{style:{color:"#F69D50"}},"BooleanType"),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," afterHook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ...")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Resources Hook (\u56FA\u5B9A\u7528\u6CD5)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resources().hook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectResource {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," conditions {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"ic_launcher"')]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," mipmap()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," replaceToModuleResource("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),D=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"private"),s("span",{style:{color:"#ADBAC7"}}," lateinit "),s("span",{style:{color:"#F47067"}},"var"),s("span",{style:{color:"#ADBAC7"}}," moduleResources"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XModuleResources")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"initZygote"),s("span",{style:{color:"#ADBAC7"}},"(sparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"IXposedHookZygoteInit"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"StartupParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XModuleResources"),s("span",{style:{color:"#ADBAC7"}},".createInstance(sparam.modulePath, "),s("span",{style:{color:"#6CB6FF"}},"null"),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"handleLoadPackage"),s("span",{style:{color:"#ADBAC7"}},"(lpparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_LoadPackage"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"LoadPackageParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684\u5305\u540D")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," lpparam.packageName")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684 ApplicationInfo")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," lpparam.applicationInfo")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u7CFB\u7EDF\u4E0A\u4E0B\u6587\u5BF9\u8C61")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5728\u539F\u751F Xposed API \u4E2D\u6CA1\u6709\u73B0\u6210\u7684\u8C03\u7528\u65B9\u6CD5\uFF0C\u4F60\u9700\u8981\u81EA\u884C\u53CD\u5C04 ActivityThread \u6765\u5B9E\u73B0")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5BBF\u4E3B Application \u751F\u547D\u5468\u671F")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"AndroidAppHelper"),s("span",{style:{color:"#ADBAC7"}},".currentApplication()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Class Hook")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"if"),s("span",{style:{color:"#ADBAC7"}},"(lpparam.packageName "),s("span",{style:{color:"#F47067"}},"=="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.demo.test"'),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XposedHelpers"),s("span",{style:{color:"#ADBAC7"}},".findAndHookMethod(")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.demo.test.TestClass"'),s("span",{style:{color:"#ADBAC7"}},", lpparam.classLoader,")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"test"'),s("span",{style:{color:"#ADBAC7"}},", Boolean::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java,")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"object"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_MethodHook"),s("span",{style:{color:"#ADBAC7"}},"() {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun afterHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," ...")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," )")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"handleInitPackageResources"),s("span",{style:{color:"#ADBAC7"}},"(resparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_InitPackageResources"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"InitPackageResourcesParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684\u5305\u540D")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resparam.packageName")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Resources Hook")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resparam.res.setReplacement(")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.demo.test"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"mipmap"'),s("span",{style:{color:"#ADBAC7"}},","),s("span",{style:{color:"#96D0FF"}},'"ic_launcher"'),s("span",{style:{color:"#ADBAC7"}},",")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources.fwd("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," )")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),u=r(' \u8FC1\u79FB Hook \u65B9\u6CD5\u4F53
XC_MethodHook.MethodHookParam
\u8FC1\u79FB\u81F3 HookParam
\u3002 Before/After Hook
YukiHookAPI
\u540C\u6837\u5BF9 HookParam
\u5B9E\u73B0\u4E86 lambda
\u65B9\u6CD5\u4F53 this
\u7528\u6CD5\uFF0C\u5728 beforeHook
\u3001afterHook
\u7B49\u65B9\u6CD5\u4F53\u5185\u5373\u53EF\u5168\u5C40\u5F97\u5230 HookParam
\u5BF9\u8C61\u3002
',5),C=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"afterHook {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684\u5B9E\u4F8B")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," instance")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684 Class \u5B9E\u4F8B")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," instanceClass")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5E76 cast \u5F53\u524D Hook \u7684\u5B9E\u4F8B\u4E3A\u6307\u5B9A\u7C7B\u578B T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," instance"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u6570\u7EC4")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u7B2C\u4E00\u4F4D T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args().first().cast"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u6700\u540E\u4E00\u4F4D T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args().last().cast"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u4EFB\u610F\u4E0B\u6807 T\uFF0C\u8FD9\u91CC\u7528 2 \u4E3E\u4F8B")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args(index "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"2"),s("span",{style:{color:"#ADBAC7"}},").cast"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u4EFB\u610F\u4E0B\u6807\uFF0C\u8FD9\u91CC\u7528 2 \u4E3E\u4F8B")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args(index "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"2"),s("span",{style:{color:"#ADBAC7"}},").set(...)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u8FD4\u56DE\u503C")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," result")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u8FD4\u56DE\u503C\u5E76 cast \u4E3A T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," result"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u4FEE\u6539\u8FD4\u56DE\u503C\u5185\u5BB9")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," result "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," ...")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5220\u9664\u8FD4\u56DE\u503C\u5185\u5BB9")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resultNull()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5411 Hook APP \u629B\u51FA\u5F02\u5E38")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Throwable"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},'"Fatal"'),s("span",{style:{color:"#ADBAC7"}},").throwToApp()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u6267\u884C\u672A\u7ECF Hook \u7684\u539F\u59CB\u65B9\u6CD5\u5E76\u4F7F\u7528\u539F\u59CB\u65B9\u6CD5\u53C2\u6570\u8C03\u7528\uFF0C\u6CDB\u578B\u53EF\u7565")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," callOriginal"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#6CB6FF"}},"Any?"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u6267\u884C\u672A\u7ECF Hook \u7684\u539F\u59CB\u65B9\u6CD5\u5E76\u81EA\u5B9A\u4E49\u65B9\u6CD5\u53C2\u6570\u8C03\u7528\uFF0C\u6CDB\u578B\u53EF\u7565")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," invokeOriginal"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#6CB6FF"}},"Any?"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"(...)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),B=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"afterHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684\u5B9E\u4F8B")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.thisObject")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5F53\u524D Hook \u7684 Class \u5B9E\u4F8B")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.thisObject.javaClass")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u5E76 cast \u5F53\u524D Hook \u7684\u5B9E\u4F8B\u4E3A\u6307\u5B9A\u7C7B\u578B T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.thisObject "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u6570\u7EC4")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u7B2C\u4E00\u4F4D T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args["),s("span",{style:{color:"#6CB6FF"}},"0"),s("span",{style:{color:"#ADBAC7"}},"] "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u6700\u540E\u4E00\u4F4D T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args[param.args.lastIndex] "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u4EFB\u610F\u4E0B\u6807 T\uFF0C\u8FD9\u91CC\u7528 2 \u4E3E\u4F8B")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args["),s("span",{style:{color:"#6CB6FF"}},"2"),s("span",{style:{color:"#ADBAC7"}},"] "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u4EFB\u610F\u4E0B\u6807\uFF0C\u8FD9\u91CC\u7528 2 \u4E3E\u4F8B")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args["),s("span",{style:{color:"#6CB6FF"}},"2"),s("span",{style:{color:"#ADBAC7"}},"] "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," ...")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u8FD4\u56DE\u503C")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.result")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5F97\u5230\u8FD4\u56DE\u503C\u5E76 cast \u4E3A T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.result "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u4FEE\u6539\u8FD4\u56DE\u503C\u5185\u5BB9")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.result "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," ...")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5220\u9664\u8FD4\u56DE\u503C\u5185\u5BB9")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.result "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"null")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5411 Hook APP \u629B\u51FA\u5F02\u5E38")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.throwable "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Throwable"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},'"Fatal"'),s("span",{style:{color:"#ADBAC7"}},")")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u6267\u884C\u672A\u7ECF Hook \u7684\u539F\u59CB\u65B9\u6CD5")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XposedBridge"),s("span",{style:{color:"#ADBAC7"}},".invokeOriginalMethod(param.method, param.thisObject, ...)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),m=s("h3",{id:"replace-hook",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#replace-hook","aria-hidden":"true"},"#"),l(" Replace Hook")],-1),b=s("p",null,[s("code",null,"replaceHook"),l(" \u65B9\u6CD5\u6BD4\u8F83\u7279\u6B8A\uFF0C"),s("code",null,"YukiHookAPI"),l(" \u4E3A\u5B83\u505A\u51FA\u4E86\u591A\u79CD\u5F62\u5F0F\u4EE5\u4F9B\u9009\u62E9\u3002")],-1),v=s("blockquote",null,[s("p",null,"API \u529F\u80FD\u5DEE\u5F02\u5BF9\u6BD4\u5982\u4E0B")],-1),F=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// \u65E0\u8FD4\u56DE\u503C\u7684\u65B9\u6CD5 void")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"replaceUnit {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u76F4\u63A5\u5728\u8FD9\u91CC\u5B9E\u73B0\u88AB\u66FF\u6362\u7684\u903B\u8F91")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// \u6709\u8FD4\u56DE\u503C\u7684\u65B9\u6CD5")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"replaceAny {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5728\u8FD9\u91CC\u5B9E\u73B0\u88AB\u66FF\u6362\u7684\u903B\u8F91")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ...")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u9700\u8981\u8FD4\u56DE\u65B9\u6CD5\u5BF9\u5E94\u7684\u8FD4\u56DE\u503C\uFF0C\u65E0\u9700\u5199 return\uFF0C\u53EA\u9700\u5C06\u53C2\u6570\u653E\u5230\u6700\u540E\u4E00\u4F4D")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5047\u8BBE\u8FD9\u4E2A\u65B9\u6CD5\u7684\u8FD4\u56DE\u503C\u662F Int\uFF0C\u6211\u4EEC\u53EA\u9700\u8981\u4FDD\u8BC1\u6700\u540E\u4E00\u4F4D\u662F\u6211\u4EEC\u9700\u8981\u7684\u8FD4\u56DE\u503C\u5373\u53EF")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"0")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// \u6709\u4E9B\u65B9\u6CD5\u6211\u4EEC\u53EA\u9700\u66FF\u6362\u5176\u8FD4\u56DE\u503C\uFF0C\u5219\u6709\u5982\u4E0B\u5B9E\u73B0")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// \u9700\u8981\u6CE8\u610F\u7684\u662F\uFF1A\u76F4\u63A5\u66FF\u6362\u8FD4\u56DE\u503C\u7684\u65B9\u6CD5\u4F20\u5165\u7684\u53C2\u6570\u662F\u56FA\u5B9A\u4E0D\u53D8\u7684\uFF0C\u82E5\u60F3\u5B9E\u73B0\u52A8\u6001\u66FF\u6362\u8FD4\u56DE\u503C\u8BF7\u4F7F\u7528\u4E0A\u9762\u7684 replaceAny \u65B9\u6CD5\u4F53")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// \u66FF\u6362\u4E3A\u4F60\u9700\u8981\u7684\u8FD4\u56DE\u503C")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"replaceTo(...)")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// \u66FF\u6362\u4E3A Boolean \u7C7B\u578B\u7684\u8FD4\u56DE\u503C")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"replaceToTrue()")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// \u62E6\u622A\u8FD4\u56DE\u503C")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"intercept()")]),l(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),k=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// \u65E0\u8FD4\u56DE\u503C\u7684\u65B9\u6CD5 void")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},")"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"Any?"),s("span",{style:{color:"#ADBAC7"}}," {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u76F4\u63A5\u5728\u8FD9\u91CC\u5B9E\u73B0\u88AB\u66FF\u6362\u7684\u903B\u8F91")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"null")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// \u6709\u8FD4\u56DE\u503C\u7684\u65B9\u6CD5")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},")"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"Int"),s("span",{style:{color:"#ADBAC7"}}," {")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5728\u8FD9\u91CC\u5B9E\u73B0\u88AB\u66FF\u6362\u7684\u903B\u8F91")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ...")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// \u5047\u8BBE\u8FD9\u4E2A\u65B9\u6CD5\u7684\u8FD4\u56DE\u503C\u662F Int")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"0")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// \u6709\u4E9B\u65B9\u6CD5\u6211\u4EEC\u53EA\u9700\u66FF\u6362\u5176\u8FD4\u56DE\u503C\uFF0C\u5219\u6709\u5982\u4E0B\u5B9E\u73B0")]),l(`
+`),s("span",{class:"line"}),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// \u66FF\u6362\u4E3A\u4F60\u9700\u8981\u7684\u8FD4\u56DE\u503C")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," ...")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// \u66FF\u6362\u4E3A Boolean \u7C7B\u578B\u7684\u8FD4\u56DE\u503C")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"true")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// \u62E6\u622A\u8FD4\u56DE\u503C")]),l(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"null")]),l(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),h=s("h2",{id:"\u8FC1\u79FB\u5176\u5B83\u529F\u80FD",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#\u8FC1\u79FB\u5176\u5B83\u529F\u80FD","aria-hidden":"true"},"#"),l(" \u8FC1\u79FB\u5176\u5B83\u529F\u80FD")],-1),H=s("p",null,[s("code",null,"YukiHookAPI"),l(" \u5BF9 Xposed API \u8FDB\u884C\u4E86\u5B8C\u5168\u91CD\u5199\uFF0C\u4F60\u53EF\u4EE5\u53C2\u8003 "),s("a",{href:"../api/home"},"API \u6587\u6863"),l(" \u4EE5\u53CA "),s("a",{href:"../api/special-features/reflection"},"\u7279\u8272\u529F\u80FD"),l(" \u6765\u51B3\u5B9A\u4E00\u4E9B\u529F\u80FD\u6027\u7684\u8FC1\u79FB\u548C\u4F7F\u7528\u3002")],-1);function _(f,P){const a=c("CodeGroupItem"),o=c("CodeGroup");return i(),t("div",null,[y,n(o,null,{default:e(()=>[n(a,{title:"Yuki Hook API"},{default:e(()=>[d]),_:1}),n(a,{title:"Xposed API"},{default:e(()=>[D]),_:1})]),_:1}),u,n(o,null,{default:e(()=>[n(a,{title:"Yuki Hook API"},{default:e(()=>[C]),_:1}),n(a,{title:"Xposed API"},{default:e(()=>[B]),_:1})]),_:1}),m,b,v,n(o,null,{default:e(()=>[n(a,{title:"Yuki Hook API"},{default:e(()=>[F]),_:1}),n(a,{title:"Xposed API"},{default:e(()=>[k]),_:1})]),_:1}),h,H])}const I=p(A,[["render",_],["__file","move-to-new-api.html.vue"]]);export{I as default};
diff --git a/docs/assets/move-to-new-api.html.508c5312.js b/docs/assets/move-to-new-api.html.508c5312.js
new file mode 100644
index 00000000..2ce9abc4
--- /dev/null
+++ b/docs/assets/move-to-new-api.html.508c5312.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-c0d5dada","path":"/zh-cn/guide/move-to-new-api.html","title":"\u4ECE Xposed API \u8FC1\u79FB","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u8FC1\u79FB Hook \u5165\u53E3\u70B9","slug":"\u8FC1\u79FB-hook-\u5165\u53E3\u70B9","link":"#\u8FC1\u79FB-hook-\u5165\u53E3\u70B9","children":[]},{"level":2,"title":"\u8FC1\u79FB Hook \u65B9\u6CD5\u4F53","slug":"\u8FC1\u79FB-hook-\u65B9\u6CD5\u4F53","link":"#\u8FC1\u79FB-hook-\u65B9\u6CD5\u4F53","children":[{"level":3,"title":"Before/After Hook","slug":"before-after-hook","link":"#before-after-hook","children":[]},{"level":3,"title":"Replace Hook","slug":"replace-hook","link":"#replace-hook","children":[]}]},{"level":2,"title":"\u8FC1\u79FB\u5176\u5B83\u529F\u80FD","slug":"\u8FC1\u79FB\u5176\u5B83\u529F\u80FD","link":"#\u8FC1\u79FB\u5176\u5B83\u529F\u80FD","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/guide/move-to-new-api.md"}');export{e as data};
diff --git a/docs/assets/move-to-new-api.html.78f39fa5.js b/docs/assets/move-to-new-api.html.78f39fa5.js
new file mode 100644
index 00000000..9f2b8fc2
--- /dev/null
+++ b/docs/assets/move-to-new-api.html.78f39fa5.js
@@ -0,0 +1 @@
+const e=JSON.parse('{"key":"v-77d752a2","path":"/en/guide/move-to-new-api.html","title":"Migrate from Xposed API","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Migrate Hook Entry Point","slug":"migrate-hook-entry-point","link":"#migrate-hook-entry-point","children":[]},{"level":2,"title":"Migrate Hook Method Body","slug":"migrate-hook-method-body","link":"#migrate-hook-method-body","children":[{"level":3,"title":"Before/After Hook","slug":"before-after-hook","link":"#before-after-hook","children":[]},{"level":3,"title":"Replace Hook","slug":"replace-hook","link":"#replace-hook","children":[]}]},{"level":2,"title":"Migrate Other Features","slug":"migrate-other-features","link":"#migrate-other-features","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/guide/move-to-new-api.md"}');export{e as data};
diff --git a/docs/assets/move-to-new-api.html.f0cc4092.js b/docs/assets/move-to-new-api.html.f0cc4092.js
new file mode 100644
index 00000000..46c05023
--- /dev/null
+++ b/docs/assets/move-to-new-api.html.f0cc4092.js
@@ -0,0 +1,184 @@
+import{_ as t,r as c,o as p,c as i,d as l,w as n,a as r,b as s,e}from"./app.fb8271cf.js";const A={},y=r(' Migrate from Xposed API
YukiHookAPI
. Migrate Hook Entry Point
XC_LoadPackage.LoadPackageParam
to PackageParam
.YukiHookAPI
implements the lambda
method body this
usage for PackageParam
, and the PackageParam
object can be obtained globally in the encase
method body.
',6),d=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"onHook"),s("span",{style:{color:"#ADBAC7"}},"() "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," encase {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the package name of the current Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," packageName")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the ApplicationInfo of the current Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," appInfo")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the system context object")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," systemContext")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the host Application lifecycle")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," appContext")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Hook specified app")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," loadApp(name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.demo.test"'),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Class Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," findClass("),s("span",{style:{color:"#96D0FF"}},'"com.demo.test.TestClass"'),s("span",{style:{color:"#ADBAC7"}},").hook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectMember {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," method {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"test"')]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param("),s("span",{style:{color:"#F69D50"}},"BooleanType"),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," afterHook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ...")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Resources Hook (fixed usage)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resources().hook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," injectResource {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," conditions {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," name "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"ic_launcher"')]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," mipmap()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," replaceToModuleResource("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),u=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"private"),s("span",{style:{color:"#ADBAC7"}}," lateinit "),s("span",{style:{color:"#F47067"}},"var"),s("span",{style:{color:"#ADBAC7"}}," moduleResources"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XModuleResources")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"initZygote"),s("span",{style:{color:"#ADBAC7"}},"(sparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"IXposedHookZygoteInit"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"StartupParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XModuleResources"),s("span",{style:{color:"#ADBAC7"}},".createInstance(sparam.modulePath, "),s("span",{style:{color:"#6CB6FF"}},"null"),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"handleLoadPackage"),s("span",{style:{color:"#ADBAC7"}},"(lpparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_LoadPackage"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"LoadPackageParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the package name of the current Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," lpparam.packageName")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the ApplicationInfo of the current Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," lpparam.applicationInfo")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the system context object")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// There is no ready-made calling method in the native Xposed API, you need to reflect ActivityThread to achieve it")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the host Application lifecycle")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"AndroidAppHelper"),s("span",{style:{color:"#ADBAC7"}},".currentApplication()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Class Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"if"),s("span",{style:{color:"#ADBAC7"}},"(lpparam.packageName "),s("span",{style:{color:"#F47067"}},"=="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.demo.test"'),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XposedHelpers"),s("span",{style:{color:"#ADBAC7"}},".findAndHookMethod(")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.demo.test.TestClass"'),s("span",{style:{color:"#ADBAC7"}},", lpparam.classLoader,")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"test"'),s("span",{style:{color:"#ADBAC7"}},", Boolean::"),s("span",{style:{color:"#6CB6FF"}},"class"),s("span",{style:{color:"#ADBAC7"}},".java,")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"object"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_MethodHook"),s("span",{style:{color:"#ADBAC7"}},"() {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," override fun afterHookedMethod(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"//"),s("span",{style:{color:"#ADBAC7"}}," ...")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," }")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," )")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"handleInitPackageResources"),s("span",{style:{color:"#ADBAC7"}},"(resparam"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XC_InitPackageResources"),s("span",{style:{color:"#ADBAC7"}},"."),s("span",{style:{color:"#F69D50"}},"InitPackageResourcesParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the package name of the current Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resparam.packageName")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Resources Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resparam.res.setReplacement(")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#96D0FF"}},'"com.demo.test"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"mipmap"'),s("span",{style:{color:"#ADBAC7"}},", "),s("span",{style:{color:"#96D0FF"}},'"ic_launcher"'),s("span",{style:{color:"#ADBAC7"}},",")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," moduleResources.fwd("),s("span",{style:{color:"#F69D50"}},"R"),s("span",{style:{color:"#ADBAC7"}},".mipmap.ic_launcher)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," )")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),m=r(' Migrate Hook Method Body
XC_MethodHook.MethodHookParam
to HookParam
. Before/After Hook
YukiHookAPI
also implements the lambda
method body this
usage for HookParam
, and the HookParam
object can be obtained globally in the method bodies such as beforeHook
and afterHook
.
',5),D=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"afterHook {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the current Hook instance")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," instance")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the Class instance of the current Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," instanceClass")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get and cast the current Hook instance to the specified type T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," instance"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the method parameter array")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the first T of the method parameter")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args().first().cast"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the last bit of the method parameter T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args().last().cast"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get any subscript T of the method parameter, here is an example of 2")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args(index "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"2"),s("span",{style:{color:"#ADBAC7"}},").cast"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Set any subscript of the method parameter, here is an example of 2")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," args(index "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"2"),s("span",{style:{color:"#ADBAC7"}},").set(...)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the return value")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," result")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the return value and cast to T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," result"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#F69D50"}},"T"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Modify the content of the return value")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," result "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," ...")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Remove the content of the return value")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," resultNull()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Throw an exception to the Hook app")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Throwable"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},'"Fatal"'),s("span",{style:{color:"#ADBAC7"}},").throwToApp()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Execute the original method without hook and call with the original method parameters, generics can be omitted")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," callOriginal"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#6CB6FF"}},"Any?"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Execute the original method without Hook and customize the method parameter call, the generic type can be omitted")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," invokeOriginal"),s("span",{style:{color:"#F47067"}},"<"),s("span",{style:{color:"#6CB6FF"}},"Any?"),s("span",{style:{color:"#F47067"}},">"),s("span",{style:{color:"#ADBAC7"}},"(...)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),C=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"afterHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the current Hook instance")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.thisObject")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the Class instance of the current Hook")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.thisObject.javaClass")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get and cast the current Hook instance to the specified type T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.thisObject "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the method parameter array")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the first T of the method parameter")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args["),s("span",{style:{color:"#6CB6FF"}},"0"),s("span",{style:{color:"#ADBAC7"}},"] "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the last bit of the method parameter T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args[param.args.lastIndex] "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get any subscript T of the method parameter, here is an example of 2")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args["),s("span",{style:{color:"#6CB6FF"}},"2"),s("span",{style:{color:"#ADBAC7"}},"] "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Set any subscript of the method parameter, here is an example of 2")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.args["),s("span",{style:{color:"#6CB6FF"}},"2"),s("span",{style:{color:"#ADBAC7"}},"] "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," ...")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the return value")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.result")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Get the return value and cast to T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.result "),s("span",{style:{color:"#F47067"}},"as"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"T")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Modify the content of the return value")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.result "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," ...")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Remove the content of the return value")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.result "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"null")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Throw an exception to the Hook app")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," param.throwable "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"Throwable"),s("span",{style:{color:"#ADBAC7"}},"("),s("span",{style:{color:"#96D0FF"}},'"Fatal"'),s("span",{style:{color:"#ADBAC7"}},")")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Execute the original method without hooking")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"XposedBridge"),s("span",{style:{color:"#ADBAC7"}},".invokeOriginalMethod(param.method, param.thisObject, ...)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),B=s("h3",{id:"replace-hook",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#replace-hook","aria-hidden":"true"},"#"),e(" Replace Hook")],-1),h=s("p",null,[e("The "),s("code",null,"replaceHook"),e(" method is special, and the "),s("code",null,"YukiHookAPI"),e(" makes a variety of forms for it to choose from.")],-1),b=s("blockquote",null,[s("p",null,"The API function differences are compared as follows")],-1),v=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// A method with no return value void")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"replaceUnit {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Implement the replaced logic directly here")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// A method with a return value")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"replaceAny {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Implement the replaced logic here")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ...")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Need to return the return value corresponding to the method, no need to write return, just put the parameter in the last digit")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Assuming the return value of this method is an Int, we just need to ensure that the last bit is the return value we need")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"0")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// For some methods, we just need to replace their return value, then there are the following implementations")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// It should be noted that the parameters passed in by the method of directly replacing the return value are fixed. If you want to dynamically replace the return value, please use the above replaceAny method body")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// Replace with the return value you need")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"replaceTo(...)")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// Replace with return value of type Boolean")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"replaceToTrue()")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// Intercept return value")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"intercept()")]),e(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),F=s("div",{class:"language-kotlin ext-kt line-numbers-mode"},[s("pre",{class:"shiki",style:{"background-color":"#22272e"}},[s("code",null,[s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// A method with no return value void")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},")"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"Any?"),s("span",{style:{color:"#ADBAC7"}}," {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Implement the replaced logic directly here")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"null")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// A method with a return value")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},")"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"Int"),s("span",{style:{color:"#ADBAC7"}}," {")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Implement the replaced logic here")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// ...")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#768390"}},"// Assume the return value of this method is an Int")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"return"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"0")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#ADBAC7"}},"}")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"/// For some methods, we just need to replace their return value, then there are the following implementations")]),e(`
+`),s("span",{class:"line"}),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// Replace with the return value you need")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," ...")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// Replace with return value of type Boolean")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"true")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#768390"}},"// Intercept return value")]),e(`
+`),s("span",{class:"line"},[s("span",{style:{color:"#F47067"}},"override"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F47067"}},"fun"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#DCBDFB"}},"replaceHookedMethod"),s("span",{style:{color:"#ADBAC7"}},"(param"),s("span",{style:{color:"#F47067"}},":"),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#F69D50"}},"MethodHookParam"),s("span",{style:{color:"#ADBAC7"}},") "),s("span",{style:{color:"#F47067"}},"="),s("span",{style:{color:"#ADBAC7"}}," "),s("span",{style:{color:"#6CB6FF"}},"null")]),e(`
+`),s("span",{class:"line"})])]),s("div",{class:"line-numbers","aria-hidden":"true"},[s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"}),s("div",{class:"line-number"})])],-1),k=s("h2",{id:"migrate-other-features",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#migrate-other-features","aria-hidden":"true"},"#"),e(" Migrate Other Features")],-1),f=s("p",null,[s("code",null,"YukiHookAPI"),e(" is a complete rewrite of the Xposed API, you can refer to "),s("a",{href:"../api/home"},"API Document"),e(" and "),s("a",{href:"../api/special-features/reflection"},"Special Features"),e(" to determine some functional Migration and use.")],-1);function g(H,_){const a=c("CodeGroupItem"),o=c("CodeGroup");return p(),i("div",null,[y,l(o,null,{default:n(()=>[l(a,{title:"Yuki Hook API"},{default:n(()=>[d]),_:1}),l(a,{title:"Xposed API"},{default:n(()=>[u]),_:1})]),_:1}),m,l(o,null,{default:n(()=>[l(a,{title:"Yuki Hook API"},{default:n(()=>[D]),_:1}),l(a,{title:"Xposed API"},{default:n(()=>[C]),_:1})]),_:1}),B,h,b,l(o,null,{default:n(()=>[l(a,{title:"Yuki Hook API"},{default:n(()=>[v]),_:1}),l(a,{title:"Xposed API"},{default:n(()=>[F]),_:1})]),_:1}),k,f])}const I=t(A,[["render",g],["__file","move-to-new-api.html.vue"]]);export{I as default};
diff --git a/docs/assets/quick-start.html.20dd75c7.js b/docs/assets/quick-start.html.20dd75c7.js
new file mode 100644
index 00000000..40f1c6e0
--- /dev/null
+++ b/docs/assets/quick-start.html.20dd75c7.js
@@ -0,0 +1,69 @@
+import{_ as l,r as o,o as p,c as i,b as n,d as c,a,e as s}from"./app.fb8271cf.js";const r={},t=a(` \u5FEB\u901F\u5F00\u59CB
YukiHookAPI
\u5230\u4F60\u7684\u9879\u76EE\u4E2D\u3002 \u73AF\u5883\u8981\u6C42
1.0.80
) \u81EA\u52A8\u6784\u5EFA\u9879\u76EE
YukiHookAPI
\u63D0\u4F9B\u4E86\u4E00\u4E2A\u81EA\u52A8\u5316\u6784\u5EFA\u5DE5\u5177\uFF0C\u5B83\u53EF\u4EE5\u5E2E\u52A9\u4F60\u5FEB\u901F\u6784\u5EFA\u4E00\u4E2A\u62E5\u6709 Xposed \u6A21\u5757\u4F9D\u8D56\u7684 Android \u6807\u51C6\u9879\u76EE\u6A21\u677F\uFF0C\u4F7F\u7528\u6784\u5EFA\u597D\u7684\u6A21\u677F\u5373\u53EF\u76F4\u63A5\u5F00\u59CB\u4E0B\u4E00\u6B65\u5DE5\u4F5C\u3002 \u624B\u52A8\u914D\u7F6E\u9879\u76EE
\u521B\u5EFA\u9879\u76EE
Android Studio
\u6216 IntelliJ IDEA
\u521B\u5EFA\u65B0\u7684 Android \u9879\u76EE\uFF0C\u5E76\u5728 Language
\u4E00\u680F\u9009\u62E9 Kotlin
\u4EE5\u81EA\u52A8\u6DFB\u52A0\u57FA\u7840\u4F9D\u8D56\u3002 \u96C6\u6210\u4F9D\u8D56
build.gradle
\u4E2D\u6DFB\u52A0\u4F9D\u8D56\u3002repositories {
+ google()
+ mavenCentral()
+ // \u2757\u82E5\u4F60\u7684 Plugin \u7248\u672C\u8FC7\u4F4E\uFF0C\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u52A1\u5FC5\u6DFB\u52A0\uFF0C\u5176\u5B83\u60C5\u51B5\u53EF\u9009
+ maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
+ // \u2757\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u52A1\u5FC5\u6DFB\u52A0\uFF0C\u5176\u5B83\u60C5\u51B5\u53EF\u9009
+ maven { url "https://api.xposed.info/" }
+ // MavenCentral \u6709 2 \u5C0F\u65F6\u7F13\u5B58\uFF0C\u82E5\u65E0\u6CD5\u96C6\u6210\u6700\u65B0\u7248\u672C\u8BF7\u6DFB\u52A0\u6B64\u5730\u5740
+ maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
+}
+
build.gradle
\u4E2D\u6DFB\u52A0 plugin
\u3002plugins {
+ // \u2757\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u52A1\u5FC5\u6DFB\u52A0\uFF0C\u5176\u5B83\u60C5\u51B5\u53EF\u9009
+ id 'com.google.devtools.ksp' version '<ksp-version>'
+}
+
build.gradle
\u4E2D\u6DFB\u52A0\u4F9D\u8D56\u3002dependencies {
+ // \u57FA\u7840\u4F9D\u8D56
+ implementation 'com.highcapable.yukihookapi:api:<yuki-version>'
+ // \u2757\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u52A1\u5FC5\u6DFB\u52A0\uFF0C\u5176\u5B83\u60C5\u51B5\u53EF\u9009
+ compileOnly 'de.robv.android.xposed:api:82'
+ // \u2757\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u52A1\u5FC5\u6DFB\u52A0\uFF0C\u5176\u5B83\u60C5\u51B5\u53EF\u9009
+ ksp 'com.highcapable.yukihookapi:ksp-xposed:<yuki-version>'
+}
+
build.gradle
\u4E2D\u4FEE\u6539 Kotlin
\u7684 Jvm \u7248\u672C\u4E3A 11 \u53CA\u4EE5\u4E0A\u3002android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
+ }
+ kotlinOptions {
+ jvmTarget = '11'
+ }
+}
+
\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528
AndroidManifest.xml
\u4E2D\u6DFB\u52A0\u57FA\u7840\u4EE3\u7801\u3002<!-- \u8BBE\u7F6E\u4E3A Xposed \u6A21\u5757 -->
+<meta-data
+ android:name="xposedmodule"
+ android:value="true" />
+
+<!-- \u8BBE\u7F6E\u4F60\u7684\u6A21\u5757\u63CF\u8FF0 -->
+<meta-data
+ android:name="xposeddescription"
+ android:value="\u586B\u5199\u4F60\u7684 Xposed \u6A21\u5757\u63CF\u8FF0" />
+
+<!-- \u6700\u4F4E Xposed \u7248\u672C\u53F7\uFF0C\u82E5\u4F60\u6B63\u5728\u4F7F\u7528 EdXposed/LSPosed\uFF0C\u5EFA\u8BAE\u6700\u4F4E\u4E3A 93 -->
+<meta-data
+ android:name="xposedminversion"
+ android:value="93" />
+
+<!-- \u53EF\u9009\uFF1A\u914D\u7F6E\u652F\u6301 New XSharePrefs \u53EF\u65E0\u9700\u8C03\u6574 xposedminversion \u4E3A 93 -->
+<meta-data
+ android:name="xposedsharedprefs"
+ android:value="true"/>
+
IYukiHookXposedInit
\u5E76\u52A0\u5165\u6CE8\u89E3 @InjectYukiHookWithXposed
\u3002@InjectYukiHookWithXposed
+class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = YukiHookAPI.encase {
+ // Your code here.
+ }
+}
+
\u4F5C\u4E3A Hook API \u4F7F\u7528
\u96C6\u6210\u65B9\u5F0F
Application
\u3002attachBaseContext
\u4E2D\u6DFB\u52A0 YukiHookAPI.encase
\u65B9\u6CD5\u3002override fun attachBaseContext(base: Context?) {
+ // \u88C5\u8F7D Hook Framework
+ //
+ // Your code here.
+ //
+ // \u88C5\u8F7D YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
Quick Start
YukiHookAPI
into your project. Environment Requirements
1.0.80
) Automatically Build Project
YukiHookAPI
provides an automated build tool that can help you quickly build an Android standard project template with Xposed Module dependencies, and use the built template to start the next step directly. Manually Configure Project
Create Project
Android Studio
or IntelliJ IDEA
to create a new Android project and select Kotlin
in the Language
column to automatically add basic dependencies. Integration Dependencies
build.gradle
.repositories {
+ google()
+ mavenCentral()
+ // \u2757If your Plugin version is too low, be sure to add it as an Xposed Module, other cases are optional
+ maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
+ // \u2757Be sure to add it as an Xposed Module, optional in other cases
+ maven { url "https://api.xposed.info/" }
+ // MavenCentral has a 2-hour cache, if you cannot integrate the latest version, please add this address
+ maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
+}
+
plugin
to your app build.gradle
.plugins {
+ // \u2757Be sure to add it as an Xposed Module, optional in other cases
+ id 'com.google.devtools.ksp' version '<ksp-version>'
+}
+
build.gradle
.dependencies {
+ // base dependencies
+ implementation 'com.highcapable.yukihookapi:api:<yuki-version>'
+ // \u2757Be sure to add it as an Xposed Module, optional in other cases
+ compileOnly 'de.robv.android.xposed:api:82'
+ // \u2757Be sure to add it as an Xposed Module, optional in other cases
+ ksp 'com.highcapable.yukihookapi:ksp-xposed:<yuki-version>'
+}
+
Kotlin
to 11 and above in your app build.gradle
.android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
+ }
+ kotlinOptions {
+ jvmTarget = '11'
+ }
+}
+
Use as Xposed Module
AndroidManifest.xml
.<!-- Set as Xposed Module -->
+<meta-data
+ android:name="xposedmodule"
+ android:value="true" />
+
+<!-- Set your module description -->
+<meta-data
+ android:name="xposeddescription"
+ android:value="Fill in your Xposed Module description" />
+
+<!-- The minimum Xposed version number -->
+<!-- If you are using EdXposed/LSPosed, the minimum recommended is 93 -->
+<meta-data
+ android:name="xposedminversion"
+ android:value="93" />
+
+<!-- Optional: Configure support for New XSharePrefs without adjusting xposedminversion to 93 -->
+<meta-data
+ android:name="xposedsharedprefs"
+ android:value="true"/>
+
IYukiHookXposedInit
and add the annotation @InjectYukiHookWithXposed
.@InjectYukiHookWithXposed
+class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = YukiHookAPI.encase {
+ // Your code here.
+ }
+}
+
Use as Hook API
Integration
Application
.YukiHookAPI.encase
method to attachBaseContext
.override fun attachBaseContext(base: Context?) {
+ // Load Hook Framework
+ //
+ // Your code here.
+ //
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
R8 & Proguard Obfuscate
R8
R8
then you don't need any special configuration for YukiHookAPI
. Proguard
If you are still using Proguard
, you need to do some rule configuration.R8
in any version, please add the following rules to the gradle.properties
file, no configuration is required for Android Gradle Plugin 7.0 and above.android.enableR8=true
+
R8 \u4E0E Proguard \u6DF7\u6DC6
R8
R8
\uFF0C\u90A3\u4E48\u4F60\u65E0\u9700\u5BF9 YukiHookAPI
\u8FDB\u884C\u4EFB\u4F55\u7279\u6B8A\u914D\u7F6E\u3002 Proguard
\u5982\u679C\u4F60\u4ECD\u7136\u5728\u4F7F\u7528 Proguard
\uFF0C\u4F60\u9700\u8981\u505A\u4E00\u4E9B\u89C4\u5219\u914D\u7F6E\u3002R8
\uFF0C\u8BF7\u5728 gradle.properties
\u6587\u4EF6\u4E2D\u52A0\u5165\u5982\u4E0B\u89C4\u5219\uFF0CAndroid Gradle Plugin 7.0 \u53CA\u4EE5\u4E0A\u7248\u672C\u65E0\u9700\u4EFB\u4F55\u914D\u7F6E\u3002android.enableR8=true
+
\u5B57\u8282\u7801\u4E0E\u53CD\u5C04\u6269\u5C55
YukiHookAPI
\u4E3A\u5F00\u53D1\u8005\u5C01\u88C5\u4E86\u4E00\u5957\u63A5\u8FD1\u96F6\u53CD\u5C04\u5199\u6CD5\u7684\u53CD\u5C04 API\uFF0C\u5B83\u51E0\u4E4E\u53EF\u4EE5\u5B8C\u5168\u53D6\u4EE3\u539F\u751F Java \u7684\u53CD\u5C04 API \u76F8\u5173\u7528\u6CD5\u3002 Class \u6269\u5C55
\u5BF9\u8C61\u8F6C\u6362
Class
\uFF0C\u901A\u5E38\u60C5\u51B5\u4E0B\uFF0C\u6211\u4EEC\u53EF\u4EE5\u4F7F\u7528\u6807\u51C6\u7684\u53CD\u5C04 API \u53BB\u67E5\u627E\u8FD9\u4E2A Class
\u3002// \u9ED8\u8BA4 ClassLoader \u73AF\u5883\u4E0B\u7684 Class
+var instance = Class.forName("com.demo.Test")
+// \u6307\u5B9A ClassLoader \u73AF\u5883\u4E0B\u7684 Class
+val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+var instance = customClassLoader?.loadClass("com.demo.Test")
+
YukiHookAPI
\u5C31\u4E3A\u4F60\u63D0\u4F9B\u4E86\u4E00\u4E2A\u53EF\u5728\u4EFB\u610F\u5730\u65B9\u4F7F\u7528\u7684\u8BED\u6CD5\u7CD6\u3002YukiHookAPI
\u53EF\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002// \u76F4\u63A5\u5F97\u5230\u8FD9\u4E2A Class
+// \u5982\u679C\u5F53\u524D\u6B63\u5904\u4E8E PackageParam \u73AF\u5883\uFF0C\u90A3\u4E48\u4F60\u53EF\u4EE5\u4E0D\u9700\u8981\u8003\u8651 ClassLoader
+var instance = "com.demo.Test".toClass()
+// \u81EA\u5B9A\u4E49 Class \u6240\u5728\u7684 ClassLoader
+val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+var instance = "com.demo.Test".toClass(customClassLoader)
+
Class
\u5E76\u4E0D\u5B58\u5728\uFF0C\u4F7F\u7528\u4E0A\u8FF0\u65B9\u6CD5\u4F1A\u629B\u51FA\u5F02\u5E38\uFF0C\u5982\u679C\u4F60\u4E0D\u786E\u5B9A Class
\u662F\u5426\u5B58\u5728\uFF0C\u53EF\u4EE5\u53C2\u8003\u4E0B\u9762\u7684\u89E3\u51B3\u65B9\u6848\u3002// \u76F4\u63A5\u5F97\u5230\u8FD9\u4E2A Class
+// \u5982\u679C\u5F53\u524D\u6B63\u5904\u4E8E PackageParam \u73AF\u5883\uFF0C\u90A3\u4E48\u4F60\u53EF\u4EE5\u4E0D\u9700\u8981\u8003\u8651 ClassLoader
+// \u5F97\u4E0D\u5230\u65F6\u7ED3\u679C\u4F1A\u4E3A null \u4F46\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38
+var instance = "com.demo.Test".toClassOrNull()
+// \u81EA\u5B9A\u4E49 Class \u6240\u5728\u7684 ClassLoader
+val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+// \u5F97\u4E0D\u5230\u65F6\u7ED3\u679C\u4F1A\u4E3A null \u4F46\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38
+var instance = "com.demo.Test".toClassOrNull(customClassLoader)
+
Class
\u5BF9\u8C61\u3002// \u5047\u8BBE\u8FD9\u4E2A Class \u662F\u80FD\u591F\u88AB\u76F4\u63A5\u5F97\u5230\u7684
+var instance = classOf<Test>()
+// \u6211\u4EEC\u540C\u6837\u53EF\u4EE5\u81EA\u5B9A\u4E49 Class \u6240\u5728\u7684 ClassLoader\uFF0C\u8FD9\u5BF9\u4E8E stub \u6765\u8BF4\u975E\u5E38\u6709\u6548
+val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+var instance = classOf<Test>(customClassLoader)
+
\u5B58\u5728\u5224\u65AD
Class
\u662F\u5426\u5B58\u5728\uFF0C\u901A\u5E38\u60C5\u51B5\u4E0B\uFF0C\u6211\u4EEC\u53EF\u4EE5\u4F7F\u7528\u6807\u51C6\u7684\u53CD\u5C04 API \u53BB\u67E5\u627E\u8FD9\u4E2A Class
\u901A\u8FC7\u5F02\u5E38\u6765\u5224\u65AD\u662F\u5426\u5B58\u5728\u3002// \u9ED8\u8BA4 ClassLoader \u73AF\u5883\u4E0B\u7684 Class
+var isExist = try {
+ Class.forName("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+// \u6307\u5B9A ClassLoader \u73AF\u5883\u4E0B\u7684 Class
+val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+var isExist = try {
+ customClassLoader?.loadClass("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+
YukiHookAPI
\u5C31\u4E3A\u4F60\u63D0\u4F9B\u4E86\u4E00\u4E2A\u53EF\u5728\u4EFB\u610F\u5730\u65B9\u4F7F\u7528\u7684\u8BED\u6CD5\u7CD6\u3002YukiHookAPI
\u53EF\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002// \u5224\u65AD\u8FD9\u4E2A Class \u662F\u5426\u5B58\u5728
+// \u5982\u679C\u5F53\u524D\u6B63\u5904\u4E8E PackageParam \u73AF\u5883\uFF0C\u90A3\u4E48\u4F60\u53EF\u4EE5\u4E0D\u9700\u8981\u8003\u8651 ClassLoader
+var isExist = "com.demo.Test".hasClass()
+// \u81EA\u5B9A\u4E49 Class \u6240\u5728\u7684 ClassLoader
+val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+var isExist = "com.demo.Test".hasClass(customClassLoader)
+
Class
\u540D\u79F0\u5C06\u4F1A\u96BE\u4EE5\u5206\u8FA8\uFF0C\u4E14\u4E0D\u786E\u5B9A\u5176\u6B63\u786E\u4F4D\u7F6E\uFF0C\u4E0D\u80FD\u76F4\u63A5\u901A\u8FC7 \u5BF9\u8C61\u8F6C\u6362 \u6765\u5F97\u5230\u3002DexClassFinder
\uFF0C\u5B83\u7684\u4F5C\u7528\u662F\u901A\u8FC7\u9700\u8981\u67E5\u627E\u7684 Class
\u4E2D\u7684\u5B57\u8282\u7801\u7279\u5F81\u6765\u786E\u5B9A\u8FD9\u4E2A Class
\u7684\u5B9E\u4F8B\u3002 \u5F00\u59CB\u4F7F\u7528
Class
\u662F\u6211\u4EEC\u60F3\u8981\u5F97\u5230\u7684\uFF0C\u5176\u4E2D\u7684\u540D\u79F0\u7ECF\u8FC7\u4E86\u6DF7\u6DC6\uFF0C\u5728\u6BCF\u4E2A\u7248\u672C\u53EF\u80FD\u90FD\u4E0D\u4E00\u6837\u3002package com.demo;
+
+public class a extends Activity implements Serializable {
+
+ public a(String var1) {
+ // ...
+ }
+
+ private String a;
+
+ private String b;
+
+ private boolean a;
+
+ protected void onCreate(Bundle var1) {
+ // ...
+ }
+
+ private static void a(String var1) {
+ // ...
+ }
+
+ private String a(boolean var1, String var2) {
+ // ...
+ }
+
+ private void a() {
+ // ...
+ }
+
+ public void a(boolean var1, a var2, b var3, String var4) {
+ // ...
+ }
+}
+
Class
\uFF0C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 ClassLoader.searchClass
\u65B9\u6CD5\u3002PackageParam
\u4E2D\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 searchClass
\u65B9\u6CD5\uFF0C\u5B83\u5C06\u81EA\u52A8\u6307\u5B9A appClassLoader
\u3002searchClass {
+ // \u4ECE\u6307\u5B9A\u7684\u5305\u540D\u8303\u56F4\u5F00\u59CB\u67E5\u627E\uFF0C\u5B9E\u9645\u4F7F\u7528\u65F6\uFF0C\u4F60\u53EF\u4EE5\u540C\u65F6\u6307\u5B9A\u591A\u4E2A\u5305\u540D\u8303\u56F4
+ from("com.demo")
+ // \u6307\u5B9A\u5F53\u524D Class \u7684 getSimpleName \u7684\u7ED3\u679C\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u5BF9\u8FD9\u4E2A\u5B57\u7B26\u4E32\u8FDB\u884C\u903B\u8F91\u5224\u65AD
+ // \u8FD9\u91CC\u6211\u4EEC\u4E0D\u786E\u5B9A\u5B83\u7684\u540D\u79F0\u662F\u4E0D\u662F a\uFF0C\u53EF\u4EE5\u53EA\u5224\u65AD\u5B57\u7B26\u4E32\u957F\u5EA6
+ simpleName { it.length == 1 }
+ // \u6307\u5B9A\u7EE7\u627F\u7684\u7236\u7C7B\u5BF9\u8C61\uFF0C\u5982\u679C\u662F\u5B58\u5728\u7684 stub\uFF0C\u53EF\u4EE5\u76F4\u63A5\u7528\u6CDB\u578B\u8868\u793A
+ extends<Activity>()
+ // \u6307\u5B9A\u7EE7\u627F\u7684\u7236\u7C7B\u5BF9\u8C61\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5199\u4E3A\u5B8C\u6574\u7C7B\u540D\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u540C\u65F6\u6307\u5B9A\u591A\u4E2A
+ extends("android.app.Activity")
+ // \u6307\u5B9A\u5B9E\u73B0\u7684\u63A5\u53E3\uFF0C\u5982\u679C\u662F\u5B58\u5728\u7684 stub\uFF0C\u53EF\u4EE5\u76F4\u63A5\u7528\u6CDB\u578B\u8868\u793A
+ implements<Serializable>()
+ // \u6307\u5B9A\u5B9E\u73B0\u7684\u63A5\u53E3\uFF0C\u53EF\u4EE5\u76F4\u63A5\u5199\u4E3A\u5B8C\u6574\u7C7B\u540D\uFF0C\u4F60\u8FD8\u53EF\u4EE5\u540C\u65F6\u6307\u5B9A\u591A\u4E2A
+ implements("java.io.Serializable")
+ // \u6307\u5B9A\u6784\u9020\u65B9\u6CD5\u7684\u7C7B\u578B\u4E0E\u6837\u5F0F\uFF0C\u4EE5\u53CA\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ constructor { param(StringType) }.count(num = 1)
+ // \u6307\u5B9A\u53D8\u91CF\u7684\u7C7B\u578B\u4E0E\u6837\u5F0F\uFF0C\u4EE5\u53CA\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ field { type = StringType }.count(num = 2)
+ // \u6307\u5B9A\u53D8\u91CF\u7684\u7C7B\u578B\u4E0E\u6837\u5F0F\uFF0C\u4EE5\u53CA\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ field { type = BooleanType }.count(num = 1)
+ // \u76F4\u63A5\u6307\u5B9A\u6240\u6709\u53D8\u91CF\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ field().count(num = 3)
+ // \u5982\u679C\u4F60\u8BA4\u4E3A\u53D8\u91CF\u7684\u4E2A\u6570\u662F\u4E0D\u786E\u5B9A\u7684\uFF0C\u8FD8\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u81EA\u5B9A\u4E49\u6761\u4EF6
+ field().count(1..3)
+ field().count { it >= 3 }
+ // \u6307\u5B9A\u65B9\u6CD5\u7684\u7C7B\u578B\u4E0E\u6837\u5F0F\uFF0C\u4EE5\u53CA\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }.count(num = 1)
+ // \u6307\u5B9A\u65B9\u6CD5\u7684\u7C7B\u578B\u4E0E\u6837\u5F0F\uFF0C\u540C\u65F6\u6307\u5B9A\u4FEE\u9970\u7B26\uFF0C\u4EE5\u53CA\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ method {
+ modifiers { isStatic && isPrivate }
+ param(StringType)
+ returnType = UnitType
+ }.count(num = 1)
+ // \u6307\u5B9A\u65B9\u6CD5\u7684\u7C7B\u578B\u4E0E\u6837\u5F0F\uFF0C\u540C\u65F6\u6307\u5B9A\u4FEE\u9970\u7B26\uFF0C\u4EE5\u53CA\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, StringType)
+ returnType = StringType
+ }.count(num = 1)
+ // \u6307\u5B9A\u65B9\u6CD5\u7684\u7C7B\u578B\u4E0E\u6837\u5F0F\uFF0C\u540C\u65F6\u6307\u5B9A\u4FEE\u9970\u7B26\uFF0C\u4EE5\u53CA\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ emptyParam()
+ returnType = UnitType
+ }.count(num = 1)
+ // \u6307\u5B9A\u65B9\u6CD5\u7684\u7C7B\u578B\u4E0E\u6837\u5F0F\uFF0C\u540C\u65F6\u6307\u5B9A\u4FEE\u9970\u7B26\u548C\u6A21\u7CCA\u7C7B\u578B VagueType\uFF0C\u4EE5\u53CA\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, VagueType, VagueType, StringType)
+ returnType = UnitType
+ }.count(num = 1)
+ // \u76F4\u63A5\u6307\u5B9A\u6240\u6709\u65B9\u6CD5\u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ method().count(num = 5)
+ // \u5982\u679C\u4F60\u8BA4\u4E3A\u65B9\u6CD5\u7684\u4E2A\u6570\u662F\u4E0D\u786E\u5B9A\u7684\uFF0C\u8FD8\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u81EA\u5B9A\u4E49\u6761\u4EF6
+ method().count(1..5)
+ method().count { it >= 5 }
+ // \u76F4\u63A5\u6307\u5B9A\u6240\u6709\u6210\u5458 (Member) \u5728\u5F53\u524D\u7C7B\u4E2D\u5B58\u5728\u7684\u4E2A\u6570 count
+ // \u6210\u5458\u5305\u62EC\uFF1AField (\u53D8\u91CF)\u3001Method (\u65B9\u6CD5)\u3001Constructor (\u6784\u9020\u65B9\u6CD5)
+ member().count(num = 9)
+ // \u6240\u6709\u6210\u5458\u4E2D\u4E00\u5B9A\u5B58\u5728\u4E00\u4E2A static \u4FEE\u9970\u7B26\uFF0C\u53EF\u4EE5\u8FD9\u6837\u52A0\u5165\u6B64\u6761\u4EF6
+ member {
+ modifiers { isStatic }
+ }
+}.get() // \u5F97\u5230\u8FD9\u4E2A Class \u672C\u8EAB\u7684\u5B9E\u4F8B\uFF0C\u627E\u4E0D\u5230\u4F1A\u8FD4\u56DE null
+
\u5F02\u6B65\u67E5\u627E
DexClassFinder
\u4F1A\u4F7F\u7528\u540C\u6B65\u65B9\u5F0F\u67E5\u627E Class
\uFF0C\u4F1A\u963B\u585E\u5F53\u524D\u7EBF\u7A0B\u76F4\u5230\u627E\u5230\u6216\u627E\u4E0D\u5230\u53D1\u751F\u5F02\u5E38\u4E3A\u6B62\uFF0C\u82E5\u67E5\u627E\u6D88\u8017\u7684\u65F6\u95F4\u8FC7\u957F\uFF0C\u53EF\u80FD\u4F1A\u5BFC\u81F4\u5BBF\u4E3B\u53D1\u751F ANR \u95EE\u9898\u3002async = true
\uFF0C\u8FD9\u5C06\u4E0D\u9700\u8981\u4F60\u518D\u6B21\u542F\u52A8\u4E00\u4E2A\u7EBF\u7A0B\uFF0CAPI \u5DF2\u5E2E\u4F60\u5904\u7406\u597D\u76F8\u5173\u95EE\u9898\u3002searchClass(async = true) {
+ // ...
+}.wait { class1 ->
+ // \u5F97\u5230\u5F02\u6B65\u7ED3\u679C
+}
+searchClass(async = true) {
+ // ...
+}.wait { class2 ->
+ // \u5F97\u5230\u5F02\u6B65\u7ED3\u679C
+}
+
\u672C\u5730\u7F13\u5B58
name
\u53C2\u6570\u6765\u5BF9\u5F53\u524D\u5BBF\u4E3B\u7248\u672C\u7684\u67E5\u627E\u7ED3\u679C\u8FDB\u884C\u672C\u5730\u7F13\u5B58\uFF0C\u4E0B\u4E00\u6B21\u5C06\u76F4\u63A5\u4ECE\u672C\u5730\u7F13\u5B58\u4E2D\u8BFB\u53D6\u67E5\u627E\u5230\u7684\u7C7B\u540D\u3002SharedPreferences
\uFF0C\u5B83\u5C06\u88AB\u4FDD\u5B58\u5230\u5BBF\u4E3B\u7684\u6570\u636E\u76EE\u5F55\u4E2D\uFF0C\u5728\u5BBF\u4E3B\u7248\u672C\u66F4\u65B0\u540E\u4F1A\u91CD\u65B0\u8FDB\u884C\u7F13\u5B58\u3002async = true
\uFF0C\u4F60\u53EF\u4EE5\u4E0D\u9700\u8981\u518D\u624B\u52A8\u8FDB\u884C\u8BBE\u7F6E\u3002searchClass(name = "com.demo.class1") {
+ // ...
+}.wait { class1 ->
+ // \u5F97\u5230\u5F02\u6B65\u7ED3\u679C
+}
+searchClass(name = "com.demo.class2") {
+ // ...
+}.wait { class2 ->
+ // \u5F97\u5230\u5F02\u6B65\u7ED3\u679C
+}
+
// \u76F4\u63A5\u8C03\u7528\uFF0C\u5728\u5BBF\u4E3B\u7684 appContext \u4E3A\u7A7A\u65F6\u53EF\u80FD\u4F1A\u5931\u8D25\uFF0C\u5931\u8D25\u4F1A\u6253\u5370\u8B66\u544A\u4FE1\u606F
+DexClassFinder.clearCache()
+// \u76D1\u542C\u5BBF\u4E3B\u7684\u751F\u547D\u5468\u671F\u540E\u8C03\u7528
+onAppLifecycle {
+ onCreate {
+ DexClassFinder.clearCache(context = this)
+ }
+}
+
// \u76F4\u63A5\u8C03\u7528\uFF0C\u5728\u5BBF\u4E3B\u7684 appContext \u4E3A\u7A7A\u65F6\u53EF\u80FD\u4F1A\u5931\u8D25\uFF0C\u5931\u8D25\u4F1A\u6253\u5370\u8B66\u544A\u4FE1\u606F
+DexClassFinder.clearCache(versionName = "1.0", versionCode = 1)
+// \u76D1\u542C\u5BBF\u4E3B\u7684\u751F\u547D\u5468\u671F\u540E\u8C03\u7528
+onAppLifecycle {
+ onCreate {
+ DexClassFinder.clearCache(context = this, versionName = "1.0", versionCode = 1)
+ }
+}
+
\u591A\u91CD\u67E5\u627E
Class
\uFF0C\u90A3\u4E48\u4F60\u53EA\u9700\u8981\u4F7F\u7528 all
\u6216 waitAll
\u65B9\u6CD5\u6765\u5F97\u5230\u7ED3\u679C\u3002// \u540C\u6B65\u67E5\u627E\uFF0C\u4F7F\u7528 all \u5F97\u5230\u6761\u4EF6\u5168\u90E8\u67E5\u627E\u5230\u7684\u7ED3\u679C
+searchClass {
+ // ...
+}.all().forEach { clazz ->
+ // \u5F97\u5230\u6BCF\u4E2A\u7ED3\u679C
+}
+// \u540C\u6B65\u67E5\u627E\uFF0C\u4F7F\u7528 all { ... } \u904D\u5386\u6BCF\u4E2A\u7ED3\u679C
+searchClass {
+ // ...
+}.all { clazz ->
+ // \u5F97\u5230\u6BCF\u4E2A\u7ED3\u679C
+}
+// \u5F02\u6B65\u67E5\u627E\uFF0C\u4F7F\u7528 waitAll \u5F97\u5230\u6761\u4EF6\u5168\u90E8\u67E5\u627E\u5230\u7684\u7ED3\u679C
+searchClass(async = true) {
+ // ...
+}.waitAll { classes ->
+ classes.forEach {
+ // \u5F97\u5230\u6BCF\u4E2A\u7ED3\u679C
+ }
+}
+
Member \u6269\u5C55
Class
\u3002package com.demo;
+
+public class BaseTest {
+
+ public BaseTest() {
+ // ...
+ }
+
+ public BaseTest(boolean isInit) {
+ // ...
+ }
+
+ private void doBaseTask(String taskName) {
+ // ...
+ }
+}
+
package com.demo;
+
+public class Test extends BaseTest {
+
+ public Test() {
+ // ...
+ }
+
+ public Test(boolean isInit) {
+ // ...
+ }
+
+ private static TAG = "Test";
+
+ private BaseTest baseInstance;
+
+ private String a;
+
+ private boolean a;
+
+ private boolean isTaskRunning = false;
+
+ private static void init() {
+ // ...
+ }
+
+ private void doTask(String taskName) {
+ // ...
+ }
+
+ private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
+ // ...
+ }
+
+ private void stop() {
+ // ...
+ }
+
+ private String getName() {
+ // ...
+ }
+
+ private void b() {
+ // ...
+ }
+
+ private void b(String a) {
+ // ...
+ }
+}
+
\u67E5\u627E\u4E0E\u53CD\u5C04\u8C03\u7528
Test
(\u4EE5\u4E0B\u7EDF\u79F0\u201C\u5F53\u524D Class
\u201D)\u7684 doTask
\u65B9\u6CD5\u5E76\u6267\u884C\uFF0C\u901A\u5E38\u60C5\u51B5\u4E0B\uFF0C\u6211\u4EEC\u53EF\u4EE5\u4F7F\u7528\u6807\u51C6\u7684\u53CD\u5C04 API \u53BB\u67E5\u627E\u8FD9\u4E2A\u65B9\u6CD5\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528\u53CD\u5C04 API \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(instance, "task_name")
+
YukiHookAPI
\u5C31\u4E3A\u4F60\u63D0\u4F9B\u4E86\u4E00\u4E2A\u53EF\u5728\u4EFB\u610F\u5730\u65B9\u4F7F\u7528\u7684\u8BED\u6CD5\u7CD6\u3002YukiHookAPI
\u53EF\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "doTask"
+ param(StringType)
+}.get(instance).call("task_name")
+
isTaskRunning
\u53D8\u91CF\u4E5F\u53EF\u4EE5\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.field {
+ name = "isTaskRunning"
+ type = BooleanType
+}.get(instance).any() // any \u4E3A Field \u7684\u4EFB\u610F\u7C7B\u578B\u5B9E\u4F8B\u5316\u5BF9\u8C61
+
Class
\u7684\u6784\u9020\u65B9\u6CD5\uFF0C\u540C\u6837\u53EF\u4EE5\u5B9E\u73B0\u3002Test::class.java.constructor {
+ param(BooleanType)
+}.get().call(true) // \u53EF\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684\u5B9E\u4F8B
+
Class
\u7684\u65E0\u53C2\u6784\u9020\u65B9\u6CD5\uFF0C\u53EF\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002Test::class.java.constructor().get().call() // \u53EF\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684\u5B9E\u4F8B
+
\u53EF\u9009\u7684\u67E5\u627E\u6761\u4EF6
Class
\u4E2D\u7684 getName
\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5B9E\u73B0\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+ returnType = StringType
+}.get(instance).string() // \u5F97\u5230\u65B9\u6CD5\u7684\u7ED3\u679C
+
Class
\u4E2D\u53EA\u6709\u4E00\u4E2A\u540D\u4E3A getName
\u7684\u65B9\u6CD5\uFF0C\u90A3\u6211\u4EEC\u53EF\u4E0D\u53EF\u4EE5\u518D\u7B80\u5355\u4E00\u70B9\u5462\uFF1F// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+}.get(instance).string() // \u5F97\u5230\u65B9\u6CD5\u7684\u7ED3\u679C
+
get
\u6216 wait
\u65B9\u6CD5\u5F97\u5230\u7ED3\u679C\u65F6 YukiHookAPI
\u4F1A\u9ED8\u8BA4\u6309\u7167\u5B57\u8282\u7801\u987A\u5E8F\u5339\u914D\u7B2C\u4E00\u4E2A\u67E5\u627E\u5230\u7684\u7ED3\u679C\u3002Class
\u4E2D\u6709\u4E00\u4E2A release
\u65B9\u6CD5\uFF0C\u4F46\u662F\u5B83\u7684\u65B9\u6CD5\u53C2\u6570\u5F88\u957F\uFF0C\u800C\u4E14\u90E8\u5206\u7C7B\u578B\u53EF\u80FD\u65E0\u6CD5\u76F4\u63A5\u5F97\u5230\u3002param(...)
\u6765\u67E5\u627E\u8FD9\u4E2A\u65B9\u6CD5\uFF0C\u4F46\u662F\u6709\u6CA1\u6709\u66F4\u7B80\u5355\u7684\u65B9\u6CD5\u5462\u3002paramCount
\u6765\u67E5\u627E\u5230\u8FD9\u4E2A\u65B9\u6CD5\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "release"
+ // \u6B64\u65F6\u6211\u4EEC\u4E0D\u5FC5\u786E\u5B9A\u65B9\u6CD5\u53C2\u6570\u5177\u4F53\u7C7B\u578B\uFF0C\u5199\u4E2A\u6570\u5C31\u597D
+ paramCount = 3
+}.get(instance) // \u5F97\u5230\u8FD9\u4E2A\u65B9\u6CD5
+
VagueType
\u6765\u586B\u5145\u4F60\u4E0D\u60F3\u586B\u5199\u7684\u65B9\u6CD5\u53C2\u6570\u7C7B\u578B\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "release"
+ // \u4F7F\u7528 VagueType \u6765\u586B\u5145\u4E0D\u60F3\u586B\u5199\u7684\u7C7B\u578B\uFF0C\u540C\u65F6\u4FDD\u8BC1\u5176\u5B83\u7C7B\u578B\u80FD\u591F\u5339\u914D
+ param(StringType, VagueType, BooleanType)
+}.get(instance) // \u5F97\u5230\u8FD9\u4E2A\u65B9\u6CD5
+
\u5728\u7236\u7C7B\u67E5\u627E
Test
\u7EE7\u627F\u4E8E BaseTest
\uFF0C\u73B0\u5728\u6211\u4EEC\u60F3\u5F97\u5230 BaseTest
\u7684 doBaseTask
\u65B9\u6CD5\uFF0C\u5728\u4E0D\u77E5\u9053\u7236\u7C7B\u540D\u79F0\u7684\u60C5\u51B5\u4E0B\uFF0C\u8981\u600E\u4E48\u505A\u5462\uFF1FsuperClass
\u5373\u53EF\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringType)
+ // \u53EA\u9700\u8981\u6DFB\u52A0\u8FD9\u4E2A\u6761\u4EF6
+ superClass()
+}.get(instance).call("task_name")
+
superClass
\u6709\u4E00\u4E2A\u53C2\u6570\u4E3A isOnlySuperClass
\uFF0C\u8BBE\u7F6E\u4E3A true
\u540E\uFF0C\u53EF\u4EE5\u8DF3\u8FC7\u5F53\u524D Class
\u4EC5\u67E5\u627E\u5F53\u524D Class
\u7684\u7236\u7C7B\u3002doBaseTask
\u65B9\u6CD5\u53EA\u5B58\u5728\u4E8E\u7236\u7C7B\uFF0C\u53EF\u4EE5\u52A0\u4E0A\u8FD9\u4E2A\u6761\u4EF6\u8282\u7701\u67E5\u627E\u65F6\u95F4\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringType)
+ // \u52A0\u5165\u4E00\u4E2A\u67E5\u627E\u6761\u4EF6
+ superClass(isOnlySuperClass = true)
+}.get(instance).call("task_name")
+
superClass
\u4E00\u65E6\u8BBE\u7F6E\u5C31\u4F1A\u81EA\u52A8\u5FAA\u73AF\u5411\u540E\u67E5\u627E\u5168\u90E8\u7EE7\u627F\u7684\u7236\u7C7B\u4E2D\u662F\u5426\u6709\u8FD9\u4E2A\u65B9\u6CD5\uFF0C\u76F4\u5230\u67E5\u627E\u5230\u76EE\u6807\u6CA1\u6709\u7236\u7C7B(\u7EE7\u627F\u5173\u7CFB\u4E3A java.lang.Object
)\u4E3A\u6B62\u3002 \u6A21\u7CCA\u67E5\u627E
Class
\u4E2D\u7684 doTask
\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5B9E\u73B0\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name {
+ // \u8BBE\u7F6E\u540D\u79F0\u4E0D\u533A\u5206\u5927\u5C0F\u5199
+ it.equals("dotask", isIgnoreCase = true)
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
Class
\u4E2D\u4EC5\u6709\u4E00\u4E2A doTask
\u65B9\u6CD5\uFF0C\u6211\u4EEC\u8FD8\u53EF\u4EE5\u5224\u65AD\u65B9\u6CD5\u540D\u79F0\u4EC5\u5305\u542B\u5176\u4E2D\u6307\u5B9A\u7684\u5B57\u7B26\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name {
+ // \u4EC5\u5305\u542B oTas
+ it.contains("oTas")
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name {
+ // \u5F00\u5934\u5305\u542B do\uFF0C\u7ED3\u5C3E\u5305\u542B Task
+ it.startsWith("do") && it.endsWith("Task")
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name {
+ // \u5F00\u5934\u5305\u542B do\uFF0C\u7ED3\u5C3E\u5305\u542B Task\uFF0C\u4EC5\u5305\u542B\u5B57\u6BCD
+ it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters()
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
\u591A\u91CD\u67E5\u627E
Class
\u4E2D\u5177\u6709\u76F8\u540C\u7279\u5F81\u7684\u4E00\u7EC4\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u3001\u53D8\u91CF\uFF0C\u6B64\u65F6\uFF0C\u6211\u4EEC\u5C31\u53EF\u4EE5\u5229\u7528\u76F8\u5BF9\u6761\u4EF6\u5339\u914D\u6765\u5B8C\u6210\u3002get
\u6362\u4E3A all
\u5373\u53EF\u5F97\u5230\u5339\u914D\u6761\u4EF6\u7684\u5168\u90E8\u5B57\u8282\u7801\u3002Class
\u4E2D\u65B9\u6CD5\u53C2\u6570\u4E2A\u6570\u8303\u56F4\u5728 1..3
\u7684\u5168\u90E8\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5B9E\u73B0\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ paramCount(1..3)
+}.all(instance).forEach { instance ->
+ // \u8C03\u7528\u6267\u884C\u6BCF\u4E2A\u65B9\u6CD5
+ instance.call(...)
+}
+
private void doTask(String taskName)
private void release(String taskName, Function<boolean, String> task, boolean isFinish)
private void b(String a)
// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ paramCount { it < 3 }
+}.all(instance).forEach { instance ->
+ // \u8C03\u7528\u6267\u884C\u6BCF\u4E2A\u65B9\u6CD5
+ instance.call(...)
+}
+
private static void init()
private void doTask(String taskName)
private void stop(String a)
private void getName(String a)
private void b()
private void b(String a)
Class
\u4E2D\u6709\u4E24\u4E2A\u540D\u79F0\u4E3A b
\u7684\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5B9E\u73B0\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "b"
+}.all(instance).forEach { instance ->
+ // \u8C03\u7528\u6267\u884C\u6BCF\u4E2A\u65B9\u6CD5
+ instance.call(...)
+}
+
private void b()
private void b(String a)
\u9759\u6001\u5B57\u8282\u7801
Class
\u4E2D\u662F\u9759\u6001\u7684\u5B9E\u73B0\uFF0C\u8FD9\u4E2A\u65F6\u5019\uFF0C\u6211\u4EEC\u4E0D\u9700\u8981\u4F20\u5165\u5B9E\u4F8B\u5C31\u53EF\u4EE5\u8C03\u7528\u5B83\u4EEC\u3002TAG
\u7684\u5185\u5BB9\u3002Test::class.java.field {
+ name = "TAG"
+ type = StringType
+}.get().string() // Field \u7684\u7C7B\u578B\u662F\u5B57\u7B26\u4E32\uFF0C\u53EF\u76F4\u63A5\u8FDB\u884C cast
+
Class
\u4E2D\u5B58\u5728\u540C\u540D\u7684\u975E\u9759\u6001 TAG
\u53D8\u91CF\uFF0C\u8FD9\u4E2A\u65F6\u5019\u600E\u4E48\u529E\u5462\uFF1FTest::class.java.field {
+ name = "TAG"
+ type = StringType
+ // \u6807\u8BC6\u67E5\u627E\u7684\u8FD9\u4E2A\u53D8\u91CF\u9700\u8981\u662F\u9759\u6001
+ modifiers { isStatic }
+}.get().string() // Field \u7684\u7C7B\u578B\u662F\u5B57\u7B26\u4E32\uFF0C\u53EF\u76F4\u63A5\u8FDB\u884C cast
+
init
\u7684\u9759\u6001\u65B9\u6CD5\u3002Test::class.java.method {
+ name = "init"
+ emptyParam()
+}.get().call()
+
Test::class.java.method {
+ name = "init"
+ emptyParam()
+ // \u6807\u8BC6\u67E5\u627E\u7684\u8FD9\u4E2A\u65B9\u6CD5\u9700\u8981\u662F\u9759\u6001
+ modifiers { isStatic }
+}.get().call()
+
\u6DF7\u6DC6\u7684\u5B57\u8282\u7801
Class
\u4E2D\u6709\u4E24\u4E2A\u6DF7\u6DC6\u7684\u53D8\u91CF\u540D\u79F0\uFF0C\u5B83\u4EEC\u90FD\u662F a
\uFF0C\u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u8981\u600E\u4E48\u5F97\u5230\u5B83\u4EEC\u5462\uFF1F// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.field {
+ name = "a"
+ type = BooleanType
+}.get(instance).any() // \u5F97\u5230\u540D\u79F0\u4E3A a \u7C7B\u578B\u4E3A Boolean \u7684\u53D8\u91CF
+
// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.field {
+ type(BooleanType).index().first()
+}.get(instance).any() // \u5F97\u5230\u7B2C\u4E00\u4E2A\u7C7B\u578B\u4E3A Boolean \u7684\u53D8\u91CF
+
private boolean a
\u3002Class
\u4E2D\u4E5F\u6709\u4E24\u4E2A\u6DF7\u6DC6\u7684\u65B9\u6CD5\u540D\u79F0\uFF0C\u5B83\u4EEC\u90FD\u662F b
\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "b"
+ param(StringType)
+}.get(instance).call("test_string") // \u5F97\u5230\u540D\u79F0\u4E3A b \u65B9\u6CD5\u53C2\u6570\u4E3A [String] \u7684\u65B9\u6CD5
+
// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ param(StringType).index().first()
+}.get(instance).call("test_string") // \u5F97\u5230\u7B2C\u4E00\u4E2A\u65B9\u6CD5\u53C2\u6570\u4E3A [String] \u7684\u65B9\u6CD5
+
Class
\u7684\u6700\u540E\u4E00\u4E2A\uFF0C\u90A3\u6211\u4EEC\u8FD8\u6709\u4E00\u4E2A\u5907\u9009\u65B9\u6848\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ order().index().last()
+}.get(instance).call("test_string") // \u5F97\u5230\u5F53\u524D Class \u7684\u6700\u540E\u4E00\u4E2A\u65B9\u6CD5
+
\u76F4\u63A5\u8C03\u7528
get(instance)
\u624D\u80FD\u8C03\u7528\u5BF9\u5E94\u7684\u65B9\u6CD5\uFF0C\u6709\u6CA1\u6709\u7B80\u5355\u4E00\u70B9\u7684\u529E\u6CD5\u5462\uFF1Fcurrent
\u65B9\u6CD5\u6765\u521B\u5EFA\u4E00\u4E2A\u8C03\u7528\u7A7A\u95F4\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u5047\u8BBE\u8FD9\u4E2A Class \u662F\u4E0D\u80FD\u88AB\u76F4\u63A5\u5F97\u5230\u7684
+instance.current {
+ // \u6267\u884C doTask \u65B9\u6CD5
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+ // \u6267\u884C stop \u65B9\u6CD5
+ method {
+ name = "stop"
+ emptyParam()
+ }.call()
+ // \u5F97\u5230 name
+ val name = method { name = "getName" }.string()
+}
+
superClass
\u8C03\u7528\u5F53\u524D Class
\u7236\u7C7B\u7684\u65B9\u6CD5\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u5047\u8BBE\u8FD9\u4E2A Class \u662F\u4E0D\u80FD\u88AB\u76F4\u63A5\u5F97\u5230\u7684
+instance.current {
+ // \u6267\u884C\u7236\u7C7B\u7684 doBaseTask \u65B9\u6CD5
+ superClass().method {
+ name = "doBaseTask"
+ param(StringType)
+ }.call("task_name")
+}
+
current()
\u65B9\u6CD5\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B\uFF0C\u8FD9\u4E2A Class \u662F\u4E0D\u80FD\u88AB\u76F4\u63A5\u5F97\u5230\u7684
+val instance = Test()
+// \u6267\u884C doTask \u65B9\u6CD5
+instance
+ .current()
+ .method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+// \u6267\u884C stop \u65B9\u6CD5
+instance
+ .current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// \u5F97\u5230 name
+val name = instance.current().method { name = "getName" }.string()
+
// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u5047\u8BBE\u8FD9\u4E2A Class \u662F\u4E0D\u80FD\u88AB\u76F4\u63A5\u5F97\u5230\u7684
+instance.current {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+}.current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// \u2757\u6CE8\u610F\uFF0C\u56E0\u4E3A current() \u8FD4\u56DE\u7684\u662F CurrentClass \u81EA\u8EAB\u5BF9\u8C61\uFF0C\u6240\u4EE5\u4E0D\u80FD\u50CF\u4E0B\u9762\u8FD9\u6837\u8C03\u7528
+instance.current().current()
+
Field
\u5B9E\u4F8B\uFF0C\u8FD8\u6709\u4E00\u4E2A\u4FBF\u6377\u7684\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u76F4\u63A5\u83B7\u53D6 Field
\u6240\u5728\u5B9E\u4F8B\u7684\u5BF9\u8C61\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u5047\u8BBE\u8FD9\u4E2A Class \u662F\u4E0D\u80FD\u88AB\u76F4\u63A5\u5F97\u5230\u7684
+instance.current {
+ // <\u65B9\u68481>
+ field {
+ name = "baseInstance"
+ }.current {
+ method {
+ name = "doBaseTask"
+ param(StringType)
+ }.call("task_name")
+ }
+ // <\u65B9\u68482>
+ field {
+ name = "baseInstance"
+ }.current()
+ ?.method {
+ name = "doBaseTask"
+ param(StringType)
+ }?.call("task_name")
+}
+
Test(true).doTask("task_name")
+
"com.demo.Test".toClass()
+ .getDeclaredConstructor(Boolean::class.java)
+ .apply { isAccessible = true }
+ .newInstance(true)
+ .apply {
+ javaClass
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(this, "task_name")
+ }
+
buildOf
\u65B9\u6CD5\u6765\u521B\u5EFA\u4E00\u4E2A\u5B9E\u4F8B\u3002"com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+}
+
buildOf
\u65B9\u6CD5\u8FD4\u56DE\u5F53\u524D\u5B9E\u4F8B\u7684\u7C7B\u578B\uFF0C\u4F60\u53EF\u4EE5\u5728\u5176\u4E2D\u52A0\u5165\u7C7B\u578B\u6CDB\u578B\u58F0\u660E\uFF0C\u800C\u65E0\u9700\u4F7F\u7528 as
\u6765 cast
\u76EE\u6807\u7C7B\u578B\u3002// \u5047\u8BBE\u8FD9\u4E2A Class \u662F\u80FD\u591F\u76F4\u63A5\u88AB\u5F97\u5230\u7684
+val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
+test.doTask("task_name")
+
\u539F\u59CB\u8C03\u7528
XposedBridge
\u4E3A\u6211\u4EEC\u63D0\u4F9B\u4E86\u4E00\u4E2A XposedBridge.invokeOriginalMethod
\u529F\u80FD\u3002YukiHookAPI
\u4E2D\u4F60\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u65B9\u6CD5\u4FBF\u6377\u5730\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002Class
\u3002public class Test {
+
+ public static String getString() {
+ return "Original";
+ }
+}
+
Class
\u4E2D getString
\u65B9\u6CD5\u7684\u65B9\u5F0F\u3002Test::class.java.hook {
+ injectMember {
+ method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+ }
+ replaceTo("Hooked")
+ }
+}
+
"Hooked"
\u3002// result \u7684\u7ED3\u679C\u4F1A\u662F "Hooked"
+val result = Test::class.java.method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+}.get().string()
+
original
\u5373\u53EF\u3002// result \u7684\u7ED3\u679C\u4F1A\u662F "Original"
+val result = Test::class.java.method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+}.get().original().string()
+
\u518D\u6B21\u67E5\u627E
Class
\uFF0C\u5B83\u4EEC\u90FD\u662F\u8FD9\u4E2A\u5BBF\u4E3B\u4E0D\u540C\u7248\u672C\u76F8\u540C\u7684 Class
\u3002doTask
\uFF0C\u5047\u8BBE\u5B83\u4EEC\u7684\u529F\u80FD\u662F\u4E00\u6837\u7684\u3002public class Test {
+
+ public void doTask() {
+ // ...
+ }
+}
+
public class Test {
+
+ public void doTask(String taskName) {
+ // ...
+ }
+}
+
public class Test {
+
+ public void doTask(String taskName, int type) {
+ // ...
+ }
+}
+
doTask
\u65B9\u6CD5\uFF0C\u8981\u600E\u4E48\u505A\u5462\uFF1FRemedyPlan
\u5B8C\u6210\u4F60\u7684\u9700\u6C42\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.onFind {
+ // \u53EF\u5728\u8FD9\u91CC\u5B9E\u73B0\u627E\u5230\u7684\u903B\u8F91
+ }
+ method {
+ name = "doTask"
+ param(StringType, IntType)
+ }.onFind {
+ // \u53EF\u5728\u8FD9\u91CC\u5B9E\u73B0\u627E\u5230\u7684\u903B\u8F91
+ }
+}.wait(instance) {
+ // \u5F97\u5230\u65B9\u6CD5\u7684\u7ED3\u679C
+}
+
RemedyPlan
\u3002// \u5047\u8BBE\u8FD9\u5C31\u662F\u8FD9\u4E2A Class \u7684\u5B9E\u4F8B
+val instance = Test()
+// \u4F7F\u7528 YukiHookAPI \u8C03\u7528\u5E76\u6267\u884C
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }.onFind {
+ // \u53EF\u5728\u8FD9\u91CC\u5B9E\u73B0\u627E\u5230\u7684\u903B\u8F91
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }.onFind {
+ // \u53EF\u5728\u8FD9\u91CC\u5B9E\u73B0\u627E\u5230\u7684\u903B\u8F91
+ }
+}.waitAll(instance) {
+ // \u5F97\u5230\u65B9\u6CD5\u7684\u7ED3\u679C
+}
+
Class
\u4E3E\u4F8B\uFF0C\u82E5 \u591A\u91CD\u67E5\u627E \u7ED3\u5408 RemedyPlan
\u5728\u521B\u5EFA Hook \u7684\u65F6\u5019\u4F7F\u7528\uFF0C\u4F60\u9700\u8981\u7A0D\u5FAE\u6539\u53D8\u4E00\u4E0B\u7528\u6CD5\u3002injectMember {
+ method {
+ name = "doTask"
+ emptyParam()
+ }.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }
+ }.all()
+ beforeHook {}
+ afterHook {}
+}
+
\u76F8\u5BF9\u5339\u914D
Class
\u4F46\u4EC5\u6709 Class
\u7684\u540D\u79F0\u4E0D\u4E00\u6837\u3002public class ATest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
public class BTest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
Class
\u91CC\u7684 doTask
\u65B9\u6CD5\u8BE5\u600E\u4E48\u505A\u5462\uFF1FClass
\u662F\u5426\u5B58\u5728\u3002// \u9996\u5148\u67E5\u627E\u5230\u8FD9\u4E2A Class
+val currentClass =
+ if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass()
+// \u7136\u540E\u518D\u67E5\u627E\u8FD9\u4E2A\u65B9\u6CD5\u5E76\u8C03\u7528
+currentClass.method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
YukiHookAPI
\u5C31\u4E3A\u4F60\u63D0\u4F9B\u4E86\u4E00\u4E2A\u975E\u5E38\u65B9\u4FBF\u7684 VariousClass
\u4E13\u95E8\u6765\u89E3\u51B3\u8FD9\u4E2A\u95EE\u9898\u3002Class
\u3002VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
\u5728\u6307\u5B9A\u7684 ClassLoader
\u4E2D\u5B58\u5728\uFF0C\u4F60\u53EF\u4EE5\u5728 get
\u4E2D\u586B\u5165\u4F60\u7684 ClassLoader
\u3002val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
\u4E00\u5B9A\u4F1A\u88AB\u5339\u914D\u5230\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 getOrNull
\u65B9\u6CD5\u3002val customClassLoader: ClassLoader? = ... // \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F\u4F60\u7684 ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
+ name = "doTask"
+ emptyParam()
+}?.get()?.call()
+
PackageParam
\u4E2D\u64CD\u4F5C (Xposed) \u5BBF\u4E3B\u73AF\u5883\u7684 Class
\uFF0C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 toClass()
\u8FDB\u884C\u8BBE\u7F6E\u3002VariousClass("com.demo.ATest", "com.demo.BTest").toClass().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
\u7684\u5F02\u5E38\u3002findClass("com.demo.ATest", "com.demo.BTest").hook {
+ // Your code here.
+}
+
Class
\u5B9A\u4E49\u4E3A\u4E00\u4E2A\u5E38\u91CF\u7C7B\u578B\u6765\u4F7F\u7528\u3002// \u5B9A\u4E49\u5E38\u91CF\u7C7B\u578B
+val ABTestClass = VariousClass("com.demo.ATest", "com.demo.BTest")
+// \u76F4\u63A5\u4F7F\u7528
+ABTestClass.hook {
+ // Your code here.
+}
+
\u8C03\u7528\u6CDB\u578B
YukiHookAPI
\u540C\u6837\u63D0\u4F9B\u4E86\u4E00\u4E2A\u53EF\u5728\u4EFB\u610F\u5730\u65B9\u4F7F\u7528\u7684\u8BED\u6CD5\u7CD6\u3002class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // ...
+ }
+}
+
Class
\u4E2D\u83B7\u5F97\u6CDB\u578B T
\u6216 R
\u7684 Class
\u5B9E\u4F8B\uFF0C\u53EA\u9700\u8981\u5982\u4E0B\u5B9E\u73B0\u3002class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // \u83B7\u5F97\u5F53\u524D\u5B9E\u4F8B\u7684\u64CD\u4F5C\u5BF9\u8C61
+ // \u83B7\u5F97 T \u7684 Class \u5B9E\u4F8B\uFF0C\u5728\u53C2\u6570\u7B2C 0 \u4F4D\uFF0C\u9ED8\u8BA4\u503C\u53EF\u4EE5\u4E0D\u5199
+ val tClass = current().generic()?.argument()
+ // \u83B7\u5F97 R \u7684 Class \u5B9E\u4F8B\uFF0C\u5728\u53C2\u6570\u7B2C 1 \u4F4D
+ val rClass = current().generic()?.argument(index = 1)
+ // \u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5199\u6CD5
+ current().generic {
+ // \u83B7\u5F97 T \u7684 Class \u5B9E\u4F8B\uFF0C\u5728\u53C2\u6570\u7B2C 0 \u4F4D\uFF0C\u9ED8\u8BA4\u503C\u53EF\u4EE5\u4E0D\u5199
+ val tClass = argument()
+ // \u83B7\u5F97 R \u7684 Class \u5B9E\u4F8B\uFF0C\u5728\u53C2\u6570\u7B2C 1 \u4F4D
+ val rClass = argument(index = 1)
+ }
+ }
+}
+
Class
\u65F6\uFF0C\u5C31\u53EF\u4EE5\u6709\u5982\u4E0B\u5B9E\u73B0\u3002// \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F T \u7684 Class
+class TI {
+
+ fun foo() {
+ // ...
+ }
+}
+// \u5047\u8BBE\u8FD9\u4E2A\u5C31\u662F T \u7684\u5B9E\u4F8B
+val tInstance: TI? = ...
+// \u83B7\u5F97 T \u7684 Class \u5B9E\u4F8B\uFF0C\u5728\u53C2\u6570\u7B2C 0 \u4F4D\uFF0C\u9ED8\u8BA4\u503C\u53EF\u4EE5\u4E0D\u5199\uFF0C\u5E76\u83B7\u5F97\u5176\u4E2D\u7684\u65B9\u6CD5 foo \u5E76\u8C03\u7528
+TestGeneric::class.java.generic()?.argument()?.method {
+ name = "foo"
+ emptyParam()
+}?.get(tInstance)?.invoke<TI>()
+
\u6CE8\u610F\u8BEF\u533A
\u9650\u5236\u6027\u67E5\u627E\u6761\u4EF6
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ // \u2757\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u8BF7\u4EC5\u4FDD\u7559\u4E00\u4E2A index \u65B9\u6CD5
+ returnType(StringType).index(num = 1)
+}
+
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ order().index(num = 1)
+}
+
\u5FC5\u8981\u7684\u67E5\u627E\u6761\u4EF6
Class
\u3002public class TestFoo {
+
+ public void foo(String string) {
+ // ...
+ }
+
+ public void foo() {
+ // ...
+ }
+}
+
public void foo()
\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002TestFoo::class.java.method {
+ name = "foo"
+}
+
Class
\u4E2D\u6709\u4E24\u4E2A foo
\u65B9\u6CD5\uFF0C\u5176\u4E2D\u4E00\u4E2A\u5E26\u6709\u65B9\u6CD5\u53C2\u6570\u3002param
\u7684\u67E5\u627E\u6761\u4EF6\uFF0C\u5F97\u5230\u7684\u7ED3\u679C\u5C06\u4F1A\u662F\u5339\u914D\u540D\u79F0\u4E14\u5339\u914D\u5B57\u8282\u7801\u987A\u5E8F\u7684\u7B2C\u4E00\u4E2A\u65B9\u6CD5 public void foo(String string)
\uFF0C\u800C\u4E0D\u662F\u6211\u4EEC\u9700\u8981\u7684\u6700\u540E\u4E00\u4E2A\u65B9\u6CD5\u3002TestFoo::class.java.method {
+ name = "foo"
+ // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u6DFB\u52A0\u8BE6\u7EC6\u7684\u7B5B\u9009\u6761\u4EF6
+ emptyParam()
+}
+
public void foo()
\u65B9\u6CD5\u3002 \u53EF\u7B80\u5199\u67E5\u627E\u6761\u4EF6
Class
\u3002public class TestFoo {
+
+ public TestFoo() {
+ // ...
+ }
+}
+
public TestFoo()
\u6784\u9020\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002TestFoo::class.java.constructor { emptyParam() }
+
public TestFoo()
\u6784\u9020\u65B9\u6CD5\uFF0C\u4F46\u662F\u611F\u89C9\u6709\u4E00\u4E9B\u7E41\u7410\u3002name
\u540D\u79F0\uFF0C\u5F53\u6784\u9020\u65B9\u6CD5\u6CA1\u6709\u53C2\u6570\u7684\u65F6\u5019\uFF0C\u6211\u4EEC\u53EF\u4EE5\u7701\u7565 emptyParam
\u53C2\u6570\u3002TestFoo::class.java.constructor()
+
\u5B57\u8282\u7801\u7C7B\u578B
Boolean
\u7C7B\u578B\u7684\u53D8\u91CF\uFF0C\u628A\u4ED6\u8F6C\u6362\u4E3A String
\u3002field {
+ name = "test"
+ type = BooleanType
+}.get().string() // \u2757\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5FC5\u987B cast \u4E3A\u5B57\u8282\u7801\u76EE\u6807\u7C7B\u578B
+
field {
+ name = "test"
+ type = BooleanType
+}.get().boolean().toString() // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u5F97\u5230\u7C7B\u578B\u540E\u518D\u8FDB\u884C\u8F6C\u6362
+
\u5E38\u7528\u7C7B\u578B\u6269\u5C55
field {
+ name = "test"
+ type = Boolean::class.java
+}
+
Kotlin
\u4E2D\u8868\u8FBE\u51FA Boolean::class.java
\u8FD9\u4E2A\u7C7B\u578B\u7684\u5199\u6CD5\u5F88\u957F\uFF0C\u611F\u89C9\u5E76\u4E0D\u65B9\u4FBF\u3002YukiHookAPI
\u4E3A\u5F00\u53D1\u8005\u5C01\u88C5\u4E86\u5E38\u89C1\u7684\u7C7B\u578B\u8C03\u7528\uFF0C\u5176\u4E2D\u5305\u542B\u4E86 Android \u7684\u57FA\u672C\u7C7B\u578B\u548C Java \u7684\u57FA\u672C\u7C7B\u578B\u3002field {
+ name = "test"
+ type = BooleanType
+}
+
IntType
\u3001FloatType
\u3002String[]
\u7C7B\u578B\u7684\u6570\u7EC4\u3002java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
\u624D\u80FD\u5F97\u5230\u8FD9\u4E2A\u7C7B\u578B\u3002ArrayClass(StringType)
\u6765\u5F97\u5230\u8FD9\u4E2A\u7C7B\u578B\u3002String
\u662F\u5E38\u89C1\u7C7B\u578B\uFF0C\u6240\u4EE5\u8FD8\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 StringArrayClass
\u6765\u5F97\u5230\u8FD9\u4E2A\u7C7B\u578B\u3002onCreate
\u65B9\u6CD5\u9700\u8981\u67E5\u627E Bundle::class.java
\u7C7B\u578B\u3002method {
+ name = "onCreate"
+ param(BundleClass)
+}
+
Reflection Extensions
YukiHookAPI
encapsulates a set of reflection API with near-zero reflection writing for developers, which can almost completely replace the usage of reflection API in Java. Class Extensions
Object Conversion
Class
that cannot be called directly.Class
.// Class in the default ClassLoader environment
+var instance = Class.forName("com.demo.Test")
+// Specify the Class in the ClassLoader environment
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = customClassLoader?.loadClass("com.demo.Test")
+
YukiHookAPI
provides you with a syntactic sugar that can be used anywhere.YukiHookAPI
as follows.// Get this Class directly
+// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader
+var instance = "com.demo.Test".toClass()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = "com.demo.Test".toClass(customClassLoader)
+
Class
does not exist, using the above method will throw an exception.Class
exists, you can refer to the following solutions.// Get this Class directly
+// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader
+// If not available, the result will be null but no exception will be thrown
+var instance = "com.demo.Test".toClassOrNull()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+// If not available, the result will be null but no exception will be thrown
+var instance = "com.demo.Test".toClassOrNull(customClassLoader)
+
Class
object by mapping.// Assume this Class can be obtained directly
+var instance = classOf<Test>()
+// We can also customize the ClassLoader where the Class is located, which is very effective for stubs
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = classOf<Test>(customClassLoader)
+
Existential Judgment
Class
exists.Class
to determine whether it exists by exception.// Class in the default ClassLoader environment
+var isExist = try {
+ Class.forName("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+// Specify the Class in the ClassLoader environment
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var isExist = try {
+ customClassLoader?.loadClass("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+
YukiHookAPI
provides you with a syntactic sugar that can be used anywhere.YukiHookAPI
as follows.// Check if this class exists
+// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader
+var isExist = "com.demo.Test".hasClass()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var isExist = "com.demo.Test".hasClass(customClassLoader)
+
Class
name in the Host App's Dex after being obfuscated by tools such as R8 will be difficult to distinguish.DexClassFinder
, its role is to determine the instance of this Class
by the bytecode features in the Class
that need to be searched. Get Started
Class
is what we want, the names are obfuscated and may be different in each version.package com.demo;
+
+public class a extends Activity implements Serializable {
+
+ public a(String var1) {
+ // ...
+ }
+
+ private String a;
+
+ private String b;
+
+ private boolean a;
+
+ protected void onCreate(Bundle var1) {
+ // ...
+ }
+
+ private static void a(String var1) {
+ // ...
+ }
+
+ private String a(boolean var1, String var2) {
+ // ...
+ }
+
+ private void a() {
+ // ...
+ }
+
+ public void a(boolean var1, a var2, b var3, String var4) {
+ // ...
+ }
+}
+
Class
, you can use the ClassLoader.searchClass
method directly.PackageParam
you can use the searchClass
method directly and it will automatically specify the appClassLoader
.searchClass {
+ // Start the search from the specified package name range
+ // In actual use, you can specify multiple package name ranges at the same time
+ from("com.demo")
+ // Specify the result of getSimpleName of the current Class
+ // You can directly make logical judgments on this string
+ // Here we are not sure whether its name is a, we can only judge the length of the string
+ simpleName { it.length == 1 }
+ // Specify the inherited parent class object
+ // If it is an existing stub, it can be directly represented by generics
+ extends<Activity>()
+ // Specify the inherited parent class object
+ // Which can be written directly as the full class name
+ // And you can also specify multiple objects at the same time
+ extends("android.app.Activity")
+ // Specify the implemented interface
+ // If it exists stub, can be directly represented by generics
+ implements<Serializable>()
+ // Specify the implemented interface
+ // Which can be written directly as a full class name, or you can specify multiple at the same time
+ 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)
+ // Specify the type and style of the variable
+ // And the number that exists in the current class count
+ field { type = StringType }.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)
+ // Directly specify the number of all variables that exist in the current class count
+ field().count(num = 3)
+ // If you think the number of variables is indeterminate
+ // You can also use the following custom conditions
+ field().count(1..3)
+ field().count { it >= 3 }
+ // Specify the type and style of the method
+ // And the number that exists in the current class count
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // Specify the modifier, and the number count in the current class
+ method {
+ modifiers { isStatic && isPrivate }
+ param(StringType)
+ 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
+ }.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() }
+ emptyParam()
+ returnType = UnitType
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // As well as the modifier and VagueType
+ // And the number count that exists in the current class
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, VagueType, VagueType, StringType)
+ returnType = UnitType
+ }.count(num = 1)
+ // Directly specify the number of all methods that exist in the current class count
+ method().count(num = 5)
+ // If you think the number of methods is uncertain, you can also use the following custom conditions
+ method().count(1..5)
+ method().count { it >= 5 }
+ // Directly specify the number of all members existing in the current class count
+ // Members include: Field, Method, Constructor
+ member().count(num = 9)
+ // There must be a static modifier in all members, you can add this condition like this
+ member {
+ modifiers { isStatic }
+ }
+}.get() // Get the instance of this Class itself, if not found, it will return null
+
Asynchronous Search
DexClassFinder
will use synchronous mode to search Class
, which will block the current thread until it finds or finds an exception.async = true
, which will not require you to start a thread again, the API has already handled the related problems for you.searchClass(async = true) {
+ // ...
+}.wait { class1 ->
+ // Get asynchronous result
+}
+searchClass(async = true) {
+ // ...
+}.wait { class2 ->
+ // Get asynchronous result
+}
+
Local Cache
name
parameter.SharedPreferences
, which will be saved to the Host App's data directory and will be re-cached after the Host App's version is updated.async = true
will be set at the same time, you don't need to set it manually.searchClass(name = "com.demo.class1") {
+ // ...
+}.wait { class1 ->
+ // Get asynchronous result
+}
+searchClass(name = "com.demo.class2") {
+ // ...
+}.wait { class2 ->
+ // Get asynchronous result
+}
+
// Call it directly
+// It may fail when the Host App's appContext is null, and a warning message will be printed on failure
+DexClassFinder.clearCache()
+// Called after listening to the lifecycle of the Host App
+onAppLifecycle {
+ onCreate {
+ DexClassFinder.clearCache(context = this)
+ }
+}
+
// Call it directly
+// It may fail when the Host App's appContext is null, and a warning message will be printed on failure
+DexClassFinder.clearCache(versionName = "1.0", versionCode = 1)
+// Called after listening to the lifecycle of the Host App
+onAppLifecycle {
+ onCreate {
+ DexClassFinder.clearCache(context = this, versionName = "1.0", versionCode = 1)
+ }
+}
+
Multiple Search
Class
at the same time using a fixed condition, then you only need to use the all
or waitAll
method to get the result.// Synchronous search, use all to get all the results found by the conditions
+searchClass {
+ // ...
+}.all().forEach { clazz ->
+ // Get each result
+}
+// Synchronous search, using all { ... } to iterate over each result
+searchClass {
+ // ...
+}.all { clazz ->
+ // Get each result
+}
+// Asynchronous search, use waitAll to get all the results found by the conditions
+searchClass(async = true) {
+ // ...
+}.waitAll { classes ->
+ classes.forEach {
+ // Get each result
+ }
+}
+
Member Extensions
Class
.package com.demo;
+
+public class BaseTest {
+
+ public BaseTest() {
+ // ...
+ }
+
+ public BaseTest(boolean isInit) {
+ // ...
+ }
+
+ private void doBaseTask(String taskName) {
+ // ...
+ }
+}
+
package com.demo;
+
+public class Test extends BaseTest {
+
+ public Test() {
+ // ...
+ }
+
+ public Test(boolean isInit) {
+ // ...
+ }
+
+ private static TAG = "Test";
+
+ private BaseTest baseInstance;
+
+ private String a;
+
+ private boolean a;
+
+ private boolean isTaskRunning = false;
+
+ private static void init() {
+ // ...
+ }
+
+ private void doTask(String taskName) {
+ // ...
+ }
+
+ private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
+ // ...
+ }
+
+ private void stop() {
+ // ...
+ }
+
+ private String getName() {
+ // ...
+ }
+
+ private void b() {
+ // ...
+ }
+
+ private void b(String a) {
+ // ...
+ }
+}
+
Find and Reflection
doTask
method of Test
and execute it.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using reflection API
+Test::class.java
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(instance, "task_name")
+
YukiHookAPI
provides you with a syntactic sugar that can be used anywhere.YukiHookAPI
as follows.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doTask"
+ param(StringType)
+}.get(instance).call("task_name")
+
isTaskRunning
field can also be written as follows.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.field {
+ name = "isTaskRunning"
+ type = BooleanType
+}.get(instance).any() // Any instantiates an object of any type of Field
+
Class
constructor, the same can be achieved.Test::class.java.constructor {
+ param(BooleanType)
+}.get().call(true) // Can create a new instance
+
Class
, you can write it as follows.Test::class.java.constructor().get().call() // Create a new instance
+
Optional Find Conditions
getName
method in Class
, which can be implemented as follows.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+ returnType = StringType
+}.get(instance).string() // Get the result of the method
+
getName
in this Class
, so can we make it simpler?// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+}.get(instance).string() // Get the result of the method
+
get
or wait
methods to get results, YukiHookAPI
will match the first found result in bytecode order by default.Class
has a release
method, but its method parameters are very long, and some types may not be directly available.param(...)
to find this method, but is there an easier way.paramCount
to find the method.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "release"
+ // At this point
+ // We don't have to determine the specific type of method parameters, just write the number
+ paramCount = 3
+}.get(instance) // Get this method
+
VagueType
to fill in the method parameter type that you do not want to fill in.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+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)
+}.get(instance) // Get this method
+
Find in Super Class
Test
extends BaseTest
, now we want to get the doBaseTask
method of BaseTest
, how do we do it without knowing the name of the super class?superClass
to the find conditions to achieve this function.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringType)
+ // Just add this condition
+ superClass()
+}.get(instance).call("task_name")
+
superClass
has a parameter isOnlySuperClass
, when set to true
, you can skip the current Class
and only find the super class of the current Class
.doBaseTask
method only exists in the super class, this condition can be added to save finding time.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringType)
+ // Add a find condition
+ superClass(isOnlySuperClass = true)
+}.get(instance).call("task_name")
+
superClass
is set, it will automatically cycle backward to find out whether this method exists in all extends super classes, until it finds that the target has no super class (the extends is java.lang.Object
). Vague Find
doTask
method in Class
, which can be implemented as follows.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name {
+ // Set name is case insensitive
+ it.equals("dotask", isIgnoreCase = true)
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
doTask
method in Class
, we can also judge that the method name contains only the characters specified in it.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name {
+ // Only contains oTas
+ it.contains("oTas")
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name {
+ // Contains do at the beginning and Task at the end
+ it.startsWith("do") && it.endsWith("Task")
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name {
+ // Start with do, end with Task, just letters
+ it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters()
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
Multiple Find
Class
.get
with all
to get all the bytecodes that match the condition.Class
with the number of method parameters in the range 1..3
, you can use the following implementation.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ paramCount(1..3)
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
private void doTask(String taskName)
private void release(String taskName, Function<boolean, String> task, boolean isFinish)
private void b(String a)
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ paramCount { it < 3 }
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
private static void init()
private void doTask(String taskName)
private void stop(String a)
private void getName(String a)
private void b()
private void b(String a)
b
in Class
, you can use the following implementation.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHook API
+Test::class.java.method {
+ name = "b"
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
private void b()
private void b(String a)
Static Bytecode
Class
, at this time, we can call them without passing in an instance.TAG
this time.Test::class.java.field {
+ name = "TAG"
+ type = StringType
+}.get().string() // The type of Field is string and can be cast directly
+
TAG
field with the same name in Class
, what should I do at this time?Test::class.java.field {
+ name = "TAG"
+ type = StringType
+ // 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
+
init
.Test::class.java.method {
+ name = "init"
+ emptyParam()
+}.get().call()
+
Test::class.java.method {
+ name = "init"
+ emptyParam()
+ // This method of identity find needs to be static
+ modifiers { isStatic }
+}.get().call()
+
Obfuscated Bytecode
Class
given here has two obfuscated field names, both of which are a
, how do we get them at this time?// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.field {
+ name = "a"
+ type = BooleanType
+}.get(instance).any() // Get a field named a with type Boolean
+
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.field {
+ type(BooleanType).index().first()
+}.get(instance).any() // Get the first field of type Boolean
+
private boolean a
can be obtained.Class
, both of which are b
.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "b"
+ param(StringType)
+}.get(instance).call("test_string") // Get the method whose name is b and whose parameter is [String]
+
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ param(StringType).index().first()
+}.get(instance).call("test_string") // Get the method whose first method parameter is [String]
+
Class
, then we have an alternative.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ order().index().last()
+}.get(instance).call("test_string") // Get the last method of the current Class
+
Directly Called
get(instance)
to call the corresponding method.current
method on any instance to create a call space.// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // Execute the doTask method
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+ // Execute the stop method
+ method {
+ name = "stop"
+ emptyParam()
+ }.call()
+ // Get name
+ val name = method { name = "getName" }.string()
+}
+
superClass
to call methods of the current Class
super class.// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // Execute the doBaseTask method of the parent class
+ superClass().method {
+ name = "doBaseTask"
+ param(StringType)
+ }.call("task_name")
+}
+
current()
method directly.// Assuming this is an instance of this Class, this Class cannot be obtained directly
+val instance = Test()
+// Execute the doTask method
+instance
+ .current()
+ .method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+// Execute the stop method
+instance
+ .current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// Get name
+val name = instance.current().method { name = "getName" }.string()
+
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+}.current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// \u2757 Note that because current() returns the CurrentClass object itself
+// It CANNOT BE CALLED like the following
+instance.current().current()
+
Field
instances, there is also a convenience method that can directly get the object of the instance where Field
is located.// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // <Plan 1>
+ field {
+ name = "baseInstance"
+ }.current {
+ method {
+ name = "doBaseTask"
+ param(StringType)
+ }.call("task_name")
+ }
+ // <Plan 2>
+ field {
+ name = "baseInstance"
+ }.current()
+ ?.method {
+ name = "doBaseTask"
+ param(StringType)
+ }?.call("task_name")
+}
+
Test(true).doTask("task_name")
+
"com.demo.Test".toClass()
+ .getDeclaredConstructor(Boolean::class.java)
+ .apply { isAccessible = true }
+ .newInstance(true)
+ .apply {
+ javaClass
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(this, "task_name")
+ }
+
buildOf
method to create an instance."com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+}
+
buildOf
method to return the type of the current instance, you can include a type-generic declaration in it instead of using as
to cast
the target type.// Assume this Class can be obtained directly
+val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
+test.doTask("task_name")
+
Original Called
XposedBridge
provides us with a XposedBridge.invokeOriginalMethod
function.YukiHookAPI
you can use the following method to implement this function conveniently.Class
we want to demonstrate.public class Test {
+
+ public static String getString() {
+ return "Original";
+ }
+}
+
getString
method in this Class
Hooks.Test::class.java.hook {
+ injectMember {
+ method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+ }
+ replaceTo("Hooked")
+ }
+}
+
"Hooked"
.// Result will be "Hooked"
+val result = Test::class.java.method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+}.get().string()
+
original
to the result.// Result will be "Original"
+val result = Test::class.java.method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+}.get().original().string()
+
Find Again
Class
, all of which are the same Class
for different versions of this Host App.doTask
in it, assuming they function the same.public class Test {
+
+ public void doTask() {
+ // ...
+ }
+}
+
public class Test {
+
+ public void doTask(String taskName) {
+ // ...
+ }
+}
+
public class Test {
+
+ public void doTask(String taskName, int type) {
+ // ...
+ }
+}
+
doTask
method in a different version, how do we do it?RemedyPlan
to complete your needs.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+ method {
+ name = "doTask"
+ param(StringType, IntType)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+}.wait(instance) {
+ // Get the result of the method
+}
+
RemedyPlan
while using Multiple Find.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+}.waitAll(instance) {
+ // Get the result of the method
+}
+
Class
as an example, if Multiple Find is used in conjunction with RemedyPlan
when creating a Hook, you need to change the usage slightly.injectMember {
+ method {
+ name = "doTask"
+ emptyParam()
+ }.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }
+ }.all()
+ beforeHook {}
+ afterHook {}
+}
+
Relative Matching
Class
with the same function in different versions of the Host App but only the name of the Class
is different.public class ATest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
public class BTest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
doTask
method in this Class
in each version?Class
exists.// First find this Class
+val currentClass =
+ if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass()
+// Then look for this method and call
+currentClass.method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
YukiHookAPI
provides you with a very convenient VariousClass
to solve this problem.Class
directly using the following methods.VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
exists in the specified ClassLoader
, you can fill in your ClassLoader
in get
.val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
will be matched, you can use the getOrNull
method.val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
+ name = "doTask"
+ emptyParam()
+}?.get()?.call()
+
Class
of the (Xposed) Host environment in PackageParam
, you can use toClass()
to set it directly.VariousClass("com.demo.ATest", "com.demo.BTest").toClass().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
cannot be found.findClass("com.demo.ATest", "com.demo.BTest").hook {
+ // Your code here.
+}
+
Class
as a constant type to use.// Define constant type
+val ABTestClass = VariousClass("com.demo.ATest", "com.demo.BTest")
+// Use directly
+ABTestClass.hook {
+ // Your code here.
+}
+
Calling Generics
YukiHookAPI
also provides a syntactic sugar that can be used anywhere.class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // ...
+ }
+}
+
Class
instance of the generic T
or R
in the current Class
, only the following implementation is required.class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // Get the operation object of the current instance
+ // Get the Class instance of T, in the 0th position of the parameter
+ // The default value can not be written
+ val tClass = current().generic()?.argument()
+ // Get the Class instance of R, in parameter 1
+ val rClass = current().generic()?.argument(index = 1)
+ // You can also use the following syntax
+ current().generic {
+ // Get the Class instance of T
+ // In the 0th position of the parameter, the default value can be left blank
+ val tClass = argument()
+ // Get the Class instance of R, in parameter 1
+ val rClass = argument(index = 1)
+ }
+ }
+}
+
Class
externally, it can be implemented as follows.// Assume this is the Class of T
+class TI {
+
+ fun foo() {
+ // ...
+ }
+}
+// Assume this is an instance of T
+val tInstance: TI? = ...
+// Get the Class instance of T
+// In the 0th position of the parameter, the default value can be left blank
+// And get the method foo and call it
+TestGeneric::class.java.generic()?.argument()?.method {
+ name = "foo"
+ emptyParam()
+}?.get(tInstance)?.invoke<TI>()
+
Pay Attention of Trap
Restrictive Find Conditions
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ // \u2757 Wrong usage, please keep only one index method
+ returnType(StringType).index(num = 1)
+}
+
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ order().index(num = 1)
+}
+
Necessary Find Conditions
Class
.public class TestFoo {
+
+ public void foo(String string) {
+ // ...
+ }
+
+ public void foo() {
+ // ...
+ }
+}
+
public void foo()
method, which can be written as follows.TestFoo::class.java.method {
+ name = "foo"
+}
+
foo
methods in this Class
, one of which takes a method parameter.param
, the result will be the first method public void foo(String string)
that matches the name and matches the bytecode order, not the last method we need.TestFoo::class.java.method {
+ name = "foo"
+ // \u2705 Correct usage, add detailed filter conditions
+ emptyParam()
+}
+
public void foo()
method. Abbreviated Find Conditions
Class
.public class TestFoo {
+
+ public TestFoo() {
+ // ...
+ }
+}
+
public TestFoo()
constructor, which can be written as follows.TestFoo::class.java.constructor { emptyParam() }
+
public TestFoo()
constructor, but it feels a bit cumbersome.name
, when the constructor has no parameters, we can omit the emptyParam
parameter.TestFoo::class.java.constructor()
+
Bytecode Type
Boolean
and cast it to String
.field {
+ name = "test"
+ type = BooleanType
+}.get().string() // \u2757 Wrong usage, must be cast to the bytecode target type
+
field {
+ name = "test"
+ type = BooleanType
+}.get().boolean().toString() // \u2705 The correct way to use, get the type and then convert
+
Common Type Extensions
field {
+ name = "test"
+ type = Boolean::class.java
+}
+
Boolean::class.java
in Kotlin
is very long and not convenient.YukiHookAPI
encapsulates common type calls for developers, including Android's basic types and Java's basic types.field {
+ name = "test"
+ type = BooleanType
+}
+
IntType
, FloatType
.String[]
.java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
to get this type.ArrayClass(StringType)
to get this type.String
is a common type, you can also directly use StringArrayClass
to get this type.onCreate
method needs to find the Bundle::class.java
type.method {
+ name = "onCreate"
+ param(BundleClass)
+}
+
Xposed \u6A21\u5757\u4E0E\u5BBF\u4E3B\u901A\u8BAF\u6865
\u57FA\u672C\u7528\u6CD5
wait
\u4E0E put
\u65B9\u6CD5\u7684\u57FA\u672C\u4F7F\u7528\u65B9\u6CD5\u3002dataChannel
\u6765\u5B9E\u73B0\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E4B\u95F4\u7684\u901A\u8BAF\u6865\uFF0C\u539F\u7406\u4E3A\u53D1\u9001\u63A5\u6536\u7CFB\u7EDF\u65E0\u5E8F\u5E7F\u64AD\u3002// \u4ECE\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u83B7\u53D6
+dataChannel(packageName = "com.example.demo").wait<String>(key = "key_from_host") { value ->
+ // Your code here.
+}
+// \u53D1\u9001\u7ED9\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B
+dataChannel(packageName = "com.example.demo").put(key = "key_from_module", value = "I am module")
+
// \u4ECE\u6A21\u5757\u83B7\u53D6
+dataChannel.wait<String>(key = "key_from_module") { value ->
+ // Your code here.
+}
+// \u53D1\u9001\u7ED9\u6A21\u5757
+dataChannel.put(key = "key_from_host", value = "I am host")
+
dataChannel
\u7684 value
\u6765\u8FBE\u5230\u4EC5\u901A\u77E5\u6A21\u5757\u6216\u5BBF\u4E3B\u56DE\u8C03 wait
\u65B9\u6CD5\u3002// \u4ECE\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u83B7\u53D6
+dataChannel(packageName = "com.example.demo").wait(key = "listener_from_host") {
+ // Your code here.
+}
+// \u53D1\u9001\u7ED9\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B
+dataChannel(packageName = "com.example.demo").put(key = "listener_from_module")
+
// \u4ECE\u6A21\u5757\u83B7\u53D6
+dataChannel.wait(key = "listener_from_module") {
+ // Your code here.
+}
+// \u53D1\u9001\u7ED9\u6A21\u5757
+dataChannel.put(key = "listener_from_host")
+
\u5224\u65AD\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7248\u672C\u662F\u5426\u5339\u914D
YukiHookAPI
\u8FD8\u4E3A\u4F60\u63D0\u4F9B\u4E86\u5728\u7528\u6237\u66F4\u65B0\u6A21\u5757\u540E\uFF0C\u5224\u65AD\u6A21\u5757\u662F\u5426\u4E0E\u5BBF\u4E3B\u7248\u672C\u5339\u914D\u7684\u89E3\u51B3\u65B9\u6848\u3002checkingVersionEquals
\u65B9\u6CD5\uFF0C\u5373\u53EF\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002// \u4ECE\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u83B7\u53D6
+dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
+ // Your code here.
+}
+
// \u4ECE\u6A21\u5757\u83B7\u53D6
+dataChannel.checkingVersionEquals { isEquals ->
+ // Your code here.
+}
+
\u56DE\u8C03\u4E8B\u4EF6\u54CD\u5E94\u7684\u89C4\u5219
key
\u59CB\u7EC8\u4E0D\u5141\u8BB8\u91CD\u590D\u521B\u5EFA\u3002class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // \u56DE\u8C03\u4E8B\u4EF6 A
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ // \u56DE\u8C03\u4E8B\u4EF6 B
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ // \u56DE\u8C03\u4E8B\u4EF6 C
+ dataChannel(packageName = "com.example.demo").wait(key = "other_test_key") {
+ // Your code here.
+ }
+ }
+}
+
+class OtherActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // \u56DE\u8C03\u4E8B\u4EF6 D
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ }
+}
+
key
\u4E0D\u4E0E\u5176\u5B83\u91CD\u590D\uFF0C\u56DE\u8C03\u4E8B\u4EF6 D \u5728\u53E6\u4E00\u4E2A Activity \u4E2D\uFF0C\u6240\u4EE5\u6700\u7EC8\u56DE\u8C03\u4E8B\u4EF6 B\u3001C\u3001D \u90FD\u53EF\u88AB\u521B\u5EFA\u6210\u529F\u3002 \u5B89\u5168\u6027\u8BF4\u660E
Xposed Module and Host Channel
Basic Usage
wait
and put
methods is described here.dataChannel
to realize the communication bridge between the Module App and the Host App, the principle is to send and receive system out-of-order broadcasts.// Get from the Host App of the specified package name
+dataChannel(packageName = "com.example.demo").wait<String>(key = "key_from_host") { value ->
+ // Your code here.
+}
+// Send to the Host App with the specified package name
+dataChannel(packageName = "com.example.demo").put(key = "key_from_module", value = "I am module")
+
// Get from the Module App
+dataChannel.wait<String>(key = "key_from_module") { value ->
+ // Your code here.
+}
+// Send to the Module App
+dataChannel.put(key = "key_from_host", value = "I am host")
+
value
of dataChannel
unset to only notify the Module App or Host App to call back the wait
method.// Get from the Host App of the specified package name
+dataChannel(packageName = "com.example.demo").wait(key = "listener_from_host") {
+ // Your code here.
+}
+// Send to the Host App with the specified package name
+dataChannel(packageName = "com.example.demo").put(key = "listener_from_module")
+
// Get from the Module App
+dataChannel.wait(key = "listener_from_module") {
+ // Your code here.
+}
+// Send to the Module App
+dataChannel.put(key = "listener_from_host")
+
Determine Module App and Host App Version Match
YukiHookAPI
also provides a solution for you to determine whether the Module App matches the Host App version after the user updates the Module App.checkingVersionEquals
method to achieve this function.// Get from the Host App of the specified package name
+dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
+ // Your code here.
+}
+
// Get from the Module App
+dataChannel.checkingVersionEquals { isEquals ->
+ // Your code here.
+}
+
Rules for Callback Event Response
key
in the Host App is always not allowed to be created repeatedly.class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Callback event A
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ // Callback event B
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ // Callback event C
+ dataChannel(packageName = "com.example.demo").wait(key = "other_test_key") {
+ // Your code here.
+ }
+ }
+}
+
+class OtherActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Callback event D
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ }
+}
+
key
of the callback event C is not repeated with others, and the callback event D is in another Activity, So the final callback events B, C, and D can all be created successfully. Security Instructions
Xposed \u6A21\u5757\u6570\u636E\u5B58\u50A8
SharedPreferences
\u548C XSharedPreferences
\u7684\u9AD8\u6548\u6A21\u5757\u6570\u636E\u5B58\u50A8\u89E3\u51B3\u65B9\u6848\u3002Sp
\u5B58\u50A8\u7684\u6570\u636E\u4E92\u901A\u963B\u788D\u3002Xposed
\u7ED9\u6211\u4EEC\u63D0\u4F9B\u4E86\u4E00\u4E2A XSharedPreferences
\u7528\u4E8E\u8BFB\u53D6\u6A21\u5757\u7684 Sp
\u6570\u636E\u3002 \u5728 Activity \u4E2D\u4F7F\u7528
Activity
\u4E2D\u88C5\u8F7D YukiHookModulePrefs
\u7684\u573A\u666F\u3002XSharedPreferences(BuildConfig.APPLICATION_ID)
+
YukiHookAPI
\u7684\u6269\u5C55\u80FD\u529B\u5FEB\u901F\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002Activity
\u5185\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u65B9\u6CD5\u3002modulePrefs.putString("test_name", "saved_value")
+
val testName = prefs.getString("test_name", "default_value")
+
YukiHookModulePrefs
\u6765\u5904\u7406\u3002prefs
\u6587\u4EF6\u7684\u540D\u79F0\u3002Activity
\u4E2D\u8FD9\u6837\u4F7F\u7528\u3002// \u63A8\u8350\u7528\u6CD5
+modulePrefs("specify_file_name").putString("test_name", "saved_value")
+// \u4E5F\u53EF\u4EE5\u8FD9\u6837\u7528
+modulePrefs.name("specify_file_name").putString("test_name", "saved_value")
+
// \u63A8\u8350\u7528\u6CD5
+val testName = prefs("specify_file_name").getString("test_name", "default_value")
+// \u4E5F\u53EF\u4EE5\u8FD9\u6837\u7528
+val testName = prefs.name("specify_file_name").getString("test_name", "default_value")
+
PrefsData
\u6765\u521B\u5EFA\u6A21\u677F\u3002 \u5728 PreferenceFragment \u4E2D\u4F7F\u7528
PreferenceFragment
\u4E2D\u88C5\u8F7D YukiHookModulePrefs
\u7684\u573A\u666F\u3002PreferenceFragmentCompat
\uFF0C\u4F60\u73B0\u5728\u53EF\u4EE5\u5C06\u5176\u7EE7\u627F\u7C7B\u5F00\u59CB\u8FC1\u79FB\u5230 ModulePreferenceFragment
\u3002 Xposed Module Data Storage
SharedPreferences
and XSharedPreferences
.Sp
storage.Xposed
provides us with a XSharedPreferences
for reading the Sp
data of the Module App. Use in Activity
YukiHookModulePrefs
in Activity
is described here.XSharedPreferences(BuildConfig.APPLICATION_ID)
+
YukiHookAPI
to quickly implement this function.Activity
.modulePrefs.putString("test_name", "saved_value")
+
val testName = prefs.getString("test_name", "default_value")
+
YukiHookModulePrefs
.prefs
file.Activity
of the Module App.// Recommended usage
+modulePrefs("specify_file_name").putString("test_name", "saved_value")
+// Can also be used like this
+modulePrefs.name("specify_file_name").putString("test_name", "saved_value")
+
// Recommended usage
+val testName = prefs("specify_file_name").getString("test_name", "default_value")
+// Can also be used like this
+val testName = prefs.name("specify_file_name").getString("test_name", "default_value")
+
PrefsData
to create templates. Use in PreferenceFragment
YukiHookModulePrefs
in PreferenceFragment
is described here.PreferenceFragmentCompat
, you can now start migrating its extends ModulePreferenceFragment
. \u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E
YukiHookAPI
\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E\u65B9\u6CD5\u3002 \u4F9D\u8D56\u914D\u7F6E
YukiHookAPI
\u63D0\u4F9B\u4E86\u4E00\u4E2A\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u3002build.gradle
\u4E2D\u96C6\u6210 com.highcapable.yukihookapi:ksp-xposed
\u4F9D\u8D56\u7684\u6700\u65B0\u7248\u672C\u3002 \u81EA\u5B9A\u4E49\u5904\u7406\u7A0B\u5E8F
YukiHookAPI
\u5C06\u5982\u4F55\u751F\u6210 xposed_init
\u5165\u53E3\u8FDB\u884C\u76F8\u5173\u914D\u7F6E\u3002 InjectYukiHookWithXposed \u6CE8\u89E3
annotation class InjectYukiHookWithXposed(
+ val sourcePath: String,
+ val modulePackageName: String,
+ val entryClassName: String,
+ val isUsingResourcesHook: Boolean
+)
+
@InjectYukiHookWithXposed
\u6CE8\u89E3\u662F\u4E00\u4E2A\u6807\u8BB0\u6A21\u5757 Hook \u5165\u53E3\u7684\u91CD\u8981\u6CE8\u89E3\u3002 sourcePath \u53C2\u6570
sourcePath
\u53C2\u6570\u51B3\u5B9A\u4E86\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u81EA\u52A8\u67E5\u627E\u5E76\u5339\u914D\u4F60\u5F53\u524D\u9879\u76EE\u8DEF\u5F84\u7684\u91CD\u8981\u6807\u8BC6\uFF0C\u6B64\u53C2\u6570\u7684\u5185\u5BB9\u4E3A\u76F8\u5BF9\u8DEF\u5F84\u5339\u914D\uFF0C\u9ED8\u8BA4\u53C2\u6570\u4E3A src/main
\u3002@InjectYukiHookWithXposed(sourcePath = "src/custom")
+
sourcePath
\u4F7F\u7528\u7684\u6587\u4EF6\u8DEF\u5F84\u5206\u9694\u7B26\u5199\u6CD5\u6839\u636E Windows
\u548C Unix
\u5C06\u81EA\u52A8\u8FDB\u884C\u8BC6\u522B\uFF0C\u4F7F\u7528 /
\u6216 \\
\u5747\u53EF\u3002 modulePackageName \u53C2\u6570
modulePackageName
\u662F\u4F60\u5F53\u524D\u9879\u76EE\u7684 applicationId
\uFF0C\u4E5F\u5C31\u662F\u4F60\u7684\u6A21\u5757\u5305\u540D (\u6700\u7EC8\u751F\u6210\u7684\u5E94\u7528\u5305\u540D)\uFF0C\u7559\u7A7A\u6216\u4E0D\u586B\u65F6\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u5C06\u5BF9\u5F53\u524D\u9879\u76EE\u6587\u4EF6\u8FDB\u884C\u5206\u6790\u5E76\u751F\u6210\u3002com.example.demo
\uFF0C\u4EE5\u4E0B\u5B9A\u4E49\u65B9\u5F0F\u4EFB\u9009\u5176\u4E00\u3002BuildConfig.java
\u6587\u4EF6\uFF0C\u5C31\u4E0D\u9700\u8981\u505A\u989D\u5916\u64CD\u4F5C\u3002AndroidManifest.xml
\u793A\u4F8B<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.demo">
+
build.gradle
\u793A\u4F8Bandroid {
+ namespace 'com.example.demo'
+}
+
build.gradle.kts
\u793A\u4F8Bandroid {
+ namespace = "com.example.demo"
+}
+
modulePackageName
\u7684\u53C2\u6570\u3002@InjectYukiHookWithXposed(modulePackageName = "com.example.demo")
+
modulePackageName
\u7684\u53C2\u6570\uFF0C\u4F60\u5C31\u4F1A\u5728\u7F16\u8BD1\u65F6\u6536\u5230\u8B66\u544A\u3002You set the customize module package name to "com.example.demo", please check for yourself if it is correct
+
entryClassName \u53C2\u6570
entryClassName
\u51B3\u5B9A\u4E86\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u5982\u4F55\u751F\u6210 xposed_init
\u4E2D\u7684\u5165\u53E3\u7C7B\u540D\uFF0C\u9ED8\u8BA4\u4F1A\u4F7F\u7528\u4F60\u7684\u5165\u53E3\u7C7B\u5305\u540D\u63D2\u5165 _YukiHookXposedInit
\u540E\u7F00\u8FDB\u884C\u751F\u6210\u3002@InjectYukiHookWithXposed
+class HookEntry: IYukiHookXposedInit
+
class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
+
...hook.HookEntry \u2190 \u4F60\u7684\u5165\u53E3\u7C7B
+...hook.HookEntry_Impl \u2190 \u81EA\u52A8\u751F\u6210\u7684 Impl \u7C7B
+...hook.HookEntry_YukiHookXposedInit \u2190 \u81EA\u52A8\u751F\u6210\u7684 Xposed \u5165\u53E3\u7C7B
+
HookXposedEntry
\u3002@InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
+class HookEntry: IYukiHookXposedInit
+
class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
+
...hook.HookEntry \u2190 \u4F60\u7684\u5165\u53E3\u7C7B
+...hook.HookEntry_Impl \u2190 \u81EA\u52A8\u751F\u6210\u7684 Impl \u7C7B
+...hook.HookXposedEntry \u2190 \u81EA\u52A8\u751F\u6210\u7684 Xposed \u5165\u53E3\u7C7B
+
isUsingResourcesHook \u53C2\u6570
isUsingResourcesHook
\u51B3\u5B9A\u4E86\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u662F\u5426\u751F\u6210\u9488\u5BF9 Resources Hook \u7684\u76F8\u5173\u4EE3\u7801\uFF0C\u6B64\u529F\u80FD\u9ED8\u8BA4\u662F\u542F\u7528\u7684\u3002class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
+ // ...
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
+ // ...
+ }
+
+ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {
+ // ...
+ }
+}
+
isUsingResourcesHook = false
\u6765\u5173\u95ED\u81EA\u52A8\u751F\u6210\u3002@InjectYukiHookWithXposed(isUsingResourcesHook = false)
+
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
+ // ...
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
+ // ...
+ }
+}
+
IYukiHookXposedInit \u63A5\u53E3
IYukiHookXposedInit
\u63A5\u53E3\u4E3A\u4F60\u7684 HookEntryClass
\u5FC5\u987B\u5B9E\u73B0\u7684\u63A5\u53E3\uFF0C\u8FD9\u662F\u4F60\u7684\u6A21\u5757\u5F00\u59CB Hook \u7684\u8D77\u70B9\u3002onHook
\u65B9\u6CD5\u5C06\u4F1A\u88AB\u56DE\u8C03\uFF0C\u4F60\u9700\u8981\u5728\u6B64\u65B9\u6CD5\u4E2D\u5F00\u59CB\u4F7F\u7528 YukiHookAPI
\u3002_YukiHookXposedInit
\u2192 IYukiHookXposedInit.onXposedEvent
\u2192 IYukiHookXposedInit.onInit
\u2192 IYukiHookXposedInit.onHook
\u539F\u751F Xposed API \u4E8B\u4EF6
onXposedEvent
\u5B9E\u73B0\u76D1\u542C\u539F\u751F Xposed API \u7684\u5168\u90E8\u88C5\u8F7D\u4E8B\u4EF6\u3002@InjectYukiHookWithXposed
+class HookEntry: IYukiHookXposedInit {
+
+ override fun onHook() {
+ // Your code here.
+ }
+
+ override fun onXposedEvent() {
+ // \u76D1\u542C\u539F\u751F Xposed API \u7684\u88C5\u8F7D\u4E8B\u4EF6
+ YukiXposedEvent.events {
+ onInitZygote {
+ // it \u5BF9\u8C61\u5373 [StartupParam]
+ }
+ onHandleLoadPackage {
+ // it \u5BF9\u8C61\u5373 [LoadPackageParam]
+ }
+ onHandleInitPackageResources {
+ // it \u5BF9\u8C61\u5373 [InitPackageResourcesParam]
+ }
+ }
+ }
+}
+
onXposedEvent
\u4E0E onHook
\u65B9\u6CD5\u5B8C\u5168\u72EC\u7ACB\u5B58\u5728\uFF0C\u4E92\u4E0D\u5F71\u54CD\uFF0C\u4F60\u53EF\u4EE5\u7EE7\u7EED\u5728 onHook
\u65B9\u6CD5\u4E2D\u4F7F\u7528 YukiHookAPI
\u3002 Use as Xposed Module Configs
YukiHookAPI
as an Xposed Module. Dependency Configs
YukiHookAPI
provides an automatic builder.com.highcapable.yukihookapi:ksp-xposed
dependency in your build.gradle
. Custom Automatic Builder
YukiHookAPI
will generate the xposed_init
entry point. InjectYukiHookWithXposed Annotation
annotation class InjectYukiHookWithXposed(
+ val sourcePath: String,
+ val modulePackageName: String,
+ val entryClassName: String,
+ val isUsingResourcesHook: Boolean
+)
+
@InjectYukiHookWithXposed
annotation is an important annotation to mark the entry point of a Module App's Hook. sourcePath Parameter
sourcePath
parameter determines the important identifier for the automatic builder to automatically find and match your current project path.src/main
.@InjectYukiHookWithXposed(sourcePath = "src/custom")
+
sourcePath
will be automatically recognized according to Windows
and Unix
, either /
or \\
can be used. modulePackageName Parameter
modulePackageName
is the applicationId
of your current project, which is your module package name (the final generated application package name).com.example.demo
, any one of the following definitions.BuildConfig.java
file normally, no additional operations are required.AndroidManifest.xml
example<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.demo">
+
build.gradle
exampleandroid {
+ namespace 'com.example.demo'
+}
+
build.gradle.kts
exampleandroid {
+ namespace = "com.example.demo"
+}
+
modulePackageName
parameter.@InjectYukiHookWithXposed(modulePackageName = "com.example.demo")
+
modulePackageName
parameter, you will get a warning at compile time.You set the customize module package name to "com.example.demo", please check for yourself if it is correct
+
entryClassName Parameter
entryClassName
determines how the automatic builder generates the entry class name in xposed_init
._YukiHookXposedInit
suffix for generation.@InjectYukiHookWithXposed
+class HookEntry: IYukiHookXposedInit
+
class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
+
...hook.HookEntry \u2190 Your entry class
+...hook.HookEntry_Impl \u2190 Auto-generated Impl class
+...hook.HookEntry_YukiHookXposedInit \u2190 Automatically generated Xposed entry class
+
HookXposedEntry
.@InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
+class HookEntry: IYukiHookXposedInit
+
class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
+
...hook.HookEntry \u2190 Your entry class
+...hook.HookEntry_Impl \u2190 Auto-generated Impl class
+...hook.HookXposedEntry \u2190 Automatically generated Xposed entry class
+
isUsingResourcesHook Parameter
isUsingResourcesHook
determines whether the automatic builder generates relevant code for the Resources Hook, this feature is enabled by default.class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
+ // ...
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
+ // ...
+ }
+
+ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {
+ // ...
+ }
+}
+
isUsingResourcesHook = false
to disable automatic generation.@InjectYukiHookWithXposed(isUsingResourcesHook = false)
+
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
+ // ...
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
+ // ...
+ }
+}
+
IYukiHookXposedInit Interface
IYukiHookXposedInit
interface that your HookEntryClass
must implements it, which is the entry point for your Module App to start hooking.onHook
method will be called back, you need to start using YukiHookAPI
in this method._YukiHookXposedInit
\u2192 IYukiHookXposedInit.onXposedEvent
\u2192 IYukiHookXposedInit.onInit
\u2192 IYukiHookXposedInit.onHook
Native Xposed API Events
onXposedEvent
to monitor all loading events of the native Xposed API.@InjectYukiHookWithXposed
+class HookEntry: IYukiHookXposedInit {
+
+ override fun onHook() {
+ // Your code here.
+ }
+
+ override fun onXposedEvent() {
+ // Listen to the loading events of the native Xposed API
+ YukiXposedEvent.events {
+ onInitZygote {
+ // The it object is [StartupParam]
+ }
+ onHandleLoadPackage {
+ // The it object is [LoadPackageParam]
+ }
+ onHandleInitPackageResources {
+ // The it object is [InitPackageResourcesParam]
+ }
+ }
+ }
+}
+
onXposedEvent
and onHook
methods exist completely independently and do not affect each other. You can continue to use YukiHookAPI
in the onHook
method. YukiHookAPI \u6784\u5EFA\u5DE5\u5177
YukiHookAPI
\u4F5C\u4E3A\u6838\u5FC3\u7684 Xposed \u6A21\u5757\u81EA\u52A8\u6784\u5EFA\u5DE5\u5177\u3002 \u83B7\u53D6\u9879\u76EE
\u4F7F\u7528\u65B9\u6CD5
\u57FA\u672C\u7528\u6CD5
\u914D\u7F6E\u6A21\u677F
\u591A\u8BED\u8A00\u652F\u6301
YukiHookAPI Project Builder
YukiHookAPI
as the core. Get Project
Usage
Basic Usage
Config Template
Multilingual Support
Yuki Hook API
About this Document
License
MIT License
+
+Copyright (C) 2019-2022 HighCapable
+
+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.
+
Yuki Hook API
Changelog
YukiHookAPI
is recorded here.latest
1.1.0 | 2022.09.28 XposedHelper
is misspelled and changed to XposedHelpers
Class
and Method
of Hook App Demo to Java to provide better demo effectHookParamWrapper
, it now interfaces directly with YukiBridgeFactory
YukiHookBridge
to AppParasitics
HookParam.args
and the underlying direct connection method setArgs
, directly get and set the object of the current arrayjar
into stub
projectCreater
naming to Creator
for all reflection and Hook classesYukiHookAPI.Status.compiledTimestamp
function, which can get the compilation completion timestamp when used as an Xposed moduleYukiHookAPI.Status.isXposedEnvironment
function, which can determine whether the current (Xposed) host environment or module environment isYukiHookAPI.Configs.debugTag
have been merged into YukiHookLogger.Configs
XposedBridge.log
or Logd
debugLog
configurationgeneric
function to reflect and call generics, you can use it in Class
or CurrentClass
buildOfAny
method, now use the buildOf
method directly (without generics) to use the constructor to create a new object and get the result Any
hasExtends
CurrentClass
added non-lambda
method of callingCurrentClass
adds name
and simpleName
functionsReflectionTool
, sorting and classifying different search conditionsMember
obtained by directly calling declared
in ReflectionTool
throws an exceptionUndefinedType
in ReflectionTool
is not correctly judged in Method
and Constructor
conditionsMember
cannot be found under specified conditionsVagueType
condition in Method
and Constructor
for reflection search, which can be used in param
condition to ignore parameters you don't want to fill inparamCount { ... }
condition in Method
and Constructor
of reflection search, now you can directly get it
in it to customize your judgment conditioncurrent
method is added to the FieldFinder
result, which can directly create a call space for the result instancemodifiers
condition and name
condition in the reflection lookup function, now you need to return a Boolean
at the end of the method body to make the condition trueas*
function in ModifierRules
renamed to is*
, thanks to Kitsune suggestionRemedyPlan
feature in FieldFinder
Class
fuzzy search function (Beta) in Dex
, you can now directly use searchClass
function to fuzzy search Class
with specified conditionsappClassLoader
is incorrect in system applications in some systems, thanks to Luckyzyx for the feedbackXposedBridge.invokeOriginalMethod
and added original
function in MethodFinder.Result.Instance
getStringSet
method in YukiHookModulePrefs
and optimize the code style, thanks to Teddy_Zhu PRYukiHookModulePrefs
to intercept exceptions that may not exist in XSharePreference
YukiHookDataChannel
could not be successfully registered in some third-party ROM system frameworksYukiHookDataChannel
, now it can only communicate between modules from the specified package name and the hostSharedPreferences
to fix the problem that file permissions are not 0664
in some systems, thanks to 5ec1cff for the feedback and implementation code providedYukiHookAPI.Configs.isEnableHookSharedPreferences
function, which is disabled by default and can be enabled if the permission of SharedPreferences
is incorrectConstructor
without filling in the search conditions, thanks B5 KAKA for the feedbackResult
instances located in method
, constructor
in injectMember
to Process
useDangerousOperation
method in the Hook process, which will automatically stop the Hook and print an error after the function in the Hook Dangerous List is not declaredActivity
proxy functions, you can call injectModuleAppResources
and registerModuleAppActivities
to useModuleContextThemeWrapper
function, you can call applyModuleTheme
to create the Context
of a module in any Activity
ClassLoader.onLoadClass
function, which can be used to listen for events when the loadClass
method of ClassLoader
is calledclassOf
and clazz
extension methods, add toClass
and toClassOrNull
usage, please move to the new method nowVariousClass
adds a getOrNull
method, which can return null
instead of throwing an exception when it can't match Class
isUseAppClassLoader
parameter in PackageParam.hook
, changed it to isForceUseAbsolute
and automatically matched the target Class
PackageParam
adds systemContext
function, you can call this function at any time to get a persistent Context
HookClass
throwToApp
function in HookParam
, which can throw exceptions directly to the hostonFailureThrowToApp
function is added to the Hook callback, which can be directly thrown to the host when an exception occursremove
and removeSelf
methods to remove the hookarray
type to Resources Hook, thanks to PR of GSWXXNme.weishu.reflection
to thirdparty
to prevent conflicting dependencies of the same name introduced at the same timeAppLifecycle
and throw it directly to the host when an exception occursstale
1.0.92 | 2022.05.31 YukiHookDataChannel
cannot call back the current Activity
broadcast on devices lower than Android 12InjectYukiHookWithXposed
annotation adds the isUsingResourcesHook
function, now you can selectively disable the dependency interface that automatically generates IXposedHookInitPackageResources
outdate
1.0.91 | 2022.05.29 ClassLoader
error when the customized system of some devices is booted in the LSPosed environment, thanks to Luckyzyx for the feedbackYukiHookDataChannel
not being able to call back the current Activity
broadcast on ZUI and systems below Android 12YukiHookModuleStatus
function into YukiHookAPI.Status
, rewrite a lot of methods, now you can judge the status information such as module activation in the module and the host in both directionsoutdate
1.0.90 | 2022.05.27 YukiHookDataChannel
crashing when the module sets the listener callbackYukiHookDataChannel
still calling back when not in current Activity
YukiHookDataChannel
callback event, no callbackYukiHookModulePrefs
warning printed if XShare is unreadableisXSharePrefsReadable
method in YukiHookModulePrefs
to determine whether the current XShare is availableoutdate
1.0.89 | 2022.05.26 YukiHookDataChannel
cannot be repeatedly set to monitor, and added the function of repeating response in different Activity
modules and automatically following Activity
to destroy the monitor functionYukiHookDataChannel
repeated listening use case description documentonAlreadyHooked
method to determine whether the current method is repeated HookputIfAbsent
method, allow to override the additionoutdate
1.0.88 | 2022.05.25 android
type in type
YukiHookModuleStatus
from auto-generated code and add isEnableHookModuleStatus
switch, it is up to you to enable or notYukiHookModulePrefs
to run as a singleton to prevent repeated creation and waste of system resources1.0.80
, and optimize the related functions of nested HookHookParam
methodMethodFinder
and FieldFinder
add the function of finding fuzzy methods and variable names, you can call name { ... }
to set search conditions, and support regular expressionsappContext
to reduce the possibility of getting emptyTAG
of logger
in the automatically generated code to default to your custom name, which is convenient for debuggingHooker
implementation of YukiHookBridge
to improve Hook performancePackageParam
adds the onAppLifecycle
method, which can natively monitor the life cycle of the host and implement the registration system broadcast functionYukiHookDataChannel
function to communicate using system out-of-order broadcast while the module and the host remain aliveYukiHookDataChannel
adds the checkingVersionEquals
method, which can be monitored to verify that the host has not updated the version mismatch problem after the module is updateddemo-module
for reference onlyoutdate
1.0.87 | 2022.05.10 refreshModuleAppResources
function to adapt Resources refresh when the language region, font size, resolution changes, etc.isEnableModuleAppResourcesCache
function, you can set whether to automatically cache the resources of the current moduleoutdate
1.0.86 | 2022.05.06 initZygote
when Resources Hook is not supported, reproduced in ZUI/LSPosed CI(1.8.3-6550)outdate
1.0.85 | 2022.05.04 1.0.80
initZygote
as android-zygote
, packageName
keeps android
unchangedoutdate
1.0.83 | 2022.05.04 YukiHookModuleStatus
reporting a lot of errors after loadSystem
android
type in type
outdate
1.0.82 | 2022.05.04 initZygote
and the system framework, there are problems with the previous comments and documentation, I am very sorryPackageParam
adds loadSystem
method, no need to write loadApp(name = "android")
to hook the system frameworkoutdate
1.0.81 | 2022.05.04 by
methodoutdate
1.0.80 | 2022.05.01 InjectYukiHookWithXposed
annotation adds the entryClassName
function, which can customize the generated xposed_init
entry class name renamed to YukiHookXposedInitProxy
IYukiHookXposedInit
, the original interface name has been invalidated and will be deleted directly in subsequent versionsinitZygote
and Resources Hook functions to support Hook LayoutonXposedEvent
method to listen to all events of native Xposed APIinline
processing on the lambda
of the Hook function to avoid generating excessively broken anonymous classes and improve the running performance after compilationPrefsData
compiled method body copy is too largeXSharePreference
readability test, which will automatically print a warning log if it failsPackageParam
adds appResources
, moduleAppResources
, moduleAppFilePath
functionsloadApp
of PackageParam
adds the function of not writing name
, and all APPs are filtered by defaultPackageParam
adds the loadZygote
method, which can directly hook the system frameworkPackageParam
added resources().hook
functionhasExtends
extension method to determine whether the current Class
has an inheritance relationshipisSupportResourcesHook
function to determine whether resource hooks are currently supported (Resources Hook)current
function adds superClass
method to call superclasssuperClass
query conditions for search methods, construction methods and variables, you can continue to search in the parent classYukiHookAPI
lots of methods are decoupled from Xposed APIisFirstApplication
may be inaccurateClassLoader
causes Hook to freeze, thanks to WankkoRee for the feedbackXC_Callback
interface is connectedtype
added ClassLoader
typeoutdate
1.0.78 | 2022.04.18 YukiHookModulePrefs
adds isRunInNewXShareMode
method, which can be used to determine whether the module is currently in New XSharePreference
modeYukiHookModulePrefs
working in New XSharePreference
modeModulePreferenceFragment
, now you can completely replace PreferenceFragmentCompat
and start using the new functionalityPreferenceFragmentCompat
, thanks to mahoshojoHCG for feedbackKotlin
dependencies to the latest versionoutdate
1.0.77 | 2022.04.15 YukiHookModulePrefs
added clear
method, thanks to WankkoRee for the suggestionYukiHookModulePrefs
added getStringSet
, putStringSet
, all
methodsany
method to args
of HookParam
ModuleApplication
, which can be inherited in modules to achieve more functionsfindClass
functions to the Xposed API, and continue to use native ClassLoader
in non-hosted environmentsoutdate
1.0.75 | 2022.04.13 firstArgs
and lastArgs
methods have been removed from HookParam
, now you can use args().first()
and args().last()
instead of itindex = 0
in args()
in HookParam
, now you can use args().first()
or args(index = 0)
to replace itresult
function in HookParam
adds generic matching, now you can use result<T>
to match the known return value type of your target methodemptyParam
condition is added to the method and constructor query function, and the misunderstanding of the query condition that needs to be paid attention to in the document has been improvedandroid
type in type
outdate
1.0.73 | 2022.04.10 XC_LoadPackage.LoadPackageParam
throws an exception when the content is empty in some cases, thanks to Luckyzyx for the feedbackoutdate
1.0.72 | 2022.04.09 appContext
function to PackageParam
outdate
1.0.71 | 2022.04.04 outdate
1.0.70 | 2022.04.04 instanceClass
reporting an error after being called in a static instanceisUseAppClassLoader
function in Hook process, thanks to WankkoRee for feedbackwithProcess
function, which can be hooked according to the currently specified process of the APPallMethods
not throwing an exception when it is not hooked to a method, thanks to WankkoRee for the feedbackindex
to locate the specified method and variable, thanks to WankkoRee for the ideas providedString
and VariousClass
current
function, which can build a reflection method operation space for any class, and easily call and modify the methods and variables in itoutdate
1.0.69 | 2022.03.30 allMethods
is used multiple times in a Hook instance, thanks to WankkoRee for the feedbackoutdate
1.0.68 | 2022.03.29 Member
lookup cache and lookup cache configuration switchesMethodFinder
, FieldFinder
and HookParam
related method callscast
types in Finder
and support cast
as arrayoutdate
1.0.67 | 2022.03.27 modifiers
functions in Finder
, which can filter static
, native
, public
, abstract
and many other description typeshasModifiers
extension for Member
give
method in MethodFinder
and ConstructorFinder
to get primitive typesPrefsData
template function in YukiHookModulePrefs
outdate
1.0.66 | 2022.03.25 MethodFinder
args
call method in hookParam
outdate
1.0.65 | 2022.03.25 MethodFinder
and FieldFinder
new return value calling methodsandroid
type and java
type in type
outdate
1.0.6 | 2022.03.20 YukiHookModulePrefs
being ignored every time after using direct
once to ignore cacheisActive
to judge module activationField
ReflectionUtils
YukiHookModuleStatus
method name confusion to reduce the size of module generationoutdate
1.0.55 | 2022.03.18 android
types in type
and a small number of java
typesoutdate
1.0.5 | 2022.03.18 onInit
method to configure YukiHookAPI
executorName
and executorVersion
to get the name and version number of the current hook frameworkby
method to set the timing and condition of HookYukiHookModulePrefs
adds a controllable key-value cache, which can dynamically update data when the host is runningoutdate
1.0.4 | 2022.03.06 XposedBridge
after enabling "Only module classloader can use Xposed API" option in latest versionYukiHookAPI
hasField
method and isAllowPrintingLogs
configuration parameterisDebug
to enable the API to automatically print the welcome message to test whether the module is validoutdate
1.0.3 | 2022.03.02 ignoredError
functionandroid
type in type
ClassNotFound
function after listening to hook
outdate
1.0.2 | 2022.02.18 BaseFinder
for integrationoutdate
1.0.1 | 2022.02.15 RemedyPlan
adds onFind
functionjava
type in type
outdate
1.0 | 2022.02.14 Yuki Hook API
Contact Us
Help with Maintenance
YukiHookAPI
.Yuki Hook API
Looking for Future
YukiHookAPI
. Unresolved Issues
YukiHookAPI
. YukiHookModulePrefs
selinux
is a big problem currently facing, which needs to be discussed and studied. Future Plans
YukiHookAPI
may add later are included here. Lite Version Supported for Standalone Use
Support for More Hook Framework
XposedBridge
as a compatibility layer still has certain limitations.inline hook
do not have a Java
compatibility layer, and the Java
compatibility layer adaptation of native hook
may be considered later.Yuki Hook API
Document Introduce
YukiHookAPI
as the latest version to use the latest version of the function. Function Description
Function Example Description
Change Record Description
v<version>
first
;v<version>
added
;v<version>
modified
;v<version>
deprecated
and strikethrough;v<version>
removed
and strikethrough. Related Symbols Description
get
/ set
method or read-only get
methodYuki Hook API
- object
YukiHookAPI object YukiHookAPI
+
v1.0
first
YukiHookAPI
的 API 调用总类,Hook 相关功能的开始、Hook 相关功能的配置都在这里。- field
API_VERSION_NAME const val API_VERSION_NAME: String
+
v1.0.4
added
YukiHookAPI
的版本。- field
API_VERSION_CODE const val API_VERSION_CODE: Int
+
v1.0.4
added
YukiHookAPI
的版本号。executorName - field
v1.0.5
added
v1.0.91
removed
Status.executorName
executorVersion - field
v1.0.5
added
v1.0.91
removed
Status.executorVersion
- object
Status object Status
+
v1.0.91
added
YukiHookAPI
的状态。- field
compiledTimestamp val compiledTimestamp: Long
+
v1.1.0
added
- field
isXposedEnvironment val isXposedEnvironment: Boolean
+
v1.1.0
added
- field
executorName val executorName: String
+
v1.0.91
added
unknown
,XposedBridge
不存在会返回 invalid
。- field
executorVersion val executorVersion: Int
+
v1.0.91
added
-1
。- field
isModuleActive val isModuleActive: Boolean
+
v1.0.91
added
- field
isXposedModuleActive val isXposedModuleActive: Boolean
+
v1.0.91
added
- field
isTaiChiModuleActive val isTaiChiModuleActive: Boolean
+
v1.0.91
added
- field
isSupportResourcesHook val isSupportResourcesHook: Boolean
+
v1.0.91
added
- object
Configs object Configs
+
v1.0
first
- method
debugLog inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit)
+
v1.1.0
added
YukiHookLogger.Configs
相关参数。debugTag - field
v1.0
first
v1.1.0
deprecated
YukiHookLogger.Configs.tag
- field
isDebug var isDebug: Boolean
+
v1.0
first
Logcat
和 XposedBridge.log
打印详细的 Hook 日志,关闭后仅会打印 E
级别的日志。isAllowPrintingLogs - field
v1.0.4
added
v1.1.0
deprecated
YukiHookLogger.Configs.isEnable
- field
isEnableModulePrefsCache var isEnableModulePrefsCache: Boolean
+
v1.0.5
added
YukiHookModulePrefs
的键值缓存功能。YukiHookModulePrefs
中自由开启和关闭缓存功能以及清除缓存。- field
isEnableModuleAppResourcesCache var isEnableModuleAppResourcesCache: Boolean
+
v1.0.87
added
Resources
缓存功能。PackageParam.refreshModuleAppResources
来刷新缓存。- field
isEnableHookModuleStatus var isEnableHookModuleStatus: Boolean
+
v1.0.88
added
- field
isEnableHookSharedPreferences var isEnableHookSharedPreferences: Boolean
+
v1.1.0
added
SharedPreferences
。SharedPreferences
文件权限调整为 Context.MODE_WORLD_READABLE
(0664)。- field
isEnableDataChannel var isEnableDataChannel: Boolean
+
v1.0.88
added
YukiHookDataChannel
功能。Application
继承于 ModuleApplication
才能有效。YukiHookDataChannel
。- field
isEnableMemberCache var isEnableMemberCache: Boolean
+
v1.0.68
added
v1.0.80
modified
Member
缓存功能。Member
复用过高造成的系统 GC 问题,此功能默认启用。Method
、Constructor
、Field
。Member
都将处于 MemberCacheStore
的全局静态实例中。MethodFinder
、ConstructorFinder
、FieldFinder
来获取 Member
。Member
发生了混淆的问题,例如使用 R8 混淆后的 APP 的目标 Member
,否则建议启用。- method
configs inline fun configs(initiate: Configs.() -> Unit)
+
v1.0
first
Configs
类实现了一个 lambda
方法体。HookEntryClass
的 onInit
方法中调用 configs
方法和 debugLog
方法完成对 API 的功能配置,实时生效。class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() {
+ YukiHookAPI.configs {
+ debugLog {
+ tag = "YukiHookAPI"
+ isEnable = true
+ isRecord = false
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ isDebug = BuildConfig.DEBUG
+ isEnableModulePrefsCache = true
+ isEnableModuleAppResourcesCache = true
+ isEnableHookModuleStatus = true
+ isEnableHookSharedPreferences = false
+ isEnableDataChannel = true
+ isEnableMemberCache = true
+ }
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() = configs {
+ debugLog {
+ tag = "YukiHookAPI"
+ isEnable = true
+ isRecord = false
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ isDebug = BuildConfig.DEBUG
+ isEnableModulePrefsCache = true
+ isEnableModuleAppResourcesCache = true
+ isEnableHookModuleStatus = true
+ isEnableHookSharedPreferences = false
+ isEnableDataChannel = true
+ isEnableMemberCache = true
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
configs
和 debugLog
方法,直接进行配置。class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() {
+ YukiHookLogger.Configs.tag = "YukiHookAPI"
+ YukiHookLogger.Configs.isEnable = true
+ YukiHookLogger.Configs.isRecord = false
+ YukiHookLogger.Configs.elements(
+ YukiHookLogger.Configs.TAG,
+ YukiHookLogger.Configs.PRIORITY,
+ YukiHookLogger.Configs.PACKAGE_NAME,
+ YukiHookLogger.Configs.USER_ID
+ )
+ YukiHookAPI.Configs.isDebug = BuildConfig.DEBUG
+ YukiHookAPI.Configs.isEnableModulePrefsCache = true
+ YukiHookAPI.Configs.isEnableModuleAppResourcesCache = true
+ YukiHookAPI.Configs.isEnableHookModuleStatus = true
+ YukiHookAPI.Configs.isEnableHookSharedPreferences = false
+ YukiHookAPI.Configs.isEnableDataChannel = true
+ YukiHookAPI.Configs.isEnableMemberCache = true
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
- method
encase fun encase(initiate: PackageParam.() -> Unit)
+
fun encase(vararg hooker: YukiBaseHooker)
+
fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
+
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
+
v1.0
first
Yuki Hook API
- annotation
InjectYukiHookWithXposed annotation class InjectYukiHookWithXposed(
+ val sourcePath: String,
+ val modulePackageName: String,
+ val entryClassName: String,
+ val isUsingResourcesHook: Boolean
+)
+
v1.0
first
v1.0.80
modified
entryClassName
参数v1.0.92
modified
isUsingResourcesHook
参数YukiHookAPI
注入 Xposed 入口的类注解。Yuki Hook API
- class
CurrentClass class CurrentClass internal constructor(internal val classSet: Class<*>, internal val instance: Any)
+
v1.0.70
added
v1.1.0
modified
- field
name val name: String
+
v1.1.0
added
classSet
的 Class.getName
。- field
simpleName val simpleName: String
+
v1.1.0
added
classSet
的 Class.getSimpleName
。- method
generic fun generic(): GenericClass?
+
v1.1.0
added
null
。- method
generic inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
v1.1.0
added
null
。- method
superClass fun superClass(): SuperClass
+
v1.0.80
added
- method
field inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
v1.0.70
added
- method
method inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
v1.0.70
added
- class
SuperClass inner class SuperClass internal constructor(internal val superClassSet: Class<*>)
+
v1.0.80
added
v1.1.0
modified
superClassSet
参数- field
name val name: String
+
v1.1.0
added
classSet
中父类的 Class.getName
。- field
simpleName val simpleName: String
+
v1.1.0
added
classSet
中父类的 Class.getSimpleName
。- method
generic fun generic(): GenericClass?
+
v1.1.0
added
null
。- method
generic inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
v1.1.0
added
null
。- method
field inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
v1.0.80
added
- method
method inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
v1.0.80
added
Yuki Hook API
- class
GenericClass class GenericClass internal constructor(private val type: ParameterizedType)
+
v1.1.0
added
Class
的泛型父类操作对象。- method
argument fun argument(index: Int): Class<*>
+
v1.1.0
added
Class
实例。Yuki Hook API
- class
HookClass class HookClass internal constructor(internal var instance: Class<*>?, internal var name: String, internal var throwable: Throwable?)
+
v1.0
first
v1.1.0
modified
HookClass
相关功能不再对外开放Class
接管类。instance
为实例,name
为实例完整包名,throwable
为找不到实例的时候抛出的异常。Yuki Hook API
- class
HookResources class HookResources internal constructor(var instance: YukiResources?)
+
v1.0.80
added
YukiResources
接管类。Yuki Hook API
- class
VariousClass class VariousClass(vararg var name: String)
+
v1.0
first
Class
类名装载器,通过 name
装载 Class
名称数组。- method
get fun get(loader: ClassLoader? = null): Class<*>
+
v1.0.70
added
loader
装载目标 Class
。- method
getOrNull fun getOrNull(loader: ClassLoader? = null): Class<*>?
+
v1.1.0
added
loader
装载目标 Class
。Class
会返回 null
,不会抛出异常。Yuki Hook API
- class
YukiMemberHookCreator class YukiMemberHookCreator(internal val packageParam: PackageParam, internal val hookClass: HookClass)
+
v1.0
first
v1.0.80
modified
hookClass
进行 inline 处理v1.1.0
modified
YukiHookAPI
的 Member
核心 Hook 实现类。- field
PRIORITY_DEFAULT val PRIORITY_DEFAULT: Int
+
v1.0.80
added
- field
PRIORITY_LOWEST val PRIORITY_LOWEST: Int
+
v1.0.80
added
- field
PRIORITY_HIGHEST val PRIORITY_HIGHEST: Int
+
v1.0.80
added
- field
instanceClass val instanceClass: Class<*>
+
v1.0
first
v1.0.2
modified
更名为 thisClass
instanceClass
Class
。- method
injectMember inline fun injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
+
v1.0
first
v1.0.80
modified
priority
Hook 优先级Method
、Constructor
。Method
与 Constructor
,使用 injectMember
即可创建一个 Hook
对象。injectMember {
+ // Your code here.
+}
+
tag
,方便你在调试的时候能够区分你的 Hook
对象。injectMember(tag = "KuriharaYuki") {
+ // Your code here.
+}
+
priority
,以控制当前 Hook 对象并列执行的优先级速度。injectMember(priority = PRIORITY_HIGHEST) {
+ // Your code here.
+}
+
- method
useDangerousOperation fun useDangerousOperation(option: String)
+
v1.1.0
added
option
中键入 Yes do as I say!
代表你同意允许所有危险行为。CauseProblemsApi
以消除警告。ClassLoader
的 loadClass
方法,请参考 ClassLoader.onLoadClass。- class
MemberHookCreator inner class MemberHookCreator internal constructor(private val priority: Int, internal val tag: String)
+
v1.0
first
v1.0.80
modified
priority
Hook 优先级v1.0.81
modified
packageName
当前 Hook 的 APP 包名v1.1.0
modified
packageName
Method
、Constructor
。member - field
v1.0
first
v1.1.0
removed
members
- method
members fun members(vararg member: Member?)
+
v1.1.0
added
Method
、Constructor
。instanceClass
来手动查找要 Hook 的 Method
、Constructor
。injectMember {
+ members(instanceClass.getDeclaredMethod("test", StringType))
+ beforeHook {}
+ afterHook {}
+}
+
Member
同时进行 Hook。injectMember {
+ members(
+ instanceClass.getDeclaredMethod("test1", StringType),
+ instanceClass.getDeclaredMethod("test2", StringType),
+ instanceClass.getDeclaredMethod("test3", StringType)
+ )
+ beforeHook {}
+ afterHook {}
+}
+
allMethods - method
v1.0
first
v1.1.0
deprecated
method { name = /** name */ }.all()
来取代它allConstructors - method
v1.0
first
v1.1.0
deprecated
allMembers(MembersType.CONSTRUCTOR)
来取代它- method
allMembers fun allMembers(type: MembersType)
+
v1.1.0
added
hookClass
中的全部 Method
、Constructor
。- method
method inline fun method(initiate: MethodConditions): MethodFinder.Result
+
v1.0
first
v1.0.80
modified
Class
需要 Hook 的 Method
。injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = UnitType
+ }
+ beforeHook {}
+ afterHook {}
+}
+
method { ... }
条件的全部结果,你只需要在最后加入 all
即可。injectMember {
+ method {
+ name = "test"
+ paramCount(1..5)
+ }.all()
+ beforeHook {}
+ afterHook {}
+}
+
beforeHook
与 afterHook
会在每个查找到的结果中多次回调 Hook 方法体。- method
constructor inline fun constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
v1.0
first
v1.0.80
modified
Class
需要 Hook 的 Constructor
。injectMember {
+ constructor { param(StringType) }
+ beforeHook {}
+ afterHook {}
+}
+
constructor { ... }
条件的全部结果,你只需要在最后加入 all
即可。injectMember {
+ constructor { paramCount(1..5) }.all()
+ beforeHook {}
+ afterHook {}
+}
+
beforeHook
与 afterHook
会在每个查找到的结果中多次回调 Hook 方法体。- i-ext-method
HookParam.field inline fun HookParam.field(initiate: FieldConditions): FieldFinder.Result
+
v1.0
first
v1.0.80
modified
hookClass
查找并得到 Field
。injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = UnitType
+ }
+ afterHook {
+ // 这里不需要再调用 instanceClass.field 进行查找
+ field {
+ name = "isSweet"
+ type = BooleanType
+ }.get(instance).setTrue()
+ }
+}
+
- i-ext-method
HookParam.method inline fun HookParam.method(initiate: MethodConditions): MethodFinder.Result
+
v1.0.2
first
v1.0.80
modified
hookClass
查找并得到 Method
。- i-ext-method
HookParam.constructor inline fun HookParam.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
v1.0.2
first
v1.0.80
modified
hookClass
查找并得到 Constructor
。- i-ext-method
HookParam.injectMember inline fun HookParam.injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
+
v1.0.88
added
Method
、Constructor
(嵌套 Hook)。- method
beforeHook fun beforeHook(initiate: HookParam.() -> Unit): HookCallback
+
v1.0
first
v1.1.0
modified
HookCallback
返回类型Member
执行完成前 Hook。- method
afterHook fun afterHook(initiate: HookParam.() -> Unit): HookCallback
+
v1.0
first
v1.1.0
modified
HookCallback
返回类型Member
执行完成后 Hook。- method
replaceAny fun replaceAny(initiate: HookParam.() -> Any?)
+
v1.0
first
Member
内容,给出返回值。- method
replaceUnit fun replaceUnit(initiate: HookParam.() -> Unit)
+
v1.0
first
Member
内容,没有返回值,可以称为 Void
。- method
replaceTo fun replaceTo(any: Any?)
+
v1.0
first
Member
返回值。- method
replaceToTrue fun replaceToTrue()
+
v1.0
first
Member
返回值为 true
。- method
replaceToFalse fun replaceToFalse()
+
v1.0
first
Member
返回值为 false
。- method
intercept fun intercept()
+
v1.0
first
Member
。Member
执行并返回 null
。- method
removeSelf fun removeSelf(result: (Boolean) -> Unit)
+
v1.1.0
added
Method
、Constructor
(解除 Hook)。- class
HookCallback inner class HookCallback internal constructor()
+
v1.1.0
added
- method
onFailureThrowToApp fun onFailureThrowToApp()
+
v1.1.0
added
- class
Result inner class Result internal constructor()
+
v1.0
first
- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0
first
v1.0.5
modified
修改为 failures
result
v1.0.80
modified
Result
类创建 lambda
方法体。injectMember {
+ // Your code here.
+}.result {
+ onHooked {}
+ onAlreadyHooked {}
+ ignoredConductFailure()
+ onHookingFailure {}
+ // ...
+}
+
- method
by inline fun by(condition: () -> Boolean): Result
+
v1.0.5
added
v1.0.80
modified
- method
onHooked fun onHooked(result: (Member) -> Unit): Result
+
v1.0.70
added
members
Hook 成功的回调方法。onAlreadyHooked
。- method
onAlreadyHooked fun onAlreadyHooked(result: (Member) -> Unit): Result
+
v1.0.89
added
members
重复 Hook 的回调方法。- method
onNoSuchMemberFailure fun onNoSuchMemberFailure(result: (Throwable) -> Unit): Result
+
v1.0.5
added
members
不存在发生错误的回调方法。- method
onConductFailure fun onConductFailure(result: (HookParam, Throwable) -> Unit): Result
+
v1.0
first
- method
onHookingFailure fun onHookingFailure(result: (Throwable) -> Unit): Result
+
v1.0
first
- method
onAllFailure fun onAllFailure(result: (Throwable) -> Unit): Result
+
v1.0
first
- method
ignoredNoSuchMemberFailure fun ignoredNoSuchMemberFailure(): Result
+
v1.0.5
added
members
不存在发生的错误。- method
ignoredConductFailure fun ignoredConductFailure(): Result
+
v1.0
first
- method
ignoredHookingFailure fun ignoredHookingFailure(): Result
+
v1.0
first
- method
ignoredAllFailure fun ignoredAllFailure(): Result
+
v1.0
first
- method
remove fun remove(result: (Boolean) -> Unit)
+
v1.1.0
added
Method
、Constructor
(解除 Hook)。- class
Result inner class Result internal constructor()
+
v1.0.3
added
- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0.3
added
v1.0.5
modified
修改为 failures
result
v1.0.80
modified
- method
by inline fun by(condition: () -> Boolean): Result
+
v1.0.5
added
v1.0.80
modified
- method
onPrepareHook fun onPrepareHook(callback: () -> Unit): Result
+
v1.0.70
added
hookClass
存在时准备开始 Hook 的操作。- method
onHookClassNotFoundFailure fun onHookClassNotFoundFailure(result: (Throwable) -> Unit): Result
+
v1.0.3
added
hookClass
找不到时发生错误的回调方法。- method
ignoredHookClassNotFoundFailure fun ignoredHookClassNotFoundFailure(): Result
+
v1.0.3
added
hookClass
找不到时出现的错误。Yuki Hook API
- class
YukiResourcesHookCreator class YukiResourcesHookCreator(internal val packageParam: PackageParam, internal val hookResources: HookResources)
+
v1.0.80
added
v1.1.0
modified
YukiHookAPI
的 Resources
核心 Hook 实现类。- method
injectResource inline fun injectResource(tag: String, initiate: ResourceHookCreator.() -> Unit): ResourceHookCreator.Result
+
v1.0.80
added
injectResource
即可创建一个 Hook
对象。injectResource {
+ // Your code here.
+}
+
tag
,方便你在调试的时候能够区分你的 Hook
对象。injectResource(tag = "KuriharaYuki") {
+ // Your code here.
+}
+
- class
ResourcesHookCreator inner class ResourcesHookCreator internal constructor(private val tag: String)
+
v1.0.80
added
v1.1.0
modified
packageName
- field
resourceId var resourceId: Int
+
v1.0.80
added
injectResource {
+ resourceId = 0x7f060001.toInt()
+ replaceTo(...)
+}
+
- method
conditions inline fun conditions(initiate: ConditionFinder.() -> Unit)
+
v1.0.80
added
resourceId
则此方法将不会被使用。injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceTo(...)
+}
+
- method
replaceTo fun replaceTo(any: Any)
+
v1.0.80
added
String
、Drawable
等。injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceTo("replace string")
+}
+
Drawable
,你无需对目标 Resources 实现 fwd
方法或 DrawableLoader
。injectResource {
+ conditions {
+ name = "test_drawable"
+ drawable()
+ }
+ replaceTo(ColorDrawable(Color.RED))
+}
+
- method
replaceToTrue fun replaceToTrue()
+
v1.0.80
added
true
。- method
replaceToFalse fun replaceToFalse()
+
v1.0.80
added
false
。- method
replaceToModuleResource fun replaceToModuleResource(resId: Int)
+
v1.0.80
added
R.string.xxx
、R.mipmap.xxx
、R.drawable.xxx
替换 Hook APP 的 Resources。fwd
方法。injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceToModuleResource(R.string.module_string)
+}
+
xml
创建的 drawable
。injectResource {
+ conditions {
+ name = "test_drawable"
+ drawable()
+ }
+ replaceToModuleResource(R.drawable.module_drawable)
+}
+
- method
injectAsLayout fun injectAsLayout(initiate: YukiResources.LayoutInflatedParam.() -> Unit)
+
v1.0.80
added
View
。injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ findViewByIdentifier<View>(name = "test_view")?.isVisible = false
+ findViewByIdentifier<TextView>(name = "test_text_view")?.text = "Hook this"
+ }
+}
+
currentView
拿到 Context
。injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ Toast.makeText(currentView.context, "Hook this", Toast.LENGTH_SHORT).show()
+ }
+}
+
- class
ConditionFinder inner class ConditionFinder internal constructor()
+
v1.0.80
added
- field
name var name: String
+
v1.0.80
added
- method
anim fun anim()
+
v1.0.80
added
- method
animator fun animator()
+
v1.0.80
added
- method
bool fun bool()
+
v1.0.80
added
- method
color fun color()
+
v1.0.80
added
- method
dimen fun dimen()
+
v1.0.80
added
- method
drawable fun drawable()
+
v1.0.80
added
- method
integer fun integer()
+
v1.0.80
added
- method
layout fun layout()
+
v1.0.80
added
- method
plurals fun plurals()
+
v1.0.80
added
- method
string fun string()
+
v1.0.80
added
- method
xml fun xml()
+
v1.0.80
added
- method
mipmap fun mipmap()
+
v1.0.80
added
- method
array fun array()
+
v1.1.0
added
- class
Result inner class Result internal constructor()
+
v1.0.80
added
- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0.80
added
- method
by inline fun by(condition: () -> Boolean): Result
+
v1.0.80
added
- method
onHookingFailure fun onHookingFailure(result: (Throwable) -> Unit): Result
+
v1.0.80
added
- method
ignoredHookingFailure fun ignoredHookingFailure(): Result
+
v1.0.80
added
Yuki Hook API
- class
BaseFinder abstract class BaseFinder
+
v1.0.70
added
v1.1.0
modified
BaseFinder
中的部分方法与参数到 MemberBaseFinder
Class
与 Member
查找类功能的基本类实现。- class
BaseFinder.IndexTypeCondition inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
+
v1.0.70
added
- method
index fun index(num: Int)
+
v1.0.70
added
index
小于零则为倒序,此时可以使用 IndexTypeConditionSort.reverse
方法实现。IndexTypeConditionSort.first
和 IndexTypeConditionSort.last
设置首位和末位筛选条件。- method
index fun index(): IndexTypeConditionSort
+
v1.0.70
added
- class
IndexTypeConditionSort inner class IndexTypeConditionSort internal constructor()
+
v1.0.70
added
- method
first fun first()
+
v1.0.70
added
- method
last fun last()
+
v1.0.70
added
- method
reverse fun reverse(num: Int)
+
v1.0.70
added
Yuki Hook API
- class
CountRules class CountRules private constructor()
+
v1.1.0
added
Class
、Member
数组 (下标) 个数条件实现类。Class
、Member
进行更加详细的定位。- i-ext-method
Int.isZero fun Int.isZero(): Boolean
+
v1.1.0
added
- i-ext-method
Int.moreThan fun Int.moreThan(count: Int): Boolean
+
v1.1.0
added
count
。- i-ext-method
Int.lessThan fun Int.lessThan(count: Int): Boolean
+
v1.1.0
added
count
。- i-ext-method
Int.inInterval fun Int.inInterval(countRange: IntRange): Boolean
+
v1.1.0
added
countRange
区间 A ≤ this ≤ B。Yuki Hook API
- class
ModifierRules class ModifierRules private constructor()
+
v1.0.67
added
v1.1.0
modified
Class
的描述符判断Class
、Member
描述符条件实现类。Class
、Member
进行更加详细的定位。- i-ext-field
isPublic val isPublic: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
、Member
类型是否包含 public
。- i-ext-field
isPrivate val isPrivate: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
、Member
类型是否包含 private
。- i-ext-field
isProtected val isProtected: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
、Member
类型是否包含 protected
。- i-ext-field
isStatic val isStatic: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
、Member
类型是否包含 static
。Class
、Member
可添加此描述进行确定。- i-ext-field
isFinal val isFinal: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
、Member
类型是否包含 final
。- i-ext-field
isSynchronized val isSynchronized: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
、Member
类型是否包含 synchronized
。- i-ext-field
isVolatile val isVolatile: Boolean
+
v1.0.67
added
v1.1.0
modified
Field
类型是否包含 volatile
。- i-ext-field
isTransient val isTransient: Boolean
+
v1.0.67
added
v1.1.0
modified
Field
类型是否包含 transient
。- i-ext-field
isNative val isNative: Boolean
+
v1.0.67
added
v1.1.0
modified
Method
类型是否包含 native
。Method
可添加此描述进行确定。- i-ext-field
isInterface val isInterface: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
类型是否包含 interface
。- i-ext-field
isAbstract val isAbstract: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
、Member
类型是否包含 abstract
。Class
、Member
可添加此描述进行确定。- i-ext-field
isStrict val isStrict: Boolean
+
v1.0.67
added
v1.1.0
modified
Class
、Member
类型是否包含 strictfp
。Yuki Hook API
- class
NameRules class NameRules private constructor()
+
v1.0.88
added
v1.1.0
modified
NameConditions
更名为 NameRules
Class
、Member
名称条件实现类。Class
、Member
进行更加详细的定位。- i-ext-method
String.isSynthetic fun String.isSynthetic(index: Int): Boolean
+
v1.0.88
added
v1.1.0
modified
- i-ext-method
String.isOnlySymbols fun String.isOnlySymbols(): Boolean
+
v1.0.88
added
v1.1.0
modified
- i-ext-method
String.isOnlyLetters fun String.isOnlyLetters(): Boolean
+
v1.0.88
added
v1.1.0
modified
- i-ext-method
String.isOnlyNumbers fun String.isOnlyNumbers(): Boolean
+
v1.0.88
added
v1.1.0
modified
- i-ext-method
String.isOnlyLettersNumbers fun String.isOnlyLettersNumbers(): Boolean
+
v1.0.88
added
v1.1.0
modified
- i-ext-method
String.isOnlyLowercase fun String.isOnlyLowercase(): Boolean
+
v1.0.88
added
v1.1.0
modified
- i-ext-method
String.isOnlyUppercase fun String.isOnlyUppercase(): Boolean
+
v1.0.88
added
v1.1.0
modified
Yuki Hook API
- class
DexClassFinder class DexClassFinder internal constructor(
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+
v1.1.0
added
Class
查找类。BaseDexClassLoader
通过指定条件查找指定 Class
或一组 Class
。- object
companion object v1.1.0
added
- method
clearCache fun clearCache(context: Context?, versionName: String?, versionCode: Long?)
+
v1.1.0
added
DexClassFinder
的 Class
缓存。DexClassFinder
。- field
fullName var fullName: String
+
v1.1.0
added
Class
完整名称。Class.getName
。com.demo.Test
需要填写 com.demo.Test
。- field
simpleName var simpleName: String
+
v1.1.0
added
Class
简单名称。Class.getSimpleName
。com.demo.Test
只需要填写 Test
。com.demo.Test$InnerTest
会为空,此时你可以使用 singleName。- field
singleName var singleName: String
+
v1.1.0
added
Class
独立名称。Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。com.demo.Test
只需要填写 Test
。com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。- method
from fun from(vararg name: String): FromPackageRules
+
v1.1.0
added
Class
。name
开头匹配的包名路径下进行查找,可提升查找速度。com.demo.test
com.demo.test.demo
- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
added
Class
标识符筛选条件。- method
fullName fun fullName(value: String): ClassNameRules
+
v1.1.0
added
Class
完整名称。Class.getName
。com.demo.Test
需要填写 com.demo.Test
。- method
simpleName fun simpleName(value: String): ClassNameRules
+
v1.1.0
added
Class
简单名称。Class.getSimpleName
。com.demo.Test
只需要填写 Test
。com.demo.Test$InnerTest 会为空
,此时你可以使用 singleName。- method
singleName fun singleName(value: String): ClassNameRules
+
v1.1.0
added
Class
独立名称。Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。com.demo.Test
只需要填写 Test
。com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。- method
fullName fun fullName(conditions: NameConditions)
+
v1.1.0
added
Class
完整名称条件。Class.getName
。- method
simpleName fun simpleName(conditions: NameConditions)
+
v1.1.0
added
Class
简单名称条件。Class.getSimpleName
。- method
singleName fun singleName(conditions: NameConditions)
+
v1.1.0
added
Class
独立名称条件。Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。- method
extends inline fun <reified T> extends()
+
v1.1.0
added
Class
继承的父类。- method
extends fun extends(vararg name: String)
+
v1.1.0
added
Class
继承的父类。name
中所有匹配的父类。- method
implements inline fun <reified T> implements()
+
v1.1.0
added
Class
实现的接口类。- method
implements fun implements(vararg name: String)
+
v1.1.0
added
Class
实现的接口类。name
中所有匹配的接口类。- method
anonymous fun anonymous()
+
v1.1.0
added
Class
为匿名类。com.demo.Test$1
或 com.demo.Test$InnerTest
。- method
noExtends fun noExtends()
+
v1.1.0
added
Class
没有任何继承。Class
只应该继承于 Any
。- method
noImplements fun noImplements()
+
v1.1.0
added
Class
没有任何接口。- method
noSuper fun noSuper()
+
v1.1.0
added
Class
没有任何继承与接口。Class
只应该继承于 Any
。- method
enclosing inline fun <reified T> enclosing()
+
v1.1.0
added
Class
匿名类的 (封闭类) 主类。- method
enclosing fun enclosing(vararg name: String)
+
v1.1.0
added
Class
匿名类的 (封闭类) 主类。name
中所有匹配的 (封闭类) 主类。- class
FromPackageRules inner class FromPackageRules internal constructor(private val packages: ArrayList<ClassRulesData.PackageRulesData>)
+
v1.1.0
added
- method
absolute fun absolute()
+
v1.1.0
added
com.demo.test.a
com.demo.test.a.b
com.demo.test.active
com.demo.test.a
则绝对匹配仅能匹配到第一个。- class
ClassNameRules inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+
v1.1.0
added
- method
optional fun optional()
+
v1.1.0
added
com.demo.Test
fullName / Test
simpleNamedefpackage.a
fullName / a
simpleNamecom.demo.Test
fullName / Test
simpleName。- method
member inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+
v1.1.0
added
Class
满足的 Member
条件。- method
field inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+
v1.1.0
added
Class
满足的 Field
条件。- method
method inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+
v1.1.0
added
Class
满足的 Method
条件。- method
constructor inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+
v1.1.0
added
Class
满足的 Constructor
条件。- class
Result inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+
v1.1.0
added
Class
查找结果实现类。- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.1.0
added
- method
get fun get(): Class<*>?
+
v1.1.0
added
Class
本身。Class
结果只会返回第一个。null
。async
请使用 wait 方法。- method
all fun all(): HashSet<Class<*>>
+
v1.1.0
added
Class
本身数组。Class
实例。HashSet
。async
请使用 waitAll 方法。- method
all fun all(result: (Class<*>) -> Unit): Result
+
v1.1.0
added
Class
本身数组 (依次遍历)。Class
实例。async
请使用 waitAll 方法。- method
wait fun wait(result: (Class<*>?) -> Unit): Result
+
v1.1.0
added
Class
本身 (异步)。Class
结果只会回调第一个。async
后此方法才会被回调,否则请使用 get 方法。- method
waitAll fun waitAll(result: (HashSet<Class<*>>) -> Unit): Result
+
v1.1.0
added
Class
本身数组 (异步)。Class
实例。HashSet
。async
后此方法才会被回调,否则请使用 all 方法。- method
onNoClassDefFoundError fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+
v1.1.0
added
Class
时。- method
ignored fun ignored(): Result
+
v1.1.0
added
Yuki Hook API
- class
ConstructorRules class ConstructorRules internal constructor(internal val rulesData: ConstructorRulesData) : BaseRules
+
v1.1.0
added
Constructor
查找条件实现类。- field
paramCount var paramCount: Int
+
v1.1.0
added
Constructor
参数个数。param
指定参数类型而是仅使用此变量指定参数个数。param
。- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
added
Constructor
标识符筛选条件。- method
emptyParam fun emptyParam()
+
v1.1.0
added
Constructor
空参数、无参数。- method
param fun param(vararg paramType: Any)
+
v1.1.0
added
Constructor
参数。paramCount
则 paramType
的数量必须与 paramCount
完全匹配。Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。- method
paramCount fun paramCount(numRange: IntRange)
+
v1.1.0
added
Constructor
参数个数范围。param
指定参数类型而是仅使用此方法指定参数个数范围。- method
paramCount fun paramCount(conditions: CountConditions)
+
v1.1.0
added
Constructor
参数个数条件。param
指定参数类型而是仅使用此方法指定参数个数条件。Yuki Hook API
- class
FieldRules class FieldRules internal constructor(internal val rulesData: FieldRulesData) : BaseRules
+
v1.1.0
added
Field
查找条件实现类。- field
name var name: String
+
v1.1.0
added
Field
名称。- field
type var type: Any?
+
v1.1.0
added
Field
类型。- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
added
Field
标识符筛选条件。- method
name fun name(conditions: NameConditions)
+
v1.1.0
added
Field
名称条件。Yuki Hook API
- class
MemberRules class MemberRules internal constructor(internal val rulesData: MemberRulesData) : BaseRules
+
v1.1.0
added
Member
查找条件实现类。- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
added
Member
标识符筛选条件。Yuki Hook API
- class
MethodRules class MethodRules internal constructor(internal val rulesData: MethodRulesData) : BaseRules
+
v1.1.0
added
Method
查找条件实现类。- field
name var name: String
+
v1.1.0
added
Method
名称。- field
paramCount var paramCount: Int
+
v1.1.0
added
Method
参数个数。param
指定参数类型而是仅使用此变量指定参数个数。param
。- field
returnType var returnType: Any?
+
v1.1.0
added
Method
返回值。- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
added
Method
标识符筛选条件。- method
emptyParam fun emptyParam()
+
v1.1.0
added
Method
空参数、无参数。- method
param fun param(vararg paramType: Any)
+
v1.1.0
added
Method
参数。paramCount
则 paramType
的数量必须与 paramCount
完全匹配。Method
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。- method
name fun name(conditions: NameConditions)
+
v1.1.0
added
Method
名称条件。- method
paramCount fun paramCount(numRange: IntRange)
+
v1.1.0
added
Method
参数个数范围。param
指定参数类型而是仅使用此方法指定参数个数范围。- method
paramCount fun paramCount(conditions: CountConditions)
+
v1.1.0
added
Method
参数个数条件。param
指定参数类型而是仅使用此方法指定参数个数条件。Yuki Hook API
- class
MemberRulesResult class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+
v1.1.0
added
Member
查找条件结果实现类。- method
none fun none(): MemberRulesResult
+
v1.1.0
added
Member
在查找条件中个数为 0
。- method
count fun count(num: Int): MemberRulesResult
+
v1.1.0
added
Member
在查找条件中需要全部匹配的个数。- method
count fun count(numRange: IntRange): MemberRulesResult
+
v1.1.0
added
Member
在查找条件中需要全部匹配的个数范围。- method
count fun count(conditions: CountConditions): MemberRulesResult
+
v1.1.0
added
Member
在查找条件中需要全部匹配的个数条件。Yuki Hook API
- class
ConstructorFinder class ConstructorFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
+
v1.0
first
v1.0.2
modified
BaseFinder
v1.1.0
modified
MemberBaseFinder
Constructor
查找类。Constructor
或一组 Constructor
。- field
paramCount var paramCount: Int
+
v1.0.67
added
Constructor
参数个数。param
指定参数类型而是仅使用此变量指定参数个数。param
。- method
modifiers fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
v1.0.67
added
v1.0.80
modified
v1.1.0
modified
ModifierConditions
Constructor
标识符筛选条件。Constructor
。- method
emptyParam fun emptyParam(): IndexTypeCondition
+
v1.0.75
added
Constructor
空参数、无参数。- method
param fun param(vararg paramType: Any): IndexTypeCondition
+
v1.0
first
Constructor
参数。paramCount
则 paramType
的数量必须与 paramCount
完全匹配。Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。- method
paramCount fun paramCount(num: Int): IndexTypeCondition
+
v1.0.70
added
Constructor
参数个数。param
指定参数类型而是仅使用此方法指定参数个数。param
。- method
paramCount fun paramCount(numRange: IntRange): IndexTypeCondition
+
v1.1.0
added
Constructor
参数个数范围。param
指定参数类型而是仅使用此方法指定参数个数范围。- method
paramCount fun paramCount(conditions: CountConditions): IndexTypeCondition
+
v1.1.0
added
Constructor
参数个数条件。param
指定参数类型而是仅使用此方法指定参数个数条件。- method
superClass fun superClass(isOnlySuperClass: Boolean)
+
v1.0.80
added
classSet
的所有父类中查找当前 Constructor
。- class
RemedyPlan inner class RemedyPlan internal constructor()
+
v1.0
first
Constructor
重查找实现类,可累计失败次数直到查找成功。- method
constructor inline fun constructor(initiate: ConstructorConditions)
+
v1.0
first
v1.0.80
modified
Constructor
。Constructor
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。- class
Result inner class Result internal constructor()
+
v1.0.1
added
RemedyPlan
结果实现类。- method
onFind fun onFind(initiate: HashSet<Constructor<*>>.() -> Unit)
+
v1.0.1
added
v1.1.0
modified
initiate
参数 Constructor
变为 HashSet<Constructor>
RemedyPlan
中找到结果时。Constructor
实现 onFind
方法。constructor {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
- class
Process inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
v1.1.0
added
Constructor
查找结果处理类,为 hookInstance
提供。- method
result inline fun result(initiate: Process.() -> Unit): Process
+
v1.1.0
added
lambda
形式创建 Result
类。constructor {
+ // Your code here.
+}.result {
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
- method
all fun all(): Process
+
v1.1.0
added
Constructor
实例结果到 hookInstance
。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.1.0
added
Constructor
重查找功能。Constructor
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchConstructor
捕获异常二次查找 Constructor
。constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
- method
onNoSuchConstructor inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
v1.1.0
added
Constructor
时。RemedyPlan
的错误信息。- class
Result inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
v1.0
first
v1.1.0
modified
BaseResult
Constructor
查找结果实现类。- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0
first
v1.0.80
modified
lambda
形式创建 Result
类。constructor {
+ // Your code here.
+}.result {
+ get().call()
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
- method
get fun get(): Instance
+
v1.0.2
added
Constructor
实例处理类。Constructor
结果只会返回第一个。constructor {
+ // Your code here.
+}.get().call()
+
cast
构造方法为指定类型的实例对象。constructor {
+ // Your code here.
+}.get().newInstance<TestClass>()
+
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>("param1", "param2")
+
- method
all fun all(): ArrayList<Instance>
+
v1.1.0
added
Constructor
实例处理类数组。Constructor
实例结果。Constructor
。constructor {
+ // Your code here.
+}.all().forEach { instance ->
+ instance.call(...)
+}
+
- method
give fun give(): Constructor<*>?
+
v1.0.67
added
Constructor
本身。Constructor
结果只会返回第一个。null
。- method
giveAll fun giveAll(): HashSet<Constructor<*>>
+
v1.1.0
added
Constructor
本身数组。Constructor
实例。HashSet
。- method
wait fun wait(initiate: Instance.() -> Unit)
+
v1.0.2
added
Constructor
实例处理类,配合 RemedyPlan
使用。Constructor
结果只会返回第一个。- method
waitAll fun waitAll(initiate: ArrayList<Instance>.() -> Unit)
+
v1.1.0
added
Constructor
实例处理类数组,配合 RemedyPlan
使用。Constructor
实例结果。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.0
first
v1.0.80
modified
Constructor
重查找功能。Constructor
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchConstructor
捕获异常二次查找 Constructor
。constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
- method
onNoSuchConstructor inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
v1.0
first
v1.0.80
modified
Constructor
时。RemedyPlan
的错误信息。- method
ignored fun ignored(): Result
+
v1.1.0
added
isNotIgnoredHookingFailure
为 false
则自动忽略。ignoredError - method
v1.0.3
added
v1.1.0
deprecated
ignored()
- class
Instance inner class Instance internal constructor(private val constructor: Constructor<*>?)
+
v1.0.2
added
v1.1.0
modified
constructor
参数Constructor
实例处理类。- method
call fun call(vararg param: Any?): Any?
+
v1.0.2
added
Constructor
创建目标实例,不指定目标实例类型。- method
newInstance fun <T> newInstance(vararg param: Any?): T?
+
v1.0.2
added
Constructor
创建目标实例 ,指定 T
目标实例类型。Yuki Hook API
- class
FieldFinder class FieldFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>?) : MemberBaseFinder
+
v1.0
first
v1.0.2
modified
BaseFinder
v1.1.0
modified
MemberBaseFinder
Field
查找类。Field
或一组 Field
。classSet - field
v1.0
first
v1.0.2
removed
- field
name var name: String
+
v1.0
first
v1.0.70
modified
Field
名称。- field
type var type: Any?
+
v1.0
first
Field
类型。- method
modifiers fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
v1.0.67
added
v1.0.80
modified
v1.1.0
modified
ModifierConditions
Field
标识符筛选条件。- method
order fun order(): IndexTypeCondition
+
v1.0.70
added
- method
name fun name(value: String): IndexTypeCondition
+
v1.0.70
added
Field
名称。- method
name fun name(conditions: NameConditions): IndexTypeCondition
+
v1.0.88
added
v1.1.0
modified
NameConditions
Field
名称条件。- method
type fun type(value: Any): IndexTypeCondition
+
v1.0.70
added
Field
类型。- method
superClass fun superClass(isOnlySuperClass: Boolean)
+
v1.0.80
added
classSet
的所有父类中查找当前 Field
。- class
RemedyPlan inner class RemedyPlan internal constructor()
+
v1.1.0
added
Field
重查找实现类,可累计失败次数直到查找成功。- method
field inline fun field(initiate: FieldConditions): Result
+
v1.1.0
added
Field
。Field
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。- class
Result inner class Result internal constructor()
+
v1.1.0
added
RemedyPlan
结果实现类。- method
onFind fun onFind(initiate: HashSet<Field>.() -> Unit)
+
v1.1.0
added
RemedyPlan
中找到结果时。Field
实现 onFind
方法。field {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
- class
Result inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
+
v1.0
first
v1.1.0
modified
BaseResult
Field
查找结果实现类。- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0
first
v1.0.80
modified
lambda
形式创建 Result
类。field {
+ // Your code here.
+}.result {
+ get(instance).set("something")
+ get(instance).string()
+ get(instance).cast<CustomClass>()
+ get().boolean()
+ all(instance)
+ give()
+ giveAll()
+ onNoSuchField {}
+}
+
- method
get fun get(instance: Any?): Instance
+
v1.0
first
Field
实例处理类。Field
结果只会返回第一个。Field
的实例以及使用它进行设置实例。field {
+ // Your code here.
+}.get(instance).set("something")
+
Field
,可以不需要设置实例。field {
+ // Your code here.
+}.get().set("something")
+
- method
all fun all(instance: Any?): ArrayList<Instance>
+
v1.1.0
added
Field
实例处理类数组。Field
实例结果。Field
,其 Field
所在实例用法与 get
相同。field {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.self
+}
+
- method
give fun give(): Field?
+
v1.0
first
Field
本身。null
。- method
giveAll fun giveAll(): HashSet<Field>
+
v1.1.0
added
Field
本身数组。Field
实例。HashSet
。- method
wait fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
v1.1.0
added
Field
实例处理类,配合 RemedyPlan
使用。Field
结果只会返回第一个。- method
waitAll fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
+
v1.1.0
added
Field
实例处理类数组,配合 RemedyPlan
使用。Field
实例结果。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.1.0
added
Field
重查找功能。Field
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchField
捕获异常二次查找 Field
。field {
+ // Your code here.
+}.remedys {
+ field {
+ // Your code here.
+ }
+ field {
+ // Your code here.
+ }
+}
+
- method
onNoSuchField fun onNoSuchField(result: (Throwable) -> Unit): Result
+
v1.0
first
Field
时。- method
ignored fun ignored(): Result
+
v1.1.0
added
isNotIgnoredHookingFailure
为 false
则自动忽略。ignoredError - method
v1.0.3
added
v1.1.0
deprecated
ignored()
- class
Instance inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
+
v1.0
first
v1.1.0
modified
field
参数self
参数Field
实例变量处理类。self - field
v1.0
first
v1.1.0
removed
any
方法得到 Field
自身的实例化对象- method
current fun current(ignored: Boolean): CurrentClass?
+
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
+
v1.1.0
added
Field
自身 self
实例的类操作对象 CurrentClass
。- method
cast fun <T> cast(): T?
+
v1.0
first
v1.0.68
modified
为 of
cast
Instance
Field
实例。- method
byte fun byte(): Byte?
+
v1.0.68
added
Field
Byte 实例。- method
int fun int(): Int
+
v1.0.65
added
v1.0.68
modified
为 ofInt
int
Instance
Field
Int 实例。- method
long fun long(): Long
+
v1.0.65
added
v1.0.68
modified
为 ofLong
long
Instance
Field
Long 实例。- method
short fun short(): Short
+
v1.0.65
added
v1.0.68
modified
为 ofShort
short
Instance
Field
Short 实例。- method
double fun double(): Double
+
v1.0.65
added
v1.0.68
modified
为 ofDouble
double
Instance
Field
Double 实例。- method
float fun float(): Float
+
v1.0.65
added
v1.0.68
modified
为 ofFloat
float
Instance
Field
Float 实例。- method
string fun string(): String
+
v1.0.65
added
v1.0.68
modified
为 ofString
string
Instance
Field
String 实例。- method
char fun char(): Char
+
v1.0.68
added
Field
Char 实例。- method
boolean fun boolean(): Boolean
+
v1.0.65
added
v1.0.68
modified
为 ofBoolean
boolean
Instance
Field
Boolean 实例。- method
any fun any(): Any?
+
v1.0.65
added
v1.0.68
modified
为 ofAny
any
Instance
Field
Any 实例。- method
array inline fun <reified T> array(): Array<T>
+
v1.0.68
added
Field
Array 实例。- method
list inline fun <reified T> list(): List<T>
+
v1.0.68
added
Field
List 实例。- method
set fun set(any: Any?)
+
v1.0
first
Field
实例。- method
setTrue fun setTrue()
+
v1.0
first
Field
实例为 true
。- method
setFalse fun setFalse()
+
v1.0
first
Field
实例为 false
。- method
setNull fun setNull()
+
v1.0
first
Field
实例为 null
。Yuki Hook API
- class
MethodFinder class MethodFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
+
v1.0
first
v1.0.2
modified
BaseFinder
v1.1.0
modified
MemberBaseFinder
Method
查找类。Method
或一组 Method
。- field
name var name: String
+
v1.0
first
v1.0.70
modified
Method
名称。- field
paramCount var paramCount: Int
+
v1.0.67
added
Method
参数个数。param
指定参数类型而是仅使用此变量指定参数个数。param
。- field
returnType var returnType: Any?
+
v1.0
first
Method
返回值,可不填写返回值。- method
modifiers fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
v1.0.67
added
v1.0.80
modified
v1.1.0
modified
ModifierConditions
Method
标识符筛选条件。- method
emptyParam fun emptyParam(): IndexTypeCondition
+
v1.0.75
added
Method
空参数、无参数。- method
param fun param(vararg paramType: Any): IndexTypeCondition
+
v1.0
first
Method
参数。paramCount
则 paramType
的数量必须与 paramCount
完全匹配。Method
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。- method
order fun order(): IndexTypeCondition
+
v1.0.70
added
- method
name fun name(value: String): IndexTypeCondition
+
v1.0.70
added
Method
名称。- method
name fun name(conditions: NameConditions): IndexTypeCondition
+
v1.0.88
added
v1.1.0
modified
NameConditions
Method
名称条件。- method
paramCount fun paramCount(num: Int): IndexTypeCondition
+
v1.0.70
added
Method
参数个数。param
指定参数类型而是仅使用此方法指定参数个数。param
。- method
paramCount fun paramCount(numRange: IntRange): IndexTypeCondition
+
v1.1.0
added
Method
参数个数范围。param
指定参数类型而是仅使用此方法指定参数个数范围。- method
paramCount fun paramCount(conditions: CountConditions): IndexTypeCondition
+
v1.1.0
added
Method
参数个数条件。param
指定参数类型而是仅使用此方法指定参数个数条件。- method
returnType fun returnType(value: Any): IndexTypeCondition
+
v1.0.70
added
Method
返回值。- method
superClass fun superClass(isOnlySuperClass: Boolean)
+
v1.0.80
added
classSet
的所有父类中查找当前 Method
。- class
RemedyPlan inner class RemedyPlan internal constructor()
+
v1.0
first
Method
重查找实现类,可累计失败次数直到查找成功。- method
method inline fun method(initiate: MethodConditions): Result
+
v1.0
first
v1.0.80
modified
Method
。Method
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。- class
Result inner class Result internal constructor()
+
v1.0.1
added
RemedyPlan
结果实现类。- method
onFind fun onFind(initiate: HashSet<Method>.() -> Unit)
+
v1.0.1
added
v1.1.0
modified
initiate
参数 Method
变为 HashSet<Method>
RemedyPlan
中找到结果时。Method
实现 onFind
方法。method {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
- class
Process inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
v1.1.0
added
Method
查找结果处理类,为 hookInstance
提供。- method
result inline fun result(initiate: Process.() -> Unit): Process
+
v1.1.0
added
lambda
形式创建 Result
类。method {
+ // Your code here.
+}.result {
+ all()
+ remedys {}
+ onNoSuchMethod {}
+}
+
- method
all fun all(): Process
+
v1.1.0
added
Method
实例结果到 hookInstance
。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.1.0
added
Method
重查找功能。Method
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchMethod
捕获异常二次查找 Method
。method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
- method
onNoSuchMethod inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
v1.1.0
added
Method
时。RemedyPlan
的错误信息。- class
Result inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
+
v1.0
first
v1.1.0
modified
BaseResult
Method
查找结果实现类。- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0
first
v1.0.80
modified
lambda
形式创建 Result
类。method {
+ // Your code here.
+}.result {
+ get(instance).call()
+ all(instance)
+ remedys {}
+ onNoSuchMethod {}
+}
+
- method
get fun get(instance: Any?): Instance
+
v1.0.2
added
Method
实例处理类。Method
结果只会返回第一个。Method
。method {
+ // Your code here.
+}.get(instance).call()
+
method {
+ // Your code here.
+}.get().call()
+
- method
all fun all(instance: Any?): ArrayList<Instance>
+
v1.1.0
added
Method
实例处理类数组。Method
实例结果。Method
,其方法所在实例用法与 get
相同。method {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.call(...)
+}
+
- method
give fun give(): Method?
+
v1.0.67
added
Method
本身。Method
结果只会返回第一个。null
。- method
giveAll fun giveAll(): HashSet<Method>
+
v1.1.0
added
Method
本身数组。Method
实例。HashSet
。- method
wait fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
v1.0.2
added
Method
实例处理类,配合 RemedyPlan
使用。Method
结果只会返回第一个。- method
waitAll fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
+
v1.1.0
added
Method
实例处理类数组,配合 RemedyPlan
使用。Method
实例结果。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.0
first
v1.0.80
modified
Method
重查找功能。Method
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchMethod
捕获异常二次查找 Method
。method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
- method
onNoSuchMethod inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
v1.0
first
v1.0.80
modified
Method
时。RemedyPlan
的错误信息。- method
ignored fun ignored(): Result
+
v1.1.0
added
isNotIgnoredHookingFailure
为 false
则自动忽略。ignoredError - method
v1.0.3
added
v1.1.0
deprecated
ignored()
- class
Instance inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
+
v1.0.2
added
v1.1.0
modified
method
参数Method
实例处理类。- method
original fun original(): Instance
+
v1.1.0
added
Method
未经 Hook 的原始方法。Method
并未 Hook 则会使用原始的 Method.invoke
方法调用。- method
call fun call(vararg param: Any?): Any?
+
v1.0.2
added
Method
,不指定返回值类型。- method
invoke fun <T> invoke(vararg param: Any?): T?
+
v1.0.2
added
Method
,指定 T
返回值类型。- method
byte fun byte(vararg param: Any?): Byte?
+
v1.0.68
added
Method
,指定 Byte 返回值类型。- method
int fun int(vararg param: Any?): Int
+
v1.0.65
added
v1.0.68
modified
为 callInt
int
Method
,指定 Int 返回值类型。- method
long fun long(vararg param: Any?): Long
+
v1.0.65
added
v1.0.68
modified
为 callLong
long
Method
,指定 Long 返回值类型。- method
short fun short(vararg param: Any?): Short
+
v1.0.65
added
v1.0.68
modified
为 callShort
short
Method
,指定 Short 返回值类型。- method
double fun double(vararg param: Any?): Double
+
v1.0.65
added
v1.0.68
modified
为 callDouble
double
Method
,指定 Double 返回值类型。- method
float fun float(vararg param: Any?): Float
+
v1.0.65
added
v1.0.68
modified
为 callFloat
float
Method
,指定 Float 返回值类型。- method
string fun string(vararg param: Any?): String
+
v1.0.65
added
v1.0.68
modified
为 callString
string
Method
,指定 String 返回值类型。- method
char fun char(vararg param: Any?): Char
+
v1.0.68
added
Method
,指定 Char 返回值类型。- method
boolean fun boolean(vararg param: Any?): Boolean
+
v1.0.65
added
v1.0.68
modified
为 callBoolean
boolean
Method
,指定 Boolean 返回值类型。- method
array inline fun <reified T> array(vararg param: Any?): Array<T>
+
v1.0.68
added
Method
,指定 Array 返回值类型。- method
list inline fun <reified T> list(vararg param: Any?): List<T>
+
v1.0.68
added
Method
,指定 List 返回值类型。Yuki Hook API
- class
YukiBaseHooker abstract class YukiBaseHooker : PackageParam()
+
v1.0
first
YukiHookAPI
的子类 Hooker 实现。- method
onHook fun onHook()
+
v1.0
first
Yuki Hook API
- kt
ReflectionFactory v1.0
first
Member
和 Class
相关功能的查找匹配以及 invoke
的封装类。- class
MembersType enum class MembersType
+
v1.1.0
added
Class
中的 Member
类型- enum
ALL ALL
+
v1.1.0
added
Method
与 Constructor
。- enum
METHOD METHOD
+
v1.1.0
added
Method
。- enum
CONSTRUCTOR CONSTRUCTOR
+
v1.1.0
added
Constructor
。- ext-method
ClassLoader.searchClass inline fun ClassLoader.searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
v1.1.0
added
ClassLoader
按指定条件查找并得到 Dex 中的 Class
。- ext-method
ClassLoader.onLoadClass fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
+
v1.1.0
added
ClassLoader
的 ClassLoader.loadClass
方法装载。ClassLoader
装载 Class
的宿主应用,你可以使用此方法来监听 Class
加载情况。PackageParam
中使用 appClassLoader
。appClassLoader.onLoadClass { clazz ->
+ // 得到 clazz 即加载对象
+ clazz... // 这里进行你需要的操作
+}
+
ClassLoader
实例,可以通过 Hook 获取。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+customClassLoader?.onLoadClass { clazz ->
+ // ...
+}
+
Class
被装载成功时,开始执行你的 Hook 功能。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+customClassLoader?.onLoadClass { clazz ->
+ if(clazz.name == /** 你需要的 Class 名称 */) {
+ clazz.hook {
+ // ...
+ }
+ }
+}
+
hookClass - field
v1.0
first
v1.1.0
removed
HookClass
相关功能不再对外开放normalClass - field
v1.0
first
v1.1.0
removed
HookClass
相关功能不再对外开放hasClass - field
v1.0
first
v1.1.0
removed
hasClass()
无参方法- ext-field
Class.hasExtends val Class<*>.hasExtends: Boolean
+
v1.0.80
added
Class
是否有继承关系,父类是 Any
将被认为没有继承关系。classOf - method
v1.0
first
v1.1.0
deprecated
toClass(...)
方法- ext-method
String.toClass fun String.toClass(loader: ClassLoader?): Class<*>
+
v1.1.0
added
loader
中的实体类。Class
,必须在默认 ClassLoader
下存在。"com.example.demo.DemoClass".toClass()
+
Class
所在的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
- ext-method
String.toClassOrNull fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
+
v1.1.0
added
loader
中的实体类。Class
会返回 null
,不会抛出异常。- method
classOf inline fun <reified T> classOf(loader: ClassLoader?): Class<*>
+
v1.1.0
added
T
得到其 Class
实例并转换为实体类。Class
在 Kotlin
下不通过反射时应该这样做。DemoClass::class.java
+
cast
一个实例并获取它的 Class
对象,必须在当前 ClassLoader
下存在。classOf<DemoClass>()
+
Class
为 stub
,通过这种方式,你还可以自定义 Class
所在的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+classOf<DemoClass>(customClassLoader)
+
- ext-method
String.hasClass fun String.hasClass(loader: ClassLoader?): Boolean
+
v1.0
first
v1.1.0
modified
ClassLoader
进行判断ClassLoader
查找是否存在。Class.forName
。if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
loader
参数可判断指定的 ClassLoader
中的 Class
是否存在。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
- ext-method
Class.hasField inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
+
v1.0.4
added
v1.0.67
modified
FieldFinder
v1.0.80
modified
- ext-method
Class.hasMethod inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
+
v1.0
first
v1.0.1
modified
returnType
参数v1.0.67
modified
MethodFinder
v1.0.80
modified
- ext-method
Class.hasConstructor inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
+
v1.0.2
added
v1.0.67
modified
ConstructorFinder
v1.0.80
modified
- ext-method
Member.hasModifiers inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
+
v1.0.67
added
v1.0.80
modified
v1.1.0
modified
ModifierConditions
Member
中匹配的描述符。- ext-method
Class.hasModifiers inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
+
v1.1.0
added
Class
中匹配的描述符。obtainStaticFieldAny - method
v1.0
first
v1.0.1
removed
obtainFieldAny - method
v1.0
first
v1.0.1
removed
modifyStaticField - method
v1.0
first
v1.0.1
removed
modifyField - method
v1.0
first
v1.0.1
removed
- ext-method
Class.field inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
+
v1.0.2
added
v1.0.80
modified
- ext-method
Class.method inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
+
v1.0
first
v1.0.1
modified
更名为 obtainMethod
method
returnType
参数v1.0.2
modified
MethodFinder
方法体v1.0.80
modified
- ext-method
Class.constructor inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
v1.0
first
v1.0.1
modified
更名为 obtainConstructor
constructor
v1.0.2
modified
ConstructorFinder
方法体v1.0.80
modified
callStatic - method
v1.0
first
v1.0.1
modified
更名为 invokeStatic
callStatic
v1.0.2
removed
call - method
v1.0
first
v1.0.1
modified
更名为 invokeAny
call
v1.0.2
removed
- ext-method
Class.generic fun Class<*>.generic(): GenericClass?
+
v1.1.0
added
Class
的泛型父类。null
。- ext-method
Class.generic inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
+
v1.1.0
added
Class
的泛型父类。null
。- ext-method
Any.current inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
+
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
+
v1.0.70
added
v1.1.0
added
ignored
参数,可以忽略在 CurrentClass
中出现的异常current { ... }
调用域直接使用 current()
得到实例的类操作对象Class.buildOfAny - ext-method
v1.0.70
added
v1.0.80
modified
v1.1.0
deprecated
buildOf
方法- ext-method
Class.buildOf inline fun Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): Any?
+
inline fun <T> Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): T?
+
v1.0.70
added
v1.0.80
modified
v1.1.0
modified
buildOf
T
或任意类型 Any
。- ext-method
Class.allMethods inline fun Class<*>.allMethods(result: (index: Int, method: Method) -> Unit)
+
v1.0.70
added
v1.0.80
modified
- ext-method
Class.allConstructors inline fun Class<*>.allConstructors(result: (index: Int, constructor: Constructor<*>) -> Unit)
+
v1.0.70
added
v1.0.80
modified
- ext-method
Class.allFields inline fun Class<*>.allFields(result: (index: Int, field: Field) -> Unit)
+
v1.0.70
added
v1.0.80
modified
Yuki Hook API
- kt
YukiHookFactory v1.0
first
v1.0.80
modified
IYukiHookXposedInit
,将方法体进行 inlineYukiHookAPI
相关 lambda
方法的封装类以及部分 API 用法。- ext-method
IYukiHookXposedInit.configs inline fun IYukiHookXposedInit.configs(initiate: YukiHookAPI.Configs.() -> Unit)
+
v1.0.1
added
v1.0.80
modified
IYukiHookXposedInit
IYukiHookXposedInit
中配置 Configs
。- ext-method
IYukiHookXposedInit.encase fun IYukiHookXposedInit.encase(initiate: PackageParam.() -> Unit)
+
fun IYukiHookXposedInit.encase(vararg hooker: YukiBaseHooker)
+
v1.0
first
v1.0.80
modified
IYukiHookXposedInit
IYukiHookXposedInit
中调用 YukiHookAPI
。- ext-field
Context.modulePrefs val Context.modulePrefs: YukiHookModulePrefs
+
v1.0
first
- ext-method
Context.modulePrefs fun Context.modulePrefs(name: String): YukiHookModulePrefs
+
v1.0
first
name
为自定义 Sp 存储名称。- ext-method
Context.dataChannel fun Context.dataChannel(packageName: String): YukiHookDataChannel.NameSpace
+
v1.0.88
added
- ext-field
Context.processName val Context.processName: String
+
v1.0
first
- ext-method
Context+Resources.injectModuleAppResources fun Context.injectModuleAppResources()
+
fun Resources.injectModuleAppResources()
+
v1.1.0
added
Context
或 Resources
注入当前 Xposed 模块的资源。ImageView.setImageResource
或 Resources.getString
装载当前 Xposed 模块的资源 ID。Context
或 Resources
,你需要在每个用到宿主 Context
或 Resources
的地方重复调用此方法进行注入才能使用。- ext-method
Context.registerModuleAppActivities fun Context.registerModuleAppActivities(proxy: Any?)
+
v1.1.0
added
Activity
。Context.startActivity
来启动未在宿主中注册的 Activity
。Activity
在 Hook APP (宿主) 中启动时自动调用 injectModuleAppResources
注入当前 Xposed 模块的资源。Activity
继承于 ModuleAppActivity
或 ModuleAppCompatActivity
。- ext-method
Context.applyModuleTheme fun Context.applyModuleTheme(theme: Int, configuration: Configuration?): ModuleContextThemeWrapper
+
v1.1.0
added
ContextThemeWrapper
代理以应用当前 Xposed 模块的主题资源。injectModuleAppResources
注入当前 Xposed 模块的资源。ClassCastException
,请手动设置 configuration
。isSupportResourcesHook - field
v1.0.80
added
v1.0.91
removed
YukiHookAPI.Status.isSupportResourcesHook
isModuleActive - field
v1.0.6
added
v1.0.91
removed
YukiHookAPI.Status.isModuleActive
isXposedModuleActive - field
v1.0.6
added
v1.0.91
removed
YukiHookAPI.Status.isXposedModuleActive
isTaiChiModuleActive - field
v1.0
first
v1.0.91
removed
YukiHookAPI.Status.isTaiChiModuleActive
YukiHookModuleStatus - class
v1.0
first
v1.0.91
deprecated
YukiHookAPI.Status
Yuki Hook API
- kt
LoggerFactory v1.0
first
YukiHookAPI
的日志封装类,可实现同时向 Logcat
和 XposedBridge.log
打印日志的功能。- class
LoggerType enum class LoggerType
+
v1.1.0
added
- enum
LOGD LOGD
+
v1.1.0
added
android.util.Log
。- enum
XPOSEDBRIDGE XPOSEDBRIDGE
+
v1.1.0
added
XposedBridge.log
。- enum
SCOPE SCOPE
+
v1.1.0
added
XPOSEDBRIDGE
。LOGD
。- enum
BOTH BOTH
+
v1.1.0
added
LOGD
与 XPOSEDBRIDGE
。LOGD
。- object
YukiHookLogger object YukiHookLogger
+
v1.1.0
added
- field
contents val contents: String
+
v1.1.0
added
- method
clear fun clear()
+
v1.1.0
added
- method
saveToFile fun saveToFile(fileName: String)
+
v1.1.0
added
Configs.isRecord
或记录为空则不会进行任何操作。fileName
的文件结尾,若文件不存在会自动创建。- object
Configs object Configs
+
v1.1.0
added
YukiHookLogger
。- field
TAG const val TAG: Int
+
v1.1.0
added
- field
PRIORITY const val PRIORITY: Int
+
v1.1.0
added
- field
PACKAGE_NAME const val PACKAGE_NAME: Int
+
v1.1.0
added
- field
USER_ID const val USER_ID: Int
+
v1.1.0
added
- field
isEnable var isEnable: Boolean
+
v1.1.0
added
YukiHookAPI
对全部日志的输出。loggerD
、loggerI
、loggerW
、loggerE
。isEnable
关闭后 YukiHookAPI.Configs.isDebug
也将同时关闭。- field
isRecord var isRecord: Boolean
+
v1.1.0
added
- field
tag var tag: String
+
v1.1.0
added
YukiHookAPI
。- method
elements fun elements(vararg item: Int)
+
v1.1.0
added
XposedBridge.log
生效。item
中设置的顺序进行显示。item
以不显示除日志内容外的全部元素。TAG
、PRIORITY
、PACKAGE_NAME
、USER_ID
。elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+
[YukiHookAPI][D][com.demo.test][999]--> This is a log
+
elements(PACKAGE_NAME, USER_ID, PRIORITY)
+
[com.demo.test][999][D]--> This is a log
+
- method
loggerD fun loggerD(tag: String, msg: String, type: LoggerType)
+
v1.0
first
v1.1.0
modified
type
参数Logcat
和 XposedBridge
打印日志,级别 D
。tag
的默认参数为 YukiHookAPI.Configs.debugTag
,你可以进行自定义。- method
loggerI fun loggerI(tag: String, msg: String, type: LoggerType)
+
v1.0
first
v1.1.0
modified
type
参数Logcat
和 XposedBridge
打印日志,级别 I
。tag
的默认参数为 YukiHookAPI.Configs.debugTag
,你可以进行自定义。- method
loggerW fun loggerW(tag: String, msg: String, type: LoggerType)
+
v1.0
first
v1.1.0
modified
type
参数Logcat
和 XposedBridge
打印日志,级别 W
。tag
的默认参数为 YukiHookAPI.Configs.debugTag
,你可以进行自定义。- method
loggerE fun loggerE(tag: String, msg: String, e: Throwable?, type: LoggerType)
+
v1.0
first
v1.1.0
modified
type
参数Logcat
和 XposedBridge
打印日志,级别 E
,可携带 e
异常信息,将打印异常堆栈。tag
的默认参数为 YukiHookAPI.Configs.debugTag
,你可以进行自定义。Yuki Hook API
- class
HookParam class HookParam internal constructor(private val creatorInstance: YukiMemberHookCreator, private var param: YukiHookCallback.Param?)
+
v1.0
first
v1.1.0
modified
HookParamWrapper
到 YukiHookCallback.Param
- field
args val args: Array<Any?>
+
v1.0
添加member
或 constructor
的参数对象数组。Any
,你可以使用 args
方法来实现 ArgsModifyer.cast
功能。firstArgs - field
v1.0
first
v1.0.75
removed
args(index = 0)
或 args().first()
lastArgs - field
v1.0
first
v1.0.75
removed
args().last()
- field
instance val instance: Any
+
v1.0
first
- field
instanceClass val instanceClass: Class<*>
+
v1.0
first
- field
member val member: Member
+
v1.1.0
added
Member
。Member
类型为 Method
或 Constructor
时可以使用此方法。- field
method val method: Method
+
v1.0
first
- field
constructor val constructor: Constructor
+
v1.0
first
- field
result var result: Any?
+
v1.0
first
method
或 constructor
的返回值。- field
hasThrowable val hasThrowable: Boolean
+
v1.1.0
added
- field
throwable val throwable: Throwable?
+
v1.1.0
added
- i-ext-method
Throwable.throwToApp fun Throwable.throwToApp()
+
v1.1.0
added
hasThrowable
判断当前是否存在被抛出的异常。throwable
获取当前设置的方法调用抛出异常。MemberHookCreator.beforeHook
或 MemberHookCreator.afterHook
中生效。injectMember {
+ method {
+ // ...
+ }
+ beforeHook {
+ RuntimeException("Test Exception").throwToApp()
+ }
+}
+
- method
result inline fun <reified T> result(): T?
+
v1.0.75
added
method
或 constructor
的返回值 T
。firstArg - method
v1.0.66
added
v1.0.75
removed
lastArgs - method
v1.0.66
added
v1.0.75
removed
- method
instance inline fun <reified T> instance(): T
+
v1.0
first
T
。instance
方法轻松使用泛型 cast
为目标对象的类型。instance<Activity>().finish()
+
- method
args fun args(): ArgsIndexCondition
+
v1.0.75
added
method
或 constructor
的参数数组下标实例化类。- method
args fun args(index: Int): ArgsModifyer
+
v1.0
first
v1.0.75
modified
index = 0
移动到新的使用方法 args().first()
method
或 constructor
的参数实例化对象类。args
方法修改当前 Hook 实例的方法、构造方法的参数内容。set
方法设置 param
为你的目标实例,接受 Any
类型。args(index = 0).set("modify the value")
+
param
的值。args().first().set("modify the value")
+
param
的值。args().last().set("modify the value")
+
setNull
方法设置 param
为空。args(index = 1).setNull()
+
setTrue
方法设置 param
为 true
。args(index = 1).setTrue()
+
setFalse
方法设置 param
为 false
。args(index = 1).setFalse()
+
- method
callOriginal fun callOriginal(): Any?
+
fun <T> callOriginal(): T?
+
v1.1.0
added
Member
。Member
并调用原始参数执行。invoke
原始未经 Hook 的 Member
对象,取决于原始 Member
的参数。beforeHook
、afterHook
以及 replaceUnit
、replaceAny
。test("test value")
,使用此方法会调用其中的 "test value"
作为参数。injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = StringType
+ }
+ afterHook {
+ // <方案1> 不使用泛型,不获取方法执行结果,调用将使用原方法传入的 args 自动传参
+ callOriginal()
+ // <方案2> 使用泛型,已知方法执行结果参数类型进行 cast
+ // 假设返回值为 String,失败会返回 null,调用将使用原方法传入的 args 自动传参
+ val value = callOriginal<String>()
+ }
+}
+
- method
invokeOriginal fun invokeOriginal(vararg args: Any?): Any?
+
fun <T> invokeOriginal(vararg args: Any?): T?
+
v1.0
first
v1.1.0
modified
member.invokeOriginal
进行调用Member
。Member
并自定义 args
执行。invoke
原始未经 Hook 的 Member
对象,可自定义需要调用的参数内容。beforeHook
、afterHook
以及 replaceUnit
、replaceAny
。test("test value")
,使用此方法可自定义其中的 args
作为参数。injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = StringType
+ }
+ afterHook {
+ // <方案1> 不使用泛型,不获取方法执行结果
+ invokeOriginal("test value")
+ // <方案2> 使用泛型,已知方法执行结果参数类型进行 cast,假设返回值为 String,失败会返回 null
+ val value = invokeOriginal<String>("test value")
+ }
+}
+
- method
resultTrue fun resultTrue()
+
v1.0
first
result
返回值为 true
。- method
resultFalse fun resultFalse()
+
v1.0
first
result
返回值为 false
。- method
resultNull fun resultNull()
+
v1.0
first
- class
ArgsIndexCondition inner class ArgsIndexCondition internal constructor()
+
v1.0.75
added
- method
first fun first(): ArgsModifyer
+
v1.0.75
added
method
或 constructor
的参数数组第一位。- method
last fun last(): ArgsModifyer
+
v1.0.75
added
method
或 constructor
的参数数组最后一位。- class
ArgsModifyer inner class ArgsModifyer internal constructor(private val index: Int)
+
v1.0
first
- method
cast fun <T> cast(): T?
+
v1.0.66
added
v1.0.68
modified
为 of
cast
T
。- method
byte fun byte(): Byte?
+
v1.0.68
added
- method
int fun int(): Int
+
v1.0.66
added
v1.0.68
modified
为 ofInt
int
- method
long fun long(): Long
+
v1.0.66
added
v1.0.68
modified
为 ofLong
long
- method
short fun short(): Short
+
v1.0.66
added
v1.0.68
modified
为 ofShort
short
- method
double fun double(): Double
+
v1.0.66
added
v1.0.68
modified
为 ofDouble
double
- method
float fun float(): Float
+
v1.0.66
added
v1.0.68
modified
为 ofFloat
float
- method
string fun string(): String
+
v1.0.66
added
v1.0.68
modified
为 ofString
string
- method
char fun char(): Char
+
v1.0.68
added
- method
boolean fun boolean(): Boolean
+
v1.0.66
added
v1.0.68
modified
为 ofBoolean
boolean
- method
any fun any(): Any?
+
v1.0.77
added
- method
array inline fun <reified T> array(): Array<T>
+
v1.0.68
added
- method
list inline fun <reified T> list(): List<T>
+
v1.0.68
added
- method
set fun <T> set(any: T?)
+
v1.0
first
- method
setNull fun setNull()
+
v1.0
first
null
。- method
setTrue fun setTrue()
+
v1.0
first
true
。- method
setFalse fun setFalse()
+
v1.0
first
false
。Yuki Hook API
- class
PackageParam open class PackageParam internal constructor(internal var wrapper: PackageParamWrapper?)
+
v1.0
first
- field
appClassLoader val appClassLoader:ClassLoader
+
v1.0
first
ClassLoader
。- field
appInfo val appInfo: ApplicationInfo
+
v1.0
first
ApplicationInfo
。- field
appUserId val appUserId: Int
+
v1.1.0
added
0
,应用双开 (分身) 或工作资料因系统环境不同 ID 也各不相同。- field
appContext val appContext: Application?
+
v1.0.72
added
v1.1.0
modified
Application
。- field
appResources val appResources:Resources?
+
v1.0.80
added
v1.1.0
modified
- field
systemContext val systemContext: Context
+
v1.1.0
added
Context
。- field
processName val processName: String
+
v1.0
first
- field
packageName val packageName: String
+
v1.0
first
- field
isFirstApplication val isFirstApplication: Boolean
+
v1.0
first
Application
。- field
mainProcessName val mainProcessName: String
+
v1.0.70
added
packageName
。- field
moduleAppFilePath val moduleAppFilePath: String
+
v1.0.80
added
- field
moduleAppResources val moduleAppResources: YukiModuleResources
+
v1.0.80
added
Resources
。- field
prefs val prefs: YukiHookModulePrefs
+
v1.0
first
- method
prefs fun prefs(name: String): YukiHookModulePrefs
+
v1.0
first
v1.0.80
modified
name
来自定义 Sp 存储的名称。- field
dataChannel val dataChannel: YukiHookDataChannel.NameSpace
+
v1.0.88
added
- method
resources fun resources(): HookResources
+
v1.0.80
added
YukiResources
对象。HookResources.hook
方法开始 Hook。- method
refreshModuleAppResources fun refreshModuleAppResources()
+
v1.0.87
added
Resources
。- method
onAppLifecycle inline fun onAppLifecycle(initiate: AppLifecycle.() -> Unit)
+
v1.0.88
added
- method
loadApp inline fun loadApp(name: String, initiate: PackageParam.() -> Unit)
+
fun loadApp(name: String, hooker: YukiBaseHooker)
+
v1.0
first
v1.0.80
modified
name
为 APP 的包名,后方的两个参数一个可作为 lambda
方法体使用,一个可以直接装载子 Hooker。loadZygote
。loadSystem
。loadApp
的 lambda
方法体形式或直接装载一个 Hooker。// 使用 lambda
+loadApp(name = "com.example.test") {
+ // Your code here.
+}
+// 使用 Hooker
+loadApp(name = "com.example.test", CustomHooker)
+
name
参数,则此方法体默认会过滤当前系统中全部可被 Hook 的 APP。// 使用 lambda
+loadApp {
+ // Your code here.
+}
+// 使用 Hooker
+loadApp(hooker = CustomHooker)
+
- method
loadZygote inline fun loadZygote(initiate: PackageParam.() -> Unit)
+
fun loadZygote(hooker: YukiBaseHooker)
+
v1.0.80
added
lambda
方法体使用,一个可以直接装载子 Hooker。- method
loadSystem inline fun loadSystem(initiate: PackageParam.() -> Unit)
+
fun loadSystem(hooker: YukiBaseHooker)
+
v1.0.82
added
lambda
方法体使用,一个可以直接装载子 Hooker。- method
withProcess inline fun withProcess(name: String, initiate: PackageParam.() -> Unit)
+
fun withProcess(name: String, hooker: YukiBaseHooker)
+
v1.0.70
added
name
为 APP 的进程名称,后方的两个参数一个可作为 lambda
方法体使用,一个可以直接装载子 Hooker。- method
loadHooker fun loadHooker(hooker: YukiBaseHooker)
+
v1.0
first
hooker
在 Hooker 中继续装载 Hooker。- method
searchClass inline fun searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
v1.1.0
added
appClassLoader
按指定条件查找并得到当前 Hook APP Dex 中的 Class
。String+VariousClass.clazz - i-ext-field
v1.0
first
v1.1.0
deprecated
toClass(...)
方法String.hasClass - i-ext-field
v1.0
first
v1.1.0
deprecated
hasClass(...)
方法- i-ext-method
String+VariousClass.toClass fun String.toClass(loader: ClassLoader?): Class<*>
+
fun VariousClass.toClass(loader: ClassLoader?): Class<*>
+
v1.1.0
added
VariousClass
转换为 loader
中的实体类。appClassLoader
装载目标 Class
。String
类型的 Class
包名转为 Class
实例。"com.example.demo.DemoClass".toClass()
+
loader
参数传入你自定义的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
VariousClass
,并转换为实体类。VariousClass
会枚举所有设置的 Class
并最终获得第一个存在的 Class
。VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass()
+
loader
参数传入你自定义的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass(customClassLoader)
+
- i-ext-method
String+VariousClass.toClassOrNull fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
+
fun VariousClass.toClassOrNull(loader: ClassLoader?): Class<*>?
+
v1.1.0
added
VariousClass
转换为 loader
中的实体类。appClassLoader
装载目标 Class
。Class
会返回 null
,不会抛出异常。- i-ext-method
String.hasClass fun String.hasClass(loader: ClassLoader?): Boolean
+
v1.1.0
added
appClassLoader
装载目标 Class
。if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
loader
参数,默认为 appClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
- method
findClass fun findClass(name: String, loader: ClassLoader?): HookClass
+
fun findClass(vararg name: String, loader: ClassLoader?): VariousClass
+
v1.0
first
v1.0.1
modified
方法findClass(various: VariousClass)
v1.1.0
modified
loader
参数Class
。Class
。Class
完整包名+名称填入 name
中。findClass(name = "com.example.demo.DemoClass")
+
Class
以及不同名称,你可以将多个完整包名+名称填入 name
中。findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
+
VariousClass
,将 Class
的完整包名+名称填入 VariousClass
的 name
中并填入 various
参数中。val variousClass = VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
+
Class
不属于 appClassLoader
,你可以使用 loader
参数指定你要装载的 ClassLoader
。val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
+findClass(name = "com.example.demo.OutsideClass", loader = outsideLoader)
+
Class
以及不同名称时,也可以使用 loader
参数指定你要装载的 ClassLoader
。val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
+findClass("com.example.demo.OutsideClass1", "com.example.demo.OutsideClass2", "com.example.demo.OutsideClass3", loader = outsideLoader)
+
- i-ext-method
String+Class+VariousClass+HookClass.hook inline fun String.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun Class<*>.hook(isForceUseAbsolute: Boolean, initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun VariousClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun HookClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
v1.0
first
v1.0.1
modified
VariousClass
的直接调用 hook
方法v1.0.2
modified
String
的直接调用 hook
方法v1.0.3
modified
YukiMemberHookCreator.Result
返回值v1.0.70
modified
isUseAppClassLoader
参数v1.0.80
modified
v1.1.0
modified
参数isUseAppClassLoader
isForceUseAbsolute
参数到 Class.hook
方法HookClass
实例进行创建。"com.example.demo.DemoClass".hook {
+ // Your code here.
+}
+
+
findClass
得到 HookClass
实例进行创建。findClass(name = "com.example.demo.DemoClass").hook {
+ // Your code here.
+}
+
stub
或直接拿到 Class
实例进行创建。Class
实例转换为类名并绑定到 appClassLoader
,若失败,则会使用原始 Class
实例直接进行 Hook。Stub::class.java.hook {
+ // Your code here.
+}
+
Class
不在 appClassLoader
且自动匹配无法找到该 Class
,请启用 isForceUseAbsolute
。YourClass::class.java.hook(isForceUseAbsolute = true) {
+ // Your code here.
+}
+
VariousClass
实例进行创建。VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
+ // Your code here.
+}
+
findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
+ // Your code here.
+}
+
- i-ext-method
HookResources.hook inline fun HookResources.hook(initiate: YukiResourcesHookCreator.() -> Unit)
+
v1.0.80
added
resources
对象,然后调用 hook
方法开始 Hook。resources().hook {
+ // Your code here.
+}
+
findClass(...).hook
做到统一,使得调用起来逻辑不会混乱。- class
AppLifecycle inner class AppLifecycle internal constructor()
+
v1.0.88
added
- method
attachBaseContext fun attachBaseContext(result: (baseContext: Context, hasCalledSuper: Boolean) -> Unit)
+
v1.0.88
added
Application.attachBaseContext
。- method
onCreate fun onCreate(initiate: Application.() -> Unit)
+
v1.0.88
added
Application.onCreate
。- method
onTerminate fun onTerminate(initiate: Application.() -> Unit)
+
v1.0.88
added
Application.onTerminate
。- method
onLowMemory fun onLowMemory(initiate: Application.() -> Unit)
+
v1.0.88
added
Application.onLowMemory
。- method
onTrimMemory fun onTrimMemory(result: (self: Application, level: Int) -> Unit)
+
v1.0.88
added
Application.onTrimMemory
。- method
onConfigurationChanged fun onConfigurationChanged(result: (self: Application, config: Configuration) -> Unit)
+
v1.0.88
added
Application.onConfigurationChanged
。- method
registerReceiver fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
+
v1.0.88
added
Yuki Hook API
- kt
ComponentTypeFactory v1.0
first
Android
相关组件的 Class
内容,跟随版本更新会逐一进行增加。Yuki Hook API
- kt
GraphicsTypeFactory v1.0
first
Android
相关 Graphics
的 Class
内容,跟随版本更新会逐一进行增加。Yuki Hook API
- kt
ViewTypeFactory v1.0
first
Android
相关 Widget
的 Class
内容,跟随版本更新会逐一进行增加。Yuki Hook API
- kt
DefinedTypeFactory v1.1.0
added
- field
VagueType val VagueType: Class<*>
+
v1.1.0
added
Yuki Hook API
- kt
VariableTypeFactory v1.0
first
Java
相关基本变量类型的 Class
内容,跟随版本更新会逐一进行增加。Yuki Hook API
- class
ModuleApplication open class ModuleApplication: Application()
+
v1.0.77
added
YukiHookAPI
Xposed 模块实现中的一个扩展功能。Application
中继承此类。AndroidManifest.xml
的 application
标签中指定此类。appContext
YukiHookAPI.Config
以确保 YukiHookAPI.Configs.debugTag
不需要重复定义YukiHookDataChannel
进行通讯YukiHookAPI.Status.isTaiChiModuleActive
判断太极、无极激活状态Application
上。package com.demo
+
+class MyApplication: ModuleApplication() {
+
+ override fun onCreate() {
+ super.onCreate()
+ }
+}
+
AndroidManifest.xml
的 application
标签中指定自定义的 Application
。<application
+ android:name="com.demo.MyApplication"
+ ...>
+
Application
可以直接将 ModuleApplication
设置到 AndroidManifest.xml
的 application
标签中。<application
+ android:name="com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication"
+ ...>
+
- field
appContext val appContext: ModuleApplication
+
v1.0.77
added
Application
实例。Yuki Hook API
- class
YukiModuleResources class YukiModuleResources private constructor(private val baseInstance: XModuleResources) : Resources
+
v1.0.80
added
XModuleResources
的中间层实例。- method
fwd fun fwd(resId: Int): YukiResForwarder
+
v1.0.80
added
XModuleResources.fwd
方法。YukiResForwarder
与 XResForwarder
实例。Yuki Hook API
- class
YukiResForwarder class YukiResForwarder private constructor(private val baseInstance: XResForwarder)
+
v1.0.80
added
XResForwarder
的中间层实例。instance - field
v1.0.80
added
v1.1.0
deprecated
instance
参数- field
id val id: Int
+
v1.0.80
added
- field
resources val resources: Resources
+
v1.0.80
added
Yuki Hook API
- class
YukiResources class YukiResources private constructor(private val baseInstance: XResources) : Resources
+
v1.0.80
added
XResources
的中间层实例。- class
LayoutInflatedParam class LayoutInflatedParam(internal val baseParam: XC_LayoutInflated.LayoutInflatedParam)
+
v1.0.80
added
- field
variantName val variantName: String
+
v1.0.80
added
layout
、layout-land
、layout-sw600dp
。- field
currentView val currentView: View
+
v1.0.80
added
- method
findViewByIdentifier inline fun <reified T : View> View.findViewByIdentifier(name: String): T?
+
inline fun <reified T : View> findViewByIdentifier(name: String): T?
+
v1.0.80
added
View
。View
。Yuki Hook API
- object
YukiXposedEvent object YukiXposedEvent
+
v1.0.80
first
- method
events inline fun events(initiate: YukiXposedEvent.() -> Unit)
+
v1.0.80
added
YukiXposedEvent
创建一个方法体。- method
onInitZygote fun onInitZygote(result: (StartupParam) -> Unit)
+
v1.0.80
added
- method
onHandleLoadPackage fun onHandleLoadPackage(result: (LoadPackageParam) -> Unit)
+
v1.0.80
added
- method
onHandleInitPackageResources fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
+
v1.0.80
added
Yuki Hook API
- class
YukiHookDataChannel class YukiHookDataChannel private constructor()
+
v1.0.88
added
BroadcastReceiver
来实现数据的交互。Application
继承于 ModuleApplication
来实现此功能。- class
NameSpace inner class NameSpace internal constructor(private val context: Context?, private val packageName: String, private val isSecure: Boolean)
+
v1.0.88
added
v1.0.90
modified
isSecure
参数YukiHookDataChannel
命名空间。- method
with inline fun with(initiate: NameSpace.() -> Unit): NameSpace
+
v1.0.88
added
- method
put fun <T> put(key: String, value: T)
+
fun <T> put(data: ChannelData<T>, value: T?)
+
fun put(vararg data: ChannelData<*>)
+
v1.0.88
added
- method
put fun put(key: String)
+
v1.0.88
added
VALUE_WAIT_FOR_LISTENER
发送键值数据。- method
wait fun <T> wait(key: String, result: (value: T) -> Unit)
+
fun <T> wait(data: ChannelData<T>, result: (value: T) -> Unit)
+
v1.0.88
added
v1.0.90
modified
value
- method
wait fun wait(key: String, callback: () -> Unit)
+
v1.0.88
added
- method
checkingVersionEquals fun checkingVersionEquals(result: (Boolean) -> Unit)
+
v1.0.88
added
Yuki Hook API
- class
ChannelData data class ChannelData<T>(var key: String, var value: T?)
+
v1.0.88
added
YukiHookDataChannel
的一个扩展用法。object DataConst {
+
+ val TEST_KV_DATA_1 = ChannelData("test_data_1", "defalut value")
+ val TEST_KV_DATA_2 = ChannelData("test_data_2", 0)
+}
+
// 从指定包名的宿主获取
+dataChannel(packageName = "com.example.demo").wait(DataConst.TEST_KV_DATA_1) { value ->
+ // Your code here.
+}
+// 发送给指定包名的宿主 - 未填写 value 时将使用模板提供的默认值
+dataChannel(packageName = "com.example.demo").put(DataConst.TEST_KV_DATA_1, value = "sending value")
+
// 从模块获取
+dataChannel.wait(DataConst.TEST_KV_DATA_1) { value ->
+ // Your code here.
+}
+// 发送给模块 - 未填写 value 时将使用模板提供的默认值
+dataChannel.put(DataConst.TEST_KV_DATA_1, value = "sending value")
+
// 获取 - 此时 value 取到的默认值将会是 2 - 并不是模板提供的 0
+dataChannel.wait(DataConst.TEST_KV_DATA_2, value = 2) { value ->
+ // Your code here.
+}
+
Yuki Hook API
- class
ModuleAppActivity open class ModuleAppActivity : Activity()
+
v1.1.0
added
Activity
。Activity
可以同时在宿主与模块中启动。Context.registerModuleAppActivities
进行注册。Yuki Hook API
- class
ModuleAppCompatActivity open class ModuleAppCompatActivity : AppCompatActivity()
+
v1.1.0
added
AppCompatActivity
。Activity
可以同时在宿主与模块中启动。Context.registerModuleAppActivities
进行注册。moduleTheme
设置 AppCompat 主题,否则会无法启动。- field
moduleTheme open val moduleTheme: Int
+
v1.1.0
added
Activity
主题。Yuki Hook API
- class
ModuleContextThemeWrapper class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) : ContextThemeWrapper
+
v1.1.0
added
ContextThemeWrapper
。- method
applyConfiguration fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
+
v1.1.0
added
ModuleContextThemeWrapper
的 Configuration
。Resources.updateConfiguration
。Yuki Hook API
- class
YukiHookModulePrefs class YukiHookModulePrefs private constructor(private var context: Context?)
+
v1.0
first
SharedPreferences
和 XSharedPreferences
。AndroidManifests.xml
中将 xposedminversion
最低设置为 93
。API
降至 26
以下,YukiHookAPI
将会尝试使用 makeWorldReadable
但仍有可能不成功。PreferenceFragmentCompat
,请迁移到 ModulePreferenceFragment
以适配上述功能特性。xposedminversion
最低设置为 93
,你可以在 AndroidManifest.xml
中添加 xposedsharedprefs
来实现支持。<meta-data
+ android:name="xposedsharedprefs"
+ android:value="true"/>
+
- field
isXSharePrefsReadable val isXSharePrefsReadable: Boolean
+
v1.0.90
added
XSharedPreferences
是否可读。- field
isRunInNewXShareMode val isRunInNewXShareMode: Boolean
+
v1.0.78
added
YukiHookModulePrefs
是否正处于 EdXposed/LSPosed 的最高权限运行。- method
name fun name(name: String): YukiHookModulePrefs
+
v1.0
first
Activity
中的使用方法。modulePrefs("custom_name").getString("custom_key")
+
PackageParam
中的使用方法。prefs("custom_name").getString("custom_key")
+
- method
direct fun direct(): YukiHookModulePrefs
+
v1.0.5
added
YukiHookAPI.Configs.isEnableModulePrefsCache
。XSharedPreferences
下生效。- method
getString fun getString(key: String, value: String): String
+
v1.0
first
String
键值。- method
getStringSet fun getStringSet(key: String, value: Set<String>): Set<String>
+
v1.0.77
added
Set<String>
键值。- method
getBoolean fun getBoolean(key: String, value: Boolean): Boolean
+
v1.0
first
Boolean
键值。- method
getInt fun getInt(key: String, value: Int): Int
+
v1.0
first
Int
键值。- method
getLong fun getLong(key: String, value: Long): Long
+
v1.0
first
Long
键值。- method
getFloat fun getFloat(key: String, value: Float): Float
+
v1.0
first
Float
键值。- method
all fun all(): HashMap<String, Any?>
+
v1.0.77
added
- method
remove fun remove(key: String)
+
v1.0
first
key
的存储数据。- method
remove inline fun <reified T> remove(prefs: PrefsData<T>)
+
v1.0.67
added
PrefsData.key
的存储数据。- method
clear fun clear()
+
v1.0.77
added
- method
putString fun putString(key: String, value: String)
+
v1.0
first
String
键值。- method
putStringSet fun putStringSet(key: String, value: Set<String>)
+
v1.0.77
added
Set<String>
键值。- method
putBoolean fun putBoolean(key: String, value: Boolean)
+
v1.0
first
Boolean
键值。- method
putInt fun putInt(key: String, value: Int)
+
v1.0
first
Int
键值。- method
putLong fun putLong(key: String, value: Long)
+
v1.0
first
Long
键值。- method
putFloat fun putFloat(key: String, value: Float)
+
v1.0
first
Float
键值。- method
get inline fun <reified T> get(prefs: PrefsData<T>, value: T): T
+
v1.0.67
added
- method
put inline fun <reified T> put(prefs: PrefsData<T>, value: T)
+
v1.0.67
added
- method
clearCache fun clearCache()
+
v1.0.5
added
XSharedPreferences
中缓存的键值数据。YukiHookAPI.Configs.isEnableModulePrefsCache
。XSharedPreferences
重新读取。Yuki Hook API
- class
PrefsData data class PrefsData<T>(var key: String, var value: T)
+
v1.0.67
added
YukiHookModulePrefs
的一个扩展用法。object DataConst {
+
+ val TEST_KV_DATA_1 = PrefsData("test_data_1", "defalut value")
+ val TEST_KV_DATA_2 = PrefsData("test_data_2", false)
+ val TEST_KV_DATA_3 = PrefsData("test_data_3", 0)
+}
+
// 读取
+val data = modulePrefs.get(DataConst.TEST_KV_DATA_1)
+// 写入
+modulePrefs.put(DataConst.TEST_KV_DATA_1, "written value")
+
// 读取 String
+val dataString = prefs.get(DataConst.TEST_KV_DATA_1)
+// 读取 Boolean
+val dataBoolean = prefs.get(DataConst.TEST_KV_DATA_2)
+
// 读取 - 此时 data 取到的默认值将会是 2 - 并不是模板提供的 0
+val data = prefs.get(DataConst.TEST_KV_DATA_3, 2)
+
Yuki Hook API
- class
ModulePreferenceFragment abstract class ModulePreferenceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener
+
v1.0.78
added
YukiHookAPI
Xposed 模块实现中的一个扩展功能。PreferenceFragmentCompat
并对其实现了 Sp 存储在 Xposed 模块中的全局可读可写。PreferenceFragmentCompat
的实例中,将继承对象换成此类。onCreatePreferences
替换为 onCreatePreferencesInModuleApp
即可。ModulePreferenceFragment
创建一个 PreferenceFragmentCompat
对象。class SettingsFragment : ModulePreferenceFragment() {
+
+ override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(R.xml.settings_preferences, rootKey)
+ // Your code here.
+ }
+}
+
PreferenceFragmentCompat
保持一致。- method
onCreatePreferencesInModuleApp abstract fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?)
+
v1.0.78
added
onCreatePreferences
。- method
onSharedPreferenceChanged override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?)
+
v1.0.78
added
SharedPreferences.OnSharedPreferenceChangeListener
的原生监听功能。class SettingsFragment : ModulePreferenceFragment() {
+
+ override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
+ // ...
+ }
+
+ override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
+ super.onSharedPreferenceChanged(sharedPreferences, key)
+ // Your code here.
+ }
+}
+
Yuki Hook API
- interface
IYukiHookXposedInit interface IYukiHookXposedInit
+
v1.0
first
v1.0.80
modified
deprecated
名称但保留接口YukiHookXposedInitProxy
IYukiHookXposedInit
新名称- method
onInit fun onInit()
+
v1.0.5
added
YukiHookAPI.Configs
的初始化方法。- method
onHook fun onHook()
+
v1.0
first
- method
onXposedEvent fun onXposedEvent()
+
v1.0.80
added
YukiXposedEvent.onInitZygote
YukiXposedEvent.onHandleLoadPackage
YukiXposedEvent.onHandleInitPackageResources
YukiHookXposedInitProxy - interface
v1.0
first
v1.0.80
deprecated
IYukiHookXposedInit
Yuki Hook API
Host Resource Injection Extension
Activity
components, and Context
topics into the Host App.build.gradle
of the current Xposed Module project.android {
+ androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
+}
+
android {
+ aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
+}
+
Inject Module App's Resources
Context
obtained in the Hooker into the current Module App's Resources.injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ instance<Activity>().also {
+ // <Scenario 1> Inject Module App's Resources through Context
+ it.injectModuleAppResources()
+ // <Scenario 2> Get the Host App's Resources directly and inject the Module App's Resources
+ it.resources.injectModuleAppResources()
+ // Use the Module App's Resource Id directly
+ it.getString(R.id.app_name)
+ }
+ }
+}
+
AppLifecycle
.onAppLifecycle {
+ onCreate {
+ // Globally inject Module App's Resources, but only in the global lifecycle
+ // Methods like ImageView.setImageResource need to be injected separately in Activity
+ // <Scenario 1> Inject Module App's Resources through Context
+ injectModuleAppResources()
+ // <Scenario 2> Get the Host App's Resources directly and inject the Module App's Resources
+ resources.injectModuleAppResources()
+ // Use the Module App's Resource Id directly
+ getString(R.id.app_name)
+ }
+}
+
Register Module App's Activity
Activity
of all applications in the Android system starts, it needs to be registered in AndroidManifest.xml
.Activity
in the Module App through the Host App, what should we do?Activity
proxy of the current Module App in the Context
obtained in the Hooker.injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ instance<Activity>().registerModuleAppActivities()
+ }
+}
+
Activity
proxy directly in AppLifecycle
.onAppLifecycle {
+ onCreate {
+ registerModuleAppActivities()
+ }
+}
+
proxy
parameter is not filled in, the API will automatically obtain the current Host App's launching entry Activity
for proxying according to the current Context
.Activity
will add launching parameters to the registration list, so we need to use another solution.Activity
cannot be launched correctly, we can manually get the Host App's AndroidManifest.xml
for analysis to get a registered Activity
tag and get the name
.Activity
that may not be used by the current Host App as a "puppet" to proxy it, which usually works.Activity
that can be proxied.<activity
+ android:name="com.demo.test.activity.TestActivity"
+ ...>
+
name
, we only need to add this parameter to the method for registration.registerModuleAppActivities(proxy = "com.demo.test.activity.TestActivity")
+
stub
for the Host App's class, you can register it directly through the Class
object.registerModuleAppActivities(TestActivity::class.java)
+
Activity
in the Module App you need to use the Host App to start by ModuleAppActivity
or ModuleAppCompatActivity
.Activity
now live seamlessly in the Host App without registration.class HostTestActivity : ModuleAppActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Module App's Resources have been injected automatically
+ // You can directly use xml to load the layout
+ setContentView(R.layout.activity_main)
+ }
+}
+
ModuleAppCompatActivity
, you need to set the AppCompat theme manually.class HostTestActivity : ModuleAppCompatActivity() {
+
+ // The theme name here is for reference only
+ // Please fill in the theme name already in your Module App
+ override val moduleTheme get() = R.style.Theme_AppCompat
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Module App's Resources have been injected automatically
+ // You can directly use xml to load the layout
+ setContentView(R.layout.activity_main)
+ }
+}
+
startActivity
anywhere in the (Xposed) Host environment where a Context
exists.val context: Context = ... // Assume this is your Context
+context.startActivity(context, HostTestActivity::class.java)
+
Create ContextThemeWrapper Proxy
MaterialAlertDialogBuilder
to beautify our own dialogs in the Host App, but we can't create them without the AppCompat theme.The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
+
MaterialAlertDialogBuilder
to create a dialog in the current Activity
of the Host App being hooked, you can have the following methods.injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ // Use applyModuleTheme to create a theme resource in the current Module App
+ val appCompatContext = instance<Activity>().applyModuleTheme(R.style.Theme_AppCompat)
+ // Directly use this Context that wraps the Module App's theme to create a dialog
+ MaterialAlertDialogBuilder(appCompatContext)
+ .setTitle("AppCompat Theme Dialog")
+ .setMessage("I am an AppCompat theme dialog displayed in the Host App.")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+}
+
Context
through uiMode
.injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ // Define the theme resource in the current Module App
+ var appCompatContext: ModuleContextThemeWrapper
+ // <Scenario 1> Get the Configuration object directly to set
+ appCompatContext = instance<Activity>()
+ .applyModuleTheme(R.style.Theme_AppCompat)
+ .applyConfiguration { uiMode = Configuration.UI_MODE_NIGHT_YES }
+ // <Scenario 2> Create a new Configuration object
+ // This solution will destroy the original font scaling and other settings in the current Host App
+ // You need to manually re-pass parameters such as densityDpi
+ appCompatContext = instance<Activity>().applyModuleTheme(
+ theme = R.style.Theme_AppCompat,
+ configuration = Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES }
+ )
+ // Directly use this Context that wraps the Module App's theme to create a dialog
+ MaterialAlertDialogBuilder(appCompatContext)
+ .setTitle("AppCompat Theme Dialog")
+ .setMessage("I am an AppCompat theme dialog displayed in the Host App.")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+}
+
MaterialAlertDialogBuilder
.Yuki Hook API
Host Lifecycle Extension
Monitor Lifecycle
Application
, just use the following methods.loadApp(name = "com.example.demo") {
+ // Register lifecycle listeners
+ onAppLifecycle {
+ // You can implement lifecycle method listeners in Application here
+ attachBaseContext { baseContext, hasCalledSuper ->
+ // Determine whether
+ // The super.attachBaseContext(base) method has been executed by judging hasCalledSuper
+ // ...
+ }
+ onCreate {
+ // Get the current Application instance through this
+ // ...
+ }
+ onTerminate {
+ // Get the current Application instance through this
+ // ...
+ }
+ onLowMemory {
+ // Get the current Application instance through this
+ // ...
+ }
+ onTrimMemory { self, level ->
+ // Here you can judge whether the app has switched to the background
+ if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+ // ...
+ }
+ // ...
+ }
+ onConfigurationChanged { self, config ->
+ // ...
+ }
+ }
+}
+
Register System Broadcast
Application.onCreate
method to monitor system broadcast.Application
.loadApp(name = "com.example.demo") {
+ // Register lifecycle listeners
+ onAppLifecycle {
+ // Broadcast monitoring when the registered user is unlocked
+ registerReceiver(Intent.ACTION_USER_PRESENT) { context, intent ->
+ // ...
+ }
+ // Register multiple broadcast listeners, will call back multiple times at the same time
+ registerReceiver(Intent.ACTION_PACKAGE_CHANGED, Intent.ACTION_TIME_TICK) { context, intent ->
+ // ...
+ }
+ }
+}
+
Yuki Hook API
Debug Logs
YukiHookAPI
encapsulates a set of stable and efficient debugging log functions for developers. Normal Logs
loggerD
, loggerI
, loggerW
to print normal logs to the console.loggerD(msg = "This is a log")
+
YukiHookAPI
will call android.util.Log
and XposedBridge.log
to print this log at the same time.TAG
of the log is the value you set in YukiHookLogger.Configs.tag
.TAG
easily to prevent logs from being filtered.loggerD(tag = "YukiHookAPI", msg = "This is a log")
+
[YukiHookAPI][D][host package name]--> This is a log
+
LoggerType
to customize the type of log printing.android.util.Log
or XposedBridge.log
to print logs.LoggerType.BOTH
, which means that both methods are used to print logs.android.util.Log
to print logs.loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.LOGD)
+
XposedBridge.log
to print the log, this method can only be used in the (Xposed) Host environment.loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.XPOSEDBRIDGE)
+
loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
+
Error Logs
loggerE
to print E
level logs to the console.loggerE(msg = "This is an error")
+
E
level logs.// Assume this is the exception that was thrown
+val throwable = Throwable(...)
+// Print log
+loggerE(msg = "This is an error", e = throwable)
+
[YukiHookAPI][E][host package name]--> This is an error
+
java.lang.Throwable
+ at com.demo.Test.<init>(...)
+ at com.demo.Test.doTask(...)
+ at com.demo.Test.stop(...)
+ at com.demo.Test.init(...)
+ at a.a.a(...)
+ ... 3 more
+
LoggerType
to specify the method type currently used to print the log. Save Logs and Custom Elements
YukiHookLogger.saveToFile
method.// Please note
+// The saved file path must have read and write permissions
+// Otherwise an exception will be thrown
+YukiHookLogger.saveToFile("/sdcard/Documents/debug_log.log")
+
YukiHookLogger.contents
to get all the log file contents that have been printed so far.// Get the contents of all log files that have been printed so far
+val fileContent = YukiHookLogger.contents
+
YukiHookLogger.Configs.isRecord
to be enabled.YukiHookLogger.Configs.elements
to customize the elements that debug logs display externally.YukiHookAPI.Configs
to be configured in onInit
of the Hook entry class.override fun onInit() = configs {
+ debugLog {
+ // ...
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ // ...
+}
+
Yuki Hook API
Reflection Extensions
YukiHookAPI
encapsulates a set of reflection API with near-zero reflection writing for developers, which can almost completely replace the usage of reflection API in Java. Class Extensions
Object Conversion
Class
that cannot be called directly.Class
.// Class in the default ClassLoader environment
+var instance = Class.forName("com.demo.Test")
+// Specify the Class in the ClassLoader environment
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = customClassLoader?.loadClass("com.demo.Test")
+
YukiHookAPI
provides you with a syntactic sugar that can be used anywhere.YukiHookAPI
as follows.// Get this Class directly
+// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader
+var instance = "com.demo.Test".toClass()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = "com.demo.Test".toClass(customClassLoader)
+
Class
does not exist, using the above method will throw an exception.Class
exists, you can refer to the following solutions.// Get this Class directly
+// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader
+// If not available, the result will be null but no exception will be thrown
+var instance = "com.demo.Test".toClassOrNull()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+// If not available, the result will be null but no exception will be thrown
+var instance = "com.demo.Test".toClassOrNull(customClassLoader)
+
Class
object by mapping.// Assume this Class can be obtained directly
+var instance = classOf<Test>()
+// We can also customize the ClassLoader where the Class is located, which is very effective for stubs
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var instance = classOf<Test>(customClassLoader)
+
Existential Judgment
Class
exists.Class
to determine whether it exists by exception.// Class in the default ClassLoader environment
+var isExist = try {
+ Class.forName("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+// Specify the Class in the ClassLoader environment
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var isExist = try {
+ customClassLoader?.loadClass("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+
YukiHookAPI
provides you with a syntactic sugar that can be used anywhere.YukiHookAPI
as follows.// Check if this class exists
+// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader
+var isExist = "com.demo.Test".hasClass()
+// ClassLoader where the custom Class is located
+val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+var isExist = "com.demo.Test".hasClass(customClassLoader)
+
Beta
Vague Search Class
name in the Host App's Dex after being obfuscated by tools such as R8 will be difficult to distinguish.DexClassFinder
, its role is to determine the instance of this Class
by the bytecode features in the Class
that need to be searched. Get Started
Class
is what we want, the names are obfuscated and may be different in each version.package com.demo;
+
+public class a extends Activity implements Serializable {
+
+ public a(String var1) {
+ // ...
+ }
+
+ private String a;
+
+ private String b;
+
+ private boolean a;
+
+ protected void onCreate(Bundle var1) {
+ // ...
+ }
+
+ private static void a(String var1) {
+ // ...
+ }
+
+ private String a(boolean var1, String var2) {
+ // ...
+ }
+
+ private void a() {
+ // ...
+ }
+
+ public void a(boolean var1, a var2, b var3, String var4) {
+ // ...
+ }
+}
+
Class
, you can use the ClassLoader.searchClass
method directly.PackageParam
you can use the searchClass
method directly and it will automatically specify the appClassLoader
.searchClass {
+ // Start the search from the specified package name range
+ // In actual use, you can specify multiple package name ranges at the same time
+ from("com.demo")
+ // Specify the result of getSimpleName of the current Class
+ // You can directly make logical judgments on this string
+ // Here we are not sure whether its name is a, we can only judge the length of the string
+ simpleName { it.length == 1 }
+ // Specify the inherited parent class object
+ // If it is an existing stub, it can be directly represented by generics
+ extends<Activity>()
+ // Specify the inherited parent class object
+ // Which can be written directly as the full class name
+ // And you can also specify multiple objects at the same time
+ extends("android.app.Activity")
+ // Specify the implemented interface
+ // If it exists stub, can be directly represented by generics
+ implements<Serializable>()
+ // Specify the implemented interface
+ // Which can be written directly as a full class name, or you can specify multiple at the same time
+ 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)
+ // Specify the type and style of the variable
+ // And the number that exists in the current class count
+ field { type = StringType }.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)
+ // Directly specify the number of all variables that exist in the current class count
+ field().count(num = 3)
+ // If you think the number of variables is indeterminate
+ // You can also use the following custom conditions
+ field().count(1..3)
+ field().count { it >= 3 }
+ // Specify the type and style of the method
+ // And the number that exists in the current class count
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // Specify the modifier, and the number count in the current class
+ method {
+ modifiers { isStatic && isPrivate }
+ param(StringType)
+ 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
+ }.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() }
+ emptyParam()
+ returnType = UnitType
+ }.count(num = 1)
+ // Specify the type and style of the method
+ // As well as the modifier and VagueType
+ // And the number count that exists in the current class
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, VagueType, VagueType, StringType)
+ returnType = UnitType
+ }.count(num = 1)
+ // Directly specify the number of all methods that exist in the current class count
+ method().count(num = 5)
+ // If you think the number of methods is uncertain, you can also use the following custom conditions
+ method().count(1..5)
+ method().count { it >= 5 }
+ // Directly specify the number of all members existing in the current class count
+ // Members include: Field, Method, Constructor
+ member().count(num = 9)
+ // There must be a static modifier in all members, you can add this condition like this
+ member {
+ modifiers { isStatic }
+ }
+}.get() // Get the instance of this Class itself, if not found, it will return null
+
Asynchronous Search
DexClassFinder
will use synchronous mode to search Class
, which will block the current thread until it finds or finds an exception.async = true
, which will not require you to start a thread again, the API has already handled the related problems for you.searchClass(async = true) {
+ // ...
+}.wait { class1 ->
+ // Get asynchronous result
+}
+searchClass(async = true) {
+ // ...
+}.wait { class2 ->
+ // Get asynchronous result
+}
+
Local Cache
name
parameter.SharedPreferences
, which will be saved to the Host App's data directory and will be re-cached after the Host App's version is updated.async = true
will be set at the same time, you don't need to set it manually.searchClass(name = "com.demo.class1") {
+ // ...
+}.wait { class1 ->
+ // Get asynchronous result
+}
+searchClass(name = "com.demo.class2") {
+ // ...
+}.wait { class2 ->
+ // Get asynchronous result
+}
+
// Call it directly
+// It may fail when the Host App's appContext is null, and a warning message will be printed on failure
+DexClassFinder.clearCache()
+// Called after listening to the lifecycle of the Host App
+onAppLifecycle {
+ onCreate {
+ DexClassFinder.clearCache(context = this)
+ }
+}
+
// Call it directly
+// It may fail when the Host App's appContext is null, and a warning message will be printed on failure
+DexClassFinder.clearCache(versionName = "1.0", versionCode = 1)
+// Called after listening to the lifecycle of the Host App
+onAppLifecycle {
+ onCreate {
+ DexClassFinder.clearCache(context = this, versionName = "1.0", versionCode = 1)
+ }
+}
+
Multiple Search
Class
at the same time using a fixed condition, then you only need to use the all
or waitAll
method to get the result.// Synchronous search, use all to get all the results found by the conditions
+searchClass {
+ // ...
+}.all().forEach { clazz ->
+ // Get each result
+}
+// Synchronous search, using all { ... } to iterate over each result
+searchClass {
+ // ...
+}.all { clazz ->
+ // Get each result
+}
+// Asynchronous search, use waitAll to get all the results found by the conditions
+searchClass(async = true) {
+ // ...
+}.waitAll { classes ->
+ classes.forEach {
+ // Get each result
+ }
+}
+
Member Extensions
Class
.package com.demo;
+
+public class BaseTest {
+
+ public BaseTest() {
+ // ...
+ }
+
+ public BaseTest(boolean isInit) {
+ // ...
+ }
+
+ private void doBaseTask(String taskName) {
+ // ...
+ }
+}
+
package com.demo;
+
+public class Test extends BaseTest {
+
+ public Test() {
+ // ...
+ }
+
+ public Test(boolean isInit) {
+ // ...
+ }
+
+ private static TAG = "Test";
+
+ private BaseTest baseInstance;
+
+ private String a;
+
+ private boolean a;
+
+ private boolean isTaskRunning = false;
+
+ private static void init() {
+ // ...
+ }
+
+ private void doTask(String taskName) {
+ // ...
+ }
+
+ private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
+ // ...
+ }
+
+ private void stop() {
+ // ...
+ }
+
+ private String getName() {
+ // ...
+ }
+
+ private void b() {
+ // ...
+ }
+
+ private void b(String a) {
+ // ...
+ }
+}
+
Find and Reflection
doTask
method of Test
and execute it.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using reflection API
+Test::class.java
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(instance, "task_name")
+
YukiHookAPI
provides you with a syntactic sugar that can be used anywhere.YukiHookAPI
as follows.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doTask"
+ param(StringType)
+}.get(instance).call("task_name")
+
isTaskRunning
field can also be written as follows.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.field {
+ name = "isTaskRunning"
+ type = BooleanType
+}.get(instance).any() // Any instantiates an object of any type of Field
+
Class
constructor, the same can be achieved.Test::class.java.constructor {
+ param(BooleanType)
+}.get().call(true) // Can create a new instance
+
Class
, you can write it as follows.Test::class.java.constructor().get().call() // Create a new instance
+
Optional Find Conditions
getName
method in Class
, which can be implemented as follows.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+ returnType = StringType
+}.get(instance).string() // Get the result of the method
+
getName
in this Class
, so can we make it simpler?// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+}.get(instance).string() // Get the result of the method
+
get
or wait
methods to get results, YukiHookAPI
will match the first found result in bytecode order by default.Class
has a release
method, but its method parameters are very long, and some types may not be directly available.param(...)
to find this method, but is there an easier way.paramCount
to find the method.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "release"
+ // At this point
+ // We don't have to determine the specific type of method parameters, just write the number
+ paramCount = 3
+}.get(instance) // Get this method
+
VagueType
to fill in the method parameter type that you do not want to fill in.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+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)
+}.get(instance) // Get this method
+
Find in Super Class
Test
extends BaseTest
, now we want to get the doBaseTask
method of BaseTest
, how do we do it without knowing the name of the super class?superClass
to the find conditions to achieve this function.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringType)
+ // Just add this condition
+ superClass()
+}.get(instance).call("task_name")
+
superClass
has a parameter isOnlySuperClass
, when set to true
, you can skip the current Class
and only find the super class of the current Class
.doBaseTask
method only exists in the super class, this condition can be added to save finding time.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringType)
+ // Add a find condition
+ superClass(isOnlySuperClass = true)
+}.get(instance).call("task_name")
+
superClass
is set, it will automatically cycle backward to find out whether this method exists in all extends super classes, until it finds that the target has no super class (the extends is java.lang.Object
). Vague Find
doTask
method in Class
, which can be implemented as follows.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name {
+ // Set name is case insensitive
+ it.equals("dotask", isIgnoreCase = true)
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
doTask
method in Class
, we can also judge that the method name contains only the characters specified in it.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name {
+ // Only contains oTas
+ it.contains("oTas")
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name {
+ // Contains do at the beginning and Task at the end
+ it.startsWith("do") && it.endsWith("Task")
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name {
+ // Start with do, end with Task, just letters
+ it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters()
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
Multiple Find
Class
.get
with all
to get all the bytecodes that match the condition.Class
with the number of method parameters in the range 1..3
, you can use the following implementation.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ paramCount(1..3)
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
private void doTask(String taskName)
private void release(String taskName, Function<boolean, String> task, boolean isFinish)
private void b(String a)
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ paramCount { it < 3 }
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
private static void init()
private void doTask(String taskName)
private void stop(String a)
private void getName(String a)
private void b()
private void b(String a)
b
in Class
, you can use the following implementation.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHook API
+Test::class.java.method {
+ name = "b"
+}.all(instance).forEach { instance ->
+ // Call and execute each method
+ instance.call(...)
+}
+
private void b()
private void b(String a)
Static Bytecode
Class
, at this time, we can call them without passing in an instance.TAG
this time.Test::class.java.field {
+ name = "TAG"
+ type = StringType
+}.get().string() // The type of Field is string and can be cast directly
+
TAG
field with the same name in Class
, what should I do at this time?Test::class.java.field {
+ name = "TAG"
+ type = StringType
+ // 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
+
init
.Test::class.java.method {
+ name = "init"
+ emptyParam()
+}.get().call()
+
Test::class.java.method {
+ name = "init"
+ emptyParam()
+ // This method of identity find needs to be static
+ modifiers { isStatic }
+}.get().call()
+
Obfuscated Bytecode
Class
given here has two obfuscated field names, both of which are a
, how do we get them at this time?// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.field {
+ name = "a"
+ type = BooleanType
+}.get(instance).any() // Get a field named a with type Boolean
+
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.field {
+ type(BooleanType).index().first()
+}.get(instance).any() // Get the first field of type Boolean
+
private boolean a
can be obtained.Class
, both of which are b
.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "b"
+ param(StringType)
+}.get(instance).call("test_string") // Get the method whose name is b and whose parameter is [String]
+
// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ param(StringType).index().first()
+}.get(instance).call("test_string") // Get the method whose first method parameter is [String]
+
Class
, then we have an alternative.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ order().index().last()
+}.get(instance).call("test_string") // Get the last method of the current Class
+
Directly Called
get(instance)
to call the corresponding method.current
method on any instance to create a call space.// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // Execute the doTask method
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+ // Execute the stop method
+ method {
+ name = "stop"
+ emptyParam()
+ }.call()
+ // Get name
+ val name = method { name = "getName" }.string()
+}
+
superClass
to call methods of the current Class
super class.// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // Execute the doBaseTask method of the parent class
+ superClass().method {
+ name = "doBaseTask"
+ param(StringType)
+ }.call("task_name")
+}
+
current()
method directly.// Assuming this is an instance of this Class, this Class cannot be obtained directly
+val instance = Test()
+// Execute the doTask method
+instance
+ .current()
+ .method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+// Execute the stop method
+instance
+ .current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// Get name
+val name = instance.current().method { name = "getName" }.string()
+
// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+}.current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// ❗ Note that because current() returns the CurrentClass object itself
+// It CANNOT BE CALLED like the following
+instance.current().current()
+
Field
instances, there is also a convenience method that can directly get the object of the instance where Field
is located.// Assume this is an instance of this Class
+val instance = Test()
+// Assume this Class is not directly available
+instance.current {
+ // <Plan 1>
+ field {
+ name = "baseInstance"
+ }.current {
+ method {
+ name = "doBaseTask"
+ param(StringType)
+ }.call("task_name")
+ }
+ // <Plan 2>
+ field {
+ name = "baseInstance"
+ }.current()
+ ?.method {
+ name = "doBaseTask"
+ param(StringType)
+ }?.call("task_name")
+}
+
Test(true).doTask("task_name")
+
"com.demo.Test".toClass()
+ .getDeclaredConstructor(Boolean::class.java)
+ .apply { isAccessible = true }
+ .newInstance(true)
+ .apply {
+ javaClass
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(this, "task_name")
+ }
+
buildOf
method to create an instance."com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+}
+
buildOf
method to return the type of the current instance, you can include a type-generic declaration in it instead of using as
to cast
the target type.// Assume this Class can be obtained directly
+val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
+test.doTask("task_name")
+
Original Called
XposedBridge
provides us with a XposedBridge.invokeOriginalMethod
function.YukiHookAPI
you can use the following method to implement this function conveniently.Class
we want to demonstrate.public class Test {
+
+ public static String getString() {
+ return "Original";
+ }
+}
+
getString
method in this Class
Hooks.Test::class.java.hook {
+ injectMember {
+ method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+ }
+ replaceTo("Hooked")
+ }
+}
+
"Hooked"
.// Result will be "Hooked"
+val result = Test::class.java.method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+}.get().string()
+
original
to the result.// Result will be "Original"
+val result = Test::class.java.method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+}.get().original().string()
+
Find Again
Class
, all of which are the same Class
for different versions of this Host App.doTask
in it, assuming they function the same.public class Test {
+
+ public void doTask() {
+ // ...
+ }
+}
+
public class Test {
+
+ public void doTask(String taskName) {
+ // ...
+ }
+}
+
public class Test {
+
+ public void doTask(String taskName, int type) {
+ // ...
+ }
+}
+
doTask
method in a different version, how do we do it?RemedyPlan
to complete your needs.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+ method {
+ name = "doTask"
+ param(StringType, IntType)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+}.wait(instance) {
+ // Get the result of the method
+}
+
RemedyPlan
while using Multiple Find.// Assume this is an instance of this Class
+val instance = Test()
+// Call and execute using YukiHookAPI
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }.onFind {
+ // Found logic can be implemented here
+ }
+}.waitAll(instance) {
+ // Get the result of the method
+}
+
Class
as an example, if Multiple Find is used in conjunction with RemedyPlan
when creating a Hook, you need to change the usage slightly.injectMember {
+ method {
+ name = "doTask"
+ emptyParam()
+ }.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }
+ }.all()
+ beforeHook {}
+ afterHook {}
+}
+
Relative Matching
Class
with the same function in different versions of the Host App but only the name of the Class
is different.public class ATest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
public class BTest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
doTask
method in this Class
in each version?Class
exists.// First find this Class
+val currentClass =
+ if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass()
+// Then look for this method and call
+currentClass.method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
YukiHookAPI
provides you with a very convenient VariousClass
to solve this problem.Class
directly using the following methods.VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
exists in the specified ClassLoader
, you can fill in your ClassLoader
in get
.val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
will be matched, you can use the getOrNull
method.val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
+ name = "doTask"
+ emptyParam()
+}?.get()?.call()
+
Class
of the (Xposed) Host environment in PackageParam
, you can use toClass()
to set it directly.VariousClass("com.demo.ATest", "com.demo.BTest").toClass().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
cannot be found.findClass("com.demo.ATest", "com.demo.BTest").hook {
+ // Your code here.
+}
+
Class
as a constant type to use.// Define constant type
+val ABTestClass = VariousClass("com.demo.ATest", "com.demo.BTest")
+// Use directly
+ABTestClass.hook {
+ // Your code here.
+}
+
Calling Generics
YukiHookAPI
also provides a syntactic sugar that can be used anywhere.class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // ...
+ }
+}
+
Class
instance of the generic T
or R
in the current Class
, only the following implementation is required.class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // Get the operation object of the current instance
+ // Get the Class instance of T, in the 0th position of the parameter
+ // The default value can not be written
+ val tClass = current().generic()?.argument()
+ // Get the Class instance of R, in parameter 1
+ val rClass = current().generic()?.argument(index = 1)
+ // You can also use the following syntax
+ current().generic {
+ // Get the Class instance of T
+ // In the 0th position of the parameter, the default value can be left blank
+ val tClass = argument()
+ // Get the Class instance of R, in parameter 1
+ val rClass = argument(index = 1)
+ }
+ }
+}
+
Class
externally, it can be implemented as follows.// Assume this is the Class of T
+class TI {
+
+ fun foo() {
+ // ...
+ }
+}
+// Assume this is an instance of T
+val tInstance: TI? = ...
+// Get the Class instance of T
+// In the 0th position of the parameter, the default value can be left blank
+// And get the method foo and call it
+TestGeneric::class.java.generic()?.argument()?.method {
+ name = "foo"
+ emptyParam()
+}?.get(tInstance)?.invoke<TI>()
+
Pay Attention of Trap
Restrictive Find Conditions
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ // ❗ Wrong usage, please keep only one index method
+ returnType(StringType).index(num = 1)
+}
+
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ order().index(num = 1)
+}
+
Necessary Find Conditions
Class
.public class TestFoo {
+
+ public void foo(String string) {
+ // ...
+ }
+
+ public void foo() {
+ // ...
+ }
+}
+
public void foo()
method, which can be written as follows.TestFoo::class.java.method {
+ name = "foo"
+}
+
foo
methods in this Class
, one of which takes a method parameter.param
, the result will be the first method public void foo(String string)
that matches the name and matches the bytecode order, not the last method we need.TestFoo::class.java.method {
+ name = "foo"
+ // ✅ Correct usage, add detailed filter conditions
+ emptyParam()
+}
+
public void foo()
method. Abbreviated Find Conditions
Class
.public class TestFoo {
+
+ public TestFoo() {
+ // ...
+ }
+}
+
public TestFoo()
constructor, which can be written as follows.TestFoo::class.java.constructor { emptyParam() }
+
public TestFoo()
constructor, but it feels a bit cumbersome.name
, when the constructor has no parameters, we can omit the emptyParam
parameter.TestFoo::class.java.constructor()
+
Bytecode Type
Boolean
and cast it to String
.field {
+ name = "test"
+ type = BooleanType
+}.get().string() // ❗ Wrong usage, must be cast to the bytecode target type
+
field {
+ name = "test"
+ type = BooleanType
+}.get().boolean().toString() // ✅ The correct way to use, get the type and then convert
+
Common Type Extensions
field {
+ name = "test"
+ type = Boolean::class.java
+}
+
Boolean::class.java
in Kotlin
is very long and not convenient.YukiHookAPI
encapsulates common type calls for developers, including Android's basic types and Java's basic types.field {
+ name = "test"
+ type = BooleanType
+}
+
IntType
, FloatType
.String[]
.java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
to get this type.ArrayClass(StringType)
to get this type.String
is a common type, you can also directly use StringArrayClass
to get this type.onCreate
method needs to find the Bundle::class.java
type.method {
+ name = "onCreate"
+ param(BundleClass)
+}
+
Yuki Hook API
Xposed Module and Host Channel
Basic Usage
wait
and put
methods is described here.dataChannel
to realize the communication bridge between the Module App and the Host App, the principle is to send and receive system out-of-order broadcasts.// Get from the Host App of the specified package name
+dataChannel(packageName = "com.example.demo").wait<String>(key = "key_from_host") { value ->
+ // Your code here.
+}
+// Send to the Host App with the specified package name
+dataChannel(packageName = "com.example.demo").put(key = "key_from_module", value = "I am module")
+
// Get from the Module App
+dataChannel.wait<String>(key = "key_from_module") { value ->
+ // Your code here.
+}
+// Send to the Module App
+dataChannel.put(key = "key_from_host", value = "I am host")
+
value
of dataChannel
unset to only notify the Module App or Host App to call back the wait
method.// Get from the Host App of the specified package name
+dataChannel(packageName = "com.example.demo").wait(key = "listener_from_host") {
+ // Your code here.
+}
+// Send to the Host App with the specified package name
+dataChannel(packageName = "com.example.demo").put(key = "listener_from_module")
+
// Get from the Module App
+dataChannel.wait(key = "listener_from_module") {
+ // Your code here.
+}
+// Send to the Module App
+dataChannel.put(key = "listener_from_host")
+
Determine Module App and Host App Version Match
YukiHookAPI
also provides a solution for you to determine whether the Module App matches the Host App version after the user updates the Module App.checkingVersionEquals
method to achieve this function.// Get from the Host App of the specified package name
+dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
+ // Your code here.
+}
+
// Get from the Module App
+dataChannel.checkingVersionEquals { isEquals ->
+ // Your code here.
+}
+
Rules for Callback Event Response
key
in the Host App is always not allowed to be created repeatedly.class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Callback event A
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ // Callback event B
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ // Callback event C
+ dataChannel(packageName = "com.example.demo").wait(key = "other_test_key") {
+ // Your code here.
+ }
+ }
+}
+
+class OtherActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // Callback event D
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ }
+}
+
key
of the callback event C is not repeated with others, and the callback event D is in another Activity, So the final callback events B, C, and D can all be created successfully. Security Instructions
Yuki Hook API
Xposed Module Data Storage
SharedPreferences
and XSharedPreferences
.Sp
storage.Xposed
provides us with a XSharedPreferences
for reading the Sp
data of the Module App. Use in Activity
YukiHookModulePrefs
in Activity
is described here.XSharedPreferences(BuildConfig.APPLICATION_ID)
+
YukiHookAPI
to quickly implement this function.Activity
.modulePrefs.putString("test_name", "saved_value")
+
val testName = prefs.getString("test_name", "default_value")
+
YukiHookModulePrefs
.prefs
file.Activity
of the Module App.// Recommended usage
+modulePrefs("specify_file_name").putString("test_name", "saved_value")
+// Can also be used like this
+modulePrefs.name("specify_file_name").putString("test_name", "saved_value")
+
// Recommended usage
+val testName = prefs("specify_file_name").getString("test_name", "default_value")
+// Can also be used like this
+val testName = prefs.name("specify_file_name").getString("test_name", "default_value")
+
PrefsData
to create templates. Use in PreferenceFragment
YukiHookModulePrefs
in PreferenceFragment
is described here.PreferenceFragmentCompat
, you can now start migrating its extends ModulePreferenceFragment
.Yuki Hook API
API Basic Configs
YukiHookAPI
is introduced here. Function Configs
YukiHookAPI
for configuration. configs Method
fun configs(initiate: Configs.() -> Unit)
+
configs
method implements a lambda
method body on the Configs
class, which you can easily call for configuration. Hooker Configs
YukiHookAPI
provides two ways to use it. Created by lambda
encase Method
fun encase(initiate: PackageParam.() -> Unit)
+
encase
method is the beginning of all Hook life. In a Module App or a Hook process, the encase
method can only be used once to create a Hooker.PackageParam
is an important instance object of the Host App, and PackageParam
is used to implement all Hook operations on the current Hook object.encase
method can be created in the onHook
method using two schemes.YukiHookAPI.encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
encase
method. Created by Custom Hooker
encase Method
fun encase(vararg hooker: YukiBaseHooker)
+
encase
method, the variable array parameter hooker
of the method here provides an object for creating an entry, you can load all Hookers extends YukiBaseHooker
at one time. YukiBaseHooker Usage
YukiBaseHooker
extends PackageParam
, you need to extends your child Hooker from YukiBaseHooker
.object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
object
creation, you can also use class
but not recommended.object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ loadApp(name = "com.example.demo1") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+ loadApp(name = "com.example.demo2") {
+ findClass(name = "$packageName.CustomClass").hook {
+ // Your code here.
+ }
+ }
+ }
+}
+
loadApp
method externally, and then directly start the Hook internally.class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase {
+ loadApp(name = "com.example.demo", ChildCustomHooker)
+ }
+}
+
+object ChildCustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
loadHooker
method to load another Hooker in multiple layers in the child Hooker, please do as you like.object FirstHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ loadHooker(SecondHooker)
+ loadHooker(ThirdHooker)
+ }
+}
+
onHook
method of your HookEntryClass
.class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() =
+ YukiHookAPI.encase(FirstHooker, SecondHooker, ThirdHooker ...)
+}
+
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase(FirstHooker, SecondHooker, ThirdHooker ...)
+}
+
Expansion Features
encase
.initZygote
, handleLoadPackage
, handleInitPackageResources
methods to perform different functions as before using the Xposed API.YukiHookAPI
, these functions are seamless.encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ // Create a Resources Hook (fixed usage)
+ resources().hook {
+ // Your code here.
+ }
+ }
+}
+
loadZygote
method to load the first event initZygote
after a new process has been forked.encase {
+ loadZygote {
+ ActivityClass.hook {
+ // Your code here.
+ }
+ // Create a Resources Hook in Zygote
+ resources().hook {
+ // Your code here.
+ }
+ }
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ // Create a Resources Hook in the app
+ resources().hook {
+ // Your code here.
+ }
+ }
+}
+
Precautions
encase
event will go through three callbacks after being loaded by Hook Framework.initZygote
→ encase
handleLoadPackage
→ encase
handleInitPackageResources
→ encase
loadApp
, loadSystem
, loadZygote
to distinguish the calling domain of each loading code, otherwise your code will be executed multiple times and cause errors.encase {
+ // ❗ Wrong usage, can't start Hook directly
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ // ❗ Wrong usage, can't start Hook directly
+ resources().hook {
+ // ...
+ }
+}
+
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() {
+ // <Scenario 1>
+ encase {
+ loadHooker(CustomHooker)
+ }
+ // <Scenario 2>
+ encase(CustomHooker)
+ }
+}
+
+object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // ❗ Wrong method of use
+ // Because there is no judgment object in the outer layer, you cannot start Hook directly
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ }
+}
+
encase {
+ // ✅ Correct usage, load in Zygote
+ loadZygote(CustomHooker)
+ // ✅ Correct usage, load in Zygote
+ loadZygote {
+ // ✅ Correct usage, Hook in Zygote
+ resources().hook {
+ // ...
+ }
+ }
+ // ✅ The correct way to use it, use the app scope to load
+ loadApp(/** name parameter optional */, hooker = CustomHooker)
+ // ✅ The correct way to use it, load the Hooker after judging the scope of the app
+ loadApp(/** name parameter optional */) {
+ loadHooker(CustomHooker)
+ // ✅ Correct usage, Hook in app scope
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ // ✅ Correct usage, Hook in app scope
+ resources().hook {
+ // ...
+ }
+ }
+}
+
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() {
+ encase(CustomHooker)
+ }
+}
+
+object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // ✅ The correct method of use, since there is no judgment object in the outer layer
+ // it is necessary to judge the scope of the app before performing Hook
+ loadApp(/** name parameter optional */) {
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ }
+ }
+}
+
Precautions when using as Hook API
encase
method at the entry point.fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
+
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
+
baseContext
here only needs to fill in the Context
you got at attachBaseContext
, and other usages are exactly the same as the above.Yuki Hook API
Use as Hook API Configs
Dependency Configs
com.highcapable.yukihookapi:api
dependency.Hook Framework
dependencies used by your target. Entry Configs
Application
.YukiHookAPI.encase
method to attachBaseContext
.class MyApplication : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ // Load Hook Framework
+ //
+ // Your code here.
+ //
+ // Configure YukiHookAPI
+ YukiHookApi.configs {
+ // Your code here.
+ }
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+ }
+}
+
Hook Framework
Hook Framework
with the YukiHookAPI
, which is widely used.Pine
top.canyie.pine:xposed
override fun attachBaseContext(base: Context?) {
+ // Load Pine
+ PineConfig.debug = true
+ PineConfig.debuggable = BuildConfig.DEBUG
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
SandHook
com.swift.sandhook:xposedcompat
or com.swift.sandhook:xposedcompat_new
override fun attachBaseContext(base: Context?) {
+ // Load SandHook
+ SandHookConfig.DEBUG = BuildConfig.DEBUG
+ XposedCompat.cacheDir = base?.cacheDir
+ XposedCompat.context = base
+ XposedCompat.classLoader = javaClass.classLoader
+ XposedCompat.isFirstApplication = base?.processName == base?.packageName
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
Whale
com.wind.xposed:xposed-on-whale
override fun attachBaseContext(base: Context?) {
+ // Loading Whale does not require any configuration
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
Yuki Hook API
R8 & Proguard Obfuscate
R8
R8
then you don't need any special configuration for YukiHookAPI
. Proguard
If you are still using Proguard
, you need to do some rule configuration.R8
in any version, please add the following rules to the gradle.properties
file, no configuration is required for Android Gradle Plugin 7.0 and above.android.enableR8=true
+
Yuki Hook API
Use as Xposed Module Configs
YukiHookAPI
as an Xposed Module. Dependency Configs
YukiHookAPI
provides an automatic builder.com.highcapable.yukihookapi:ksp-xposed
dependency in your build.gradle
. Custom Automatic Builder
YukiHookAPI
will generate the xposed_init
entry point. InjectYukiHookWithXposed Annotation
annotation class InjectYukiHookWithXposed(
+ val sourcePath: String,
+ val modulePackageName: String,
+ val entryClassName: String,
+ val isUsingResourcesHook: Boolean
+)
+
@InjectYukiHookWithXposed
annotation is an important annotation to mark the entry point of a Module App's Hook. sourcePath Parameter
sourcePath
parameter determines the important identifier for the automatic builder to automatically find and match your current project path.src/main
.@InjectYukiHookWithXposed(sourcePath = "src/custom")
+
sourcePath
will be automatically recognized according to Windows
and Unix
, either /
or \
can be used. modulePackageName Parameter
modulePackageName
is the applicationId
of your current project, which is your module package name (the final generated application package name).com.example.demo
, any one of the following definitions.BuildConfig.java
file normally, no additional operations are required.AndroidManifest.xml
example<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.demo">
+
build.gradle
exampleandroid {
+ namespace 'com.example.demo'
+}
+
build.gradle.kts
exampleandroid {
+ namespace = "com.example.demo"
+}
+
modulePackageName
parameter.@InjectYukiHookWithXposed(modulePackageName = "com.example.demo")
+
modulePackageName
parameter, you will get a warning at compile time.You set the customize module package name to "com.example.demo", please check for yourself if it is correct
+
entryClassName Parameter
entryClassName
determines how the automatic builder generates the entry class name in xposed_init
._YukiHookXposedInit
suffix for generation.@InjectYukiHookWithXposed
+class HookEntry: IYukiHookXposedInit
+
class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
+
...hook.HookEntry ← Your entry class
+...hook.HookEntry_Impl ← Auto-generated Impl class
+...hook.HookEntry_YukiHookXposedInit ← Automatically generated Xposed entry class
+
HookXposedEntry
.@InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
+class HookEntry: IYukiHookXposedInit
+
class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
+
...hook.HookEntry ← Your entry class
+...hook.HookEntry_Impl ← Auto-generated Impl class
+...hook.HookXposedEntry ← Automatically generated Xposed entry class
+
isUsingResourcesHook Parameter
isUsingResourcesHook
determines whether the automatic builder generates relevant code for the Resources Hook, this feature is enabled by default.class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
+ // ...
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
+ // ...
+ }
+
+ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {
+ // ...
+ }
+}
+
isUsingResourcesHook = false
to disable automatic generation.@InjectYukiHookWithXposed(isUsingResourcesHook = false)
+
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
+ // ...
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
+ // ...
+ }
+}
+
IYukiHookXposedInit Interface
IYukiHookXposedInit
interface that your HookEntryClass
must implements it, which is the entry point for your Module App to start hooking.onHook
method will be called back, you need to start using YukiHookAPI
in this method._YukiHookXposedInit
→ IYukiHookXposedInit.onXposedEvent
→ IYukiHookXposedInit.onInit
→ IYukiHookXposedInit.onHook
Native Xposed API Events
onXposedEvent
to monitor all loading events of the native Xposed API.@InjectYukiHookWithXposed
+class HookEntry: IYukiHookXposedInit {
+
+ override fun onHook() {
+ // Your code here.
+ }
+
+ override fun onXposedEvent() {
+ // Listen to the loading events of the native Xposed API
+ YukiXposedEvent.events {
+ onInitZygote {
+ // The it object is [StartupParam]
+ }
+ onHandleLoadPackage {
+ // The it object is [LoadPackageParam]
+ }
+ onHandleInitPackageResources {
+ // The it object is [InitPackageResourcesParam]
+ }
+ }
+ }
+}
+
onXposedEvent
and onHook
methods exist completely independently and do not affect each other. You can continue to use YukiHookAPI
in the onHook
method.Yuki Hook API
Usage Example
YukiHookAPI
and a list of simple Hook examples and common functions. Structure Diagram
YukiHookAPI
.Host Environment
+└── YukiMemberHookCreator
+ └── Class
+ └── MemberHookCreator
+ └── Member
+ ├── Before
+ └── After
+ MemberHookCreator
+ └── Member
+ ├── Before
+ └── After
+ ...
+ YukiResourcesHookCreator
+ └── Resources
+ └── ResourcesHookCreator
+ └── Drawable
+ └── Replace
+ ResourcesHookCreator
+ └── Layout
+ └── Inject
+ ...
+
TargetClass.hook {
+ injectMember {
+ method {
+ // Your code here.
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+}
+resources().hook {
+ injectResource {
+ conditions {
+ // Your code here.
+ }
+ replaceTo(...)
+ }
+}
+
Demo
YukiHookAPI
. A Simple Hook Example
Hook App
onCreate
method in com.android.browser
and show a dialog.encase
method.loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ AlertDialog.Builder(instance())
+ .setTitle("Hooked")
+ .setMessage("I am hook!")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+ }
+ }
+}
+
onCreate
method will be successfully hooked and this dialog will show when every Activity
in com.android.browser
starts.onStart
method?injectMember
method body.loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ AlertDialog.Builder(instance())
+ .setTitle("Hooked")
+ .setMessage("I am hook!")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+ }
+ injectMember {
+ method {
+ name = "onStart"
+ emptyParam()
+ returnType = UnitType
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+}
+
Class
that does not exist in the current project, you can use the stub
method or the findClass
method to get the class that needs to be hooked.com.example.demo.TestClass
.findClass(name = "com.example.demo.TestClass").hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
com.example.demo
is the app you want to hook, then the writing method can be simpler.findClass(name = "$packageName.TestClass").hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
findClass
is a bit cumbersome in some scenarios.const val TestClass = "com.example.demo.TestClass"
+
+TestClass.hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
"$packageName.TestClass".hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
Hook Zygote
initZygote
after the new process is forked when the app starts.onCreate
event of an app Activity
encase
method.loadZygote {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+}
+
Hook System Framework
YukiHookAPI
, the implementation of the Hook System Framework is very simple.ApplicationInfo
and PackageInfo
and do something with them.encase
method.loadSystem {
+ ApplicationInfoClass.hook {
+ // Your code here.
+ }
+ PackageInfoClass.hook {
+ // Your code here.
+ }
+}
+
Hook Resources
app_name
of type string
in Hook com.android.browser
with 123
.encase
method.loadApp(name = "com.android.browser") {
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "app_name"
+ string()
+ }
+ replaceTo("123")
+ }
+ }
+}
+
app_name
, it will become our 123
.ic_launcher
of type mipmap
in com.android.browser
.loadApp(name = "com.android.browser") {
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+}
+
loadApp
with loadZygote
.loadZygote {
+ resources().hook {
+ // Your code here.
+ }
+}
+
Remove Hook
XC_MethodHook.Unhook
function, which can remove the current Hook from the Hook queue, and YukiHookAPI
can also implement this function.Result
instance of the current injected object, and call remove
at the appropriate time and place to remove the injected object.// Set a variable to save the current instance
+val hookResult = injectMember {
+ method {
+ name = "test"
+ returnType = UnitType
+ }
+ afterHook {
+ // ...
+ }
+}
+// Call the following method when appropriate
+hookResult.remove()
+
removeSelf
in the Hook callback method to remove itself.injectMember {
+ method {
+ name = "test"
+ returnType = UnitType
+ }
+ afterHook {
+ // Just call the following method directly
+ removeSelf()
+ }
+}
+
Exception Handling
YukiHookAPI
has redesigned the monitoring of exceptions, any exception will not be thrown during the hook process, to avoid interrupting the next hook process and causing the hook process to "die". Listen for Exceptions
injectMember {
+ // Your code here.
+}.result {
+ // Handle the exception at the start of the hook
+ onHookingFailure {}
+ // Handle exceptions in the hook process
+ onConductFailure { param, throwable -> }
+ // Handle all exceptions
+ onAllFailure {}
+ // ...
+}
+
injectResource {
+ // Your code here.
+}.result {
+ // Handle arbitrary exceptions when hooking
+ onHookingFailure {}
+ // ...
+}
+
Class
does not exist.TargetClass.hook {
+ injectMember {
+ // Your code here.
+ }
+}.onHookClassNotFoundFailure {
+ // Your code here.
+}
+
method {
+ // Your code here.
+}.onNoSuchMethod {
+ // Your code here.
+}
+
Throw an Exception
hook
method body will be taken over by the YukiHookAPI
to avoid interrupting the next Hook process and causing the Hook process to "die".YukiHookAPI
takes over.// <Scenario 1>
+injectMember {
+ method {
+ throw RuntimeException("Exception Test")
+ }
+ afterHook {
+ // ...
+ }
+}.result {
+ // Can catch RuntimeException
+ onHookingFailure {}
+}
+// <Scenario 2>
+injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ throw RuntimeException("Exception Test")
+ }
+}.result {
+ // Can catch RuntimeException
+ onConductFailure { param, throwable -> }
+}
+
param.throwable
method, and YukiHookAPI
can also implement this function.injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ RuntimeException("Exception Test").throwToApp()
+ }
+}
+
injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ throw RuntimeException("Exception Test")
+ }.onFailureThrowToApp()
+}
+
Status Monitor
XposedHelpers
often print Unhook
after the Hook to determine whether the Hook is successful.YukiHookAPI
, you can easily reimplement this functionality with the following methods.YourClass.hook {
+ // Your code here.
+}.onPrepareHook {
+ loggerD(msg = "$instanceClass hook start")
+}
+
injectMember {
+ // Your code here.
+}.onHooked { member ->
+ loggerD(msg = "$member has hooked")
+}
+
Expansion Usage
Multiple Hosts
loadApp
method body to distinguish the app you want to hook.loadApp(name = "com.android.browser") {
+ // Your code here.
+}
+loadApp(name = "com.android.phone") {
+ // Your code here.
+}
+
Multiple Processes
withProcess
method body to hook them separately.withProcess(mainProcessName) {
+ // Your code here.
+}
+withProcess(name = "$packageName:tool") {
+ // Your code here.
+}
+
Writing Optimization
YukiHookAPI
and write your onHook
entry as lambda
.override fun onHook() = encase {
+ // Your code here.
+}
+
Xposed Module own Active State
false
, and then Hook this method to return true
to prove that the Hook has taken effect.YukiHookAPI
, you don't need to do this at all. YukiHookAPI
has already encapsulated this operation for you, and you can use it directly.YukiHookAPI.Status.isXposedModuleActive
directly in the Module App to determine whether it is active.if(YukiHookAPI.Status.isXposedModuleActive) {
+ // Your code here.
+}
+
YukiHookAPI.Status.isTaiChiModuleActive
to determine whether it is activated.if(YukiHookAPI.Status.isTaiChiModuleActive) {
+ // Your code here.
+}
+
YukiHookAPI
also encapsulates a convenient way for you.YukiHookAPI.Status.isModuleActive
to determine whether you are activated in Xposed or TaiChi and Promise.if(YukiHookAPI.Status.isModuleActive) {
+ // Your code here.
+}
+
Yuki Hook API
Introduce
Background
Kotlin
. Usage
YukiHookAPI
is built entirely with Kotlin
lambda
syntax.XposedHelpers
, you can use it to easily create Xposed Modules and easily implement custom Hook API. Language Requirement
Kotlin
, the framework part of the code composition is also compatible with Java
but the implementation of the basic Hook scene may not work at all.Kotlin
, if you don't know how to use Kotlin
then you may not be able to use YukiHookAPI
. Source of Inspiration
xposed_init
file under assets
.XposedHelpers
to implement our Hook logic.Kotlin
is the main Android development language, this API is really not very elegant to use.YukiHookAPI
was born.Kotlin
's elegant lambda
writing and YukiHookAPI
, you can make your Hook logic more beautiful and clear.@InjectYukiHookWithXposed
+class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase {
+ loadZygote {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "sym_def_app_icon"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+ }
+ loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+ }
+ }
+}
+
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
+
+ private lateinit var moduleResources: XModuleResources
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
+ moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
+ XResources.setSystemWideReplacement(
+ "android", "mipmap", "sym_def_app_icon",
+ moduleResources.fwd(R.mipmap.ic_launcher)
+ )
+ XposedHelpers.findAndHookMethod(
+ Activity::class.java.name,
+ null, "onCreate",
+ Bundle::class.java,
+ object : XC_MethodHook() {
+ override fun beforeHookedMethod(param: MethodHookParam?) {
+ // Your code here.
+ }
+
+ override fun afterHookedMethod(param: MethodHookParam?) {
+ // Your code here.
+ }
+ })
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
+ if (lpparam.packageName == "com.android.browser")
+ XposedHelpers.findAndHookMethod(
+ Activity::class.java.name,
+ lpparam.classLoader, "onCreate",
+ Bundle::class.java,
+ object : XC_MethodHook() {
+ override fun beforeHookedMethod(param: MethodHookParam?) {
+ // Your code here.
+ }
+
+ override fun afterHookedMethod(param: MethodHookParam?) {
+ // Your code here.
+ }
+ })
+ }
+
+ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
+ if (resparam.packageName == "com.android.browser")
+ resparam.res.setReplacement(
+ "com.android.browser", "mipmap", "ic_launcher",
+ moduleResources.fwd(R.mipmap.ic_launcher)
+ )
+ }
+}
+
YukiHookAPI
, you can implement a very simple Xposed Module. Suppored Hook Framework
Hook Framework
and Xposed framework supported by YukiHookAPI
.Hook Framework ST Description LSPosed ✅ Stable use in multiple scenarios LSPatch ⭕ WIP after this project is improved EdXposed ❎ Maintenance has stopped, no longer recommended Pine ⭕ Only available SandHook ⭕ Only available Whale ⭕ Need xposed-hook-based-on-whale YAHFA ❗ Need to implement the Xposed API yourself FastHook ❗ Need to implement the Xposed API yourself Epic ❗ Need Dexposed by yourself TaiChi ⭕ Only available for Xposed Module Xposed ❎ Not test, no longer recommended Yuki Hook API
Basic Knowledge
Related Introduction
What is Xposed
What can Xposed do
Xposed Framework
+└── App's Environment
+ └── Hooker (Hooked)
+ ...
+ App's Environment
+ └── Hooker (Hooked)
+ ...
+ ...
+
XposedBridge
to dynamically insert our own code before and after the method to be executed by the Host (App), or completely replace the target, or even intercept. Development Process
Derivatives
App's Environment
+└── Hook Framework
+ └── Hooker (Hooked)
+ ...
+
What YukiHookAPI does
XposedHelpers
, which is well known to developers, there is still no set of syntactic sugar for Kotlin
and API with complete usage encapsulation.YukiHookAPI
will adapt to more third-party Hook Frameworks based on the goal of using the Xposed API, so as to improve the entire ecosystem and help more developers make Xposed Module development simpler and easier to understand. Let's Started
YukiHookAPI
.Yuki Hook API
Migrate from Xposed API
YukiHookAPI
. Migrate Hook Entry Point
XC_LoadPackage.LoadPackageParam
to PackageParam
.YukiHookAPI
implements the lambda
method body this
usage for PackageParam
, and the PackageParam
object can be obtained globally in the encase
method body.override fun onHook() = encase {
+ // Get the package name of the current Hook
+ packageName
+ // Get the ApplicationInfo of the current Hook
+ appInfo
+ // Get the system context object
+ systemContext
+ // Get the host Application lifecycle
+ appContext
+ // Hook specified app
+ loadApp(name = "com.demo.test") {
+ // Class Hook
+ findClass("com.demo.test.TestClass").hook {
+ injectMember {
+ method {
+ name = "test"
+ param(BooleanType)
+ }
+ afterHook {
+ // ...
+ }
+ }
+ }
+ // Resources Hook (fixed usage)
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+ }
+}
+
private lateinit var moduleResources: XModuleResources
+
+override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
+ moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
+}
+
+override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
+ // Get the package name of the current Hook
+ lpparam.packageName
+ // Get the ApplicationInfo of the current Hook
+ lpparam.applicationInfo
+ // Get the system context object
+ // There is no ready-made calling method in the native Xposed API, you need to reflect ActivityThread to achieve it
+ // Get the host Application lifecycle
+ AndroidAppHelper.currentApplication()
+ // Class Hook
+ if(lpparam.packageName == "com.demo.test")
+ XposedHelpers.findAndHookMethod(
+ "com.demo.test.TestClass", lpparam.classLoader,
+ "test", Boolean::class.java,
+ object : XC_MethodHook() {
+ override fun afterHookedMethod(param: MethodHookParam) {
+ // ...
+ }
+ }
+ )
+}
+
+override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
+ // Get the package name of the current Hook
+ resparam.packageName
+ // Resources Hook
+ resparam.res.setReplacement(
+ "com.demo.test", "mipmap", "ic_launcher",
+ moduleResources.fwd(R.mipmap.ic_launcher)
+ )
+}
+
Migrate Hook Method Body
XC_MethodHook.MethodHookParam
to HookParam
. Before/After Hook
YukiHookAPI
also implements the lambda
method body this
usage for HookParam
, and the HookParam
object can be obtained globally in the method bodies such as beforeHook
and afterHook
.afterHook {
+ // Get the current Hook instance
+ instance
+ // Get the Class instance of the current Hook
+ instanceClass
+ // Get and cast the current Hook instance to the specified type T
+ instance<T>()
+ // Get the method parameter array
+ args
+ // Get the first T of the method parameter
+ args().first().cast<T>()
+ // Get the last bit of the method parameter T
+ args().last().cast<T>()
+ // Get any subscript T of the method parameter, here is an example of 2
+ args(index = 2).cast<T>()
+ // Set any subscript of the method parameter, here is an example of 2
+ args(index = 2).set(...)
+ // Get the return value
+ result
+ // Get the return value and cast to T
+ result<T>()
+ // Modify the content of the return value
+ result = ...
+ // Remove the content of the return value
+ resultNull()
+ // Throw an exception to the Hook app
+ Throwable("Fatal").throwToApp()
+ // Execute the original method without hook and call with the original method parameters, generics can be omitted
+ callOriginal<Any?>()
+ // Execute the original method without Hook and customize the method parameter call, the generic type can be omitted
+ invokeOriginal<Any?>(...)
+}
+
override fun afterHookedMethod(param: MethodHookParam) {
+ // Get the current Hook instance
+ param.thisObject
+ // Get the Class instance of the current Hook
+ param.thisObject.javaClass
+ // Get and cast the current Hook instance to the specified type T
+ param.thisObject as T
+ // Get the method parameter array
+ param.args
+ // Get the first T of the method parameter
+ param.args[0] as T
+ // Get the last bit of the method parameter T
+ param.args[param.args.lastIndex] as T
+ // Get any subscript T of the method parameter, here is an example of 2
+ param.args[2] as T
+ // Set any subscript of the method parameter, here is an example of 2
+ param.args[2] = ...
+ // Get the return value
+ param.result
+ // Get the return value and cast to T
+ param.result as T
+ // Modify the content of the return value
+ param.result = ...
+ // Remove the content of the return value
+ param.result = null
+ // Throw an exception to the Hook app
+ param.throwable = Throwable("Fatal")
+ // Execute the original method without hooking
+ XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
+}
+
Replace Hook
replaceHook
method is special, and the YukiHookAPI
makes a variety of forms for it to choose from./// A method with no return value void
+
+replaceUnit {
+ // Implement the replaced logic directly here
+}
+
+/// A method with a return value
+
+replaceAny {
+ // Implement the replaced logic here
+ // ...
+ // Need to return the return value corresponding to the method, no need to write return, just put the parameter in the last digit
+ // Assuming the return value of this method is an Int, we just need to ensure that the last bit is the return value we need
+ 0
+}
+
+/// For some methods, we just need to replace their return value, then there are the following implementations
+/// It should be noted that the parameters passed in by the method of directly replacing the return value are fixed. If you want to dynamically replace the return value, please use the above replaceAny method body
+
+// Replace with the return value you need
+replaceTo(...)
+// Replace with return value of type Boolean
+replaceToTrue()
+// Intercept return value
+intercept()
+
/// A method with no return value void
+
+override fun replaceHookedMethod(param: MethodHookParam): Any? {
+ // Implement the replaced logic directly here
+ return null
+}
+
+/// A method with a return value
+
+override fun replaceHookedMethod(param: MethodHookParam): Int {
+ // Implement the replaced logic here
+ // ...
+ // Assume the return value of this method is an Int
+ return 0
+}
+
+/// For some methods, we just need to replace their return value, then there are the following implementations
+
+// Replace with the return value you need
+override fun replaceHookedMethod(param: MethodHookParam) = ...
+// Replace with return value of type Boolean
+override fun replaceHookedMethod(param: MethodHookParam) = true
+// Intercept return value
+override fun replaceHookedMethod(param: MethodHookParam) = null
+
Migrate Other Features
YukiHookAPI
is a complete rewrite of the Xposed API, you can refer to API Document and Special Features to determine some functional Migration and use.Yuki Hook API
Quick Start
YukiHookAPI
into your project. Environment Requirements
1.0.80
) Automatically Build Project
YukiHookAPI
provides an automated build tool that can help you quickly build an Android standard project template with Xposed Module dependencies, and use the built template to start the next step directly. Manually Configure Project
Create Project
Android Studio
or IntelliJ IDEA
to create a new Android project and select Kotlin
in the Language
column to automatically add basic dependencies. Integration Dependencies
build.gradle
.repositories {
+ google()
+ mavenCentral()
+ // ❗If your Plugin version is too low, be sure to add it as an Xposed Module, other cases are optional
+ maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
+ // ❗Be sure to add it as an Xposed Module, optional in other cases
+ maven { url "https://api.xposed.info/" }
+ // MavenCentral has a 2-hour cache, if you cannot integrate the latest version, please add this address
+ maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
+}
+
plugin
to your app build.gradle
.plugins {
+ // ❗Be sure to add it as an Xposed Module, optional in other cases
+ id 'com.google.devtools.ksp' version '<ksp-version>'
+}
+
build.gradle
.dependencies {
+ // base dependencies
+ implementation 'com.highcapable.yukihookapi:api:<yuki-version>'
+ // ❗Be sure to add it as an Xposed Module, optional in other cases
+ compileOnly 'de.robv.android.xposed:api:82'
+ // ❗Be sure to add it as an Xposed Module, optional in other cases
+ ksp 'com.highcapable.yukihookapi:ksp-xposed:<yuki-version>'
+}
+
Kotlin
to 11 and above in your app build.gradle
.android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
+ }
+ kotlinOptions {
+ jvmTarget = '11'
+ }
+}
+
Use as Xposed Module
AndroidManifest.xml
.<!-- Set as Xposed Module -->
+<meta-data
+ android:name="xposedmodule"
+ android:value="true" />
+
+<!-- Set your module description -->
+<meta-data
+ android:name="xposeddescription"
+ android:value="Fill in your Xposed Module description" />
+
+<!-- The minimum Xposed version number -->
+<!-- If you are using EdXposed/LSPosed, the minimum recommended is 93 -->
+<meta-data
+ android:name="xposedminversion"
+ android:value="93" />
+
+<!-- Optional: Configure support for New XSharePrefs without adjusting xposedminversion to 93 -->
+<meta-data
+ android:name="xposedsharedprefs"
+ android:value="true"/>
+
IYukiHookXposedInit
and add the annotation @InjectYukiHookWithXposed
.@InjectYukiHookWithXposed
+class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = YukiHookAPI.encase {
+ // Your code here.
+ }
+}
+
Use as Hook API
Integration
Application
.YukiHookAPI.encase
method to attachBaseContext
.override fun attachBaseContext(base: Context?) {
+ // Load Hook Framework
+ //
+ // Your code here.
+ //
+ // Load YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
Yuki Hook API
YukiHookAPI Project Builder
YukiHookAPI
as the core. Get Project
Usage
Basic Usage
Config Template
Multilingual Support
Yuki Hook API
关于此文档
License
MIT License
+
+Copyright (C) 2019-2022 HighCapable
+
+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.
+
Yuki Hook API
更新日志
YukiHookAPI
的版本更新历史。最新
1.1.0 | 2022.09.28 XposedHelper
拼写错误修改为了 XposedHelpers
Class
与 Method
转为 Java 以提供更好的演示效果HookParamWrapper
,现已将其直接与 YukiBridgeFactory
对接YukiHookBridge
中的方法到 AppParasitics
HookParam.args
与底层的直接对接方法 setArgs
,直接获取并设置当前数组的对象jar
合并到 stub
项目Creater
命名到 Creator
YukiHookAPI.Status.compiledTimestamp
功能,可以在作为 Xposed 模块使用时获取编译完成的时间戳YukiHookAPI.Status.isXposedEnvironment
功能,可以判断当前为 (Xposed) 宿主环境还是模块环境YukiHookAPI.Configs.debugTag
等功能合并到 YukiHookLogger.Configs
中XposedBridge.log
或 Logd
debugLog
配置中自行更改generic
功能,可对泛型进行反射和调用,你可以在 Class
或 CurrentClass
中使用它buildOfAny
方法,现在请直接使用 buildOf
方法 (不带泛型) 来使用构造方法创建新对象并得到结果 Any
hasExtends
使用过程发生空指针异常的问题CurrentClass
新增非 lambda
方式的调用方法CurrentClass
新增 name
与 simpleName
功能ReflectionTool
的核心方法,将不同的查找条件进行了整理分类ReflectionTool
中可能的直接调用 declared
获取的 Member
抛出异常的问题ReflectionTool
中 UndefinedType
未在 Method
与 Constructor
条件中正确判断的问题Member
的问题Method
、Constructor
中新增 VagueType
条件,可使用在 param
条件中用于忽略你不想填写的参数Method
、Constructor
中新增 paramCount { ... }
条件,现在你可以直接拿到其中的 it
来自定义你的判断条件FieldFinder
结果中新增 current
方法,可直接对结果实例创建调用空间modifiers
条件以及 name
条件,现在你需要对此方法体结尾返回一个 Boolean
以使条件成立ModifierRules
中的 as*
功能改名为 is*
,感谢 Kitsune 的建议FieldFinder
中新增 RemedyPlan
功能Dex
中的 Class
模糊查找功能 (Beta),你现在可以直接使用 searchClass
功能来使用指定条件模糊查找 Class
appClassLoader
获取到的对象在某些系统中的系统应用中不正确的问题,感谢 Luckyzyx 的反馈XposedBridge.invokeOriginalMethod
的调用方式并在 MethodFinder.Result.Instance
中增加 original
功能YukiHookModulePrefs
中 getStringSet
方法取值错误的问题并优化代码风格,感谢 Teddy_Zhu 的 PRYukiHookModulePrefs
,拦截 XSharePreference
可能不存在的异常YukiHookDataChannel
在某些第三方 ROM 系统框架中无法注册成功的问题YukiHookDataChannel
,现在它只能在来自指定包名的模块与宿主之间通信SharedPreferences
以修复部分系统中文件权限不是 0664
的问题,感谢 5ec1cff 的反馈及提供的实现代码YukiHookAPI.Configs.isEnableHookSharedPreferences
功能,默认关闭,若 SharedPreferences
的权限错误可进行启用Constructor
时无参构造方法在不填写查找条件时无法找到的 BUG,感谢 B5 KAKA 的反馈injectMember
中 method
、constructor
的 Result
实例到 Process
useDangerousOperation
方法,未进行声明时在 Hook 危险列表中的功能后会自动停止 Hook 并打印错误Activity
代理功能,你可以调用 injectModuleAppResources
及 registerModuleAppActivities
来使用ModuleContextThemeWrapper
功能,你可以调用 applyModuleTheme
在任意 Activity
中创建模块的 Context
ClassLoader.onLoadClass
功能,可用于监听 ClassLoader
的 loadClass
方法被调用的事件classOf
与 clazz
扩展方法,新增 toClass
以及 toClassOrNull
用法,请现在转移到新的方法VariousClass
新增 getOrNull
方法,可在匹配不到 Class
的时候不抛出异常而是返回 null
PackageParam.hook
中移除了 isUseAppClassLoader
参数,修改为 isForceUseAbsolute
并自动匹配目标 Class
PackageParam
新增 systemContext
功能,你可以在任意时间调用此功能获取一个持久化的 Context
HookClass
中的任何方法HookParam
中新增 throwToApp
功能,可将异常直接抛给宿主onFailureThrowToApp
功能,可在发生异常时直接抛给宿主remove
及 removeSelf
方法解除 Hookarray
类型,感谢 GSWXXN 的 PRme.weishu.reflection
到 thirdparty
防止同时引入的同名依赖冲突AppLifecycle
的异常处理逻辑,当其发生异常时直接抛给宿主过旧
1.0.92 | 2022.05.31 YukiHookDataChannel
在低于 Android 12 的设备上不能回调当前 Activity
广播的问题InjectYukiHookWithXposed
注解新增 isUsingResourcesHook
功能,现在你可以选择性关闭自动生成 IXposedHookInitPackageResources
的依赖接口了过期
1.0.91 | 2022.05.29 ClassLoader
错误的问题,感谢 Luckyzyx 的反馈YukiHookDataChannel
在 ZUI 以及低于 Android 12 的系统上不能回调当前 Activity
广播的问题YukiHookModuleStatus
功能到 YukiHookAPI.Status
,重写了大量方法,现在你可以在模块与宿主中双向判断模块激活等状态信息过期
1.0.90 | 2022.05.27 YukiHookDataChannel
在模块设置监听回调时闪退的问题YukiHookDataChannel
在非当前 Activity
情况下依然会回调的问题YukiHookDataChannel
回调事件的默认值,没有即不回调YukiHookModulePrefs
在 XShare 不可读的情况下打印的警告YukiHookModulePrefs
中的 isXSharePrefsReadable
方法,可判断当前的 XShare 是否可用过期
1.0.89 | 2022.05.26 YukiHookDataChannel
不能重复设置监听的问题,并加入在模块不同 Activity
中重复响应和自动跟随 Activity
销毁监听功能YukiHookDataChannel
重复监听用例说明文档onAlreadyHooked
方法,可判断当前方法是否被重复 HookputIfAbsent
方法,允许覆盖添加过期
1.0.88 | 2022.05.25 type
中的 android
类型YukiHookModuleStatus
从自动生成代码中分离,并加入 isEnableHookModuleStatus
的开关,由你决定是否启用YukiHookModulePrefs
设置为单例运行,防止重复创建浪费系统资源1.0.80
版本后无法嵌套 Hook 的 BUG,并优化嵌套 Hook 相关功能HookParam
方法MethodFinder
与 FieldFinder
加入查找模糊方法、变量名称功能,可调用 name { ... }
来设置查找条件,支持正则appContext
的获取方式,降低会取到空的问题的可能性logger
的打印 TAG
默认为你自定义的名称,方便进行调试YukiHookBridge
的 Hooker
实现方式,提升 Hook 性能PackageParam
增加 onAppLifecycle
方法,可原生监听宿主的生命周期以及实现注册系统广播功能YukiHookDataChannel
功能,可在模块与宿主保持存活的情况下使用系统无序广播进行通讯YukiHookDataChannel
增加 checkingVersionEquals
方法,可通过监听来验证模块更新后宿主并未更新版本不匹配问题demo-module
的示例代码中新增 Java 版本的示例,仅供参考过期
1.0.87 | 2022.05.10 refreshModuleAppResources
功能,以适配语言区域、字体大小、分辨率改变等情况下的 Resources 刷新isEnableModuleAppResourcesCache
功能,可自行设置是否自动缓存当前模块的 Resources过期
1.0.86 | 2022.05.06 initZygote
时持续报错的问题,复现在 ZUI/LSPosed CI(1.8.3-6550)过期
1.0.85 | 2022.05.04 1.0.80
开始出现initZygote
装载的包名为 android-zygote
,packageName
保持 android
不变过期
1.0.83 | 2022.05.04 YukiHookModuleStatus
在 loadSystem
后大量报错的问题type
中的 android
类型过期
1.0.82 | 2022.05.04 initZygote
与系统框架的关系,之前的注释和文档有问题,非常抱歉PackageParam
新增 loadSystem
方法,不需要再写 loadApp(name = "android")
即可 Hook 系统框架过期
1.0.81 | 2022.05.04 by
方法设置条件后 Hook 方法体内查找不到的方法、构造方法依然输出错误日志的问题过期
1.0.80 | 2022.05.01 InjectYukiHookWithXposed
注解新增 entryClassName
功能,可自定义生成的 xposed_init
入口类名 更名为 YukiHookXposedInitProxy
IYukiHookXposedInit
,原接口名称已作废,将在后续版本中直接被删除initZygote
与 Resources Hook 功能,支持 Hook LayoutonXposedEvent
方法,可监听原生 Xposed API 的全部事件lambda
进行 inline
处理,避免生成过碎的匿名类,提升编译后的运行性能PrefsData
编译后的方法体复制过大的问题XSharePreference
可读性测试,失败后会自动打印警告日志PackageParam
新增 appResources
、moduleAppResources
、moduleAppFilePath
功能PackageParam
的 loadApp
新增不写 name
功能,默认筛选全部 APPPackageParam
新增 loadZygote
方法,可直接 Hook 系统框架PackageParam
新增 resources().hook
功能hasExtends
扩展方法,可判断当前 Class
是否有继承关系isSupportResourcesHook
功能,判断当前是否支持资源钩子(Resources Hook)current
功能新增 superClass
方法调用父类superClass
查找条件,可继续在父类中查找YukiHookAPI
大量方法与 Xposed API 解耦合isFirstApplication
可能判断不准确的问题ClassLoader
导致 Hook 卡死的问题,感谢 WankkoRee 的反馈XC_Callback
接口对接后的性能type
新增 ClassLoader
类型过期
1.0.78 | 2022.04.18 YukiHookModulePrefs
新增 isRunInNewXShareMode
方法,可用于判断模块当前是否处于 New XSharePreference
模式YukiHookModulePrefs
在 New XSharePreference
模式下工作的部分问题ModulePreferenceFragment
,现在,你可以完全替换掉 PreferenceFragmentCompat
并开始使用新的功能PreferenceFragmentCompat
的 Sp 数据存储解决方案,感谢 mahoshojoHCG 的反馈Kotlin
依赖到最新版本过期
1.0.77 | 2022.04.15 YukiHookModulePrefs
新增 clear
方法,感谢 WankkoRee 的建议YukiHookModulePrefs
新增 getStringSet
、putStringSet
、all
方法HookParam
的 args
增加 any
方法ModuleApplication
,可在模块中继承此类实现更多功能findClass
功能到 Xposed API,在非宿主环境继续使用原生 ClassLoader
过期
1.0.75 | 2022.04.13 HookParam
中删除了 firstArgs
与 lastArgs
方法,现在你可以使用 args().first()
与 args().last()
来取代它HookParam
中删除了 args()
中的默认参数 index = 0
,现在你可以使用 args().first()
或 args(index = 0)
来取代它HookParam
中 result
功能增加了泛型匹配,现在你可以使用 result<T>
来匹配你的目标方法已知返回值类型了emptyParam
条件,并完善了文档相关需要注意的查找条件误区type
中的 android
类型 1.0.73 | 2022.04.10
XC_LoadPackage.LoadPackageParam
内容为空抛出异常的问题,感谢 Luckyzyx 的反馈过期
1.0.72 | 2022.04.09 PackageParam
中加入 appContext
功能过期
1.0.71 | 2022.04.04 过期
1.0.70 | 2022.04.04 instanceClass
在静态实例中调用后报错问题isUseAppClassLoader
功能,感谢 WankkoRee 的反馈withProcess
功能,可根据 APP 当前指定进程进行 HookallMethods
未 Hook 到方法时不会抛出异常的问题,感谢 WankkoRee 的反馈index
定位指定的方法和变量,感谢 WankkoRee 提供的思路String
声明的类名和 VariousClass
current
功能,可对任意的类构建一个反射方法操作空间,方便地调用和修改其中的方法和变量过期
1.0.69 | 2022.03.30 allMethods
多次使用时只有最后一个生效的问题,感谢 WankkoRee 的反馈过期
1.0.68 | 2022.03.29 Member
查找缓存和查找缓存配置开关MethodFinder
、FieldFinder
以及 HookParam
相关方法的调用Finder
中的 cast
类型并支持 cast
为数组过期
1.0.67 | 2022.03.27 Finder
中的 modifiers
功能,可筛选 static
、native
、public
、abstract
等诸多描述类型Member
的 hasModifiers
扩展功能MethodFinder
和 ConstructorFinder
中的 give
方法,可获得原始类型YukiHookModulePrefs
中的 PrefsData
模板功能过期
1.0.66 | 2022.03.25 MethodFinder
中的一个严重问题hookParam
中的 args
调用方法过期
1.0.65 | 2022.03.25 MethodFinder
与 FieldFinder
新的返回值调用方法type
中的 android
类型以及 java
类型过期
1.0.6 | 2022.03.20 YukiHookModulePrefs
在使用一次 direct
忽略缓存后每次都忽略的 BUGisActive
判断模块激活的传统用法Field
时的日志输出问题和未拦截的异常问题ReflectionUtils
中的 Xposed APIYukiHookModuleStatus
方法名称的混淆,以精简模块生成的体积过期
1.0.55 | 2022.03.18 type
中的大量 android
类型以及少量 java
类型过期
1.0.5 | 2022.03.18 onInit
方法来配置 YukiHookAPI
executorName
和 executorVersion
来获取当前 Hook 框架的名称和版本号by
方法来设置 Hook 的时机和条件YukiHookModulePrefs
新增可控制的键值缓存,可在宿主运行时模块动态更新数据过期
1.0.4 | 2022.03.06 XposedBridge
的问题YukiHookAPI
的常量版本名称和版本号hasField
方法以及 isAllowPrintingLogs
配置参数isDebug
开启的情况下 API 将自动打印欢迎信息测试模块是否生效过期
1.0.3 | 2022.03.02 ignoredError
功能type
中的 android
类型hook
后的 ClassNotFound
功能过期
1.0.2 | 2022.02.18 BaseFinder
进行整合过期
1.0.1 | 2022.02.15 RemedyPlan
增加 onFind
功能type
中的 java
类型过期
1.0 | 2022.02.14 Yuki Hook API
联系我们
助力维护
YukiHookAPI
,如有代码相关的建议和请求,可在 Github 提交 Pull Request。Yuki Hook API
展望未来
YukiHookAPI
在未来的发展空间。 未解决的问题
YukiHookAPI
尚未解决的问题。 YukiHookModulePrefs
selinux
就是目前面临的一个大问题,有待讨论和研究。 未来的计划
YukiHookAPI
可能会在后期添加的功能。 支持独立使用的 Lite 版本
支持更多 Hook Framework
XposedBridge
作为兼容层,还是有一定的局限性。inline hook
没有 Java
兼容层,后期可能会考虑 native hook
的 Java
兼容层适配。Yuki Hook API
文档介绍
YukiHookAPI
为最新版本以使用最新版本的功能。 功能描述说明
功能示例说明
变更记录说明
v<version>
添加
;v<version>
新增
;v<version>
修改
;v<version>
作废
并会标注删除线;v<version>
移除
并会标注删除线。 相关符号说明
get
、set
方法或只读的 get
方法Yuki Hook API
- object
YukiHookAPI object YukiHookAPI
+
v1.0
添加
YukiHookAPI
的 API 调用总类,Hook 相关功能的开始、Hook 相关功能的配置都在这里。- field
API_VERSION_NAME const val API_VERSION_NAME: String
+
v1.0.4
新增
YukiHookAPI
的版本。- field
API_VERSION_CODE const val API_VERSION_CODE: Int
+
v1.0.4
新增
YukiHookAPI
的版本号。executorName - field
v1.0.5
新增
v1.0.91
移除
Status.executorName
executorVersion - field
v1.0.5
新增
v1.0.91
移除
Status.executorVersion
- object
Status object Status
+
v1.0.91
新增
YukiHookAPI
的状态。- field
compiledTimestamp val compiledTimestamp: Long
+
v1.1.0
新增
- field
isXposedEnvironment val isXposedEnvironment: Boolean
+
v1.1.0
新增
- field
executorName val executorName: String
+
v1.0.91
新增
unknown
,XposedBridge
不存在会返回 invalid
。- field
executorVersion val executorVersion: Int
+
v1.0.91
新增
-1
。- field
isModuleActive val isModuleActive: Boolean
+
v1.0.91
新增
- field
isXposedModuleActive val isXposedModuleActive: Boolean
+
v1.0.91
新增
- field
isTaiChiModuleActive val isTaiChiModuleActive: Boolean
+
v1.0.91
新增
- field
isSupportResourcesHook val isSupportResourcesHook: Boolean
+
v1.0.91
新增
- object
Configs object Configs
+
v1.0
添加
- method
debugLog inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit)
+
v1.1.0
新增
YukiHookLogger.Configs
相关参数。debugTag - field
v1.0
添加
v1.1.0
作废
YukiHookLogger.Configs.tag
- field
isDebug var isDebug: Boolean
+
v1.0
添加
Logcat
和 XposedBridge.log
打印详细的 Hook 日志,关闭后仅会打印 E
级别的日志。isAllowPrintingLogs - field
v1.0.4
新增
v1.1.0
作废
YukiHookLogger.Configs.isEnable
- field
isEnableModulePrefsCache var isEnableModulePrefsCache: Boolean
+
v1.0.5
新增
YukiHookModulePrefs
的键值缓存功能。YukiHookModulePrefs
中自由开启和关闭缓存功能以及清除缓存。- field
isEnableModuleAppResourcesCache var isEnableModuleAppResourcesCache: Boolean
+
v1.0.87
新增
Resources
缓存功能。PackageParam.refreshModuleAppResources
来刷新缓存。- field
isEnableHookModuleStatus var isEnableHookModuleStatus: Boolean
+
v1.0.88
新增
- field
isEnableHookSharedPreferences var isEnableHookSharedPreferences: Boolean
+
v1.1.0
新增
SharedPreferences
。SharedPreferences
文件权限调整为 Context.MODE_WORLD_READABLE
(0664)。- field
isEnableDataChannel var isEnableDataChannel: Boolean
+
v1.0.88
新增
YukiHookDataChannel
功能。Application
继承于 ModuleApplication
才能有效。YukiHookDataChannel
。- field
isEnableMemberCache var isEnableMemberCache: Boolean
+
v1.0.68
新增
v1.0.80
修改
Member
缓存功能。Member
复用过高造成的系统 GC 问题,此功能默认启用。Method
、Constructor
、Field
。Member
都将处于 MemberCacheStore
的全局静态实例中。MethodFinder
、ConstructorFinder
、FieldFinder
来获取 Member
。Member
发生了混淆的问题,例如使用 R8 混淆后的 APP 的目标 Member
,否则建议启用。- method
configs inline fun configs(initiate: Configs.() -> Unit)
+
v1.0
添加
Configs
类实现了一个 lambda
方法体。HookEntryClass
的 onInit
方法中调用 configs
方法和 debugLog
方法完成对 API 的功能配置,实时生效。class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() {
+ YukiHookAPI.configs {
+ debugLog {
+ tag = "YukiHookAPI"
+ isEnable = true
+ isRecord = false
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ isDebug = BuildConfig.DEBUG
+ isEnableModulePrefsCache = true
+ isEnableModuleAppResourcesCache = true
+ isEnableHookModuleStatus = true
+ isEnableHookSharedPreferences = false
+ isEnableDataChannel = true
+ isEnableMemberCache = true
+ }
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() = configs {
+ debugLog {
+ tag = "YukiHookAPI"
+ isEnable = true
+ isRecord = false
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ isDebug = BuildConfig.DEBUG
+ isEnableModulePrefsCache = true
+ isEnableModuleAppResourcesCache = true
+ isEnableHookModuleStatus = true
+ isEnableHookSharedPreferences = false
+ isEnableDataChannel = true
+ isEnableMemberCache = true
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
configs
和 debugLog
方法,直接进行配置。class HookEntryClass : IYukiHookXposedInit {
+
+ override fun onInit() {
+ YukiHookLogger.Configs.tag = "YukiHookAPI"
+ YukiHookLogger.Configs.isEnable = true
+ YukiHookLogger.Configs.isRecord = false
+ YukiHookLogger.Configs.elements(
+ YukiHookLogger.Configs.TAG,
+ YukiHookLogger.Configs.PRIORITY,
+ YukiHookLogger.Configs.PACKAGE_NAME,
+ YukiHookLogger.Configs.USER_ID
+ )
+ YukiHookAPI.Configs.isDebug = BuildConfig.DEBUG
+ YukiHookAPI.Configs.isEnableModulePrefsCache = true
+ YukiHookAPI.Configs.isEnableModuleAppResourcesCache = true
+ YukiHookAPI.Configs.isEnableHookModuleStatus = true
+ YukiHookAPI.Configs.isEnableHookSharedPreferences = false
+ YukiHookAPI.Configs.isEnableDataChannel = true
+ YukiHookAPI.Configs.isEnableMemberCache = true
+ }
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
- method
encase fun encase(initiate: PackageParam.() -> Unit)
+
fun encase(vararg hooker: YukiBaseHooker)
+
fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
+
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
+
v1.0
添加
Yuki Hook API
- annotation
InjectYukiHookWithXposed annotation class InjectYukiHookWithXposed(
+ val sourcePath: String,
+ val modulePackageName: String,
+ val entryClassName: String,
+ val isUsingResourcesHook: Boolean
+)
+
v1.0
添加
v1.0.80
修改
entryClassName
参数v1.0.92
修改
isUsingResourcesHook
参数YukiHookAPI
注入 Xposed 入口的类注解。Yuki Hook API
- class
CurrentClass class CurrentClass internal constructor(internal val classSet: Class<*>, internal val instance: Any)
+
v1.0.70
新增
v1.1.0
修改
- field
name val name: String
+
v1.1.0
新增
classSet
的 Class.getName
。- field
simpleName val simpleName: String
+
v1.1.0
新增
classSet
的 Class.getSimpleName
。- method
generic fun generic(): GenericClass?
+
v1.1.0
新增
null
。- method
generic inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
v1.1.0
新增
null
。- method
superClass fun superClass(): SuperClass
+
v1.0.80
新增
- method
field inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
v1.0.70
新增
- method
method inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
v1.0.70
新增
- class
SuperClass inner class SuperClass internal constructor(internal val superClassSet: Class<*>)
+
v1.0.80
新增
v1.1.0
修改
superClassSet
参数- field
name val name: String
+
v1.1.0
新增
classSet
中父类的 Class.getName
。- field
simpleName val simpleName: String
+
v1.1.0
新增
classSet
中父类的 Class.getSimpleName
。- method
generic fun generic(): GenericClass?
+
v1.1.0
新增
null
。- method
generic inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
+
v1.1.0
新增
null
。- method
field inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
+
v1.0.80
新增
- method
method inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+
v1.0.80
新增
Yuki Hook API
- class
GenericClass class GenericClass internal constructor(private val type: ParameterizedType)
+
v1.1.0
新增
Class
的泛型父类操作对象。- method
argument fun argument(index: Int): Class<*>
+
v1.1.0
新增
Class
实例。Yuki Hook API
- class
HookClass class HookClass internal constructor(internal var instance: Class<*>?, internal var name: String, internal var throwable: Throwable?)
+
v1.0
添加
v1.1.0
修改
HookClass
相关功能不再对外开放Class
接管类。instance
为实例,name
为实例完整包名,throwable
为找不到实例的时候抛出的异常。Yuki Hook API
- class
HookResources class HookResources internal constructor(var instance: YukiResources?)
+
v1.0.80
新增
YukiResources
接管类。Yuki Hook API
- class
VariousClass class VariousClass(vararg var name: String)
+
v1.0
添加
Class
类名装载器,通过 name
装载 Class
名称数组。- method
get fun get(loader: ClassLoader? = null): Class<*>
+
v1.0.70
新增
loader
装载目标 Class
。- method
getOrNull fun getOrNull(loader: ClassLoader? = null): Class<*>?
+
v1.1.0
新增
loader
装载目标 Class
。Class
会返回 null
,不会抛出异常。Yuki Hook API
- class
YukiMemberHookCreator class YukiMemberHookCreator(internal val packageParam: PackageParam, internal val hookClass: HookClass)
+
v1.0
添加
v1.0.80
修改
hookClass
进行 inline 处理v1.1.0
修改
YukiHookAPI
的 Member
核心 Hook 实现类。- field
PRIORITY_DEFAULT val PRIORITY_DEFAULT: Int
+
v1.0.80
新增
- field
PRIORITY_LOWEST val PRIORITY_LOWEST: Int
+
v1.0.80
新增
- field
PRIORITY_HIGHEST val PRIORITY_HIGHEST: Int
+
v1.0.80
新增
- field
instanceClass val instanceClass: Class<*>
+
v1.0
添加
v1.0.2
修改
更名为 thisClass
instanceClass
Class
。- method
injectMember inline fun injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
+
v1.0
添加
v1.0.80
修改
priority
Hook 优先级Method
、Constructor
。Method
与 Constructor
,使用 injectMember
即可创建一个 Hook
对象。injectMember {
+ // Your code here.
+}
+
tag
,方便你在调试的时候能够区分你的 Hook
对象。injectMember(tag = "KuriharaYuki") {
+ // Your code here.
+}
+
priority
,以控制当前 Hook 对象并列执行的优先级速度。injectMember(priority = PRIORITY_HIGHEST) {
+ // Your code here.
+}
+
- method
useDangerousOperation fun useDangerousOperation(option: String)
+
v1.1.0
新增
option
中键入 Yes do as I say!
代表你同意允许所有危险行为。CauseProblemsApi
以消除警告。ClassLoader
的 loadClass
方法,请参考 ClassLoader.onLoadClass。- class
MemberHookCreator inner class MemberHookCreator internal constructor(private val priority: Int, internal val tag: String)
+
v1.0
添加
v1.0.80
修改
priority
Hook 优先级v1.0.81
修改
packageName
当前 Hook 的 APP 包名v1.1.0
修改
packageName
Method
、Constructor
。member - field
v1.0
添加
v1.1.0
移除
members
- method
members fun members(vararg member: Member?)
+
v1.1.0
新增
Method
、Constructor
。instanceClass
来手动查找要 Hook 的 Method
、Constructor
。injectMember {
+ members(instanceClass.getDeclaredMethod("test", StringType))
+ beforeHook {}
+ afterHook {}
+}
+
Member
同时进行 Hook。injectMember {
+ members(
+ instanceClass.getDeclaredMethod("test1", StringType),
+ instanceClass.getDeclaredMethod("test2", StringType),
+ instanceClass.getDeclaredMethod("test3", StringType)
+ )
+ beforeHook {}
+ afterHook {}
+}
+
allMethods - method
v1.0
添加
v1.1.0
作废
method { name = /** name */ }.all()
来取代它allConstructors - method
v1.0
添加
v1.1.0
作废
allMembers(MembersType.CONSTRUCTOR)
来取代它- method
allMembers fun allMembers(type: MembersType)
+
v1.1.0
新增
hookClass
中的全部 Method
、Constructor
。- method
method inline fun method(initiate: MethodConditions): MethodFinder.Result
+
v1.0
添加
v1.0.80
修改
Class
需要 Hook 的 Method
。injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = UnitType
+ }
+ beforeHook {}
+ afterHook {}
+}
+
method { ... }
条件的全部结果,你只需要在最后加入 all
即可。injectMember {
+ method {
+ name = "test"
+ paramCount(1..5)
+ }.all()
+ beforeHook {}
+ afterHook {}
+}
+
beforeHook
与 afterHook
会在每个查找到的结果中多次回调 Hook 方法体。- method
constructor inline fun constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
v1.0
添加
v1.0.80
修改
Class
需要 Hook 的 Constructor
。injectMember {
+ constructor { param(StringType) }
+ beforeHook {}
+ afterHook {}
+}
+
constructor { ... }
条件的全部结果,你只需要在最后加入 all
即可。injectMember {
+ constructor { paramCount(1..5) }.all()
+ beforeHook {}
+ afterHook {}
+}
+
beforeHook
与 afterHook
会在每个查找到的结果中多次回调 Hook 方法体。- i-ext-method
HookParam.field inline fun HookParam.field(initiate: FieldConditions): FieldFinder.Result
+
v1.0
添加
v1.0.80
修改
hookClass
查找并得到 Field
。injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = UnitType
+ }
+ afterHook {
+ // 这里不需要再调用 instanceClass.field 进行查找
+ field {
+ name = "isSweet"
+ type = BooleanType
+ }.get(instance).setTrue()
+ }
+}
+
- i-ext-method
HookParam.method inline fun HookParam.method(initiate: MethodConditions): MethodFinder.Result
+
v1.0.2
添加
v1.0.80
修改
hookClass
查找并得到 Method
。- i-ext-method
HookParam.constructor inline fun HookParam.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
v1.0.2
添加
v1.0.80
修改
hookClass
查找并得到 Constructor
。- i-ext-method
HookParam.injectMember inline fun HookParam.injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
+
v1.0.88
新增
Method
、Constructor
(嵌套 Hook)。- method
beforeHook fun beforeHook(initiate: HookParam.() -> Unit): HookCallback
+
v1.0
添加
v1.1.0
修改
HookCallback
返回类型Member
执行完成前 Hook。- method
afterHook fun afterHook(initiate: HookParam.() -> Unit): HookCallback
+
v1.0
添加
v1.1.0
修改
HookCallback
返回类型Member
执行完成后 Hook。- method
replaceAny fun replaceAny(initiate: HookParam.() -> Any?)
+
v1.0
添加
Member
内容,给出返回值。- method
replaceUnit fun replaceUnit(initiate: HookParam.() -> Unit)
+
v1.0
添加
Member
内容,没有返回值,可以称为 Void
。- method
replaceTo fun replaceTo(any: Any?)
+
v1.0
添加
Member
返回值。- method
replaceToTrue fun replaceToTrue()
+
v1.0
添加
Member
返回值为 true
。- method
replaceToFalse fun replaceToFalse()
+
v1.0
添加
Member
返回值为 false
。- method
intercept fun intercept()
+
v1.0
添加
Member
。Member
执行并返回 null
。- method
removeSelf fun removeSelf(result: (Boolean) -> Unit)
+
v1.1.0
新增
Method
、Constructor
(解除 Hook)。- class
HookCallback inner class HookCallback internal constructor()
+
v1.1.0
新增
- method
onFailureThrowToApp fun onFailureThrowToApp()
+
v1.1.0
新增
- class
Result inner class Result internal constructor()
+
v1.0
添加
- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0
添加
v1.0.5
修改
修改为 failures
result
v1.0.80
修改
Result
类创建 lambda
方法体。injectMember {
+ // Your code here.
+}.result {
+ onHooked {}
+ onAlreadyHooked {}
+ ignoredConductFailure()
+ onHookingFailure {}
+ // ...
+}
+
- method
by inline fun by(condition: () -> Boolean): Result
+
v1.0.5
新增
v1.0.80
修改
- method
onHooked fun onHooked(result: (Member) -> Unit): Result
+
v1.0.70
新增
members
Hook 成功的回调方法。onAlreadyHooked
。- method
onAlreadyHooked fun onAlreadyHooked(result: (Member) -> Unit): Result
+
v1.0.89
新增
members
重复 Hook 的回调方法。- method
onNoSuchMemberFailure fun onNoSuchMemberFailure(result: (Throwable) -> Unit): Result
+
v1.0.5
新增
members
不存在发生错误的回调方法。- method
onConductFailure fun onConductFailure(result: (HookParam, Throwable) -> Unit): Result
+
v1.0
添加
- method
onHookingFailure fun onHookingFailure(result: (Throwable) -> Unit): Result
+
v1.0
添加
- method
onAllFailure fun onAllFailure(result: (Throwable) -> Unit): Result
+
v1.0
添加
- method
ignoredNoSuchMemberFailure fun ignoredNoSuchMemberFailure(): Result
+
v1.0.5
新增
members
不存在发生的错误。- method
ignoredConductFailure fun ignoredConductFailure(): Result
+
v1.0
添加
- method
ignoredHookingFailure fun ignoredHookingFailure(): Result
+
v1.0
添加
- method
ignoredAllFailure fun ignoredAllFailure(): Result
+
v1.0
添加
- method
remove fun remove(result: (Boolean) -> Unit)
+
v1.1.0
新增
Method
、Constructor
(解除 Hook)。- class
Result inner class Result internal constructor()
+
v1.0.3
新增
- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0.3
新增
v1.0.5
修改
修改为 failures
result
v1.0.80
修改
- method
by inline fun by(condition: () -> Boolean): Result
+
v1.0.5
新增
v1.0.80
修改
- method
onPrepareHook fun onPrepareHook(callback: () -> Unit): Result
+
v1.0.70
新增
hookClass
存在时准备开始 Hook 的操作。- method
onHookClassNotFoundFailure fun onHookClassNotFoundFailure(result: (Throwable) -> Unit): Result
+
v1.0.3
新增
hookClass
找不到时发生错误的回调方法。- method
ignoredHookClassNotFoundFailure fun ignoredHookClassNotFoundFailure(): Result
+
v1.0.3
新增
hookClass
找不到时出现的错误。Yuki Hook API
- class
YukiResourcesHookCreator class YukiResourcesHookCreator(internal val packageParam: PackageParam, internal val hookResources: HookResources)
+
v1.0.80
新增
v1.1.0
修改
YukiHookAPI
的 Resources
核心 Hook 实现类。- method
injectResource inline fun injectResource(tag: String, initiate: ResourceHookCreator.() -> Unit): ResourceHookCreator.Result
+
v1.0.80
新增
injectResource
即可创建一个 Hook
对象。injectResource {
+ // Your code here.
+}
+
tag
,方便你在调试的时候能够区分你的 Hook
对象。injectResource(tag = "KuriharaYuki") {
+ // Your code here.
+}
+
- class
ResourcesHookCreator inner class ResourcesHookCreator internal constructor(private val tag: String)
+
v1.0.80
新增
v1.1.0
修改
packageName
- field
resourceId var resourceId: Int
+
v1.0.80
新增
injectResource {
+ resourceId = 0x7f060001.toInt()
+ replaceTo(...)
+}
+
- method
conditions inline fun conditions(initiate: ConditionFinder.() -> Unit)
+
v1.0.80
新增
resourceId
则此方法将不会被使用。injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceTo(...)
+}
+
- method
replaceTo fun replaceTo(any: Any)
+
v1.0.80
新增
String
、Drawable
等。injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceTo("replace string")
+}
+
Drawable
,你无需对目标 Resources 实现 fwd
方法或 DrawableLoader
。injectResource {
+ conditions {
+ name = "test_drawable"
+ drawable()
+ }
+ replaceTo(ColorDrawable(Color.RED))
+}
+
- method
replaceToTrue fun replaceToTrue()
+
v1.0.80
新增
true
。- method
replaceToFalse fun replaceToFalse()
+
v1.0.80
新增
false
。- method
replaceToModuleResource fun replaceToModuleResource(resId: Int)
+
v1.0.80
新增
R.string.xxx
、R.mipmap.xxx
、R.drawable.xxx
替换 Hook APP 的 Resources。fwd
方法。injectResource {
+ conditions {
+ name = "test_string"
+ string()
+ }
+ replaceToModuleResource(R.string.module_string)
+}
+
xml
创建的 drawable
。injectResource {
+ conditions {
+ name = "test_drawable"
+ drawable()
+ }
+ replaceToModuleResource(R.drawable.module_drawable)
+}
+
- method
injectAsLayout fun injectAsLayout(initiate: YukiResources.LayoutInflatedParam.() -> Unit)
+
v1.0.80
新增
View
。injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ findViewByIdentifier<View>(name = "test_view")?.isVisible = false
+ findViewByIdentifier<TextView>(name = "test_text_view")?.text = "Hook this"
+ }
+}
+
currentView
拿到 Context
。injectResource {
+ conditions {
+ name = "activity_main"
+ layout()
+ }
+ injectAsLayout {
+ Toast.makeText(currentView.context, "Hook this", Toast.LENGTH_SHORT).show()
+ }
+}
+
- class
ConditionFinder inner class ConditionFinder internal constructor()
+
v1.0.80
新增
- field
name var name: String
+
v1.0.80
新增
- method
anim fun anim()
+
v1.0.80
新增
- method
animator fun animator()
+
v1.0.80
新增
- method
bool fun bool()
+
v1.0.80
新增
- method
color fun color()
+
v1.0.80
新增
- method
dimen fun dimen()
+
v1.0.80
新增
- method
drawable fun drawable()
+
v1.0.80
新增
- method
integer fun integer()
+
v1.0.80
新增
- method
layout fun layout()
+
v1.0.80
新增
- method
plurals fun plurals()
+
v1.0.80
新增
- method
string fun string()
+
v1.0.80
新增
- method
xml fun xml()
+
v1.0.80
新增
- method
mipmap fun mipmap()
+
v1.0.80
新增
- method
array fun array()
+
v1.1.0
新增
- class
Result inner class Result internal constructor()
+
v1.0.80
新增
- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0.80
新增
- method
by inline fun by(condition: () -> Boolean): Result
+
v1.0.80
新增
- method
onHookingFailure fun onHookingFailure(result: (Throwable) -> Unit): Result
+
v1.0.80
新增
- method
ignoredHookingFailure fun ignoredHookingFailure(): Result
+
v1.0.80
新增
Yuki Hook API
- class
BaseFinder abstract class BaseFinder
+
v1.0.70
新增
v1.1.0
修改
BaseFinder
中的部分方法与参数到 MemberBaseFinder
Class
与 Member
查找类功能的基本类实现。- class
BaseFinder.IndexTypeCondition inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
+
v1.0.70
新增
- method
index fun index(num: Int)
+
v1.0.70
新增
index
小于零则为倒序,此时可以使用 IndexTypeConditionSort.reverse
方法实现。IndexTypeConditionSort.first
和 IndexTypeConditionSort.last
设置首位和末位筛选条件。- method
index fun index(): IndexTypeConditionSort
+
v1.0.70
新增
- class
IndexTypeConditionSort inner class IndexTypeConditionSort internal constructor()
+
v1.0.70
新增
- method
first fun first()
+
v1.0.70
新增
- method
last fun last()
+
v1.0.70
新增
- method
reverse fun reverse(num: Int)
+
v1.0.70
新增
Yuki Hook API
- class
CountRules class CountRules private constructor()
+
v1.1.0
新增
Class
、Member
数组 (下标) 个数条件实现类。Class
、Member
进行更加详细的定位。- i-ext-method
Int.isZero fun Int.isZero(): Boolean
+
v1.1.0
新增
- i-ext-method
Int.moreThan fun Int.moreThan(count: Int): Boolean
+
v1.1.0
新增
count
。- i-ext-method
Int.lessThan fun Int.lessThan(count: Int): Boolean
+
v1.1.0
新增
count
。- i-ext-method
Int.inInterval fun Int.inInterval(countRange: IntRange): Boolean
+
v1.1.0
新增
countRange
区间 A ≤ this ≤ B。Yuki Hook API
- class
ModifierRules class ModifierRules private constructor()
+
v1.0.67
新增
v1.1.0
修改
Class
的描述符判断Class
、Member
描述符条件实现类。Class
、Member
进行更加详细的定位。- i-ext-field
isPublic val isPublic: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
、Member
类型是否包含 public
。- i-ext-field
isPrivate val isPrivate: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
、Member
类型是否包含 private
。- i-ext-field
isProtected val isProtected: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
、Member
类型是否包含 protected
。- i-ext-field
isStatic val isStatic: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
、Member
类型是否包含 static
。Class
、Member
可添加此描述进行确定。- i-ext-field
isFinal val isFinal: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
、Member
类型是否包含 final
。- i-ext-field
isSynchronized val isSynchronized: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
、Member
类型是否包含 synchronized
。- i-ext-field
isVolatile val isVolatile: Boolean
+
v1.0.67
新增
v1.1.0
修改
Field
类型是否包含 volatile
。- i-ext-field
isTransient val isTransient: Boolean
+
v1.0.67
新增
v1.1.0
修改
Field
类型是否包含 transient
。- i-ext-field
isNative val isNative: Boolean
+
v1.0.67
新增
v1.1.0
修改
Method
类型是否包含 native
。Method
可添加此描述进行确定。- i-ext-field
isInterface val isInterface: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
类型是否包含 interface
。- i-ext-field
isAbstract val isAbstract: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
、Member
类型是否包含 abstract
。Class
、Member
可添加此描述进行确定。- i-ext-field
isStrict val isStrict: Boolean
+
v1.0.67
新增
v1.1.0
修改
Class
、Member
类型是否包含 strictfp
。Yuki Hook API
- class
NameRules class NameRules private constructor()
+
v1.0.88
新增
v1.1.0
修改
NameConditions
更名为 NameRules
Class
、Member
名称条件实现类。Class
、Member
进行更加详细的定位。- i-ext-method
String.isSynthetic fun String.isSynthetic(index: Int): Boolean
+
v1.0.88
新增
v1.1.0
修改
- i-ext-method
String.isOnlySymbols fun String.isOnlySymbols(): Boolean
+
v1.0.88
新增
v1.1.0
修改
- i-ext-method
String.isOnlyLetters fun String.isOnlyLetters(): Boolean
+
v1.0.88
新增
v1.1.0
修改
- i-ext-method
String.isOnlyNumbers fun String.isOnlyNumbers(): Boolean
+
v1.0.88
新增
v1.1.0
修改
- i-ext-method
String.isOnlyLettersNumbers fun String.isOnlyLettersNumbers(): Boolean
+
v1.0.88
新增
v1.1.0
修改
- i-ext-method
String.isOnlyLowercase fun String.isOnlyLowercase(): Boolean
+
v1.0.88
新增
v1.1.0
修改
- i-ext-method
String.isOnlyUppercase fun String.isOnlyUppercase(): Boolean
+
v1.0.88
新增
v1.1.0
修改
Yuki Hook API
- class
DexClassFinder class DexClassFinder internal constructor(
+ internal var name: String,
+ internal var async: Boolean,
+ override val loaderSet: ClassLoader?
+) : ClassBaseFinder
+
v1.1.0
新增
Class
查找类。BaseDexClassLoader
通过指定条件查找指定 Class
或一组 Class
。- object
companion object v1.1.0
新增
- method
clearCache fun clearCache(context: Context?, versionName: String?, versionCode: Long?)
+
v1.1.0
新增
DexClassFinder
的 Class
缓存。DexClassFinder
。- field
fullName var fullName: String
+
v1.1.0
新增
Class
完整名称。Class.getName
。com.demo.Test
需要填写 com.demo.Test
。- field
simpleName var simpleName: String
+
v1.1.0
新增
Class
简单名称。Class.getSimpleName
。com.demo.Test
只需要填写 Test
。com.demo.Test$InnerTest
会为空,此时你可以使用 singleName。- field
singleName var singleName: String
+
v1.1.0
新增
Class
独立名称。Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。com.demo.Test
只需要填写 Test
。com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。- method
from fun from(vararg name: String): FromPackageRules
+
v1.1.0
新增
Class
。name
开头匹配的包名路径下进行查找,可提升查找速度。com.demo.test
com.demo.test.demo
- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
新增
Class
标识符筛选条件。- method
fullName fun fullName(value: String): ClassNameRules
+
v1.1.0
新增
Class
完整名称。Class.getName
。com.demo.Test
需要填写 com.demo.Test
。- method
simpleName fun simpleName(value: String): ClassNameRules
+
v1.1.0
新增
Class
简单名称。Class.getSimpleName
。com.demo.Test
只需要填写 Test
。com.demo.Test$InnerTest 会为空
,此时你可以使用 singleName。- method
singleName fun singleName(value: String): ClassNameRules
+
v1.1.0
新增
Class
独立名称。Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。com.demo.Test
只需要填写 Test
。com.demo.Test$InnerTest
只需要填写 Test$InnerTest
。- method
fullName fun fullName(conditions: NameConditions)
+
v1.1.0
新增
Class
完整名称条件。Class.getName
。- method
simpleName fun simpleName(conditions: NameConditions)
+
v1.1.0
新增
Class
简单名称条件。Class.getSimpleName
。- method
singleName fun singleName(conditions: NameConditions)
+
v1.1.0
新增
Class
独立名称条件。Class.getSimpleName
,若为空则会使用 Class.getName
进行处理。- method
extends inline fun <reified T> extends()
+
v1.1.0
新增
Class
继承的父类。- method
extends fun extends(vararg name: String)
+
v1.1.0
新增
Class
继承的父类。name
中所有匹配的父类。- method
implements inline fun <reified T> implements()
+
v1.1.0
新增
Class
实现的接口类。- method
implements fun implements(vararg name: String)
+
v1.1.0
新增
Class
实现的接口类。name
中所有匹配的接口类。- method
anonymous fun anonymous()
+
v1.1.0
新增
Class
为匿名类。com.demo.Test$1
或 com.demo.Test$InnerTest
。- method
noExtends fun noExtends()
+
v1.1.0
新增
Class
没有任何继承。Class
只应该继承于 Any
。- method
noImplements fun noImplements()
+
v1.1.0
新增
Class
没有任何接口。- method
noSuper fun noSuper()
+
v1.1.0
新增
Class
没有任何继承与接口。Class
只应该继承于 Any
。- method
enclosing inline fun <reified T> enclosing()
+
v1.1.0
新增
Class
匿名类的 (封闭类) 主类。- method
enclosing fun enclosing(vararg name: String)
+
v1.1.0
新增
Class
匿名类的 (封闭类) 主类。name
中所有匹配的 (封闭类) 主类。- class
FromPackageRules inner class FromPackageRules internal constructor(private val packages: ArrayList<ClassRulesData.PackageRulesData>)
+
v1.1.0
新增
- method
absolute fun absolute()
+
v1.1.0
新增
com.demo.test.a
com.demo.test.a.b
com.demo.test.active
com.demo.test.a
则绝对匹配仅能匹配到第一个。- class
ClassNameRules inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
+
v1.1.0
新增
- method
optional fun optional()
+
v1.1.0
新增
com.demo.Test
fullName / Test
simpleNamedefpackage.a
fullName / a
simpleNamecom.demo.Test
fullName / Test
simpleName。- method
member inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+
v1.1.0
新增
Class
满足的 Member
条件。- method
field inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+
v1.1.0
新增
Class
满足的 Field
条件。- method
method inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+
v1.1.0
新增
Class
满足的 Method
条件。- method
constructor inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+
v1.1.0
新增
Class
满足的 Constructor
条件。- class
Result inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
+
v1.1.0
新增
Class
查找结果实现类。- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.1.0
新增
- method
get fun get(): Class<*>?
+
v1.1.0
新增
Class
本身。Class
结果只会返回第一个。null
。async
请使用 wait 方法。- method
all fun all(): HashSet<Class<*>>
+
v1.1.0
新增
Class
本身数组。Class
实例。HashSet
。async
请使用 waitAll 方法。- method
all fun all(result: (Class<*>) -> Unit): Result
+
v1.1.0
新增
Class
本身数组 (依次遍历)。Class
实例。async
请使用 waitAll 方法。- method
wait fun wait(result: (Class<*>?) -> Unit): Result
+
v1.1.0
新增
Class
本身 (异步)。Class
结果只会回调第一个。async
后此方法才会被回调,否则请使用 get 方法。- method
waitAll fun waitAll(result: (HashSet<Class<*>>) -> Unit): Result
+
v1.1.0
新增
Class
本身数组 (异步)。Class
实例。HashSet
。async
后此方法才会被回调,否则请使用 all 方法。- method
onNoClassDefFoundError fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+
v1.1.0
新增
Class
时。- method
ignored fun ignored(): Result
+
v1.1.0
新增
Yuki Hook API
- class
ConstructorRules class ConstructorRules internal constructor(internal val rulesData: ConstructorRulesData) : BaseRules
+
v1.1.0
新增
Constructor
查找条件实现类。- field
paramCount var paramCount: Int
+
v1.1.0
新增
Constructor
参数个数。param
指定参数类型而是仅使用此变量指定参数个数。param
。- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
新增
Constructor
标识符筛选条件。- method
emptyParam fun emptyParam()
+
v1.1.0
新增
Constructor
空参数、无参数。- method
param fun param(vararg paramType: Any)
+
v1.1.0
新增
Constructor
参数。paramCount
则 paramType
的数量必须与 paramCount
完全匹配。Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。- method
paramCount fun paramCount(numRange: IntRange)
+
v1.1.0
新增
Constructor
参数个数范围。param
指定参数类型而是仅使用此方法指定参数个数范围。- method
paramCount fun paramCount(conditions: CountConditions)
+
v1.1.0
新增
Constructor
参数个数条件。param
指定参数类型而是仅使用此方法指定参数个数条件。Yuki Hook API
- class
FieldRules class FieldRules internal constructor(internal val rulesData: FieldRulesData) : BaseRules
+
v1.1.0
新增
Field
查找条件实现类。- field
name var name: String
+
v1.1.0
新增
Field
名称。- field
type var type: Any?
+
v1.1.0
新增
Field
类型。- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
新增
Field
标识符筛选条件。- method
name fun name(conditions: NameConditions)
+
v1.1.0
新增
Field
名称条件。Yuki Hook API
- class
MemberRules class MemberRules internal constructor(internal val rulesData: MemberRulesData) : BaseRules
+
v1.1.0
新增
Member
查找条件实现类。- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
新增
Member
标识符筛选条件。Yuki Hook API
- class
MethodRules class MethodRules internal constructor(internal val rulesData: MethodRulesData) : BaseRules
+
v1.1.0
新增
Method
查找条件实现类。- field
name var name: String
+
v1.1.0
新增
Method
名称。- field
paramCount var paramCount: Int
+
v1.1.0
新增
Method
参数个数。param
指定参数类型而是仅使用此变量指定参数个数。param
。- field
returnType var returnType: Any?
+
v1.1.0
新增
Method
返回值。- method
modifiers fun modifiers(conditions: ModifierConditions)
+
v1.1.0
新增
Method
标识符筛选条件。- method
emptyParam fun emptyParam()
+
v1.1.0
新增
Method
空参数、无参数。- method
param fun param(vararg paramType: Any)
+
v1.1.0
新增
Method
参数。paramCount
则 paramType
的数量必须与 paramCount
完全匹配。Method
中存在一些无意义又很长的类型,你可以使用 VagueType
来替代它。- method
name fun name(conditions: NameConditions)
+
v1.1.0
新增
Method
名称条件。- method
paramCount fun paramCount(numRange: IntRange)
+
v1.1.0
新增
Method
参数个数范围。param
指定参数类型而是仅使用此方法指定参数个数范围。- method
paramCount fun paramCount(conditions: CountConditions)
+
v1.1.0
新增
Method
参数个数条件。param
指定参数类型而是仅使用此方法指定参数个数条件。Yuki Hook API
- class
MemberRulesResult class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
+
v1.1.0
新增
Member
查找条件结果实现类。- method
none fun none(): MemberRulesResult
+
v1.1.0
新增
Member
在查找条件中个数为 0
。- method
count fun count(num: Int): MemberRulesResult
+
v1.1.0
新增
Member
在查找条件中需要全部匹配的个数。- method
count fun count(numRange: IntRange): MemberRulesResult
+
v1.1.0
新增
Member
在查找条件中需要全部匹配的个数范围。- method
count fun count(conditions: CountConditions): MemberRulesResult
+
v1.1.0
新增
Member
在查找条件中需要全部匹配的个数条件。Yuki Hook API
- class
ConstructorFinder class ConstructorFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
+
v1.0
添加
v1.0.2
修改
BaseFinder
v1.1.0
修改
MemberBaseFinder
Constructor
查找类。Constructor
或一组 Constructor
。- field
paramCount var paramCount: Int
+
v1.0.67
新增
Constructor
参数个数。param
指定参数类型而是仅使用此变量指定参数个数。param
。- method
modifiers fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
v1.0.67
新增
v1.0.80
修改
v1.1.0
修改
ModifierConditions
Constructor
标识符筛选条件。Constructor
。- method
emptyParam fun emptyParam(): IndexTypeCondition
+
v1.0.75
新增
Constructor
空参数、无参数。- method
param fun param(vararg paramType: Any): IndexTypeCondition
+
v1.0
添加
Constructor
参数。paramCount
则 paramType
的数量必须与 paramCount
完全匹配。Constructor
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。- method
paramCount fun paramCount(num: Int): IndexTypeCondition
+
v1.0.70
新增
Constructor
参数个数。param
指定参数类型而是仅使用此方法指定参数个数。param
。- method
paramCount fun paramCount(numRange: IntRange): IndexTypeCondition
+
v1.1.0
新增
Constructor
参数个数范围。param
指定参数类型而是仅使用此方法指定参数个数范围。- method
paramCount fun paramCount(conditions: CountConditions): IndexTypeCondition
+
v1.1.0
新增
Constructor
参数个数条件。param
指定参数类型而是仅使用此方法指定参数个数条件。- method
superClass fun superClass(isOnlySuperClass: Boolean)
+
v1.0.80
新增
classSet
的所有父类中查找当前 Constructor
。- class
RemedyPlan inner class RemedyPlan internal constructor()
+
v1.0
添加
Constructor
重查找实现类,可累计失败次数直到查找成功。- method
constructor inline fun constructor(initiate: ConstructorConditions)
+
v1.0
添加
v1.0.80
修改
Constructor
。Constructor
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。- class
Result inner class Result internal constructor()
+
v1.0.1
新增
RemedyPlan
结果实现类。- method
onFind fun onFind(initiate: HashSet<Constructor<*>>.() -> Unit)
+
v1.0.1
新增
v1.1.0
修改
initiate
参数 Constructor
变为 HashSet<Constructor>
RemedyPlan
中找到结果时。Constructor
实现 onFind
方法。constructor {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
- class
Process inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
v1.1.0
新增
Constructor
查找结果处理类,为 hookInstance
提供。- method
result inline fun result(initiate: Process.() -> Unit): Process
+
v1.1.0
新增
lambda
形式创建 Result
类。constructor {
+ // Your code here.
+}.result {
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
- method
all fun all(): Process
+
v1.1.0
新增
Constructor
实例结果到 hookInstance
。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.1.0
新增
Constructor
重查找功能。Constructor
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchConstructor
捕获异常二次查找 Constructor
。constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
- method
onNoSuchConstructor inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
v1.1.0
新增
Constructor
时。RemedyPlan
的错误信息。- class
Result inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
v1.0
添加
v1.1.0
修改
BaseResult
Constructor
查找结果实现类。- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0
添加
v1.0.80
修改
lambda
形式创建 Result
类。constructor {
+ // Your code here.
+}.result {
+ get().call()
+ all()
+ remedys {}
+ onNoSuchConstructor {}
+}
+
- method
get fun get(): Instance
+
v1.0.2
新增
Constructor
实例处理类。Constructor
结果只会返回第一个。constructor {
+ // Your code here.
+}.get().call()
+
cast
构造方法为指定类型的实例对象。constructor {
+ // Your code here.
+}.get().newInstance<TestClass>()
+
constructor {
+ // Your code here.
+}.get().newInstance<TestClass>("param1", "param2")
+
- method
all fun all(): ArrayList<Instance>
+
v1.1.0
新增
Constructor
实例处理类数组。Constructor
实例结果。Constructor
。constructor {
+ // Your code here.
+}.all().forEach { instance ->
+ instance.call(...)
+}
+
- method
give fun give(): Constructor<*>?
+
v1.0.67
新增
Constructor
本身。Constructor
结果只会返回第一个。null
。- method
giveAll fun giveAll(): HashSet<Constructor<*>>
+
v1.1.0
新增
Constructor
本身数组。Constructor
实例。HashSet
。- method
wait fun wait(initiate: Instance.() -> Unit)
+
v1.0.2
新增
Constructor
实例处理类,配合 RemedyPlan
使用。Constructor
结果只会返回第一个。- method
waitAll fun waitAll(initiate: ArrayList<Instance>.() -> Unit)
+
v1.1.0
新增
Constructor
实例处理类数组,配合 RemedyPlan
使用。Constructor
实例结果。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.0
添加
v1.0.80
修改
Constructor
重查找功能。Constructor
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchConstructor
捕获异常二次查找 Constructor
。constructor {
+ // Your code here.
+}.remedys {
+ constructor {
+ // Your code here.
+ }
+ constructor {
+ // Your code here.
+ }
+}
+
- method
onNoSuchConstructor inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
+
v1.0
添加
v1.0.80
修改
Constructor
时。RemedyPlan
的错误信息。- method
ignored fun ignored(): Result
+
v1.1.0
新增
isNotIgnoredHookingFailure
为 false
则自动忽略。ignoredError - method
v1.0.3
新增
v1.1.0
作废
ignored()
- class
Instance inner class Instance internal constructor(private val constructor: Constructor<*>?)
+
v1.0.2
新增
v1.1.0
修改
constructor
参数Constructor
实例处理类。- method
call fun call(vararg param: Any?): Any?
+
v1.0.2
新增
Constructor
创建目标实例,不指定目标实例类型。- method
newInstance fun <T> newInstance(vararg param: Any?): T?
+
v1.0.2
新增
Constructor
创建目标实例 ,指定 T
目标实例类型。Yuki Hook API
- class
FieldFinder class FieldFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>?) : MemberBaseFinder
+
v1.0
添加
v1.0.2
修改
BaseFinder
v1.1.0
修改
MemberBaseFinder
Field
查找类。Field
或一组 Field
。classSet - field
v1.0
添加
v1.0.2
移除
- field
name var name: String
+
v1.0
添加
v1.0.70
修改
Field
名称。- field
type var type: Any?
+
v1.0
添加
Field
类型。- method
modifiers fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
v1.0.67
新增
v1.0.80
修改
v1.1.0
修改
ModifierConditions
Field
标识符筛选条件。- method
order fun order(): IndexTypeCondition
+
v1.0.70
新增
- method
name fun name(value: String): IndexTypeCondition
+
v1.0.70
新增
Field
名称。- method
name fun name(conditions: NameConditions): IndexTypeCondition
+
v1.0.88
新增
v1.1.0
修改
NameConditions
Field
名称条件。- method
type fun type(value: Any): IndexTypeCondition
+
v1.0.70
新增
Field
类型。- method
superClass fun superClass(isOnlySuperClass: Boolean)
+
v1.0.80
新增
classSet
的所有父类中查找当前 Field
。- class
RemedyPlan inner class RemedyPlan internal constructor()
+
v1.1.0
新增
Field
重查找实现类,可累计失败次数直到查找成功。- method
field inline fun field(initiate: FieldConditions): Result
+
v1.1.0
新增
Field
。Field
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。- class
Result inner class Result internal constructor()
+
v1.1.0
新增
RemedyPlan
结果实现类。- method
onFind fun onFind(initiate: HashSet<Field>.() -> Unit)
+
v1.1.0
新增
RemedyPlan
中找到结果时。Field
实现 onFind
方法。field {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
- class
Result inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
+
v1.0
添加
v1.1.0
修改
BaseResult
Field
查找结果实现类。- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0
添加
v1.0.80
修改
lambda
形式创建 Result
类。field {
+ // Your code here.
+}.result {
+ get(instance).set("something")
+ get(instance).string()
+ get(instance).cast<CustomClass>()
+ get().boolean()
+ all(instance)
+ give()
+ giveAll()
+ onNoSuchField {}
+}
+
- method
get fun get(instance: Any?): Instance
+
v1.0
添加
Field
实例处理类。Field
结果只会返回第一个。Field
的实例以及使用它进行设置实例。field {
+ // Your code here.
+}.get(instance).set("something")
+
Field
,可以不需要设置实例。field {
+ // Your code here.
+}.get().set("something")
+
- method
all fun all(instance: Any?): ArrayList<Instance>
+
v1.1.0
新增
Field
实例处理类数组。Field
实例结果。Field
,其 Field
所在实例用法与 get
相同。field {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.self
+}
+
- method
give fun give(): Field?
+
v1.0
添加
Field
本身。null
。- method
giveAll fun giveAll(): HashSet<Field>
+
v1.1.0
新增
Field
本身数组。Field
实例。HashSet
。- method
wait fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
v1.1.0
新增
Field
实例处理类,配合 RemedyPlan
使用。Field
结果只会返回第一个。- method
waitAll fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
+
v1.1.0
新增
Field
实例处理类数组,配合 RemedyPlan
使用。Field
实例结果。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.1.0
新增
Field
重查找功能。Field
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchField
捕获异常二次查找 Field
。field {
+ // Your code here.
+}.remedys {
+ field {
+ // Your code here.
+ }
+ field {
+ // Your code here.
+ }
+}
+
- method
onNoSuchField fun onNoSuchField(result: (Throwable) -> Unit): Result
+
v1.0
添加
Field
时。- method
ignored fun ignored(): Result
+
v1.1.0
新增
isNotIgnoredHookingFailure
为 false
则自动忽略。ignoredError - method
v1.0.3
新增
v1.1.0
作废
ignored()
- class
Instance inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
+
v1.0
添加
v1.1.0
修改
field
参数self
参数Field
实例变量处理类。self - field
v1.0
添加
v1.1.0
移除
any
方法得到 Field
自身的实例化对象- method
current fun current(ignored: Boolean): CurrentClass?
+
inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
+
v1.1.0
新增
Field
自身 self
实例的类操作对象 CurrentClass
。- method
cast fun <T> cast(): T?
+
v1.0
添加
v1.0.68
修改
为 of
cast
Instance
Field
实例。- method
byte fun byte(): Byte?
+
v1.0.68
新增
Field
Byte 实例。- method
int fun int(): Int
+
v1.0.65
新增
v1.0.68
修改
为 ofInt
int
Instance
Field
Int 实例。- method
long fun long(): Long
+
v1.0.65
新增
v1.0.68
修改
为 ofLong
long
Instance
Field
Long 实例。- method
short fun short(): Short
+
v1.0.65
新增
v1.0.68
修改
为 ofShort
short
Instance
Field
Short 实例。- method
double fun double(): Double
+
v1.0.65
新增
v1.0.68
修改
为 ofDouble
double
Instance
Field
Double 实例。- method
float fun float(): Float
+
v1.0.65
新增
v1.0.68
修改
为 ofFloat
float
Instance
Field
Float 实例。- method
string fun string(): String
+
v1.0.65
新增
v1.0.68
修改
为 ofString
string
Instance
Field
String 实例。- method
char fun char(): Char
+
v1.0.68
新增
Field
Char 实例。- method
boolean fun boolean(): Boolean
+
v1.0.65
新增
v1.0.68
修改
为 ofBoolean
boolean
Instance
Field
Boolean 实例。- method
any fun any(): Any?
+
v1.0.65
新增
v1.0.68
修改
为 ofAny
any
Instance
Field
Any 实例。- method
array inline fun <reified T> array(): Array<T>
+
v1.0.68
新增
Field
Array 实例。- method
list inline fun <reified T> list(): List<T>
+
v1.0.68
新增
Field
List 实例。- method
set fun set(any: Any?)
+
v1.0
添加
Field
实例。- method
setTrue fun setTrue()
+
v1.0
添加
Field
实例为 true
。- method
setFalse fun setFalse()
+
v1.0
添加
Field
实例为 false
。- method
setNull fun setNull()
+
v1.0
添加
Field
实例为 null
。Yuki Hook API
- class
MethodFinder class MethodFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
+
v1.0
添加
v1.0.2
修改
BaseFinder
v1.1.0
修改
MemberBaseFinder
Method
查找类。Method
或一组 Method
。- field
name var name: String
+
v1.0
添加
v1.0.70
修改
Method
名称。- field
paramCount var paramCount: Int
+
v1.0.67
新增
Method
参数个数。param
指定参数类型而是仅使用此变量指定参数个数。param
。- field
returnType var returnType: Any?
+
v1.0
添加
Method
返回值,可不填写返回值。- method
modifiers fun modifiers(conditions: ModifierConditions): IndexTypeCondition
+
v1.0.67
新增
v1.0.80
修改
v1.1.0
修改
ModifierConditions
Method
标识符筛选条件。- method
emptyParam fun emptyParam(): IndexTypeCondition
+
v1.0.75
新增
Method
空参数、无参数。- method
param fun param(vararg paramType: Any): IndexTypeCondition
+
v1.0
添加
Method
参数。paramCount
则 paramType
的数量必须与 paramCount
完全匹配。Method
中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。- method
order fun order(): IndexTypeCondition
+
v1.0.70
新增
- method
name fun name(value: String): IndexTypeCondition
+
v1.0.70
新增
Method
名称。- method
name fun name(conditions: NameConditions): IndexTypeCondition
+
v1.0.88
新增
v1.1.0
修改
NameConditions
Method
名称条件。- method
paramCount fun paramCount(num: Int): IndexTypeCondition
+
v1.0.70
新增
Method
参数个数。param
指定参数类型而是仅使用此方法指定参数个数。param
。- method
paramCount fun paramCount(numRange: IntRange): IndexTypeCondition
+
v1.1.0
新增
Method
参数个数范围。param
指定参数类型而是仅使用此方法指定参数个数范围。- method
paramCount fun paramCount(conditions: CountConditions): IndexTypeCondition
+
v1.1.0
新增
Method
参数个数条件。param
指定参数类型而是仅使用此方法指定参数个数条件。- method
returnType fun returnType(value: Any): IndexTypeCondition
+
v1.0.70
新增
Method
返回值。- method
superClass fun superClass(isOnlySuperClass: Boolean)
+
v1.0.80
新增
classSet
的所有父类中查找当前 Method
。- class
RemedyPlan inner class RemedyPlan internal constructor()
+
v1.0
添加
Method
重查找实现类,可累计失败次数直到查找成功。- method
method inline fun method(initiate: MethodConditions): Result
+
v1.0
添加
v1.0.80
修改
Method
。Method
,直到成功为止,若最后依然失败,将停止查找并输出错误日志。- class
Result inner class Result internal constructor()
+
v1.0.1
新增
RemedyPlan
结果实现类。- method
onFind fun onFind(initiate: HashSet<Method>.() -> Unit)
+
v1.0.1
新增
v1.1.0
修改
initiate
参数 Method
变为 HashSet<Method>
RemedyPlan
中找到结果时。Method
实现 onFind
方法。method {
+ // Your code here.
+}.onFind {
+ // Your code here.
+}
+
- class
Process inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
+
v1.1.0
新增
Method
查找结果处理类,为 hookInstance
提供。- method
result inline fun result(initiate: Process.() -> Unit): Process
+
v1.1.0
新增
lambda
形式创建 Result
类。method {
+ // Your code here.
+}.result {
+ all()
+ remedys {}
+ onNoSuchMethod {}
+}
+
- method
all fun all(): Process
+
v1.1.0
新增
Method
实例结果到 hookInstance
。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.1.0
新增
Method
重查找功能。Method
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchMethod
捕获异常二次查找 Method
。method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
- method
onNoSuchMethod inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
v1.1.0
新增
Method
时。RemedyPlan
的错误信息。- class
Result inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
+
v1.0
添加
v1.1.0
修改
BaseResult
Method
查找结果实现类。- method
result inline fun result(initiate: Result.() -> Unit): Result
+
v1.0
添加
v1.0.80
修改
lambda
形式创建 Result
类。method {
+ // Your code here.
+}.result {
+ get(instance).call()
+ all(instance)
+ remedys {}
+ onNoSuchMethod {}
+}
+
- method
get fun get(instance: Any?): Instance
+
v1.0.2
新增
Method
实例处理类。Method
结果只会返回第一个。Method
。method {
+ // Your code here.
+}.get(instance).call()
+
method {
+ // Your code here.
+}.get().call()
+
- method
all fun all(instance: Any?): ArrayList<Instance>
+
v1.1.0
新增
Method
实例处理类数组。Method
实例结果。Method
,其方法所在实例用法与 get
相同。method {
+ // Your code here.
+}.all(instance).forEach { instance ->
+ instance.call(...)
+}
+
- method
give fun give(): Method?
+
v1.0.67
新增
Method
本身。Method
结果只会返回第一个。null
。- method
giveAll fun giveAll(): HashSet<Method>
+
v1.1.0
新增
Method
本身数组。Method
实例。HashSet
。- method
wait fun wait(instance: Any?, initiate: Instance.() -> Unit)
+
v1.0.2
新增
Method
实例处理类,配合 RemedyPlan
使用。Method
结果只会返回第一个。- method
waitAll fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
+
v1.1.0
新增
Method
实例处理类数组,配合 RemedyPlan
使用。Method
实例结果。- method
remedys inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
+
v1.0
添加
v1.0.80
修改
Method
重查找功能。Method
可能存在不同形式的存在时,可以使用 RemedyPlan
重新查找它,而没有必要使用 onNoSuchMethod
捕获异常二次查找 Method
。method {
+ // Your code here.
+}.remedys {
+ method {
+ // Your code here.
+ }
+ method {
+ // Your code here.
+ }
+}
+
- method
onNoSuchMethod inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
+
v1.0
添加
v1.0.80
修改
Method
时。RemedyPlan
的错误信息。- method
ignored fun ignored(): Result
+
v1.1.0
新增
isNotIgnoredHookingFailure
为 false
则自动忽略。ignoredError - method
v1.0.3
新增
v1.1.0
作废
ignored()
- class
Instance inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
+
v1.0.2
新增
v1.1.0
修改
method
参数Method
实例处理类。- method
original fun original(): Instance
+
v1.1.0
新增
Method
未经 Hook 的原始方法。Method
并未 Hook 则会使用原始的 Method.invoke
方法调用。- method
call fun call(vararg param: Any?): Any?
+
v1.0.2
新增
Method
,不指定返回值类型。- method
invoke fun <T> invoke(vararg param: Any?): T?
+
v1.0.2
新增
Method
,指定 T
返回值类型。- method
byte fun byte(vararg param: Any?): Byte?
+
v1.0.68
新增
Method
,指定 Byte 返回值类型。- method
int fun int(vararg param: Any?): Int
+
v1.0.65
新增
v1.0.68
修改
为 callInt
int
Method
,指定 Int 返回值类型。- method
long fun long(vararg param: Any?): Long
+
v1.0.65
新增
v1.0.68
修改
为 callLong
long
Method
,指定 Long 返回值类型。- method
short fun short(vararg param: Any?): Short
+
v1.0.65
新增
v1.0.68
修改
为 callShort
short
Method
,指定 Short 返回值类型。- method
double fun double(vararg param: Any?): Double
+
v1.0.65
新增
v1.0.68
修改
为 callDouble
double
Method
,指定 Double 返回值类型。- method
float fun float(vararg param: Any?): Float
+
v1.0.65
新增
v1.0.68
修改
为 callFloat
float
Method
,指定 Float 返回值类型。- method
string fun string(vararg param: Any?): String
+
v1.0.65
新增
v1.0.68
修改
为 callString
string
Method
,指定 String 返回值类型。- method
char fun char(vararg param: Any?): Char
+
v1.0.68
新增
Method
,指定 Char 返回值类型。- method
boolean fun boolean(vararg param: Any?): Boolean
+
v1.0.65
新增
v1.0.68
修改
为 callBoolean
boolean
Method
,指定 Boolean 返回值类型。- method
array inline fun <reified T> array(vararg param: Any?): Array<T>
+
v1.0.68
新增
Method
,指定 Array 返回值类型。- method
list inline fun <reified T> list(vararg param: Any?): List<T>
+
v1.0.68
新增
Method
,指定 List 返回值类型。Yuki Hook API
- class
YukiBaseHooker abstract class YukiBaseHooker : PackageParam()
+
v1.0
添加
YukiHookAPI
的子类 Hooker 实现。- method
onHook fun onHook()
+
v1.0
添加
Yuki Hook API
- kt
ReflectionFactory v1.0
添加
Member
和 Class
相关功能的查找匹配以及 invoke
的封装类。- class
MembersType enum class MembersType
+
v1.1.0
新增
Class
中的 Member
类型- enum
ALL ALL
+
v1.1.0
新增
Method
与 Constructor
。- enum
METHOD METHOD
+
v1.1.0
新增
Method
。- enum
CONSTRUCTOR CONSTRUCTOR
+
v1.1.0
新增
Constructor
。- ext-method
ClassLoader.searchClass inline fun ClassLoader.searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
v1.1.0
新增
ClassLoader
按指定条件查找并得到 Dex 中的 Class
。- ext-method
ClassLoader.onLoadClass fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
+
v1.1.0
新增
ClassLoader
的 ClassLoader.loadClass
方法装载。ClassLoader
装载 Class
的宿主应用,你可以使用此方法来监听 Class
加载情况。PackageParam
中使用 appClassLoader
。appClassLoader.onLoadClass { clazz ->
+ // 得到 clazz 即加载对象
+ clazz... // 这里进行你需要的操作
+}
+
ClassLoader
实例,可以通过 Hook 获取。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+customClassLoader?.onLoadClass { clazz ->
+ // ...
+}
+
Class
被装载成功时,开始执行你的 Hook 功能。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+customClassLoader?.onLoadClass { clazz ->
+ if(clazz.name == /** 你需要的 Class 名称 */) {
+ clazz.hook {
+ // ...
+ }
+ }
+}
+
hookClass - field
v1.0
添加
v1.1.0
移除
HookClass
相关功能不再对外开放normalClass - field
v1.0
添加
v1.1.0
移除
HookClass
相关功能不再对外开放hasClass - field
v1.0
添加
v1.1.0
移除
hasClass()
无参方法- ext-field
Class.hasExtends val Class<*>.hasExtends: Boolean
+
v1.0.80
新增
Class
是否有继承关系,父类是 Any
将被认为没有继承关系。classOf - method
v1.0
添加
v1.1.0
作废
toClass(...)
方法- ext-method
String.toClass fun String.toClass(loader: ClassLoader?): Class<*>
+
v1.1.0
新增
loader
中的实体类。Class
,必须在默认 ClassLoader
下存在。"com.example.demo.DemoClass".toClass()
+
Class
所在的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
- ext-method
String.toClassOrNull fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
+
v1.1.0
新增
loader
中的实体类。Class
会返回 null
,不会抛出异常。- method
classOf inline fun <reified T> classOf(loader: ClassLoader?): Class<*>
+
v1.1.0
新增
T
得到其 Class
实例并转换为实体类。Class
在 Kotlin
下不通过反射时应该这样做。DemoClass::class.java
+
cast
一个实例并获取它的 Class
对象,必须在当前 ClassLoader
下存在。classOf<DemoClass>()
+
Class
为 stub
,通过这种方式,你还可以自定义 Class
所在的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+classOf<DemoClass>(customClassLoader)
+
- ext-method
String.hasClass fun String.hasClass(loader: ClassLoader?): Boolean
+
v1.0
添加
v1.1.0
修改
ClassLoader
进行判断ClassLoader
查找是否存在。Class.forName
。if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
loader
参数可判断指定的 ClassLoader
中的 Class
是否存在。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
- ext-method
Class.hasField inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
+
v1.0.4
新增
v1.0.67
修改
FieldFinder
v1.0.80
修改
- ext-method
Class.hasMethod inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
+
v1.0
添加
v1.0.1
修改
returnType
参数v1.0.67
修改
MethodFinder
v1.0.80
修改
- ext-method
Class.hasConstructor inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
+
v1.0.2
新增
v1.0.67
修改
ConstructorFinder
v1.0.80
修改
- ext-method
Member.hasModifiers inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
+
v1.0.67
新增
v1.0.80
修改
v1.1.0
修改
ModifierConditions
Member
中匹配的描述符。- ext-method
Class.hasModifiers inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
+
v1.1.0
新增
Class
中匹配的描述符。obtainStaticFieldAny - method
v1.0
添加
v1.0.1
移除
obtainFieldAny - method
v1.0
添加
v1.0.1
移除
modifyStaticField - method
v1.0
添加
v1.0.1
移除
modifyField - method
v1.0
添加
v1.0.1
移除
- ext-method
Class.field inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
+
v1.0.2
新增
v1.0.80
修改
- ext-method
Class.method inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
+
v1.0
添加
v1.0.1
修改
更名为 obtainMethod
method
returnType
参数v1.0.2
修改
MethodFinder
方法体v1.0.80
修改
- ext-method
Class.constructor inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
+
v1.0
添加
v1.0.1
修改
更名为 obtainConstructor
constructor
v1.0.2
修改
ConstructorFinder
方法体v1.0.80
修改
callStatic - method
v1.0
添加
v1.0.1
修改
更名为 invokeStatic
callStatic
v1.0.2
移除
call - method
v1.0
添加
v1.0.1
修改
更名为 invokeAny
call
v1.0.2
移除
- ext-method
Class.generic fun Class<*>.generic(): GenericClass?
+
v1.1.0
新增
Class
的泛型父类。null
。- ext-method
Class.generic inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
+
v1.1.0
新增
Class
的泛型父类。null
。- ext-method
Any.current inline fun <reified T : Any> T.current(ignored: Boolean): CurrentClass
+
inline fun <reified T : Any> T.current(ignored: Boolean, initiate: CurrentClass.() -> Unit): T
+
v1.0.70
新增
v1.1.0
新增
ignored
参数,可以忽略在 CurrentClass
中出现的异常current { ... }
调用域直接使用 current()
得到实例的类操作对象Class.buildOfAny - ext-method
v1.0.70
新增
v1.0.80
修改
v1.1.0
作废
buildOf
方法- ext-method
Class.buildOf inline fun Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): Any?
+
inline fun <T> Class<*>.buildOf(vararg param: Any?, initiate: ConstructorConditions): T?
+
v1.0.70
新增
v1.0.80
修改
v1.1.0
修改
buildOf
T
或任意类型 Any
。- ext-method
Class.allMethods inline fun Class<*>.allMethods(result: (index: Int, method: Method) -> Unit)
+
v1.0.70
新增
v1.0.80
修改
- ext-method
Class.allConstructors inline fun Class<*>.allConstructors(result: (index: Int, constructor: Constructor<*>) -> Unit)
+
v1.0.70
新增
v1.0.80
修改
- ext-method
Class.allFields inline fun Class<*>.allFields(result: (index: Int, field: Field) -> Unit)
+
v1.0.70
新增
v1.0.80
修改
Yuki Hook API
- kt
YukiHookFactory v1.0
添加
v1.0.80
修改
IYukiHookXposedInit
,将方法体进行 inlineYukiHookAPI
相关 lambda
方法的封装类以及部分 API 用法。- ext-method
IYukiHookXposedInit.configs inline fun IYukiHookXposedInit.configs(initiate: YukiHookAPI.Configs.() -> Unit)
+
v1.0.1
新增
v1.0.80
修改
IYukiHookXposedInit
IYukiHookXposedInit
中配置 Configs
。- ext-method
IYukiHookXposedInit.encase fun IYukiHookXposedInit.encase(initiate: PackageParam.() -> Unit)
+
fun IYukiHookXposedInit.encase(vararg hooker: YukiBaseHooker)
+
v1.0
添加
v1.0.80
修改
IYukiHookXposedInit
IYukiHookXposedInit
中调用 YukiHookAPI
。- ext-field
Context.modulePrefs val Context.modulePrefs: YukiHookModulePrefs
+
v1.0
添加
- ext-method
Context.modulePrefs fun Context.modulePrefs(name: String): YukiHookModulePrefs
+
v1.0
添加
name
为自定义 Sp 存储名称。- ext-method
Context.dataChannel fun Context.dataChannel(packageName: String): YukiHookDataChannel.NameSpace
+
v1.0.88
新增
- ext-field
Context.processName val Context.processName: String
+
v1.0
添加
- ext-method
Context+Resources.injectModuleAppResources fun Context.injectModuleAppResources()
+
fun Resources.injectModuleAppResources()
+
v1.1.0
新增
Context
或 Resources
注入当前 Xposed 模块的资源。ImageView.setImageResource
或 Resources.getString
装载当前 Xposed 模块的资源 ID。Context
或 Resources
,你需要在每个用到宿主 Context
或 Resources
的地方重复调用此方法进行注入才能使用。- ext-method
Context.registerModuleAppActivities fun Context.registerModuleAppActivities(proxy: Any?)
+
v1.1.0
新增
Activity
。Context.startActivity
来启动未在宿主中注册的 Activity
。Activity
在 Hook APP (宿主) 中启动时自动调用 injectModuleAppResources
注入当前 Xposed 模块的资源。Activity
继承于 ModuleAppActivity
或 ModuleAppCompatActivity
。- ext-method
Context.applyModuleTheme fun Context.applyModuleTheme(theme: Int, configuration: Configuration?): ModuleContextThemeWrapper
+
v1.1.0
新增
ContextThemeWrapper
代理以应用当前 Xposed 模块的主题资源。injectModuleAppResources
注入当前 Xposed 模块的资源。ClassCastException
,请手动设置 configuration
。isSupportResourcesHook - field
v1.0.80
新增
v1.0.91
移除
YukiHookAPI.Status.isSupportResourcesHook
isModuleActive - field
v1.0.6
新增
v1.0.91
移除
YukiHookAPI.Status.isModuleActive
isXposedModuleActive - field
v1.0.6
新增
v1.0.91
移除
YukiHookAPI.Status.isXposedModuleActive
isTaiChiModuleActive - field
v1.0
添加
v1.0.91
移除
YukiHookAPI.Status.isTaiChiModuleActive
YukiHookModuleStatus - class
v1.0
添加
v1.0.91
作废
YukiHookAPI.Status
Yuki Hook API
- kt
LoggerFactory v1.0
添加
YukiHookAPI
的日志封装类,可实现同时向 Logcat
和 XposedBridge.log
打印日志的功能。- class
LoggerType enum class LoggerType
+
v1.1.0
新增
- enum
LOGD LOGD
+
v1.1.0
新增
android.util.Log
。- enum
XPOSEDBRIDGE XPOSEDBRIDGE
+
v1.1.0
新增
XposedBridge.log
。- enum
SCOPE SCOPE
+
v1.1.0
新增
XPOSEDBRIDGE
。LOGD
。- enum
BOTH BOTH
+
v1.1.0
新增
LOGD
与 XPOSEDBRIDGE
。LOGD
。- object
YukiHookLogger object YukiHookLogger
+
v1.1.0
新增
- field
contents val contents: String
+
v1.1.0
新增
- method
clear fun clear()
+
v1.1.0
新增
- method
saveToFile fun saveToFile(fileName: String)
+
v1.1.0
新增
Configs.isRecord
或记录为空则不会进行任何操作。fileName
的文件结尾,若文件不存在会自动创建。- object
Configs object Configs
+
v1.1.0
新增
YukiHookLogger
。- field
TAG const val TAG: Int
+
v1.1.0
新增
- field
PRIORITY const val PRIORITY: Int
+
v1.1.0
新增
- field
PACKAGE_NAME const val PACKAGE_NAME: Int
+
v1.1.0
新增
- field
USER_ID const val USER_ID: Int
+
v1.1.0
新增
- field
isEnable var isEnable: Boolean
+
v1.1.0
新增
YukiHookAPI
对全部日志的输出。loggerD
、loggerI
、loggerW
、loggerE
。isEnable
关闭后 YukiHookAPI.Configs.isDebug
也将同时关闭。- field
isRecord var isRecord: Boolean
+
v1.1.0
新增
- field
tag var tag: String
+
v1.1.0
新增
YukiHookAPI
。- method
elements fun elements(vararg item: Int)
+
v1.1.0
新增
XposedBridge.log
生效。item
中设置的顺序进行显示。item
以不显示除日志内容外的全部元素。TAG
、PRIORITY
、PACKAGE_NAME
、USER_ID
。elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+
[YukiHookAPI][D][com.demo.test][999]--> This is a log
+
elements(PACKAGE_NAME, USER_ID, PRIORITY)
+
[com.demo.test][999][D]--> This is a log
+
- method
loggerD fun loggerD(tag: String, msg: String, type: LoggerType)
+
v1.0
添加
v1.1.0
修改
type
参数Logcat
和 XposedBridge
打印日志,级别 D
。tag
的默认参数为 YukiHookAPI.Configs.debugTag
,你可以进行自定义。- method
loggerI fun loggerI(tag: String, msg: String, type: LoggerType)
+
v1.0
添加
v1.1.0
修改
type
参数Logcat
和 XposedBridge
打印日志,级别 I
。tag
的默认参数为 YukiHookAPI.Configs.debugTag
,你可以进行自定义。- method
loggerW fun loggerW(tag: String, msg: String, type: LoggerType)
+
v1.0
添加
v1.1.0
修改
type
参数Logcat
和 XposedBridge
打印日志,级别 W
。tag
的默认参数为 YukiHookAPI.Configs.debugTag
,你可以进行自定义。- method
loggerE fun loggerE(tag: String, msg: String, e: Throwable?, type: LoggerType)
+
v1.0
添加
v1.1.0
修改
type
参数Logcat
和 XposedBridge
打印日志,级别 E
,可携带 e
异常信息,将打印异常堆栈。tag
的默认参数为 YukiHookAPI.Configs.debugTag
,你可以进行自定义。Yuki Hook API
- class
HookParam class HookParam internal constructor(private val creatorInstance: YukiMemberHookCreator, private var param: YukiHookCallback.Param?)
+
v1.0
添加
v1.1.0
修改
HookParamWrapper
到 YukiHookCallback.Param
- field
args val args: Array<Any?>
+
v1.0
添加member
或 constructor
的参数对象数组。Any
,你可以使用 args
方法来实现 ArgsModifyer.cast
功能。firstArgs - field
v1.0
添加
v1.0.75
移除
args(index = 0)
或 args().first()
lastArgs - field
v1.0
添加
v1.0.75
移除
args().last()
- field
instance val instance: Any
+
v1.0
添加
- field
instanceClass val instanceClass: Class<*>
+
v1.0
添加
- field
member val member: Member
+
v1.1.0
新增
Member
。Member
类型为 Method
或 Constructor
时可以使用此方法。- field
method val method: Method
+
v1.0
添加
- field
constructor val constructor: Constructor
+
v1.0
添加
- field
result var result: Any?
+
v1.0
添加
method
或 constructor
的返回值。- field
hasThrowable val hasThrowable: Boolean
+
v1.1.0
新增
- field
throwable val throwable: Throwable?
+
v1.1.0
新增
- i-ext-method
Throwable.throwToApp fun Throwable.throwToApp()
+
v1.1.0
新增
hasThrowable
判断当前是否存在被抛出的异常。throwable
获取当前设置的方法调用抛出异常。MemberHookCreator.beforeHook
或 MemberHookCreator.afterHook
中生效。injectMember {
+ method {
+ // ...
+ }
+ beforeHook {
+ RuntimeException("Test Exception").throwToApp()
+ }
+}
+
- method
result inline fun <reified T> result(): T?
+
v1.0.75
新增
method
或 constructor
的返回值 T
。firstArg - method
v1.0.66
新增
v1.0.75
移除
lastArgs - method
v1.0.66
新增
v1.0.75
移除
- method
instance inline fun <reified T> instance(): T
+
v1.0
添加
T
。instance
方法轻松使用泛型 cast
为目标对象的类型。instance<Activity>().finish()
+
- method
args fun args(): ArgsIndexCondition
+
v1.0.75
新增
method
或 constructor
的参数数组下标实例化类。- method
args fun args(index: Int): ArgsModifyer
+
v1.0
添加
v1.0.75
修改
index = 0
移动到新的使用方法 args().first()
method
或 constructor
的参数实例化对象类。args
方法修改当前 Hook 实例的方法、构造方法的参数内容。set
方法设置 param
为你的目标实例,接受 Any
类型。args(index = 0).set("modify the value")
+
param
的值。args().first().set("modify the value")
+
param
的值。args().last().set("modify the value")
+
setNull
方法设置 param
为空。args(index = 1).setNull()
+
setTrue
方法设置 param
为 true
。args(index = 1).setTrue()
+
setFalse
方法设置 param
为 false
。args(index = 1).setFalse()
+
- method
callOriginal fun callOriginal(): Any?
+
fun <T> callOriginal(): T?
+
v1.1.0
新增
Member
。Member
并调用原始参数执行。invoke
原始未经 Hook 的 Member
对象,取决于原始 Member
的参数。beforeHook
、afterHook
以及 replaceUnit
、replaceAny
。test("test value")
,使用此方法会调用其中的 "test value"
作为参数。injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = StringType
+ }
+ afterHook {
+ // <方案1> 不使用泛型,不获取方法执行结果,调用将使用原方法传入的 args 自动传参
+ callOriginal()
+ // <方案2> 使用泛型,已知方法执行结果参数类型进行 cast
+ // 假设返回值为 String,失败会返回 null,调用将使用原方法传入的 args 自动传参
+ val value = callOriginal<String>()
+ }
+}
+
- method
invokeOriginal fun invokeOriginal(vararg args: Any?): Any?
+
fun <T> invokeOriginal(vararg args: Any?): T?
+
v1.0
添加
v1.1.0
修改
member.invokeOriginal
进行调用Member
。Member
并自定义 args
执行。invoke
原始未经 Hook 的 Member
对象,可自定义需要调用的参数内容。beforeHook
、afterHook
以及 replaceUnit
、replaceAny
。test("test value")
,使用此方法可自定义其中的 args
作为参数。injectMember {
+ method {
+ name = "test"
+ param(StringType)
+ returnType = StringType
+ }
+ afterHook {
+ // <方案1> 不使用泛型,不获取方法执行结果
+ invokeOriginal("test value")
+ // <方案2> 使用泛型,已知方法执行结果参数类型进行 cast,假设返回值为 String,失败会返回 null
+ val value = invokeOriginal<String>("test value")
+ }
+}
+
- method
resultTrue fun resultTrue()
+
v1.0
添加
result
返回值为 true
。- method
resultFalse fun resultFalse()
+
v1.0
添加
result
返回值为 false
。- method
resultNull fun resultNull()
+
v1.0
添加
- class
ArgsIndexCondition inner class ArgsIndexCondition internal constructor()
+
v1.0.75
新增
- method
first fun first(): ArgsModifyer
+
v1.0.75
新增
method
或 constructor
的参数数组第一位。- method
last fun last(): ArgsModifyer
+
v1.0.75
新增
method
或 constructor
的参数数组最后一位。- class
ArgsModifyer inner class ArgsModifyer internal constructor(private val index: Int)
+
v1.0
添加
- method
cast fun <T> cast(): T?
+
v1.0.66
新增
v1.0.68
修改
为 of
cast
T
。- method
byte fun byte(): Byte?
+
v1.0.68
新增
- method
int fun int(): Int
+
v1.0.66
新增
v1.0.68
修改
为 ofInt
int
- method
long fun long(): Long
+
v1.0.66
新增
v1.0.68
修改
为 ofLong
long
- method
short fun short(): Short
+
v1.0.66
新增
v1.0.68
修改
为 ofShort
short
- method
double fun double(): Double
+
v1.0.66
新增
v1.0.68
修改
为 ofDouble
double
- method
float fun float(): Float
+
v1.0.66
新增
v1.0.68
修改
为 ofFloat
float
- method
string fun string(): String
+
v1.0.66
新增
v1.0.68
修改
为 ofString
string
- method
char fun char(): Char
+
v1.0.68
新增
- method
boolean fun boolean(): Boolean
+
v1.0.66
新增
v1.0.68
修改
为 ofBoolean
boolean
- method
any fun any(): Any?
+
v1.0.77
新增
- method
array inline fun <reified T> array(): Array<T>
+
v1.0.68
新增
- method
list inline fun <reified T> list(): List<T>
+
v1.0.68
新增
- method
set fun <T> set(any: T?)
+
v1.0
添加
- method
setNull fun setNull()
+
v1.0
添加
null
。- method
setTrue fun setTrue()
+
v1.0
添加
true
。- method
setFalse fun setFalse()
+
v1.0
添加
false
。Yuki Hook API
- class
PackageParam open class PackageParam internal constructor(internal var wrapper: PackageParamWrapper?)
+
v1.0
添加
- field
appClassLoader val appClassLoader:ClassLoader
+
v1.0
添加
ClassLoader
。- field
appInfo val appInfo: ApplicationInfo
+
v1.0
添加
ApplicationInfo
。- field
appUserId val appUserId: Int
+
v1.1.0
新增
0
,应用双开 (分身) 或工作资料因系统环境不同 ID 也各不相同。- field
appContext val appContext: Application?
+
v1.0.72
新增
v1.1.0
修改
Application
。- field
appResources val appResources:Resources?
+
v1.0.80
新增
v1.1.0
修改
- field
systemContext val systemContext: Context
+
v1.1.0
新增
Context
。- field
processName val processName: String
+
v1.0
添加
- field
packageName val packageName: String
+
v1.0
添加
- field
isFirstApplication val isFirstApplication: Boolean
+
v1.0
添加
Application
。- field
mainProcessName val mainProcessName: String
+
v1.0.70
新增
packageName
。- field
moduleAppFilePath val moduleAppFilePath: String
+
v1.0.80
新增
- field
moduleAppResources val moduleAppResources: YukiModuleResources
+
v1.0.80
新增
Resources
。- field
prefs val prefs: YukiHookModulePrefs
+
v1.0
添加
- method
prefs fun prefs(name: String): YukiHookModulePrefs
+
v1.0
添加
v1.0.80
修改
name
来自定义 Sp 存储的名称。- field
dataChannel val dataChannel: YukiHookDataChannel.NameSpace
+
v1.0.88
新增
- method
resources fun resources(): HookResources
+
v1.0.80
新增
YukiResources
对象。HookResources.hook
方法开始 Hook。- method
refreshModuleAppResources fun refreshModuleAppResources()
+
v1.0.87
新增
Resources
。- method
onAppLifecycle inline fun onAppLifecycle(initiate: AppLifecycle.() -> Unit)
+
v1.0.88
新增
- method
loadApp inline fun loadApp(name: String, initiate: PackageParam.() -> Unit)
+
fun loadApp(name: String, hooker: YukiBaseHooker)
+
v1.0
添加
v1.0.80
修改
name
为 APP 的包名,后方的两个参数一个可作为 lambda
方法体使用,一个可以直接装载子 Hooker。loadZygote
。loadSystem
。loadApp
的 lambda
方法体形式或直接装载一个 Hooker。// 使用 lambda
+loadApp(name = "com.example.test") {
+ // Your code here.
+}
+// 使用 Hooker
+loadApp(name = "com.example.test", CustomHooker)
+
name
参数,则此方法体默认会过滤当前系统中全部可被 Hook 的 APP。// 使用 lambda
+loadApp {
+ // Your code here.
+}
+// 使用 Hooker
+loadApp(hooker = CustomHooker)
+
- method
loadZygote inline fun loadZygote(initiate: PackageParam.() -> Unit)
+
fun loadZygote(hooker: YukiBaseHooker)
+
v1.0.80
新增
lambda
方法体使用,一个可以直接装载子 Hooker。- method
loadSystem inline fun loadSystem(initiate: PackageParam.() -> Unit)
+
fun loadSystem(hooker: YukiBaseHooker)
+
v1.0.82
新增
lambda
方法体使用,一个可以直接装载子 Hooker。- method
withProcess inline fun withProcess(name: String, initiate: PackageParam.() -> Unit)
+
fun withProcess(name: String, hooker: YukiBaseHooker)
+
v1.0.70
新增
name
为 APP 的进程名称,后方的两个参数一个可作为 lambda
方法体使用,一个可以直接装载子 Hooker。- method
loadHooker fun loadHooker(hooker: YukiBaseHooker)
+
v1.0
添加
hooker
在 Hooker 中继续装载 Hooker。- method
searchClass inline fun searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
+
v1.1.0
新增
appClassLoader
按指定条件查找并得到当前 Hook APP Dex 中的 Class
。String+VariousClass.clazz - i-ext-field
v1.0
添加
v1.1.0
作废
toClass(...)
方法String.hasClass - i-ext-field
v1.0
添加
v1.1.0
作废
hasClass(...)
方法- i-ext-method
String+VariousClass.toClass fun String.toClass(loader: ClassLoader?): Class<*>
+
fun VariousClass.toClass(loader: ClassLoader?): Class<*>
+
v1.1.0
新增
VariousClass
转换为 loader
中的实体类。appClassLoader
装载目标 Class
。String
类型的 Class
包名转为 Class
实例。"com.example.demo.DemoClass".toClass()
+
loader
参数传入你自定义的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+"com.example.demo.DemoClass".toClass(customClassLoader)
+
VariousClass
,并转换为实体类。VariousClass
会枚举所有设置的 Class
并最终获得第一个存在的 Class
。VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass()
+
loader
参数传入你自定义的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass(customClassLoader)
+
- i-ext-method
String+VariousClass.toClassOrNull fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
+
fun VariousClass.toClassOrNull(loader: ClassLoader?): Class<*>?
+
v1.1.0
新增
VariousClass
转换为 loader
中的实体类。appClassLoader
装载目标 Class
。Class
会返回 null
,不会抛出异常。- i-ext-method
String.hasClass fun String.hasClass(loader: ClassLoader?): Boolean
+
v1.1.0
新增
appClassLoader
装载目标 Class
。if("com.example.demo.DemoClass".hasClass()) {
+ // Your code here.
+}
+
loader
参数,默认为 appClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
+ // Your code here.
+}
+
- method
findClass fun findClass(name: String, loader: ClassLoader?): HookClass
+
fun findClass(vararg name: String, loader: ClassLoader?): VariousClass
+
v1.0
添加
v1.0.1
修改
方法findClass(various: VariousClass)
v1.1.0
修改
loader
参数Class
。Class
。Class
完整包名+名称填入 name
中。findClass(name = "com.example.demo.DemoClass")
+
Class
以及不同名称,你可以将多个完整包名+名称填入 name
中。findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
+
VariousClass
,将 Class
的完整包名+名称填入 VariousClass
的 name
中并填入 various
参数中。val variousClass = VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
+
Class
不属于 appClassLoader
,你可以使用 loader
参数指定你要装载的 ClassLoader
。val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
+findClass(name = "com.example.demo.OutsideClass", loader = outsideLoader)
+
Class
以及不同名称时,也可以使用 loader
参数指定你要装载的 ClassLoader
。val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
+findClass("com.example.demo.OutsideClass1", "com.example.demo.OutsideClass2", "com.example.demo.OutsideClass3", loader = outsideLoader)
+
- i-ext-method
String+Class+VariousClass+HookClass.hook inline fun String.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun Class<*>.hook(isForceUseAbsolute: Boolean, initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun VariousClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
inline fun HookClass.hook(initiate: YukiMemberHookCreator.() -> Unit): YukiMemberHookCreator.Result
+
v1.0
添加
v1.0.1
修改
VariousClass
的直接调用 hook
方法v1.0.2
修改
String
的直接调用 hook
方法v1.0.3
修改
YukiMemberHookCreator.Result
返回值v1.0.70
修改
isUseAppClassLoader
参数v1.0.80
修改
v1.1.0
修改
参数isUseAppClassLoader
isForceUseAbsolute
参数到 Class.hook
方法HookClass
实例进行创建。"com.example.demo.DemoClass".hook {
+ // Your code here.
+}
+
+
findClass
得到 HookClass
实例进行创建。findClass(name = "com.example.demo.DemoClass").hook {
+ // Your code here.
+}
+
stub
或直接拿到 Class
实例进行创建。Class
实例转换为类名并绑定到 appClassLoader
,若失败,则会使用原始 Class
实例直接进行 Hook。Stub::class.java.hook {
+ // Your code here.
+}
+
Class
不在 appClassLoader
且自动匹配无法找到该 Class
,请启用 isForceUseAbsolute
。YourClass::class.java.hook(isForceUseAbsolute = true) {
+ // Your code here.
+}
+
VariousClass
实例进行创建。VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
+ // Your code here.
+}
+
findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
+ // Your code here.
+}
+
- i-ext-method
HookResources.hook inline fun HookResources.hook(initiate: YukiResourcesHookCreator.() -> Unit)
+
v1.0.80
新增
resources
对象,然后调用 hook
方法开始 Hook。resources().hook {
+ // Your code here.
+}
+
findClass(...).hook
做到统一,使得调用起来逻辑不会混乱。- class
AppLifecycle inner class AppLifecycle internal constructor()
+
v1.0.88
新增
- method
attachBaseContext fun attachBaseContext(result: (baseContext: Context, hasCalledSuper: Boolean) -> Unit)
+
v1.0.88
新增
Application.attachBaseContext
。- method
onCreate fun onCreate(initiate: Application.() -> Unit)
+
v1.0.88
新增
Application.onCreate
。- method
onTerminate fun onTerminate(initiate: Application.() -> Unit)
+
v1.0.88
新增
Application.onTerminate
。- method
onLowMemory fun onLowMemory(initiate: Application.() -> Unit)
+
v1.0.88
新增
Application.onLowMemory
。- method
onTrimMemory fun onTrimMemory(result: (self: Application, level: Int) -> Unit)
+
v1.0.88
新增
Application.onTrimMemory
。- method
onConfigurationChanged fun onConfigurationChanged(result: (self: Application, config: Configuration) -> Unit)
+
v1.0.88
新增
Application.onConfigurationChanged
。- method
registerReceiver fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
+
v1.0.88
新增
Yuki Hook API
- kt
ComponentTypeFactory v1.0
添加
Android
相关组件的 Class
内容,跟随版本更新会逐一进行增加。Yuki Hook API
- kt
GraphicsTypeFactory v1.0
添加
Android
相关 Graphics
的 Class
内容,跟随版本更新会逐一进行增加。Yuki Hook API
- kt
ViewTypeFactory v1.0
添加
Android
相关 Widget
的 Class
内容,跟随版本更新会逐一进行增加。Yuki Hook API
- kt
DefinedTypeFactory v1.1.0
新增
- field
VagueType val VagueType: Class<*>
+
v1.1.0
新增
Yuki Hook API
- kt
VariableTypeFactory v1.0
添加
Java
相关基本变量类型的 Class
内容,跟随版本更新会逐一进行增加。Yuki Hook API
- class
ModuleApplication open class ModuleApplication: Application()
+
v1.0.77
新增
YukiHookAPI
Xposed 模块实现中的一个扩展功能。Application
中继承此类。AndroidManifest.xml
的 application
标签中指定此类。appContext
YukiHookAPI.Config
以确保 YukiHookAPI.Configs.debugTag
不需要重复定义YukiHookDataChannel
进行通讯YukiHookAPI.Status.isTaiChiModuleActive
判断太极、无极激活状态Application
上。package com.demo
+
+class MyApplication: ModuleApplication() {
+
+ override fun onCreate() {
+ super.onCreate()
+ }
+}
+
AndroidManifest.xml
的 application
标签中指定自定义的 Application
。<application
+ android:name="com.demo.MyApplication"
+ ...>
+
Application
可以直接将 ModuleApplication
设置到 AndroidManifest.xml
的 application
标签中。<application
+ android:name="com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication"
+ ...>
+
- field
appContext val appContext: ModuleApplication
+
v1.0.77
新增
Application
实例。Yuki Hook API
- class
YukiModuleResources class YukiModuleResources private constructor(private val baseInstance: XModuleResources) : Resources
+
v1.0.80
新增
XModuleResources
的中间层实例。- method
fwd fun fwd(resId: Int): YukiResForwarder
+
v1.0.80
新增
XModuleResources.fwd
方法。YukiResForwarder
与 XResForwarder
实例。Yuki Hook API
- class
YukiResForwarder class YukiResForwarder private constructor(private val baseInstance: XResForwarder)
+
v1.0.80
新增
XResForwarder
的中间层实例。instance - field
v1.0.80
新增
v1.1.0
作废
instance
参数- field
id val id: Int
+
v1.0.80
新增
- field
resources val resources: Resources
+
v1.0.80
新增
Yuki Hook API
- class
YukiResources class YukiResources private constructor(private val baseInstance: XResources) : Resources
+
v1.0.80
新增
XResources
的中间层实例。- class
LayoutInflatedParam class LayoutInflatedParam(internal val baseParam: XC_LayoutInflated.LayoutInflatedParam)
+
v1.0.80
新增
- field
variantName val variantName: String
+
v1.0.80
新增
layout
、layout-land
、layout-sw600dp
。- field
currentView val currentView: View
+
v1.0.80
新增
- method
findViewByIdentifier inline fun <reified T : View> View.findViewByIdentifier(name: String): T?
+
inline fun <reified T : View> findViewByIdentifier(name: String): T?
+
v1.0.80
新增
View
。View
。Yuki Hook API
- object
YukiXposedEvent object YukiXposedEvent
+
v1.0.80
添加
- method
events inline fun events(initiate: YukiXposedEvent.() -> Unit)
+
v1.0.80
新增
YukiXposedEvent
创建一个方法体。- method
onInitZygote fun onInitZygote(result: (StartupParam) -> Unit)
+
v1.0.80
新增
- method
onHandleLoadPackage fun onHandleLoadPackage(result: (LoadPackageParam) -> Unit)
+
v1.0.80
新增
- method
onHandleInitPackageResources fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
+
v1.0.80
新增
Yuki Hook API
- class
YukiHookDataChannel class YukiHookDataChannel private constructor()
+
v1.0.88
新增
BroadcastReceiver
来实现数据的交互。Application
继承于 ModuleApplication
来实现此功能。- class
NameSpace inner class NameSpace internal constructor(private val context: Context?, private val packageName: String, private val isSecure: Boolean)
+
v1.0.88
新增
v1.0.90
修改
isSecure
参数YukiHookDataChannel
命名空间。- method
with inline fun with(initiate: NameSpace.() -> Unit): NameSpace
+
v1.0.88
新增
- method
put fun <T> put(key: String, value: T)
+
fun <T> put(data: ChannelData<T>, value: T?)
+
fun put(vararg data: ChannelData<*>)
+
v1.0.88
新增
- method
put fun put(key: String)
+
v1.0.88
新增
VALUE_WAIT_FOR_LISTENER
发送键值数据。- method
wait fun <T> wait(key: String, result: (value: T) -> Unit)
+
fun <T> wait(data: ChannelData<T>, result: (value: T) -> Unit)
+
v1.0.88
新增
v1.0.90
修改
value
- method
wait fun wait(key: String, callback: () -> Unit)
+
v1.0.88
新增
- method
checkingVersionEquals fun checkingVersionEquals(result: (Boolean) -> Unit)
+
v1.0.88
新增
Yuki Hook API
- class
ChannelData data class ChannelData<T>(var key: String, var value: T?)
+
v1.0.88
新增
YukiHookDataChannel
的一个扩展用法。object DataConst {
+
+ val TEST_KV_DATA_1 = ChannelData("test_data_1", "defalut value")
+ val TEST_KV_DATA_2 = ChannelData("test_data_2", 0)
+}
+
// 从指定包名的宿主获取
+dataChannel(packageName = "com.example.demo").wait(DataConst.TEST_KV_DATA_1) { value ->
+ // Your code here.
+}
+// 发送给指定包名的宿主 - 未填写 value 时将使用模板提供的默认值
+dataChannel(packageName = "com.example.demo").put(DataConst.TEST_KV_DATA_1, value = "sending value")
+
// 从模块获取
+dataChannel.wait(DataConst.TEST_KV_DATA_1) { value ->
+ // Your code here.
+}
+// 发送给模块 - 未填写 value 时将使用模板提供的默认值
+dataChannel.put(DataConst.TEST_KV_DATA_1, value = "sending value")
+
// 获取 - 此时 value 取到的默认值将会是 2 - 并不是模板提供的 0
+dataChannel.wait(DataConst.TEST_KV_DATA_2, value = 2) { value ->
+ // Your code here.
+}
+
Yuki Hook API
- class
ModuleAppActivity open class ModuleAppActivity : Activity()
+
v1.1.0
新增
Activity
。Activity
可以同时在宿主与模块中启动。Context.registerModuleAppActivities
进行注册。Yuki Hook API
- class
ModuleAppCompatActivity open class ModuleAppCompatActivity : AppCompatActivity()
+
v1.1.0
新增
AppCompatActivity
。Activity
可以同时在宿主与模块中启动。Context.registerModuleAppActivities
进行注册。moduleTheme
设置 AppCompat 主题,否则会无法启动。- field
moduleTheme open val moduleTheme: Int
+
v1.1.0
新增
Activity
主题。Yuki Hook API
- class
ModuleContextThemeWrapper class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) : ContextThemeWrapper
+
v1.1.0
新增
ContextThemeWrapper
。- method
applyConfiguration fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
+
v1.1.0
新增
ModuleContextThemeWrapper
的 Configuration
。Resources.updateConfiguration
。Yuki Hook API
- class
YukiHookModulePrefs class YukiHookModulePrefs private constructor(private var context: Context?)
+
v1.0
添加
SharedPreferences
和 XSharedPreferences
。AndroidManifests.xml
中将 xposedminversion
最低设置为 93
。API
降至 26
以下,YukiHookAPI
将会尝试使用 makeWorldReadable
但仍有可能不成功。PreferenceFragmentCompat
,请迁移到 ModulePreferenceFragment
以适配上述功能特性。xposedminversion
最低设置为 93
,你可以在 AndroidManifest.xml
中添加 xposedsharedprefs
来实现支持。<meta-data
+ android:name="xposedsharedprefs"
+ android:value="true"/>
+
- field
isXSharePrefsReadable val isXSharePrefsReadable: Boolean
+
v1.0.90
新增
XSharedPreferences
是否可读。- field
isRunInNewXShareMode val isRunInNewXShareMode: Boolean
+
v1.0.78
新增
YukiHookModulePrefs
是否正处于 EdXposed/LSPosed 的最高权限运行。- method
name fun name(name: String): YukiHookModulePrefs
+
v1.0
添加
Activity
中的使用方法。modulePrefs("custom_name").getString("custom_key")
+
PackageParam
中的使用方法。prefs("custom_name").getString("custom_key")
+
- method
direct fun direct(): YukiHookModulePrefs
+
v1.0.5
新增
YukiHookAPI.Configs.isEnableModulePrefsCache
。XSharedPreferences
下生效。- method
getString fun getString(key: String, value: String): String
+
v1.0
添加
String
键值。- method
getStringSet fun getStringSet(key: String, value: Set<String>): Set<String>
+
v1.0.77
新增
Set<String>
键值。- method
getBoolean fun getBoolean(key: String, value: Boolean): Boolean
+
v1.0
添加
Boolean
键值。- method
getInt fun getInt(key: String, value: Int): Int
+
v1.0
添加
Int
键值。- method
getLong fun getLong(key: String, value: Long): Long
+
v1.0
添加
Long
键值。- method
getFloat fun getFloat(key: String, value: Float): Float
+
v1.0
添加
Float
键值。- method
all fun all(): HashMap<String, Any?>
+
v1.0.77
新增
- method
remove fun remove(key: String)
+
v1.0
添加
key
的存储数据。- method
remove inline fun <reified T> remove(prefs: PrefsData<T>)
+
v1.0.67
新增
PrefsData.key
的存储数据。- method
clear fun clear()
+
v1.0.77
新增
- method
putString fun putString(key: String, value: String)
+
v1.0
添加
String
键值。- method
putStringSet fun putStringSet(key: String, value: Set<String>)
+
v1.0.77
新增
Set<String>
键值。- method
putBoolean fun putBoolean(key: String, value: Boolean)
+
v1.0
添加
Boolean
键值。- method
putInt fun putInt(key: String, value: Int)
+
v1.0
添加
Int
键值。- method
putLong fun putLong(key: String, value: Long)
+
v1.0
添加
Long
键值。- method
putFloat fun putFloat(key: String, value: Float)
+
v1.0
添加
Float
键值。- method
get inline fun <reified T> get(prefs: PrefsData<T>, value: T): T
+
v1.0.67
新增
- method
put inline fun <reified T> put(prefs: PrefsData<T>, value: T)
+
v1.0.67
新增
- method
clearCache fun clearCache()
+
v1.0.5
新增
XSharedPreferences
中缓存的键值数据。YukiHookAPI.Configs.isEnableModulePrefsCache
。XSharedPreferences
重新读取。Yuki Hook API
- class
PrefsData data class PrefsData<T>(var key: String, var value: T)
+
v1.0.67
新增
YukiHookModulePrefs
的一个扩展用法。object DataConst {
+
+ val TEST_KV_DATA_1 = PrefsData("test_data_1", "defalut value")
+ val TEST_KV_DATA_2 = PrefsData("test_data_2", false)
+ val TEST_KV_DATA_3 = PrefsData("test_data_3", 0)
+}
+
// 读取
+val data = modulePrefs.get(DataConst.TEST_KV_DATA_1)
+// 写入
+modulePrefs.put(DataConst.TEST_KV_DATA_1, "written value")
+
// 读取 String
+val dataString = prefs.get(DataConst.TEST_KV_DATA_1)
+// 读取 Boolean
+val dataBoolean = prefs.get(DataConst.TEST_KV_DATA_2)
+
// 读取 - 此时 data 取到的默认值将会是 2 - 并不是模板提供的 0
+val data = prefs.get(DataConst.TEST_KV_DATA_3, 2)
+
Yuki Hook API
- class
ModulePreferenceFragment abstract class ModulePreferenceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener
+
v1.0.78
新增
YukiHookAPI
Xposed 模块实现中的一个扩展功能。PreferenceFragmentCompat
并对其实现了 Sp 存储在 Xposed 模块中的全局可读可写。PreferenceFragmentCompat
的实例中,将继承对象换成此类。onCreatePreferences
替换为 onCreatePreferencesInModuleApp
即可。ModulePreferenceFragment
创建一个 PreferenceFragmentCompat
对象。class SettingsFragment : ModulePreferenceFragment() {
+
+ override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(R.xml.settings_preferences, rootKey)
+ // Your code here.
+ }
+}
+
PreferenceFragmentCompat
保持一致。- method
onCreatePreferencesInModuleApp abstract fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?)
+
v1.0.78
新增
onCreatePreferences
。- method
onSharedPreferenceChanged override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?)
+
v1.0.78
新增
SharedPreferences.OnSharedPreferenceChangeListener
的原生监听功能。class SettingsFragment : ModulePreferenceFragment() {
+
+ override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
+ // ...
+ }
+
+ override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
+ super.onSharedPreferenceChanged(sharedPreferences, key)
+ // Your code here.
+ }
+}
+
Yuki Hook API
- interface
IYukiHookXposedInit interface IYukiHookXposedInit
+
v1.0
添加
v1.0.80
修改
作废
名称但保留接口YukiHookXposedInitProxy
IYukiHookXposedInit
新名称- method
onInit fun onInit()
+
v1.0.5
新增
YukiHookAPI.Configs
的初始化方法。- method
onHook fun onHook()
+
v1.0
添加
- method
onXposedEvent fun onXposedEvent()
+
v1.0.80
新增
YukiXposedEvent.onInitZygote
YukiXposedEvent.onHandleLoadPackage
YukiXposedEvent.onHandleInitPackageResources
YukiHookXposedInitProxy - interface
v1.0
添加
v1.0.80
作废
IYukiHookXposedInit
Yuki Hook API
宿主资源注入扩展
Activity
组件以及 Context
主题注入到宿主的扩展功能。build.gradle
中修改资源 ID。android {
+ androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
+}
+
android {
+ aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
+}
+
注入模块资源 (Resources)
Context
注入当前模块资源。injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ instance<Activity>().also {
+ // <方案1> 通过 Context 注入模块资源
+ it.injectModuleAppResources()
+ // <方案2> 直接得到宿主 Resources 注入模块资源
+ it.resources.injectModuleAppResources()
+ // 直接使用模块资源 ID
+ it.getString(R.id.app_name)
+ }
+ }
+}
+
AppLifecycle
中注入当前模块资源。onAppLifecycle {
+ onCreate {
+ // 全局注入模块资源,但仅限于全局生命周期
+ // 类似 ImageView.setImageResource 这样的方法在 Activity 中需要单独注入
+ // <方案1> 通过 Context 注入模块资源
+ injectModuleAppResources()
+ // <方案2> 直接得到宿主 Resources 注入模块资源
+ resources.injectModuleAppResources()
+ // 直接使用模块资源 ID
+ getString(R.id.app_name)
+ }
+}
+
注册模块 Activity
Activity
启动时,都需要在 AndroidManifest.xml
中进行注册,在 Hook 过程中,如果我们想通过宿主来直接启动模块中未注册的 Activity
要怎么做呢?Context
注册当前模块的 Activity
代理。injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ instance<Activity>().registerModuleAppActivities()
+ }
+}
+
AppLifecycle
中注册当前模块的 Activity
代理。onAppLifecycle {
+ onCreate {
+ registerModuleAppActivities()
+ }
+}
+
proxy
参数,API 将会根据当前 Context
自动获取当前宿主的启动入口 Activity
进行代理。Activity
会在注册清单上加入启动参数,那么我们就需要使用另一种解决方案。Activity
不能被正确启动,我们可以手动拿到宿主的 AndroidManifest.xml
进行分析,来得到一个注册过的 Activity
标签,获取其中的 name
。Activity
作为一个“傀儡”将其进行代理,通常是有效的。Activity
。<activity
+ android:name="com.demo.test.activity.TestActivity"
+ ...>
+
name
,我们只需要在方法中加入这个参数进行注册即可。registerModuleAppActivities(proxy = "com.demo.test.activity.TestActivity")
+
stub
,那么你可以直接通过 Class
对象来进行注册。registerModuleAppActivities(TestActivity::class.java)
+
Activity
继承于 ModuleAppActivity
或 ModuleAppCompatActivity
。Activity
现在无需注册即可无缝存活于宿主中。class HostTestActivity : ModuleAppActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // 模块资源已被自动注入,可以直接使用 xml 装载布局
+ setContentView(R.layout.activity_main)
+ }
+}
+
ModuleAppCompatActivity
,你需要手动设置 AppCompat 主题。class HostTestActivity : ModuleAppCompatActivity() {
+
+ // 这里的主题名称仅供参考,请填写你模块中已有的主题名称
+ override val moduleTheme get() = R.style.Theme_AppCompat
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // 模块资源已被自动注入,可以直接使用 xml 装载布局
+ setContentView(R.layout.activity_main)
+ }
+}
+
Context
的地方愉快地调用 startActivity
了。val context: Context = ... // 假设这就是你的 Context
+context.startActivity(context, HostTestActivity::class.java)
+
创建 ContextThemeWrapper 代理
MaterialAlertDialogBuilder
来美化自己在宿主中的对话框,但是拿不到 AppCompat 主题就无法创建。The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
+
Activity
中使用 MaterialAlertDialogBuilder
来创建对话框,就可以有如下方法。injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ // 使用 applyModuleTheme 创建一个当前模块中的主题资源
+ val appCompatContext = instance<Activity>().applyModuleTheme(R.style.Theme_AppCompat)
+ // 直接使用这个包装了模块主题后的 Context 创建对话框
+ MaterialAlertDialogBuilder(appCompatContext)
+ .setTitle("AppCompat 主题对话框")
+ .setMessage("我是一个在宿主中显示的 AppCompat 主题对话框。")
+ .setPositiveButton("确定", null)
+ .show()
+ }
+}
+
Context
通过 uiMode
设置原生的夜间模式和日间模式,至少需要 Android 10 及以上系统版本支持且当前主题包含夜间模式相关元素。injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ afterHook {
+ // 定义当前模块中的主题资源
+ var appCompatContext: ModuleContextThemeWrapper
+ // <方案1> 直接得到 Configuration 对象进行设置
+ appCompatContext = instance<Activity>()
+ .applyModuleTheme(R.style.Theme_AppCompat)
+ .applyConfiguration { uiMode = Configuration.UI_MODE_NIGHT_YES }
+ // <方案2> 创建一个新的 Configuration 对象
+ // 此方案会破坏当前宿主中原有的字体缩放大小等设置,你需要手动重新传递 densityDpi 等参数
+ appCompatContext = instance<Activity>().applyModuleTheme(
+ theme = R.style.Theme_AppCompat,
+ configuration = Configuration().apply { uiMode = Configuration.UI_MODE_NIGHT_YES }
+ )
+ // 直接使用这个包装了模块主题后的 Context 创建对话框
+ MaterialAlertDialogBuilder(appCompatContext)
+ .setTitle("AppCompat 主题对话框")
+ .setMessage("我是一个在宿主中显示的 AppCompat 主题对话框。")
+ .setPositiveButton("确定", null)
+ .show()
+ }
+}
+
MaterialAlertDialogBuilder
创建对话框了。Yuki Hook API
宿主生命周期扩展
监听生命周期
Application
的启动和生命周期方法,只需要使用以下方式实现。loadApp(name = "com.example.demo") {
+ // 注册生命周期监听
+ onAppLifecycle {
+ // 你可以在这里实现 Application 中的生命周期方法监听
+ attachBaseContext { baseContext, hasCalledSuper ->
+ // 通过判断 hasCalledSuper 来确定是否已执行 super.attachBaseContext(base) 方法
+ // ...
+ }
+ onCreate {
+ // 通过 this 得到当前 Application 实例
+ // ...
+ }
+ onTerminate {
+ // 通过 this 得到当前 Application 实例
+ // ...
+ }
+ onLowMemory {
+ // 通过 this 得到当前 Application 实例
+ // ...
+ }
+ onTrimMemory { self, level ->
+ // 可在这里判断 APP 是否已切换到后台
+ if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
+ // ...
+ }
+ // ...
+ }
+ onConfigurationChanged { self, config ->
+ // ...
+ }
+ }
+}
+
注册系统广播
Application.onCreate
方法注册系统广播,来实现对系统广播的监听。Application
中注册系统广播。loadApp(name = "com.example.demo") {
+ // 注册生命周期监听
+ onAppLifecycle {
+ // 注册用户解锁时的广播监听
+ registerReceiver(Intent.ACTION_USER_PRESENT) { context, intent ->
+ // ...
+ }
+ // 注册多个广播监听,会同时回调多次
+ registerReceiver(Intent.ACTION_PACKAGE_CHANGED, Intent.ACTION_TIME_TICK) { context, intent ->
+ // ...
+ }
+ }
+}
+
Yuki Hook API
调试日志
YukiHookAPI
为开发者封装了一套稳定高效的调试日志功能。 普通日志
loggerD
、loggerI
、loggerW
来向控制台打印普通日志。loggerD(msg = "This is a log")
+
YukiHookAPI
会调用 android.util.Log
与 XposedBridge.log
同时打印这条日志。TAG
为你在 YukiHookLogger.Configs.tag
中设置的值。TAG
防止过滤不到日志。loggerD(tag = "YukiHookAPI", msg = "This is a log")
+
[YukiHookAPI][D][宿主包名]--> This is a log
+
LoggerType
自定义日志打印的类型,可选择使用 android.util.Log
还是 XposedBridge.log
来打印日志。LoggerType.BOTH
,含义为同时使用这两个方法来打印日志。android.util.Log
来打印日志。loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.LOGD)
+
XposedBridge.log
来打印日志,此方法仅可在 (Xposed) 宿主环境使用。loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.XPOSEDBRIDGE)
+
loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
+
错误日志
loggerE
来向控制台打印 E
级别的日志。loggerE(msg = "This is an error")
+
E
级别的日志。// 假设这就是被抛出的异常
+val throwable = Throwable(...)
+// 打印日志
+loggerE(msg = "This is an error", e = throwable)
+
[YukiHookAPI][E][宿主包名]--> This is an error
+
java.lang.Throwable
+ at com.demo.Test.<init>(...)
+ at com.demo.Test.doTask(...)
+ at com.demo.Test.stop(...)
+ at com.demo.Test.init(...)
+ at a.a.a(...)
+ ... 3 more
+
LoggerType
来指定当前打印日志所用到的方法类型。 保存日志与自定义元素
YukiHookLogger.saveToFile
方法直接保存当前已打印的全部日志到文件。// 请注意保存的文件路径必须拥有读写权限,否则会抛出异常
+YukiHookLogger.saveToFile("/sdcard/Documents/debug_log.log")
+
YukiHookLogger.contents
获取当前已打印的全部日志文件内容。// 获取当前已打印的全部日志文件内容
+val fileContent = YukiHookLogger.contents
+
YukiHookLogger.Configs.isRecord
。YukiHookLogger.Configs.elements
自定义调试日志对外显示的元素。onInit
中对 YukiHookAPI.Configs
进行配置。override fun onInit() = configs {
+ debugLog {
+ // ...
+ elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
+ }
+ // ...
+}
+
Yuki Hook API
字节码与反射扩展
YukiHookAPI
为开发者封装了一套接近零反射写法的反射 API,它几乎可以完全取代原生 Java 的反射 API 相关用法。 Class 扩展
对象转换
Class
,通常情况下,我们可以使用标准的反射 API 去查找这个 Class
。// 默认 ClassLoader 环境下的 Class
+var instance = Class.forName("com.demo.Test")
+// 指定 ClassLoader 环境下的 Class
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = customClassLoader?.loadClass("com.demo.Test")
+
YukiHookAPI
就为你提供了一个可在任意地方使用的语法糖。YukiHookAPI
可写作如下形式。// 直接得到这个 Class
+// 如果当前正处于 PackageParam 环境,那么你可以不需要考虑 ClassLoader
+var instance = "com.demo.Test".toClass()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = "com.demo.Test".toClass(customClassLoader)
+
Class
并不存在,使用上述方法会抛出异常,如果你不确定 Class
是否存在,可以参考下面的解决方案。// 直接得到这个 Class
+// 如果当前正处于 PackageParam 环境,那么你可以不需要考虑 ClassLoader
+// 得不到时结果会为 null 但不会抛出异常
+var instance = "com.demo.Test".toClassOrNull()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+// 得不到时结果会为 null 但不会抛出异常
+var instance = "com.demo.Test".toClassOrNull(customClassLoader)
+
Class
对象。// 假设这个 Class 是能够被直接得到的
+var instance = classOf<Test>()
+// 我们同样可以自定义 Class 所在的 ClassLoader,这对于 stub 来说非常有效
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var instance = classOf<Test>(customClassLoader)
+
存在判断
Class
是否存在,通常情况下,我们可以使用标准的反射 API 去查找这个 Class
通过异常来判断是否存在。// 默认 ClassLoader 环境下的 Class
+var isExist = try {
+ Class.forName("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+// 指定 ClassLoader 环境下的 Class
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var isExist = try {
+ customClassLoader?.loadClass("com.demo.Test")
+ true
+} catch (_: Throwable) {
+ false
+}
+
YukiHookAPI
就为你提供了一个可在任意地方使用的语法糖。YukiHookAPI
可写作如下形式。// 判断这个 Class 是否存在
+// 如果当前正处于 PackageParam 环境,那么你可以不需要考虑 ClassLoader
+var isExist = "com.demo.Test".hasClass()
+// 自定义 Class 所在的 ClassLoader
+val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+var isExist = "com.demo.Test".hasClass(customClassLoader)
+
Beta
模糊查找 Class
名称将会难以分辨,且不确定其正确位置,不能直接通过 对象转换 来得到。DexClassFinder
,它的作用是通过需要查找的 Class
中的字节码特征来确定这个 Class
的实例。 开始使用
Class
是我们想要得到的,其中的名称经过了混淆,在每个版本可能都不一样。package com.demo;
+
+public class a extends Activity implements Serializable {
+
+ public a(String var1) {
+ // ...
+ }
+
+ private String a;
+
+ private String b;
+
+ private boolean a;
+
+ protected void onCreate(Bundle var1) {
+ // ...
+ }
+
+ private static void a(String var1) {
+ // ...
+ }
+
+ private String a(boolean var1, String var2) {
+ // ...
+ }
+
+ private void a() {
+ // ...
+ }
+
+ public void a(boolean var1, a var2, b var3, String var4) {
+ // ...
+ }
+}
+
Class
,可以直接使用 ClassLoader.searchClass
方法。PackageParam
中,你可以直接使用 searchClass
方法,它将自动指定 appClassLoader
。searchClass {
+ // 从指定的包名范围开始查找,实际使用时,你可以同时指定多个包名范围
+ from("com.demo")
+ // 指定当前 Class 的 getSimpleName 的结果,你可以直接对这个字符串进行逻辑判断
+ // 这里我们不确定它的名称是不是 a,可以只判断字符串长度
+ simpleName { it.length == 1 }
+ // 指定继承的父类对象,如果是存在的 stub,可以直接用泛型表示
+ extends<Activity>()
+ // 指定继承的父类对象,可以直接写为完整类名,你还可以同时指定多个
+ extends("android.app.Activity")
+ // 指定实现的接口,如果是存在的 stub,可以直接用泛型表示
+ implements<Serializable>()
+ // 指定实现的接口,可以直接写为完整类名,你还可以同时指定多个
+ implements("java.io.Serializable")
+ // 指定构造方法的类型与样式,以及在当前类中存在的个数 count
+ constructor { param(StringType) }.count(num = 1)
+ // 指定变量的类型与样式,以及在当前类中存在的个数 count
+ field { type = StringType }.count(num = 2)
+ // 指定变量的类型与样式,以及在当前类中存在的个数 count
+ field { type = BooleanType }.count(num = 1)
+ // 直接指定所有变量在当前类中存在的个数 count
+ field().count(num = 3)
+ // 如果你认为变量的个数是不确定的,还可以使用如下自定义条件
+ field().count(1..3)
+ field().count { it >= 3 }
+ // 指定方法的类型与样式,以及在当前类中存在的个数 count
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isStatic && isPrivate }
+ param(StringType)
+ returnType = UnitType
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, StringType)
+ returnType = StringType
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ emptyParam()
+ returnType = UnitType
+ }.count(num = 1)
+ // 指定方法的类型与样式,同时指定修饰符和模糊类型 VagueType,以及在当前类中存在的个数 count
+ method {
+ modifiers { isPrivate && isStatic.not() }
+ param(BooleanType, VagueType, VagueType, StringType)
+ returnType = UnitType
+ }.count(num = 1)
+ // 直接指定所有方法在当前类中存在的个数 count
+ method().count(num = 5)
+ // 如果你认为方法的个数是不确定的,还可以使用如下自定义条件
+ method().count(1..5)
+ method().count { it >= 5 }
+ // 直接指定所有成员 (Member) 在当前类中存在的个数 count
+ // 成员包括:Field (变量)、Method (方法)、Constructor (构造方法)
+ member().count(num = 9)
+ // 所有成员中一定存在一个 static 修饰符,可以这样加入此条件
+ member {
+ modifiers { isStatic }
+ }
+}.get() // 得到这个 Class 本身的实例,找不到会返回 null
+
异步查找
DexClassFinder
会使用同步方式查找 Class
,会阻塞当前线程直到找到或找不到发生异常为止,若查找消耗的时间过长,可能会导致宿主发生 ANR 问题。async = true
,这将不需要你再次启动一个线程,API 已帮你处理好相关问题。searchClass(async = true) {
+ // ...
+}.wait { class1 ->
+ // 得到异步结果
+}
+searchClass(async = true) {
+ // ...
+}.wait { class2 ->
+ // 得到异步结果
+}
+
本地缓存
name
参数来对当前宿主版本的查找结果进行本地缓存,下一次将直接从本地缓存中读取查找到的类名。SharedPreferences
,它将被保存到宿主的数据目录中,在宿主版本更新后会重新进行缓存。async = true
,你可以不需要再手动进行设置。searchClass(name = "com.demo.class1") {
+ // ...
+}.wait { class1 ->
+ // 得到异步结果
+}
+searchClass(name = "com.demo.class2") {
+ // ...
+}.wait { class2 ->
+ // 得到异步结果
+}
+
// 直接调用,在宿主的 appContext 为空时可能会失败,失败会打印警告信息
+DexClassFinder.clearCache()
+// 监听宿主的生命周期后调用
+onAppLifecycle {
+ onCreate {
+ DexClassFinder.clearCache(context = this)
+ }
+}
+
// 直接调用,在宿主的 appContext 为空时可能会失败,失败会打印警告信息
+DexClassFinder.clearCache(versionName = "1.0", versionCode = 1)
+// 监听宿主的生命周期后调用
+onAppLifecycle {
+ onCreate {
+ DexClassFinder.clearCache(context = this, versionName = "1.0", versionCode = 1)
+ }
+}
+
多重查找
Class
,那么你只需要使用 all
或 waitAll
方法来得到结果。// 同步查找,使用 all 得到条件全部查找到的结果
+searchClass {
+ // ...
+}.all().forEach { clazz ->
+ // 得到每个结果
+}
+// 同步查找,使用 all { ... } 遍历每个结果
+searchClass {
+ // ...
+}.all { clazz ->
+ // 得到每个结果
+}
+// 异步查找,使用 waitAll 得到条件全部查找到的结果
+searchClass(async = true) {
+ // ...
+}.waitAll { classes ->
+ classes.forEach {
+ // 得到每个结果
+ }
+}
+
Member 扩展
Class
。package com.demo;
+
+public class BaseTest {
+
+ public BaseTest() {
+ // ...
+ }
+
+ public BaseTest(boolean isInit) {
+ // ...
+ }
+
+ private void doBaseTask(String taskName) {
+ // ...
+ }
+}
+
package com.demo;
+
+public class Test extends BaseTest {
+
+ public Test() {
+ // ...
+ }
+
+ public Test(boolean isInit) {
+ // ...
+ }
+
+ private static TAG = "Test";
+
+ private BaseTest baseInstance;
+
+ private String a;
+
+ private boolean a;
+
+ private boolean isTaskRunning = false;
+
+ private static void init() {
+ // ...
+ }
+
+ private void doTask(String taskName) {
+ // ...
+ }
+
+ private void release(String taskName, Function<boolean, String> task, boolean isFinish) {
+ // ...
+ }
+
+ private void stop() {
+ // ...
+ }
+
+ private String getName() {
+ // ...
+ }
+
+ private void b() {
+ // ...
+ }
+
+ private void b(String a) {
+ // ...
+ }
+}
+
查找与反射调用
Test
(以下统称“当前 Class
”)的 doTask
方法并执行,通常情况下,我们可以使用标准的反射 API 去查找这个方法。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用反射 API 调用并执行
+Test::class.java
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(instance, "task_name")
+
YukiHookAPI
就为你提供了一个可在任意地方使用的语法糖。YukiHookAPI
可写作如下形式。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ param(StringType)
+}.get(instance).call("task_name")
+
isTaskRunning
变量也可以写作如下形式。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.field {
+ name = "isTaskRunning"
+ type = BooleanType
+}.get(instance).any() // any 为 Field 的任意类型实例化对象
+
Class
的构造方法,同样可以实现。Test::class.java.constructor {
+ param(BooleanType)
+}.get().call(true) // 可创建一个新的实例
+
Class
的无参构造方法,可写作如下形式。Test::class.java.constructor().get().call() // 可创建一个新的实例
+
可选的查找条件
Class
中的 getName
方法,可以使用如下实现。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+ returnType = StringType
+}.get(instance).string() // 得到方法的结果
+
Class
中只有一个名为 getName
的方法,那我们可不可以再简单一点呢?// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "getName"
+ emptyParam()
+}.get(instance).string() // 得到方法的结果
+
get
或 wait
方法得到结果时 YukiHookAPI
会默认按照字节码顺序匹配第一个查找到的结果。Class
中有一个 release
方法,但是它的方法参数很长,而且部分类型可能无法直接得到。param(...)
来查找这个方法,但是有没有更简单的方法呢。paramCount
来查找到这个方法。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "release"
+ // 此时我们不必确定方法参数具体类型,写个数就好
+ paramCount = 3
+}.get(instance) // 得到这个方法
+
VagueType
来填充你不想填写的方法参数类型。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "release"
+ // 使用 VagueType 来填充不想填写的类型,同时保证其它类型能够匹配
+ param(StringType, VagueType, BooleanType)
+}.get(instance) // 得到这个方法
+
在父类查找
Test
继承于 BaseTest
,现在我们想得到 BaseTest
的 doBaseTask
方法,在不知道父类名称的情况下,要怎么做呢?superClass
即可实现这个功能。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringType)
+ // 只需要添加这个条件
+ superClass()
+}.get(instance).call("task_name")
+
superClass
有一个参数为 isOnlySuperClass
,设置为 true
后,可以跳过当前 Class
仅查找当前 Class
的父类。doBaseTask
方法只存在于父类,可以加上这个条件节省查找时间。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "doBaseTask"
+ param(StringType)
+ // 加入一个查找条件
+ superClass(isOnlySuperClass = true)
+}.get(instance).call("task_name")
+
superClass
一旦设置就会自动循环向后查找全部继承的父类中是否有这个方法,直到查找到目标没有父类(继承关系为 java.lang.Object
)为止。 模糊查找
Class
中的 doTask
方法,可以使用如下实现。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name {
+ // 设置名称不区分大小写
+ it.equals("dotask", isIgnoreCase = true)
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
Class
中仅有一个 doTask
方法,我们还可以判断方法名称仅包含其中指定的字符。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name {
+ // 仅包含 oTas
+ it.contains("oTas")
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name {
+ // 开头包含 do,结尾包含 Task
+ it.startsWith("do") && it.endsWith("Task")
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name {
+ // 开头包含 do,结尾包含 Task,仅包含字母
+ it.startsWith("do") && it.endsWith("Task") && it.isOnlyLetters()
+ }
+ param(StringType)
+}.get(instance).call("task_name")
+
多重查找
Class
中具有相同特征的一组方法、构造方法、变量,此时,我们就可以利用相对条件匹配来完成。get
换为 all
即可得到匹配条件的全部字节码。Class
中方法参数个数范围在 1..3
的全部方法,可以使用如下实现。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ paramCount(1..3)
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
private void doTask(String taskName)
private void release(String taskName, Function<boolean, String> task, boolean isFinish)
private void b(String a)
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ paramCount { it < 3 }
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
private static void init()
private void doTask(String taskName)
private void stop(String a)
private void getName(String a)
private void b()
private void b(String a)
Class
中有两个名称为 b
的方法,可以使用如下实现。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "b"
+}.all(instance).forEach { instance ->
+ // 调用执行每个方法
+ instance.call(...)
+}
+
private void b()
private void b(String a)
静态字节码
Class
中是静态的实现,这个时候,我们不需要传入实例就可以调用它们。TAG
的内容。Test::class.java.field {
+ name = "TAG"
+ type = StringType
+}.get().string() // Field 的类型是字符串,可直接进行 cast
+
Class
中存在同名的非静态 TAG
变量,这个时候怎么办呢?Test::class.java.field {
+ name = "TAG"
+ type = StringType
+ // 标识查找的这个变量需要是静态
+ modifiers { isStatic }
+}.get().string() // Field 的类型是字符串,可直接进行 cast
+
init
的静态方法。Test::class.java.method {
+ name = "init"
+ emptyParam()
+}.get().call()
+
Test::class.java.method {
+ name = "init"
+ emptyParam()
+ // 标识查找的这个方法需要是静态
+ modifiers { isStatic }
+}.get().call()
+
混淆的字节码
Class
中有两个混淆的变量名称,它们都是 a
,这个时候我们要怎么得到它们呢?// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.field {
+ name = "a"
+ type = BooleanType
+}.get(instance).any() // 得到名称为 a 类型为 Boolean 的变量
+
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.field {
+ type(BooleanType).index().first()
+}.get(instance).any() // 得到第一个类型为 Boolean 的变量
+
private boolean a
。Class
中也有两个混淆的方法名称,它们都是 b
。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "b"
+ param(StringType)
+}.get(instance).call("test_string") // 得到名称为 b 方法参数为 [String] 的方法
+
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ param(StringType).index().first()
+}.get(instance).call("test_string") // 得到第一个方法参数为 [String] 的方法
+
Class
的最后一个,那我们还有一个备选方案。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ order().index().last()
+}.get(instance).call("test_string") // 得到当前 Class 的最后一个方法
+
直接调用
get(instance)
才能调用对应的方法,有没有简单一点的办法呢?current
方法来创建一个调用空间。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // 执行 doTask 方法
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+ // 执行 stop 方法
+ method {
+ name = "stop"
+ emptyParam()
+ }.call()
+ // 得到 name
+ val name = method { name = "getName" }.string()
+}
+
superClass
调用当前 Class
父类的方法。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // 执行父类的 doBaseTask 方法
+ superClass().method {
+ name = "doBaseTask"
+ param(StringType)
+ }.call("task_name")
+}
+
current()
方法。// 假设这就是这个 Class 的实例,这个 Class 是不能被直接得到的
+val instance = Test()
+// 执行 doTask 方法
+instance
+ .current()
+ .method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+// 执行 stop 方法
+instance
+ .current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// 得到 name
+val name = instance.current().method { name = "getName" }.string()
+
// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+}.current()
+ .method {
+ name = "stop"
+ emptyParam()
+ }.call()
+// ❗注意,因为 current() 返回的是 CurrentClass 自身对象,所以不能像下面这样调用
+instance.current().current()
+
Field
实例,还有一个便捷的方法,可以直接获取 Field
所在实例的对象。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 假设这个 Class 是不能被直接得到的
+instance.current {
+ // <方案1>
+ field {
+ name = "baseInstance"
+ }.current {
+ method {
+ name = "doBaseTask"
+ param(StringType)
+ }.call("task_name")
+ }
+ // <方案2>
+ field {
+ name = "baseInstance"
+ }.current()
+ ?.method {
+ name = "doBaseTask"
+ param(StringType)
+ }?.call("task_name")
+}
+
Test(true).doTask("task_name")
+
"com.demo.Test".toClass()
+ .getDeclaredConstructor(Boolean::class.java)
+ .apply { isAccessible = true }
+ .newInstance(true)
+ .apply {
+ javaClass
+ .getDeclaredMethod("doTask", String::class.java)
+ .apply { isAccessible = true }
+ .invoke(this, "task_name")
+ }
+
buildOf
方法来创建一个实例。"com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.call("task_name")
+}
+
buildOf
方法返回当前实例的类型,你可以在其中加入类型泛型声明,而无需使用 as
来 cast
目标类型。// 假设这个 Class 是能够直接被得到的
+val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
+test.doTask("task_name")
+
原始调用
XposedBridge
为我们提供了一个 XposedBridge.invokeOriginalMethod
功能。YukiHookAPI
中你可以使用如下方法便捷地实现这个功能。Class
。public class Test {
+
+ public static String getString() {
+ return "Original";
+ }
+}
+
Class
中 getString
方法的方式。Test::class.java.hook {
+ injectMember {
+ method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+ }
+ replaceTo("Hooked")
+ }
+}
+
"Hooked"
。// result 的结果会是 "Hooked"
+val result = Test::class.java.method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+}.get().string()
+
original
即可。// result 的结果会是 "Original"
+val result = Test::class.java.method {
+ name = "getString"
+ emptyParam()
+ returnType = StringType
+}.get().original().string()
+
再次查找
Class
,它们都是这个宿主不同版本相同的 Class
。doTask
,假设它们的功能是一样的。public class Test {
+
+ public void doTask() {
+ // ...
+ }
+}
+
public class Test {
+
+ public void doTask(String taskName) {
+ // ...
+ }
+}
+
public class Test {
+
+ public void doTask(String taskName, int type) {
+ // ...
+ }
+}
+
doTask
方法,要怎么做呢?RemedyPlan
完成你的需求。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ param(StringType)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+ method {
+ name = "doTask"
+ param(StringType, IntType)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+}.wait(instance) {
+ // 得到方法的结果
+}
+
RemedyPlan
。// 假设这就是这个 Class 的实例
+val instance = Test()
+// 使用 YukiHookAPI 调用并执行
+Test::class.java.method {
+ name = "doTask"
+ emptyParam()
+}.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }.onFind {
+ // 可在这里实现找到的逻辑
+ }
+}.waitAll(instance) {
+ // 得到方法的结果
+}
+
Class
举例,若 多重查找 结合 RemedyPlan
在创建 Hook 的时候使用,你需要稍微改变一下用法。injectMember {
+ method {
+ name = "doTask"
+ emptyParam()
+ }.remedys {
+ method {
+ name = "doTask"
+ paramCount(0..1)
+ }
+ method {
+ name = "doTask"
+ paramCount(1..2)
+ }
+ }.all()
+ beforeHook {}
+ afterHook {}
+}
+
相对匹配
Class
但仅有 Class
的名称不一样。public class ATest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
public class BTest {
+
+ public static void doTask() {
+ // ...
+ }
+}
+
Class
里的 doTask
方法该怎么做呢?Class
是否存在。// 首先查找到这个 Class
+val currentClass =
+ if("com.demo.ATest".hasClass()) "com.demo.ATest".toClass() else "com.demo.BTest".toClass()
+// 然后再查找这个方法并调用
+currentClass.method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
YukiHookAPI
就为你提供了一个非常方便的 VariousClass
专门来解决这个问题。Class
。VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
在指定的 ClassLoader
中存在,你可以在 get
中填入你的 ClassLoader
。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
一定会被匹配到,你可以使用 getOrNull
方法。val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
+VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
+ name = "doTask"
+ emptyParam()
+}?.get()?.call()
+
PackageParam
中操作 (Xposed) 宿主环境的 Class
,可以直接使用 toClass()
进行设置。VariousClass("com.demo.ATest", "com.demo.BTest").toClass().method {
+ name = "doTask"
+ emptyParam()
+}.get().call()
+
Class
的异常。findClass("com.demo.ATest", "com.demo.BTest").hook {
+ // Your code here.
+}
+
Class
定义为一个常量类型来使用。// 定义常量类型
+val ABTestClass = VariousClass("com.demo.ATest", "com.demo.BTest")
+// 直接使用
+ABTestClass.hook {
+ // Your code here.
+}
+
调用泛型
YukiHookAPI
同样提供了一个可在任意地方使用的语法糖。class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // ...
+ }
+}
+
Class
中获得泛型 T
或 R
的 Class
实例,只需要如下实现。class TestGeneric<T, R> (t: T, r: R) {
+
+ fun foo() {
+ // 获得当前实例的操作对象
+ // 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写
+ val tClass = current().generic()?.argument()
+ // 获得 R 的 Class 实例,在参数第 1 位
+ val rClass = current().generic()?.argument(index = 1)
+ // 你还可以使用如下写法
+ current().generic {
+ // 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写
+ val tClass = argument()
+ // 获得 R 的 Class 实例,在参数第 1 位
+ val rClass = argument(index = 1)
+ }
+ }
+}
+
Class
时,就可以有如下实现。// 假设这个就是 T 的 Class
+class TI {
+
+ fun foo() {
+ // ...
+ }
+}
+// 假设这个就是 T 的实例
+val tInstance: TI? = ...
+// 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写,并获得其中的方法 foo 并调用
+TestGeneric::class.java.generic()?.argument()?.method {
+ name = "foo"
+ emptyParam()
+}?.get(tInstance)?.invoke<TI>()
+
注意误区
限制性查找条件
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ // ❗错误的使用方法,请仅保留一个 index 方法
+ returnType(StringType).index(num = 1)
+}
+
method {
+ name = "test"
+ param(BooleanType).index(num = 2)
+ order().index(num = 1)
+}
+
必要的查找条件
Class
。public class TestFoo {
+
+ public void foo(String string) {
+ // ...
+ }
+
+ public void foo() {
+ // ...
+ }
+}
+
public void foo()
方法,可以写作如下形式。TestFoo::class.java.method {
+ name = "foo"
+}
+
Class
中有两个 foo
方法,其中一个带有方法参数。param
的查找条件,得到的结果将会是匹配名称且匹配字节码顺序的第一个方法 public void foo(String string)
,而不是我们需要的最后一个方法。TestFoo::class.java.method {
+ name = "foo"
+ // ✅ 正确的使用方法,添加详细的筛选条件
+ emptyParam()
+}
+
public void foo()
方法。 可简写查找条件
Class
。public class TestFoo {
+
+ public TestFoo() {
+ // ...
+ }
+}
+
public TestFoo()
构造方法,可以写作如下形式。TestFoo::class.java.constructor { emptyParam() }
+
public TestFoo()
构造方法,但是感觉有一些繁琐。name
名称,当构造方法没有参数的时候,我们可以省略 emptyParam
参数。TestFoo::class.java.constructor()
+
字节码类型
Boolean
类型的变量,把他转换为 String
。field {
+ name = "test"
+ type = BooleanType
+}.get().string() // ❗错误的使用方法,必须 cast 为字节码目标类型
+
field {
+ name = "test"
+ type = BooleanType
+}.get().boolean().toString() // ✅ 正确的使用方法,得到类型后再进行转换
+
常用类型扩展
field {
+ name = "test"
+ type = Boolean::class.java
+}
+
Kotlin
中表达出 Boolean::class.java
这个类型的写法很长,感觉并不方便。YukiHookAPI
为开发者封装了常见的类型调用,其中包含了 Android 的基本类型和 Java 的基本类型。field {
+ name = "test"
+ type = BooleanType
+}
+
IntType
、FloatType
。String[]
类型的数组。java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass
才能得到这个类型。ArrayClass(StringType)
来得到这个类型。String
是常见类型,所以还可以直接使用 StringArrayClass
来得到这个类型。onCreate
方法需要查找 Bundle::class.java
类型。method {
+ name = "onCreate"
+ param(BundleClass)
+}
+
Yuki Hook API
Xposed 模块与宿主通讯桥
基本用法
wait
与 put
方法的基本使用方法。dataChannel
来实现模块与宿主之间的通讯桥,原理为发送接收系统无序广播。// 从指定包名的宿主获取
+dataChannel(packageName = "com.example.demo").wait<String>(key = "key_from_host") { value ->
+ // Your code here.
+}
+// 发送给指定包名的宿主
+dataChannel(packageName = "com.example.demo").put(key = "key_from_module", value = "I am module")
+
// 从模块获取
+dataChannel.wait<String>(key = "key_from_module") { value ->
+ // Your code here.
+}
+// 发送给模块
+dataChannel.put(key = "key_from_host", value = "I am host")
+
dataChannel
的 value
来达到仅通知模块或宿主回调 wait
方法。// 从指定包名的宿主获取
+dataChannel(packageName = "com.example.demo").wait(key = "listener_from_host") {
+ // Your code here.
+}
+// 发送给指定包名的宿主
+dataChannel(packageName = "com.example.demo").put(key = "listener_from_module")
+
// 从模块获取
+dataChannel.wait(key = "listener_from_module") {
+ // Your code here.
+}
+// 发送给模块
+dataChannel.put(key = "listener_from_host")
+
判断模块与宿主版本是否匹配
YukiHookAPI
还为你提供了在用户更新模块后,判断模块是否与宿主版本匹配的解决方案。checkingVersionEquals
方法,即可实现这个功能。// 从指定包名的宿主获取
+dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
+ // Your code here.
+}
+
// 从模块获取
+dataChannel.checkingVersionEquals { isEquals ->
+ // Your code here.
+}
+
回调事件响应的规则
key
始终不允许重复创建。class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // 回调事件 A
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ // 回调事件 B
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ // 回调事件 C
+ dataChannel(packageName = "com.example.demo").wait(key = "other_test_key") {
+ // Your code here.
+ }
+ }
+}
+
+class OtherActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ // 回调事件 D
+ dataChannel(packageName = "com.example.demo").wait(key = "test_key") {
+ // Your code here.
+ }
+ }
+}
+
key
不与其它重复,回调事件 D 在另一个 Activity 中,所以最终回调事件 B、C、D 都可被创建成功。 安全性说明
Yuki Hook API
Xposed 模块数据存储
SharedPreferences
和 XSharedPreferences
的高效模块数据存储解决方案。Sp
存储的数据互通阻碍。Xposed
给我们提供了一个 XSharedPreferences
用于读取模块的 Sp
数据。 在 Activity 中使用
Activity
中装载 YukiHookModulePrefs
的场景。XSharedPreferences(BuildConfig.APPLICATION_ID)
+
YukiHookAPI
的扩展能力快速实现这个功能。Activity
内,可以使用如下方法。modulePrefs.putString("test_name", "saved_value")
+
val testName = prefs.getString("test_name", "default_value")
+
YukiHookModulePrefs
来处理。prefs
文件的名称。Activity
中这样使用。// 推荐用法
+modulePrefs("specify_file_name").putString("test_name", "saved_value")
+// 也可以这样用
+modulePrefs.name("specify_file_name").putString("test_name", "saved_value")
+
// 推荐用法
+val testName = prefs("specify_file_name").getString("test_name", "default_value")
+// 也可以这样用
+val testName = prefs.name("specify_file_name").getString("test_name", "default_value")
+
PrefsData
来创建模板。 在 PreferenceFragment 中使用
PreferenceFragment
中装载 YukiHookModulePrefs
的场景。PreferenceFragmentCompat
,你现在可以将其继承类开始迁移到 ModulePreferenceFragment
。Yuki Hook API
API 基本配置
YukiHookAPI
的基本配置方法。 功能配置
YukiHookAPI
进行配置。 configs 方法
fun configs(initiate: Configs.() -> Unit)
+
configs
方法对 Configs
类实现了一个 lambda
方法体,你可以轻松地调用它进行配置。 Hooker 配置
YukiHookAPI
提供了两种使用方法。 通过 lambda 创建
encase 方法
fun encase(initiate: PackageParam.() -> Unit)
+
encase
方法是 Hook 一切生命的开始,在一个模块或一个 Hook 过程中,encase
方法只能作用一次,用于创建 Hooker。PackageParam
为宿主(目标 APP)的重要实例对象,通过 PackageParam
来实现对当前 Hook 作用对象的全部 Hook 操作。encase
方法可以在 onHook
方法中使用两种方案创建。YukiHookAPI.encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
encase
方法中进行你的 Hook 操作。 通过自定义 Hooker 创建
encase 方法
fun encase(vararg hooker: YukiBaseHooker)
+
encase
方法,这里的方法可变数组参数 hooker
为创建入口提供了一个对象,你可以将所有继承于 YukiBaseHooker
的 Hooker 一次性进行装载。 YukiBaseHooker 用法
YukiBaseHooker
继承于 PackageParam
,你需要将你的子 Hooker 继承于 YukiBaseHooker
。object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // Your code here.
+ }
+}
+
object
创建,你也可以使用 class
但不推荐。object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ loadApp(name = "com.example.demo1") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+ loadApp(name = "com.example.demo2") {
+ findClass(name = "$packageName.CustomClass").hook {
+ // Your code here.
+ }
+ }
+ }
+}
+
loadApp
方法,然后在内部直接开始 Hook。class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase {
+ loadApp(name = "com.example.demo", ChildCustomHooker)
+ }
+}
+
+object ChildCustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ }
+}
+
loadHooker
方法在子 Hooker 中多层装载另一个 Hooker,请按照你的喜好进行即可。object FirstHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ loadHooker(SecondHooker)
+ loadHooker(ThirdHooker)
+ }
+}
+
HookEntryClass
入口类中的 onHook
方法中装载你的 Hooker 了。class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() =
+ YukiHookAPI.encase(FirstHooker, SecondHooker, ThirdHooker ...)
+}
+
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase(FirstHooker, SecondHooker, ThirdHooker ...)
+}
+
扩展特性
encase
中创建 Resources Hook。initZygote
、handleLoadPackage
、handleInitPackageResources
方法来执行不同的功能。YukiHookAPI
中,这些功能是无缝的。encase {
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ // 创建一个 Resources Hook (固定用法)
+ resources().hook {
+ // Your code here.
+ }
+ }
+}
+
loadZygote
方法来装载新的进程被 fork 后的第一个事件 initZygote
。encase {
+ loadZygote {
+ ActivityClass.hook {
+ // Your code here.
+ }
+ // 在 Zygote 中创建 Resources Hook
+ resources().hook {
+ // Your code here.
+ }
+ }
+ loadApp(name = "com.example.demo") {
+ findClass(name = "$packageName.DemoClass").hook {
+ // Your code here.
+ }
+ // 在 APP 中创建 Resources Hook
+ resources().hook {
+ // Your code here.
+ }
+ }
+}
+
注意事项
encase
事件在被 Hook Framework 装载后,会经历三次回调。initZygote
→ encase
handleLoadPackage
→ encase
handleInitPackageResources
→ encase
loadApp
、loadSystem
、loadZygote
来区分每一次装载代码的调用域,否则你的代码就会被多次执行造成错误。encase {
+ // ❗错误的使用方法,不能直接开始 Hook
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ // ❗错误的使用方法,不能直接开始 Hook
+ resources().hook {
+ // ...
+ }
+}
+
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() {
+ // <情景1>
+ encase {
+ loadHooker(CustomHooker)
+ }
+ // <情景2>
+ encase(CustomHooker)
+ }
+}
+
+object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // ❗错误的使用方法,由于外层没有任何判断对象,不能直接开始 Hook
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ }
+}
+
encase {
+ // ✅ 正确的使用方法,在 Zygote 中装载
+ loadZygote(CustomHooker)
+ // ✅ 正确的使用方法,在 Zygote 中装载
+ loadZygote {
+ // ✅ 正确的使用方法,在 Zygote 内 Hook
+ resources().hook {
+ // ...
+ }
+ }
+ // ✅ 正确的使用方法,使用 APP 作用域装载
+ loadApp(/** name 参数可选 */, hooker = CustomHooker)
+ // ✅ 正确的使用方法,判断 APP 作用域后再装载 Hooker
+ loadApp(/** name 参数可选 */) {
+ loadHooker(CustomHooker)
+ // ✅ 正确的使用方法,在 APP 作用域内 Hook
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ // ✅ 正确的使用方法,在 APP 作用域内 Hook
+ resources().hook {
+ // ...
+ }
+ }
+}
+
class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() {
+ encase(CustomHooker)
+ }
+}
+
+object CustomHooker : YukiBaseHooker() {
+
+ override fun onHook() {
+ // ✅ 正确的使用方法,由于外层没有任何判断对象,需要判断 APP 作用域后再进行 Hook
+ loadApp(/** name 参数可选 */) {
+ findClass(name = "com.example.demo.DemoClass").hook {
+ // ...
+ }
+ }
+ }
+}
+
作为 Hook API 使用需要注意的地方
encase
方法进行区分。fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
+
fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
+
baseContext
只需填入你在 attachBaseContext
处得到的 Context
即可,其它用法与上述内容完全一致。Yuki Hook API
作为 Hook API 使用的相关配置
依赖配置
com.highcapable.yukihookapi:api
依赖即可。Hook Framework
依赖。 入口配置
Application
。attachBaseContext
中添加 YukiHookAPI.encase
方法。class MyApplication : Application() {
+
+ override fun attachBaseContext(base: Context?) {
+ // 装载 Hook Framework
+ //
+ // Your code here.
+ //
+ // 配置 YukiHookAPI
+ YukiHookApi.configs {
+ // Your code here.
+ }
+ // 装载 YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+ }
+}
+
Hook Framework
Hook Framework
如何对接 YukiHookAPI
的相关方式。Pine
top.canyie.pine:xposed
override fun attachBaseContext(base: Context?) {
+ // 装载 Pine
+ PineConfig.debug = true
+ PineConfig.debuggable = BuildConfig.DEBUG
+ // 装载 YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
SandHook
com.swift.sandhook:xposedcompat
或 com.swift.sandhook:xposedcompat_new
override fun attachBaseContext(base: Context?) {
+ // 装载 SandHook
+ SandHookConfig.DEBUG = BuildConfig.DEBUG
+ XposedCompat.cacheDir = base?.cacheDir
+ XposedCompat.context = base
+ XposedCompat.classLoader = javaClass.classLoader
+ XposedCompat.isFirstApplication = base?.processName == base?.packageName
+ // 装载 YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
Whale
com.wind.xposed:xposed-on-whale
override fun attachBaseContext(base: Context?) {
+ // 装载 Whale 不需要任何配置
+ // 装载 YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
Yuki Hook API
R8 与 Proguard 混淆
R8
R8
,那么你无需对 YukiHookAPI
进行任何特殊配置。 Proguard
如果你仍然在使用 Proguard
,你需要做一些规则配置。R8
,请在 gradle.properties
文件中加入如下规则,Android Gradle Plugin 7.0 及以上版本无需任何配置。android.enableR8=true
+
Yuki Hook API
作为 Xposed 模块使用的相关配置
YukiHookAPI
作为 Xposed 模块使用的相关配置方法。 依赖配置
YukiHookAPI
提供了一个自动处理程序。build.gradle
中集成 com.highcapable.yukihookapi:ksp-xposed
依赖的最新版本。 自定义处理程序
YukiHookAPI
将如何生成 xposed_init
入口进行相关配置。 InjectYukiHookWithXposed 注解
annotation class InjectYukiHookWithXposed(
+ val sourcePath: String,
+ val modulePackageName: String,
+ val entryClassName: String,
+ val isUsingResourcesHook: Boolean
+)
+
@InjectYukiHookWithXposed
注解是一个标记模块 Hook 入口的重要注解。 sourcePath 参数
sourcePath
参数决定了自动处理程序自动查找并匹配你当前项目路径的重要标识,此参数的内容为相对路径匹配,默认参数为 src/main
。@InjectYukiHookWithXposed(sourcePath = "src/custom")
+
sourcePath
使用的文件路径分隔符写法根据 Windows
和 Unix
将自动进行识别,使用 /
或 \
均可。 modulePackageName 参数
modulePackageName
是你当前项目的 applicationId
,也就是你的模块包名 (最终生成的应用包名),留空或不填时自动处理程序将对当前项目文件进行分析并生成。com.example.demo
,以下定义方式任选其一。BuildConfig.java
文件,就不需要做额外操作。AndroidManifest.xml
示例<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.demo">
+
build.gradle
示例android {
+ namespace 'com.example.demo'
+}
+
build.gradle.kts
示例android {
+ namespace = "com.example.demo"
+}
+
modulePackageName
的参数。@InjectYukiHookWithXposed(modulePackageName = "com.example.demo")
+
modulePackageName
的参数,你就会在编译时收到警告。You set the customize module package name to "com.example.demo", please check for yourself if it is correct
+
entryClassName 参数
entryClassName
决定了自动处理程序如何生成 xposed_init
中的入口类名,默认会使用你的入口类包名插入 _YukiHookXposedInit
后缀进行生成。@InjectYukiHookWithXposed
+class HookEntry: IYukiHookXposedInit
+
class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
+
...hook.HookEntry ← 你的入口类
+...hook.HookEntry_Impl ← 自动生成的 Impl 类
+...hook.HookEntry_YukiHookXposedInit ← 自动生成的 Xposed 入口类
+
HookXposedEntry
。@InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
+class HookEntry: IYukiHookXposedInit
+
class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
+
...hook.HookEntry ← 你的入口类
+...hook.HookEntry_Impl ← 自动生成的 Impl 类
+...hook.HookXposedEntry ← 自动生成的 Xposed 入口类
+
isUsingResourcesHook 参数
isUsingResourcesHook
决定了自动处理程序是否生成针对 Resources Hook 的相关代码,此功能默认是启用的。class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
+ // ...
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
+ // ...
+ }
+
+ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam?) {
+ // ...
+ }
+}
+
isUsingResourcesHook = false
来关闭自动生成。@InjectYukiHookWithXposed(isUsingResourcesHook = false)
+
class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
+ // ...
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
+ // ...
+ }
+}
+
IYukiHookXposedInit 接口
IYukiHookXposedInit
接口为你的 HookEntryClass
必须实现的接口,这是你的模块开始 Hook 的起点。onHook
方法将会被回调,你需要在此方法中开始使用 YukiHookAPI
。_YukiHookXposedInit
→ IYukiHookXposedInit.onXposedEvent
→ IYukiHookXposedInit.onInit
→ IYukiHookXposedInit.onHook
原生 Xposed API 事件
onXposedEvent
实现监听原生 Xposed API 的全部装载事件。@InjectYukiHookWithXposed
+class HookEntry: IYukiHookXposedInit {
+
+ override fun onHook() {
+ // Your code here.
+ }
+
+ override fun onXposedEvent() {
+ // 监听原生 Xposed API 的装载事件
+ YukiXposedEvent.events {
+ onInitZygote {
+ // it 对象即 [StartupParam]
+ }
+ onHandleLoadPackage {
+ // it 对象即 [LoadPackageParam]
+ }
+ onHandleInitPackageResources {
+ // it 对象即 [InitPackageResourcesParam]
+ }
+ }
+ }
+}
+
onXposedEvent
与 onHook
方法完全独立存在,互不影响,你可以继续在 onHook
方法中使用 YukiHookAPI
。Yuki Hook API
用法示例
YukiHookAPI
的基本工作方式以及列举了简单的 Hook 例子和常用功能。 结构图解
YukiHookAPI
的基本工作方式和原理。Host Environment
+└── YukiMemberHookCreator
+ └── Class
+ └── MemberHookCreator
+ └── Member
+ ├── Before
+ └── After
+ MemberHookCreator
+ └── Member
+ ├── Before
+ └── After
+ ...
+ YukiResourcesHookCreator
+ └── Resources
+ └── ResourcesHookCreator
+ └── Drawable
+ └── Replace
+ ResourcesHookCreator
+ └── Layout
+ └── Inject
+ ...
+
TargetClass.hook {
+ injectMember {
+ method {
+ // Your code here.
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+}
+resources().hook {
+ injectResource {
+ conditions {
+ // Your code here.
+ }
+ replaceTo(...)
+ }
+}
+
Demo
YukiHookAPI
的使用方法。 一个简单的 Hook 例子
Hook APP
com.android.browser
中的 onCreate
方法并弹出一个对话框。encase
方法体中添加代码。loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ AlertDialog.Builder(instance())
+ .setTitle("Hooked")
+ .setMessage("I am hook!")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+ }
+ }
+}
+
onCreate
方法将被成功 Hook 并在 com.android.browser
中的每个 Activity
启动时弹出此对话框。onStart
方法要怎么做呢?injectMember
方法体即可。loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ AlertDialog.Builder(instance())
+ .setTitle("Hooked")
+ .setMessage("I am hook!")
+ .setPositiveButton("OK", null)
+ .show()
+ }
+ }
+ injectMember {
+ method {
+ name = "onStart"
+ emptyParam()
+ returnType = UnitType
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+}
+
Class
,你可以使用 stub
方式或 findClass
方法来得到需要 Hook 的类。com.example.demo.TestClass
。findClass(name = "com.example.demo.TestClass").hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
com.example.demo
是你要 Hook 的 APP,那么写法可以更简单。findClass(name = "$packageName.TestClass").hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
findClass
显得有些繁琐。const val TestClass = "com.example.demo.TestClass"
+
+TestClass.hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
"$packageName.TestClass".hook {
+ injectMember {
+ // Your code here.
+ }
+}
+
Hook Zygote
initZygote
。Activity
的 onCreate
事件encase
方法体中添加代码。loadZygote {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ returnType = UnitType
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+}
+
Hook 系统框架
YukiHookAPI
中,Hook 系统框架的实现非常简单。ApplicationInfo
与 PackageInfo
并对它们进行一些操作。encase
方法体中添加代码。loadSystem {
+ ApplicationInfoClass.hook {
+ // Your code here.
+ }
+ PackageInfoClass.hook {
+ // Your code here.
+ }
+}
+
Hook Resources
com.android.browser
中 string
类型的 app_name
内容替换为 123
。encase
方法体中添加代码。loadApp(name = "com.android.browser") {
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "app_name"
+ string()
+ }
+ replaceTo("123")
+ }
+ }
+}
+
app_name
设置了标题栏文本,则它就会变成我们的 123
。com.android.browser
中 mipmap
类型的 ic_launcher
。loadApp(name = "com.android.browser") {
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+}
+
loadApp
换成 loadZygote
即可。loadZygote {
+ resources().hook {
+ // Your code here.
+ }
+}
+
解除 Hook
XC_MethodHook.Unhook
功能,可以从 Hook 队列中将当前 Hook 移除,YukiHookAPI
同样可以实现此功能。Result
实例,在适当的时候和地方调用 remove
即可解除该注入对象。// 设置一个变量保存当前实例
+val hookResult = injectMember {
+ method {
+ name = "test"
+ returnType = UnitType
+ }
+ afterHook {
+ // ...
+ }
+}
+// 在适当的时候调用如下方法即可
+hookResult.remove()
+
removeSelf
移除自身。injectMember {
+ method {
+ name = "test"
+ returnType = UnitType
+ }
+ afterHook {
+ // 直接调用如下方法即可
+ removeSelf()
+ }
+}
+
异常处理
YukiHookAPI
重新设计了对异常的监听,任何异常都不会在 Hook 过程中抛出,避免打断下一个 Hook 流程导致 Hook 进程“死掉”。 监听异常
injectMember {
+ // Your code here.
+}.result {
+ // 处理 Hook 开始时的异常
+ onHookingFailure {}
+ // 处理 Hook 过程中的异常
+ onConductFailure { param, throwable -> }
+ // 处理全部异常
+ onAllFailure {}
+ // ...
+}
+
injectResource {
+ // Your code here.
+}.result {
+ // 处理 Hook 时的任意异常
+ onHookingFailure {}
+ // ...
+}
+
Class
不存在时发生的异常。TargetClass.hook {
+ injectMember {
+ // Your code here.
+ }
+}.onHookClassNotFoundFailure {
+ // Your code here.
+}
+
method {
+ // Your code here.
+}.onNoSuchMethod {
+ // Your code here.
+}
+
抛出异常
hook
方法体内抛出的异常会被 YukiHookAPI
接管,避免打断下一个 Hook 流程导致 Hook 进程“死掉”。YukiHookAPI
接管时这些异常的运作方式。// <情景1>
+injectMember {
+ method {
+ throw RuntimeException("Exception Test")
+ }
+ afterHook {
+ // ...
+ }
+}.result {
+ // 能够捕获到 RuntimeException
+ onHookingFailure {}
+}
+// <情景2>
+injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ throw RuntimeException("Exception Test")
+ }
+}.result {
+ // 能够捕获到 RuntimeException
+ onConductFailure { param, throwable -> }
+}
+
param.throwable
方法,YukiHookAPI
同样可以实现此功能。injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ RuntimeException("Exception Test").throwToApp()
+ }
+}
+
injectMember {
+ method {
+ // ...
+ }
+ afterHook {
+ throw RuntimeException("Exception Test")
+ }.onFailureThrowToApp()
+}
+
状态监听
XposedHelpers
的同学往往会在 Hook 后打印 Unhook
的方法确定是否 Hook 成功。YukiHookAPI
中,你可以用以下方法方便地重新实现这个功能。YourClass.hook {
+ // Your code here.
+}.onPrepareHook {
+ loggerD(msg = "$instanceClass hook start")
+}
+
injectMember {
+ // Your code here.
+}.onHooked { member ->
+ loggerD(msg = "$member has hooked")
+}
+
扩展用法
多个宿主
loadApp
方法体来区分你要 Hook 的 APP。loadApp(name = "com.android.browser") {
+ // Your code here.
+}
+loadApp(name = "com.android.phone") {
+ // Your code here.
+}
+
多个进程
withProcess
方法体来对它们分别进行 Hook。withProcess(mainProcessName) {
+ // Your code here.
+}
+withProcess(name = "$packageName:tool") {
+ // Your code here.
+}
+
写法优化
YukiHookAPI
的名称,将你的 onHook
入口写作 lambda
形式。override fun onHook() = encase {
+ // Your code here.
+}
+
Xposed 模块判断自身激活状态
false
,然后 Hook 掉这个方法使其返回 true
来证明 Hook 已经生效。YukiHookAPI
中你完全不需要再这么做了,YukiHookAPI
已经帮你封装好了这个操作,你可以直接进行使用。YukiHookAPI.Status.isXposedModuleActive
在模块中判断自身是否被激活。if(YukiHookAPI.Status.isXposedModuleActive) {
+ // Your code here.
+}
+
YukiHookAPI.Status.isTaiChiModuleActive
判断自身是否被激活。if(YukiHookAPI.Status.isTaiChiModuleActive) {
+ // Your code here.
+}
+
YukiHookAPI
同样为你封装了便捷的方式。YukiHookAPI.Status.isModuleActive
判断自身是否在 Xposed 或太极、无极中被激活。if(YukiHookAPI.Status.isModuleActive) {
+ // Your code here.
+}
+
Yuki Hook API
介绍
背景
Kotlin
重新构建的高效 Xposed Hook API。 用途
YukiHookAPI
完全采用 Kotlin
lambda
语法构建。XposedHelpers
,你可以使用它来轻松创建 Xposed 模块以及轻松实现自定义 Hook API。 语言要求
Kotlin
,框架部分代码构成同样兼容 Java
但基础 Hook 场景的实现可能完全无法使用。Kotlin
进行描述,如果你完全不会使用 Kotlin
那你将有可能无法使用 YukiHookAPI
。 灵感来源
assets
下创建 xposed_init
文件。XposedHelpers
去实现我们的 Hook 逻辑。Kotlin
作为 Android 主要开发语言以来,这套 API 用起来确实已经不是很优雅了。YukiHookAPI
诞生了。Kotlin
优雅的 lambda
写法以及 YukiHookAPI
,可以让你的 Hook 逻辑更加美观清晰。@InjectYukiHookWithXposed
+class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = encase {
+ loadZygote {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "sym_def_app_icon"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+ }
+ loadApp(name = "com.android.browser") {
+ ActivityClass.hook {
+ injectMember {
+ method {
+ name = "onCreate"
+ param(BundleClass)
+ }
+ beforeHook {
+ // Your code here.
+ }
+ afterHook {
+ // Your code here.
+ }
+ }
+ }
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+ }
+ }
+}
+
class HookEntry : IXposedHookZygoteInit, IXposedHookLoadPackage, IXposedHookInitPackageResources {
+
+ private lateinit var moduleResources: XModuleResources
+
+ override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
+ moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
+ XResources.setSystemWideReplacement(
+ "android", "mipmap", "sym_def_app_icon",
+ moduleResources.fwd(R.mipmap.ic_launcher)
+ )
+ XposedHelpers.findAndHookMethod(
+ Activity::class.java.name,
+ null, "onCreate",
+ Bundle::class.java,
+ object : XC_MethodHook() {
+ override fun beforeHookedMethod(param: MethodHookParam?) {
+ // Your code here.
+ }
+
+ override fun afterHookedMethod(param: MethodHookParam?) {
+ // Your code here.
+ }
+ })
+ }
+
+ override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
+ if (lpparam.packageName == "com.android.browser")
+ XposedHelpers.findAndHookMethod(
+ Activity::class.java.name,
+ lpparam.classLoader, "onCreate",
+ Bundle::class.java,
+ object : XC_MethodHook() {
+ override fun beforeHookedMethod(param: MethodHookParam?) {
+ // Your code here.
+ }
+
+ override fun afterHookedMethod(param: MethodHookParam?) {
+ // Your code here.
+ }
+ })
+ }
+
+ override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
+ if (resparam.packageName == "com.android.browser")
+ resparam.res.setReplacement(
+ "com.android.browser", "mipmap", "ic_launcher",
+ moduleResources.fwd(R.mipmap.ic_launcher)
+ )
+ }
+}
+
YukiHookAPI
,你就可以实现一个非常简单的 Xposed 模块。 支持的 Hook 框架
YukiHookAPI
支持的 Hook Framework
以及 Xposed 框架。Hook Framework ST Description LSPosed ✅ 多场景下稳定使用 LSPatch ⭕ 将在此项目完善后逐渐加入 API 支持 EdXposed ❎ 已停止维护,不再推荐使用 Pine ⭕ 可以使用 SandHook ⭕ 可以使用 Whale ⭕ 需要 xposed-hook-based-on-whale YAHFA ❗ 需要自行实现 Xposed API FastHook ❗ 需要自行实现 Xposed API Epic ❗ 需要自行对接 Dexposed TaiChi ⭕ 可以作为模块使用 Xposed ❎ 未测试,不再推荐使用 Yuki Hook API
基础知识
相关介绍
Xposed 是什么
Xposed 能做什么
Xposed Framework
+└── App's Environment
+ └── Hooker (Hooked)
+ ...
+ App's Environment
+ └── Hooker (Hooked)
+ ...
+ ...
+
XposedBridge
所提供的 Hook 操作动态地在宿主 (APP) 要执行的方法前后插入自己的代码,或完全替换目标,甚至是拦截。 发展过程
衍生产品
App's Environment
+└── Hook Framework
+ └── Hooker (Hooked)
+ ...
+
YukiHookAPI 做了什么
XposedHelpers
,依然没有一套针对 Kotlin
打造的语法糖以及用法封装十分完善的 API。YukiHookAPI
将在使用 Xposed API 的目标基础上适配更多第三方 Hook 框架,使得整个生态得到完善,并帮助更多开发者让 Xposed 模块开发变得更加简单和易懂。 让我们开始吧
YukiHookAPI
。Yuki Hook API
从 Xposed API 迁移
YukiHookAPI
。 迁移 Hook 入口点
XC_LoadPackage.LoadPackageParam
迁移至 PackageParam
。YukiHookAPI
对 PackageParam
实现了 lambda
方法体 this
用法,在 encase
方法体内即可全局得到 PackageParam
对象。override fun onHook() = encase {
+ // 得到当前 Hook 的包名
+ packageName
+ // 得到当前 Hook 的 ApplicationInfo
+ appInfo
+ // 得到系统上下文对象
+ systemContext
+ // 得到宿主 Application 生命周期
+ appContext
+ // Hook 指定的 APP
+ loadApp(name = "com.demo.test") {
+ // Class Hook
+ findClass("com.demo.test.TestClass").hook {
+ injectMember {
+ method {
+ name = "test"
+ param(BooleanType)
+ }
+ afterHook {
+ // ...
+ }
+ }
+ }
+ // Resources Hook (固定用法)
+ resources().hook {
+ injectResource {
+ conditions {
+ name = "ic_launcher"
+ mipmap()
+ }
+ replaceToModuleResource(R.mipmap.ic_launcher)
+ }
+ }
+ }
+}
+
private lateinit var moduleResources: XModuleResources
+
+override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam) {
+ moduleResources = XModuleResources.createInstance(sparam.modulePath, null)
+}
+
+override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam) {
+ // 得到当前 Hook 的包名
+ lpparam.packageName
+ // 得到当前 Hook 的 ApplicationInfo
+ lpparam.applicationInfo
+ // 得到系统上下文对象
+ // 在原生 Xposed API 中没有现成的调用方法,你需要自行反射 ActivityThread 来实现
+ // 得到宿主 Application 生命周期
+ AndroidAppHelper.currentApplication()
+ // Class Hook
+ if(lpparam.packageName == "com.demo.test")
+ XposedHelpers.findAndHookMethod(
+ "com.demo.test.TestClass", lpparam.classLoader,
+ "test", Boolean::class.java,
+ object : XC_MethodHook() {
+ override fun afterHookedMethod(param: MethodHookParam) {
+ // ...
+ }
+ }
+ )
+}
+
+override fun handleInitPackageResources(resparam: XC_InitPackageResources.InitPackageResourcesParam) {
+ // 得到当前 Hook 的包名
+ resparam.packageName
+ // Resources Hook
+ resparam.res.setReplacement(
+ "com.demo.test", "mipmap","ic_launcher",
+ moduleResources.fwd(R.mipmap.ic_launcher)
+ )
+}
+
迁移 Hook 方法体
XC_MethodHook.MethodHookParam
迁移至 HookParam
。 Before/After Hook
YukiHookAPI
同样对 HookParam
实现了 lambda
方法体 this
用法,在 beforeHook
、afterHook
等方法体内即可全局得到 HookParam
对象。afterHook {
+ // 得到当前 Hook 的实例
+ instance
+ // 得到当前 Hook 的 Class 实例
+ instanceClass
+ // 得到并 cast 当前 Hook 的实例为指定类型 T
+ instance<T>()
+ // 得到方法参数数组
+ args
+ // 得到方法参数的第一位 T
+ args().first().cast<T>()
+ // 得到方法参数的最后一位 T
+ args().last().cast<T>()
+ // 得到方法参数的任意下标 T,这里用 2 举例
+ args(index = 2).cast<T>()
+ // 设置方法参数的任意下标,这里用 2 举例
+ args(index = 2).set(...)
+ // 得到返回值
+ result
+ // 得到返回值并 cast 为 T
+ result<T>()
+ // 修改返回值内容
+ result = ...
+ // 删除返回值内容
+ resultNull()
+ // 向 Hook APP 抛出异常
+ Throwable("Fatal").throwToApp()
+ // 执行未经 Hook 的原始方法并使用原始方法参数调用,泛型可略
+ callOriginal<Any?>()
+ // 执行未经 Hook 的原始方法并自定义方法参数调用,泛型可略
+ invokeOriginal<Any?>(...)
+}
+
override fun afterHookedMethod(param: MethodHookParam) {
+ // 得到当前 Hook 的实例
+ param.thisObject
+ // 得到当前 Hook 的 Class 实例
+ param.thisObject.javaClass
+ // 得到并 cast 当前 Hook 的实例为指定类型 T
+ param.thisObject as T
+ // 得到方法参数数组
+ param.args
+ // 得到方法参数的第一位 T
+ param.args[0] as T
+ // 得到方法参数的最后一位 T
+ param.args[param.args.lastIndex] as T
+ // 得到方法参数的任意下标 T,这里用 2 举例
+ param.args[2] as T
+ // 设置方法参数的任意下标,这里用 2 举例
+ param.args[2] = ...
+ // 得到返回值
+ param.result
+ // 得到返回值并 cast 为 T
+ param.result as T
+ // 修改返回值内容
+ param.result = ...
+ // 删除返回值内容
+ param.result = null
+ // 向 Hook APP 抛出异常
+ param.throwable = Throwable("Fatal")
+ // 执行未经 Hook 的原始方法
+ XposedBridge.invokeOriginalMethod(param.method, param.thisObject, ...)
+}
+
Replace Hook
replaceHook
方法比较特殊,YukiHookAPI
为它做出了多种形式以供选择。/// 无返回值的方法 void
+
+replaceUnit {
+ // 直接在这里实现被替换的逻辑
+}
+
+/// 有返回值的方法
+
+replaceAny {
+ // 在这里实现被替换的逻辑
+ // ...
+ // 需要返回方法对应的返回值,无需写 return,只需将参数放到最后一位
+ // 假设这个方法的返回值是 Int,我们只需要保证最后一位是我们需要的返回值即可
+ 0
+}
+
+/// 有些方法我们只需替换其返回值,则有如下实现
+/// 需要注意的是:直接替换返回值的方法传入的参数是固定不变的,若想实现动态替换返回值请使用上面的 replaceAny 方法体
+
+// 替换为你需要的返回值
+replaceTo(...)
+// 替换为 Boolean 类型的返回值
+replaceToTrue()
+// 拦截返回值
+intercept()
+
/// 无返回值的方法 void
+
+override fun replaceHookedMethod(param: MethodHookParam): Any? {
+ // 直接在这里实现被替换的逻辑
+ return null
+}
+
+/// 有返回值的方法
+
+override fun replaceHookedMethod(param: MethodHookParam): Int {
+ // 在这里实现被替换的逻辑
+ // ...
+ // 假设这个方法的返回值是 Int
+ return 0
+}
+
+/// 有些方法我们只需替换其返回值,则有如下实现
+
+// 替换为你需要的返回值
+override fun replaceHookedMethod(param: MethodHookParam) = ...
+// 替换为 Boolean 类型的返回值
+override fun replaceHookedMethod(param: MethodHookParam) = true
+// 拦截返回值
+override fun replaceHookedMethod(param: MethodHookParam) = null
+
迁移其它功能
YukiHookAPI
对 Xposed API 进行了完全重写,你可以参考 API 文档 以及 特色功能 来决定一些功能性的迁移和使用。Yuki Hook API
快速开始
YukiHookAPI
到你的项目中。 环境要求
1.0.80
) 自动构建项目
YukiHookAPI
提供了一个自动化构建工具,它可以帮助你快速构建一个拥有 Xposed 模块依赖的 Android 标准项目模板,使用构建好的模板即可直接开始下一步工作。 手动配置项目
创建项目
Android Studio
或 IntelliJ IDEA
创建新的 Android 项目,并在 Language
一栏选择 Kotlin
以自动添加基础依赖。 集成依赖
build.gradle
中添加依赖。repositories {
+ google()
+ mavenCentral()
+ // ❗若你的 Plugin 版本过低,作为 Xposed 模块使用务必添加,其它情况可选
+ maven { url "https://dl.bintray.com/kotlin/kotlin-eap" }
+ // ❗作为 Xposed 模块使用务必添加,其它情况可选
+ maven { url "https://api.xposed.info/" }
+ // MavenCentral 有 2 小时缓存,若无法集成最新版本请添加此地址
+ maven { url "https://s01.oss.sonatype.org/content/repositories/releases" }
+}
+
build.gradle
中添加 plugin
。plugins {
+ // ❗作为 Xposed 模块使用务必添加,其它情况可选
+ id 'com.google.devtools.ksp' version '<ksp-version>'
+}
+
build.gradle
中添加依赖。dependencies {
+ // 基础依赖
+ implementation 'com.highcapable.yukihookapi:api:<yuki-version>'
+ // ❗作为 Xposed 模块使用务必添加,其它情况可选
+ compileOnly 'de.robv.android.xposed:api:82'
+ // ❗作为 Xposed 模块使用务必添加,其它情况可选
+ ksp 'com.highcapable.yukihookapi:ksp-xposed:<yuki-version>'
+}
+
build.gradle
中修改 Kotlin
的 Jvm 版本为 11 及以上。android {
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_11
+ targetCompatibility JavaVersion.VERSION_11
+ }
+ kotlinOptions {
+ jvmTarget = '11'
+ }
+}
+
作为 Xposed 模块使用
AndroidManifest.xml
中添加基础代码。<!-- 设置为 Xposed 模块 -->
+<meta-data
+ android:name="xposedmodule"
+ android:value="true" />
+
+<!-- 设置你的模块描述 -->
+<meta-data
+ android:name="xposeddescription"
+ android:value="填写你的 Xposed 模块描述" />
+
+<!-- 最低 Xposed 版本号,若你正在使用 EdXposed/LSPosed,建议最低为 93 -->
+<meta-data
+ android:name="xposedminversion"
+ android:value="93" />
+
+<!-- 可选:配置支持 New XSharePrefs 可无需调整 xposedminversion 为 93 -->
+<meta-data
+ android:name="xposedsharedprefs"
+ android:value="true"/>
+
IYukiHookXposedInit
并加入注解 @InjectYukiHookWithXposed
。@InjectYukiHookWithXposed
+class HookEntry : IYukiHookXposedInit {
+
+ override fun onHook() = YukiHookAPI.encase {
+ // Your code here.
+ }
+}
+
作为 Hook API 使用
集成方式
Application
。attachBaseContext
中添加 YukiHookAPI.encase
方法。override fun attachBaseContext(base: Context?) {
+ // 装载 Hook Framework
+ //
+ // Your code here.
+ //
+ // 装载 YukiHookAPI
+ YukiHookAPI.encase(base) {
+ // Your code here.
+ }
+ super.attachBaseContext(base)
+}
+
Yuki Hook API
YukiHookAPI 构建工具
YukiHookAPI
作为核心的 Xposed 模块自动构建工具。 获取项目
使用方法
基本用法
配置模板
多语言支持