From 5019f3c03a86fc713642e5319a1fd2bf8306f522 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Wed, 28 Sep 2022 04:26:36 +0800 Subject: [PATCH] Automatically compile documentation (1.1.0) --- docs/404.html | 33 + docs/assets/404.html.c038a05a.js | 1 + docs/assets/404.html.d9151b86.js | 1 + docs/assets/BaseFinder.html.1ec4ffab.js | 9 + docs/assets/BaseFinder.html.8588c8ac.js | 9 + docs/assets/BaseFinder.html.8f275c85.js | 1 + docs/assets/BaseFinder.html.a5dbb7a7.js | 1 + docs/assets/ChannelData.html.194718a1.js | 1 + docs/assets/ChannelData.html.2358cb0e.js | 23 + docs/assets/ChannelData.html.2404edfd.js | 23 + docs/assets/ChannelData.html.f8f818f6.js | 1 + .../ComponentTypeFactory.html.0026a7b8.js | 1 + .../ComponentTypeFactory.html.2f6bbc66.js | 1 + .../ComponentTypeFactory.html.5af05d7d.js | 1 + .../ComponentTypeFactory.html.61d8989e.js | 1 + .../assets/ConstructorFinder.html.022babd4.js | 87 ++ .../assets/ConstructorFinder.html.0c13dc47.js | 1 + .../assets/ConstructorFinder.html.254da89b.js | 87 ++ .../assets/ConstructorFinder.html.7de4f560.js | 1 + docs/assets/ConstructorRules.html.d56dfdf4.js | 8 + docs/assets/ConstructorRules.html.d62bae6c.js | 1 + docs/assets/ConstructorRules.html.e17434ce.js | 8 + docs/assets/ConstructorRules.html.f8d7dd83.js | 1 + docs/assets/CountRules.html.2639d392.js | 1 + docs/assets/CountRules.html.2d5ab94d.js | 1 + docs/assets/CountRules.html.5103015c.js | 6 + docs/assets/CountRules.html.52ed8a0d.js | 6 + docs/assets/CurrentClass.html.072e89c6.js | 16 + docs/assets/CurrentClass.html.16c29272.js | 1 + docs/assets/CurrentClass.html.2e606398.js | 16 + docs/assets/CurrentClass.html.641fcd58.js | 1 + .../DefinedTypeFactory.html.1a27d470.js | 2 + .../DefinedTypeFactory.html.8137c32c.js | 1 + .../DefinedTypeFactory.html.ba3bdd0b.js | 1 + .../DefinedTypeFactory.html.bca7fe3f.js | 2 + docs/assets/DexClassFinder.html.5d8e12f0.js | 1 + docs/assets/DexClassFinder.html.5e274913.js | 45 + docs/assets/DexClassFinder.html.78c5f805.js | 1 + docs/assets/DexClassFinder.html.92677d64.js | 45 + docs/assets/FieldFinder.html.25713065.js | 1 + docs/assets/FieldFinder.html.4410e26c.js | 1 + docs/assets/FieldFinder.html.7f3e47fc.js | 83 ++ docs/assets/FieldFinder.html.908d5caa.js | 83 ++ docs/assets/FieldRules.html.1fea86e8.js | 6 + docs/assets/FieldRules.html.6858f0d6.js | 1 + docs/assets/FieldRules.html.990238ad.js | 6 + docs/assets/FieldRules.html.9b04521f.js | 1 + docs/assets/GenericClass.html.3a0e1ac6.js | 1 + docs/assets/GenericClass.html.7b666428.js | 1 + docs/assets/GenericClass.html.b1c03ed1.js | 3 + docs/assets/GenericClass.html.ca958253.js | 3 + .../GraphicsTypeFactory.html.61eca533.js | 1 + .../GraphicsTypeFactory.html.a3936b7c.js | 1 + .../GraphicsTypeFactory.html.bfb4e259.js | 1 + .../GraphicsTypeFactory.html.df9b6853.js | 1 + docs/assets/HookClass.html.486aa6ea.js | 1 + docs/assets/HookClass.html.52e59cf0.js | 1 + docs/assets/HookClass.html.7354fd95.js | 2 + docs/assets/HookClass.html.f01a0415.js | 2 + docs/assets/HookParam.html.30f4fb72.js | 86 ++ docs/assets/HookParam.html.918accc4.js | 86 ++ docs/assets/HookParam.html.b19d4ad2.js | 1 + docs/assets/HookParam.html.f98d02d2.js | 1 + docs/assets/HookResources.html.2486cf29.js | 1 + docs/assets/HookResources.html.4f07fd98.js | 1 + docs/assets/HookResources.html.70a752b2.js | 2 + docs/assets/HookResources.html.b888e8b6.js | 2 + .../IYukiHookXposedInit.html.4813ba4f.js | 5 + .../IYukiHookXposedInit.html.78a55860.js | 1 + .../IYukiHookXposedInit.html.7f3e0a05.js | 5 + .../IYukiHookXposedInit.html.b37a852b.js | 1 + .../InjectYukiHookWithXposed.html.56391530.js | 1 + .../InjectYukiHookWithXposed.html.b6100747.js | 7 + .../InjectYukiHookWithXposed.html.cf9b500d.js | 1 + .../InjectYukiHookWithXposed.html.ecb261b1.js | 7 + docs/assets/LoggerFactory.html.72d1861a.js | 1 + docs/assets/LoggerFactory.html.84495d50.js | 27 + docs/assets/LoggerFactory.html.914e1c34.js | 1 + docs/assets/LoggerFactory.html.bb211a96.js | 27 + docs/assets/MemberRules.html.1a50f297.js | 3 + docs/assets/MemberRules.html.a071b3c6.js | 1 + docs/assets/MemberRules.html.b3e5d297.js | 1 + docs/assets/MemberRules.html.fbc5b06f.js | 3 + .../assets/MemberRulesResult.html.2524371e.js | 6 + .../assets/MemberRulesResult.html.49b372bb.js | 6 + .../assets/MemberRulesResult.html.58e81c94.js | 1 + .../assets/MemberRulesResult.html.e79843c3.js | 1 + docs/assets/MethodFinder.html.03ce70ab.js | 1 + docs/assets/MethodFinder.html.55746f01.js | 102 ++ docs/assets/MethodFinder.html.97f89f93.js | 1 + docs/assets/MethodFinder.html.9844b141.js | 102 ++ docs/assets/MethodRules.html.146b27be.js | 1 + docs/assets/MethodRules.html.9819df7e.js | 11 + docs/assets/MethodRules.html.b1f90f61.js | 11 + docs/assets/MethodRules.html.c10f9770.js | 1 + docs/assets/ModifierRules.html.1596e901.js | 14 + docs/assets/ModifierRules.html.4767495f.js | 14 + docs/assets/ModifierRules.html.c36dff17.js | 1 + docs/assets/ModifierRules.html.f7582dc2.js | 1 + .../assets/ModuleAppActivity.html.09451ff7.js | 1 + .../assets/ModuleAppActivity.html.1aa71ae6.js | 2 + .../assets/ModuleAppActivity.html.90d3c4e6.js | 1 + .../assets/ModuleAppActivity.html.fd7c57b2.js | 2 + .../ModuleAppCompatActivity.html.2fd9ae3a.js | 3 + .../ModuleAppCompatActivity.html.a20d9206.js | 1 + .../ModuleAppCompatActivity.html.dd9e40e9.js | 1 + .../ModuleAppCompatActivity.html.de402219.js | 3 + .../assets/ModuleApplication.html.57573770.js | 1 + .../assets/ModuleApplication.html.a386b8db.js | 1 + .../assets/ModuleApplication.html.ad43cded.js | 17 + .../assets/ModuleApplication.html.e946b5fe.js | 17 + ...ModuleContextThemeWrapper.html.0879426b.js | 1 + ...ModuleContextThemeWrapper.html.229a46ac.js | 1 + ...ModuleContextThemeWrapper.html.5787cac6.js | 3 + ...ModuleContextThemeWrapper.html.7262b83c.js | 3 + .../ModulePreferenceFragment.html.0c7dadc7.js | 1 + .../ModulePreferenceFragment.html.40d2af95.js | 22 + .../ModulePreferenceFragment.html.764fecc3.js | 1 + .../ModulePreferenceFragment.html.7e33a328.js | 22 + docs/assets/NameRules.html.00ac96fb.js | 1 + docs/assets/NameRules.html.4729f5e5.js | 9 + docs/assets/NameRules.html.47e512e4.js | 1 + docs/assets/NameRules.html.5da95c04.js | 9 + docs/assets/PackageParam.html.3014d07d.js | 104 +++ docs/assets/PackageParam.html.37aae471.js | 1 + docs/assets/PackageParam.html.4c3306f9.js | 104 +++ docs/assets/PackageParam.html.7a64d58c.js | 1 + docs/assets/PrefsData.html.0d8e9948.js | 18 + docs/assets/PrefsData.html.be01fa30.js | 18 + docs/assets/PrefsData.html.d3cf97f9.js | 1 + docs/assets/PrefsData.html.dfd7c23c.js | 1 + .../assets/ReflectionFactory.html.a9e6e2d7.js | 1 + .../assets/ReflectionFactory.html.d2629c75.js | 59 ++ .../assets/ReflectionFactory.html.daab3686.js | 59 ++ .../assets/ReflectionFactory.html.f7b7c82c.js | 1 + .../VariableTypeFactory.html.550d3346.js | 1 + .../VariableTypeFactory.html.6d08103b.js | 1 + .../VariableTypeFactory.html.c8d4e99d.js | 1 + .../VariableTypeFactory.html.d4c9dbd1.js | 1 + docs/assets/VariousClass.html.3e45065c.js | 4 + docs/assets/VariousClass.html.5a07233f.js | 4 + docs/assets/VariousClass.html.7c81aa10.js | 1 + docs/assets/VariousClass.html.bd237fa4.js | 1 + docs/assets/ViewTypeFactory.html.612b6202.js | 1 + docs/assets/ViewTypeFactory.html.7da3eef4.js | 1 + docs/assets/ViewTypeFactory.html.e29c5d7e.js | 1 + docs/assets/ViewTypeFactory.html.f12c489b.js | 1 + docs/assets/YukiBaseHooker.html.0fb80f07.js | 3 + docs/assets/YukiBaseHooker.html.6b167698.js | 3 + docs/assets/YukiBaseHooker.html.99eec744.js | 1 + docs/assets/YukiBaseHooker.html.b68236f9.js | 1 + docs/assets/YukiHookAPI.html.18811dc9.js | 98 ++ docs/assets/YukiHookAPI.html.1c02f82e.js | 98 ++ docs/assets/YukiHookAPI.html.476693ca.js | 1 + docs/assets/YukiHookAPI.html.77b2a461.js | 1 + .../YukiHookDataChannel.html.74e08a45.js | 1 + .../YukiHookDataChannel.html.75c012dd.js | 1 + .../YukiHookDataChannel.html.b01666c1.js | 12 + .../YukiHookDataChannel.html.f40252bf.js | 12 + docs/assets/YukiHookFactory.html.122ae5d0.js | 12 + docs/assets/YukiHookFactory.html.61878d38.js | 12 + docs/assets/YukiHookFactory.html.61db5860.js | 1 + docs/assets/YukiHookFactory.html.64f654a6.js | 1 + .../YukiHookModulePrefs.html.5eb62ec3.js | 1 + .../YukiHookModulePrefs.html.77ac932a.js | 30 + .../YukiHookModulePrefs.html.9506520f.js | 30 + .../YukiHookModulePrefs.html.e0f278fe.js | 1 + .../YukiMemberHookCreator.html.37dcaec4.js | 1 + .../YukiMemberHookCreator.html.55afd41d.js | 121 +++ .../YukiMemberHookCreator.html.bacce7a8.js | 121 +++ .../YukiMemberHookCreator.html.d3b181da.js | 1 + .../YukiModuleResources.html.581abd4c.js | 3 + .../YukiModuleResources.html.c36ad6ed.js | 3 + .../YukiModuleResources.html.d8e27a7f.js | 1 + .../YukiModuleResources.html.e5c5fb30.js | 1 + docs/assets/YukiResForwarder.html.0dadd8db.js | 1 + docs/assets/YukiResForwarder.html.3fa53afd.js | 4 + docs/assets/YukiResForwarder.html.4e23df75.js | 1 + docs/assets/YukiResForwarder.html.ef96ef7b.js | 4 + docs/assets/YukiResources.html.7b0a4824.js | 1 + docs/assets/YukiResources.html.afb6fb92.js | 1 + docs/assets/YukiResources.html.b3a31d94.js | 7 + docs/assets/YukiResources.html.d71b960b.js | 7 + .../YukiResourcesHookCreator.html.46168b72.js | 1 + .../YukiResourcesHookCreator.html.8aaa9934.js | 1 + .../YukiResourcesHookCreator.html.d14760e0.js | 95 ++ .../YukiResourcesHookCreator.html.ddbc430b.js | 95 ++ docs/assets/YukiXposedEvent.html.560fa41c.js | 1 + docs/assets/YukiXposedEvent.html.a93ee4ef.js | 1 + docs/assets/YukiXposedEvent.html.ae210e6f.js | 6 + docs/assets/YukiXposedEvent.html.e00ead3e.js | 6 + docs/assets/about.html.7638d3a2.js | 1 + docs/assets/about.html.7d8b24a5.js | 22 + docs/assets/about.html.c0115524.js | 1 + docs/assets/about.html.f4c8582a.js | 22 + docs/assets/api-example.html.47c311e0.js | 1 + docs/assets/api-example.html.63409bed.js | 180 ++++ docs/assets/api-example.html.f5361b1b.js | 1 + docs/assets/api-example.html.ffabf490.js | 182 ++++ docs/assets/api-exception.html.5fb01524.js | 359 ++++++++ docs/assets/api-exception.html.72ebad13.js | 1 + docs/assets/api-exception.html.9f654113.js | 354 +++++++ docs/assets/api-exception.html.ac2a5859.js | 1 + docs/assets/api-using.html.0a59e2e0.js | 1 + docs/assets/api-using.html.1ec848ab.js | 50 + docs/assets/api-using.html.37eb156b.js | 50 + docs/assets/api-using.html.c794f69e.js | 1 + docs/assets/app.fb8271cf.js | 10 + docs/assets/back-to-top.8efcbe56.svg | 1 + docs/assets/changelog.html.05a4745e.js | 1 + docs/assets/changelog.html.22a53013.js | 1 + docs/assets/changelog.html.576ee237.js | 1 + docs/assets/changelog.html.86d916d5.js | 1 + docs/assets/contacts.html.0e0a7262.js | 1 + docs/assets/contacts.html.3df7cacf.js | 1 + docs/assets/contacts.html.5dc8225c.js | 1 + docs/assets/contacts.html.8946c067.js | 1 + docs/assets/example.html.13ac887a.js | 1 + docs/assets/example.html.a036bda1.js | 1 + docs/assets/example.html.be2f529d.js | 286 ++++++ docs/assets/example.html.e66bd85b.js | 286 ++++++ docs/assets/future.html.2cf8d6de.js | 1 + docs/assets/future.html.4da05d23.js | 1 + docs/assets/future.html.94bd226b.js | 1 + docs/assets/future.html.e52259cf.js | 1 + docs/assets/home.html.06a0e41c.js | 107 +++ docs/assets/home.html.4d8cac8a.js | 1 + docs/assets/home.html.6cc8b4b8.js | 107 +++ docs/assets/home.html.cad3998c.js | 1 + docs/assets/home.html.e164d825.js | 1 + docs/assets/home.html.f6b9c2a4.js | 1 + docs/assets/home.html.f6f658d0.js | 1 + docs/assets/home.html.fd8a27c6.js | 1 + docs/assets/host-inject.html.83f072dc.js | 1 + docs/assets/host-inject.html.acabeb56.js | 118 +++ docs/assets/host-inject.html.c5fc5faf.js | 1 + docs/assets/host-inject.html.e5c6c6ae.js | 122 +++ docs/assets/host-lifecycle.html.09c0b222.js | 1 + docs/assets/host-lifecycle.html.412bbdd6.js | 1 + docs/assets/host-lifecycle.html.56277eb5.js | 46 + docs/assets/host-lifecycle.html.73e3c8fc.js | 47 + docs/assets/index.html.1b76ac9e.js | 1 + docs/assets/index.html.6cc32291.js | 1 + docs/assets/index.html.872aa7a1.js | 1 + docs/assets/index.html.d735d08d.js | 26 + docs/assets/index.html.f36dcd2e.js | 26 + docs/assets/index.html.f53b6095.js | 1 + docs/assets/knowledge.html.437816ed.js | 1 + docs/assets/knowledge.html.821f04b5.js | 1 + docs/assets/knowledge.html.a4616f5c.js | 13 + docs/assets/knowledge.html.e0a069f9.js | 13 + docs/assets/logger.html.2d57680b.js | 1 + docs/assets/logger.html.55af0b09.js | 33 + docs/assets/logger.html.e8fab6a3.js | 1 + docs/assets/logger.html.fd07b1ad.js | 31 + docs/assets/move-to-new-api.html.2d2ee2a7.js | 184 ++++ docs/assets/move-to-new-api.html.508c5312.js | 1 + docs/assets/move-to-new-api.html.78f39fa5.js | 1 + docs/assets/move-to-new-api.html.f0cc4092.js | 184 ++++ docs/assets/quick-start.html.20dd75c7.js | 69 ++ docs/assets/quick-start.html.749cf17e.js | 70 ++ docs/assets/quick-start.html.e309979a.js | 1 + docs/assets/quick-start.html.eacb83f2.js | 1 + docs/assets/r8-proguard.html.15e04e11.js | 1 + docs/assets/r8-proguard.html.1ec215bf.js | 2 + docs/assets/r8-proguard.html.44d498ce.js | 2 + docs/assets/r8-proguard.html.683a5429.js | 1 + docs/assets/reflection.html.2e612549.js | 1 + docs/assets/reflection.html.3174ec77.js | 812 ++++++++++++++++ docs/assets/reflection.html.37e12a3d.js | 838 +++++++++++++++++ docs/assets/reflection.html.ff24950f.js | 1 + docs/assets/search.0782d0d1.svg | 1 + docs/assets/style.e115708c.css | 1 + docs/assets/xposed-channel.html.18cd2bdb.js | 62 ++ docs/assets/xposed-channel.html.96712a39.js | 1 + docs/assets/xposed-channel.html.b798a8f8.js | 1 + docs/assets/xposed-channel.html.ea22e7ce.js | 62 ++ docs/assets/xposed-storage.html.5fd9a913.js | 1 + docs/assets/xposed-storage.html.6926bcf4.js | 12 + docs/assets/xposed-storage.html.c35a7041.js | 1 + docs/assets/xposed-storage.html.cd1e83bb.js | 12 + docs/assets/xposed-using.html.557dcdf1.js | 1 + docs/assets/xposed-using.html.701123e9.js | 77 ++ docs/assets/xposed-using.html.cd65195d.js | 1 + docs/assets/xposed-using.html.f07fa93e.js | 77 ++ ...ukihookapi-projectbuilder.html.ae5d1a49.js | 1 + ...ukihookapi-projectbuilder.html.c5d87cd3.js | 1 + ...ukihookapi-projectbuilder.html.d499d226.js | 1 + ...ukihookapi-projectbuilder.html.ed4fa356.js | 1 + docs/en/about/about.html | 54 ++ docs/en/about/changelog.html | 33 + docs/en/about/contacts.html | 33 + docs/en/about/future.html | 33 + docs/en/api/home.html | 33 + .../highcapable/yukihookapi/YukiHookAPI.html | 130 +++ .../xposed/InjectYukiHookWithXposed.html | 39 + .../yukihookapi/hook/bean/CurrentClass.html | 48 + .../yukihookapi/hook/bean/GenericClass.html | 35 + .../yukihookapi/hook/bean/HookClass.html | 34 + .../yukihookapi/hook/bean/HookResources.html | 34 + .../yukihookapi/hook/bean/VariousClass.html | 36 + .../hook/core/YukiMemberHookCreator.html | 153 +++ .../hook/core/YukiResourcesHookCreator.html | 127 +++ .../hook/core/finder/base/BaseFinder.html | 41 + .../core/finder/base/rules/CountRules.html | 38 + .../core/finder/base/rules/ModifierRules.html | 46 + .../core/finder/base/rules/NameRules.html | 41 + .../core/finder/classes/DexClassFinder.html | 77 ++ .../classes/rules/ConstructorRules.html | 40 + .../core/finder/classes/rules/FieldRules.html | 38 + .../finder/classes/rules/MemberRules.html | 35 + .../finder/classes/rules/MethodRules.html | 43 + .../rules/result/MemberRulesResult.html | 38 + .../finder/members/ConstructorFinder.html | 119 +++ .../hook/core/finder/members/FieldFinder.html | 115 +++ .../core/finder/members/MethodFinder.html | 134 +++ .../hook/entity/YukiBaseHooker.html | 35 + .../hook/factory/ReflectionFactory.html | 91 ++ .../hook/factory/YukiHookFactory.html | 44 + .../yukihookapi/hook/log/LoggerFactory.html | 59 ++ .../yukihookapi/hook/param/HookParam.html | 118 +++ .../yukihookapi/hook/param/PackageParam.html | 136 +++ .../type/android/ComponentTypeFactory.html | 33 + .../type/android/GraphicsTypeFactory.html | 33 + .../hook/type/android/ViewTypeFactory.html | 33 + .../hook/type/defined/DefinedTypeFactory.html | 34 + .../hook/type/java/VariableTypeFactory.html | 33 + .../xposed/application/ModuleApplication.html | 49 + .../bridge/dummy/YukiModuleResources.html | 35 + .../xposed/bridge/dummy/YukiResForwarder.html | 36 + .../xposed/bridge/dummy/YukiResources.html | 39 + .../xposed/bridge/event/YukiXposedEvent.html | 38 + .../xposed/channel/YukiHookDataChannel.html | 44 + .../hook/xposed/channel/data/ChannelData.html | 55 ++ .../activity/base/ModuleAppActivity.html | 34 + .../base/ModuleAppCompatActivity.html | 35 + .../wrapper/ModuleContextThemeWrapper.html | 35 + .../xposed/prefs/YukiHookModulePrefs.html | 62 ++ .../hook/xposed/prefs/data/PrefsData.html | 50 + .../prefs/ui/ModulePreferenceFragment.html | 54 ++ .../xposed/proxy/IYukiHookXposedInit.html | 37 + docs/en/api/special-features/host-inject.html | 154 ++++ .../api/special-features/host-lifecycle.html | 79 ++ docs/en/api/special-features/logger.html | 65 ++ docs/en/api/special-features/reflection.html | 870 ++++++++++++++++++ .../api/special-features/xposed-channel.html | 94 ++ .../api/special-features/xposed-storage.html | 44 + docs/en/config/api-example.html | 214 +++++ docs/en/config/api-exception.html | 391 ++++++++ docs/en/config/api-using.html | 82 ++ docs/en/config/r8-proguard.html | 34 + docs/en/config/xposed-using.html | 109 +++ docs/en/guide/example.html | 318 +++++++ docs/en/guide/home.html | 139 +++ docs/en/guide/knowledge.html | 45 + docs/en/guide/move-to-new-api.html | 216 +++++ docs/en/guide/quick-start.html | 102 ++ docs/en/index.html | 58 ++ docs/en/tools/yukihookapi-projectbuilder.html | 33 + docs/images/logo.png | Bin 0 -> 24264 bytes docs/images/yukihookapi-projectbuilder-en.png | Bin 0 -> 364753 bytes .../yukihookapi-projectbuilder-zh-cn.png | Bin 0 -> 684305 bytes docs/index.html | 33 + docs/zh-cn/about/about.html | 54 ++ docs/zh-cn/about/changelog.html | 33 + docs/zh-cn/about/contacts.html | 33 + docs/zh-cn/about/future.html | 33 + docs/zh-cn/api/home.html | 33 + .../highcapable/yukihookapi/YukiHookAPI.html | 130 +++ .../xposed/InjectYukiHookWithXposed.html | 39 + .../yukihookapi/hook/bean/CurrentClass.html | 48 + .../yukihookapi/hook/bean/GenericClass.html | 35 + .../yukihookapi/hook/bean/HookClass.html | 34 + .../yukihookapi/hook/bean/HookResources.html | 34 + .../yukihookapi/hook/bean/VariousClass.html | 36 + .../hook/core/YukiMemberHookCreator.html | 153 +++ .../hook/core/YukiResourcesHookCreator.html | 127 +++ .../hook/core/finder/base/BaseFinder.html | 41 + .../core/finder/base/rules/CountRules.html | 38 + .../core/finder/base/rules/ModifierRules.html | 46 + .../core/finder/base/rules/NameRules.html | 41 + .../core/finder/classes/DexClassFinder.html | 77 ++ .../classes/rules/ConstructorRules.html | 40 + .../core/finder/classes/rules/FieldRules.html | 38 + .../finder/classes/rules/MemberRules.html | 35 + .../finder/classes/rules/MethodRules.html | 43 + .../rules/result/MemberRulesResult.html | 38 + .../finder/members/ConstructorFinder.html | 119 +++ .../hook/core/finder/members/FieldFinder.html | 115 +++ .../core/finder/members/MethodFinder.html | 134 +++ .../hook/entity/YukiBaseHooker.html | 35 + .../hook/factory/ReflectionFactory.html | 91 ++ .../hook/factory/YukiHookFactory.html | 44 + .../yukihookapi/hook/log/LoggerFactory.html | 59 ++ .../yukihookapi/hook/param/HookParam.html | 118 +++ .../yukihookapi/hook/param/PackageParam.html | 136 +++ .../type/android/ComponentTypeFactory.html | 33 + .../type/android/GraphicsTypeFactory.html | 33 + .../hook/type/android/ViewTypeFactory.html | 33 + .../hook/type/defined/DefinedTypeFactory.html | 34 + .../hook/type/java/VariableTypeFactory.html | 33 + .../xposed/application/ModuleApplication.html | 49 + .../bridge/dummy/YukiModuleResources.html | 35 + .../xposed/bridge/dummy/YukiResForwarder.html | 36 + .../xposed/bridge/dummy/YukiResources.html | 39 + .../xposed/bridge/event/YukiXposedEvent.html | 38 + .../xposed/channel/YukiHookDataChannel.html | 44 + .../hook/xposed/channel/data/ChannelData.html | 55 ++ .../activity/base/ModuleAppActivity.html | 34 + .../base/ModuleAppCompatActivity.html | 35 + .../wrapper/ModuleContextThemeWrapper.html | 35 + .../xposed/prefs/YukiHookModulePrefs.html | 62 ++ .../hook/xposed/prefs/data/PrefsData.html | 50 + .../prefs/ui/ModulePreferenceFragment.html | 54 ++ .../xposed/proxy/IYukiHookXposedInit.html | 37 + .../api/special-features/host-inject.html | 150 +++ .../api/special-features/host-lifecycle.html | 78 ++ docs/zh-cn/api/special-features/logger.html | 63 ++ .../api/special-features/reflection.html | 844 +++++++++++++++++ .../api/special-features/xposed-channel.html | 94 ++ .../api/special-features/xposed-storage.html | 44 + docs/zh-cn/config/api-example.html | 212 +++++ docs/zh-cn/config/api-exception.html | 386 ++++++++ docs/zh-cn/config/api-using.html | 82 ++ docs/zh-cn/config/r8-proguard.html | 34 + docs/zh-cn/config/xposed-using.html | 109 +++ docs/zh-cn/guide/example.html | 318 +++++++ docs/zh-cn/guide/home.html | 139 +++ docs/zh-cn/guide/knowledge.html | 45 + docs/zh-cn/guide/move-to-new-api.html | 216 +++++ docs/zh-cn/guide/quick-start.html | 101 ++ docs/zh-cn/index.html | 58 ++ .../tools/yukihookapi-projectbuilder.html | 33 + 433 files changed, 19365 insertions(+) create mode 100644 docs/404.html create mode 100644 docs/assets/404.html.c038a05a.js create mode 100644 docs/assets/404.html.d9151b86.js create mode 100644 docs/assets/BaseFinder.html.1ec4ffab.js create mode 100644 docs/assets/BaseFinder.html.8588c8ac.js create mode 100644 docs/assets/BaseFinder.html.8f275c85.js create mode 100644 docs/assets/BaseFinder.html.a5dbb7a7.js create mode 100644 docs/assets/ChannelData.html.194718a1.js create mode 100644 docs/assets/ChannelData.html.2358cb0e.js create mode 100644 docs/assets/ChannelData.html.2404edfd.js create mode 100644 docs/assets/ChannelData.html.f8f818f6.js create mode 100644 docs/assets/ComponentTypeFactory.html.0026a7b8.js create mode 100644 docs/assets/ComponentTypeFactory.html.2f6bbc66.js create mode 100644 docs/assets/ComponentTypeFactory.html.5af05d7d.js create mode 100644 docs/assets/ComponentTypeFactory.html.61d8989e.js create mode 100644 docs/assets/ConstructorFinder.html.022babd4.js create mode 100644 docs/assets/ConstructorFinder.html.0c13dc47.js create mode 100644 docs/assets/ConstructorFinder.html.254da89b.js create mode 100644 docs/assets/ConstructorFinder.html.7de4f560.js create mode 100644 docs/assets/ConstructorRules.html.d56dfdf4.js create mode 100644 docs/assets/ConstructorRules.html.d62bae6c.js create mode 100644 docs/assets/ConstructorRules.html.e17434ce.js create mode 100644 docs/assets/ConstructorRules.html.f8d7dd83.js create mode 100644 docs/assets/CountRules.html.2639d392.js create mode 100644 docs/assets/CountRules.html.2d5ab94d.js create mode 100644 docs/assets/CountRules.html.5103015c.js create mode 100644 docs/assets/CountRules.html.52ed8a0d.js create mode 100644 docs/assets/CurrentClass.html.072e89c6.js create mode 100644 docs/assets/CurrentClass.html.16c29272.js create mode 100644 docs/assets/CurrentClass.html.2e606398.js create mode 100644 docs/assets/CurrentClass.html.641fcd58.js create mode 100644 docs/assets/DefinedTypeFactory.html.1a27d470.js create mode 100644 docs/assets/DefinedTypeFactory.html.8137c32c.js create mode 100644 docs/assets/DefinedTypeFactory.html.ba3bdd0b.js create mode 100644 docs/assets/DefinedTypeFactory.html.bca7fe3f.js create mode 100644 docs/assets/DexClassFinder.html.5d8e12f0.js create mode 100644 docs/assets/DexClassFinder.html.5e274913.js create mode 100644 docs/assets/DexClassFinder.html.78c5f805.js create mode 100644 docs/assets/DexClassFinder.html.92677d64.js create mode 100644 docs/assets/FieldFinder.html.25713065.js create mode 100644 docs/assets/FieldFinder.html.4410e26c.js create mode 100644 docs/assets/FieldFinder.html.7f3e47fc.js create mode 100644 docs/assets/FieldFinder.html.908d5caa.js create mode 100644 docs/assets/FieldRules.html.1fea86e8.js create mode 100644 docs/assets/FieldRules.html.6858f0d6.js create mode 100644 docs/assets/FieldRules.html.990238ad.js create mode 100644 docs/assets/FieldRules.html.9b04521f.js create mode 100644 docs/assets/GenericClass.html.3a0e1ac6.js create mode 100644 docs/assets/GenericClass.html.7b666428.js create mode 100644 docs/assets/GenericClass.html.b1c03ed1.js create mode 100644 docs/assets/GenericClass.html.ca958253.js create mode 100644 docs/assets/GraphicsTypeFactory.html.61eca533.js create mode 100644 docs/assets/GraphicsTypeFactory.html.a3936b7c.js create mode 100644 docs/assets/GraphicsTypeFactory.html.bfb4e259.js create mode 100644 docs/assets/GraphicsTypeFactory.html.df9b6853.js create mode 100644 docs/assets/HookClass.html.486aa6ea.js create mode 100644 docs/assets/HookClass.html.52e59cf0.js create mode 100644 docs/assets/HookClass.html.7354fd95.js create mode 100644 docs/assets/HookClass.html.f01a0415.js create mode 100644 docs/assets/HookParam.html.30f4fb72.js create mode 100644 docs/assets/HookParam.html.918accc4.js create mode 100644 docs/assets/HookParam.html.b19d4ad2.js create mode 100644 docs/assets/HookParam.html.f98d02d2.js create mode 100644 docs/assets/HookResources.html.2486cf29.js create mode 100644 docs/assets/HookResources.html.4f07fd98.js create mode 100644 docs/assets/HookResources.html.70a752b2.js create mode 100644 docs/assets/HookResources.html.b888e8b6.js create mode 100644 docs/assets/IYukiHookXposedInit.html.4813ba4f.js create mode 100644 docs/assets/IYukiHookXposedInit.html.78a55860.js create mode 100644 docs/assets/IYukiHookXposedInit.html.7f3e0a05.js create mode 100644 docs/assets/IYukiHookXposedInit.html.b37a852b.js create mode 100644 docs/assets/InjectYukiHookWithXposed.html.56391530.js create mode 100644 docs/assets/InjectYukiHookWithXposed.html.b6100747.js create mode 100644 docs/assets/InjectYukiHookWithXposed.html.cf9b500d.js create mode 100644 docs/assets/InjectYukiHookWithXposed.html.ecb261b1.js create mode 100644 docs/assets/LoggerFactory.html.72d1861a.js create mode 100644 docs/assets/LoggerFactory.html.84495d50.js create mode 100644 docs/assets/LoggerFactory.html.914e1c34.js create mode 100644 docs/assets/LoggerFactory.html.bb211a96.js create mode 100644 docs/assets/MemberRules.html.1a50f297.js create mode 100644 docs/assets/MemberRules.html.a071b3c6.js create mode 100644 docs/assets/MemberRules.html.b3e5d297.js create mode 100644 docs/assets/MemberRules.html.fbc5b06f.js create mode 100644 docs/assets/MemberRulesResult.html.2524371e.js create mode 100644 docs/assets/MemberRulesResult.html.49b372bb.js create mode 100644 docs/assets/MemberRulesResult.html.58e81c94.js create mode 100644 docs/assets/MemberRulesResult.html.e79843c3.js create mode 100644 docs/assets/MethodFinder.html.03ce70ab.js create mode 100644 docs/assets/MethodFinder.html.55746f01.js create mode 100644 docs/assets/MethodFinder.html.97f89f93.js create mode 100644 docs/assets/MethodFinder.html.9844b141.js create mode 100644 docs/assets/MethodRules.html.146b27be.js create mode 100644 docs/assets/MethodRules.html.9819df7e.js create mode 100644 docs/assets/MethodRules.html.b1f90f61.js create mode 100644 docs/assets/MethodRules.html.c10f9770.js create mode 100644 docs/assets/ModifierRules.html.1596e901.js create mode 100644 docs/assets/ModifierRules.html.4767495f.js create mode 100644 docs/assets/ModifierRules.html.c36dff17.js create mode 100644 docs/assets/ModifierRules.html.f7582dc2.js create mode 100644 docs/assets/ModuleAppActivity.html.09451ff7.js create mode 100644 docs/assets/ModuleAppActivity.html.1aa71ae6.js create mode 100644 docs/assets/ModuleAppActivity.html.90d3c4e6.js create mode 100644 docs/assets/ModuleAppActivity.html.fd7c57b2.js create mode 100644 docs/assets/ModuleAppCompatActivity.html.2fd9ae3a.js create mode 100644 docs/assets/ModuleAppCompatActivity.html.a20d9206.js create mode 100644 docs/assets/ModuleAppCompatActivity.html.dd9e40e9.js create mode 100644 docs/assets/ModuleAppCompatActivity.html.de402219.js create mode 100644 docs/assets/ModuleApplication.html.57573770.js create mode 100644 docs/assets/ModuleApplication.html.a386b8db.js create mode 100644 docs/assets/ModuleApplication.html.ad43cded.js create mode 100644 docs/assets/ModuleApplication.html.e946b5fe.js create mode 100644 docs/assets/ModuleContextThemeWrapper.html.0879426b.js create mode 100644 docs/assets/ModuleContextThemeWrapper.html.229a46ac.js create mode 100644 docs/assets/ModuleContextThemeWrapper.html.5787cac6.js create mode 100644 docs/assets/ModuleContextThemeWrapper.html.7262b83c.js create mode 100644 docs/assets/ModulePreferenceFragment.html.0c7dadc7.js create mode 100644 docs/assets/ModulePreferenceFragment.html.40d2af95.js create mode 100644 docs/assets/ModulePreferenceFragment.html.764fecc3.js create mode 100644 docs/assets/ModulePreferenceFragment.html.7e33a328.js create mode 100644 docs/assets/NameRules.html.00ac96fb.js create mode 100644 docs/assets/NameRules.html.4729f5e5.js create mode 100644 docs/assets/NameRules.html.47e512e4.js create mode 100644 docs/assets/NameRules.html.5da95c04.js create mode 100644 docs/assets/PackageParam.html.3014d07d.js create mode 100644 docs/assets/PackageParam.html.37aae471.js create mode 100644 docs/assets/PackageParam.html.4c3306f9.js create mode 100644 docs/assets/PackageParam.html.7a64d58c.js create mode 100644 docs/assets/PrefsData.html.0d8e9948.js create mode 100644 docs/assets/PrefsData.html.be01fa30.js create mode 100644 docs/assets/PrefsData.html.d3cf97f9.js create mode 100644 docs/assets/PrefsData.html.dfd7c23c.js create mode 100644 docs/assets/ReflectionFactory.html.a9e6e2d7.js create mode 100644 docs/assets/ReflectionFactory.html.d2629c75.js create mode 100644 docs/assets/ReflectionFactory.html.daab3686.js create mode 100644 docs/assets/ReflectionFactory.html.f7b7c82c.js create mode 100644 docs/assets/VariableTypeFactory.html.550d3346.js create mode 100644 docs/assets/VariableTypeFactory.html.6d08103b.js create mode 100644 docs/assets/VariableTypeFactory.html.c8d4e99d.js create mode 100644 docs/assets/VariableTypeFactory.html.d4c9dbd1.js create mode 100644 docs/assets/VariousClass.html.3e45065c.js create mode 100644 docs/assets/VariousClass.html.5a07233f.js create mode 100644 docs/assets/VariousClass.html.7c81aa10.js create mode 100644 docs/assets/VariousClass.html.bd237fa4.js create mode 100644 docs/assets/ViewTypeFactory.html.612b6202.js create mode 100644 docs/assets/ViewTypeFactory.html.7da3eef4.js create mode 100644 docs/assets/ViewTypeFactory.html.e29c5d7e.js create mode 100644 docs/assets/ViewTypeFactory.html.f12c489b.js create mode 100644 docs/assets/YukiBaseHooker.html.0fb80f07.js create mode 100644 docs/assets/YukiBaseHooker.html.6b167698.js create mode 100644 docs/assets/YukiBaseHooker.html.99eec744.js create mode 100644 docs/assets/YukiBaseHooker.html.b68236f9.js create mode 100644 docs/assets/YukiHookAPI.html.18811dc9.js create mode 100644 docs/assets/YukiHookAPI.html.1c02f82e.js create mode 100644 docs/assets/YukiHookAPI.html.476693ca.js create mode 100644 docs/assets/YukiHookAPI.html.77b2a461.js create mode 100644 docs/assets/YukiHookDataChannel.html.74e08a45.js create mode 100644 docs/assets/YukiHookDataChannel.html.75c012dd.js create mode 100644 docs/assets/YukiHookDataChannel.html.b01666c1.js create mode 100644 docs/assets/YukiHookDataChannel.html.f40252bf.js create mode 100644 docs/assets/YukiHookFactory.html.122ae5d0.js create mode 100644 docs/assets/YukiHookFactory.html.61878d38.js create mode 100644 docs/assets/YukiHookFactory.html.61db5860.js create mode 100644 docs/assets/YukiHookFactory.html.64f654a6.js create mode 100644 docs/assets/YukiHookModulePrefs.html.5eb62ec3.js create mode 100644 docs/assets/YukiHookModulePrefs.html.77ac932a.js create mode 100644 docs/assets/YukiHookModulePrefs.html.9506520f.js create mode 100644 docs/assets/YukiHookModulePrefs.html.e0f278fe.js create mode 100644 docs/assets/YukiMemberHookCreator.html.37dcaec4.js create mode 100644 docs/assets/YukiMemberHookCreator.html.55afd41d.js create mode 100644 docs/assets/YukiMemberHookCreator.html.bacce7a8.js create mode 100644 docs/assets/YukiMemberHookCreator.html.d3b181da.js create mode 100644 docs/assets/YukiModuleResources.html.581abd4c.js create mode 100644 docs/assets/YukiModuleResources.html.c36ad6ed.js create mode 100644 docs/assets/YukiModuleResources.html.d8e27a7f.js create mode 100644 docs/assets/YukiModuleResources.html.e5c5fb30.js create mode 100644 docs/assets/YukiResForwarder.html.0dadd8db.js create mode 100644 docs/assets/YukiResForwarder.html.3fa53afd.js create mode 100644 docs/assets/YukiResForwarder.html.4e23df75.js create mode 100644 docs/assets/YukiResForwarder.html.ef96ef7b.js create mode 100644 docs/assets/YukiResources.html.7b0a4824.js create mode 100644 docs/assets/YukiResources.html.afb6fb92.js create mode 100644 docs/assets/YukiResources.html.b3a31d94.js create mode 100644 docs/assets/YukiResources.html.d71b960b.js create mode 100644 docs/assets/YukiResourcesHookCreator.html.46168b72.js create mode 100644 docs/assets/YukiResourcesHookCreator.html.8aaa9934.js create mode 100644 docs/assets/YukiResourcesHookCreator.html.d14760e0.js create mode 100644 docs/assets/YukiResourcesHookCreator.html.ddbc430b.js create mode 100644 docs/assets/YukiXposedEvent.html.560fa41c.js create mode 100644 docs/assets/YukiXposedEvent.html.a93ee4ef.js create mode 100644 docs/assets/YukiXposedEvent.html.ae210e6f.js create mode 100644 docs/assets/YukiXposedEvent.html.e00ead3e.js create mode 100644 docs/assets/about.html.7638d3a2.js create mode 100644 docs/assets/about.html.7d8b24a5.js create mode 100644 docs/assets/about.html.c0115524.js create mode 100644 docs/assets/about.html.f4c8582a.js create mode 100644 docs/assets/api-example.html.47c311e0.js create mode 100644 docs/assets/api-example.html.63409bed.js create mode 100644 docs/assets/api-example.html.f5361b1b.js create mode 100644 docs/assets/api-example.html.ffabf490.js create mode 100644 docs/assets/api-exception.html.5fb01524.js create mode 100644 docs/assets/api-exception.html.72ebad13.js create mode 100644 docs/assets/api-exception.html.9f654113.js create mode 100644 docs/assets/api-exception.html.ac2a5859.js create mode 100644 docs/assets/api-using.html.0a59e2e0.js create mode 100644 docs/assets/api-using.html.1ec848ab.js create mode 100644 docs/assets/api-using.html.37eb156b.js create mode 100644 docs/assets/api-using.html.c794f69e.js create mode 100644 docs/assets/app.fb8271cf.js create mode 100644 docs/assets/back-to-top.8efcbe56.svg create mode 100644 docs/assets/changelog.html.05a4745e.js create mode 100644 docs/assets/changelog.html.22a53013.js create mode 100644 docs/assets/changelog.html.576ee237.js create mode 100644 docs/assets/changelog.html.86d916d5.js create mode 100644 docs/assets/contacts.html.0e0a7262.js create mode 100644 docs/assets/contacts.html.3df7cacf.js create mode 100644 docs/assets/contacts.html.5dc8225c.js create mode 100644 docs/assets/contacts.html.8946c067.js create mode 100644 docs/assets/example.html.13ac887a.js create mode 100644 docs/assets/example.html.a036bda1.js create mode 100644 docs/assets/example.html.be2f529d.js create mode 100644 docs/assets/example.html.e66bd85b.js create mode 100644 docs/assets/future.html.2cf8d6de.js create mode 100644 docs/assets/future.html.4da05d23.js create mode 100644 docs/assets/future.html.94bd226b.js create mode 100644 docs/assets/future.html.e52259cf.js create mode 100644 docs/assets/home.html.06a0e41c.js create mode 100644 docs/assets/home.html.4d8cac8a.js create mode 100644 docs/assets/home.html.6cc8b4b8.js create mode 100644 docs/assets/home.html.cad3998c.js create mode 100644 docs/assets/home.html.e164d825.js create mode 100644 docs/assets/home.html.f6b9c2a4.js create mode 100644 docs/assets/home.html.f6f658d0.js create mode 100644 docs/assets/home.html.fd8a27c6.js create mode 100644 docs/assets/host-inject.html.83f072dc.js create mode 100644 docs/assets/host-inject.html.acabeb56.js create mode 100644 docs/assets/host-inject.html.c5fc5faf.js create mode 100644 docs/assets/host-inject.html.e5c6c6ae.js create mode 100644 docs/assets/host-lifecycle.html.09c0b222.js create mode 100644 docs/assets/host-lifecycle.html.412bbdd6.js create mode 100644 docs/assets/host-lifecycle.html.56277eb5.js create mode 100644 docs/assets/host-lifecycle.html.73e3c8fc.js create mode 100644 docs/assets/index.html.1b76ac9e.js create mode 100644 docs/assets/index.html.6cc32291.js create mode 100644 docs/assets/index.html.872aa7a1.js create mode 100644 docs/assets/index.html.d735d08d.js create mode 100644 docs/assets/index.html.f36dcd2e.js create mode 100644 docs/assets/index.html.f53b6095.js create mode 100644 docs/assets/knowledge.html.437816ed.js create mode 100644 docs/assets/knowledge.html.821f04b5.js create mode 100644 docs/assets/knowledge.html.a4616f5c.js create mode 100644 docs/assets/knowledge.html.e0a069f9.js create mode 100644 docs/assets/logger.html.2d57680b.js create mode 100644 docs/assets/logger.html.55af0b09.js create mode 100644 docs/assets/logger.html.e8fab6a3.js create mode 100644 docs/assets/logger.html.fd07b1ad.js create mode 100644 docs/assets/move-to-new-api.html.2d2ee2a7.js create mode 100644 docs/assets/move-to-new-api.html.508c5312.js create mode 100644 docs/assets/move-to-new-api.html.78f39fa5.js create mode 100644 docs/assets/move-to-new-api.html.f0cc4092.js create mode 100644 docs/assets/quick-start.html.20dd75c7.js create mode 100644 docs/assets/quick-start.html.749cf17e.js create mode 100644 docs/assets/quick-start.html.e309979a.js create mode 100644 docs/assets/quick-start.html.eacb83f2.js create mode 100644 docs/assets/r8-proguard.html.15e04e11.js create mode 100644 docs/assets/r8-proguard.html.1ec215bf.js create mode 100644 docs/assets/r8-proguard.html.44d498ce.js create mode 100644 docs/assets/r8-proguard.html.683a5429.js create mode 100644 docs/assets/reflection.html.2e612549.js create mode 100644 docs/assets/reflection.html.3174ec77.js create mode 100644 docs/assets/reflection.html.37e12a3d.js create mode 100644 docs/assets/reflection.html.ff24950f.js create mode 100644 docs/assets/search.0782d0d1.svg create mode 100644 docs/assets/style.e115708c.css create mode 100644 docs/assets/xposed-channel.html.18cd2bdb.js create mode 100644 docs/assets/xposed-channel.html.96712a39.js create mode 100644 docs/assets/xposed-channel.html.b798a8f8.js create mode 100644 docs/assets/xposed-channel.html.ea22e7ce.js create mode 100644 docs/assets/xposed-storage.html.5fd9a913.js create mode 100644 docs/assets/xposed-storage.html.6926bcf4.js create mode 100644 docs/assets/xposed-storage.html.c35a7041.js create mode 100644 docs/assets/xposed-storage.html.cd1e83bb.js create mode 100644 docs/assets/xposed-using.html.557dcdf1.js create mode 100644 docs/assets/xposed-using.html.701123e9.js create mode 100644 docs/assets/xposed-using.html.cd65195d.js create mode 100644 docs/assets/xposed-using.html.f07fa93e.js create mode 100644 docs/assets/yukihookapi-projectbuilder.html.ae5d1a49.js create mode 100644 docs/assets/yukihookapi-projectbuilder.html.c5d87cd3.js create mode 100644 docs/assets/yukihookapi-projectbuilder.html.d499d226.js create mode 100644 docs/assets/yukihookapi-projectbuilder.html.ed4fa356.js create mode 100644 docs/en/about/about.html create mode 100644 docs/en/about/changelog.html create mode 100644 docs/en/about/contacts.html create mode 100644 docs/en/about/future.html create mode 100644 docs/en/api/home.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html create mode 100644 docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html create mode 100644 docs/en/api/special-features/host-inject.html create mode 100644 docs/en/api/special-features/host-lifecycle.html create mode 100644 docs/en/api/special-features/logger.html create mode 100644 docs/en/api/special-features/reflection.html create mode 100644 docs/en/api/special-features/xposed-channel.html create mode 100644 docs/en/api/special-features/xposed-storage.html create mode 100644 docs/en/config/api-example.html create mode 100644 docs/en/config/api-exception.html create mode 100644 docs/en/config/api-using.html create mode 100644 docs/en/config/r8-proguard.html create mode 100644 docs/en/config/xposed-using.html create mode 100644 docs/en/guide/example.html create mode 100644 docs/en/guide/home.html create mode 100644 docs/en/guide/knowledge.html create mode 100644 docs/en/guide/move-to-new-api.html create mode 100644 docs/en/guide/quick-start.html create mode 100644 docs/en/index.html create mode 100644 docs/en/tools/yukihookapi-projectbuilder.html create mode 100644 docs/images/logo.png create mode 100644 docs/images/yukihookapi-projectbuilder-en.png create mode 100644 docs/images/yukihookapi-projectbuilder-zh-cn.png create mode 100644 docs/index.html create mode 100644 docs/zh-cn/about/about.html create mode 100644 docs/zh-cn/about/changelog.html create mode 100644 docs/zh-cn/about/contacts.html create mode 100644 docs/zh-cn/about/future.html create mode 100644 docs/zh-cn/api/home.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html create mode 100644 docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html create mode 100644 docs/zh-cn/api/special-features/host-inject.html create mode 100644 docs/zh-cn/api/special-features/host-lifecycle.html create mode 100644 docs/zh-cn/api/special-features/logger.html create mode 100644 docs/zh-cn/api/special-features/reflection.html create mode 100644 docs/zh-cn/api/special-features/xposed-channel.html create mode 100644 docs/zh-cn/api/special-features/xposed-storage.html create mode 100644 docs/zh-cn/config/api-example.html create mode 100644 docs/zh-cn/config/api-exception.html create mode 100644 docs/zh-cn/config/api-using.html create mode 100644 docs/zh-cn/config/r8-proguard.html create mode 100644 docs/zh-cn/config/xposed-using.html create mode 100644 docs/zh-cn/guide/example.html create mode 100644 docs/zh-cn/guide/home.html create mode 100644 docs/zh-cn/guide/knowledge.html create mode 100644 docs/zh-cn/guide/move-to-new-api.html create mode 100644 docs/zh-cn/guide/quick-start.html create mode 100644 docs/zh-cn/index.html create mode 100644 docs/zh-cn/tools/yukihookapi-projectbuilder.html 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 @@ + + + + + + + + + Yuki Hook API + + + + +

404

How did we get here?
Take me home
+ + + diff --git a/docs/assets/404.html.c038a05a.js b/docs/assets/404.html.c038a05a.js new file mode 100644 index 00000000..2a1a1ca6 --- /dev/null +++ b/docs/assets/404.html.c038a05a.js @@ -0,0 +1 @@ +const t=JSON.parse('{"key":"v-3706649a","path":"/404.html","title":"","lang":"en-US","frontmatter":{"layout":"NotFound"},"excerpt":"","headers":[],"git":{},"filePathRelative":null}');export{t as data}; diff --git a/docs/assets/404.html.d9151b86.js b/docs/assets/404.html.d9151b86.js new file mode 100644 index 00000000..e9384019 --- /dev/null +++ b/docs/assets/404.html.d9151b86.js @@ -0,0 +1 @@ +import{_ as e,o as c,c as t}from"./app.fb8271cf.js";const _={};function o(r,n){return c(),t("div")}const a=e(_,[["render",o],["__file","404.html.vue"]]);export{a as default}; diff --git a/docs/assets/BaseFinder.html.1ec4ffab.js b/docs/assets/BaseFinder.html.1ec4ffab.js new file mode 100644 index 00000000..4fa2cd33 --- /dev/null +++ b/docs/assets/BaseFinder.html.1ec4ffab.js @@ -0,0 +1,9 @@ +import{_ as s,o as e,c as o,a as n}from"./app.fb8271cf.js";const a={},p=n(`

BaseFinder - class

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 \u4E0E Member \u67E5\u627E\u7C7B\u529F\u80FD\u7684\u57FA\u672C\u7C7B\u5B9E\u73B0\u3002

BaseFinder.IndexTypeCondition - class

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

index - method

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

index - method

fun index(): IndexTypeConditionSort
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.70 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u4E0B\u6807\u3002

IndexTypeConditionSort - class

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

first - method

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

last - method

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

reverse - method

fun reverse(num: Int)
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.70 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E\u5012\u5E8F\u4E0B\u6807\u3002

`,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(`

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.

BaseFinder - class

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 \u4E0E Member \u67E5\u627E\u7C7B\u529F\u80FD\u7684\u57FA\u672C\u7C7B\u5B9E\u73B0\u3002

BaseFinder.IndexTypeCondition - class

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

index - method

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

index - method

fun index(): IndexTypeConditionSort
+

Change Records

v1.0.70 added

Function Illustrate

\u5F97\u5230\u4E0B\u6807\u3002

IndexTypeConditionSort - class

inner class IndexTypeConditionSort internal constructor()
+

Change Records

v1.0.70 added

Function Illustrate

\u5B57\u8282\u7801\u4E0B\u6807\u6392\u5E8F\u5B9E\u73B0\u7C7B\u3002

first - method

fun first()
+

Change Records

v1.0.70 added

Function Illustrate

\u8BBE\u7F6E\u6EE1\u8DB3\u6761\u4EF6\u7684\u7B2C\u4E00\u4E2A\u3002

last - method

fun last()
+

Change Records

v1.0.70 added

Function Illustrate

\u8BBE\u7F6E\u6EE1\u8DB3\u6761\u4EF6\u7684\u6700\u540E\u4E00\u4E2A\u3002

reverse - method

fun reverse(num: Int)
+

Change Records

v1.0.70 added

Function Illustrate

\u8BBE\u7F6E\u5012\u5E8F\u4E0B\u6807\u3002

`,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(`

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.

ChannelData - class

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.
+}
+
`,20),p=[o];function t(c,r){return a(),n("div",null,p)}const d=s(e,[["render",t],["__file","ChannelData.html.vue"]]);export{d as default}; diff --git a/docs/assets/ChannelData.html.2404edfd.js b/docs/assets/ChannelData.html.2404edfd.js new file mode 100644 index 00000000..a2fc9629 --- /dev/null +++ b/docs/assets/ChannelData.html.2404edfd.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(`

ChannelData - class

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.
+}
+
`,19),p=[o];function c(t,r){return a(),n("div",null,p)}const A=s(e,[["render",c],["__file","ChannelData.html.vue"]]);export{A as default}; diff --git a/docs/assets/ChannelData.html.f8f818f6.js b/docs/assets/ChannelData.html.f8f818f6.js new file mode 100644 index 00000000..1d8b9160 --- /dev/null +++ b/docs/assets/ChannelData.html.f8f818f6.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-2f64a2d4","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html","title":"ChannelData - 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/xposed/channel/data/ChannelData.md"}');export{a as data}; diff --git a/docs/assets/ComponentTypeFactory.html.0026a7b8.js b/docs/assets/ComponentTypeFactory.html.0026a7b8.js new file mode 100644 index 00000000..dce9bd73 --- /dev/null +++ b/docs/assets/ComponentTypeFactory.html.0026a7b8.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5e874c45","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html","title":"ComponentTypeFactory - 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/ComponentTypeFactory.md"}');export{e as data}; diff --git a/docs/assets/ComponentTypeFactory.html.2f6bbc66.js b/docs/assets/ComponentTypeFactory.html.2f6bbc66.js new file mode 100644 index 00000000..fb99b158 --- /dev/null +++ b/docs/assets/ComponentTypeFactory.html.2f6bbc66.js @@ -0,0 +1 @@ +import{_ as n,r as c,o as a,c as r,b as e,d as s,a as p,e as o}from"./app.fb8271cf.js";const d={},i=p('

ComponentTypeFactory - kt

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

\u529F\u80FD\u63CF\u8FF0

\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A Android \u76F8\u5173\u7EC4\u4EF6\u7684 Class \u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002

',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('

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.

ComponentTypeFactory - kt

Change Records

v1.0 first

Function Illustrate

\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A Android \u76F8\u5173\u7EC4\u4EF6\u7684 Class \u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002

',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(`

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.

ConstructorFinder - class

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

paramCount - field

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

modifiers - method

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

emptyParam - method

fun emptyParam(): IndexTypeCondition
+

Change Records

v1.0.75 added

Function Illustrate

\u8BBE\u7F6E Constructor \u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002

param - method

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

paramCount - method

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

paramCount - method

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

paramCount - method

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

superClass - method

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\u524D Constructor\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

RemedyPlan - class

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

constructor - method

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

Result - class

inner class Result internal constructor()
+

Change Records

v1.0.1 added

Function Illustrate

RemedyPlan \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002

onFind - method

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.
+}
+

Process - class

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\u4E3A hookInstance \u63D0\u4F9B\u3002

result - method

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 {}
+}
+

all - method

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\u5230 hookInstance\u3002

remedys - method

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.
+    }
+}
+

onNoSuchConstructor - method

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

Result - class

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

result - method

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 {}
+}
+

get - method

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")
+

all - method

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(...)
+}
+

give - method

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

giveAll - method

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

wait - method

fun wait(initiate: Instance.() -> Unit)
+

Change Records

v1.0.2 added

Function Illustrate

\u83B7\u5F97 Constructor \u5B9E\u4F8B\u5904\u7406\u7C7B\uFF0C\u914D\u5408 RemedyPlan \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

waitAll - method

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\u5408 RemedyPlan \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

remedys - method

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.
+    }
+}
+

onNoSuchConstructor - method

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

ignored - method

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

ignoredError - method

Change Records

v1.0.3 added

v1.1.0 deprecated

\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()

Instance - class

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

call - method

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

newInstance - method

fun <T> newInstance(vararg param: Any?): T?
+

Change Records

v1.0.2 added

Function Illustrate

\u6267\u884C Constructor \u521B\u5EFA\u76EE\u6807\u5B9E\u4F8B \uFF0C\u6307\u5B9A T \u76EE\u6807\u5B9E\u4F8B\u7C7B\u578B\u3002

`,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(`

ConstructorFinder - class

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

paramCount - field

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

modifiers - method

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

emptyParam - method

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

param - method

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

paramCount - method

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

paramCount - method

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

paramCount - method

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

superClass - method

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\u524D Constructor\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

RemedyPlan - class

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

constructor - method

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

Result - class

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

onFind - method

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.
+}
+

Process - class

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\u4E3A hookInstance \u63D0\u4F9B\u3002

result - method

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 {}
+}
+

all - method

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\u5230 hookInstance\u3002

remedys - method

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.
+    }
+}
+

onNoSuchConstructor - method

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

Result - class

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

result - method

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 {}
+}
+

get - method

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")
+

all - method

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(...)
+}
+

give - method

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

giveAll - method

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

wait - method

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\u5408 RemedyPlan \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

waitAll - method

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\u5408 RemedyPlan \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

remedys - method

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.
+    }
+}
+

onNoSuchConstructor - method

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

ignored - method

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

ignoredError - method

\u53D8\u66F4\u8BB0\u5F55

v1.0.3 \u65B0\u589E

v1.1.0 \u4F5C\u5E9F

\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()

Instance - class

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

call - method

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

newInstance - method

fun <T> newInstance(vararg param: Any?): T?
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.2 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Constructor \u521B\u5EFA\u76EE\u6807\u5B9E\u4F8B \uFF0C\u6307\u5B9A T \u76EE\u6807\u5B9E\u4F8B\u7C7B\u578B\u3002

`,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(`

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.

ConstructorRules - class

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

paramCount - field

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

modifiers - method

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

emptyParam - method

fun emptyParam()
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Constructor \u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002

param - method

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

paramCount - method

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

paramCount - method

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

`,51),p=[t];function c(l,r){return o(),a("div",null,p)}const i=s(e,[["render",c],["__file","ConstructorRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/ConstructorRules.html.d62bae6c.js b/docs/assets/ConstructorRules.html.d62bae6c.js new file mode 100644 index 00000000..cc827028 --- /dev/null +++ b/docs/assets/ConstructorRules.html.d62bae6c.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-08b70f7f","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html","title":"ConstructorRules - 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":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.md"}');export{e as data}; diff --git a/docs/assets/ConstructorRules.html.e17434ce.js b/docs/assets/ConstructorRules.html.e17434ce.js new file mode 100644 index 00000000..a6f86bbc --- /dev/null +++ b/docs/assets/ConstructorRules.html.e17434ce.js @@ -0,0 +1,8 @@ +import{_ as s,o,c as a,a as n}from"./app.fb8271cf.js";const e={},p=n(`

ConstructorRules - class

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

paramCount - field

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

modifiers - method

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

emptyParam - method

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

param - method

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

paramCount - method

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

paramCount - method

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

`,50),c=[p];function t(l,r){return o(),a("div",null,c)}const i=s(e,[["render",t],["__file","ConstructorRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/ConstructorRules.html.f8d7dd83.js b/docs/assets/ConstructorRules.html.f8d7dd83.js new file mode 100644 index 00000000..01016238 --- /dev/null +++ b/docs/assets/ConstructorRules.html.f8d7dd83.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-a42f54a4","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html","title":"ConstructorRules - 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":[]}],"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/ConstructorRules.md"}');export{e as data}; diff --git a/docs/assets/CountRules.html.2639d392.js b/docs/assets/CountRules.html.2639d392.js new file mode 100644 index 00000000..457c0681 --- /dev/null +++ b/docs/assets/CountRules.html.2639d392.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-1b2ad030","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html","title":"CountRules - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"Int.isZero - i-ext-method","slug":"int-iszero-i-ext-method","link":"#int-iszero-i-ext-method","children":[]},{"level":2,"title":"Int.moreThan - i-ext-method","slug":"int-morethan-i-ext-method","link":"#int-morethan-i-ext-method","children":[]},{"level":2,"title":"Int.lessThan - i-ext-method","slug":"int-lessthan-i-ext-method","link":"#int-lessthan-i-ext-method","children":[]},{"level":2,"title":"Int.inInterval - i-ext-method","slug":"int-ininterval-i-ext-method","link":"#int-ininterval-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/CountRules.md"}');export{e as data}; diff --git a/docs/assets/CountRules.html.2d5ab94d.js b/docs/assets/CountRules.html.2d5ab94d.js new file mode 100644 index 00000000..3eb58d42 --- /dev/null +++ b/docs/assets/CountRules.html.2d5ab94d.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-52995ef7","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html","title":"CountRules - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"Int.isZero - i-ext-method","slug":"int-iszero-i-ext-method","link":"#int-iszero-i-ext-method","children":[]},{"level":2,"title":"Int.moreThan - i-ext-method","slug":"int-morethan-i-ext-method","link":"#int-morethan-i-ext-method","children":[]},{"level":2,"title":"Int.lessThan - i-ext-method","slug":"int-lessthan-i-ext-method","link":"#int-lessthan-i-ext-method","children":[]},{"level":2,"title":"Int.inInterval - i-ext-method","slug":"int-ininterval-i-ext-method","link":"#int-ininterval-i-ext-method","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/CountRules.md"}');export{e as data}; diff --git a/docs/assets/CountRules.html.5103015c.js b/docs/assets/CountRules.html.5103015c.js new file mode 100644 index 00000000..8fdca5ed --- /dev/null +++ b/docs/assets/CountRules.html.5103015c.js @@ -0,0 +1,6 @@ +import{_ as s,o,c as n,a as e}from"./app.fb8271cf.js";const a={},l=e(`

CountRules - class

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

Int.isZero - i-ext-method

fun Int.isZero(): Boolean
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u662F\u5426\u4E3A 0\u3002

Int.moreThan - i-ext-method

fun Int.moreThan(count: Int): Boolean
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u5927\u4E8E count\u3002

Int.lessThan - i-ext-method

fun Int.lessThan(count: Int): Boolean
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u5C0F\u4E8E count\u3002

Int.inInterval - i-ext-method

fun Int.inInterval(countRange: IntRange): Boolean
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u5728 countRange \u533A\u95F4 A \u2264 this \u2264 B\u3002

`,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(`

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.

CountRules - class

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

Int.isZero - i-ext-method

fun Int.isZero(): Boolean
+

Change Records

v1.1.0 added

Function Illustrate

\u662F\u5426\u4E3A 0\u3002

Int.moreThan - i-ext-method

fun Int.moreThan(count: Int): Boolean
+

Change Records

v1.1.0 added

Function Illustrate

\u5927\u4E8E count\u3002

Int.lessThan - i-ext-method

fun Int.lessThan(count: Int): Boolean
+

Change Records

v1.1.0 added

Function Illustrate

\u5C0F\u4E8E count\u3002

Int.inInterval - i-ext-method

fun Int.inInterval(countRange: IntRange): Boolean
+

Change Records

v1.1.0 added

Function Illustrate

\u5728 countRange \u533A\u95F4 A \u2264 this \u2264 B\u3002

`,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(`

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.

CurrentClass - class

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

name - field

val name: String
+

Change Records

v1.1.0 added

Function Illustrate

\u83B7\u5F97\u5F53\u524D classSet \u7684 Class.getName\u3002

simpleName - field

val simpleName: String
+

Change Records

v1.1.0 added

Function Illustrate

\u83B7\u5F97\u5F53\u524D classSet \u7684 Class.getSimpleName\u3002

generic - method

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

generic - method

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

superClass - method

fun superClass(): SuperClass
+

Change Records

v1.0.80 added

Function Illustrate

\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u3002

field - method

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

method - method

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

SuperClass - class

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

name - field

val name: String
+

Change Records

v1.1.0 added

Function Illustrate

\u83B7\u5F97\u5F53\u524D classSet \u4E2D\u7236\u7C7B\u7684 Class.getName\u3002

simpleName - field

val simpleName: String
+

Change Records

v1.1.0 added

Function Illustrate

\u83B7\u5F97\u5F53\u524D classSet \u4E2D\u7236\u7C7B\u7684 Class.getSimpleName\u3002

generic - method

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

generic - method

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

field - method

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

method - method

inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+

Change Records

v1.0.80 added

Function Illustrate

\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u4E2D\u7684\u65B9\u6CD5\u3002

`,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(`

CurrentClass - class

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

name - field

val name: String
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u83B7\u5F97\u5F53\u524D classSet \u7684 Class.getName\u3002

simpleName - field

val simpleName: String
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u83B7\u5F97\u5F53\u524D classSet \u7684 Class.getSimpleName\u3002

generic - method

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

generic - method

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

superClass - method

fun superClass(): SuperClass
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.80 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u3002

field - method

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

method - method

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

SuperClass - class

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

name - field

val name: String
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u83B7\u5F97\u5F53\u524D classSet \u4E2D\u7236\u7C7B\u7684 Class.getName\u3002

simpleName - field

val simpleName: String
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u83B7\u5F97\u5F53\u524D classSet \u4E2D\u7236\u7C7B\u7684 Class.getSimpleName\u3002

generic - method

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

generic - method

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

field - method

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

method - method

inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.80 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u8C03\u7528\u7236\u7C7B\u5B9E\u4F8B\u4E2D\u7684\u65B9\u6CD5\u3002

`,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(`

DefinedTypeFactory - kt

\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

VagueType - field

val VagueType: Class<*>
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u6A21\u7CCA\u7C7B\u578B\u3002

`,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(`

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.

DefinedTypeFactory - kt

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

VagueType - field

val VagueType: Class<*>
+

Change Records

v1.1.0 added

Function Illustrate

\u5F97\u5230\u6A21\u7CCA\u7C7B\u578B\u3002

`,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(`

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.

DexClassFinder - class

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

companion object - object

Change Records

v1.1.0 added

clearCache - method

fun clearCache(context: Context?, versionName: String?, versionCode: Long?)
+

Change Records

v1.1.0 added

Function Illustrate

\u6E05\u9664\u5F53\u524D DexClassFinder \u7684 Class \u7F13\u5B58\u3002

\u9002\u7528\u4E8E\u5168\u90E8\u901A\u8FC7 ClassLoader.searchClass \u6216 PackageParam.searchClass \u83B7\u53D6\u7684 DexClassFinder\u3002

fullName - field

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

simpleName - field

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

singleName - field

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

from - method

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

modifiers - method

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

fullName - method

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

simpleName - method

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

singleName - method

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

fullName - method

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

simpleName - method

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

singleName - method

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

extends - method

inline fun <reified T> extends()
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Class \u7EE7\u627F\u7684\u7236\u7C7B\u3002

extends - method

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

implements - method

inline fun <reified T> implements()
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Class \u5B9E\u73B0\u7684\u63A5\u53E3\u7C7B\u3002

implements - method

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

anonymous - method

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

noExtends - method

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

noImplements - method

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

noSuper - method

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

enclosing - method

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

enclosing - method

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

FromPackageRules - class

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

absolute - method

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

ClassNameRules - class

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

optional - method

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

member - method

inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Class \u6EE1\u8DB3\u7684 Member \u6761\u4EF6\u3002

field - method

inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Class \u6EE1\u8DB3\u7684 Field \u6761\u4EF6\u3002

method - method

inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Class \u6EE1\u8DB3\u7684 Method \u6761\u4EF6\u3002

constructor - method

inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Class \u6EE1\u8DB3\u7684 Constructor \u6761\u4EF6\u3002

Result - class

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

result - method

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

get - method

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

all - method

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

all - method

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

wait - method

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

waitAll - method

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

onNoClassDefFoundError - method

fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
+

Change Records

v1.1.0 added

Function Illustrate

\u76D1\u542C\u627E\u4E0D\u5230 Class \u65F6\u3002

ignored - method

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(`

DexClassFinder - class

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

companion object - object

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

clearCache - method

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 \u7684 Class \u7F13\u5B58\u3002

\u9002\u7528\u4E8E\u5168\u90E8\u901A\u8FC7 ClassLoader.searchClass \u6216 PackageParam.searchClass \u83B7\u53D6\u7684 DexClassFinder\u3002

fullName - field

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

simpleName - field

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

singleName - field

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

from - method

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

modifiers - method

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

fullName - method

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

simpleName - method

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

singleName - method

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

fullName - method

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

simpleName - method

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

singleName - method

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

extends - method

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

extends - method

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

implements - method

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

implements - method

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

anonymous - method

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

noExtends - method

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

noImplements - method

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

noSuper - method

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

enclosing - method

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

enclosing - method

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

FromPackageRules - class

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

absolute - method

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

ClassNameRules - class

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

optional - method

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

member - method

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\u7684 Member \u6761\u4EF6\u3002

field - method

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\u7684 Field \u6761\u4EF6\u3002

method - method

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\u7684 Method \u6761\u4EF6\u3002

constructor - method

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\u7684 Constructor \u6761\u4EF6\u3002

Result - class

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

result - method

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

get - method

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

all - method

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

all - method

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

wait - method

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

waitAll - method

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

onNoClassDefFoundError - method

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

ignored - method

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.

FieldFinder - class

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

classSet - field

Change Records

v1.0 first

v1.0.2 removed

name - field

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

type - field

var type: Any?
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E Field \u7C7B\u578B\u3002

\u53EF\u4E0D\u586B\u5199\u7C7B\u578B\u3002

modifiers - method

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

order - method

fun order(): IndexTypeCondition
+

Change Records

v1.0.70 added

Function Illustrate

\u987A\u5E8F\u7B5B\u9009\u5B57\u8282\u7801\u7684\u4E0B\u6807\u3002

name - method

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

name - method

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

type - method

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

superClass - method

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\u524D Field\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

RemedyPlan - class

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

field - method

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

Result - class

inner class Result internal constructor()
+

Change Records

v1.1.0 added

Function Illustrate

RemedyPlan \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002

onFind - method

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.
+}
+

Result - class

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

result - method

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 {}
+}
+

get - method

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")
+

all - method

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
+}
+

give - method

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

giveAll - method

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

wait - method

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\u5408 RemedyPlan \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

waitAll - method

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\u5408 RemedyPlan \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

remedys - method

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.
+    }
+}
+

onNoSuchField - method

fun onNoSuchField(result: (Throwable) -> Unit): Result
+

Change Records

v1.0 first

Function Illustrate

\u76D1\u542C\u627E\u4E0D\u5230 Field \u65F6\u3002

ignored - method

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

ignoredError - method

Change Records

v1.0.3 added

v1.1.0 deprecated

\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()

Instance - class

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

self - field

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

current - method

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\u8EAB self \u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61 CurrentClass\u3002

cast - method

fun <T> cast(): T?
+

Change Records

v1.0 first

v1.0.68 modified

\u4FEE\u6539 of \u4E3A cast

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field \u5B9E\u4F8B\u3002

byte - method

fun byte(): Byte?
+

Change Records

v1.0.68 added

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Byte \u5B9E\u4F8B\u3002

int - method

fun int(): Int
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 ofInt \u4E3A int

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Int \u5B9E\u4F8B\u3002

long - method

fun long(): Long
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 ofLong \u4E3A long

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Long \u5B9E\u4F8B\u3002

short - method

fun short(): Short
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 ofShort \u4E3A short

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Short \u5B9E\u4F8B\u3002

double - method

fun double(): Double
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 ofDouble \u4E3A double

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Double \u5B9E\u4F8B\u3002

float - method

fun float(): Float
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 ofFloat \u4E3A float

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Float \u5B9E\u4F8B\u3002

string - method

fun string(): String
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 ofString \u4E3A string

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field String \u5B9E\u4F8B\u3002

char - method

fun char(): Char
+

Change Records

v1.0.68 added

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Char \u5B9E\u4F8B\u3002

boolean - method

fun boolean(): Boolean
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 ofBoolean \u4E3A boolean

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Boolean \u5B9E\u4F8B\u3002

any - method

fun any(): Any?
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 ofAny \u4E3A any

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Any \u5B9E\u4F8B\u3002

array - method

inline fun <reified T> array(): Array<T>
+

Change Records

v1.0.68 added

Function Illustrate

\u5F97\u5230\u5F53\u524D Field Array \u5B9E\u4F8B\u3002

list - method

inline fun <reified T> list(): List<T>
+

Change Records

v1.0.68 added

Function Illustrate

\u5F97\u5230\u5F53\u524D Field List \u5B9E\u4F8B\u3002

set - method

fun set(any: Any?)
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E\u5F53\u524D Field \u5B9E\u4F8B\u3002

setTrue - method

fun setTrue()
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E\u5F53\u524D Field \u5B9E\u4F8B\u4E3A true\u3002

Pay Attention

\u8BF7\u786E\u4FDD\u5B9E\u4F8B\u5BF9\u8C61\u7C7B\u578B\u4E3A Boolean\u3002

setFalse - method

fun setFalse()
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E\u5F53\u524D Field \u5B9E\u4F8B\u4E3A false\u3002

Pay Attention

\u8BF7\u786E\u4FDD\u5B9E\u4F8B\u5BF9\u8C61\u7C7B\u578B\u4E3A Boolean\u3002

setNull - method

fun setNull()
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E\u5F53\u524D Field \u5B9E\u4F8B\u4E3A null\u3002

`,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(`

FieldFinder - class

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

classSet - field

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

v1.0.2 \u79FB\u9664

name - field

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

type - field

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

modifiers - method

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

order - method

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

name - method

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

name - method

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

type - method

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

superClass - method

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\u524D Field\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

RemedyPlan - class

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

field - method

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

Result - class

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

onFind - method

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.
+}
+

Result - class

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

result - method

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 {}
+}
+

get - method

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")
+

all - method

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
+}
+

give - method

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

giveAll - method

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

wait - method

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\u5408 RemedyPlan \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

waitAll - method

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\u5408 RemedyPlan \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

remedys - method

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.
+    }
+}
+

onNoSuchField - method

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

ignored - method

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

ignoredError - method

\u53D8\u66F4\u8BB0\u5F55

v1.0.3 \u65B0\u589E

v1.1.0 \u4F5C\u5E9F

\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()

Instance - class

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

self - field

\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

current - method

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\u8EAB self \u5B9E\u4F8B\u7684\u7C7B\u64CD\u4F5C\u5BF9\u8C61 CurrentClass\u3002

cast - method

fun <T> cast(): T?
+

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 of \u4E3A cast

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field \u5B9E\u4F8B\u3002

byte - method

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

int - method

fun int(): Int
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofInt \u4E3A int

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field Int \u5B9E\u4F8B\u3002

long - method

fun long(): Long
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofLong \u4E3A long

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field Long \u5B9E\u4F8B\u3002

short - method

fun short(): Short
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofShort \u4E3A short

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field Short \u5B9E\u4F8B\u3002

double - method

fun double(): Double
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofDouble \u4E3A double

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field Double \u5B9E\u4F8B\u3002

float - method

fun float(): Float
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofFloat \u4E3A float

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field Float \u5B9E\u4F8B\u3002

string - method

fun string(): String
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofString \u4E3A string

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field String \u5B9E\u4F8B\u3002

char - method

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

boolean - method

fun boolean(): Boolean
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofBoolean \u4E3A boolean

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field Boolean \u5B9E\u4F8B\u3002

any - method

fun any(): Any?
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofAny \u4E3A any

\u79FB\u52A8\u65B9\u6CD5\u5230 Instance

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u5F53\u524D Field Any \u5B9E\u4F8B\u3002

array - method

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

list - method

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

set - method

fun set(any: Any?)
+

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E\u5F53\u524D Field \u5B9E\u4F8B\u3002

setTrue - method

fun setTrue()
+

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E\u5F53\u524D Field \u5B9E\u4F8B\u4E3A true\u3002

\u7279\u522B\u6CE8\u610F

\u8BF7\u786E\u4FDD\u5B9E\u4F8B\u5BF9\u8C61\u7C7B\u578B\u4E3A Boolean\u3002

setFalse - method

fun setFalse()
+

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E\u5F53\u524D Field \u5B9E\u4F8B\u4E3A false\u3002

\u7279\u522B\u6CE8\u610F

\u8BF7\u786E\u4FDD\u5B9E\u4F8B\u5BF9\u8C61\u7C7B\u578B\u4E3A Boolean\u3002

setNull - method

fun setNull()
+

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E\u5F53\u524D Field \u5B9E\u4F8B\u4E3A null\u3002

`,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(`

FieldRules - class

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

name - field

var name: String
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E Field \u540D\u79F0\u3002

type - field

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

modifiers - method

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

name - method

fun name(conditions: NameConditions)
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E Field \u540D\u79F0\u6761\u4EF6\u3002

`,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(`

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.

FieldRules - class

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

name - field

var name: String
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Field \u540D\u79F0\u3002

type - field

var type: Any?
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Field \u7C7B\u578B\u3002

\u53EF\u4E0D\u586B\u5199\u7C7B\u578B\u3002

modifiers - method

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

name - method

fun name(conditions: NameConditions)
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Field \u540D\u79F0\u6761\u4EF6\u3002

`,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(`

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.

GenericClass - class

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

argument - method

fun argument(index: Int): Class<*>
+

Change Records

v1.1.0 added

Function Illustrate

\u83B7\u5F97\u6CDB\u578B\u53C2\u6570\u6570\u7EC4\u4E0B\u6807\u7684 Class \u5B9E\u4F8B\u3002

`,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(`

GenericClass - class

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

argument - method

fun argument(index: Int): Class<*>
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u83B7\u5F97\u6CDB\u578B\u53C2\u6570\u6570\u7EC4\u4E0B\u6807\u7684 Class \u5B9E\u4F8B\u3002

`,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('

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.

GraphicsTypeFactory - kt

Change Records

v1.0 first

Function Illustrate

\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A Android \u76F8\u5173 Graphics \u7684 Class \u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002

',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('

GraphicsTypeFactory - kt

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

\u529F\u80FD\u63CF\u8FF0

\u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A Android \u76F8\u5173 Graphics \u7684 Class \u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002

',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(`

HookClass - class

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

`,9),p=[e];function c(t,r){return o(),a("div",null,p)}const y=s(l,[["render",c],["__file","HookClass.html.vue"]]);export{y as default}; diff --git a/docs/assets/HookClass.html.f01a0415.js b/docs/assets/HookClass.html.f01a0415.js new file mode 100644 index 00000000..a280aa28 --- /dev/null +++ b/docs/assets/HookClass.html.f01a0415.js @@ -0,0 +1,2 @@ +import{_ as s,o,c as a,a as n}from"./app.fb8271cf.js";const e={},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.

HookClass - class

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

`,10),t=[l];function c(p,r){return o(),a("div",null,t)}const d=s(e,[["render",c],["__file","HookClass.html.vue"]]);export{d as default}; diff --git a/docs/assets/HookParam.html.30f4fb72.js b/docs/assets/HookParam.html.30f4fb72.js new file mode 100644 index 00000000..337b3045 --- /dev/null +++ b/docs/assets/HookParam.html.30f4fb72.js @@ -0,0 +1,86 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},l=e(`

HookParam - class

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

args - field

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 \u6216 constructor \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

firstArgs - field

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

v1.0.75 \u79FB\u9664

\u8BF7\u4F7F\u7528 args(index = 0) \u6216 args().first()

lastArgs - field

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

v1.0.75 \u79FB\u9664

\u8BF7\u4F7F\u7528 args().last()

instance - field

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

instanceClass - field

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

member - field

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

method - field

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

constructor - field

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

result - field

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 \u6216 constructor \u7684\u8FD4\u56DE\u503C\u3002

hasThrowable - field

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

throwable - field

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

Throwable.throwToApp - i-ext-method

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

result - method

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 \u6216 constructor \u7684\u8FD4\u56DE\u503C T\u3002

firstArg - method

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.75 \u79FB\u9664

lastArgs - method

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.75 \u79FB\u9664

instance - method

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()
+

args - method

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 \u6216 constructor \u7684\u53C2\u6570\u6570\u7EC4\u4E0B\u6807\u5B9E\u4F8B\u5316\u7C7B\u3002

args - method

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 \u6216 constructor \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()
+

callOriginal - method

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>()
+    }
+}
+

invokeOriginal - method

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")
+    }
+}
+

resultTrue - method

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\u4E3A true\u3002

\u7279\u522B\u6CE8\u610F

\u8BF7\u786E\u4FDD result \u7C7B\u578B\u4E3A Boolean\u3002

resultFalse - method

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\u4E3A false\u3002

\u7279\u522B\u6CE8\u610F

\u8BF7\u786E\u4FDD result \u7C7B\u578B\u4E3A Boolean\u3002

resultNull - method

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

ArgsIndexCondition - class

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

first - method

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 \u6216 constructor \u7684\u53C2\u6570\u6570\u7EC4\u7B2C\u4E00\u4F4D\u3002

last - method

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 \u6216 constructor \u7684\u53C2\u6570\u6570\u7EC4\u6700\u540E\u4E00\u4F4D\u3002

ArgsModifyer - class

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

cast - method

fun <T> cast(): T?
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 of \u4E3A cast

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 T\u3002

byte - method

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

int - method

fun int(): Int
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofInt \u4E3A int

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Int\u3002

long - method

fun long(): Long
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofLong \u4E3A long

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Long\u3002

short - method

fun short(): Short
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofShort \u4E3A short

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Short\u3002

double - method

fun double(): Double
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofDouble \u4E3A double

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Double\u3002

float - method

fun float(): Float
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofFloat \u4E3A float

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Float\u3002

string - method

fun string(): String
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofString \u4E3A string

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 String\u3002

char - method

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

boolean - method

fun boolean(): Boolean
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.66 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 ofBoolean \u4E3A boolean

\u529F\u80FD\u63CF\u8FF0

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Boolean\u3002

any - method

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

array - method

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

list - method

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

set - method

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

setNull - method

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

setTrue - method

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

setFalse - method

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

`,347),p=[l];function c(t,r){return o(),a("div",null,p)}const i=s(n,[["render",c],["__file","HookParam.html.vue"]]);export{i as default}; diff --git a/docs/assets/HookParam.html.918accc4.js b/docs/assets/HookParam.html.918accc4.js new file mode 100644 index 00000000..54877e65 --- /dev/null +++ b/docs/assets/HookParam.html.918accc4.js @@ -0,0 +1,86 @@ +import{_ as s,o,c as e,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.

HookParam - class

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

args - field

val args: Array<Any?>
+

Change Records

\u5728 v1.0 \u6DFB\u52A0

Function Illustrate

\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61 member \u6216 constructor \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

firstArgs - field

Change Records

v1.0 first

v1.0.75 removed

\u8BF7\u4F7F\u7528 args(index = 0) \u6216 args().first()

lastArgs - field

Change Records

v1.0 first

v1.0.75 removed

\u8BF7\u4F7F\u7528 args().last()

instance - field

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

instanceClass - field

val instanceClass: Class<*>
+

Change Records

v1.0 first

Function Illustrate

\u83B7\u53D6\u5F53\u524D Hook \u5B9E\u4F8B\u7684\u7C7B\u5BF9\u8C61\u3002

member - field

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

method - field

val method: Method
+

Change Records

v1.0 first

Function Illustrate

\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684\u65B9\u6CD5\u3002

constructor - field

val constructor: Constructor
+

Change Records

v1.0 first

Function Illustrate

\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684\u6784\u9020\u65B9\u6CD5\u3002

result - field

var result: Any?
+

Change Records

v1.0 first

Function Illustrate

\u83B7\u53D6\u3001\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u7684 method \u6216 constructor \u7684\u8FD4\u56DE\u503C\u3002

hasThrowable - field

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

throwable - field

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

Throwable.throwToApp - i-ext-method

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

result - method

inline fun <reified T> result(): T?
+

Change Records

v1.0.75 added

Function Illustrate

\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684 method \u6216 constructor \u7684\u8FD4\u56DE\u503C T\u3002

firstArg - method

Change Records

v1.0.66 added

v1.0.75 removed

lastArgs - method

Change Records

v1.0.66 added

v1.0.75 removed

instance - method

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()
+

args - method

fun args(): ArgsIndexCondition
+

Change Records

v1.0.75 added

Function Illustrate

\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684 method \u6216 constructor \u7684\u53C2\u6570\u6570\u7EC4\u4E0B\u6807\u5B9E\u4F8B\u5316\u7C7B\u3002

args - method

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 \u6216 constructor \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()
+

callOriginal - method

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>()
+    }
+}
+

invokeOriginal - method

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")
+    }
+}
+

resultTrue - method

fun resultTrue()
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u65B9\u6CD5\u7684 result \u8FD4\u56DE\u503C\u4E3A true\u3002

Pay Attention

\u8BF7\u786E\u4FDD result \u7C7B\u578B\u4E3A Boolean\u3002

resultFalse - method

fun resultFalse()
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E\u5F53\u524D Hook \u5BF9\u8C61\u65B9\u6CD5\u7684 result \u8FD4\u56DE\u503C\u4E3A false\u3002

Pay Attention

\u8BF7\u786E\u4FDD result \u7C7B\u578B\u4E3A Boolean\u3002

resultNull - method

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

ArgsIndexCondition - class

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

first - method

fun first(): ArgsModifyer
+

Change Records

v1.0.75 added

Function Illustrate

\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684 method \u6216 constructor \u7684\u53C2\u6570\u6570\u7EC4\u7B2C\u4E00\u4F4D\u3002

last - method

fun last(): ArgsModifyer
+

Change Records

v1.0.75 added

Function Illustrate

\u83B7\u53D6\u5F53\u524D Hook \u5BF9\u8C61\u7684 method \u6216 constructor \u7684\u53C2\u6570\u6570\u7EC4\u6700\u540E\u4E00\u4F4D\u3002

ArgsModifyer - class

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

cast - method

fun <T> cast(): T?
+

Change Records

v1.0.66 added

v1.0.68 modified

\u4FEE\u6539 of \u4E3A cast

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 T\u3002

byte - method

fun byte(): Byte?
+

Change Records

v1.0.68 added

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Byte\u3002

int - method

fun int(): Int
+

Change Records

v1.0.66 added

v1.0.68 modified

\u4FEE\u6539 ofInt \u4E3A int

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Int\u3002

long - method

fun long(): Long
+

Change Records

v1.0.66 added

v1.0.68 modified

\u4FEE\u6539 ofLong \u4E3A long

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Long\u3002

short - method

fun short(): Short
+

Change Records

v1.0.66 added

v1.0.68 modified

\u4FEE\u6539 ofShort \u4E3A short

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Short\u3002

double - method

fun double(): Double
+

Change Records

v1.0.66 added

v1.0.68 modified

\u4FEE\u6539 ofDouble \u4E3A double

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Double\u3002

float - method

fun float(): Float
+

Change Records

v1.0.66 added

v1.0.68 modified

\u4FEE\u6539 ofFloat \u4E3A float

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Float\u3002

string - method

fun string(): String
+

Change Records

v1.0.66 added

v1.0.68 modified

\u4FEE\u6539 ofString \u4E3A string

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 String\u3002

char - method

fun char(): Char
+

Change Records

v1.0.68 added

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Char\u3002

boolean - method

fun boolean(): Boolean
+

Change Records

v1.0.66 added

v1.0.68 modified

\u4FEE\u6539 ofBoolean \u4E3A boolean

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Boolean\u3002

any - method

fun any(): Any?
+

Change Records

v1.0.77 added

Function Illustrate

\u5F97\u5230\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61 Any\u3002

array - method

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

list - method

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

set - method

fun <T> set(any: T?)
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u3002

setNull - method

fun setNull()
+

Change Records

v1.0 first

Function Illustrate

\u8BBE\u7F6E\u65B9\u6CD5\u53C2\u6570\u7684\u5B9E\u4F8B\u5BF9\u8C61\u4E3A null\u3002

setTrue - method

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

setFalse - method

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

`,348),p=[l];function c(t,r){return o(),e("div",null,p)}const i=s(n,[["render",c],["__file","HookParam.html.vue"]]);export{i as default}; diff --git a/docs/assets/HookParam.html.b19d4ad2.js b/docs/assets/HookParam.html.b19d4ad2.js new file mode 100644 index 00000000..650ee064 --- /dev/null +++ b/docs/assets/HookParam.html.b19d4ad2.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-60cbe1b4","path":"/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html","title":"HookParam - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"args - field","slug":"args-field","link":"#args-field","children":[]},{"level":2,"title":"instance - field","slug":"instance-field","link":"#instance-field","children":[]},{"level":2,"title":"instanceClass - field","slug":"instanceclass-field","link":"#instanceclass-field","children":[]},{"level":2,"title":"member - field","slug":"member-field","link":"#member-field","children":[]},{"level":2,"title":"method - field","slug":"method-field","link":"#method-field","children":[]},{"level":2,"title":"constructor - field","slug":"constructor-field","link":"#constructor-field","children":[]},{"level":2,"title":"result - field","slug":"result-field","link":"#result-field","children":[]},{"level":2,"title":"hasThrowable - field","slug":"hasthrowable-field","link":"#hasthrowable-field","children":[]},{"level":2,"title":"throwable - field","slug":"throwable-field","link":"#throwable-field","children":[]},{"level":2,"title":"Throwable.throwToApp - i-ext-method","slug":"throwable-throwtoapp-i-ext-method","link":"#throwable-throwtoapp-i-ext-method","children":[]},{"level":2,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":2,"title":"instance - method","slug":"instance-method","link":"#instance-method","children":[]},{"level":2,"title":"args - method","slug":"args-method","link":"#args-method","children":[]},{"level":2,"title":"args - method","slug":"args-method-1","link":"#args-method-1","children":[]},{"level":2,"title":"callOriginal - method","slug":"calloriginal-method","link":"#calloriginal-method","children":[]},{"level":2,"title":"invokeOriginal - method","slug":"invokeoriginal-method","link":"#invokeoriginal-method","children":[]},{"level":2,"title":"resultTrue - method","slug":"resulttrue-method","link":"#resulttrue-method","children":[]},{"level":2,"title":"resultFalse - method","slug":"resultfalse-method","link":"#resultfalse-method","children":[]},{"level":2,"title":"resultNull - method","slug":"resultnull-method","link":"#resultnull-method","children":[]},{"level":2,"title":"ArgsIndexCondition - class","slug":"argsindexcondition-class","link":"#argsindexcondition-class","children":[{"level":3,"title":"first - method","slug":"first-method","link":"#first-method","children":[]},{"level":3,"title":"last - method","slug":"last-method","link":"#last-method","children":[]}]},{"level":2,"title":"ArgsModifyer - class","slug":"argsmodifyer-class","link":"#argsmodifyer-class","children":[{"level":3,"title":"cast - method","slug":"cast-method","link":"#cast-method","children":[]},{"level":3,"title":"byte - method","slug":"byte-method","link":"#byte-method","children":[]},{"level":3,"title":"int - method","slug":"int-method","link":"#int-method","children":[]},{"level":3,"title":"long - method","slug":"long-method","link":"#long-method","children":[]},{"level":3,"title":"short - method","slug":"short-method","link":"#short-method","children":[]},{"level":3,"title":"double - method","slug":"double-method","link":"#double-method","children":[]},{"level":3,"title":"float - method","slug":"float-method","link":"#float-method","children":[]},{"level":3,"title":"string - method","slug":"string-method","link":"#string-method","children":[]},{"level":3,"title":"char - method","slug":"char-method","link":"#char-method","children":[]},{"level":3,"title":"boolean - method","slug":"boolean-method","link":"#boolean-method","children":[]},{"level":3,"title":"any - method","slug":"any-method","link":"#any-method","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":[]},{"level":3,"title":"set - method","slug":"set-method","link":"#set-method","children":[]},{"level":3,"title":"setNull - method","slug":"setnull-method","link":"#setnull-method","children":[]},{"level":3,"title":"setTrue - method","slug":"settrue-method","link":"#settrue-method","children":[]},{"level":3,"title":"setFalse - method","slug":"setfalse-method","link":"#setfalse-method","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md"}');export{e as data}; diff --git a/docs/assets/HookParam.html.f98d02d2.js b/docs/assets/HookParam.html.f98d02d2.js new file mode 100644 index 00000000..869fdbf7 --- /dev/null +++ b/docs/assets/HookParam.html.f98d02d2.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-75a9b636","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html","title":"HookParam - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"args - field","slug":"args-field","link":"#args-field","children":[]},{"level":2,"title":"instance - field","slug":"instance-field","link":"#instance-field","children":[]},{"level":2,"title":"instanceClass - field","slug":"instanceclass-field","link":"#instanceclass-field","children":[]},{"level":2,"title":"member - field","slug":"member-field","link":"#member-field","children":[]},{"level":2,"title":"method - field","slug":"method-field","link":"#method-field","children":[]},{"level":2,"title":"constructor - field","slug":"constructor-field","link":"#constructor-field","children":[]},{"level":2,"title":"result - field","slug":"result-field","link":"#result-field","children":[]},{"level":2,"title":"hasThrowable - field","slug":"hasthrowable-field","link":"#hasthrowable-field","children":[]},{"level":2,"title":"throwable - field","slug":"throwable-field","link":"#throwable-field","children":[]},{"level":2,"title":"Throwable.throwToApp - i-ext-method","slug":"throwable-throwtoapp-i-ext-method","link":"#throwable-throwtoapp-i-ext-method","children":[]},{"level":2,"title":"result - method","slug":"result-method","link":"#result-method","children":[]},{"level":2,"title":"instance - method","slug":"instance-method","link":"#instance-method","children":[]},{"level":2,"title":"args - method","slug":"args-method","link":"#args-method","children":[]},{"level":2,"title":"args - method","slug":"args-method-1","link":"#args-method-1","children":[]},{"level":2,"title":"callOriginal - method","slug":"calloriginal-method","link":"#calloriginal-method","children":[]},{"level":2,"title":"invokeOriginal - method","slug":"invokeoriginal-method","link":"#invokeoriginal-method","children":[]},{"level":2,"title":"resultTrue - method","slug":"resulttrue-method","link":"#resulttrue-method","children":[]},{"level":2,"title":"resultFalse - method","slug":"resultfalse-method","link":"#resultfalse-method","children":[]},{"level":2,"title":"resultNull - method","slug":"resultnull-method","link":"#resultnull-method","children":[]},{"level":2,"title":"ArgsIndexCondition - class","slug":"argsindexcondition-class","link":"#argsindexcondition-class","children":[{"level":3,"title":"first - method","slug":"first-method","link":"#first-method","children":[]},{"level":3,"title":"last - method","slug":"last-method","link":"#last-method","children":[]}]},{"level":2,"title":"ArgsModifyer - class","slug":"argsmodifyer-class","link":"#argsmodifyer-class","children":[{"level":3,"title":"cast - method","slug":"cast-method","link":"#cast-method","children":[]},{"level":3,"title":"byte - method","slug":"byte-method","link":"#byte-method","children":[]},{"level":3,"title":"int - method","slug":"int-method","link":"#int-method","children":[]},{"level":3,"title":"long - method","slug":"long-method","link":"#long-method","children":[]},{"level":3,"title":"short - method","slug":"short-method","link":"#short-method","children":[]},{"level":3,"title":"double - method","slug":"double-method","link":"#double-method","children":[]},{"level":3,"title":"float - method","slug":"float-method","link":"#float-method","children":[]},{"level":3,"title":"string - method","slug":"string-method","link":"#string-method","children":[]},{"level":3,"title":"char - method","slug":"char-method","link":"#char-method","children":[]},{"level":3,"title":"boolean - method","slug":"boolean-method","link":"#boolean-method","children":[]},{"level":3,"title":"any - method","slug":"any-method","link":"#any-method","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":[]},{"level":3,"title":"set - method","slug":"set-method","link":"#set-method","children":[]},{"level":3,"title":"setNull - method","slug":"setnull-method","link":"#setnull-method","children":[]},{"level":3,"title":"setTrue - method","slug":"settrue-method","link":"#settrue-method","children":[]},{"level":3,"title":"setFalse - method","slug":"setfalse-method","link":"#setfalse-method","children":[]}]}],"git":{"updatedTime":1663398125000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md"}');export{e as data}; diff --git a/docs/assets/HookResources.html.2486cf29.js b/docs/assets/HookResources.html.2486cf29.js new file mode 100644 index 00000000..27b14c42 --- /dev/null +++ b/docs/assets/HookResources.html.2486cf29.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-9af56c1a","path":"/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html","title":"HookResources - class","lang":"en-US","frontmatter":{"next":{"text":"\u7279\u8272\u529F\u80FD","link":"/zh-cn/api/special-features/reflection"},"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/HookResources.md"}');export{e as data}; diff --git a/docs/assets/HookResources.html.4f07fd98.js b/docs/assets/HookResources.html.4f07fd98.js new file mode 100644 index 00000000..b2234439 --- /dev/null +++ b/docs/assets/HookResources.html.4f07fd98.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-1c516d22","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html","title":"HookResources - class","lang":"zh-CN","frontmatter":{"next":{"text":"\u7279\u8272\u529F\u80FD","link":"/zh-cn/api/special-features/reflection"},"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/HookResources.md"}');export{e as data}; diff --git a/docs/assets/HookResources.html.70a752b2.js b/docs/assets/HookResources.html.70a752b2.js new file mode 100644 index 00000000..25a714bb --- /dev/null +++ b/docs/assets/HookResources.html.70a752b2.js @@ -0,0 +1,2 @@ +import{_ as s,o,c as e,a}from"./app.fb8271cf.js";const c={},n=a(`

HookResources - class

class HookResources internal constructor(var instance: YukiResources?)
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.80 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u521B\u5EFA\u4E00\u4E2A\u5F53\u524D Hook \u7684 YukiResources \u63A5\u7BA1\u7C7B\u3002

`,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(`

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.

HookResources - class

class HookResources internal constructor(var instance: YukiResources?)
+

Change Records

v1.0.80 added

Function Illustrate

\u521B\u5EFA\u4E00\u4E2A\u5F53\u524D Hook \u7684 YukiResources \u63A5\u7BA1\u7C7B\u3002

`,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(`

IYukiHookXposedInit - interface

interface IYukiHookXposedInit
+

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

v1.0.80 \u4FEE\u6539 \u4F5C\u5E9F

\u4F5C\u5E9F\u4E86 YukiHookXposedInitProxy \u540D\u79F0\u4F46\u4FDD\u7559\u63A5\u53E3

\u8F6C\u79FB\u5230 IYukiHookXposedInit \u65B0\u540D\u79F0

\u529F\u80FD\u63CF\u8FF0

YukiHookAPI \u7684 Xposed \u88C5\u8F7D API \u8C03\u7528\u63A5\u53E3\u3002

onInit - method

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

onHook - method

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

onXposedEvent - method

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

YukiHookXposedInitProxy - interface

\u53D8\u66F4\u8BB0\u5F55

v1.0 \u6DFB\u52A0

v1.0.80 \u4F5C\u5E9F

\u8BF7\u8F6C\u79FB\u5230 IYukiHookXposedInit

`,41),c=[a];function t(d,i){return e(),s("div",null,c)}const r=o(p,[["render",t],["__file","IYukiHookXposedInit.html.vue"]]);export{r as default}; diff --git a/docs/assets/IYukiHookXposedInit.html.78a55860.js b/docs/assets/IYukiHookXposedInit.html.78a55860.js new file mode 100644 index 00000000..70ff71fc --- /dev/null +++ b/docs/assets/IYukiHookXposedInit.html.78a55860.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-763140ee","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html","title":"IYukiHookXposedInit - interface","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"onInit - method","slug":"oninit-method","link":"#oninit-method","children":[]},{"level":2,"title":"onHook - method","slug":"onhook-method","link":"#onhook-method","children":[]},{"level":2,"title":"onXposedEvent - method","slug":"onxposedevent-method","link":"#onxposedevent-method","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.md"}');export{e as data}; diff --git a/docs/assets/IYukiHookXposedInit.html.7f3e0a05.js b/docs/assets/IYukiHookXposedInit.html.7f3e0a05.js new file mode 100644 index 00000000..88efe33c --- /dev/null +++ b/docs/assets/IYukiHookXposedInit.html.7f3e0a05.js @@ -0,0 +1,5 @@ +import{_ as o,o as e,c as s,a as n}from"./app.fb8271cf.js";const a={},t=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.

IYukiHookXposedInit - interface

interface IYukiHookXposedInit
+

Change Records

v1.0 first

v1.0.80 modified deprecated

\u4F5C\u5E9F\u4E86 YukiHookXposedInitProxy \u540D\u79F0\u4F46\u4FDD\u7559\u63A5\u53E3

\u8F6C\u79FB\u5230 IYukiHookXposedInit \u65B0\u540D\u79F0

Function Illustrate

YukiHookAPI \u7684 Xposed \u88C5\u8F7D API \u8C03\u7528\u63A5\u53E3\u3002

onInit - method

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

onHook - method

fun onHook()
+

Change Records

v1.0 first

Function Illustrate

Xposed API \u7684\u6A21\u5757\u88C5\u8F7D\u8C03\u7528\u5165\u53E3\u65B9\u6CD5\u3002

onXposedEvent - method

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

YukiHookXposedInitProxy - interface

Change Records

v1.0 first

v1.0.80 deprecated

\u8BF7\u8F6C\u79FB\u5230 IYukiHookXposedInit

`,42),c=[t];function p(d,i){return e(),s("div",null,c)}const l=o(a,[["render",p],["__file","IYukiHookXposedInit.html.vue"]]);export{l as default}; diff --git a/docs/assets/IYukiHookXposedInit.html.b37a852b.js b/docs/assets/IYukiHookXposedInit.html.b37a852b.js new file mode 100644 index 00000000..fa1bce64 --- /dev/null +++ b/docs/assets/IYukiHookXposedInit.html.b37a852b.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-1d680acc","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html","title":"IYukiHookXposedInit - interface","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"onInit - method","slug":"oninit-method","link":"#oninit-method","children":[]},{"level":2,"title":"onHook - method","slug":"onhook-method","link":"#onhook-method","children":[]},{"level":2,"title":"onXposedEvent - method","slug":"onxposedevent-method","link":"#onxposedevent-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.md"}');export{e as data}; diff --git a/docs/assets/InjectYukiHookWithXposed.html.56391530.js b/docs/assets/InjectYukiHookWithXposed.html.56391530.js new file mode 100644 index 00000000..7fdad838 --- /dev/null +++ b/docs/assets/InjectYukiHookWithXposed.html.56391530.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-818b3ca6","path":"/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html","title":"InjectYukiHookWithXposed - annotation","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/annotation/xposed/InjectYukiHookWithXposed.md"}');export{e as data}; diff --git a/docs/assets/InjectYukiHookWithXposed.html.b6100747.js b/docs/assets/InjectYukiHookWithXposed.html.b6100747.js new file mode 100644 index 00000000..cda4e703 --- /dev/null +++ b/docs/assets/InjectYukiHookWithXposed.html.b6100747.js @@ -0,0 +1,7 @@ +import{_ as s,o,c as n,a}from"./app.fb8271cf.js";const e={},t=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.

InjectYukiHookWithXposed - annotation

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(`

InjectYukiHookWithXposed - annotation

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.

LoggerFactory - kt

Change Records

v1.0 first

Function Illustrate

\u8FD9\u662F YukiHookAPI \u7684\u65E5\u5FD7\u5C01\u88C5\u7C7B\uFF0C\u53EF\u5B9E\u73B0\u540C\u65F6\u5411 Logcat \u548C XposedBridge.log \u6253\u5370\u65E5\u5FD7\u7684\u529F\u80FD\u3002

LoggerType - class

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 - enum

LOGD
+

Change Records

v1.1.0 added

Function Illustrate

\u4EC5\u4F7F\u7528 android.util.Log\u3002

XPOSEDBRIDGE - enum

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 - enum

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 - enum

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

YukiHookLogger - object

object YukiHookLogger
+

Change Records

v1.1.0 added

Function Illustrate

\u8C03\u8BD5\u65E5\u5FD7\u5B9E\u73B0\u7C7B\u3002

contents - field

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

clear - method

fun clear()
+

Change Records

v1.1.0 added

Function Illustrate

\u6E05\u9664\u5168\u90E8\u5DF2\u8BB0\u5F55\u7684\u65E5\u5FD7\u3002

saveToFile - method

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

Configs - object

object Configs
+

Change Records

v1.1.0 added

Function Illustrate

\u914D\u7F6E YukiHookLogger\u3002

TAG - field

const val TAG: Int
+

Change Records

v1.1.0 added

Function Illustrate

\u6807\u7B7E\u3002

PRIORITY - field

const val PRIORITY: Int
+

Change Records

v1.1.0 added

Function Illustrate

\u4F18\u5148\u7EA7\u3002

PACKAGE_NAME - field

const val PACKAGE_NAME: Int
+

Change Records

v1.1.0 added

Function Illustrate

\u5F53\u524D\u5BBF\u4E3B\u7684\u5305\u540D\u3002

USER_ID - field

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

isEnable - field

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

isRecord - field

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

tag - field

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

elements - method

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
+

loggerD - method

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 \u548C XposedBridge \u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522B D\u3002

tag \u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002

loggerI - method

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 \u548C XposedBridge \u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522B I\u3002

tag \u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002

loggerW - method

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 \u548C XposedBridge \u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522B W\u3002

tag \u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002

loggerE - method

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 \u548C XposedBridge \u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522B E\uFF0C\u53EF\u643A\u5E26 e \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

`,187),p=[l];function c(t,r){return e(),o("div",null,p)}const i=s(n,[["render",c],["__file","LoggerFactory.html.vue"]]);export{i as default}; diff --git a/docs/assets/LoggerFactory.html.914e1c34.js b/docs/assets/LoggerFactory.html.914e1c34.js new file mode 100644 index 00000000..f1679dad --- /dev/null +++ b/docs/assets/LoggerFactory.html.914e1c34.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-36aec5ad","path":"/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html","title":"LoggerFactory - kt","lang":"en-US","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":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.md"}');export{e as data}; diff --git a/docs/assets/LoggerFactory.html.bb211a96.js b/docs/assets/LoggerFactory.html.bb211a96.js new file mode 100644 index 00000000..c8cc1467 --- /dev/null +++ b/docs/assets/LoggerFactory.html.bb211a96.js @@ -0,0 +1,27 @@ +import{_ as s,o,c as e,a}from"./app.fb8271cf.js";const n={},p=a(`

LoggerFactory - kt

\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\u5411 Logcat \u548C XposedBridge.log \u6253\u5370\u65E5\u5FD7\u7684\u529F\u80FD\u3002

LoggerType - class

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 - enum

LOGD
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u4EC5\u4F7F\u7528 android.util.Log\u3002

XPOSEDBRIDGE - enum

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 - enum

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 - enum

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

YukiHookLogger - object

object YukiHookLogger
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u8C03\u8BD5\u65E5\u5FD7\u5B9E\u73B0\u7C7B\u3002

contents - field

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

clear - method

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

saveToFile - method

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

Configs - object

object Configs
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u914D\u7F6E YukiHookLogger\u3002

TAG - field

const val TAG: Int
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u6807\u7B7E\u3002

PRIORITY - field

const val PRIORITY: Int
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u4F18\u5148\u7EA7\u3002

PACKAGE_NAME - field

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

USER_ID - field

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

isEnable - field

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

isRecord - field

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

tag - field

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

elements - method

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
+

loggerD - method

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 \u548C XposedBridge \u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522B D\u3002

tag \u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002

loggerI - method

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 \u548C XposedBridge \u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522B I\u3002

tag \u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002

loggerW - method

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 \u548C XposedBridge \u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522B W\u3002

tag \u7684\u9ED8\u8BA4\u53C2\u6570\u4E3A YukiHookAPI.Configs.debugTag\uFF0C\u4F60\u53EF\u4EE5\u8FDB\u884C\u81EA\u5B9A\u4E49\u3002

loggerE - method

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 \u548C XposedBridge \u6253\u5370\u65E5\u5FD7\uFF0C\u7EA7\u522B E\uFF0C\u53EF\u643A\u5E26 e \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

`,186),l=[p];function c(t,r){return o(),e("div",null,l)}const i=s(n,[["render",c],["__file","LoggerFactory.html.vue"]]);export{i as default}; diff --git a/docs/assets/MemberRules.html.1a50f297.js b/docs/assets/MemberRules.html.1a50f297.js new file mode 100644 index 00000000..7d18d244 --- /dev/null +++ b/docs/assets/MemberRules.html.1a50f297.js @@ -0,0 +1,3 @@ +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.

MemberRules - class

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

modifiers - method

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(`

MemberRules - class

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

modifiers - method

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.

MemberRulesResult - class

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

none - method

fun none(): MemberRulesResult
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E\u5F53\u524D Member \u5728\u67E5\u627E\u6761\u4EF6\u4E2D\u4E2A\u6570\u4E3A 0\u3002

count - method

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

count - method

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

count - method

fun count(conditions: CountConditions): 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\u6761\u4EF6\u3002

`,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(`

MemberRulesResult - class

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

none - method

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\u4E3A 0\u3002

count - method

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

count - method

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

count - method

fun count(conditions: CountConditions): 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\u6761\u4EF6\u3002

`,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(`

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.

MethodFinder - class

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

name - field

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

paramCount - field

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

returnType - field

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

modifiers - method

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

emptyParam - method

fun emptyParam(): IndexTypeCondition
+

Change Records

v1.0.75 added

Function Illustrate

\u8BBE\u7F6E Method \u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002

param - method

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

order - method

fun order(): IndexTypeCondition
+

Change Records

v1.0.70 added

Function Illustrate

\u987A\u5E8F\u7B5B\u9009\u5B57\u8282\u7801\u7684\u4E0B\u6807\u3002

name - method

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

name - method

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

paramCount - method

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

paramCount - method

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

paramCount - method

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

returnType - method

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

superClass - method

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\u524D Method\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

RemedyPlan - class

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

method - method

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

Result - class

inner class Result internal constructor()
+

Change Records

v1.0.1 added

Function Illustrate

RemedyPlan \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002

onFind - method

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.
+}
+

Process - class

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\u4E3A hookInstance \u63D0\u4F9B\u3002

result - method

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 {}
+}
+

all - method

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\u5230 hookInstance\u3002

remedys - method

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.
+    }
+}
+

onNoSuchMethod - method

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

Result - class

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

result - method

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 {}
+}
+

get - method

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()
+

all - method

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(...)
+}
+

give - method

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

giveAll - method

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

wait - method

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\u5408 RemedyPlan \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

waitAll - method

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\u5408 RemedyPlan \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

remedys - method

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.
+    }
+}
+

onNoSuchMethod - method

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

ignored - method

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

ignoredError - method

Change Records

v1.0.3 added

v1.1.0 deprecated

\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()

Instance - class

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

original - method

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

call - method

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

invoke - method

fun <T> invoke(vararg param: Any?): T?
+

Change Records

v1.0.2 added

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A T \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

byte - method

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

int - method

fun int(vararg param: Any?): Int
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 callInt \u4E3A int

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A Int \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

long - method

fun long(vararg param: Any?): Long
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 callLong \u4E3A long

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A Long \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

short - method

fun short(vararg param: Any?): Short
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 callShort \u4E3A short

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A Short \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

double - method

fun double(vararg param: Any?): Double
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 callDouble \u4E3A double

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A Double \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

float - method

fun float(vararg param: Any?): Float
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 callFloat \u4E3A float

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A Float \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

string - method

fun string(vararg param: Any?): String
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 callString \u4E3A string

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A String \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

char - method

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

boolean - method

fun boolean(vararg param: Any?): Boolean
+

Change Records

v1.0.65 added

v1.0.68 modified

\u4FEE\u6539 callBoolean \u4E3A boolean

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A Boolean \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

array - method

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

list - method

inline fun <reified T> list(vararg param: Any?): List<T>
+

Change Records

v1.0.68 added

Function Illustrate

\u6267\u884C Method\uFF0C\u6307\u5B9A List \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

`,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(`

MethodFinder - class

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

name - field

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

paramCount - field

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

returnType - field

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

modifiers - method

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

emptyParam - method

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

param - method

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

order - method

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

name - method

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

name - method

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

paramCount - method

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

paramCount - method

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

paramCount - method

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

returnType - method

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

superClass - method

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\u524D Method\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

RemedyPlan - class

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

method - method

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

Result - class

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

onFind - method

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.
+}
+

Process - class

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\u4E3A hookInstance \u63D0\u4F9B\u3002

result - method

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 {}
+}
+

all - method

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\u5230 hookInstance\u3002

remedys - method

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.
+    }
+}
+

onNoSuchMethod - method

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

Result - class

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

result - method

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 {}
+}
+

get - method

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()
+

all - method

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(...)
+}
+

give - method

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

giveAll - method

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

wait - method

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\u5408 RemedyPlan \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

waitAll - method

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\u5408 RemedyPlan \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

remedys - method

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.
+    }
+}
+

onNoSuchMethod - method

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

ignored - method

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

ignoredError - method

\u53D8\u66F4\u8BB0\u5F55

v1.0.3 \u65B0\u589E

v1.1.0 \u4F5C\u5E9F

\u8BF7\u8F6C\u79FB\u5230\u65B0\u65B9\u6CD5 ignored()

Instance - class

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

original - method

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

call - method

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

invoke - method

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\u5B9A T \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

byte - method

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

int - method

fun int(vararg param: Any?): Int
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 callInt \u4E3A int

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Method\uFF0C\u6307\u5B9A Int \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

long - method

fun long(vararg param: Any?): Long
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 callLong \u4E3A long

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Method\uFF0C\u6307\u5B9A Long \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

short - method

fun short(vararg param: Any?): Short
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 callShort \u4E3A short

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Method\uFF0C\u6307\u5B9A Short \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

double - method

fun double(vararg param: Any?): Double
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 callDouble \u4E3A double

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Method\uFF0C\u6307\u5B9A Double \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

float - method

fun float(vararg param: Any?): Float
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 callFloat \u4E3A float

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Method\uFF0C\u6307\u5B9A Float \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

string - method

fun string(vararg param: Any?): String
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 callString \u4E3A string

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Method\uFF0C\u6307\u5B9A String \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

char - method

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

boolean - method

fun boolean(vararg param: Any?): Boolean
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.65 \u65B0\u589E

v1.0.68 \u4FEE\u6539

\u4FEE\u6539 callBoolean \u4E3A boolean

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Method\uFF0C\u6307\u5B9A Boolean \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

array - method

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

list - method

inline fun <reified T> list(vararg param: Any?): List<T>
+

\u53D8\u66F4\u8BB0\u5F55

v1.0.68 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u6267\u884C Method\uFF0C\u6307\u5B9A List \u8FD4\u56DE\u503C\u7C7B\u578B\u3002

`,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(`

MethodRules - class

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

name - field

var name: String
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E Method \u540D\u79F0\u3002

paramCount - field

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

returnType - field

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

modifiers - method

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

emptyParam - method

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

param - method

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

name - method

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

paramCount - method

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

paramCount - method

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

`,69),l=[p];function c(t,r){return o(),a("div",null,l)}const i=s(n,[["render",c],["__file","MethodRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/MethodRules.html.b1f90f61.js b/docs/assets/MethodRules.html.b1f90f61.js new file mode 100644 index 00000000..ff1e0c8b --- /dev/null +++ b/docs/assets/MethodRules.html.b1f90f61.js @@ -0,0 +1,11 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},p=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.

MethodRules - class

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

name - field

var name: String
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Method \u540D\u79F0\u3002

paramCount - field

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

returnType - field

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

modifiers - method

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

emptyParam - method

fun emptyParam()
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Method \u7A7A\u53C2\u6570\u3001\u65E0\u53C2\u6570\u3002

param - method

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

name - method

fun name(conditions: NameConditions)
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E Method \u540D\u79F0\u6761\u4EF6\u3002

paramCount - method

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

paramCount - method

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

`,70),l=[p];function t(c,r){return o(),a("div",null,l)}const i=s(n,[["render",t],["__file","MethodRules.html.vue"]]);export{i as default}; diff --git a/docs/assets/MethodRules.html.c10f9770.js b/docs/assets/MethodRules.html.c10f9770.js new file mode 100644 index 00000000..2e93f2b4 --- /dev/null +++ b/docs/assets/MethodRules.html.c10f9770.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-64827680","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html","title":"MethodRules - 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":"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":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.md"}');export{e as data}; diff --git a/docs/assets/ModifierRules.html.1596e901.js b/docs/assets/ModifierRules.html.1596e901.js new file mode 100644 index 00000000..5f40deb4 --- /dev/null +++ b/docs/assets/ModifierRules.html.1596e901.js @@ -0,0 +1,14 @@ +import{_ as e,o as s,c as o,a}from"./app.fb8271cf.js";const c={},n=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.

ModifierRules - class

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

isPublic - i-ext-field

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\u542B public\u3002

isPrivate - i-ext-field

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\u542B private\u3002

isProtected - i-ext-field

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\u542B protected\u3002

isStatic - i-ext-field

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\u542B static\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

isFinal - i-ext-field

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\u542B final\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

isSynchronized - i-ext-field

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\u542B synchronized\u3002

isVolatile - i-ext-field

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\u542B volatile\u3002

isTransient - i-ext-field

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\u542B transient\u3002

isNative - i-ext-field

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\u542B native\u3002

\u5BF9\u4E8E\u4EFB\u610F JNI \u5BF9\u63A5\u7684 Method \u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002

isInterface - i-ext-field

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\u542B interface\u3002

isAbstract - i-ext-field

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\u542B abstract\u3002

\u5BF9\u4E8E\u4EFB\u610F\u7684\u62BD\u8C61 Class\u3001Member \u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002

isStrict - i-ext-field

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

Class\u3001Member \u7C7B\u578B\u662F\u5426\u5305\u542B strictfp\u3002

`,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(`

ModifierRules - class

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

isPublic - i-ext-field

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\u542B public\u3002

isPrivate - i-ext-field

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\u542B private\u3002

isProtected - i-ext-field

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\u542B protected\u3002

isStatic - i-ext-field

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\u542B static\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

isFinal - i-ext-field

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\u542B final\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

isSynchronized - i-ext-field

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\u542B synchronized\u3002

isVolatile - i-ext-field

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\u542B volatile\u3002

isTransient - i-ext-field

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\u542B transient\u3002

isNative - i-ext-field

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\u542B native\u3002

\u5BF9\u4E8E\u4EFB\u610F JNI \u5BF9\u63A5\u7684 Method \u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002

isInterface - i-ext-field

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\u542B interface\u3002

isAbstract - i-ext-field

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\u542B abstract\u3002

\u5BF9\u4E8E\u4EFB\u610F\u7684\u62BD\u8C61 Class\u3001Member \u53EF\u6DFB\u52A0\u6B64\u63CF\u8FF0\u8FDB\u884C\u786E\u5B9A\u3002

isStrict - i-ext-field

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

Class\u3001Member \u7C7B\u578B\u662F\u5426\u5305\u542B strictfp\u3002

`,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(`

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.

ModuleAppActivity - class

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

`,9),c=[n];function p(l,i){return s(),o("div",null,c)}const d=e(a,[["render",p],["__file","ModuleAppActivity.html.vue"]]);export{d as default}; diff --git a/docs/assets/ModuleAppActivity.html.90d3c4e6.js b/docs/assets/ModuleAppActivity.html.90d3c4e6.js new file mode 100644 index 00000000..8541e8d3 --- /dev/null +++ b/docs/assets/ModuleAppActivity.html.90d3c4e6.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-2d5d16db","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html","title":"ModuleAppActivity - 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/xposed/parasitic/activity/base/ModuleAppActivity.md"}');export{a as data}; diff --git a/docs/assets/ModuleAppActivity.html.fd7c57b2.js b/docs/assets/ModuleAppActivity.html.fd7c57b2.js new file mode 100644 index 00000000..53be6f46 --- /dev/null +++ b/docs/assets/ModuleAppActivity.html.fd7c57b2.js @@ -0,0 +1,2 @@ +import{_ as s,o as e,c as o,a as t}from"./app.fb8271cf.js";const c={},a=t(`

ModuleAppActivity - class

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

`,8),p=[a];function l(n,i){return e(),o("div",null,p)}const d=s(c,[["render",l],["__file","ModuleAppActivity.html.vue"]]);export{d as default}; diff --git a/docs/assets/ModuleAppCompatActivity.html.2fd9ae3a.js b/docs/assets/ModuleAppCompatActivity.html.2fd9ae3a.js new file mode 100644 index 00000000..b80669fd --- /dev/null +++ b/docs/assets/ModuleAppCompatActivity.html.2fd9ae3a.js @@ -0,0 +1,3 @@ +import{_ as e,o,c as s,a}from"./app.fb8271cf.js";const t={},n=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.

ModuleAppCompatActivity - class

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

moduleTheme - field

open val moduleTheme: Int
+

Change Records

v1.1.0 added

Function Illustrate

\u8BBE\u7F6E\u5F53\u524D\u4EE3\u7406\u7684 Activity \u4E3B\u9898\u3002

`,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(`

ModuleAppCompatActivity - class

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

moduleTheme - field

open val moduleTheme: Int
+

\u53D8\u66F4\u8BB0\u5F55

v1.1.0 \u65B0\u589E

\u529F\u80FD\u63CF\u8FF0

\u8BBE\u7F6E\u5F53\u524D\u4EE3\u7406\u7684 Activity \u4E3B\u9898\u3002

`,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(`

ModuleApplication - class

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

  • ",3),u=n("\u5728\u6A21\u5757\u4E2D\u4F7F\u7528\u7CFB\u7EDF\u9690\u85CF API\uFF0C\u6838\u5FC3\u6280\u672F\u5F15\u7528\u4E86\u5F00\u6E90\u9879\u76EE "),A={href:"https://github.com/tiann/FreeReflection",target:"_blank",rel:"noopener noreferrer"},y=n("FreeReflection"),v=s("li",null,[s("p",null,[n("\u5728\u6A21\u5757\u4E2D\u4F7F\u7528 "),s("code",null,"YukiHookAPI.Status.isTaiChiModuleActive"),n(" \u5224\u65AD\u592A\u6781\u3001\u65E0\u6781\u6FC0\u6D3B\u72B6\u6001")])],-1),m=o(`

    \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"
    +    ...>
    +

    appContext - field

    val appContext: ModuleApplication
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.77 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u83B7\u53D6\u5168\u5C40\u9759\u6001 Application \u5B9E\u4F8B\u3002

    `,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(`

    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.

    ModuleApplication - class

    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

  • ",3),u=n("\u5728\u6A21\u5757\u4E2D\u4F7F\u7528\u7CFB\u7EDF\u9690\u85CF API\uFF0C\u6838\u5FC3\u6280\u672F\u5F15\u7528\u4E86\u5F00\u6E90\u9879\u76EE "),A={href:"https://github.com/tiann/FreeReflection",target:"_blank",rel:"noopener noreferrer"},y=n("FreeReflection"),m=s("li",null,[s("p",null,[n("\u5728\u6A21\u5757\u4E2D\u4F7F\u7528 "),s("code",null,"YukiHookAPI.Status.isTaiChiModuleActive"),n(" \u5224\u65AD\u592A\u6781\u3001\u65E0\u6781\u6FC0\u6D3B\u72B6\u6001")])],-1),v=e(`

    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"
    +    ...>
    +

    appContext - field

    val appContext: ModuleApplication
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    \u83B7\u53D6\u5168\u5C40\u9759\u6001 Application \u5B9E\u4F8B\u3002

    `,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(`

    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.

    ModuleContextThemeWrapper - class

    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

    applyConfiguration - method

    fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u8BBE\u7F6E\u5F53\u524D ModuleContextThemeWrapper \u7684 Configuration\u3002

    \u8BBE\u7F6E\u540E\u4F1A\u81EA\u52A8\u8C03\u7528 Resources.updateConfiguration\u3002

    `,15),p=[t];function l(r,c){return o(),e("div",null,p)}const d=s(a,[["render",l],["__file","ModuleContextThemeWrapper.html.vue"]]);export{d as default}; diff --git a/docs/assets/ModuleContextThemeWrapper.html.7262b83c.js b/docs/assets/ModuleContextThemeWrapper.html.7262b83c.js new file mode 100644 index 00000000..0840a7ef --- /dev/null +++ b/docs/assets/ModuleContextThemeWrapper.html.7262b83c.js @@ -0,0 +1,3 @@ +import{_ as s,o,c as e,a}from"./app.fb8271cf.js";const n={},p=a(`

    ModuleContextThemeWrapper - class

    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

    applyConfiguration - method

    fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.1.0 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u8BBE\u7F6E\u5F53\u524D ModuleContextThemeWrapper \u7684 Configuration\u3002

    \u8BBE\u7F6E\u540E\u4F1A\u81EA\u52A8\u8C03\u7528 Resources.updateConfiguration\u3002

    `,14),l=[p];function t(c,r){return o(),e("div",null,l)}const i=s(n,[["render",t],["__file","ModuleContextThemeWrapper.html.vue"]]);export{i as default}; diff --git a/docs/assets/ModulePreferenceFragment.html.0c7dadc7.js b/docs/assets/ModulePreferenceFragment.html.0c7dadc7.js new file mode 100644 index 00000000..c3e17122 --- /dev/null +++ b/docs/assets/ModulePreferenceFragment.html.0c7dadc7.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-53bcae06","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html","title":"ModulePreferenceFragment - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"onCreatePreferencesInModuleApp - method","slug":"oncreatepreferencesinmoduleapp-method","link":"#oncreatepreferencesinmoduleapp-method","children":[]},{"level":2,"title":"onSharedPreferenceChanged - method","slug":"onsharedpreferencechanged-method","link":"#onsharedpreferencechanged-method","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.md"}');export{e as data}; diff --git a/docs/assets/ModulePreferenceFragment.html.40d2af95.js b/docs/assets/ModulePreferenceFragment.html.40d2af95.js new file mode 100644 index 00000000..8cb116c6 --- /dev/null +++ b/docs/assets/ModulePreferenceFragment.html.40d2af95.js @@ -0,0 +1,22 @@ +import{_ as s,o as e,c as n,a}from"./app.fb8271cf.js";const o={},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.

    ModulePreferenceFragment - class

    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

    onCreatePreferencesInModuleApp - method

    abstract fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?)
    +

    Change Records

    v1.0.78 added

    Function Illustrate

    \u5BF9\u63A5\u539F\u59CB\u65B9\u6CD5 onCreatePreferences\u3002

    onSharedPreferenceChanged - method

    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.
    +    }
    +}
    +
    `,31),p=[l];function r(c,t){return e(),n("div",null,p)}const i=s(o,[["render",r],["__file","ModulePreferenceFragment.html.vue"]]);export{i as default}; diff --git a/docs/assets/ModulePreferenceFragment.html.764fecc3.js b/docs/assets/ModulePreferenceFragment.html.764fecc3.js new file mode 100644 index 00000000..168d3e42 --- /dev/null +++ b/docs/assets/ModulePreferenceFragment.html.764fecc3.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-23e1a817","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html","title":"ModulePreferenceFragment - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"onCreatePreferencesInModuleApp - method","slug":"oncreatepreferencesinmoduleapp-method","link":"#oncreatepreferencesinmoduleapp-method","children":[]},{"level":2,"title":"onSharedPreferenceChanged - method","slug":"onsharedpreferencechanged-method","link":"#onsharedpreferencechanged-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.md"}');export{e as data}; diff --git a/docs/assets/ModulePreferenceFragment.html.7e33a328.js b/docs/assets/ModulePreferenceFragment.html.7e33a328.js new file mode 100644 index 00000000..1f441a2d --- /dev/null +++ b/docs/assets/ModulePreferenceFragment.html.7e33a328.js @@ -0,0 +1,22 @@ +import{_ as s,o as e,c as n,a}from"./app.fb8271cf.js";const o={},l=a(`

    ModulePreferenceFragment - class

    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

    onCreatePreferencesInModuleApp - method

    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

    onSharedPreferenceChanged - method

    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.
    +    }
    +}
    +
    `,30),p=[l];function r(c,t){return e(),n("div",null,p)}const i=s(o,[["render",r],["__file","ModulePreferenceFragment.html.vue"]]);export{i as default}; diff --git a/docs/assets/NameRules.html.00ac96fb.js b/docs/assets/NameRules.html.00ac96fb.js new file mode 100644 index 00000000..dc0491f2 --- /dev/null +++ b/docs/assets/NameRules.html.00ac96fb.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-f5b1ffb2","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html","title":"NameRules - class","lang":"en-US","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":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.md"}');export{e as data}; diff --git a/docs/assets/NameRules.html.4729f5e5.js b/docs/assets/NameRules.html.4729f5e5.js new file mode 100644 index 00000000..e3df107b --- /dev/null +++ b/docs/assets/NameRules.html.4729f5e5.js @@ -0,0 +1,9 @@ +import{_ as s,o as e,c as o,a as n}from"./app.fb8271cf.js";const a={},p=n(`

    NameRules - class

    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

    String.isSynthetic - i-ext-method

    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

    String.isOnlySymbols - i-ext-method

    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

    String.isOnlyLetters - i-ext-method

    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

    String.isOnlyNumbers - i-ext-method

    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

    String.isOnlyLettersNumbers - i-ext-method

    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

    String.isOnlyLowercase - i-ext-method

    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

    String.isOnlyUppercase - i-ext-method

    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.

    NameRules - class

    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

    String.isSynthetic - i-ext-method

    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

    String.isOnlySymbols - i-ext-method

    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

    String.isOnlyLetters - i-ext-method

    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

    String.isOnlyNumbers - i-ext-method

    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

    String.isOnlyLettersNumbers - i-ext-method

    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

    String.isOnlyLowercase - i-ext-method

    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

    String.isOnlyUppercase - i-ext-method

    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.

    PackageParam - class

    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

    appClassLoader - field

    val appClassLoader\uFF1AClassLoader
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D Hook APP \u7684 ClassLoader\u3002

    appInfo - field

    val appInfo: ApplicationInfo
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D Hook APP \u7684 ApplicationInfo\u3002

    appUserId - field

    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

    appContext - field

    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

    appResources - field

    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

    systemContext - field

    val systemContext: Context
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D\u7CFB\u7EDF\u6846\u67B6\u7684 Context\u3002

    processName - field

    val processName: String
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D Hook APP \u7684\u8FDB\u7A0B\u540D\u79F0\u3002

    packageName - field

    val packageName: String
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D Hook APP \u7684\u5305\u540D\u3002

    isFirstApplication - field

    val isFirstApplication: Boolean
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D Hook APP \u662F\u5426\u4E3A\u7B2C\u4E00\u4E2A Application\u3002

    mainProcessName - field

    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

    moduleAppFilePath - field

    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

    moduleAppResources - field

    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

    prefs - field

    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

    prefs - method

    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

    dataChannel - field

    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

    resources - method

    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

    refreshModuleAppResources - method

    fun refreshModuleAppResources()
    +

    Change Records

    v1.0.87 added

    Function Illustrate

    \u5237\u65B0\u5F53\u524D Xposed \u6A21\u5757\u81EA\u8EAB Resources\u3002

    onAppLifecycle - method

    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

    loadApp - method

    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)
    +

    loadZygote - method

    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

    loadSystem - method

    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

    withProcess - method

    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

    loadHooker - method

    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

    searchClass - method

    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\u7684 Class\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

    String+VariousClass.clazz - i-ext-field

    Change Records

    v1.0 first

    v1.1.0 deprecated

    \u8BF7\u8F6C\u79FB\u5230 toClass(...) \u65B9\u6CD5

    String.hasClass - i-ext-field

    Change Records

    v1.0 first

    v1.1.0 deprecated

    \u8BF7\u8F6C\u79FB\u5230 hasClass(...) \u65B9\u6CD5

    String+VariousClass.toClass - i-ext-method

    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\u3001VariousClass \u8F6C\u6362\u4E3A loader \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)
    +

    String+VariousClass.toClassOrNull - i-ext-method

    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\u3001VariousClass \u8F6C\u6362\u4E3A loader \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

    String.hasClass - i-ext-method

    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.
    +}
    +

    findClass - method

    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 findClass(various: VariousClass) \u65B9\u6CD5

    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)
    +

    String+Class+VariousClass+HookClass.hook - i-ext-method

    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 isUseAppClassLoader \u53C2\u6570

    \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.
    +}
    +

    HookResources.hook - i-ext-method

    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

    AppLifecycle - class

    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

    attachBaseContext - method

    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

    onCreate - method

    fun onCreate(initiate: Application.() -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    \u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D Application.onCreate\u3002

    onTerminate - method

    fun onTerminate(initiate: Application.() -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    \u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D Application.onTerminate\u3002

    onLowMemory - method

    fun onLowMemory(initiate: Application.() -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    \u76D1\u542C\u5F53\u524D Hook APP \u88C5\u8F7D Application.onLowMemory\u3002

    onTrimMemory - method

    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

    onConfigurationChanged - method

    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

    registerReceiver - method

    fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    \u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\u76D1\u542C\u3002

    `,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(`

    PackageParam - class

    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

    appClassLoader - field

    val appClassLoader\uFF1AClassLoader
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    \u83B7\u53D6\u5F53\u524D Hook APP \u7684 ClassLoader\u3002

    appInfo - field

    val appInfo: ApplicationInfo
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    \u83B7\u53D6\u5F53\u524D Hook APP \u7684 ApplicationInfo\u3002

    appUserId - field

    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

    appContext - field

    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

    appResources - field

    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

    systemContext - field

    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

    processName - field

    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

    packageName - field

    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

    isFirstApplication - field

    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

    mainProcessName - field

    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

    moduleAppFilePath - field

    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

    moduleAppResources - field

    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

    prefs - field

    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

    prefs - method

    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

    dataChannel - field

    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

    resources - method

    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

    refreshModuleAppResources - method

    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

    onAppLifecycle - method

    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

    loadApp - method

    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)
    +

    loadZygote - method

    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

    loadSystem - method

    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

    withProcess - method

    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

    loadHooker - method

    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

    searchClass - method

    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\u7684 Class\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

    String+VariousClass.clazz - i-ext-field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u4F5C\u5E9F

    \u8BF7\u8F6C\u79FB\u5230 toClass(...) \u65B9\u6CD5

    String.hasClass - i-ext-field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u4F5C\u5E9F

    \u8BF7\u8F6C\u79FB\u5230 hasClass(...) \u65B9\u6CD5

    String+VariousClass.toClass - i-ext-method

    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\u3001VariousClass \u8F6C\u6362\u4E3A loader \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)
    +

    String+VariousClass.toClassOrNull - i-ext-method

    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\u3001VariousClass \u8F6C\u6362\u4E3A loader \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

    String.hasClass - i-ext-method

    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.
    +}
    +

    findClass - method

    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 findClass(various: VariousClass) \u65B9\u6CD5

    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)
    +

    String+Class+VariousClass+HookClass.hook - i-ext-method

    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 isUseAppClassLoader \u53C2\u6570

    \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.
    +}
    +

    HookResources.hook - i-ext-method

    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

    AppLifecycle - class

    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

    attachBaseContext - method

    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

    onCreate - method

    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

    onTerminate - method

    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

    onLowMemory - method

    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

    onTrimMemory - method

    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

    onConfigurationChanged - method

    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

    registerReceiver - method

    fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.88 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\u76D1\u542C\u3002

    `,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(`

    PrefsData - class

    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)
    +
    `,19),e=[p];function t(c,r){return a(),n("div",null,e)}const A=s(o,[["render",t],["__file","PrefsData.html.vue"]]);export{A as default}; diff --git a/docs/assets/PrefsData.html.be01fa30.js b/docs/assets/PrefsData.html.be01fa30.js new file mode 100644 index 00000000..cdf20e9b --- /dev/null +++ b/docs/assets/PrefsData.html.be01fa30.js @@ -0,0 +1,18 @@ +import{_ as s,o as a,c as n,a as l}from"./app.fb8271cf.js";const o={},e=l(`

    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.

    PrefsData - class

    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)
    +
    `,20),p=[e];function t(c,r){return a(),n("div",null,p)}const A=s(o,[["render",t],["__file","PrefsData.html.vue"]]);export{A as default}; diff --git a/docs/assets/PrefsData.html.d3cf97f9.js b/docs/assets/PrefsData.html.d3cf97f9.js new file mode 100644 index 00000000..756e7e6c --- /dev/null +++ b/docs/assets/PrefsData.html.d3cf97f9.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-d99f7f36","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html","title":"PrefsData - 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/prefs/data/PrefsData.md"}');export{a as data}; diff --git a/docs/assets/PrefsData.html.dfd7c23c.js b/docs/assets/PrefsData.html.dfd7c23c.js new file mode 100644 index 00000000..2adde194 --- /dev/null +++ b/docs/assets/PrefsData.html.dfd7c23c.js @@ -0,0 +1 @@ +const a=JSON.parse('{"key":"v-58ed8298","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html","title":"PrefsData - 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/xposed/prefs/data/PrefsData.md"}');export{a as data}; diff --git a/docs/assets/ReflectionFactory.html.a9e6e2d7.js b/docs/assets/ReflectionFactory.html.a9e6e2d7.js new file mode 100644 index 00000000..e2f14d9d --- /dev/null +++ b/docs/assets/ReflectionFactory.html.a9e6e2d7.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0d0fcec2","path":"/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html","title":"ReflectionFactory - kt","lang":"en-US","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":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.md"}');export{e as data}; diff --git a/docs/assets/ReflectionFactory.html.d2629c75.js b/docs/assets/ReflectionFactory.html.d2629c75.js new file mode 100644 index 00000000..81323b07 --- /dev/null +++ b/docs/assets/ReflectionFactory.html.d2629c75.js @@ -0,0 +1,59 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},l=e(`

    ReflectionFactory - kt

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    \u8FD9\u662F\u81EA\u5B9A\u4E49 Member \u548C Class \u76F8\u5173\u529F\u80FD\u7684\u67E5\u627E\u5339\u914D\u4EE5\u53CA invoke \u7684\u5C01\u88C5\u7C7B\u3002

    MembersType - class

    enum class MembersType
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.1.0 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u5B9A\u4E49\u4E00\u4E2A Class \u4E2D\u7684 Member \u7C7B\u578B

    ALL - enum

    ALL
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.1.0 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u5168\u90E8 Method \u4E0E Constructor\u3002

    METHOD - enum

    METHOD
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.1.0 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u5168\u90E8 Method\u3002

    CONSTRUCTOR - enum

    CONSTRUCTOR
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.1.0 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u5168\u90E8 Constructor\u3002

    ClassLoader.searchClass - ext-method

    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\u7684 Class\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

    ClassLoader.onLoadClass - ext-method

    fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.1.0 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u76D1\u542C\u5F53\u524D ClassLoader \u7684 ClassLoader.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 {
    +            // ...
    +        }
    +    }
    +}
    +

    hookClass - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u79FB\u9664

    HookClass \u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E

    normalClass - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u79FB\u9664

    HookClass \u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E

    hasClass - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u79FB\u9664

    \u8BF7\u76F4\u63A5\u4F7F\u7528 hasClass() \u65E0\u53C2\u65B9\u6CD5

    Class.hasExtends - ext-field

    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\u662F Any \u5C06\u88AB\u8BA4\u4E3A\u6CA1\u6709\u7EE7\u627F\u5173\u7CFB\u3002

    classOf - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u4F5C\u5E9F

    \u8BF7\u8F6C\u5230 toClass(...) \u65B9\u6CD5

    String.toClass - ext-method

    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)
    +

    String.toClassOrNull - ext-method

    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

    classOf - method

    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\u5176 Class \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)
    +

    String.hasClass - ext-method

    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.
    +}
    +

    Class.hasField - ext-method

    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

    Class.hasMethod - ext-method

    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

    Class.hasConstructor - ext-method

    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

    Member.hasModifiers - ext-method

    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

    Class.hasModifiers - ext-method

    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

    obtainStaticFieldAny - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.1 \u79FB\u9664

    obtainFieldAny - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.1 \u79FB\u9664

    modifyStaticField - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.1 \u79FB\u9664

    modifyField - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.1 \u79FB\u9664

    Class.field - ext-method

    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

    Class.method - ext-method

    inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.1 \u4FEE\u6539

    obtainMethod \u66F4\u540D\u4E3A 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

    Class.constructor - ext-method

    inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.1 \u4FEE\u6539

    obtainConstructor \u66F4\u540D\u4E3A 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

    callStatic - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.1 \u4FEE\u6539

    invokeStatic \u66F4\u540D\u4E3A callStatic

    v1.0.2 \u79FB\u9664

    call - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.1 \u4FEE\u6539

    invokeAny \u66F4\u540D\u4E3A call

    v1.0.2 \u79FB\u9664

    Class.generic - ext-method

    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

    Class.generic - ext-method

    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

    Any.current - ext-method

    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

    Class.buildOfAny - ext-method

    \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

    Class.buildOf - ext-method

    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\u578B Any\u3002

    Class.allMethods - ext-method

    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

    Class.allConstructors - ext-method

    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

    Class.allFields - ext-method

    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

    \u904D\u5386\u5F53\u524D\u7C7B\u4E2D\u7684\u6240\u6709\u53D8\u91CF\u3002

    `,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(`

    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.

    ReflectionFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    \u8FD9\u662F\u81EA\u5B9A\u4E49 Member \u548C Class \u76F8\u5173\u529F\u80FD\u7684\u67E5\u627E\u5339\u914D\u4EE5\u53CA invoke \u7684\u5C01\u88C5\u7C7B\u3002

    MembersType - class

    enum class MembersType
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u5B9A\u4E49\u4E00\u4E2A Class \u4E2D\u7684 Member \u7C7B\u578B

    ALL - enum

    ALL
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u5168\u90E8 Method \u4E0E Constructor\u3002

    METHOD - enum

    METHOD
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u5168\u90E8 Method\u3002

    CONSTRUCTOR - enum

    CONSTRUCTOR
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u5168\u90E8 Constructor\u3002

    ClassLoader.searchClass - ext-method

    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\u7684 Class\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

    ClassLoader.onLoadClass - ext-method

    fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u76D1\u542C\u5F53\u524D ClassLoader \u7684 ClassLoader.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 {
    +            // ...
    +        }
    +    }
    +}
    +

    hookClass - field

    Change Records

    v1.0 first

    v1.1.0 removed

    HookClass \u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E

    normalClass - field

    Change Records

    v1.0 first

    v1.1.0 removed

    HookClass \u76F8\u5173\u529F\u80FD\u4E0D\u518D\u5BF9\u5916\u5F00\u653E

    hasClass - field

    Change Records

    v1.0 first

    v1.1.0 removed

    \u8BF7\u76F4\u63A5\u4F7F\u7528 hasClass() \u65E0\u53C2\u65B9\u6CD5

    Class.hasExtends - ext-field

    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\u662F Any \u5C06\u88AB\u8BA4\u4E3A\u6CA1\u6709\u7EE7\u627F\u5173\u7CFB\u3002

    classOf - method

    Change Records

    v1.0 first

    v1.1.0 deprecated

    \u8BF7\u8F6C\u5230 toClass(...) \u65B9\u6CD5

    String.toClass - ext-method

    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)
    +

    String.toClassOrNull - ext-method

    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

    classOf - method

    inline fun <reified T> classOf(loader: ClassLoader?): Class<*>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u901A\u8FC7 T \u5F97\u5230\u5176 Class \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)
    +

    String.hasClass - ext-method

    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.
    +}
    +

    Class.hasField - ext-method

    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

    Class.hasMethod - ext-method

    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

    Class.hasConstructor - ext-method

    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

    Member.hasModifiers - ext-method

    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

    Class.hasModifiers - ext-method

    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

    obtainStaticFieldAny - method

    Change Records

    v1.0 first

    v1.0.1 removed

    obtainFieldAny - method

    Change Records

    v1.0 first

    v1.0.1 removed

    modifyStaticField - method

    Change Records

    v1.0 first

    v1.0.1 removed

    modifyField - method

    Change Records

    v1.0 first

    v1.0.1 removed

    Class.field - ext-method

    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

    Class.method - ext-method

    inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
    +

    Change Records

    v1.0 first

    v1.0.1 modified

    obtainMethod \u66F4\u540D\u4E3A 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

    Class.constructor - ext-method

    inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
    +

    Change Records

    v1.0 first

    v1.0.1 modified

    obtainConstructor \u66F4\u540D\u4E3A 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

    callStatic - method

    Change Records

    v1.0 first

    v1.0.1 modified

    invokeStatic \u66F4\u540D\u4E3A callStatic

    v1.0.2 removed

    call - method

    Change Records

    v1.0 first

    v1.0.1 modified

    invokeAny \u66F4\u540D\u4E3A call

    v1.0.2 removed

    Class.generic - ext-method

    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

    Class.generic - ext-method

    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

    Any.current - ext-method

    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

    Class.buildOfAny - ext-method

    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

    Class.buildOf - ext-method

    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\u578B Any\u3002

    Class.allMethods - ext-method

    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

    Class.allConstructors - ext-method

    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

    Class.allFields - ext-method

    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

    \u904D\u5386\u5F53\u524D\u7C7B\u4E2D\u7684\u6240\u6709\u53D8\u91CF\u3002

    `,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('

    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.

    VariableTypeFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    \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\u7684 Class \u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002

    ',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('

    VariableTypeFactory - kt

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    \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\u7684 Class \u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002

    ',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(`

    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.

    VariousClass - class

    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\u8FC7 name \u88C5\u8F7D Class \u540D\u79F0\u6570\u7EC4\u3002

    get - method

    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

    getOrNull - method

    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

    `,22),p=[l];function t(c,r){return o(),a("div",null,p)}const i=s(n,[["render",t],["__file","VariousClass.html.vue"]]);export{i as default}; diff --git a/docs/assets/VariousClass.html.5a07233f.js b/docs/assets/VariousClass.html.5a07233f.js new file mode 100644 index 00000000..c4612a52 --- /dev/null +++ b/docs/assets/VariousClass.html.5a07233f.js @@ -0,0 +1,4 @@ +import{_ as s,o as a,c as o,a as l}from"./app.fb8271cf.js";const e={},n=l(`

    VariousClass - class

    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\u8FC7 name \u88C5\u8F7D Class \u540D\u79F0\u6570\u7EC4\u3002

    get - method

    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

    getOrNull - method

    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

    `,21),p=[n];function c(t,r){return a(),o("div",null,p)}const y=s(e,[["render",c],["__file","VariousClass.html.vue"]]);export{y as default}; diff --git a/docs/assets/VariousClass.html.7c81aa10.js b/docs/assets/VariousClass.html.7c81aa10.js new file mode 100644 index 00000000..ca110519 --- /dev/null +++ b/docs/assets/VariousClass.html.7c81aa10.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-66735bfe","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html","title":"VariousClass - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":2,"title":"getOrNull - method","slug":"getornull-method","link":"#getornull-method","children":[]}],"git":{"updatedTime":1664278073000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.md"}');export{e as data}; diff --git a/docs/assets/VariousClass.html.bd237fa4.js b/docs/assets/VariousClass.html.bd237fa4.js new file mode 100644 index 00000000..c1fc9968 --- /dev/null +++ b/docs/assets/VariousClass.html.bd237fa4.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-032b1710","path":"/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html","title":"VariousClass - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"get - method","slug":"get-method","link":"#get-method","children":[]},{"level":2,"title":"getOrNull - method","slug":"getornull-method","link":"#getornull-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.md"}');export{e as data}; diff --git a/docs/assets/ViewTypeFactory.html.612b6202.js b/docs/assets/ViewTypeFactory.html.612b6202.js new file mode 100644 index 00000000..a212623a --- /dev/null +++ b/docs/assets/ViewTypeFactory.html.612b6202.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-ef79cde2","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html","title":"ViewTypeFactory - 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/ViewTypeFactory.md"}');export{e as data}; diff --git a/docs/assets/ViewTypeFactory.html.7da3eef4.js b/docs/assets/ViewTypeFactory.html.7da3eef4.js new file mode 100644 index 00000000..fdd41c32 --- /dev/null +++ b/docs/assets/ViewTypeFactory.html.7da3eef4.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5309e4a0","path":"/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html","title":"ViewTypeFactory - 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/ViewTypeFactory.md"}');export{e as data}; diff --git a/docs/assets/ViewTypeFactory.html.e29c5d7e.js b/docs/assets/ViewTypeFactory.html.e29c5d7e.js new file mode 100644 index 00000000..d05b1e9d --- /dev/null +++ b/docs/assets/ViewTypeFactory.html.e29c5d7e.js @@ -0,0 +1 @@ +import{_ as a,r as n,o as c,c as s,b as o,d as r,a as i,e}from"./app.fb8271cf.js";const p={},d=i('

    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.

    ViewTypeFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    \u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A Android \u76F8\u5173 Widget \u7684 Class \u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002

    ',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('

    ViewTypeFactory - kt

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    \u8FD9\u662F\u4E00\u4E2A\u9884\u7F6E Hook \u7C7B\u578B\u7684\u5E38\u91CF\u7C7B\uFF0C\u4E3B\u8981\u4E3A Android \u76F8\u5173 Widget \u7684 Class \u5185\u5BB9\uFF0C\u8DDF\u968F\u7248\u672C\u66F4\u65B0\u4F1A\u9010\u4E00\u8FDB\u884C\u589E\u52A0\u3002

    ',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(`

    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.

    YukiBaseHooker - class

    abstract class YukiBaseHooker : PackageParam()
    +

    Change Records

    v1.0 first

    Function Illustrate

    YukiHookAPI \u7684\u5B50\u7C7B Hooker \u5B9E\u73B0\u3002

    onHook - method

    fun onHook()
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u5B50\u7C7B Hook \u5F00\u59CB\u3002

    `,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(`

    YukiBaseHooker - class

    abstract class YukiBaseHooker : PackageParam()
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    YukiHookAPI \u7684\u5B50\u7C7B Hooker \u5B9E\u73B0\u3002

    onHook - method

    fun onHook()
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    \u5B50\u7C7B Hook \u5F00\u59CB\u3002

    `,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(`

    YukiHookAPI - object

    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

    API_VERSION_NAME - field

    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

    API_VERSION_CODE - field

    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

    executorName - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.5 \u65B0\u589E

    v1.0.91 \u79FB\u9664

    \u8BF7\u8F6C\u79FB\u5230 Status.executorName

    executorVersion - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.5 \u65B0\u589E

    v1.0.91 \u79FB\u9664

    \u8BF7\u8F6C\u79FB\u5230 Status.executorVersion

    Status - object

    object Status
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.91 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u5F53\u524D YukiHookAPI \u7684\u72B6\u6001\u3002

    compiledTimestamp - field

    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

    isXposedEnvironment - field

    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

    executorName - field

    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

    executorVersion - field

    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

    isModuleActive - field

    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

    isXposedModuleActive - field

    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

    isTaiChiModuleActive - field

    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

    isSupportResourcesHook - field

    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

    Configs - object

    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

    debugLog - method

    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

    debugTag - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u4F5C\u5E9F

    \u8BF7\u8F6C\u79FB\u5230 YukiHookLogger.Configs.tag

    isDebug - field

    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

    isAllowPrintingLogs - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.4 \u65B0\u589E

    v1.1.0 \u4F5C\u5E9F

    \u8BF7\u8F6C\u79FB\u5230 YukiHookLogger.Configs.isEnable

    isEnableModulePrefsCache - field

    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

    isEnableModuleAppResourcesCache - field

    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

    isEnableHookModuleStatus - field

    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

    isEnableHookSharedPreferences - field

    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

    isEnableDataChannel - field

    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

    isEnableMemberCache - field

    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

    configs - method

    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\u4E2A lambda \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.
    +    }
    +}
    +

    encase - method

    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.

    YukiHookAPI - object

    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

    API_VERSION_NAME - field

    const val API_VERSION_NAME: String
    +

    Change Records

    v1.0.4 added

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D YukiHookAPI \u7684\u7248\u672C\u3002

    API_VERSION_CODE - field

    const val API_VERSION_CODE: Int
    +

    Change Records

    v1.0.4 added

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D YukiHookAPI \u7684\u7248\u672C\u53F7\u3002

    executorName - field

    Change Records

    v1.0.5 added

    v1.0.91 removed

    \u8BF7\u8F6C\u79FB\u5230 Status.executorName

    executorVersion - field

    Change Records

    v1.0.5 added

    v1.0.91 removed

    \u8BF7\u8F6C\u79FB\u5230 Status.executorVersion

    Status - object

    object Status
    +

    Change Records

    v1.0.91 added

    Function Illustrate

    \u5F53\u524D YukiHookAPI \u7684\u72B6\u6001\u3002

    compiledTimestamp - field

    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

    isXposedEnvironment - field

    val isXposedEnvironment: Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D\u662F\u5426\u4E3A (Xposed) \u5BBF\u4E3B\u73AF\u5883\u3002

    executorName - field

    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

    executorVersion - field

    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

    isModuleActive - field

    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

    isXposedModuleActive - field

    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

    isTaiChiModuleActive - field

    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

    isSupportResourcesHook - field

    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

    Configs - object

    object Configs
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u5BF9 API \u76F8\u5173\u529F\u80FD\u7684\u914D\u7F6E\u7C7B\u3002

    debugLog - method

    inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u914D\u7F6E YukiHookLogger.Configs \u76F8\u5173\u53C2\u6570\u3002

    debugTag - field

    Change Records

    v1.0 first

    v1.1.0 deprecated

    \u8BF7\u8F6C\u79FB\u5230 YukiHookLogger.Configs.tag

    isDebug - field

    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

    isAllowPrintingLogs - field

    Change Records

    v1.0.4 added

    v1.1.0 deprecated

    \u8BF7\u8F6C\u79FB\u5230 YukiHookLogger.Configs.isEnable

    isEnableModulePrefsCache - field

    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

    isEnableModuleAppResourcesCache - field

    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

    isEnableHookModuleStatus - field

    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

    isEnableHookSharedPreferences - field

    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

    isEnableDataChannel - field

    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

    isEnableMemberCache - field

    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

    configs - method

    inline fun configs(initiate: Configs.() -> Unit)
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u5BF9 Configs \u7C7B\u5B9E\u73B0\u4E86\u4E00\u4E2A lambda \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.
    +    }
    +}
    +

    encase - method

    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(`

    YukiHookDataChannel - class

    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

    NameSpace - class

    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

    with - method

    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

    put - method

    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

    put - method

    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

    wait - method

    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

    wait - method

    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

    checkingVersionEquals - method

    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.

    YukiHookDataChannel - class

    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

    NameSpace - class

    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

    with - method

    inline fun with(initiate: NameSpace.() -> Unit): NameSpace
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    \u521B\u5EFA\u4E00\u4E2A\u8C03\u7528\u7A7A\u95F4\u3002

    put - method

    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

    put - method

    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

    wait - method

    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

    wait - method

    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

    checkingVersionEquals - method

    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(`

    YukiHookFactory - kt

    \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\u5173 lambda \u65B9\u6CD5\u7684\u5C01\u88C5\u7C7B\u4EE5\u53CA\u90E8\u5206 API \u7528\u6CD5\u3002

    IYukiHookXposedInit.configs - ext-method

    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\u7F6E Configs\u3002

    IYukiHookXposedInit.encase - ext-method

    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\u7528 YukiHookAPI\u3002

    Context.modulePrefs - ext-field

    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

    Context.modulePrefs - ext-method

    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

    Context.dataChannel - ext-method

    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

    Context.processName - ext-field

    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

    Context+Resources.injectModuleAppResources - ext-method

    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 \u6216 Resources \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

    Context.registerModuleAppActivities - ext-method

    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

    Context.applyModuleTheme - ext-method

    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

    isSupportResourcesHook - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    v1.0.91 \u79FB\u9664

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isSupportResourcesHook

    isModuleActive - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.6 \u65B0\u589E

    v1.0.91 \u79FB\u9664

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isModuleActive

    isXposedModuleActive - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.6 \u65B0\u589E

    v1.0.91 \u79FB\u9664

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isXposedModuleActive

    isTaiChiModuleActive - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.91 \u79FB\u9664

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isTaiChiModuleActive

    YukiHookModuleStatus - class

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.91 \u4F5C\u5E9F

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status

    `,102),c=[p];function t(l,d){return e(),s("div",null,c)}const i=o(a,[["render",t],["__file","YukiHookFactory.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiHookFactory.html.61878d38.js b/docs/assets/YukiHookFactory.html.61878d38.js new file mode 100644 index 00000000..9c11b1e5 --- /dev/null +++ b/docs/assets/YukiHookFactory.html.61878d38.js @@ -0,0 +1,12 @@ +import{_ as e,o,c as s,a as n}from"./app.fb8271cf.js";const a={},t=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.

    YukiHookFactory - kt

    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\u5173 lambda \u65B9\u6CD5\u7684\u5C01\u88C5\u7C7B\u4EE5\u53CA\u90E8\u5206 API \u7528\u6CD5\u3002

    IYukiHookXposedInit.configs - ext-method

    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\u7F6E Configs\u3002

    IYukiHookXposedInit.encase - ext-method

    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\u7528 YukiHookAPI\u3002

    Context.modulePrefs - ext-field

    val Context.modulePrefs: YukiHookModulePrefs
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6\u6A21\u5757\u7684\u5B58\u53D6\u5BF9\u8C61\u3002

    Context.modulePrefs - ext-method

    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

    Context.dataChannel - ext-method

    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

    Context.processName - ext-field

    val Context.processName: String
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D\u8FDB\u7A0B\u540D\u79F0\u3002

    Context+Resources.injectModuleAppResources - ext-method

    fun Context.injectModuleAppResources()
    +
    fun Resources.injectModuleAppResources()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u5411 Hook APP (\u5BBF\u4E3B) Context \u6216 Resources \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

    Context.registerModuleAppActivities - ext-method

    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

    Context.applyModuleTheme - ext-method

    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

    isSupportResourcesHook - field

    Change Records

    v1.0.80 added

    v1.0.91 removed

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isSupportResourcesHook

    isModuleActive - field

    Change Records

    v1.0.6 added

    v1.0.91 removed

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isModuleActive

    isXposedModuleActive - field

    Change Records

    v1.0.6 added

    v1.0.91 removed

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isXposedModuleActive

    isTaiChiModuleActive - field

    Change Records

    v1.0 first

    v1.0.91 removed

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status.isTaiChiModuleActive

    YukiHookModuleStatus - class

    Change Records

    v1.0 first

    v1.0.91 deprecated

    \u8BF7\u8F6C\u79FB\u5230 YukiHookAPI.Status

    `,103),c=[t];function p(l,d){return o(),s("div",null,c)}const i=e(a,[["render",p],["__file","YukiHookFactory.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiHookFactory.html.61db5860.js b/docs/assets/YukiHookFactory.html.61db5860.js new file mode 100644 index 00000000..e95660b0 --- /dev/null +++ b/docs/assets/YukiHookFactory.html.61db5860.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-65091354","path":"/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html","title":"YukiHookFactory - kt","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"IYukiHookXposedInit.configs - ext-method","slug":"iyukihookxposedinit-configs-ext-method","link":"#iyukihookxposedinit-configs-ext-method","children":[]},{"level":2,"title":"IYukiHookXposedInit.encase - ext-method","slug":"iyukihookxposedinit-encase-ext-method","link":"#iyukihookxposedinit-encase-ext-method","children":[]},{"level":2,"title":"Context.modulePrefs - ext-field","slug":"context-moduleprefs-ext-field","link":"#context-moduleprefs-ext-field","children":[]},{"level":2,"title":"Context.modulePrefs - ext-method","slug":"context-moduleprefs-ext-method","link":"#context-moduleprefs-ext-method","children":[]},{"level":2,"title":"Context.dataChannel - ext-method","slug":"context-datachannel-ext-method","link":"#context-datachannel-ext-method","children":[]},{"level":2,"title":"Context.processName - ext-field","slug":"context-processname-ext-field","link":"#context-processname-ext-field","children":[]},{"level":2,"title":"Context+Resources.injectModuleAppResources - ext-method","slug":"context-resources-injectmoduleappresources-ext-method","link":"#context-resources-injectmoduleappresources-ext-method","children":[]},{"level":2,"title":"Context.registerModuleAppActivities - ext-method","slug":"context-registermoduleappactivities-ext-method","link":"#context-registermoduleappactivities-ext-method","children":[]},{"level":2,"title":"Context.applyModuleTheme - ext-method","slug":"context-applymoduletheme-ext-method","link":"#context-applymoduletheme-ext-method","children":[]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.md"}');export{e as data}; diff --git a/docs/assets/YukiHookFactory.html.64f654a6.js b/docs/assets/YukiHookFactory.html.64f654a6.js new file mode 100644 index 00000000..6458dd02 --- /dev/null +++ b/docs/assets/YukiHookFactory.html.64f654a6.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-448e9585","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html","title":"YukiHookFactory - kt","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"IYukiHookXposedInit.configs - ext-method","slug":"iyukihookxposedinit-configs-ext-method","link":"#iyukihookxposedinit-configs-ext-method","children":[]},{"level":2,"title":"IYukiHookXposedInit.encase - ext-method","slug":"iyukihookxposedinit-encase-ext-method","link":"#iyukihookxposedinit-encase-ext-method","children":[]},{"level":2,"title":"Context.modulePrefs - ext-field","slug":"context-moduleprefs-ext-field","link":"#context-moduleprefs-ext-field","children":[]},{"level":2,"title":"Context.modulePrefs - ext-method","slug":"context-moduleprefs-ext-method","link":"#context-moduleprefs-ext-method","children":[]},{"level":2,"title":"Context.dataChannel - ext-method","slug":"context-datachannel-ext-method","link":"#context-datachannel-ext-method","children":[]},{"level":2,"title":"Context.processName - ext-field","slug":"context-processname-ext-field","link":"#context-processname-ext-field","children":[]},{"level":2,"title":"Context+Resources.injectModuleAppResources - ext-method","slug":"context-resources-injectmoduleappresources-ext-method","link":"#context-resources-injectmoduleappresources-ext-method","children":[]},{"level":2,"title":"Context.registerModuleAppActivities - ext-method","slug":"context-registermoduleappactivities-ext-method","link":"#context-registermoduleappactivities-ext-method","children":[]},{"level":2,"title":"Context.applyModuleTheme - ext-method","slug":"context-applymoduletheme-ext-method","link":"#context-applymoduletheme-ext-method","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.md"}');export{e as data}; diff --git a/docs/assets/YukiHookModulePrefs.html.5eb62ec3.js b/docs/assets/YukiHookModulePrefs.html.5eb62ec3.js new file mode 100644 index 00000000..eb32858b --- /dev/null +++ b/docs/assets/YukiHookModulePrefs.html.5eb62ec3.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5858709e","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html","title":"YukiHookModulePrefs - class","lang":"zh-CN","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":1663862409000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.md"}');export{e as data}; diff --git a/docs/assets/YukiHookModulePrefs.html.77ac932a.js b/docs/assets/YukiHookModulePrefs.html.77ac932a.js new file mode 100644 index 00000000..e862a202 --- /dev/null +++ b/docs/assets/YukiHookModulePrefs.html.77ac932a.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(`

    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.

    YukiHookModulePrefs - class

    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 \u548C XSharedPreferences\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

    `,10),i=s("\u8BE6\u89C1 "),y={href:"https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences#for-the-module",target:"_blank",rel:"noopener noreferrer"},u=s("New XSharedPreferences"),g=s("\u3002"),h=o("p",null,[s("\u82E5\u4F60\u5728\u6309\u7167\u89C4\u5B9A\u914D\u7F6E\u540E\u4F9D\u7136\u65E0\u6CD5\u4F7F\u7528\u6216\u51FA\u73B0\u6587\u4EF6\u6743\u9650\u9519\u8BEF\u95EE\u9898\uFF0C\u53EF\u4EE5\u53C2\u8003 "),o("a",{href:"../../../YukiHookAPI#isenablehooksharedpreferences-field"},"isEnableHookSharedPreferences"),s("\u3002")],-1),A=o("p",null,[s("\u672A\u4F7F\u7528 LSPosed \u73AF\u5883\u8BF7\u5C06\u4F60\u7684\u6A21\u5757 "),o("code",null,"API"),s(" \u964D\u81F3 "),o("code",null,"26"),s(" \u4EE5\u4E0B\uFF0C"),o("code",null,"YukiHookAPI"),s(" \u5C06\u4F1A\u5C1D\u8BD5\u4F7F\u7528 "),o("code",null,"makeWorldReadable"),s(" \u4F46\u4ECD\u6709\u53EF\u80FD\u4E0D\u6210\u529F\u3002")],-1),F=s("\u592A\u6781\u8BF7\u53C2\u9605 "),B={href:"https://taichi.cool/zh/doc/for-xposed-dev.html#%E6%96%87%E4%BB%B6%E6%9D%83%E9%99%90-%E9%85%8D%E7%BD%AE-xsharedpreference",target:"_blank",rel:"noopener noreferrer"},C=s("\u6587\u4EF6\u6743\u9650/\u914D\u7F6E/XSharedPreference"),D=s("\u3002"),k=a('

    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

    ',4),m=s("\u8BE6\u89C1 "),b={href:"https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences#for-the-module",target:"_blank",rel:"noopener noreferrer"},v=s("New XSharedPreferences"),f=s("\u3002"),x=a(`

    The following example

    <meta-data
    +    android:name="xposedsharedprefs"
    +    android:value="true"/>
    +

    isXSharePrefsReadable - field

    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

    isRunInNewXShareMode - field

    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

    name - method

    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")
    +

    direct - method

    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

    getString - method

    fun getString(key: String, value: String): String
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6 String \u952E\u503C\u3002

    getStringSet - method

    fun getStringSet(key: String, value: Set<String>): Set<String>
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    \u83B7\u53D6 Set<String> \u952E\u503C\u3002

    getBoolean - method

    fun getBoolean(key: String, value: Boolean): Boolean
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6 Boolean \u952E\u503C\u3002

    getInt - method

    fun getInt(key: String, value: Int): Int
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6 Int \u952E\u503C\u3002

    getLong - method

    fun getLong(key: String, value: Long): Long
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6 Long \u952E\u503C\u3002

    getFloat - method

    fun getFloat(key: String, value: Float): Float
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u83B7\u53D6 Float \u952E\u503C\u3002

    all - method

    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

    remove - method

    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

    remove - method

    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

    clear - method

    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

    putString - method

    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

    putStringSet - method

    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

    putBoolean - method

    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

    putInt - method

    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

    putLong - method

    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

    putFloat - method

    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

    get - method

    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

    put - method

    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

    clearCache - method

    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(`

    YukiHookModulePrefs - class

    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 \u548C XSharedPreferences\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

    `,9),i=s("\u8BE6\u89C1 "),y={href:"https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences#for-the-module",target:"_blank",rel:"noopener noreferrer"},g=s("New XSharedPreferences"),u=s("\u3002"),A=o("p",null,[s("\u82E5\u4F60\u5728\u6309\u7167\u89C4\u5B9A\u914D\u7F6E\u540E\u4F9D\u7136\u65E0\u6CD5\u4F7F\u7528\u6216\u51FA\u73B0\u6587\u4EF6\u6743\u9650\u9519\u8BEF\u95EE\u9898\uFF0C\u53EF\u4EE5\u53C2\u8003 "),o("a",{href:"../../../YukiHookAPI#isenablehooksharedpreferences-field"},"isEnableHookSharedPreferences"),s("\u3002")],-1),h=o("p",null,[s("\u672A\u4F7F\u7528 LSPosed \u73AF\u5883\u8BF7\u5C06\u4F60\u7684\u6A21\u5757 "),o("code",null,"API"),s(" \u964D\u81F3 "),o("code",null,"26"),s(" \u4EE5\u4E0B\uFF0C"),o("code",null,"YukiHookAPI"),s(" \u5C06\u4F1A\u5C1D\u8BD5\u4F7F\u7528 "),o("code",null,"makeWorldReadable"),s(" \u4F46\u4ECD\u6709\u53EF\u80FD\u4E0D\u6210\u529F\u3002")],-1),B=s("\u592A\u6781\u8BF7\u53C2\u9605 "),F={href:"https://taichi.cool/zh/doc/for-xposed-dev.html#%E6%96%87%E4%BB%B6%E6%9D%83%E9%99%90-%E9%85%8D%E7%BD%AE-xsharedpreference",target:"_blank",rel:"noopener noreferrer"},D=s("\u6587\u4EF6\u6743\u9650/\u914D\u7F6E/XSharedPreference"),C=s("\u3002"),k=a('

    \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

    ',4),m=s("\u8BE6\u89C1 "),b={href:"https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences#for-the-module",target:"_blank",rel:"noopener noreferrer"},v=s("New XSharedPreferences"),f=s("\u3002"),x=a(`

    \u793A\u4F8B\u5982\u4E0B

    <meta-data
    +    android:name="xposedsharedprefs"
    +    android:value="true"/>
    +

    isXSharePrefsReadable - field

    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

    isRunInNewXShareMode - field

    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

    name - method

    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")
    +

    direct - method

    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

    getString - method

    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

    getStringSet - method

    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

    getBoolean - method

    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

    getInt - method

    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

    getLong - method

    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

    getFloat - method

    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

    all - method

    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

    remove - method

    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

    remove - method

    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

    clear - method

    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

    putString - method

    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

    putStringSet - method

    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

    putBoolean - method

    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

    putInt - method

    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

    putLong - method

    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

    putFloat - method

    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

    get - method

    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

    put - method

    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

    clearCache - method

    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(`

    YukiMemberHookCreator - class

    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 \u7684 Member \u6838\u5FC3 Hook \u5B9E\u73B0\u7C7B\u3002

    PRIORITY_DEFAULT - field

    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

    PRIORITY_LOWEST - field

    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

    PRIORITY_HIGHEST - field

    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

    instanceClass - field

    val instanceClass: Class<*>
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.2 \u4FEE\u6539

    thisClass \u66F4\u540D\u4E3A 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

    injectMember - method

    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.
    +}
    +

    useDangerousOperation - method

    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

    MemberHookCreator - class

    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

    member - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u79FB\u9664

    \u8BF7\u8F6C\u79FB\u5230 members

    members - method

    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 {}
    +}
    +

    allMethods - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u4F5C\u5E9F

    \u8BF7\u4F7F\u7528 method { name = /** name */ }.all() \u6765\u53D6\u4EE3\u5B83

    allConstructors - method

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.1.0 \u4F5C\u5E9F

    \u8BF7\u4F7F\u7528 allMembers(MembersType.CONSTRUCTOR) \u6765\u53D6\u4EE3\u5B83

    allMembers - method

    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\u90E8 Method\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

    method - method

    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 \u7684 Method \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

    constructor - method

    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 \u7684 Constructor\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

    HookParam.field - i-ext-method

    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\u5230 Field\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()
    +    }
    +}
    +

    HookParam.method - i-ext-method

    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\u5230 Method \u3002

    HookParam.constructor - i-ext-method

    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\u5230 Constructor\u3002

    HookParam.injectMember - i-ext-method

    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

    beforeHook - method

    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

    afterHook - method

    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

    replaceAny - method

    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

    replaceUnit - method

    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\u4E3A Void\u3002

    replaceTo - method

    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

    replaceToTrue - method

    fun replaceToTrue()
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    \u62E6\u622A\u5E76\u66FF\u6362 Member \u8FD4\u56DE\u503C\u4E3A true\u3002

    \u7279\u522B\u6CE8\u610F

    \u786E\u4FDD\u66FF\u6362 Member \u7684\u8FD4\u56DE\u5BF9\u8C61\u4E3A Boolean\u3002

    replaceToFalse - method

    fun replaceToFalse()
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    \u529F\u80FD\u63CF\u8FF0

    \u62E6\u622A\u5E76\u66FF\u6362 Member \u8FD4\u56DE\u503C\u4E3A false\u3002

    \u7279\u522B\u6CE8\u610F

    \u786E\u4FDD\u66FF\u6362 Member \u7684\u8FD4\u56DE\u5BF9\u8C61\u4E3A Boolean\u3002

    intercept - method

    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

    removeSelf - method

    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

    HookCallback - class

    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

    onFailureThrowToApp - method

    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

    Result - class

    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

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0 \u6DFB\u52A0

    v1.0.5 \u4FEE\u6539

    failures \u4FEE\u6539\u4E3A 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 {}
    +    // ...
    +}
    +

    by - method

    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

    onHooked - method

    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

    onAlreadyHooked - method

    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

    onNoSuchMemberFailure - method

    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

    onConductFailure - method

    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

    onHookingFailure - method

    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

    onAllFailure - method

    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

    ignoredNoSuchMemberFailure - method

    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

    ignoredConductFailure - method

    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

    ignoredHookingFailure - method

    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

    ignoredAllFailure - method

    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

    remove - method

    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

    Result - class

    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

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.3 \u65B0\u589E

    v1.0.5 \u4FEE\u6539

    failures \u4FEE\u6539\u4E3A 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

    by - method

    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

    onPrepareHook - method

    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

    onHookClassNotFoundFailure - method

    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

    ignoredHookClassNotFoundFailure - method

    fun ignoredHookClassNotFoundFailure(): Result
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.3 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u5FFD\u7565 hookClass \u627E\u4E0D\u5230\u65F6\u51FA\u73B0\u7684\u9519\u8BEF\u3002

    `,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(`

    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.

    YukiMemberHookCreator - class

    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 \u7684 Member \u6838\u5FC3 Hook \u5B9E\u73B0\u7C7B\u3002

    PRIORITY_DEFAULT - field

    val PRIORITY_DEFAULT: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u9ED8\u8BA4 Hook \u56DE\u8C03\u4F18\u5148\u7EA7\u3002

    PRIORITY_LOWEST - field

    val PRIORITY_LOWEST: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u5EF6\u8FDF\u56DE\u8C03 Hook \u65B9\u6CD5\u7ED3\u679C\u3002

    PRIORITY_HIGHEST - field

    val PRIORITY_HIGHEST: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u66F4\u5FEB\u56DE\u8C03 Hook \u65B9\u6CD5\u7ED3\u679C\u3002

    instanceClass - field

    val instanceClass: Class<*>
    +

    Change Records

    v1.0 first

    v1.0.2 modified

    thisClass \u66F4\u540D\u4E3A 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

    injectMember - method

    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.
    +}
    +

    useDangerousOperation - method

    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

    MemberHookCreator - class

    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

    member - field

    Change Records

    v1.0 first

    v1.1.0 removed

    \u8BF7\u8F6C\u79FB\u5230 members

    members - method

    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 {}
    +}
    +

    allMethods - method

    Change Records

    v1.0 first

    v1.1.0 deprecated

    \u8BF7\u4F7F\u7528 method { name = /** name */ }.all() \u6765\u53D6\u4EE3\u5B83

    allConstructors - method

    Change Records

    v1.0 first

    v1.1.0 deprecated

    \u8BF7\u4F7F\u7528 allMembers(MembersType.CONSTRUCTOR) \u6765\u53D6\u4EE3\u5B83

    allMembers - method

    fun allMembers(type: MembersType)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u67E5\u627E\u5E76 Hook hookClass \u4E2D\u7684\u5168\u90E8 Method\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

    method - method

    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 \u7684 Method \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

    constructor - method

    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 \u7684 Constructor\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

    HookParam.field - i-ext-method

    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\u5230 Field\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()
    +    }
    +}
    +

    HookParam.method - i-ext-method

    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\u5230 Method \u3002

    HookParam.constructor - i-ext-method

    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\u5230 Constructor\u3002

    HookParam.injectMember - i-ext-method

    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

    beforeHook - method

    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

    afterHook - method

    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

    replaceAny - method

    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

    replaceUnit - method

    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\u4E3A Void\u3002

    replaceTo - method

    fun replaceTo(any: Any?)
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u62E6\u622A\u5E76\u66FF Member \u8FD4\u56DE\u503C\u3002

    replaceToTrue - method

    fun replaceToTrue()
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u62E6\u622A\u5E76\u66FF\u6362 Member \u8FD4\u56DE\u503C\u4E3A true\u3002

    Pay Attention

    \u786E\u4FDD\u66FF\u6362 Member \u7684\u8FD4\u56DE\u5BF9\u8C61\u4E3A Boolean\u3002

    replaceToFalse - method

    fun replaceToFalse()
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u62E6\u622A\u5E76\u66FF\u6362 Member \u8FD4\u56DE\u503C\u4E3A false\u3002

    Pay Attention

    \u786E\u4FDD\u66FF\u6362 Member \u7684\u8FD4\u56DE\u5BF9\u8C61\u4E3A Boolean\u3002

    intercept - method

    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

    removeSelf - method

    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

    HookCallback - class

    inner class HookCallback internal constructor()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Hook \u65B9\u6CD5\u4F53\u56DE\u8C03\u5B9E\u73B0\u7C7B\u3002

    onFailureThrowToApp - method

    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

    Result - class

    inner class Result internal constructor()
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u76D1\u542C Hook \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.5 modified

    failures \u4FEE\u6539\u4E3A 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 {}
    +    // ...
    +}
    +

    by - method

    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

    onHooked - method

    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

    onAlreadyHooked - method

    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

    onNoSuchMemberFailure - method

    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

    onConductFailure - method

    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

    onHookingFailure - method

    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

    onAllFailure - method

    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

    ignoredNoSuchMemberFailure - method

    fun ignoredNoSuchMemberFailure(): Result
    +

    Change Records

    v1.0.5 added

    Function Illustrate

    \u5FFD\u7565 members \u4E0D\u5B58\u5728\u53D1\u751F\u7684\u9519\u8BEF\u3002

    ignoredConductFailure - method

    fun ignoredConductFailure(): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u5FFD\u7565 Hook \u8FDB\u884C\u8FC7\u7A0B\u4E2D\u53D1\u751F\u7684\u9519\u8BEF\u3002

    ignoredHookingFailure - method

    fun ignoredHookingFailure(): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u5FFD\u7565 Hook \u5F00\u59CB\u65F6\u53D1\u751F\u7684\u9519\u8BEF\u3002

    ignoredAllFailure - method

    fun ignoredAllFailure(): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    \u5FFD\u7565\u5168\u90E8 Hook \u8FC7\u7A0B\u53D1\u751F\u7684\u9519\u8BEF\u3002

    remove - method

    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

    Result - class

    inner class Result internal constructor()
    +

    Change Records

    v1.0.3 added

    Function Illustrate

    \u76D1\u542C\u5168\u90E8 Hook \u7ED3\u679C\u5B9E\u73B0\u7C7B\u3002

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.0.3 added

    v1.0.5 modified

    failures \u4FEE\u6539\u4E3A result

    v1.0.80 modified

    \u5C06\u65B9\u6CD5\u4F53\u8FDB\u884C inline

    Function Illustrate

    \u521B\u5EFA\u76D1\u542C\u4E8B\u4EF6\u65B9\u6CD5\u4F53\u3002

    by - method

    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

    onPrepareHook - method

    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

    onHookClassNotFoundFailure - method

    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

    ignoredHookClassNotFoundFailure - method

    fun ignoredHookClassNotFoundFailure(): Result
    +

    Change Records

    v1.0.3 added

    Function Illustrate

    \u5FFD\u7565 hookClass \u627E\u4E0D\u5230\u65F6\u51FA\u73B0\u7684\u9519\u8BEF\u3002

    `,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(`

    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.

    YukiModuleResources - class

    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

    fwd - method

    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

    `,14),c=[l];function t(r,p){return e(),o("div",null,c)}const i=s(n,[["render",t],["__file","YukiModuleResources.html.vue"]]);export{i as default}; diff --git a/docs/assets/YukiModuleResources.html.c36ad6ed.js b/docs/assets/YukiModuleResources.html.c36ad6ed.js new file mode 100644 index 00000000..d440a291 --- /dev/null +++ b/docs/assets/YukiModuleResources.html.c36ad6ed.js @@ -0,0 +1,3 @@ +import{_ as s,o,c as e,a}from"./app.fb8271cf.js";const n={},l=a(`

    YukiModuleResources - class

    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

    fwd - method

    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

    `,13),c=[l];function p(r,t){return o(),e("div",null,c)}const u=s(n,[["render",p],["__file","YukiModuleResources.html.vue"]]);export{u as default}; diff --git a/docs/assets/YukiModuleResources.html.d8e27a7f.js b/docs/assets/YukiModuleResources.html.d8e27a7f.js new file mode 100644 index 00000000..7ae0743c --- /dev/null +++ b/docs/assets/YukiModuleResources.html.d8e27a7f.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-3d943532","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html","title":"YukiModuleResources - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"fwd - method","slug":"fwd-method","link":"#fwd-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/YukiModuleResources.md"}');export{e as data}; diff --git a/docs/assets/YukiModuleResources.html.e5c5fb30.js b/docs/assets/YukiModuleResources.html.e5c5fb30.js new file mode 100644 index 00000000..2dfb298c --- /dev/null +++ b/docs/assets/YukiModuleResources.html.e5c5fb30.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0f1e3594","path":"/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html","title":"YukiModuleResources - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"fwd - method","slug":"fwd-method","link":"#fwd-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/YukiModuleResources.md"}');export{e as data}; diff --git a/docs/assets/YukiResForwarder.html.0dadd8db.js b/docs/assets/YukiResForwarder.html.0dadd8db.js new file mode 100644 index 00000000..609026a8 --- /dev/null +++ b/docs/assets/YukiResForwarder.html.0dadd8db.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-526c4200","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html","title":"YukiResForwarder - class","lang":"zh-CN","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":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.md"}');export{e as data}; diff --git a/docs/assets/YukiResForwarder.html.3fa53afd.js b/docs/assets/YukiResForwarder.html.3fa53afd.js new file mode 100644 index 00000000..b545bf90 --- /dev/null +++ b/docs/assets/YukiResForwarder.html.3fa53afd.js @@ -0,0 +1,4 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const n={},r=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.

    YukiResForwarder - class

    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

    instance - field

    Change Records

    v1.0.80 added

    v1.1.0 deprecated

    \u4E0D\u518D\u5BF9\u5916\u516C\u5F00 instance \u53C2\u6570

    id - field

    val id: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u83B7\u5F97\u5F53\u524D APP \u7684 Resources Id\u3002

    resources - field

    val resources: Resources
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u83B7\u5F97\u5F53\u524D APP \u7684 Resources\u3002

    `,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(`

    YukiResForwarder - class

    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

    instance - field

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    v1.1.0 \u4F5C\u5E9F

    \u4E0D\u518D\u5BF9\u5916\u516C\u5F00 instance \u53C2\u6570

    id - field

    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

    resources - field

    val resources: Resources
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u83B7\u5F97\u5F53\u524D APP \u7684 Resources\u3002

    `,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(`

    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.

    YukiResources - class

    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

    LayoutInflatedParam - class

    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

    variantName - field

    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

    currentView - field

    val currentView: View
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u83B7\u53D6\u5F53\u524D\u88AB Hook \u7684\u5E03\u5C40\u5B9E\u4F8B\u3002

    findViewByIdentifier - method

    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

    `,34),p=[l];function t(c,r){return a(),n("div",null,p)}const d=s(e,[["render",t],["__file","YukiResources.html.vue"]]);export{d as default}; diff --git a/docs/assets/YukiResources.html.d71b960b.js b/docs/assets/YukiResources.html.d71b960b.js new file mode 100644 index 00000000..a924afed --- /dev/null +++ b/docs/assets/YukiResources.html.d71b960b.js @@ -0,0 +1,7 @@ +import{_ as s,o as a,c as o,a as n}from"./app.fb8271cf.js";const e={},l=n(`

    YukiResources - class

    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

    LayoutInflatedParam - class

    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

    variantName - field

    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

    currentView - field

    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

    findViewByIdentifier - method

    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

    `,33),p=[l];function c(t,r){return a(),o("div",null,p)}const d=s(e,[["render",c],["__file","YukiResources.html.vue"]]);export{d as default}; diff --git a/docs/assets/YukiResourcesHookCreator.html.46168b72.js b/docs/assets/YukiResourcesHookCreator.html.46168b72.js new file mode 100644 index 00000000..6fc3538e --- /dev/null +++ b/docs/assets/YukiResourcesHookCreator.html.46168b72.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5e81af42","path":"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html","title":"YukiResourcesHookCreator - class","lang":"zh-CN","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"injectResource - method","slug":"injectresource-method","link":"#injectresource-method","children":[]},{"level":2,"title":"ResourcesHookCreator - class","slug":"resourceshookcreator-class","link":"#resourceshookcreator-class","children":[{"level":3,"title":"resourceId - field","slug":"resourceid-field","link":"#resourceid-field","children":[]},{"level":3,"title":"conditions - method","slug":"conditions-method","link":"#conditions-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":"replaceToModuleResource - method","slug":"replacetomoduleresource-method","link":"#replacetomoduleresource-method","children":[]},{"level":3,"title":"injectAsLayout - method","slug":"injectaslayout-method","link":"#injectaslayout-method","children":[]},{"level":3,"title":"ConditionFinder - class","slug":"conditionfinder-class","link":"#conditionfinder-class","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]},{"level":3,"title":"onHookingFailure - method","slug":"onhookingfailure-method","link":"#onhookingfailure-method","children":[]},{"level":3,"title":"ignoredHookingFailure - method","slug":"ignoredhookingfailure-method","link":"#ignoredhookingfailure-method","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.md"}');export{e as data}; diff --git a/docs/assets/YukiResourcesHookCreator.html.8aaa9934.js b/docs/assets/YukiResourcesHookCreator.html.8aaa9934.js new file mode 100644 index 00000000..3579a7ee --- /dev/null +++ b/docs/assets/YukiResourcesHookCreator.html.8aaa9934.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5ed1ceee","path":"/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html","title":"YukiResourcesHookCreator - class","lang":"en-US","frontmatter":{"pageClass":"code-page"},"excerpt":"","headers":[{"level":2,"title":"injectResource - method","slug":"injectresource-method","link":"#injectresource-method","children":[]},{"level":2,"title":"ResourcesHookCreator - class","slug":"resourceshookcreator-class","link":"#resourceshookcreator-class","children":[{"level":3,"title":"resourceId - field","slug":"resourceid-field","link":"#resourceid-field","children":[]},{"level":3,"title":"conditions - method","slug":"conditions-method","link":"#conditions-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":"replaceToModuleResource - method","slug":"replacetomoduleresource-method","link":"#replacetomoduleresource-method","children":[]},{"level":3,"title":"injectAsLayout - method","slug":"injectaslayout-method","link":"#injectaslayout-method","children":[]},{"level":3,"title":"ConditionFinder - class","slug":"conditionfinder-class","link":"#conditionfinder-class","children":[]},{"level":3,"title":"Result - class","slug":"result-class","link":"#result-class","children":[]},{"level":3,"title":"onHookingFailure - method","slug":"onhookingfailure-method","link":"#onhookingfailure-method","children":[]},{"level":3,"title":"ignoredHookingFailure - method","slug":"ignoredhookingfailure-method","link":"#ignoredhookingfailure-method","children":[]}]}],"git":{"updatedTime":1664299331000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.md"}');export{e as data}; diff --git a/docs/assets/YukiResourcesHookCreator.html.d14760e0.js b/docs/assets/YukiResourcesHookCreator.html.d14760e0.js new file mode 100644 index 00000000..0b1a00bd --- /dev/null +++ b/docs/assets/YukiResourcesHookCreator.html.d14760e0.js @@ -0,0 +1,95 @@ +import{_ as s,o as n,c as e,a}from"./app.fb8271cf.js";const o={},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.

    YukiResourcesHookCreator - class

    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 \u7684 Resources \u6838\u5FC3 Hook \u5B9E\u73B0\u7C7B\u3002

    injectResource - method

    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.
    +}
    +

    ResourcesHookCreator - class

    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

    resourceId - field

    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(...)
    +}
    +

    conditions - method

    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(...)
    +}
    +

    replaceTo - method

    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))
    +}
    +

    replaceToTrue - method

    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

    replaceToFalse - method

    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

    replaceToModuleResource - method

    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)
    +}
    +

    injectAsLayout - method

    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()
    +    }
    +}
    +

    ConditionFinder - class

    inner class ConditionFinder internal constructor()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    Resources \u67E5\u627E\u6761\u4EF6\u5B9E\u73B0\u7C7B\u3002

    name - field

    var name: String
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u540D\u79F0\u3002

    anim - method

    fun anim()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u52A8\u753B\u3002

    animator - method

    fun animator()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5C5E\u6027\u52A8\u753B\u3002

    bool - method

    fun bool()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5E03\u6717(Boolean)\u3002

    color - method

    fun color()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u989C\u8272(Color)\u3002

    dimen - method

    fun dimen()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5C3A\u5BF8(Dimention)\u3002

    drawable - method

    fun drawable()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Drawable\u3002

    integer - method

    fun integer()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u6574\u578B(Integer)\u3002

    layout - method

    fun layout()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5E03\u5C40(Layout)\u3002

    plurals - method

    fun plurals()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Plurals\u3002

    string - method

    fun string()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u5B57\u7B26\u4E32(String)\u3002

    xml - method

    fun xml()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Xml\u3002

    mipmap - method

    fun mipmap()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u4F4D\u56FE(Mipmap)\u3002

    array - method

    fun array()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u6570\u7EC4(Array)\u3002

    Result - class

    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

    result - method

    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

    by - method

    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

    onHookingFailure - method

    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

    ignoredHookingFailure - method

    fun ignoredHookingFailure(): Result
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u5FFD\u7565 Hook \u8FC7\u7A0B\u51FA\u73B0\u7684\u9519\u8BEF\u3002

    `,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(`

    YukiResourcesHookCreator - class

    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 \u7684 Resources \u6838\u5FC3 Hook \u5B9E\u73B0\u7C7B\u3002

    injectResource - method

    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.
    +}
    +

    ResourcesHookCreator - class

    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

    resourceId - field

    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(...)
    +}
    +

    conditions - method

    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(...)
    +}
    +

    replaceTo - method

    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))
    +}
    +

    replaceToTrue - method

    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

    replaceToFalse - method

    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

    replaceToModuleResource - method

    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)
    +}
    +

    injectAsLayout - method

    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()
    +    }
    +}
    +

    ConditionFinder - class

    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

    name - field

    var name: String
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u8BBE\u7F6E Resources \u540D\u79F0\u3002

    anim - method

    fun anim()
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A\u52A8\u753B\u3002

    animator - method

    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

    bool - method

    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

    color - method

    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

    dimen - method

    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

    drawable - method

    fun drawable()
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Drawable\u3002

    integer - method

    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

    layout - method

    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

    plurals - method

    fun plurals()
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Plurals\u3002

    string - method

    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

    xml - method

    fun xml()
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u8BBE\u7F6E Resources \u7C7B\u578B\u4E3A Xml\u3002

    mipmap - method

    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

    array - method

    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

    Result - class

    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

    result - method

    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

    by - method

    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

    onHookingFailure - method

    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

    ignoredHookingFailure - method

    fun ignoredHookingFailure(): Result
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u5FFD\u7565 Hook \u8FC7\u7A0B\u51FA\u73B0\u7684\u9519\u8BEF\u3002

    `,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(`

    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.

    YukiXposedEvent - object

    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

    events - method

    inline fun events(initiate: YukiXposedEvent.() -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u5BF9 YukiXposedEvent \u521B\u5EFA\u4E00\u4E2A\u65B9\u6CD5\u4F53\u3002

    onInitZygote - method

    fun onInitZygote(result: (StartupParam) -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E initZygote \u4E8B\u4EF6\u76D1\u542C\u3002

    onHandleLoadPackage - method

    fun onHandleLoadPackage(result: (LoadPackageParam) -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E handleLoadPackage \u4E8B\u4EF6\u76D1\u542C\u3002

    onHandleInitPackageResources - method

    fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    \u8BBE\u7F6E handleInitPackageResources \u4E8B\u4EF6\u76D1\u542C\u3002

    `,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(`

    YukiXposedEvent - object

    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

    events - method

    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

    onInitZygote - method

    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

    onHandleLoadPackage - method

    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

    onHandleInitPackageResources - method

    fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
    +

    \u53D8\u66F4\u8BB0\u5F55

    v1.0.80 \u65B0\u589E

    \u529F\u80FD\u63CF\u8FF0

    \u8BBE\u7F6E handleInitPackageResources \u4E8B\u4EF6\u76D1\u542C\u3002

    `,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(`
    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(`

    API \u57FA\u672C\u914D\u7F6E

    \u8FD9\u91CC\u4ECB\u7ECD\u4E86 YukiHookAPI \u7684\u57FA\u672C\u914D\u7F6E\u65B9\u6CD5\u3002

    \u529F\u80FD\u914D\u7F6E

    \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

    configs \u65B9\u6CD5

    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

    Hooker \u914D\u7F6E

    \u4E00\u4E2A Xposed \u6A21\u5757\u6216 Hook API \u6700\u91CD\u8981\u7684\u5730\u65B9\u5C31\u662F Hooker \u7684\u521B\u5EFA\u4E0E\u4F7F\u7528\uFF0CYukiHookAPI \u63D0\u4F9B\u4E86\u4E24\u79CD\u4F7F\u7528\u65B9\u6CD5\u3002

    \u901A\u8FC7 lambda \u521B\u5EFA

    \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

    encase \u65B9\u6CD5

    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

    \u901A\u8FC7\u81EA\u5B9A\u4E49 Hooker \u521B\u5EFA

    \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

    encase \u65B9\u6CD5

    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 \u7528\u6CD5

    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 ...)
    +}
    +

    \u6269\u5C55\u7279\u6027

    \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.
    +        }
    +    }
    +}
    +

    \u6CE8\u610F\u4E8B\u9879

    \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

    \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 {
    +                // ...
    +            }
    +        }
    +    }
    +}
    +

    \u4F5C\u4E3A Hook API \u4F7F\u7528\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9

    \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

    `,82),p=[e];function c(i,r){return n(),a("div",null,p)}const d=s(o,[["render",c],["__file","api-example.html.vue"]]);export{d as default}; diff --git a/docs/assets/api-example.html.f5361b1b.js b/docs/assets/api-example.html.f5361b1b.js new file mode 100644 index 00000000..13c95e97 --- /dev/null +++ b/docs/assets/api-example.html.f5361b1b.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-c6114c9e","path":"/zh-cn/config/api-example.html","title":"API \u57FA\u672C\u914D\u7F6E","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u529F\u80FD\u914D\u7F6E","slug":"\u529F\u80FD\u914D\u7F6E","link":"#\u529F\u80FD\u914D\u7F6E","children":[{"level":3,"title":"configs \u65B9\u6CD5","slug":"configs-\u65B9\u6CD5","link":"#configs-\u65B9\u6CD5","children":[]}]},{"level":2,"title":"Hooker \u914D\u7F6E","slug":"hooker-\u914D\u7F6E","link":"#hooker-\u914D\u7F6E","children":[{"level":3,"title":"\u901A\u8FC7 lambda \u521B\u5EFA","slug":"\u901A\u8FC7-lambda-\u521B\u5EFA","link":"#\u901A\u8FC7-lambda-\u521B\u5EFA","children":[]},{"level":3,"title":"\u901A\u8FC7\u81EA\u5B9A\u4E49 Hooker \u521B\u5EFA","slug":"\u901A\u8FC7\u81EA\u5B9A\u4E49-hooker-\u521B\u5EFA","link":"#\u901A\u8FC7\u81EA\u5B9A\u4E49-hooker-\u521B\u5EFA","children":[]},{"level":3,"title":"\u6269\u5C55\u7279\u6027","slug":"\u6269\u5C55\u7279\u6027","link":"#\u6269\u5C55\u7279\u6027","children":[]},{"level":3,"title":"\u6CE8\u610F\u4E8B\u9879","slug":"\u6CE8\u610F\u4E8B\u9879","link":"#\u6CE8\u610F\u4E8B\u9879","children":[]}]},{"level":2,"title":"\u4F5C\u4E3A Hook API \u4F7F\u7528\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9","slug":"\u4F5C\u4E3A-hook-api-\u4F7F\u7528\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9","link":"#\u4F5C\u4E3A-hook-api-\u4F7F\u7528\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9","children":[]}],"git":{"updatedTime":1663857406000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/config/api-example.md"}');export{e as data}; diff --git a/docs/assets/api-example.html.ffabf490.js b/docs/assets/api-example.html.ffabf490.js new file mode 100644 index 00000000..20ef49f6 --- /dev/null +++ b/docs/assets/api-example.html.ffabf490.js @@ -0,0 +1,182 @@ +import{_ as s,o as n,c as a,a as e}from"./app.fb8271cf.js";const o={},l=e(`

    API Basic Configs

    The basic configuration method of YukiHookAPI is introduced here.

    Function Configs

    Either Use as Xposed Module Configs or Use as Hook API Configs, you can specify YukiHookAPI for configuration.

    configs Method

    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.

    Hooker Configs

    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.

    Created by lambda

    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.

    encase Method

    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.

    Created by Custom Hooker

    This scheme is more suitable for large-scale projects, such as the need to classify Hooker or classify the role of Hook.

    encase Method

    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 Usage

    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 ...)
    +}
    +

    Expansion Features

    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.
    +        }
    +    }
    +}
    +

    Precautions

    It is wrong to load Hooker directly or start Hook directly, encase event will go through three callbacks after being loaded by Hook Framework.

    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 {
    +                // ...
    +            }
    +        }
    +    }
    +}
    +

    Precautions when using as Hook API

    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.

    `,82),p=[l];function c(i,r){return n(),a("div",null,p)}const d=s(o,[["render",c],["__file","api-example.html.vue"]]);export{d as default}; diff --git a/docs/assets/api-exception.html.5fb01524.js b/docs/assets/api-exception.html.5fb01524.js new file mode 100644 index 00000000..ada2285d --- /dev/null +++ b/docs/assets/api-exception.html.5fb01524.js @@ -0,0 +1,359 @@ +import{_ as s,o as e,c as n,a}from"./app.fb8271cf.js";const o={},l=a(`

    API Exception Handling

    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.

    Non-Blocking Exceptions

    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.

    exception

    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.

    exception

    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.
    +        }
    +    }
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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 {
    +        // ...
    +    }
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    Blocking Exceptions

    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".

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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")
    +    }
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    `,561),t=[l];function i(p,c){return e(),n("div",null,t)}const d=s(o,[["render",i],["__file","api-exception.html.vue"]]);export{d as default}; diff --git a/docs/assets/api-exception.html.72ebad13.js b/docs/assets/api-exception.html.72ebad13.js new file mode 100644 index 00000000..b675f687 --- /dev/null +++ b/docs/assets/api-exception.html.72ebad13.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-72c12b7d","path":"/en/config/api-exception.html","title":"API Exception Handling","lang":"en-US","frontmatter":{"pageClass":"hidden-anchor-page"},"excerpt":"","headers":[{"level":2,"title":"Non-Blocking Exceptions","slug":"non-blocking-exceptions","link":"#non-blocking-exceptions","children":[]},{"level":2,"title":"Blocking Exceptions","slug":"blocking-exceptions","link":"#blocking-exceptions","children":[]}],"git":{"updatedTime":1664013512000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":3}]},"filePathRelative":"en/config/api-exception.md"}');export{e as data}; diff --git a/docs/assets/api-exception.html.9f654113.js b/docs/assets/api-exception.html.9f654113.js new file mode 100644 index 00000000..4e611197 --- /dev/null +++ b/docs/assets/api-exception.html.9f654113.js @@ -0,0 +1,354 @@ +import{_ as s,o as n,c as e,a}from"./app.fb8271cf.js";const o={},l=a(`

    API \u5F02\u5E38\u5904\u7406

    \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

    \u975E\u963B\u65AD\u5F02\u5E38

    \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

    exception

    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

    exception

    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.
    +        }
    +    }
    +}
    +
    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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 {
    +        // ...
    +    }
    +}
    +
    exception

    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

    exception

    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

    exception

    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

    exception

    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
    +}
    +
    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    \u963B\u65AD\u5F02\u5E38

    \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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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")
    +    }
    +}
    +
    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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

    exception

    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
    +}
    +
    exception

    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

    exception

    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

    exception

    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

    `,534),p=[l];function c(i,t){return n(),e("div",null,p)}const d=s(o,[["render",c],["__file","api-exception.html.vue"]]);export{d as default}; diff --git a/docs/assets/api-exception.html.ac2a5859.js b/docs/assets/api-exception.html.ac2a5859.js new file mode 100644 index 00000000..8125853b --- /dev/null +++ b/docs/assets/api-exception.html.ac2a5859.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-5b43296c","path":"/zh-cn/config/api-exception.html","title":"API \u5F02\u5E38\u5904\u7406","lang":"zh-CN","frontmatter":{"pageClass":"hidden-anchor-page"},"excerpt":"","headers":[{"level":2,"title":"\u975E\u963B\u65AD\u5F02\u5E38","slug":"\u975E\u963B\u65AD\u5F02\u5E38","link":"#\u975E\u963B\u65AD\u5F02\u5E38","children":[]},{"level":2,"title":"\u963B\u65AD\u5F02\u5E38","slug":"\u963B\u65AD\u5F02\u5E38","link":"#\u963B\u65AD\u5F02\u5E38","children":[]}],"git":{"updatedTime":1664013437000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":7}]},"filePathRelative":"zh-cn/config/api-exception.md"}');export{e as data}; diff --git a/docs/assets/api-using.html.0a59e2e0.js b/docs/assets/api-using.html.0a59e2e0.js new file mode 100644 index 00000000..a473b618 --- /dev/null +++ b/docs/assets/api-using.html.0a59e2e0.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2ee67152","path":"/zh-cn/config/api-using.html","title":"\u4F5C\u4E3A Hook API \u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u4F9D\u8D56\u914D\u7F6E","slug":"\u4F9D\u8D56\u914D\u7F6E","link":"#\u4F9D\u8D56\u914D\u7F6E","children":[]},{"level":2,"title":"\u5165\u53E3\u914D\u7F6E","slug":"\u5165\u53E3\u914D\u7F6E","link":"#\u5165\u53E3\u914D\u7F6E","children":[]},{"level":2,"title":"Hook Framework","slug":"hook-framework","link":"#hook-framework","children":[{"level":3,"title":"Pine","slug":"pine","link":"#pine","children":[]},{"level":3,"title":"SandHook","slug":"sandhook","link":"#sandhook","children":[]},{"level":3,"title":"Whale","slug":"whale","link":"#whale","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/config/api-using.md"}');export{e as data}; diff --git a/docs/assets/api-using.html.1ec848ab.js b/docs/assets/api-using.html.1ec848ab.js new file mode 100644 index 00000000..56b30e5d --- /dev/null +++ b/docs/assets/api-using.html.1ec848ab.js @@ -0,0 +1,50 @@ +import{_ as l,r as p,o as c,c as t,b as s,d as e,a as o,e as n}from"./app.fb8271cf.js";const i={},r=o(`

    Use as Hook API Configs

    As a Hook API, it is usually used for Hook operations for hot updates or functional needs of its own app and product testing.

    Dependency Configs

    You just need to integrate the com.highcapable.yukihookapi:api dependency.

    Then please integrate the Hook Framework dependencies used by your target.

    Entry Configs

    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.

    Hook Framework

    Here are some related ways of how to connect the Hook Framework with the YukiHookAPI, which is widely used.

    `,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(`

    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)
    +}
    +
    `,3),D={id:"sandhook",tabindex:"-1"},v=s("a",{class:"header-anchor",href:"#sandhook","aria-hidden":"true"},"#",-1),B=n(),b={href:"https://github.com/asLody/SandHook",target:"_blank",rel:"noopener noreferrer"},m=n("SandHook"),k=o(`

    Required Xposed API dependencies com.swift.sandhook:xposedcompat or com.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)
    +}
    +
    `,3),_={id:"whale",tabindex:"-1"},g=s("a",{class:"header-anchor",href:"#whale","aria-hidden":"true"},"#",-1),F=n(),f={href:"https://github.com/asLody/whale",target:"_blank",rel:"noopener noreferrer"},x=n("Whale"),w=s("blockquote",null,[s("p",null,[s("strong",null,"Required Xposed API dependencies"),n(),s("code",null,"com.wind.xposed:xposed-on-whale")])],-1),H=n("Please refer to "),P={href:"https://github.com/WindySha/xposed-hook-based-on-whale",target:"_blank",rel:"noopener noreferrer"},q=n("xposed-hook-based-on-whale"),Y=n("."),I=o(`

    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)
    +}
    +
    `,2);function L(E,N){const a=p("ExternalLinkIcon");return c(),t("div",null,[r,s("h3",d,[A,y,s("a",u,[h,e(a)])]),C,s("h3",D,[v,B,s("a",b,[m,e(a)])]),k,s("h3",_,[g,F,s("a",f,[x,e(a)])]),w,s("p",null,[H,s("a",P,[q,e(a)]),Y]),I])}const S=l(i,[["render",L],["__file","api-using.html.vue"]]);export{S as default}; diff --git a/docs/assets/api-using.html.37eb156b.js b/docs/assets/api-using.html.37eb156b.js new file mode 100644 index 00000000..be8c45ed --- /dev/null +++ b/docs/assets/api-using.html.37eb156b.js @@ -0,0 +1,50 @@ +import{_ as l,r as p,o as c,c as r,b as s,d as e,a as o,e as n}from"./app.fb8271cf.js";const t={},i=o(`

    \u4F5C\u4E3A Hook API \u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E

    \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

    \u4F9D\u8D56\u914D\u7F6E

    \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

    \u5165\u53E3\u914D\u7F6E

    \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

    Hook Framework

    \u8FD9\u91CC\u7ED9\u51FA\u4E86\u4E00\u4E9B\u8F83\u9AD8\u4F7F\u7528\u7387\u7684 Hook Framework \u5982\u4F55\u5BF9\u63A5 YukiHookAPI \u7684\u76F8\u5173\u65B9\u5F0F\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(`

    \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)
    +}
    +
    `,3),D={id:"sandhook",tabindex:"-1"},h=s("a",{class:"header-anchor",href:"#sandhook","aria-hidden":"true"},"#",-1),v=n(),b={href:"https://github.com/asLody/SandHook",target:"_blank",rel:"noopener noreferrer"},k=n("SandHook"),m=o(`

    \u6240\u9700 Xposed API \u4F9D\u8D56 com.swift.sandhook:xposedcompat \u6216 com.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)
    +}
    +
    `,3),F={id:"whale",tabindex:"-1"},_=s("a",{class:"header-anchor",href:"#whale","aria-hidden":"true"},"#",-1),g=n(),x={href:"https://github.com/asLody/whale",target:"_blank",rel:"noopener noreferrer"},f=n("Whale"),H=s("blockquote",null,[s("p",null,[s("strong",null,"\u6240\u9700 Xposed API \u4F9D\u8D56"),n(),s("code",null,"com.wind.xposed:xposed-on-whale")])],-1),P=n("\u8BF7\u53C2\u8003 "),I={href:"https://github.com/WindySha/xposed-hook-based-on-whale",target:"_blank",rel:"noopener noreferrer"},Y=n("xposed-hook-based-on-whale"),q=n("\u3002"),w=o(`

    \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)
    +}
    +
    `,2);function E(X,L){const a=p("ExternalLinkIcon");return c(),r("div",null,[i,s("h3",d,[A,y,s("a",u,[B,e(a)])]),C,s("h3",D,[h,v,s("a",b,[k,e(a)])]),m,s("h3",F,[_,g,s("a",x,[f,e(a)])]),H,s("p",null,[P,s("a",I,[Y,e(a)]),q]),w])}const S=l(t,[["render",E],["__file","api-using.html.vue"]]);export{S as default}; diff --git a/docs/assets/api-using.html.c794f69e.js b/docs/assets/api-using.html.c794f69e.js new file mode 100644 index 00000000..c63652e3 --- /dev/null +++ b/docs/assets/api-using.html.c794f69e.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-793879e8","path":"/en/config/api-using.html","title":"Use as Hook API Configs","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Dependency Configs","slug":"dependency-configs","link":"#dependency-configs","children":[]},{"level":2,"title":"Entry Configs","slug":"entry-configs","link":"#entry-configs","children":[]},{"level":2,"title":"Hook Framework","slug":"hook-framework","link":"#hook-framework","children":[{"level":3,"title":"Pine","slug":"pine","link":"#pine","children":[]},{"level":3,"title":"SandHook","slug":"sandhook","link":"#sandhook","children":[]},{"level":3,"title":"Whale","slug":"whale","link":"#whale","children":[]}]}],"git":{"updatedTime":1663943791000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/config/api-using.md"}');export{e as data}; diff --git a/docs/assets/app.fb8271cf.js b/docs/assets/app.fb8271cf.js new file mode 100644 index 00000000..6094107e --- /dev/null +++ b/docs/assets/app.fb8271cf.js @@ -0,0 +1,10 @@ +const Za="modulepreload",Ja=function(e){return"/YukiHookAPI/"+e},Xo={},d=function(t,l,i){return!l||l.length===0?t():Promise.all(l.map(o=>{if(o=Ja(o),o in Xo)return;Xo[o]=!0;const n=o.endsWith(".css"),r=n?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${o}"]${r}`))return;const a=document.createElement("link");if(a.rel=n?"stylesheet":Za,n||(a.as="script",a.crossOrigin=""),a.href=o,document.head.appendChild(a),n)return new Promise((s,c)=>{a.addEventListener("load",s),a.addEventListener("error",()=>c(new Error(`Unable to preload CSS for ${o}`)))})})).then(()=>t())},es={"v-8daa1a0e":()=>d(()=>import("./index.html.1b76ac9e.js"),[]).then(({data:e})=>e),"v-2d0a870d":()=>d(()=>import("./index.html.872aa7a1.js"),[]).then(({data:e})=>e),"v-c0c85b84":()=>d(()=>import("./index.html.6cc32291.js"),[]).then(({data:e})=>e),"v-7a15fe3b":()=>d(()=>import("./about.html.7638d3a2.js"),[]).then(({data:e})=>e),"v-3f851d14":()=>d(()=>import("./changelog.html.86d916d5.js"),[]).then(({data:e})=>e),"v-193cf592":()=>d(()=>import("./contacts.html.5dc8225c.js"),[]).then(({data:e})=>e),"v-ae7b83f2":()=>d(()=>import("./future.html.94bd226b.js"),[]).then(({data:e})=>e),"v-64fc7bb8":()=>d(()=>import("./home.html.f6b9c2a4.js"),[]).then(({data:e})=>e),"v-9cfea7fc":()=>d(()=>import("./api-example.html.47c311e0.js"),[]).then(({data:e})=>e),"v-72c12b7d":()=>d(()=>import("./api-exception.html.72ebad13.js"),[]).then(({data:e})=>e),"v-793879e8":()=>d(()=>import("./api-using.html.c794f69e.js"),[]).then(({data:e})=>e),"v-29d6c1ba":()=>d(()=>import("./r8-proguard.html.15e04e11.js"),[]).then(({data:e})=>e),"v-24e71de7":()=>d(()=>import("./xposed-using.html.cd65195d.js"),[]).then(({data:e})=>e),"v-7b22efaf":()=>d(()=>import("./example.html.a036bda1.js"),[]).then(({data:e})=>e),"v-efb45d4c":()=>d(()=>import("./home.html.f6f658d0.js"),[]).then(({data:e})=>e),"v-277b35ca":()=>d(()=>import("./knowledge.html.437816ed.js"),[]).then(({data:e})=>e),"v-77d752a2":()=>d(()=>import("./move-to-new-api.html.78f39fa5.js"),[]).then(({data:e})=>e),"v-72889797":()=>d(()=>import("./quick-start.html.e309979a.js"),[]).then(({data:e})=>e),"v-55c11626":()=>d(()=>import("./yukihookapi-projectbuilder.html.ed4fa356.js"),[]).then(({data:e})=>e),"v-41967128":()=>d(()=>import("./about.html.c0115524.js"),[]).then(({data:e})=>e),"v-0e6c3476":()=>d(()=>import("./changelog.html.05a4745e.js"),[]).then(({data:e})=>e),"v-6cf86266":()=>d(()=>import("./contacts.html.3df7cacf.js"),[]).then(({data:e})=>e),"v-3106ca14":()=>d(()=>import("./future.html.2cf8d6de.js"),[]).then(({data:e})=>e),"v-c8deafb2":()=>d(()=>import("./home.html.cad3998c.js"),[]).then(({data:e})=>e),"v-c6114c9e":()=>d(()=>import("./api-example.html.f5361b1b.js"),[]).then(({data:e})=>e),"v-5b43296c":()=>d(()=>import("./api-exception.html.ac2a5859.js"),[]).then(({data:e})=>e),"v-2ee67152":()=>d(()=>import("./api-using.html.0a59e2e0.js"),[]).then(({data:e})=>e),"v-154d6f69":()=>d(()=>import("./r8-proguard.html.683a5429.js"),[]).then(({data:e})=>e),"v-af73b3d0":()=>d(()=>import("./xposed-using.html.557dcdf1.js"),[]).then(({data:e})=>e),"v-13b430a0":()=>d(()=>import("./example.html.13ac887a.js"),[]).then(({data:e})=>e),"v-6a609e09":()=>d(()=>import("./home.html.4d8cac8a.js"),[]).then(({data:e})=>e),"v-b4f1a468":()=>d(()=>import("./knowledge.html.821f04b5.js"),[]).then(({data:e})=>e),"v-c0d5dada":()=>d(()=>import("./move-to-new-api.html.508c5312.js"),[]).then(({data:e})=>e),"v-24840ff0":()=>d(()=>import("./quick-start.html.eacb83f2.js"),[]).then(({data:e})=>e),"v-a2fab4d6":()=>d(()=>import("./yukihookapi-projectbuilder.html.d499d226.js"),[]).then(({data:e})=>e),"v-12042f1f":()=>d(()=>import("./host-inject.html.c5fc5faf.js"),[]).then(({data:e})=>e),"v-deaff1d0":()=>d(()=>import("./host-lifecycle.html.412bbdd6.js"),[]).then(({data:e})=>e),"v-33c1dc26":()=>d(()=>import("./logger.html.2d57680b.js"),[]).then(({data:e})=>e),"v-581ddb9c":()=>d(()=>import("./reflection.html.ff24950f.js"),[]).then(({data:e})=>e),"v-2e6ad66c":()=>d(()=>import("./xposed-channel.html.96712a39.js"),[]).then(({data:e})=>e),"v-68bebbf4":()=>d(()=>import("./xposed-storage.html.c35a7041.js"),[]).then(({data:e})=>e),"v-6ac5be8e":()=>d(()=>import("./host-inject.html.83f072dc.js"),[]).then(({data:e})=>e),"v-357a8d49":()=>d(()=>import("./host-lifecycle.html.09c0b222.js"),[]).then(({data:e})=>e),"v-1f0f591e":()=>d(()=>import("./logger.html.e8fab6a3.js"),[]).then(({data:e})=>e),"v-001858e3":()=>d(()=>import("./reflection.html.2e612549.js"),[]).then(({data:e})=>e),"v-598546c6":()=>d(()=>import("./xposed-channel.html.b798a8f8.js"),[]).then(({data:e})=>e),"v-0d914225":()=>d(()=>import("./xposed-storage.html.5fd9a913.js"),[]).then(({data:e})=>e),"v-053599a5":()=>d(()=>import("./YukiHookAPI.html.77b2a461.js"),[]).then(({data:e})=>e),"v-6931cb54":()=>d(()=>import("./YukiHookAPI.html.476693ca.js"),[]).then(({data:e})=>e),"v-818b3ca6":()=>d(()=>import("./InjectYukiHookWithXposed.html.56391530.js"),[]).then(({data:e})=>e),"v-b6a815c4":()=>d(()=>import("./CurrentClass.html.16c29272.js"),[]).then(({data:e})=>e),"v-0183e3fc":()=>d(()=>import("./GenericClass.html.7b666428.js"),[]).then(({data:e})=>e),"v-57506200":()=>d(()=>import("./HookClass.html.52e59cf0.js"),[]).then(({data:e})=>e),"v-9af56c1a":()=>d(()=>import("./HookResources.html.2486cf29.js"),[]).then(({data:e})=>e),"v-032b1710":()=>d(()=>import("./VariousClass.html.bd237fa4.js"),[]).then(({data:e})=>e),"v-71147891":()=>d(()=>import("./YukiMemberHookCreator.html.d3b181da.js"),[]).then(({data:e})=>e),"v-5ed1ceee":()=>d(()=>import("./YukiResourcesHookCreator.html.8aaa9934.js"),[]).then(({data:e})=>e),"v-e288ce96":()=>d(()=>import("./YukiBaseHooker.html.99eec744.js"),[]).then(({data:e})=>e),"v-0d0fcec2":()=>d(()=>import("./ReflectionFactory.html.a9e6e2d7.js"),[]).then(({data:e})=>e),"v-65091354":()=>d(()=>import("./YukiHookFactory.html.61db5860.js"),[]).then(({data:e})=>e),"v-36aec5ad":()=>d(()=>import("./LoggerFactory.html.914e1c34.js"),[]).then(({data:e})=>e),"v-60cbe1b4":()=>d(()=>import("./HookParam.html.b19d4ad2.js"),[]).then(({data:e})=>e),"v-b381a126":()=>d(()=>import("./PackageParam.html.7a64d58c.js"),[]).then(({data:e})=>e),"v-6e47300f":()=>d(()=>import("./CurrentClass.html.641fcd58.js"),[]).then(({data:e})=>e),"v-69c1c226":()=>d(()=>import("./GenericClass.html.3a0e1ac6.js"),[]).then(({data:e})=>e),"v-735374af":()=>d(()=>import("./HookClass.html.486aa6ea.js"),[]).then(({data:e})=>e),"v-1c516d22":()=>d(()=>import("./HookResources.html.4f07fd98.js"),[]).then(({data:e})=>e),"v-66735bfe":()=>d(()=>import("./VariousClass.html.7c81aa10.js"),[]).then(({data:e})=>e),"v-30f3ba1e":()=>d(()=>import("./InjectYukiHookWithXposed.html.cf9b500d.js"),[]).then(({data:e})=>e),"v-3ac40680":()=>d(()=>import("./YukiMemberHookCreator.html.37dcaec4.js"),[]).then(({data:e})=>e),"v-5e81af42":()=>d(()=>import("./YukiResourcesHookCreator.html.46168b72.js"),[]).then(({data:e})=>e),"v-516df326":()=>d(()=>import("./YukiBaseHooker.html.b68236f9.js"),[]).then(({data:e})=>e),"v-213d88b3":()=>d(()=>import("./ReflectionFactory.html.f7b7c82c.js"),[]).then(({data:e})=>e),"v-448e9585":()=>d(()=>import("./YukiHookFactory.html.64f654a6.js"),[]).then(({data:e})=>e),"v-004a009e":()=>d(()=>import("./LoggerFactory.html.72d1861a.js"),[]).then(({data:e})=>e),"v-75a9b636":()=>d(()=>import("./HookParam.html.f98d02d2.js"),[]).then(({data:e})=>e),"v-100b529c":()=>d(()=>import("./PackageParam.html.37aae471.js"),[]).then(({data:e})=>e),"v-8293d958":()=>d(()=>import("./ComponentTypeFactory.html.5af05d7d.js"),[]).then(({data:e})=>e),"v-7b0abf86":()=>d(()=>import("./GraphicsTypeFactory.html.a3936b7c.js"),[]).then(({data:e})=>e),"v-5309e4a0":()=>d(()=>import("./ViewTypeFactory.html.7da3eef4.js"),[]).then(({data:e})=>e),"v-a2615d0c":()=>d(()=>import("./DefinedTypeFactory.html.8137c32c.js"),[]).then(({data:e})=>e),"v-ba01a600":()=>d(()=>import("./VariableTypeFactory.html.d4c9dbd1.js"),[]).then(({data:e})=>e),"v-7fec5836":()=>d(()=>import("./ModuleApplication.html.57573770.js"),[]).then(({data:e})=>e),"v-7414265a":()=>d(()=>import("./YukiHookDataChannel.html.75c012dd.js"),[]).then(({data:e})=>e),"v-003862c2":()=>d(()=>import("./YukiHookModulePrefs.html.e0f278fe.js"),[]).then(({data:e})=>e),"v-1d680acc":()=>d(()=>import("./IYukiHookXposedInit.html.b37a852b.js"),[]).then(({data:e})=>e),"v-5e874c45":()=>d(()=>import("./ComponentTypeFactory.html.0026a7b8.js"),[]).then(({data:e})=>e),"v-4ea62475":()=>d(()=>import("./GraphicsTypeFactory.html.bfb4e259.js"),[]).then(({data:e})=>e),"v-ef79cde2":()=>d(()=>import("./ViewTypeFactory.html.612b6202.js"),[]).then(({data:e})=>e),"v-5acc12ab":()=>d(()=>import("./DefinedTypeFactory.html.ba3bdd0b.js"),[]).then(({data:e})=>e),"v-14ec8671":()=>d(()=>import("./VariableTypeFactory.html.550d3346.js"),[]).then(({data:e})=>e),"v-4709ad58":()=>d(()=>import("./ModuleApplication.html.a386b8db.js"),[]).then(({data:e})=>e),"v-632be8ee":()=>d(()=>import("./YukiHookDataChannel.html.74e08a45.js"),[]).then(({data:e})=>e),"v-5858709e":()=>d(()=>import("./YukiHookModulePrefs.html.5eb62ec3.js"),[]).then(({data:e})=>e),"v-763140ee":()=>d(()=>import("./IYukiHookXposedInit.html.78a55860.js"),[]).then(({data:e})=>e),"v-4fca92c0":()=>d(()=>import("./BaseFinder.html.a5dbb7a7.js"),[]).then(({data:e})=>e),"v-2a898c66":()=>d(()=>import("./DexClassFinder.html.5d8e12f0.js"),[]).then(({data:e})=>e),"v-a71937aa":()=>d(()=>import("./ConstructorFinder.html.0c13dc47.js"),[]).then(({data:e})=>e),"v-42e0f0ab":()=>d(()=>import("./FieldFinder.html.4410e26c.js"),[]).then(({data:e})=>e),"v-a4aa4d00":()=>d(()=>import("./MethodFinder.html.97f89f93.js"),[]).then(({data:e})=>e),"v-0f1e3594":()=>d(()=>import("./YukiModuleResources.html.e5c5fb30.js"),[]).then(({data:e})=>e),"v-35faec91":()=>d(()=>import("./YukiResForwarder.html.4e23df75.js"),[]).then(({data:e})=>e),"v-2c04b82a":()=>d(()=>import("./YukiResources.html.afb6fb92.js"),[]).then(({data:e})=>e),"v-19e7277e":()=>d(()=>import("./YukiXposedEvent.html.560fa41c.js"),[]).then(({data:e})=>e),"v-2f64a2d4":()=>d(()=>import("./ChannelData.html.f8f818f6.js"),[]).then(({data:e})=>e),"v-58ed8298":()=>d(()=>import("./PrefsData.html.dfd7c23c.js"),[]).then(({data:e})=>e),"v-23e1a817":()=>d(()=>import("./ModulePreferenceFragment.html.764fecc3.js"),[]).then(({data:e})=>e),"v-0f719471":()=>d(()=>import("./BaseFinder.html.8f275c85.js"),[]).then(({data:e})=>e),"v-45111efc":()=>d(()=>import("./DexClassFinder.html.78c5f805.js"),[]).then(({data:e})=>e),"v-1e2cbc9c":()=>d(()=>import("./ConstructorFinder.html.7de4f560.js"),[]).then(({data:e})=>e),"v-22449c48":()=>d(()=>import("./FieldFinder.html.25713065.js"),[]).then(({data:e})=>e),"v-fd738322":()=>d(()=>import("./MethodFinder.html.03ce70ab.js"),[]).then(({data:e})=>e),"v-3d943532":()=>d(()=>import("./YukiModuleResources.html.d8e27a7f.js"),[]).then(({data:e})=>e),"v-526c4200":()=>d(()=>import("./YukiResForwarder.html.0dadd8db.js"),[]).then(({data:e})=>e),"v-68541dca":()=>d(()=>import("./YukiResources.html.7b0a4824.js"),[]).then(({data:e})=>e),"v-0a4de82f":()=>d(()=>import("./YukiXposedEvent.html.a93ee4ef.js"),[]).then(({data:e})=>e),"v-493d37f6":()=>d(()=>import("./ChannelData.html.194718a1.js"),[]).then(({data:e})=>e),"v-d99f7f36":()=>d(()=>import("./PrefsData.html.d3cf97f9.js"),[]).then(({data:e})=>e),"v-53bcae06":()=>d(()=>import("./ModulePreferenceFragment.html.0c7dadc7.js"),[]).then(({data:e})=>e),"v-52995ef7":()=>d(()=>import("./CountRules.html.2d5ab94d.js"),[]).then(({data:e})=>e),"v-8d5ce71a":()=>d(()=>import("./ModifierRules.html.c36dff17.js"),[]).then(({data:e})=>e),"v-f5b1ffb2":()=>d(()=>import("./NameRules.html.00ac96fb.js"),[]).then(({data:e})=>e),"v-08b70f7f":()=>d(()=>import("./ConstructorRules.html.d62bae6c.js"),[]).then(({data:e})=>e),"v-21f64ebf":()=>d(()=>import("./FieldRules.html.9b04521f.js"),[]).then(({data:e})=>e),"v-77f11cf9":()=>d(()=>import("./MemberRules.html.a071b3c6.js"),[]).then(({data:e})=>e),"v-64827680":()=>d(()=>import("./MethodRules.html.c10f9770.js"),[]).then(({data:e})=>e),"v-2d5d16db":()=>d(()=>import("./ModuleAppActivity.html.90d3c4e6.js"),[]).then(({data:e})=>e),"v-cadbe48e":()=>d(()=>import("./ModuleAppCompatActivity.html.a20d9206.js"),[]).then(({data:e})=>e),"v-78731c50":()=>d(()=>import("./ModuleContextThemeWrapper.html.0879426b.js"),[]).then(({data:e})=>e),"v-1b2ad030":()=>d(()=>import("./CountRules.html.2639d392.js"),[]).then(({data:e})=>e),"v-547a3c3c":()=>d(()=>import("./ModifierRules.html.f7582dc2.js"),[]).then(({data:e})=>e),"v-58c26516":()=>d(()=>import("./NameRules.html.47e512e4.js"),[]).then(({data:e})=>e),"v-a42f54a4":()=>d(()=>import("./ConstructorRules.html.f8d7dd83.js"),[]).then(({data:e})=>e),"v-3e67a42e":()=>d(()=>import("./FieldRules.html.6858f0d6.js"),[]).then(({data:e})=>e),"v-2cab152c":()=>d(()=>import("./MemberRules.html.b3e5d297.js"),[]).then(({data:e})=>e),"v-5388621e":()=>d(()=>import("./MethodRules.html.146b27be.js"),[]).then(({data:e})=>e),"v-44efb702":()=>d(()=>import("./ModuleContextThemeWrapper.html.229a46ac.js"),[]).then(({data:e})=>e),"v-1446bdca":()=>d(()=>import("./ModuleAppActivity.html.09451ff7.js"),[]).then(({data:e})=>e),"v-c7cef530":()=>d(()=>import("./ModuleAppCompatActivity.html.dd9e40e9.js"),[]).then(({data:e})=>e),"v-5e375d98":()=>d(()=>import("./MemberRulesResult.html.e79843c3.js"),[]).then(({data:e})=>e),"v-b8000f3a":()=>d(()=>import("./MemberRulesResult.html.58e81c94.js"),[]).then(({data:e})=>e),"v-3706649a":()=>d(()=>import("./404.html.c038a05a.js"),[]).then(({data:e})=>e)};function mo(e,t){const l=Object.create(null),i=e.split(",");for(let o=0;o!!l[o.toLowerCase()]:o=>!!l[o]}const ts="itemscope,allowfullscreen,formnovalidate,ismap,nomodule,novalidate,readonly",ls=mo(ts);function hr(e){return!!e||e===""}function Sl(e){if(te(e)){const t={};for(let l=0;l{if(l){const i=l.split(os);i.length>1&&(t[i[0].trim()]=i[1].trim())}}),t}function Ke(e){let t="";if(be(e))t=e;else if(te(e))for(let l=0;lbe(e)?e:e==null?"":te(e)||Oe(e)&&(e.toString===mr||!re(e.toString))?JSON.stringify(e,dr,2):String(e),dr=(e,t)=>t&&t.__v_isRef?dr(e,t.value):al(t)?{[`Map(${t.size})`]:[...t.entries()].reduce((l,[i,o])=>(l[`${i} =>`]=o,l),{})}:ur(t)?{[`Set(${t.size})`]:[...t.values()]}:Oe(t)&&!te(t)&&!fr(t)?String(t):t,Re={},rl=[],at=()=>{},rs=()=>!1,as=/^on[^a-z]/,Vl=e=>as.test(e),fo=e=>e.startsWith("onUpdate:"),Se=Object.assign,go=(e,t)=>{const l=e.indexOf(t);l>-1&&e.splice(l,1)},ss=Object.prototype.hasOwnProperty,de=(e,t)=>ss.call(e,t),te=Array.isArray,al=e=>bi(e)==="[object Map]",ur=e=>bi(e)==="[object Set]",re=e=>typeof e=="function",be=e=>typeof e=="string",ko=e=>typeof e=="symbol",Oe=e=>e!==null&&typeof e=="object",pr=e=>Oe(e)&&re(e.then)&&re(e.catch),mr=Object.prototype.toString,bi=e=>mr.call(e),cs=e=>bi(e).slice(8,-1),fr=e=>bi(e)==="[object Object]",vo=e=>be(e)&&e!=="NaN"&&e[0]!=="-"&&""+parseInt(e,10)===e,Rl=mo(",key,ref,ref_for,ref_key,onVnodeBeforeMount,onVnodeMounted,onVnodeBeforeUpdate,onVnodeUpdated,onVnodeBeforeUnmount,onVnodeUnmounted"),_i=e=>{const t=Object.create(null);return l=>t[l]||(t[l]=e(l))},hs=/-(\w)/g,ut=_i(e=>e.replace(hs,(t,l)=>l?l.toUpperCase():"")),ds=/\B([A-Z])/g,Zt=_i(e=>e.replace(ds,"-$1").toLowerCase()),yi=_i(e=>e.charAt(0).toUpperCase()+e.slice(1)),Oi=_i(e=>e?`on${yi(e)}`:""),wl=(e,t)=>!Object.is(e,t),Fi=(e,t)=>{for(let l=0;l{Object.defineProperty(e,t,{configurable:!0,enumerable:!1,value:l})},gr=e=>{const t=parseFloat(e);return isNaN(t)?e:t};let qo;const us=()=>qo||(qo=typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:typeof global<"u"?global:{});let Xe;class ps{constructor(t=!1){this.active=!0,this.effects=[],this.cleanups=[],!t&&Xe&&(this.parent=Xe,this.index=(Xe.scopes||(Xe.scopes=[])).push(this)-1)}run(t){if(this.active){const l=Xe;try{return Xe=this,t()}finally{Xe=l}}}on(){Xe=this}off(){Xe=this.parent}stop(t){if(this.active){let l,i;for(l=0,i=this.effects.length;l{const t=new Set(e);return t.w=0,t.n=0,t},kr=e=>(e.w&Ft)>0,vr=e=>(e.n&Ft)>0,ks=({deps:e})=>{if(e.length)for(let t=0;t{const{deps:t}=e;if(t.length){let l=0;for(let i=0;i{(c==="length"||c>=i)&&a.push(s)});else switch(l!==void 0&&a.push(r.get(l)),t){case"add":te(e)?vo(l)&&a.push(r.get("length")):(a.push(r.get(Kt)),al(e)&&a.push(r.get(qi)));break;case"delete":te(e)||(a.push(r.get(Kt)),al(e)&&a.push(r.get(qi)));break;case"set":al(e)&&a.push(r.get(Kt));break}if(a.length===1)a[0]&&Ki(a[0]);else{const s=[];for(const c of a)c&&s.push(...c);Ki(bo(s))}}function Ki(e,t){const l=te(e)?e:[...e];for(const i of l)i.computed&&Go(i);for(const i of l)i.computed||Go(i)}function Go(e,t){(e!==nt||e.allowRecurse)&&(e.scheduler?e.scheduler():e.run())}const bs=mo("__proto__,__v_isRef,__isVue"),yr=new Set(Object.getOwnPropertyNames(Symbol).filter(e=>e!=="arguments"&&e!=="caller").map(e=>Symbol[e]).filter(ko)),_s=yo(),ys=yo(!1,!0),xs=yo(!0),Qo=Es();function Es(){const e={};return["includes","indexOf","lastIndexOf"].forEach(t=>{e[t]=function(...l){const i=ke(this);for(let n=0,r=this.length;n{e[t]=function(...l){ml();const i=ke(this)[t].apply(this,l);return fl(),i}}),e}function yo(e=!1,t=!1){return function(i,o,n){if(o==="__v_isReactive")return!e;if(o==="__v_isReadonly")return e;if(o==="__v_isShallow")return t;if(o==="__v_raw"&&n===(e?t?Vs:Pr:t?Cr:Rr).get(i))return i;const r=te(i);if(!e&&r&&de(Qo,o))return Reflect.get(Qo,o,n);const a=Reflect.get(i,o,n);return(ko(o)?yr.has(o):bs(o))||(e||Qe(i,"get",o),t)?a:De(a)?r&&vo(o)?a:a.value:Oe(a)?e?Ro(a):gl(a):a}}const Rs=xr(),Cs=xr(!0);function xr(e=!1){return function(l,i,o,n){let r=l[i];if(Ol(r)&&De(r)&&!De(o))return!1;if(!e&&!Ol(o)&&(Gi(o)||(o=ke(o),r=ke(r)),!te(l)&&De(r)&&!De(o)))return r.value=o,!0;const a=te(l)&&vo(i)?Number(i)e,xi=e=>Reflect.getPrototypeOf(e);function Xl(e,t,l=!1,i=!1){e=e.__v_raw;const o=ke(e),n=ke(t);l||(t!==n&&Qe(o,"get",t),Qe(o,"get",n));const{has:r}=xi(o),a=i?xo:l?Po:Fl;if(r.call(o,t))return a(e.get(t));if(r.call(o,n))return a(e.get(n));e!==o&&e.get(t)}function ql(e,t=!1){const l=this.__v_raw,i=ke(l),o=ke(e);return t||(e!==o&&Qe(i,"has",e),Qe(i,"has",o)),e===o?l.has(e):l.has(e)||l.has(o)}function Kl(e,t=!1){return e=e.__v_raw,!t&&Qe(ke(e),"iterate",Kt),Reflect.get(e,"size",e)}function Zo(e){e=ke(e);const t=ke(this);return xi(t).has.call(t,e)||(t.add(e),bt(t,"add",e,e)),this}function Jo(e,t){t=ke(t);const l=ke(this),{has:i,get:o}=xi(l);let n=i.call(l,e);n||(e=ke(e),n=i.call(l,e));const r=o.call(l,e);return l.set(e,t),n?wl(t,r)&&bt(l,"set",e,t):bt(l,"add",e,t),this}function en(e){const t=ke(this),{has:l,get:i}=xi(t);let o=l.call(t,e);o||(e=ke(e),o=l.call(t,e)),i&&i.call(t,e);const n=t.delete(e);return o&&bt(t,"delete",e,void 0),n}function tn(){const e=ke(this),t=e.size!==0,l=e.clear();return t&&bt(e,"clear",void 0,void 0),l}function Gl(e,t){return function(i,o){const n=this,r=n.__v_raw,a=ke(r),s=t?xo:e?Po:Fl;return!e&&Qe(a,"iterate",Kt),r.forEach((c,h)=>i.call(o,s(c),s(h),n))}}function Ql(e,t,l){return function(...i){const o=this.__v_raw,n=ke(o),r=al(n),a=e==="entries"||e===Symbol.iterator&&r,s=e==="keys"&&r,c=o[e](...i),h=l?xo:t?Po:Fl;return!t&&Qe(n,"iterate",s?qi:Kt),{next(){const{value:p,done:m}=c.next();return m?{value:p,done:m}:{value:a?[h(p[0]),h(p[1])]:h(p),done:m}},[Symbol.iterator](){return this}}}}function xt(e){return function(...t){return e==="delete"?!1:this}}function ws(){const e={get(n){return Xl(this,n)},get size(){return Kl(this)},has:ql,add:Zo,set:Jo,delete:en,clear:tn,forEach:Gl(!1,!1)},t={get(n){return Xl(this,n,!1,!0)},get size(){return Kl(this)},has:ql,add:Zo,set:Jo,delete:en,clear:tn,forEach:Gl(!1,!0)},l={get(n){return Xl(this,n,!0)},get size(){return Kl(this,!0)},has(n){return ql.call(this,n,!0)},add:xt("add"),set:xt("set"),delete:xt("delete"),clear:xt("clear"),forEach:Gl(!0,!1)},i={get(n){return Xl(this,n,!0,!0)},get size(){return Kl(this,!0)},has(n){return ql.call(this,n,!0)},add:xt("add"),set:xt("set"),delete:xt("delete"),clear:xt("clear"),forEach:Gl(!0,!0)};return["keys","values","entries",Symbol.iterator].forEach(n=>{e[n]=Ql(n,!1,!1),l[n]=Ql(n,!0,!1),t[n]=Ql(n,!1,!0),i[n]=Ql(n,!0,!0)}),[e,l,t,i]}const[Os,Fs,zs,Ds]=ws();function Eo(e,t){const l=t?e?Ds:zs:e?Fs:Os;return(i,o,n)=>o==="__v_isReactive"?!e:o==="__v_isReadonly"?e:o==="__v_raw"?i:Reflect.get(de(l,o)&&o in i?l:i,o,n)}const Hs={get:Eo(!1,!1)},Ms={get:Eo(!1,!0)},Ss={get:Eo(!0,!1)},Rr=new WeakMap,Cr=new WeakMap,Pr=new WeakMap,Vs=new WeakMap;function Ns(e){switch(e){case"Object":case"Array":return 1;case"Map":case"Set":case"WeakMap":case"WeakSet":return 2;default:return 0}}function js(e){return e.__v_skip||!Object.isExtensible(e)?0:Ns(cs(e))}function gl(e){return Ol(e)?e:Co(e,!1,Er,Hs,Rr)}function $s(e){return Co(e,!1,Is,Ms,Cr)}function Ro(e){return Co(e,!0,Ts,Ss,Pr)}function Co(e,t,l,i,o){if(!Oe(e)||e.__v_raw&&!(t&&e.__v_isReactive))return e;const n=o.get(e);if(n)return n;const r=js(e);if(r===0)return e;const a=new Proxy(e,r===2?i:l);return o.set(e,a),a}function sl(e){return Ol(e)?sl(e.__v_raw):!!(e&&e.__v_isReactive)}function Ol(e){return!!(e&&e.__v_isReadonly)}function Gi(e){return!!(e&&e.__v_isShallow)}function Lr(e){return sl(e)||Ol(e)}function ke(e){const t=e&&e.__v_raw;return t?ke(t):e}function Ar(e){return ni(e,"__v_skip",!0),e}const Fl=e=>Oe(e)?gl(e):e,Po=e=>Oe(e)?Ro(e):e;function Tr(e){It&&nt&&(e=ke(e),_r(e.dep||(e.dep=bo())))}function Ir(e,t){e=ke(e),e.dep&&Ki(e.dep)}function De(e){return!!(e&&e.__v_isRef===!0)}function ye(e){return Or(e,!1)}function wr(e){return Or(e,!0)}function Or(e,t){return De(e)?e:new Ys(e,t)}class Ys{constructor(t,l){this.__v_isShallow=l,this.dep=void 0,this.__v_isRef=!0,this._rawValue=l?t:ke(t),this._value=l?t:Fl(t)}get value(){return Tr(this),this._value}set value(t){t=this.__v_isShallow?t:ke(t),wl(t,this._rawValue)&&(this._rawValue=t,this._value=this.__v_isShallow?t:Fl(t),Ir(this))}}function O(e){return De(e)?e.value:e}const Bs={get:(e,t,l)=>O(Reflect.get(e,t,l)),set:(e,t,l,i)=>{const o=e[t];return De(o)&&!De(l)?(o.value=l,!0):Reflect.set(e,t,l,i)}};function Fr(e){return sl(e)?e:new Proxy(e,Bs)}function Ei(e){const t=te(e)?new Array(e.length):{};for(const l in e)t[l]=Ws(e,l);return t}class Us{constructor(t,l,i){this._object=t,this._key=l,this._defaultValue=i,this.__v_isRef=!0}get value(){const t=this._object[this._key];return t===void 0?this._defaultValue:t}set value(t){this._object[this._key]=t}}function Ws(e,t,l){const i=e[t];return De(i)?i:new Us(e,t,l)}class Xs{constructor(t,l,i,o){this._setter=l,this.dep=void 0,this.__v_isRef=!0,this._dirty=!0,this.effect=new _o(t,()=>{this._dirty||(this._dirty=!0,Ir(this))}),this.effect.computed=this,this.effect.active=this._cacheable=!o,this.__v_isReadonly=i}get value(){const t=ke(this);return Tr(t),(t._dirty||!t._cacheable)&&(t._dirty=!1,t._value=t.effect.run()),t._value}set value(t){this._setter(t)}}function qs(e,t,l=!1){let i,o;const n=re(e);return n?(i=e,o=at):(i=e.get,o=e.set),new Xs(i,o,n||!o,l)}function wt(e,t,l,i){let o;try{o=i?e(...i):e()}catch(n){Nl(n,t,l)}return o}function lt(e,t,l,i){if(re(e)){const n=wt(e,t,l,i);return n&&pr(n)&&n.catch(r=>{Nl(r,t,l)}),n}const o=[];for(let n=0;n>>1;zl(qe[i])ft&&qe.splice(t,1)}function Hr(e,t,l,i){te(e)?l.push(...e):(!t||!t.includes(e,e.allowRecurse?i+1:i))&&l.push(e),Dr()}function Zs(e){Hr(e,El,Cl,il)}function Js(e){Hr(e,Pt,Pl,ol)}function Ri(e,t=null){if(Cl.length){for(Zi=t,El=[...new Set(Cl)],Cl.length=0,il=0;ilzl(l)-zl(i)),ol=0;ole.id==null?1/0:e.id;function Mr(e){Qi=!1,ri=!0,Ri(e),qe.sort((l,i)=>zl(l)-zl(i));const t=at;try{for(ft=0;ftg.trim())),p&&(o=l.map(gr))}let a,s=i[a=Oi(t)]||i[a=Oi(ut(t))];!s&&n&&(s=i[a=Oi(Zt(t))]),s&<(s,e,6,o);const c=i[a+"Once"];if(c){if(!e.emitted)e.emitted={};else if(e.emitted[a])return;e.emitted[a]=!0,lt(c,e,6,o)}}function Sr(e,t,l=!1){const i=t.emitsCache,o=i.get(e);if(o!==void 0)return o;const n=e.emits;let r={},a=!1;if(!re(e)){const s=c=>{const h=Sr(c,t,!0);h&&(a=!0,Se(r,h))};!l&&t.mixins.length&&t.mixins.forEach(s),e.extends&&s(e.extends),e.mixins&&e.mixins.forEach(s)}return!n&&!a?(i.set(e,null),null):(te(n)?n.forEach(s=>r[s]=null):Se(r,n),i.set(e,r),r)}function Ci(e,t){return!e||!Vl(t)?!1:(t=t.slice(2).replace(/Once$/,""),de(e,t[0].toLowerCase()+t.slice(1))||de(e,Zt(t))||de(e,t))}let Ve=null,Vr=null;function si(e){const t=Ve;return Ve=e,Vr=e&&e.type.__scopeId||null,t}function Me(e,t=Ve,l){if(!t||e._n)return e;const i=(...o)=>{i._d&&pn(-1);const n=si(t),r=e(...o);return si(n),i._d&&pn(1),r};return i._n=!0,i._c=!0,i._d=!0,i}function zi(e){const{type:t,vnode:l,proxy:i,withProxy:o,props:n,propsOptions:[r],slots:a,attrs:s,emit:c,render:h,renderCache:p,data:m,setupState:g,ctx:x,inheritAttrs:P}=e;let E,k;const b=si(e);try{if(l.shapeFlag&4){const M=o||i;E=ot(h.call(M,M,p,n,g,m,x)),k=s}else{const M=t;E=ot(M.length>1?M(n,{attrs:s,slots:a,emit:c}):M(n,null)),k=t.props?s:tc(s)}}catch(M){Al.length=0,Nl(M,e,1),E=oe(Ge)}let L=E;if(k&&P!==!1){const M=Object.keys(k),{shapeFlag:U}=L;M.length&&U&7&&(r&&M.some(fo)&&(k=lc(k,r)),L=Dt(L,k))}return l.dirs&&(L=Dt(L),L.dirs=L.dirs?L.dirs.concat(l.dirs):l.dirs),l.transition&&(L.transition=l.transition),E=L,si(b),E}const tc=e=>{let t;for(const l in e)(l==="class"||l==="style"||Vl(l))&&((t||(t={}))[l]=e[l]);return t},lc=(e,t)=>{const l={};for(const i in e)(!fo(i)||!(i.slice(9)in t))&&(l[i]=e[i]);return l};function ic(e,t,l){const{props:i,children:o,component:n}=e,{props:r,children:a,patchFlag:s}=t,c=n.emitsOptions;if(t.dirs||t.transition)return!0;if(l&&s>=0){if(s&1024)return!0;if(s&16)return i?ln(i,r,c):!!r;if(s&8){const h=t.dynamicProps;for(let p=0;pe.__isSuspense;function Nr(e,t){t&&t.pendingBranch?te(e)?t.effects.push(...e):t.effects.push(e):Js(e)}function Gt(e,t){if(Fe){let l=Fe.provides;const i=Fe.parent&&Fe.parent.provides;i===l&&(l=Fe.provides=Object.create(i)),l[e]=t}}function He(e,t,l=!1){const i=Fe||Ve;if(i){const o=i.parent==null?i.vnode.appContext&&i.vnode.appContext.provides:i.parent.provides;if(o&&e in o)return o[e];if(arguments.length>1)return l&&re(t)?t.call(i.proxy):t}}const on={};function dt(e,t,l){return jr(e,t,l)}function jr(e,t,{immediate:l,deep:i,flush:o,onTrack:n,onTrigger:r}=Re){const a=Fe;let s,c=!1,h=!1;if(De(e)?(s=()=>e.value,c=Gi(e)):sl(e)?(s=()=>e,i=!0):te(e)?(h=!0,c=e.some(k=>sl(k)||Gi(k)),s=()=>e.map(k=>{if(De(k))return k.value;if(sl(k))return qt(k);if(re(k))return wt(k,a,2)})):re(e)?t?s=()=>wt(e,a,2):s=()=>{if(!(a&&a.isUnmounted))return p&&p(),lt(e,a,3,[m])}:s=at,t&&i){const k=s;s=()=>qt(k())}let p,m=k=>{p=E.onStop=()=>{wt(k,a,4)}};if(dl)return m=at,t?l&<(t,a,3,[s(),h?[]:void 0,m]):s(),at;let g=h?[]:on;const x=()=>{if(!!E.active)if(t){const k=E.run();(i||c||(h?k.some((b,L)=>wl(b,g[L])):wl(k,g)))&&(p&&p(),lt(t,a,3,[k,g===on?void 0:g,m]),g=k)}else E.run()};x.allowRecurse=!!t;let P;o==="sync"?P=x:o==="post"?P=()=>Be(x,a&&a.suspense):P=()=>Zs(x);const E=new _o(s,P);return t?l?x():g=E.run():o==="post"?Be(E.run.bind(E),a&&a.suspense):E.run(),()=>{E.stop(),a&&a.scope&&go(a.scope.effects,E)}}function rc(e,t,l){const i=this.proxy,o=be(e)?e.includes(".")?$r(i,e):()=>i[e]:e.bind(i,i);let n;re(t)?n=t:(n=t.handler,l=t);const r=Fe;hl(this);const a=jr(o,n.bind(i),l);return r?hl(r):Qt(),a}function $r(e,t){const l=t.split(".");return()=>{let i=e;for(let o=0;o{qt(l,t)});else if(fr(e))for(const l in e)qt(e[l],t);return e}function ac(){const e={isMounted:!1,isLeaving:!1,isUnmounting:!1,leavingVNodes:new Map};return Ze(()=>{e.isMounted=!0}),Yl(()=>{e.isUnmounting=!0}),e}const et=[Function,Array],sc={name:"BaseTransition",props:{mode:String,appear:Boolean,persisted:Boolean,onBeforeEnter:et,onEnter:et,onAfterEnter:et,onEnterCancelled:et,onBeforeLeave:et,onLeave:et,onAfterLeave:et,onLeaveCancelled:et,onBeforeAppear:et,onAppear:et,onAfterAppear:et,onAppearCancelled:et},setup(e,{slots:t}){const l=wo(),i=ac();let o;return()=>{const n=t.default&&Ur(t.default(),!0);if(!n||!n.length)return;let r=n[0];if(n.length>1){for(const P of n)if(P.type!==Ge){r=P;break}}const a=ke(e),{mode:s}=a;if(i.isLeaving)return Di(r);const c=nn(r);if(!c)return Di(r);const h=Ji(c,a,i,l);eo(c,h);const p=l.subTree,m=p&&nn(p);let g=!1;const{getTransitionKey:x}=c.type;if(x){const P=x();o===void 0?o=P:P!==o&&(o=P,g=!0)}if(m&&m.type!==Ge&&(!Wt(c,m)||g)){const P=Ji(m,a,i,l);if(eo(m,P),s==="out-in")return i.isLeaving=!0,P.afterLeave=()=>{i.isLeaving=!1,l.update()},Di(r);s==="in-out"&&c.type!==Ge&&(P.delayLeave=(E,k,b)=>{const L=Br(i,m);L[String(m.key)]=m,E._leaveCb=()=>{k(),E._leaveCb=void 0,delete h.delayedLeave},h.delayedLeave=b})}return r}}},Yr=sc;function Br(e,t){const{leavingVNodes:l}=e;let i=l.get(t.type);return i||(i=Object.create(null),l.set(t.type,i)),i}function Ji(e,t,l,i){const{appear:o,mode:n,persisted:r=!1,onBeforeEnter:a,onEnter:s,onAfterEnter:c,onEnterCancelled:h,onBeforeLeave:p,onLeave:m,onAfterLeave:g,onLeaveCancelled:x,onBeforeAppear:P,onAppear:E,onAfterAppear:k,onAppearCancelled:b}=t,L=String(e.key),M=Br(l,e),U=(v,q)=>{v&<(v,i,9,q)},ee=(v,q)=>{const B=q[1];U(v,q),te(v)?v.every(G=>G.length<=1)&&B():v.length<=1&&B()},w={mode:n,persisted:r,beforeEnter(v){let q=a;if(!l.isMounted)if(o)q=P||a;else return;v._leaveCb&&v._leaveCb(!0);const B=M[L];B&&Wt(e,B)&&B.el._leaveCb&&B.el._leaveCb(),U(q,[v])},enter(v){let q=s,B=c,G=h;if(!l.isMounted)if(o)q=E||s,B=k||c,G=b||h;else return;let R=!1;const S=v._enterCb=F=>{R||(R=!0,F?U(G,[v]):U(B,[v]),w.delayedLeave&&w.delayedLeave(),v._enterCb=void 0)};q?ee(q,[v,S]):S()},leave(v,q){const B=String(e.key);if(v._enterCb&&v._enterCb(!0),l.isUnmounting)return q();U(p,[v]);let G=!1;const R=v._leaveCb=S=>{G||(G=!0,q(),S?U(x,[v]):U(g,[v]),v._leaveCb=void 0,M[B]===e&&delete M[B])};M[B]=e,m?ee(m,[v,R]):R()},clone(v){return Ji(v,t,l,i)}};return w}function Di(e){if($l(e))return e=Dt(e),e.children=null,e}function nn(e){return $l(e)?e.children?e.children[0]:void 0:e}function eo(e,t){e.shapeFlag&6&&e.component?eo(e.component.subTree,t):e.shapeFlag&128?(e.ssContent.transition=t.clone(e.ssContent),e.ssFallback.transition=t.clone(e.ssFallback)):e.transition=t}function Ur(e,t=!1,l){let i=[],o=0;for(let n=0;n1)for(let n=0;n!!e.type.__asyncLoader;function _(e){re(e)&&(e={loader:e});const{loader:t,loadingComponent:l,errorComponent:i,delay:o=200,timeout:n,suspensible:r=!0,onError:a}=e;let s=null,c,h=0;const p=()=>(h++,s=null,m()),m=()=>{let g;return s||(g=s=t().catch(x=>{if(x=x instanceof Error?x:new Error(String(x)),a)return new Promise((P,E)=>{a(x,()=>P(p()),()=>E(x),h+1)});throw x}).then(x=>g!==s&&s?s:(x&&(x.__esModule||x[Symbol.toStringTag]==="Module")&&(x=x.default),c=x,x)))};return ue({name:"AsyncComponentWrapper",__asyncLoader:m,get __asyncResolved(){return c},setup(){const g=Fe;if(c)return()=>Hi(c,g);const x=b=>{s=null,Nl(b,g,13,!i)};if(r&&g.suspense||dl)return m().then(b=>()=>Hi(b,g)).catch(b=>(x(b),()=>i?oe(i,{error:b}):null));const P=ye(!1),E=ye(),k=ye(!!o);return o&&setTimeout(()=>{k.value=!1},o),n!=null&&setTimeout(()=>{if(!P.value&&!E.value){const b=new Error(`Async component timed out after ${n}ms.`);x(b),E.value=b}},n),m().then(()=>{P.value=!0,g.parent&&$l(g.parent.vnode)&&Ao(g.parent.update)}).catch(b=>{x(b),E.value=b}),()=>{if(P.value&&c)return Hi(c,g);if(E.value&&i)return oe(i,{error:E.value});if(l&&!k.value)return oe(l)}}})}function Hi(e,{vnode:{ref:t,props:l,children:i,shapeFlag:o},parent:n}){const r=oe(e,l,i);return r.ref=t,r}const $l=e=>e.type.__isKeepAlive;function cc(e,t){Wr(e,"a",t)}function hc(e,t){Wr(e,"da",t)}function Wr(e,t,l=Fe){const i=e.__wdc||(e.__wdc=()=>{let o=l;for(;o;){if(o.isDeactivated)return;o=o.parent}return e()});if(Pi(t,i,l),l){let o=l.parent;for(;o&&o.parent;)$l(o.parent.vnode)&&dc(i,t,l,o),o=o.parent}}function dc(e,t,l,i){const o=Pi(t,e,i,!0);Li(()=>{go(i[t],o)},l)}function Pi(e,t,l=Fe,i=!1){if(l){const o=l[e]||(l[e]=[]),n=t.__weh||(t.__weh=(...r)=>{if(l.isUnmounted)return;ml(),hl(l);const a=lt(t,l,e,r);return Qt(),fl(),a});return i?o.unshift(n):o.push(n),n}}const yt=e=>(t,l=Fe)=>(!dl||e==="sp")&&Pi(e,t,l),Xr=yt("bm"),Ze=yt("m"),uc=yt("bu"),pc=yt("u"),Yl=yt("bum"),Li=yt("um"),mc=yt("sp"),fc=yt("rtg"),gc=yt("rtc");function kc(e,t=Fe){Pi("ec",e,t)}function ci(e,t){const l=Ve;if(l===null)return e;const i=Ti(l)||l.proxy,o=e.dirs||(e.dirs=[]);for(let n=0;nt(r,a,void 0,n&&n[a]));else{const r=Object.keys(e);o=new Array(r.length);for(let a=0,s=r.length;api(t)?!(t.type===Ge||t.type===Pe&&!Kr(t.children)):!0)?e:null}const to=e=>e?aa(e)?Ti(e)||e.proxy:to(e.parent):null,hi=Se(Object.create(null),{$:e=>e,$el:e=>e.vnode.el,$data:e=>e.data,$props:e=>e.props,$attrs:e=>e.attrs,$slots:e=>e.slots,$refs:e=>e.refs,$parent:e=>to(e.parent),$root:e=>to(e.root),$emit:e=>e.emit,$options:e=>Qr(e),$forceUpdate:e=>e.f||(e.f=()=>Ao(e.update)),$nextTick:e=>e.n||(e.n=jl.bind(e.proxy)),$watch:e=>rc.bind(e)}),_c={get({_:e},t){const{ctx:l,setupState:i,data:o,props:n,accessCache:r,type:a,appContext:s}=e;let c;if(t[0]!=="$"){const g=r[t];if(g!==void 0)switch(g){case 1:return i[t];case 2:return o[t];case 4:return l[t];case 3:return n[t]}else{if(i!==Re&&de(i,t))return r[t]=1,i[t];if(o!==Re&&de(o,t))return r[t]=2,o[t];if((c=e.propsOptions[0])&&de(c,t))return r[t]=3,n[t];if(l!==Re&&de(l,t))return r[t]=4,l[t];lo&&(r[t]=0)}}const h=hi[t];let p,m;if(h)return t==="$attrs"&&Qe(e,"get",t),h(e);if((p=a.__cssModules)&&(p=p[t]))return p;if(l!==Re&&de(l,t))return r[t]=4,l[t];if(m=s.config.globalProperties,de(m,t))return m[t]},set({_:e},t,l){const{data:i,setupState:o,ctx:n}=e;return o!==Re&&de(o,t)?(o[t]=l,!0):i!==Re&&de(i,t)?(i[t]=l,!0):de(e.props,t)||t[0]==="$"&&t.slice(1)in e?!1:(n[t]=l,!0)},has({_:{data:e,setupState:t,accessCache:l,ctx:i,appContext:o,propsOptions:n}},r){let a;return!!l[r]||e!==Re&&de(e,r)||t!==Re&&de(t,r)||(a=n[0])&&de(a,r)||de(i,r)||de(hi,r)||de(o.config.globalProperties,r)},defineProperty(e,t,l){return l.get!=null?e._.accessCache[t]=0:de(l,"value")&&this.set(e,t,l.value,null),Reflect.defineProperty(e,t,l)}};let lo=!0;function yc(e){const t=Qr(e),l=e.proxy,i=e.ctx;lo=!1,t.beforeCreate&&an(t.beforeCreate,e,"bc");const{data:o,computed:n,methods:r,watch:a,provide:s,inject:c,created:h,beforeMount:p,mounted:m,beforeUpdate:g,updated:x,activated:P,deactivated:E,beforeDestroy:k,beforeUnmount:b,destroyed:L,unmounted:M,render:U,renderTracked:ee,renderTriggered:w,errorCaptured:v,serverPrefetch:q,expose:B,inheritAttrs:G,components:R,directives:S,filters:F}=t;if(c&&xc(c,i,null,e.appContext.config.unwrapInjectedRef),r)for(const le in r){const se=r[le];re(se)&&(i[le]=se.bind(l))}if(o){const le=o.call(l,l);Oe(le)&&(e.data=gl(le))}if(lo=!0,n)for(const le in n){const se=n[le],Ie=re(se)?se.bind(l,l):re(se.get)?se.get.bind(l,l):at,Ne=!re(se)&&re(se.set)?se.set.bind(l):at,Ue=Y({get:Ie,set:Ne});Object.defineProperty(i,le,{enumerable:!0,configurable:!0,get:()=>Ue.value,set:Je=>Ue.value=Je})}if(a)for(const le in a)Gr(a[le],i,l,le);if(s){const le=re(s)?s.call(l):s;Reflect.ownKeys(le).forEach(se=>{Gt(se,le[se])})}h&&an(h,e,"c");function j(le,se){te(se)?se.forEach(Ie=>le(Ie.bind(l))):se&&le(se.bind(l))}if(j(Xr,p),j(Ze,m),j(uc,g),j(pc,x),j(cc,P),j(hc,E),j(kc,v),j(gc,ee),j(fc,w),j(Yl,b),j(Li,M),j(mc,q),te(B))if(B.length){const le=e.exposed||(e.exposed={});B.forEach(se=>{Object.defineProperty(le,se,{get:()=>l[se],set:Ie=>l[se]=Ie})})}else e.exposed||(e.exposed={});U&&e.render===at&&(e.render=U),G!=null&&(e.inheritAttrs=G),R&&(e.components=R),S&&(e.directives=S)}function xc(e,t,l=at,i=!1){te(e)&&(e=io(e));for(const o in e){const n=e[o];let r;Oe(n)?"default"in n?r=He(n.from||o,n.default,!0):r=He(n.from||o):r=He(n),De(r)&&i?Object.defineProperty(t,o,{enumerable:!0,configurable:!0,get:()=>r.value,set:a=>r.value=a}):t[o]=r}}function an(e,t,l){lt(te(e)?e.map(i=>i.bind(t.proxy)):e.bind(t.proxy),t,l)}function Gr(e,t,l,i){const o=i.includes(".")?$r(l,i):()=>l[i];if(be(e)){const n=t[e];re(n)&&dt(o,n)}else if(re(e))dt(o,e.bind(l));else if(Oe(e))if(te(e))e.forEach(n=>Gr(n,t,l,i));else{const n=re(e.handler)?e.handler.bind(l):t[e.handler];re(n)&&dt(o,n,e)}}function Qr(e){const t=e.type,{mixins:l,extends:i}=t,{mixins:o,optionsCache:n,config:{optionMergeStrategies:r}}=e.appContext,a=n.get(t);let s;return a?s=a:!o.length&&!l&&!i?s=t:(s={},o.length&&o.forEach(c=>di(s,c,r,!0)),di(s,t,r)),n.set(t,s),s}function di(e,t,l,i=!1){const{mixins:o,extends:n}=t;n&&di(e,n,l,!0),o&&o.forEach(r=>di(e,r,l,!0));for(const r in t)if(!(i&&r==="expose")){const a=Ec[r]||l&&l[r];e[r]=a?a(e[r],t[r]):t[r]}return e}const Ec={data:sn,props:Yt,emits:Yt,methods:Yt,computed:Yt,beforeCreate:je,created:je,beforeMount:je,mounted:je,beforeUpdate:je,updated:je,beforeDestroy:je,beforeUnmount:je,destroyed:je,unmounted:je,activated:je,deactivated:je,errorCaptured:je,serverPrefetch:je,components:Yt,directives:Yt,watch:Cc,provide:sn,inject:Rc};function sn(e,t){return t?e?function(){return Se(re(e)?e.call(this,this):e,re(t)?t.call(this,this):t)}:t:e}function Rc(e,t){return Yt(io(e),io(t))}function io(e){if(te(e)){const t={};for(let l=0;l0)&&!(r&16)){if(r&8){const h=e.vnode.dynamicProps;for(let p=0;p{s=!0;const[m,g]=Jr(p,t,!0);Se(r,m),g&&a.push(...g)};!l&&t.mixins.length&&t.mixins.forEach(h),e.extends&&h(e.extends),e.mixins&&e.mixins.forEach(h)}if(!n&&!s)return i.set(e,rl),rl;if(te(n))for(let h=0;h-1,g[1]=P<0||x-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{ee=ee||!!b.dynamicChildren;const{type:w,props:v,patchFlag:q,shapeFlag:B,dirs:G}=b,R=w==="input"&&G||w==="option";if(R||q!==-1){if(G&&ht(b,null,L,"created"),v)if(R||!ee||q&48)for(const F in v)(R&&F.endsWith("value")||Vl(F)&&!Rl(F))&&i(k,F,null,v[F],!1,void 0,L);else v.onClick&&i(k,"onClick",null,v.onClick,!1,void 0,L);let S;if((S=v&&v.onVnodeBeforeMount)&&tt(S,L,b),G&&ht(b,null,L,"beforeMount"),((S=v&&v.onVnodeMounted)||G)&&Nr(()=>{S&&tt(S,L,b),G&&ht(b,null,L,"mounted")},M),B&16&&!(v&&(v.innerHTML||v.textContent))){let F=g(k.firstChild,b,k,L,M,U,ee);for(;F;){Et=!0;const ae=F;F=F.nextSibling,a(ae)}}else B&8&&k.textContent!==b.children&&(Et=!0,k.textContent=b.children)}return k.nextSibling},g=(k,b,L,M,U,ee,w)=>{w=w||!!b.dynamicChildren;const v=b.children,q=v.length;for(let B=0;B{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{for(let I=V;I{const D=f.el=u.el;let{patchFlag:V,dynamicChildren:I,dirs:Q}=f;V|=u.patchFlag&16;const K=u.props||Re,Z=f.props||Re;let ne;y&&Nt(y,!1),(ne=Z.onVnodeBeforeUpdate)&&tt(ne,y,f,u),Q&&ht(f,u,y,"beforeUpdate"),y&&Nt(y,!0);const pe=A&&f.type!=="foreignObject";if(I?G(u.dynamicChildren,I,D,y,T,pe,z):$||Ie(u,f,D,null,y,T,pe,z,!1),V>0){if(V&16)R(D,f,K,Z,y,T,A);else if(V&2&&K.class!==Z.class&&n(D,"class",null,Z.class,A),V&4&&n(D,"style",K.style,Z.style,A),V&8){const xe=f.dynamicProps;for(let Ee=0;Ee{ne&&tt(ne,y,f,u),Q&&ht(f,u,y,"updated")},T)},G=(u,f,y,T,A,z,$)=>{for(let D=0;D{if(y!==T){for(const D in T){if(Rl(D))continue;const V=T[D],I=y[D];V!==I&&D!=="value"&&n(u,D,I,V,$,f.children,A,z,H)}if(y!==Re)for(const D in y)!Rl(D)&&!(D in T)&&n(u,D,y[D],null,$,f.children,A,z,H);"value"in T&&n(u,"value",y.value,T.value)}},S=(u,f,y,T,A,z,$,D,V)=>{const I=f.el=u?u.el:a(""),Q=f.anchor=u?u.anchor:a("");let{patchFlag:K,dynamicChildren:Z,slotScopeIds:ne}=f;ne&&(D=D?D.concat(ne):ne),u==null?(i(I,y,T),i(Q,y,T),q(f.children,y,Q,A,z,$,D,V)):K>0&&K&64&&Z&&u.dynamicChildren?(G(u.dynamicChildren,Z,y,A,z,$,D),(f.key!=null||A&&f===A.subTree)&&oa(u,f,!0)):Ie(u,f,y,Q,A,z,$,D,V)},F=(u,f,y,T,A,z,$,D,V)=>{f.slotScopeIds=D,u==null?f.shapeFlag&512?A.ctx.activate(f,y,T,$,V):ae(f,y,T,A,z,$,V):j(u,f,V)},ae=(u,f,y,T,A,z,$)=>{const D=u.component=Bc(u,T,A);if($l(u)&&(D.ctx.renderer=_e),Uc(D),D.asyncDep){if(A&&A.registerDep(D,le),!u.el){const V=D.subTree=oe(Ge);b(null,V,f,y)}return}le(D,u,f,y,A,z,$)},j=(u,f,y)=>{const T=f.component=u.component;if(ic(u,f,y))if(T.asyncDep&&!T.asyncResolved){se(T,f,y);return}else T.next=f,Qs(T.update),T.update();else f.el=u.el,T.vnode=f},le=(u,f,y,T,A,z,$)=>{const D=()=>{if(u.isMounted){let{next:Q,bu:K,u:Z,parent:ne,vnode:pe}=u,xe=Q,Ee;Nt(u,!1),Q?(Q.el=pe.el,se(u,Q,$)):Q=pe,K&&Fi(K),(Ee=Q.props&&Q.props.onVnodeBeforeUpdate)&&tt(Ee,ne,Q,pe),Nt(u,!0);const Le=zi(u),it=u.subTree;u.subTree=Le,E(it,Le,p(it.el),X(it),u,A,z),Q.el=Le.el,xe===null&&oc(u,Le.el),Z&&Be(Z,A),(Ee=Q.props&&Q.props.onVnodeUpdated)&&Be(()=>tt(Ee,ne,Q,pe),A)}else{let Q;const{el:K,props:Z}=f,{bm:ne,m:pe,parent:xe}=u,Ee=cl(f);if(Nt(u,!1),ne&&Fi(ne),!Ee&&(Q=Z&&Z.onVnodeBeforeMount)&&tt(Q,xe,f),Nt(u,!0),K&&ie){const Le=()=>{u.subTree=zi(u),ie(K,u.subTree,u,A,null)};Ee?f.type.__asyncLoader().then(()=>!u.isUnmounted&&Le()):Le()}else{const Le=u.subTree=zi(u);E(null,Le,y,T,u,A,z),f.el=Le.el}if(pe&&Be(pe,A),!Ee&&(Q=Z&&Z.onVnodeMounted)){const Le=f;Be(()=>tt(Q,xe,Le),A)}(f.shapeFlag&256||xe&&cl(xe.vnode)&&xe.vnode.shapeFlag&256)&&u.a&&Be(u.a,A),u.isMounted=!0,f=y=T=null}},V=u.effect=new _o(D,()=>Ao(I),u.scope),I=u.update=()=>V.run();I.id=u.uid,Nt(u,!0),I()},se=(u,f,y)=>{f.component=u;const T=u.vnode.props;u.vnode=f,u.next=null,Lc(u,f.props,T,y),Ic(u,f.children,y),ml(),Ri(void 0,u.update),fl()},Ie=(u,f,y,T,A,z,$,D,V=!1)=>{const I=u&&u.children,Q=u?u.shapeFlag:0,K=f.children,{patchFlag:Z,shapeFlag:ne}=f;if(Z>0){if(Z&128){Ue(I,K,y,T,A,z,$,D,V);return}else if(Z&256){Ne(I,K,y,T,A,z,$,D,V);return}}ne&8?(Q&16&&H(I,A,z),K!==I&&h(y,K)):Q&16?ne&16?Ue(I,K,y,T,A,z,$,D,V):H(I,A,z,!0):(Q&8&&h(y,""),ne&16&&q(K,y,T,A,z,$,D,V))},Ne=(u,f,y,T,A,z,$,D,V)=>{u=u||rl,f=f||rl;const I=u.length,Q=f.length,K=Math.min(I,Q);let Z;for(Z=0;ZQ?H(u,A,z,!0,!1,K):q(f,y,T,A,z,$,D,V,K)},Ue=(u,f,y,T,A,z,$,D,V)=>{let I=0;const Q=f.length;let K=u.length-1,Z=Q-1;for(;I<=K&&I<=Z;){const ne=u[I],pe=f[I]=V?Lt(f[I]):ot(f[I]);if(Wt(ne,pe))E(ne,pe,y,null,A,z,$,D,V);else break;I++}for(;I<=K&&I<=Z;){const ne=u[K],pe=f[Z]=V?Lt(f[Z]):ot(f[Z]);if(Wt(ne,pe))E(ne,pe,y,null,A,z,$,D,V);else break;K--,Z--}if(I>K){if(I<=Z){const ne=Z+1,pe=neZ)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=it){Ye(We,A,z,!0);continue}let ct;if(We.key!=null)ct=xe.get(We.key);else for(Ee=pe;Ee<=Z;Ee++)if(kl[Ee-pe]===0&&Wt(We,f[Ee])){ct=Ee;break}ct===void 0?Ye(We,A,z,!0):(kl[ct-pe]=I+1,ct>=Bo?Bo=ct:el=!0,E(We,f[ct],y,null,A,z,$,D,V),Le++)}const Uo=el?Hc(kl):rl;for(Ee=Uo.length-1,I=it-1;I>=0;I--){const We=pe+I,ct=f[We],Wo=We+1{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;KD.enter(z),A);else{const{leave:K,delayLeave:Z,afterLeave:ne}=D,pe=()=>i(z,f,y),xe=()=>{K(z,()=>{pe(),ne&&ne()})};Z?Z(z,pe,xe):xe()}else i(z,f,y)},Ye=(u,f,y,T=!1,A=!1)=>{const{type:z,props:$,ref:D,children:V,dynamicChildren:I,shapeFlag:Q,patchFlag:K,dirs:Z}=u;if(D!=null&&ui(D,null,y,u,!0),Q&256){f.ctx.deactivate(u);return}const ne=Q&1&&Z,pe=!cl(u);let xe;if(pe&&(xe=$&&$.onVnodeBeforeUnmount)&&tt(xe,f,u),Q&6)W(u.component,y,T);else{if(Q&128){u.suspense.unmount(y,T);return}ne&&ht(u,null,f,"beforeUnmount"),Q&64?u.type.remove(u,f,y,A,_e,T):I&&(z!==Pe||K>0&&K&64)?H(I,f,y,!1,!0):(z===Pe&&K&384||!A&&Q&16)&&H(V,f,y),T&&Vt(u)}(pe&&(xe=$&&$.onVnodeUnmounted)||ne)&&Be(()=>{xe&&tt(xe,f,u),ne&&ht(u,null,f,"unmounted")},y)},Vt=u=>{const{type:f,el:y,anchor:T,transition:A}=u;if(f===Pe){C(y,T);return}if(f===Ll){U(u);return}const z=()=>{o(y),A&&!A.persisted&&A.afterLeave&&A.afterLeave()};if(u.shapeFlag&1&&A&&!A.persisted){const{leave:$,delayLeave:D}=A,V=()=>$(y,z);D?D(u.el,z,V):V()}else z()},C=(u,f)=>{let y;for(;u!==f;)y=m(u),o(u),u=y;o(f)},W=(u,f,y)=>{const{bum:T,scope:A,update:z,subTree:$,um:D}=u;T&&Fi(T),A.stop(),z&&(z.active=!1,Ye($,u,f,y)),D&&Be(D,f),Be(()=>{u.isUnmounted=!0},f),f&&f.pendingBranch&&!f.isUnmounted&&u.asyncDep&&!u.asyncResolved&&u.suspenseId===f.pendingId&&(f.deps--,f.deps===0&&f.resolve())},H=(u,f,y,T=!1,A=!1,z=0)=>{for(let $=z;$u.shapeFlag&6?X(u.component.subTree):u.shapeFlag&128?u.suspense.next():m(u.anchor||u.el),ge=(u,f,y)=>{u==null?f._vnode&&Ye(f._vnode,null,null,!0):E(f._vnode||null,u,f,null,null,null,y),ai(),f._vnode=u},_e={p:E,um:Ye,m:Je,r:Vt,mt:ae,mc:q,pc:Ie,pbc:G,n:X,o:e};let ce,ie;return t&&([ce,ie]=t(_e)),{render:ge,hydrate:ce,createApp:Oc(ge,ce)}}function Nt({effect:e,update:t},l){e.allowRecurse=t.allowRecurse=l}function oa(e,t,l=!1){const i=e.children,o=t.children;if(te(i)&&te(o))for(let n=0;n>1,e[l[a]]0&&(t[i]=l[n-1]),l[n]=i)}}for(n=l.length,r=l[n-1];n-- >0;)l[n]=r,r=t[r];return l}const Mc=e=>e.__isTeleport,Pe=Symbol(void 0),Dl=Symbol(void 0),Ge=Symbol(void 0),Ll=Symbol(void 0),Al=[];let rt=null;function N(e=!1){Al.push(rt=e?null:[])}function Sc(){Al.pop(),rt=Al[Al.length-1]||null}let Hl=1;function pn(e){Hl+=e}function na(e){return e.dynamicChildren=Hl>0?rt||rl:null,Sc(),Hl>0&&rt&&rt.push(e),e}function J(e,t,l,i,o,n){return na(fe(e,t,l,i,o,n,!0))}function we(e,t,l,i,o){return na(oe(e,t,l,i,o,!0))}function pi(e){return e?e.__v_isVNode===!0:!1}function Wt(e,t){return e.type===t.type&&e.key===t.key}const Ai="__vInternal",ra=({key:e})=>e!=null?e:null,li=({ref:e,ref_key:t,ref_for:l})=>e!=null?be(e)||De(e)||re(e)?{i:Ve,r:e,k:t,f:!!l}:e:null;function fe(e,t=null,l=null,i=0,o=null,n=e===Pe?0:1,r=!1,a=!1){const s={__v_isVNode:!0,__v_skip:!0,type:e,props:t,key:t&&ra(t),ref:t&&li(t),scopeId:Vr,slotScopeIds:null,children:l,component:null,suspense:null,ssContent:null,ssFallback:null,dirs:null,transition:null,el:null,anchor:null,target:null,targetAnchor:null,staticCount:0,shapeFlag:n,patchFlag:i,dynamicProps:o,dynamicChildren:null,appContext:null};return a?(Io(s,l),n&128&&e.normalize(s)):l&&(s.shapeFlag|=be(l)?8:16),Hl>0&&!r&&rt&&(s.patchFlag>0||n&6)&&s.patchFlag!==32&&rt.push(s),s}const oe=Vc;function Vc(e,t=null,l=null,i=0,o=null,n=!1){if((!e||e===vc)&&(e=Ge),pi(e)){const a=Dt(e,t,!0);return l&&Io(a,l),Hl>0&&!n&&rt&&(a.shapeFlag&6?rt[rt.indexOf(e)]=a:rt.push(a)),a.patchFlag|=-2,a}if(Gc(e)&&(e=e.__vccOpts),t){t=Nc(t);let{class:a,style:s}=t;a&&!be(a)&&(t.class=Ke(a)),Oe(s)&&(Lr(s)&&!te(s)&&(s=Se({},s)),t.style=Sl(s))}const r=be(e)?1:nc(e)?128:Mc(e)?64:Oe(e)?4:re(e)?2:0;return fe(e,t,l,i,o,r,n,!0)}function Nc(e){return e?Lr(e)||Ai in e?Se({},e):e:null}function Dt(e,t,l=!1){const{props:i,ref:o,patchFlag:n,children:r}=e,a=t?no(i||{},t):i;return{__v_isVNode:!0,__v_skip:!0,type:e.type,props:a,key:a&&ra(a),ref:t&&t.ref?l&&o?te(o)?o.concat(li(t)):[o,li(t)]:li(t):o,scopeId:e.scopeId,slotScopeIds:e.slotScopeIds,children:r,target:e.target,targetAnchor:e.targetAnchor,staticCount:e.staticCount,shapeFlag:e.shapeFlag,patchFlag:t&&e.type!==Pe?n===-1?16:n|16:n,dynamicProps:e.dynamicProps,dynamicChildren:e.dynamicChildren,appContext:e.appContext,dirs:e.dirs,transition:e.transition,component:e.component,suspense:e.suspense,ssContent:e.ssContent&&Dt(e.ssContent),ssFallback:e.ssFallback&&Dt(e.ssFallback),el:e.el,anchor:e.anchor}}function Ht(e=" ",t=0){return oe(Dl,null,e,t)}function jc(e,t){const l=oe(Ll,null,e);return l.staticCount=t,l}function Te(e="",t=!1){return t?(N(),we(Ge,null,e)):oe(Ge,null,e)}function ot(e){return e==null||typeof e=="boolean"?oe(Ge):te(e)?oe(Pe,null,e.slice()):typeof e=="object"?Lt(e):oe(Dl,null,String(e))}function Lt(e){return e.el===null||e.memo?e:Dt(e)}function Io(e,t){let l=0;const{shapeFlag:i}=e;if(t==null)t=null;else if(te(t))l=16;else if(typeof t=="object")if(i&65){const o=t.default;o&&(o._c&&(o._d=!1),Io(e,o()),o._c&&(o._d=!0));return}else{l=32;const o=t._;!o&&!(Ai in t)?t._ctx=Ve:o===3&&Ve&&(Ve.slots._===1?t._=1:(t._=2,e.patchFlag|=1024))}else re(t)?(t={default:t,_ctx:Ve},l=32):(t=String(t),i&64?(l=16,t=[Ht(t)]):l=8);e.children=t,e.shapeFlag|=l}function no(...e){const t={};for(let l=0;lFe||Ve,hl=e=>{Fe=e,e.scope.on()},Qt=()=>{Fe&&Fe.scope.off(),Fe=null};function aa(e){return e.vnode.shapeFlag&4}let dl=!1;function Uc(e,t=!1){dl=t;const{props:l,children:i}=e.vnode,o=aa(e);Pc(e,l,o,t),Tc(e,i);const n=o?Wc(e,t):void 0;return dl=!1,n}function Wc(e,t){const l=e.type;e.accessCache=Object.create(null),e.proxy=Ar(new Proxy(e.ctx,_c));const{setup:i}=l;if(i){const o=e.setupContext=i.length>1?qc(e):null;hl(e),ml();const n=wt(i,e,0,[e.props,o]);if(fl(),Qt(),pr(n)){if(n.then(Qt,Qt),t)return n.then(r=>{mn(e,r,t)}).catch(r=>{Nl(r,e,0)});e.asyncDep=n}else mn(e,n,t)}else sa(e,t)}function mn(e,t,l){re(t)?e.type.__ssrInlineRender?e.ssrRender=t:e.render=t:Oe(t)&&(e.setupState=Fr(t)),sa(e,l)}let fn;function sa(e,t,l){const i=e.type;if(!e.render){if(!t&&fn&&!i.render){const o=i.template;if(o){const{isCustomElement:n,compilerOptions:r}=e.appContext.config,{delimiters:a,compilerOptions:s}=i,c=Se(Se({isCustomElement:n,delimiters:a},r),s);i.render=fn(o,c)}}e.render=i.render||at}hl(e),ml(),yc(e),fl(),Qt()}function Xc(e){return new Proxy(e.attrs,{get(t,l){return Qe(e,"get","$attrs"),t[l]}})}function qc(e){const t=i=>{e.exposed=i||{}};let l;return{get attrs(){return l||(l=Xc(e))},slots:e.slots,emit:e.emit,expose:t}}function Ti(e){if(e.exposed)return e.exposeProxy||(e.exposeProxy=new Proxy(Fr(Ar(e.exposed)),{get(t,l){if(l in t)return t[l];if(l in hi)return hi[l](e)}}))}function Kc(e,t=!0){return re(e)?e.displayName||e.name:e.name||t&&e.__name}function Gc(e){return re(e)&&"__vccOpts"in e}const Y=(e,t)=>qs(e,t,dl);function he(e,t,l){const i=arguments.length;return i===2?Oe(t)&&!te(t)?pi(t)?oe(e,null,[t]):oe(e,t):oe(e,null,t):(i>3?l=Array.prototype.slice.call(arguments,2):i===3&&pi(l)&&(l=[l]),oe(e,t,l))}const Qc="3.2.37",Zc="http://www.w3.org/2000/svg",Xt=typeof document<"u"?document:null,gn=Xt&&Xt.createElement("template"),Jc={insert:(e,t,l)=>{t.insertBefore(e,l||null)},remove:e=>{const t=e.parentNode;t&&t.removeChild(e)},createElement:(e,t,l,i)=>{const o=t?Xt.createElementNS(Zc,e):Xt.createElement(e,l?{is:l}:void 0);return e==="select"&&i&&i.multiple!=null&&o.setAttribute("multiple",i.multiple),o},createText:e=>Xt.createTextNode(e),createComment:e=>Xt.createComment(e),setText:(e,t)=>{e.nodeValue=t},setElementText:(e,t)=>{e.textContent=t},parentNode:e=>e.parentNode,nextSibling:e=>e.nextSibling,querySelector:e=>Xt.querySelector(e),setScopeId(e,t){e.setAttribute(t,"")},cloneNode(e){const t=e.cloneNode(!0);return"_value"in e&&(t._value=e._value),t},insertStaticContent(e,t,l,i,o,n){const r=l?l.previousSibling:t.lastChild;if(o&&(o===n||o.nextSibling))for(;t.insertBefore(o.cloneNode(!0),l),!(o===n||!(o=o.nextSibling)););else{gn.innerHTML=i?`${e}`:e;const a=gn.content;if(i){const s=a.firstChild;for(;s.firstChild;)a.appendChild(s.firstChild);a.removeChild(s)}t.insertBefore(a,l)}return[r?r.nextSibling:t.firstChild,l?l.previousSibling:t.lastChild]}};function eh(e,t,l){const i=e._vtc;i&&(t=(t?[t,...i]:[...i]).join(" ")),t==null?e.removeAttribute("class"):l?e.setAttribute("class",t):e.className=t}function th(e,t,l){const i=e.style,o=be(l);if(l&&!o){for(const n in l)ro(i,n,l[n]);if(t&&!be(t))for(const n in t)l[n]==null&&ro(i,n,"")}else{const n=i.display;o?t!==l&&(i.cssText=l):t&&e.removeAttribute("style"),"_vod"in e&&(i.display=n)}}const kn=/\s*!important$/;function ro(e,t,l){if(te(l))l.forEach(i=>ro(e,t,i));else if(l==null&&(l=""),t.startsWith("--"))e.setProperty(t,l);else{const i=lh(e,t);kn.test(l)?e.setProperty(Zt(i),l.replace(kn,""),"important"):e[i]=l}}const vn=["Webkit","Moz","ms"],Mi={};function lh(e,t){const l=Mi[t];if(l)return l;let i=ut(t);if(i!=="filter"&&i in e)return Mi[t]=i;i=yi(i);for(let o=0;o{let e=Date.now,t=!1;if(typeof window<"u"){Date.now()>document.createEvent("Event").timeStamp&&(e=performance.now.bind(performance));const l=navigator.userAgent.match(/firefox\/(\d+)/i);t=!!(l&&Number(l[1])<=53)}return[e,t]})();let ao=0;const rh=Promise.resolve(),ah=()=>{ao=0},sh=()=>ao||(rh.then(ah),ao=ca());function ch(e,t,l,i){e.addEventListener(t,l,i)}function hh(e,t,l,i){e.removeEventListener(t,l,i)}function dh(e,t,l,i,o=null){const n=e._vei||(e._vei={}),r=n[t];if(i&&r)r.value=i;else{const[a,s]=uh(t);if(i){const c=n[t]=ph(i,o);ch(e,a,c,s)}else r&&(hh(e,a,r,s),n[t]=void 0)}}const _n=/(?:Once|Passive|Capture)$/;function uh(e){let t;if(_n.test(e)){t={};let l;for(;l=e.match(_n);)e=e.slice(0,e.length-l[0].length),t[l[0].toLowerCase()]=!0}return[Zt(e.slice(2)),t]}function ph(e,t){const l=i=>{const o=i.timeStamp||ca();(nh||o>=l.attached-1)&<(mh(i,l.value),t,5,[i])};return l.value=e,l.attached=sh(),l}function mh(e,t){if(te(t)){const l=e.stopImmediatePropagation;return e.stopImmediatePropagation=()=>{l.call(e),e._stopped=!0},t.map(i=>o=>!o._stopped&&i&&i(o))}else return t}const yn=/^on[a-z]/,fh=(e,t,l,i,o=!1,n,r,a,s)=>{t==="class"?eh(e,i,o):t==="style"?th(e,l,i):Vl(t)?fo(t)||dh(e,t,l,i,r):(t[0]==="."?(t=t.slice(1),!0):t[0]==="^"?(t=t.slice(1),!1):gh(e,t,i,o))?oh(e,t,i,n,r,a,s):(t==="true-value"?e._trueValue=i:t==="false-value"&&(e._falseValue=i),ih(e,t,i,o))};function gh(e,t,l,i){return i?!!(t==="innerHTML"||t==="textContent"||t in e&&yn.test(t)&&re(l)):t==="spellcheck"||t==="draggable"||t==="translate"||t==="form"||t==="list"&&e.tagName==="INPUT"||t==="type"&&e.tagName==="TEXTAREA"||yn.test(t)&&be(l)?!1:t in e}const Rt="transition",vl="animation",Bl=(e,{slots:t})=>he(Yr,kh(e),t);Bl.displayName="Transition";const ha={name:String,type:String,css:{type:Boolean,default:!0},duration:[String,Number,Object],enterFromClass:String,enterActiveClass:String,enterToClass:String,appearFromClass:String,appearActiveClass:String,appearToClass:String,leaveFromClass:String,leaveActiveClass:String,leaveToClass:String};Bl.props=Se({},Yr.props,ha);const jt=(e,t=[])=>{te(e)?e.forEach(l=>l(...t)):e&&e(...t)},xn=e=>e?te(e)?e.some(t=>t.length>1):e.length>1:!1;function kh(e){const t={};for(const R in e)R in ha||(t[R]=e[R]);if(e.css===!1)return t;const{name:l="v",type:i,duration:o,enterFromClass:n=`${l}-enter-from`,enterActiveClass:r=`${l}-enter-active`,enterToClass:a=`${l}-enter-to`,appearFromClass:s=n,appearActiveClass:c=r,appearToClass:h=a,leaveFromClass:p=`${l}-leave-from`,leaveActiveClass:m=`${l}-leave-active`,leaveToClass:g=`${l}-leave-to`}=e,x=vh(o),P=x&&x[0],E=x&&x[1],{onBeforeEnter:k,onEnter:b,onEnterCancelled:L,onLeave:M,onLeaveCancelled:U,onBeforeAppear:ee=k,onAppear:w=b,onAppearCancelled:v=L}=t,q=(R,S,F)=>{$t(R,S?h:a),$t(R,S?c:r),F&&F()},B=(R,S)=>{R._isLeaving=!1,$t(R,p),$t(R,g),$t(R,m),S&&S()},G=R=>(S,F)=>{const ae=R?w:b,j=()=>q(S,R,F);jt(ae,[S,j]),En(()=>{$t(S,R?s:n),Ct(S,R?h:a),xn(ae)||Rn(S,i,P,j)})};return Se(t,{onBeforeEnter(R){jt(k,[R]),Ct(R,n),Ct(R,r)},onBeforeAppear(R){jt(ee,[R]),Ct(R,s),Ct(R,c)},onEnter:G(!1),onAppear:G(!0),onLeave(R,S){R._isLeaving=!0;const F=()=>B(R,S);Ct(R,p),yh(),Ct(R,m),En(()=>{!R._isLeaving||($t(R,p),Ct(R,g),xn(M)||Rn(R,i,E,F))}),jt(M,[R,F])},onEnterCancelled(R){q(R,!1),jt(L,[R])},onAppearCancelled(R){q(R,!0),jt(v,[R])},onLeaveCancelled(R){B(R),jt(U,[R])}})}function vh(e){if(e==null)return null;if(Oe(e))return[Si(e.enter),Si(e.leave)];{const t=Si(e);return[t,t]}}function Si(e){return gr(e)}function Ct(e,t){t.split(/\s+/).forEach(l=>l&&e.classList.add(l)),(e._vtc||(e._vtc=new Set)).add(t)}function $t(e,t){t.split(/\s+/).forEach(i=>i&&e.classList.remove(i));const{_vtc:l}=e;l&&(l.delete(t),l.size||(e._vtc=void 0))}function En(e){requestAnimationFrame(()=>{requestAnimationFrame(e)})}let bh=0;function Rn(e,t,l,i){const o=e._endId=++bh,n=()=>{o===e._endId&&i()};if(l)return setTimeout(n,l);const{type:r,timeout:a,propCount:s}=_h(e,t);if(!r)return i();const c=r+"end";let h=0;const p=()=>{e.removeEventListener(c,m),n()},m=g=>{g.target===e&&++h>=s&&p()};setTimeout(()=>{h(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.lengthPn(l)+Pn(e[i])))}function Pn(e){return Number(e.slice(0,-1).replace(",","."))*1e3}function yh(){return document.body.offsetHeight}const xh={esc:"escape",space:" ",up:"arrow-up",left:"arrow-left",right:"arrow-right",down:"arrow-down",delete:"backspace"},Eh=(e,t)=>l=>{if(!("key"in l))return;const i=Zt(l.key);if(t.some(o=>o===i||xh[o]===i))return e(l)},mi={beforeMount(e,{value:t},{transition:l}){e._vod=e.style.display==="none"?"":e.style.display,l&&t?l.beforeEnter(e):bl(e,t)},mounted(e,{value:t},{transition:l}){l&&t&&l.enter(e)},updated(e,{value:t,oldValue:l},{transition:i}){!t!=!l&&(i?t?(i.beforeEnter(e),bl(e,!0),i.enter(e)):i.leave(e,()=>{bl(e,!1)}):bl(e,t))},beforeUnmount(e,{value:t}){bl(e,t)}};function bl(e,t){e.style.display=t?e._vod:"none"}const Rh=Se({patchProp:fh},Jc);let Vi,Ln=!1;function Ch(){return Vi=Ln?Vi:zc(Rh),Ln=!0,Vi}const Ph=(...e)=>{const t=Ch().createApp(...e),{mount:l}=t;return t.mount=i=>{const o=Lh(i);if(o)return l(o,!0,o instanceof SVGElement)},t};function Lh(e){return be(e)?document.querySelector(e):e}const Ah=JSON.parse('{"base":"/YukiHookAPI/","lang":"en-US","title":"Yuki Hook API","description":"An efficient Kotlin version of the Xposed Hook API","head":[["link",{"rel":"icon","href":"/images/logo.png"}]],"locales":{"/en/":{"lang":"en-US","description":"An efficient Kotlin version of the Xposed Hook API"},"/zh-cn/":{"lang":"zh-CN","description":"\u4E00\u4E2A\u4F7F\u7528 Kotlin \u91CD\u6784\u7684\u8F7B\u91CF\u3001\u9AD8\u6548\u3001\u7A33\u5B9A\u7684 Xposed Hook API"}}}');var Th=([e,t,l])=>e==="meta"&&t.name?`${e}.${t.name}`:["title","base"].includes(e)?e:e==="template"&&t.id?`${e}.${t.id}`:JSON.stringify([e,t,l]),Ih=e=>{const t=new Set,l=[];return e.forEach(i=>{const o=Th(i);t.has(o)||(t.add(o),l.push(i))}),l},Ul=e=>/^(https?:)?\/\//.test(e),wh=e=>/^mailto:/.test(e),Oh=e=>/^tel:/.test(e),Oo=e=>Object.prototype.toString.call(e)==="[object Object]",da=e=>e.replace(/\/$/,""),ua=e=>e.replace(/^\//,""),pa=(e,t)=>{const l=Object.keys(e).sort((i,o)=>{const n=o.split("/").length-i.split("/").length;return n!==0?n:o.length-i.length});for(const i of l)if(t.startsWith(i))return i;return"/"};const ma={"v-8daa1a0e":_(()=>d(()=>import("./index.html.f53b6095.js"),[])),"v-2d0a870d":_(()=>d(()=>import("./index.html.d735d08d.js"),[])),"v-c0c85b84":_(()=>d(()=>import("./index.html.f36dcd2e.js"),[])),"v-7a15fe3b":_(()=>d(()=>import("./about.html.7d8b24a5.js"),[])),"v-3f851d14":_(()=>d(()=>import("./changelog.html.22a53013.js"),[])),"v-193cf592":_(()=>d(()=>import("./contacts.html.8946c067.js"),[])),"v-ae7b83f2":_(()=>d(()=>import("./future.html.e52259cf.js"),[])),"v-64fc7bb8":_(()=>d(()=>import("./home.html.fd8a27c6.js"),[])),"v-9cfea7fc":_(()=>d(()=>import("./api-example.html.ffabf490.js"),[])),"v-72c12b7d":_(()=>d(()=>import("./api-exception.html.5fb01524.js"),[])),"v-793879e8":_(()=>d(()=>import("./api-using.html.1ec848ab.js"),[])),"v-29d6c1ba":_(()=>d(()=>import("./r8-proguard.html.1ec215bf.js"),[])),"v-24e71de7":_(()=>d(()=>import("./xposed-using.html.f07fa93e.js"),[])),"v-7b22efaf":_(()=>d(()=>import("./example.html.e66bd85b.js"),[])),"v-efb45d4c":_(()=>d(()=>import("./home.html.6cc8b4b8.js"),[])),"v-277b35ca":_(()=>d(()=>import("./knowledge.html.a4616f5c.js"),[])),"v-77d752a2":_(()=>d(()=>import("./move-to-new-api.html.f0cc4092.js"),[])),"v-72889797":_(()=>d(()=>import("./quick-start.html.749cf17e.js"),[])),"v-55c11626":_(()=>d(()=>import("./yukihookapi-projectbuilder.html.c5d87cd3.js"),[])),"v-41967128":_(()=>d(()=>import("./about.html.f4c8582a.js"),[])),"v-0e6c3476":_(()=>d(()=>import("./changelog.html.576ee237.js"),[])),"v-6cf86266":_(()=>d(()=>import("./contacts.html.0e0a7262.js"),[])),"v-3106ca14":_(()=>d(()=>import("./future.html.4da05d23.js"),[])),"v-c8deafb2":_(()=>d(()=>import("./home.html.e164d825.js"),[])),"v-c6114c9e":_(()=>d(()=>import("./api-example.html.63409bed.js"),[])),"v-5b43296c":_(()=>d(()=>import("./api-exception.html.9f654113.js"),[])),"v-2ee67152":_(()=>d(()=>import("./api-using.html.37eb156b.js"),[])),"v-154d6f69":_(()=>d(()=>import("./r8-proguard.html.44d498ce.js"),[])),"v-af73b3d0":_(()=>d(()=>import("./xposed-using.html.701123e9.js"),[])),"v-13b430a0":_(()=>d(()=>import("./example.html.be2f529d.js"),[])),"v-6a609e09":_(()=>d(()=>import("./home.html.06a0e41c.js"),[])),"v-b4f1a468":_(()=>d(()=>import("./knowledge.html.e0a069f9.js"),[])),"v-c0d5dada":_(()=>d(()=>import("./move-to-new-api.html.2d2ee2a7.js"),[])),"v-24840ff0":_(()=>d(()=>import("./quick-start.html.20dd75c7.js"),[])),"v-a2fab4d6":_(()=>d(()=>import("./yukihookapi-projectbuilder.html.ae5d1a49.js"),[])),"v-12042f1f":_(()=>d(()=>import("./host-inject.html.e5c6c6ae.js"),[])),"v-deaff1d0":_(()=>d(()=>import("./host-lifecycle.html.73e3c8fc.js"),[])),"v-33c1dc26":_(()=>d(()=>import("./logger.html.55af0b09.js"),[])),"v-581ddb9c":_(()=>d(()=>import("./reflection.html.37e12a3d.js"),[])),"v-2e6ad66c":_(()=>d(()=>import("./xposed-channel.html.ea22e7ce.js"),[])),"v-68bebbf4":_(()=>d(()=>import("./xposed-storage.html.cd1e83bb.js"),[])),"v-6ac5be8e":_(()=>d(()=>import("./host-inject.html.acabeb56.js"),[])),"v-357a8d49":_(()=>d(()=>import("./host-lifecycle.html.56277eb5.js"),[])),"v-1f0f591e":_(()=>d(()=>import("./logger.html.fd07b1ad.js"),[])),"v-001858e3":_(()=>d(()=>import("./reflection.html.3174ec77.js"),[])),"v-598546c6":_(()=>d(()=>import("./xposed-channel.html.18cd2bdb.js"),[])),"v-0d914225":_(()=>d(()=>import("./xposed-storage.html.6926bcf4.js"),[])),"v-053599a5":_(()=>d(()=>import("./YukiHookAPI.html.1c02f82e.js"),[])),"v-6931cb54":_(()=>d(()=>import("./YukiHookAPI.html.18811dc9.js"),[])),"v-818b3ca6":_(()=>d(()=>import("./InjectYukiHookWithXposed.html.b6100747.js"),[])),"v-b6a815c4":_(()=>d(()=>import("./CurrentClass.html.072e89c6.js"),[])),"v-0183e3fc":_(()=>d(()=>import("./GenericClass.html.b1c03ed1.js"),[])),"v-57506200":_(()=>d(()=>import("./HookClass.html.f01a0415.js"),[])),"v-9af56c1a":_(()=>d(()=>import("./HookResources.html.b888e8b6.js"),[])),"v-032b1710":_(()=>d(()=>import("./VariousClass.html.3e45065c.js"),[])),"v-71147891":_(()=>d(()=>import("./YukiMemberHookCreator.html.bacce7a8.js"),[])),"v-5ed1ceee":_(()=>d(()=>import("./YukiResourcesHookCreator.html.d14760e0.js"),[])),"v-e288ce96":_(()=>d(()=>import("./YukiBaseHooker.html.0fb80f07.js"),[])),"v-0d0fcec2":_(()=>d(()=>import("./ReflectionFactory.html.daab3686.js"),[])),"v-65091354":_(()=>d(()=>import("./YukiHookFactory.html.61878d38.js"),[])),"v-36aec5ad":_(()=>d(()=>import("./LoggerFactory.html.84495d50.js"),[])),"v-60cbe1b4":_(()=>d(()=>import("./HookParam.html.918accc4.js"),[])),"v-b381a126":_(()=>d(()=>import("./PackageParam.html.3014d07d.js"),[])),"v-6e47300f":_(()=>d(()=>import("./CurrentClass.html.2e606398.js"),[])),"v-69c1c226":_(()=>d(()=>import("./GenericClass.html.ca958253.js"),[])),"v-735374af":_(()=>d(()=>import("./HookClass.html.7354fd95.js"),[])),"v-1c516d22":_(()=>d(()=>import("./HookResources.html.70a752b2.js"),[])),"v-66735bfe":_(()=>d(()=>import("./VariousClass.html.5a07233f.js"),[])),"v-30f3ba1e":_(()=>d(()=>import("./InjectYukiHookWithXposed.html.ecb261b1.js"),[])),"v-3ac40680":_(()=>d(()=>import("./YukiMemberHookCreator.html.55afd41d.js"),[])),"v-5e81af42":_(()=>d(()=>import("./YukiResourcesHookCreator.html.ddbc430b.js"),[])),"v-516df326":_(()=>d(()=>import("./YukiBaseHooker.html.6b167698.js"),[])),"v-213d88b3":_(()=>d(()=>import("./ReflectionFactory.html.d2629c75.js"),[])),"v-448e9585":_(()=>d(()=>import("./YukiHookFactory.html.122ae5d0.js"),[])),"v-004a009e":_(()=>d(()=>import("./LoggerFactory.html.bb211a96.js"),[])),"v-75a9b636":_(()=>d(()=>import("./HookParam.html.30f4fb72.js"),[])),"v-100b529c":_(()=>d(()=>import("./PackageParam.html.4c3306f9.js"),[])),"v-8293d958":_(()=>d(()=>import("./ComponentTypeFactory.html.61d8989e.js"),[])),"v-7b0abf86":_(()=>d(()=>import("./GraphicsTypeFactory.html.61eca533.js"),[])),"v-5309e4a0":_(()=>d(()=>import("./ViewTypeFactory.html.e29c5d7e.js"),[])),"v-a2615d0c":_(()=>d(()=>import("./DefinedTypeFactory.html.bca7fe3f.js"),[])),"v-ba01a600":_(()=>d(()=>import("./VariableTypeFactory.html.6d08103b.js"),[])),"v-7fec5836":_(()=>d(()=>import("./ModuleApplication.html.e946b5fe.js"),[])),"v-7414265a":_(()=>d(()=>import("./YukiHookDataChannel.html.f40252bf.js"),[])),"v-003862c2":_(()=>d(()=>import("./YukiHookModulePrefs.html.77ac932a.js"),[])),"v-1d680acc":_(()=>d(()=>import("./IYukiHookXposedInit.html.7f3e0a05.js"),[])),"v-5e874c45":_(()=>d(()=>import("./ComponentTypeFactory.html.2f6bbc66.js"),[])),"v-4ea62475":_(()=>d(()=>import("./GraphicsTypeFactory.html.df9b6853.js"),[])),"v-ef79cde2":_(()=>d(()=>import("./ViewTypeFactory.html.f12c489b.js"),[])),"v-5acc12ab":_(()=>d(()=>import("./DefinedTypeFactory.html.1a27d470.js"),[])),"v-14ec8671":_(()=>d(()=>import("./VariableTypeFactory.html.c8d4e99d.js"),[])),"v-4709ad58":_(()=>d(()=>import("./ModuleApplication.html.ad43cded.js"),[])),"v-632be8ee":_(()=>d(()=>import("./YukiHookDataChannel.html.b01666c1.js"),[])),"v-5858709e":_(()=>d(()=>import("./YukiHookModulePrefs.html.9506520f.js"),[])),"v-763140ee":_(()=>d(()=>import("./IYukiHookXposedInit.html.4813ba4f.js"),[])),"v-4fca92c0":_(()=>d(()=>import("./BaseFinder.html.8588c8ac.js"),[])),"v-2a898c66":_(()=>d(()=>import("./DexClassFinder.html.5e274913.js"),[])),"v-a71937aa":_(()=>d(()=>import("./ConstructorFinder.html.022babd4.js"),[])),"v-42e0f0ab":_(()=>d(()=>import("./FieldFinder.html.7f3e47fc.js"),[])),"v-a4aa4d00":_(()=>d(()=>import("./MethodFinder.html.55746f01.js"),[])),"v-0f1e3594":_(()=>d(()=>import("./YukiModuleResources.html.581abd4c.js"),[])),"v-35faec91":_(()=>d(()=>import("./YukiResForwarder.html.3fa53afd.js"),[])),"v-2c04b82a":_(()=>d(()=>import("./YukiResources.html.b3a31d94.js"),[])),"v-19e7277e":_(()=>d(()=>import("./YukiXposedEvent.html.ae210e6f.js"),[])),"v-2f64a2d4":_(()=>d(()=>import("./ChannelData.html.2358cb0e.js"),[])),"v-58ed8298":_(()=>d(()=>import("./PrefsData.html.be01fa30.js"),[])),"v-23e1a817":_(()=>d(()=>import("./ModulePreferenceFragment.html.40d2af95.js"),[])),"v-0f719471":_(()=>d(()=>import("./BaseFinder.html.1ec4ffab.js"),[])),"v-45111efc":_(()=>d(()=>import("./DexClassFinder.html.92677d64.js"),[])),"v-1e2cbc9c":_(()=>d(()=>import("./ConstructorFinder.html.254da89b.js"),[])),"v-22449c48":_(()=>d(()=>import("./FieldFinder.html.908d5caa.js"),[])),"v-fd738322":_(()=>d(()=>import("./MethodFinder.html.9844b141.js"),[])),"v-3d943532":_(()=>d(()=>import("./YukiModuleResources.html.c36ad6ed.js"),[])),"v-526c4200":_(()=>d(()=>import("./YukiResForwarder.html.ef96ef7b.js"),[])),"v-68541dca":_(()=>d(()=>import("./YukiResources.html.d71b960b.js"),[])),"v-0a4de82f":_(()=>d(()=>import("./YukiXposedEvent.html.e00ead3e.js"),[])),"v-493d37f6":_(()=>d(()=>import("./ChannelData.html.2404edfd.js"),[])),"v-d99f7f36":_(()=>d(()=>import("./PrefsData.html.0d8e9948.js"),[])),"v-53bcae06":_(()=>d(()=>import("./ModulePreferenceFragment.html.7e33a328.js"),[])),"v-52995ef7":_(()=>d(()=>import("./CountRules.html.52ed8a0d.js"),[])),"v-8d5ce71a":_(()=>d(()=>import("./ModifierRules.html.1596e901.js"),[])),"v-f5b1ffb2":_(()=>d(()=>import("./NameRules.html.5da95c04.js"),[])),"v-08b70f7f":_(()=>d(()=>import("./ConstructorRules.html.d56dfdf4.js"),[])),"v-21f64ebf":_(()=>d(()=>import("./FieldRules.html.990238ad.js"),[])),"v-77f11cf9":_(()=>d(()=>import("./MemberRules.html.1a50f297.js"),[])),"v-64827680":_(()=>d(()=>import("./MethodRules.html.b1f90f61.js"),[])),"v-2d5d16db":_(()=>d(()=>import("./ModuleAppActivity.html.1aa71ae6.js"),[])),"v-cadbe48e":_(()=>d(()=>import("./ModuleAppCompatActivity.html.2fd9ae3a.js"),[])),"v-78731c50":_(()=>d(()=>import("./ModuleContextThemeWrapper.html.5787cac6.js"),[])),"v-1b2ad030":_(()=>d(()=>import("./CountRules.html.5103015c.js"),[])),"v-547a3c3c":_(()=>d(()=>import("./ModifierRules.html.4767495f.js"),[])),"v-58c26516":_(()=>d(()=>import("./NameRules.html.4729f5e5.js"),[])),"v-a42f54a4":_(()=>d(()=>import("./ConstructorRules.html.e17434ce.js"),[])),"v-3e67a42e":_(()=>d(()=>import("./FieldRules.html.1fea86e8.js"),[])),"v-2cab152c":_(()=>d(()=>import("./MemberRules.html.fbc5b06f.js"),[])),"v-5388621e":_(()=>d(()=>import("./MethodRules.html.9819df7e.js"),[])),"v-44efb702":_(()=>d(()=>import("./ModuleContextThemeWrapper.html.7262b83c.js"),[])),"v-1446bdca":_(()=>d(()=>import("./ModuleAppActivity.html.fd7c57b2.js"),[])),"v-c7cef530":_(()=>d(()=>import("./ModuleAppCompatActivity.html.de402219.js"),[])),"v-5e375d98":_(()=>d(()=>import("./MemberRulesResult.html.2524371e.js"),[])),"v-b8000f3a":_(()=>d(()=>import("./MemberRulesResult.html.49b372bb.js"),[])),"v-3706649a":_(()=>d(()=>import("./404.html.d9151b86.js"),[]))};var Mt=(e={})=>e;function fa(e,t,l){var i,o,n;t===void 0&&(t=50),l===void 0&&(l={});var r=(i=l.isImmediate)!=null&&i,a=(o=l.callback)!=null&&o,s=l.maxWait,c=Date.now(),h=[];function p(){if(s!==void 0){var g=Date.now()-c;if(g+t>=s)return s-g}return t}var m=function(){var g=[].slice.call(arguments),x=this;return new Promise(function(P,E){var k=r&&n===void 0;if(n!==void 0&&clearTimeout(n),n=setTimeout(function(){if(n=void 0,c=Date.now(),!r){var L=e.apply(x,g);a&&a(L),h.forEach(function(M){return(0,M.resolve)(L)}),h=[]}},p()),k){var b=e.apply(x,g);return a&&a(b),P(b)}h.push({resolve:P,reject:E})})};return m.cancel=function(g){n!==void 0&&clearTimeout(n),h.forEach(function(x){return(0,x.reject)(g)}),h=[]},m}/*! + * vue-router v4.1.5 + * (c) 2022 Eduardo San Martin Morote + * @license MIT + */const nl=typeof window<"u";function Fh(e){return e.__esModule||e[Symbol.toStringTag]==="Module"}const ve=Object.assign;function Ni(e,t){const l={};for(const i in t){const o=t[i];l[i]=st(o)?o.map(e):e(o)}return l}const Tl=()=>{},st=Array.isArray,zh=/\/$/,Dh=e=>e.replace(zh,"");function ji(e,t,l="/"){let i,o={},n="",r="";const a=t.indexOf("#");let s=t.indexOf("?");return a=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;n1&&o--;else break;return l.slice(0,o).join("/")+"/"+i.slice(n-(n===i.length?1:0)).join("/")}var Ml;(function(e){e.pop="pop",e.push="push"})(Ml||(Ml={}));var Il;(function(e){e.back="back",e.forward="forward",e.unknown=""})(Il||(Il={}));function Nh(e){if(!e)if(nl){const t=document.querySelector("base");e=t&&t.getAttribute("href")||"/",e=e.replace(/^\w+:\/\/[^\/]+/,"")}else e="/";return e[0]!=="/"&&e[0]!=="#"&&(e="/"+e),Dh(e)}const jh=/^[^#]+#/;function $h(e,t){return e.replace(jh,"#")+t}function Yh(e,t){const l=document.documentElement.getBoundingClientRect(),i=e.getBoundingClientRect();return{behavior:t.behavior,left:i.left-l.left-(t.left||0),top:i.top-l.top-(t.top||0)}}const Ii=()=>({left:window.pageXOffset,top:window.pageYOffset});function Bh(e){let t;if("el"in e){const l=e.el,i=typeof l=="string"&&l.startsWith("#"),o=typeof l=="string"?i?document.getElementById(l.slice(1)):document.querySelector(l):l;if(!o)return;t=Yh(o,e)}else t=e;"scrollBehavior"in document.documentElement.style?window.scrollTo(t):window.scrollTo(t.left!=null?t.left:window.pageXOffset,t.top!=null?t.top:window.pageYOffset)}function In(e,t){return(history.state?history.state.position-t:-1)+e}const so=new Map;function Uh(e,t){so.set(e,t)}function Wh(e){const t=so.get(e);return so.delete(e),t}let Xh=()=>location.protocol+"//"+location.host;function ka(e,t){const{pathname:l,search:i,hash:o}=t,n=e.indexOf("#");if(n>-1){let a=o.includes(e.slice(n))?e.slice(n).length:1,s=o.slice(a);return s[0]!=="/"&&(s="/"+s),An(s,"")}return An(l,e)+i+o}function qh(e,t,l,i){let o=[],n=[],r=null;const a=({state:m})=>{const g=ka(e,location),x=l.value,P=t.value;let E=0;if(m){if(l.value=g,t.value=m,r&&r===x){r=null;return}E=P?m.position-P.position:0}else i(g);o.forEach(k=>{k(l.value,x,{delta:E,type:Ml.pop,direction:E?E>0?Il.forward:Il.back:Il.unknown})})};function s(){r=l.value}function c(m){o.push(m);const g=()=>{const x=o.indexOf(m);x>-1&&o.splice(x,1)};return n.push(g),g}function h(){const{history:m}=window;!m.state||m.replaceState(ve({},m.state,{scroll:Ii()}),"")}function p(){for(const m of n)m();n=[],window.removeEventListener("popstate",a),window.removeEventListener("beforeunload",h)}return window.addEventListener("popstate",a),window.addEventListener("beforeunload",h),{pauseListeners:s,listen:c,destroy:p}}function wn(e,t,l,i=!1,o=!1){return{back:e,current:t,forward:l,replaced:i,position:window.history.length,scroll:o?Ii():null}}function Kh(e){const{history:t,location:l}=window,i={value:ka(e,l)},o={value:t.state};o.value||n(i.value,{back:null,current:i.value,forward:null,position:t.length-1,replaced:!0,scroll:null},!0);function n(s,c,h){const p=e.indexOf("#"),m=p>-1?(l.host&&document.querySelector("base")?e:e.slice(p))+s:Xh()+e+s;try{t[h?"replaceState":"pushState"](c,"",m),o.value=c}catch(g){console.error(g),l[h?"replace":"assign"](m)}}function r(s,c){const h=ve({},t.state,wn(o.value.back,s,o.value.forward,!0),c,{position:o.value.position});n(s,h,!0),i.value=s}function a(s,c){const h=ve({},o.value,t.state,{forward:s,scroll:Ii()});n(h.current,h,!0);const p=ve({},wn(i.value,s,null),{position:h.position+1},c);n(s,p,!1),i.value=s}return{location:i,state:o,push:a,replace:r}}function Gh(e){e=Nh(e);const t=Kh(e),l=qh(e,t.state,t.location,t.replace);function i(n,r=!0){r||l.pauseListeners(),history.go(n)}const o=ve({location:"",base:e,go:i,createHref:$h.bind(null,e)},t,l);return Object.defineProperty(o,"location",{enumerable:!0,get:()=>t.location.value}),Object.defineProperty(o,"state",{enumerable:!0,get:()=>t.state.value}),o}function Qh(e){return typeof e=="string"||e&&typeof e=="object"}function va(e){return typeof e=="string"||typeof e=="symbol"}const mt={path:"/",name:void 0,params:{},query:{},hash:"",fullPath:"/",matched:[],meta:{},redirectedFrom:void 0},ba=Symbol("");var On;(function(e){e[e.aborted=4]="aborted",e[e.cancelled=8]="cancelled",e[e.duplicated=16]="duplicated"})(On||(On={}));function pl(e,t){return ve(new Error,{type:e,[ba]:!0},t)}function pt(e,t){return e instanceof Error&&ba in e&&(t==null||!!(e.type&t))}const Fn="[^/]+?",Zh={sensitive:!1,strict:!1,start:!0,end:!0},Jh=/[.+*?^${}()[\]/\\]/g;function ed(e,t){const l=ve({},Zh,t),i=[];let o=l.start?"^":"";const n=[];for(const c of e){const h=c.length?[]:[90];l.strict&&!c.length&&(o+="/");for(let p=0;pt.length?t.length===1&&t[0]===40+40?1:-1:0}function ld(e,t){let l=0;const i=e.score,o=t.score;for(;l0&&t[t.length-1]<0}const id={type:0,value:""},od=/[a-zA-Z0-9_]/;function nd(e){if(!e)return[[]];if(e==="/")return[[id]];if(!e.startsWith("/"))throw new Error(`Invalid path "${e}"`);function t(g){throw new Error(`ERR (${l})/"${c}": ${g}`)}let l=0,i=l;const o=[];let n;function r(){n&&o.push(n),n=[]}let a=0,s,c="",h="";function p(){!c||(l===0?n.push({type:0,value:c}):l===1||l===2||l===3?(n.length>1&&(s==="*"||s==="+")&&t(`A repeatable param (${c}) must be alone in its segment. eg: '/:ids+.`),n.push({type:1,value:c,regexp:h,repeatable:s==="*"||s==="+",optional:s==="*"||s==="?"})):t("Invalid state to consume buffer"),c="")}function m(){c+=s}for(;a{r(b)}:Tl}function r(h){if(va(h)){const p=i.get(h);p&&(i.delete(h),l.splice(l.indexOf(p),1),p.children.forEach(r),p.alias.forEach(r))}else{const p=l.indexOf(h);p>-1&&(l.splice(p,1),h.record.name&&i.delete(h.record.name),h.children.forEach(r),h.alias.forEach(r))}}function a(){return l}function s(h){let p=0;for(;p=0&&(h.record.path!==l[p].record.path||!_a(h,l[p]));)p++;l.splice(p,0,h),h.record.name&&!Hn(h)&&i.set(h.record.name,h)}function c(h,p){let m,g={},x,P;if("name"in h&&h.name){if(m=i.get(h.name),!m)throw pl(1,{location:h});P=m.record.name,g=ve(Dn(p.params,m.keys.filter(b=>!b.optional).map(b=>b.name)),h.params&&Dn(h.params,m.keys.map(b=>b.name))),x=m.stringify(g)}else if("path"in h)x=h.path,m=l.find(b=>b.re.test(x)),m&&(g=m.parse(x),P=m.record.name);else{if(m=p.name?i.get(p.name):l.find(b=>b.re.test(p.path)),!m)throw pl(1,{location:h,currentLocation:p});P=m.record.name,g=ve({},p.params,h.params),x=m.stringify(g)}const E=[];let k=m;for(;k;)E.unshift(k.record),k=k.parent;return{name:P,path:x,params:g,matched:E,meta:hd(E)}}return e.forEach(h=>n(h)),{addRoute:n,resolve:c,removeRoute:r,getRoutes:a,getRecordMatcher:o}}function Dn(e,t){const l={};for(const i of t)i in e&&(l[i]=e[i]);return l}function sd(e){return{path:e.path,redirect:e.redirect,name:e.name,meta:e.meta||{},aliasOf:void 0,beforeEnter:e.beforeEnter,props:cd(e),children:e.children||[],instances:{},leaveGuards:new Set,updateGuards:new Set,enterCallbacks:{},components:"components"in e?e.components||null:e.component&&{default:e.component}}}function cd(e){const t={},l=e.props||!1;if("component"in e)t.default=l;else for(const i in e.components)t[i]=typeof l=="boolean"?l:l[i];return t}function Hn(e){for(;e;){if(e.record.aliasOf)return!0;e=e.parent}return!1}function hd(e){return e.reduce((t,l)=>ve(t,l.meta),{})}function Mn(e,t){const l={};for(const i in e)l[i]=i in t?t[i]:e[i];return l}function _a(e,t){return t.children.some(l=>l===e||_a(e,l))}const ya=/#/g,dd=/&/g,ud=/\//g,pd=/=/g,md=/\?/g,xa=/\+/g,fd=/%5B/g,gd=/%5D/g,Ea=/%5E/g,kd=/%60/g,Ra=/%7B/g,vd=/%7C/g,Ca=/%7D/g,bd=/%20/g;function Fo(e){return encodeURI(""+e).replace(vd,"|").replace(fd,"[").replace(gd,"]")}function _d(e){return Fo(e).replace(Ra,"{").replace(Ca,"}").replace(Ea,"^")}function co(e){return Fo(e).replace(xa,"%2B").replace(bd,"+").replace(ya,"%23").replace(dd,"%26").replace(kd,"`").replace(Ra,"{").replace(Ca,"}").replace(Ea,"^")}function yd(e){return co(e).replace(pd,"%3D")}function xd(e){return Fo(e).replace(ya,"%23").replace(md,"%3F")}function Ed(e){return e==null?"":xd(e).replace(ud,"%2F")}function fi(e){try{return decodeURIComponent(""+e)}catch{}return""+e}function Rd(e){const t={};if(e===""||e==="?")return t;const i=(e[0]==="?"?e.slice(1):e).split("&");for(let o=0;on&&co(n)):[i&&co(i)]).forEach(n=>{n!==void 0&&(t+=(t.length?"&":"")+l,n!=null&&(t+="="+n))})}return t}function Cd(e){const t={};for(const l in e){const i=e[l];i!==void 0&&(t[l]=st(i)?i.map(o=>o==null?null:""+o):i==null?i:""+i)}return t}const Pd=Symbol(""),Vn=Symbol(""),wi=Symbol(""),zo=Symbol(""),ho=Symbol("");function _l(){let e=[];function t(i){return e.push(i),()=>{const o=e.indexOf(i);o>-1&&e.splice(o,1)}}function l(){e=[]}return{add:t,list:()=>e,reset:l}}function At(e,t,l,i,o){const n=i&&(i.enterCallbacks[o]=i.enterCallbacks[o]||[]);return()=>new Promise((r,a)=>{const s=p=>{p===!1?a(pl(4,{from:l,to:t})):p instanceof Error?a(p):Qh(p)?a(pl(2,{from:t,to:p})):(n&&i.enterCallbacks[o]===n&&typeof p=="function"&&n.push(p),r())},c=e.call(i&&i.instances[o],t,l,s);let h=Promise.resolve(c);e.length<3&&(h=h.then(s)),h.catch(p=>a(p))})}function $i(e,t,l,i){const o=[];for(const n of e)for(const r in n.components){let a=n.components[r];if(!(t!=="beforeRouteEnter"&&!n.instances[r]))if(Ld(a)){const c=(a.__vccOpts||a)[t];c&&o.push(At(c,l,i,n,r))}else{let s=a();o.push(()=>s.then(c=>{if(!c)return Promise.reject(new Error(`Couldn't resolve component "${r}" at "${n.path}"`));const h=Fh(c)?c.default:c;n.components[r]=h;const m=(h.__vccOpts||h)[t];return m&&At(m,l,i,n,r)()}))}}return o}function Ld(e){return typeof e=="object"||"displayName"in e||"props"in e||"__vccOpts"in e}function Nn(e){const t=He(wi),l=He(zo),i=Y(()=>t.resolve(O(e.to))),o=Y(()=>{const{matched:s}=i.value,{length:c}=s,h=s[c-1],p=l.matched;if(!h||!p.length)return-1;const m=p.findIndex(ul.bind(null,h));if(m>-1)return m;const g=jn(s[c-2]);return c>1&&jn(h)===g&&p[p.length-1].path!==g?p.findIndex(ul.bind(null,s[c-2])):m}),n=Y(()=>o.value>-1&&wd(l.params,i.value.params)),r=Y(()=>o.value>-1&&o.value===l.matched.length-1&&ga(l.params,i.value.params));function a(s={}){return Id(s)?t[O(e.replace)?"replace":"push"](O(e.to)).catch(Tl):Promise.resolve()}return{route:i,href:Y(()=>i.value.href),isActive:n,isExactActive:r,navigate:a}}const Ad=ue({name:"RouterLink",compatConfig:{MODE:3},props:{to:{type:[String,Object],required:!0},replace:Boolean,activeClass:String,exactActiveClass:String,custom:Boolean,ariaCurrentValue:{type:String,default:"page"}},useLink:Nn,setup(e,{slots:t}){const l=gl(Nn(e)),{options:i}=He(wi),o=Y(()=>({[$n(e.activeClass,i.linkActiveClass,"router-link-active")]:l.isActive,[$n(e.exactActiveClass,i.linkExactActiveClass,"router-link-exact-active")]:l.isExactActive}));return()=>{const n=t.default&&t.default(l);return e.custom?n:he("a",{"aria-current":l.isExactActive?e.ariaCurrentValue:null,href:l.href,onClick:l.navigate,class:o.value},n)}}}),Td=Ad;function Id(e){if(!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)&&!e.defaultPrevented&&!(e.button!==void 0&&e.button!==0)){if(e.currentTarget&&e.currentTarget.getAttribute){const t=e.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(t))return}return e.preventDefault&&e.preventDefault(),!0}}function wd(e,t){for(const l in t){const i=t[l],o=e[l];if(typeof i=="string"){if(i!==o)return!1}else if(!st(o)||o.length!==i.length||i.some((n,r)=>n!==o[r]))return!1}return!0}function jn(e){return e?e.aliasOf?e.aliasOf.path:e.path:""}const $n=(e,t,l)=>e!=null?e:t!=null?t:l,Od=ue({name:"RouterView",inheritAttrs:!1,props:{name:{type:String,default:"default"},route:Object},compatConfig:{MODE:3},setup(e,{attrs:t,slots:l}){const i=He(ho),o=Y(()=>e.route||i.value),n=He(Vn,0),r=Y(()=>{let c=O(n);const{matched:h}=o.value;let p;for(;(p=h[c])&&!p.components;)c++;return c}),a=Y(()=>o.value.matched[r.value]);Gt(Vn,Y(()=>r.value+1)),Gt(Pd,a),Gt(ho,o);const s=ye();return dt(()=>[s.value,a.value,e.name],([c,h,p],[m,g,x])=>{h&&(h.instances[p]=c,g&&g!==h&&c&&c===m&&(h.leaveGuards.size||(h.leaveGuards=g.leaveGuards),h.updateGuards.size||(h.updateGuards=g.updateGuards))),c&&h&&(!g||!ul(h,g)||!m)&&(h.enterCallbacks[p]||[]).forEach(P=>P(c))},{flush:"post"}),()=>{const c=o.value,h=e.name,p=a.value,m=p&&p.components[h];if(!m)return Yn(l.default,{Component:m,route:c});const g=p.props[h],x=g?g===!0?c.params:typeof g=="function"?g(c):g:null,E=he(m,ve({},x,t,{onVnodeUnmounted:k=>{k.component.isUnmounted&&(p.instances[h]=null)},ref:s}));return Yn(l.default,{Component:E,route:c})||E}}});function Yn(e,t){if(!e)return null;const l=e(t);return l.length===1?l[0]:l}const Pa=Od;function Fd(e){const t=ad(e.routes,e),l=e.parseQuery||Rd,i=e.stringifyQuery||Sn,o=e.history,n=_l(),r=_l(),a=_l(),s=wr(mt);let c=mt;nl&&e.scrollBehavior&&"scrollRestoration"in history&&(history.scrollRestoration="manual");const h=Ni.bind(null,C=>""+C),p=Ni.bind(null,Ed),m=Ni.bind(null,fi);function g(C,W){let H,X;return va(C)?(H=t.getRecordMatcher(C),X=W):X=C,t.addRoute(X,H)}function x(C){const W=t.getRecordMatcher(C);W&&t.removeRoute(W)}function P(){return t.getRoutes().map(C=>C.record)}function E(C){return!!t.getRecordMatcher(C)}function k(C,W){if(W=ve({},W||s.value),typeof C=="string"){const ie=ji(l,C,W.path),u=t.resolve({path:ie.path},W),f=o.createHref(ie.fullPath);return ve(ie,u,{params:m(u.params),hash:fi(ie.hash),redirectedFrom:void 0,href:f})}let H;if("path"in C)H=ve({},C,{path:ji(l,C.path,W.path).path});else{const ie=ve({},C.params);for(const u in ie)ie[u]==null&&delete ie[u];H=ve({},C,{params:p(C.params)}),W.params=p(W.params)}const X=t.resolve(H,W),ge=C.hash||"";X.params=h(m(X.params));const _e=Hh(i,ve({},C,{hash:_d(ge),path:X.path})),ce=o.createHref(_e);return ve({fullPath:_e,hash:ge,query:i===Sn?Cd(C.query):C.query||{}},X,{redirectedFrom:void 0,href:ce})}function b(C){return typeof C=="string"?ji(l,C,s.value.path):ve({},C)}function L(C,W){if(c!==C)return pl(8,{from:W,to:C})}function M(C){return w(C)}function U(C){return M(ve(b(C),{replace:!0}))}function ee(C){const W=C.matched[C.matched.length-1];if(W&&W.redirect){const{redirect:H}=W;let X=typeof H=="function"?H(C):H;return typeof X=="string"&&(X=X.includes("?")||X.includes("#")?X=b(X):{path:X},X.params={}),ve({query:C.query,hash:C.hash,params:"path"in X?{}:C.params},X)}}function w(C,W){const H=c=k(C),X=s.value,ge=C.state,_e=C.force,ce=C.replace===!0,ie=ee(H);if(ie)return w(ve(b(ie),{state:typeof ie=="object"?ve({},ge,ie.state):ge,force:_e,replace:ce}),W||H);const u=H;u.redirectedFrom=W;let f;return!_e&&Mh(i,X,H)&&(f=pl(16,{to:u,from:X}),Ne(X,X,!0,!1)),(f?Promise.resolve(f):q(u,X)).catch(y=>pt(y)?pt(y,2)?y:Ie(y):le(y,u,X)).then(y=>{if(y){if(pt(y,2))return w(ve({replace:ce},b(y.to),{state:typeof y.to=="object"?ve({},ge,y.to.state):ge,force:_e}),W||u)}else y=G(u,X,!0,ce,ge);return B(u,X,y),y})}function v(C,W){const H=L(C,W);return H?Promise.reject(H):Promise.resolve()}function q(C,W){let H;const[X,ge,_e]=zd(C,W);H=$i(X.reverse(),"beforeRouteLeave",C,W);for(const ie of X)ie.leaveGuards.forEach(u=>{H.push(At(u,C,W))});const ce=v.bind(null,C,W);return H.push(ce),tl(H).then(()=>{H=[];for(const ie of n.list())H.push(At(ie,C,W));return H.push(ce),tl(H)}).then(()=>{H=$i(ge,"beforeRouteUpdate",C,W);for(const ie of ge)ie.updateGuards.forEach(u=>{H.push(At(u,C,W))});return H.push(ce),tl(H)}).then(()=>{H=[];for(const ie of C.matched)if(ie.beforeEnter&&!W.matched.includes(ie))if(st(ie.beforeEnter))for(const u of ie.beforeEnter)H.push(At(u,C,W));else H.push(At(ie.beforeEnter,C,W));return H.push(ce),tl(H)}).then(()=>(C.matched.forEach(ie=>ie.enterCallbacks={}),H=$i(_e,"beforeRouteEnter",C,W),H.push(ce),tl(H))).then(()=>{H=[];for(const ie of r.list())H.push(At(ie,C,W));return H.push(ce),tl(H)}).catch(ie=>pt(ie,8)?ie:Promise.reject(ie))}function B(C,W,H){for(const X of a.list())X(C,W,H)}function G(C,W,H,X,ge){const _e=L(C,W);if(_e)return _e;const ce=W===mt,ie=nl?history.state:{};H&&(X||ce?o.replace(C.fullPath,ve({scroll:ce&&ie&&ie.scroll},ge)):o.push(C.fullPath,ge)),s.value=C,Ne(C,W,H,ce),Ie()}let R;function S(){R||(R=o.listen((C,W,H)=>{if(!Vt.listening)return;const X=k(C),ge=ee(X);if(ge){w(ve(ge,{replace:!0}),X).catch(Tl);return}c=X;const _e=s.value;nl&&Uh(In(_e.fullPath,H.delta),Ii()),q(X,_e).catch(ce=>pt(ce,12)?ce:pt(ce,2)?(w(ce.to,X).then(ie=>{pt(ie,20)&&!H.delta&&H.type===Ml.pop&&o.go(-1,!1)}).catch(Tl),Promise.reject()):(H.delta&&o.go(-H.delta,!1),le(ce,X,_e))).then(ce=>{ce=ce||G(X,_e,!1),ce&&(H.delta&&!pt(ce,8)?o.go(-H.delta,!1):H.type===Ml.pop&&pt(ce,20)&&o.go(-1,!1)),B(X,_e,ce)}).catch(Tl)}))}let F=_l(),ae=_l(),j;function le(C,W,H){Ie(C);const X=ae.list();return X.length?X.forEach(ge=>ge(C,W,H)):console.error(C),Promise.reject(C)}function se(){return j&&s.value!==mt?Promise.resolve():new Promise((C,W)=>{F.add([C,W])})}function Ie(C){return j||(j=!C,S(),F.list().forEach(([W,H])=>C?H(C):W()),F.reset()),C}function Ne(C,W,H,X){const{scrollBehavior:ge}=e;if(!nl||!ge)return Promise.resolve();const _e=!H&&Wh(In(C.fullPath,0))||(X||!H)&&history.state&&history.state.scroll||null;return jl().then(()=>ge(C,W,_e)).then(ce=>ce&&Bh(ce)).catch(ce=>le(ce,C,W))}const Ue=C=>o.go(C);let Je;const Ye=new Set,Vt={currentRoute:s,listening:!0,addRoute:g,removeRoute:x,hasRoute:E,getRoutes:P,resolve:k,options:e,push:M,replace:U,go:Ue,back:()=>Ue(-1),forward:()=>Ue(1),beforeEach:n.add,beforeResolve:r.add,afterEach:a.add,onError:ae.add,isReady:se,install(C){const W=this;C.component("RouterLink",Td),C.component("RouterView",Pa),C.config.globalProperties.$router=W,Object.defineProperty(C.config.globalProperties,"$route",{enumerable:!0,get:()=>O(s)}),nl&&!Je&&s.value===mt&&(Je=!0,M(o.location).catch(ge=>{}));const H={};for(const ge in mt)H[ge]=Y(()=>s.value[ge]);C.provide(wi,W),C.provide(zo,gl(H)),C.provide(ho,s);const X=C.unmount;Ye.add(C),C.unmount=function(){Ye.delete(C),Ye.size<1&&(c=mt,R&&R(),R=null,s.value=mt,Je=!1,j=!1),X()}}};return Vt}function tl(e){return e.reduce((t,l)=>t.then(()=>l()),Promise.resolve())}function zd(e,t){const l=[],i=[],o=[],n=Math.max(t.matched.length,e.matched.length);for(let r=0;rul(c,a))?i.push(a):l.push(a));const s=e.matched[r];s&&(t.matched.find(c=>ul(c,s))||o.push(s))}return[l,i,o]}function Jt(){return He(wi)}function St(){return He(zo)}const Dd=({headerLinkSelector:e,headerAnchorSelector:t,delay:l,offset:i=5})=>{const o=Jt(),r=fa(()=>{var P,E,k,b;const a=Math.max(window.scrollY,document.documentElement.scrollTop,document.body.scrollTop);if(Math.abs(a-0)m.some(M=>M.hash===L.hash));for(let L=0;L=((E=(P=M.parentElement)==null?void 0:P.offsetTop)!=null?E:0)-i,w=!U||a<((b=(k=U.parentElement)==null?void 0:k.offsetTop)!=null?b:0)-i;if(!(ee&&w))continue;const q=decodeURIComponent(o.currentRoute.value.hash),B=decodeURIComponent(M.hash);if(q===B)return;if(p){for(let G=L+1;G{window.addEventListener("scroll",r)}),Yl(()=>{window.removeEventListener("scroll",r)})},Bn=async(e,t)=>{const{scrollBehavior:l}=e.options;e.options.scrollBehavior=void 0,await e.replace({query:e.currentRoute.value.query,hash:t,force:!0}).finally(()=>e.options.scrollBehavior=l)},Hd="a.sidebar-item",Md=".header-anchor",Sd=300,Vd=5,Nd=Mt({setup(){Dd({headerLinkSelector:Hd,headerAnchorSelector:Md,delay:Sd,offset:Vd})}}),Un=()=>window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,jd=()=>window.scrollTo({top:0,behavior:"smooth"});const $d=ue({name:"BackToTop",setup(){const e=ye(0),t=Y(()=>e.value>300),l=fa(()=>{e.value=Un()},100);Ze(()=>{e.value=Un(),window.addEventListener("scroll",()=>l())});const i=he("div",{class:"back-to-top",onClick:jd});return()=>he(Bl,{name:"back-to-top"},()=>t.value?i:null)}}),Yd=Mt({rootComponents:[$d]});const Bd=he("svg",{class:"external-link-icon",xmlns:"http://www.w3.org/2000/svg","aria-hidden":"true",focusable:"false",x:"0px",y:"0px",viewBox:"0 0 100 100",width:"15",height:"15"},[he("path",{fill:"currentColor",d:"M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"}),he("polygon",{fill:"currentColor",points:"45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"})]),Ud=ue({name:"ExternalLinkIcon",props:{locales:{type:Object,required:!1,default:()=>({})}},setup(e){const t=Wl(),l=Y(()=>{var i;return(i=e.locales[t.value])!=null?i:{openInNewWindow:"open in new window"}});return()=>he("span",[Bd,he("span",{class:"external-link-icon-sr-only"},l.value.openInNewWindow)])}}),Wd={"/en/":{openInNewWindow:"open in new window"},"/zh-cn/":{openInNewWindow:"\u5728\u65B0\u7A97\u53E3\u4E2D\u6253\u5F00"},"/":{openInNewWindow:"open in new window"}},Xd=Mt({enhance({app:e}){e.component("ExternalLinkIcon",he(Ud,{locales:Wd}))}});/*! medium-zoom 1.0.6 | MIT License | https://github.com/francoischalifour/medium-zoom */var Bt=Object.assign||function(e){for(var t=1;t1&&arguments[1]!==void 0?arguments[1]:{},i=window.Promise||function(R){function S(){}R(S,S)},o=function(R){var S=R.target;if(S===q){x();return}L.indexOf(S)!==-1&&P({target:S})},n=function(){if(!(U||!v.original)){var R=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(ee-R)>w.scrollOffset&&setTimeout(x,150)}},r=function(R){var S=R.key||R.keyCode;(S==="Escape"||S==="Esc"||S===27)&&x()},a=function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},S=R;if(R.background&&(q.style.background=R.background),R.container&&R.container instanceof Object&&(S.container=Bt({},w.container,R.container)),R.template){var F=ii(R.template)?R.template:document.querySelector(R.template);S.template=F}return w=Bt({},w,S),L.forEach(function(ae){ae.dispatchEvent(ll("medium-zoom:update",{detail:{zoom:B}}))}),B},s=function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};return e(Bt({},w,R))},c=function(){for(var R=arguments.length,S=Array(R),F=0;F0?S.reduce(function(j,le){return[].concat(j,Xn(le))},[]):L;return ae.forEach(function(j){j.classList.remove("medium-zoom-image"),j.dispatchEvent(ll("medium-zoom:detach",{detail:{zoom:B}}))}),L=L.filter(function(j){return ae.indexOf(j)===-1}),B},p=function(R,S){var F=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return L.forEach(function(ae){ae.addEventListener("medium-zoom:"+R,S,F)}),M.push({type:"medium-zoom:"+R,listener:S,options:F}),B},m=function(R,S){var F=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{};return L.forEach(function(ae){ae.removeEventListener("medium-zoom:"+R,S,F)}),M=M.filter(function(ae){return!(ae.type==="medium-zoom:"+R&&ae.listener.toString()===S.toString())}),B},g=function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},S=R.target,F=function(){var j={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},le=void 0,se=void 0;if(w.container)if(w.container instanceof Object)j=Bt({},j,w.container),le=j.width-j.left-j.right-w.margin*2,se=j.height-j.top-j.bottom-w.margin*2;else{var Ie=ii(w.container)?w.container:document.querySelector(w.container),Ne=Ie.getBoundingClientRect(),Ue=Ne.width,Je=Ne.height,Ye=Ne.left,Vt=Ne.top;j=Bt({},j,{width:Ue,height:Je,left:Ye,top:Vt})}le=le||j.width-w.margin*2,se=se||j.height-w.margin*2;var C=v.zoomedHd||v.original,W=Wn(C)?le:C.naturalWidth||le,H=Wn(C)?se:C.naturalHeight||se,X=C.getBoundingClientRect(),ge=X.top,_e=X.left,ce=X.width,ie=X.height,u=Math.min(W,le)/ce,f=Math.min(H,se)/ie,y=Math.min(u,f),T=(-_e+(le-ce)/2+w.margin+j.left)/y,A=(-ge+(se-ie)/2+w.margin+j.top)/y,z="scale("+y+") translate3d("+T+"px, "+A+"px, 0)";v.zoomed.style.transform=z,v.zoomedHd&&(v.zoomedHd.style.transform=z)};return new i(function(ae){if(S&&L.indexOf(S)===-1){ae(B);return}var j=function Ue(){U=!1,v.zoomed.removeEventListener("transitionend",Ue),v.original.dispatchEvent(ll("medium-zoom:opened",{detail:{zoom:B}})),ae(B)};if(v.zoomed){ae(B);return}if(S)v.original=S;else if(L.length>0){var le=L;v.original=le[0]}else{ae(B);return}if(v.original.dispatchEvent(ll("medium-zoom:open",{detail:{zoom:B}})),ee=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,U=!0,v.zoomed=Gd(v.original),document.body.appendChild(q),w.template){var se=ii(w.template)?w.template:document.querySelector(w.template);v.template=document.createElement("div"),v.template.appendChild(se.content.cloneNode(!0)),document.body.appendChild(v.template)}if(document.body.appendChild(v.zoomed),window.requestAnimationFrame(function(){document.body.classList.add("medium-zoom--opened")}),v.original.classList.add("medium-zoom-image--hidden"),v.zoomed.classList.add("medium-zoom-image--opened"),v.zoomed.addEventListener("click",x),v.zoomed.addEventListener("transitionend",j),v.original.getAttribute("data-zoom-src")){v.zoomedHd=v.zoomed.cloneNode(),v.zoomedHd.removeAttribute("srcset"),v.zoomedHd.removeAttribute("sizes"),v.zoomedHd.src=v.zoomed.getAttribute("data-zoom-src"),v.zoomedHd.onerror=function(){clearInterval(Ie),console.warn("Unable to reach the zoom image target "+v.zoomedHd.src),v.zoomedHd=null,F()};var Ie=setInterval(function(){v.zoomedHd.complete&&(clearInterval(Ie),v.zoomedHd.classList.add("medium-zoom-image--opened"),v.zoomedHd.addEventListener("click",x),document.body.appendChild(v.zoomedHd),F())},10)}else if(v.original.hasAttribute("srcset")){v.zoomedHd=v.zoomed.cloneNode(),v.zoomedHd.removeAttribute("sizes"),v.zoomedHd.removeAttribute("loading");var Ne=v.zoomedHd.addEventListener("load",function(){v.zoomedHd.removeEventListener("load",Ne),v.zoomedHd.classList.add("medium-zoom-image--opened"),v.zoomedHd.addEventListener("click",x),document.body.appendChild(v.zoomedHd),F()})}else F()})},x=function(){return new i(function(R){if(U||!v.original){R(B);return}var S=function F(){v.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(v.zoomed),v.zoomedHd&&document.body.removeChild(v.zoomedHd),document.body.removeChild(q),v.zoomed.classList.remove("medium-zoom-image--opened"),v.template&&document.body.removeChild(v.template),U=!1,v.zoomed.removeEventListener("transitionend",F),v.original.dispatchEvent(ll("medium-zoom:closed",{detail:{zoom:B}})),v.original=null,v.zoomed=null,v.zoomedHd=null,v.template=null,R(B)};U=!0,document.body.classList.remove("medium-zoom--opened"),v.zoomed.style.transform="",v.zoomedHd&&(v.zoomedHd.style.transform=""),v.template&&(v.template.style.transition="opacity 150ms",v.template.style.opacity=0),v.original.dispatchEvent(ll("medium-zoom:close",{detail:{zoom:B}})),v.zoomed.addEventListener("transitionend",S)})},P=function(){var R=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{},S=R.target;return v.original?x():g({target:S})},E=function(){return w},k=function(){return L},b=function(){return v.original},L=[],M=[],U=!1,ee=0,w=l,v={original:null,zoomed:null,zoomedHd:null,template:null};Object.prototype.toString.call(t)==="[object Object]"?w=t:(t||typeof t=="string")&&c(t),w=Bt({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},w);var q=Kd(w.background);document.addEventListener("click",o),document.addEventListener("keyup",r),document.addEventListener("scroll",n),window.addEventListener("resize",x);var B={open:g,close:x,toggle:P,update:a,clone:s,attach:c,detach:h,on:p,off:m,getOptions:E,getImages:k,getZoomedImage:b};return B};function Zd(e,t){t===void 0&&(t={});var l=t.insertAt;if(!(!e||typeof document>"u")){var i=document.head||document.getElementsByTagName("head")[0],o=document.createElement("style");o.type="text/css",l==="top"&&i.firstChild?i.insertBefore(o,i.firstChild):i.appendChild(o),o.styleSheet?o.styleSheet.cssText=e:o.appendChild(document.createTextNode(e))}}var Jd=".medium-zoom-overlay{position:fixed;top:0;right:0;bottom:0;left:0;opacity:0;transition:opacity .3s;will-change:opacity}.medium-zoom--opened .medium-zoom-overlay{cursor:pointer;cursor:zoom-out;opacity:1}.medium-zoom-image{cursor:pointer;cursor:zoom-in;transition:transform .3s cubic-bezier(.2,0,.2,1)!important}.medium-zoom-image--hidden{visibility:hidden}.medium-zoom-image--opened{position:relative;cursor:pointer;cursor:zoom-out;will-change:transform}";Zd(Jd);const eu=Qd,tu=Symbol("mediumZoom");const lu=".theme-default-content > img, .theme-default-content :not(a) > img",iu={},ou=300,nu=Mt({enhance({app:e,router:t}){const l=eu(iu);l.refresh=(i=lu)=>{l.detach(),l.attach(i)},e.provide(tu,l),t.afterEach(()=>{setTimeout(()=>l.refresh(),ou)})}});/** + * NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress + * @license MIT + */const me={settings:{minimum:.08,easing:"ease",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,barSelector:'[role="bar"]',parent:"body",template:'
    '},status:null,set:e=>{const t=me.isStarted();e=Yi(e,me.settings.minimum,1),me.status=e===1?null:e;const l=me.render(!t),i=l.querySelector(me.settings.barSelector),o=me.settings.speed,n=me.settings.easing;return l.offsetWidth,ru(r=>{ti(i,{transform:"translate3d("+qn(e)+"%,0,0)",transition:"all "+o+"ms "+n}),e===1?(ti(l,{transition:"none",opacity:"1"}),l.offsetWidth,setTimeout(function(){ti(l,{transition:"all "+o+"ms linear",opacity:"0"}),setTimeout(function(){me.remove(),r()},o)},o)):setTimeout(()=>r(),o)}),me},isStarted:()=>typeof me.status=="number",start:()=>{me.status||me.set(0);const e=()=>{setTimeout(()=>{!me.status||(me.trickle(),e())},me.settings.trickleSpeed)};return me.settings.trickle&&e(),me},done:e=>!e&&!me.status?me:me.inc(.3+.5*Math.random()).set(1),inc:e=>{let t=me.status;return t?(typeof e!="number"&&(e=(1-t)*Yi(Math.random()*t,.1,.95)),t=Yi(t+e,0,.994),me.set(t)):me.start()},trickle:()=>me.inc(Math.random()*me.settings.trickleRate),render:e=>{if(me.isRendered())return document.getElementById("nprogress");Kn(document.documentElement,"nprogress-busy");const t=document.createElement("div");t.id="nprogress",t.innerHTML=me.settings.template;const l=t.querySelector(me.settings.barSelector),i=e?"-100":qn(me.status||0),o=document.querySelector(me.settings.parent);return ti(l,{transition:"all 0 linear",transform:"translate3d("+i+"%,0,0)"}),o!==document.body&&Kn(o,"nprogress-custom-parent"),o==null||o.appendChild(t),t},remove:()=>{Gn(document.documentElement,"nprogress-busy"),Gn(document.querySelector(me.settings.parent),"nprogress-custom-parent");const e=document.getElementById("nprogress");e&&au(e)},isRendered:()=>!!document.getElementById("nprogress")},Yi=(e,t,l)=>el?l:e,qn=e=>(-1+e)*100,ru=function(){const e=[];function t(){const l=e.shift();l&&l(t)}return function(l){e.push(l),e.length===1&&t()}}(),ti=function(){const e=["Webkit","O","Moz","ms"],t={};function l(r){return r.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,function(a,s){return s.toUpperCase()})}function i(r){const a=document.body.style;if(r in a)return r;let s=e.length;const c=r.charAt(0).toUpperCase()+r.slice(1);let h;for(;s--;)if(h=e[s]+c,h in a)return h;return r}function o(r){return r=l(r),t[r]||(t[r]=i(r))}function n(r,a,s){a=o(a),r.style[a]=s}return function(r,a){for(const s in a){const c=a[s];c!==void 0&&Object.prototype.hasOwnProperty.call(a,s)&&n(r,s,c)}}}(),La=(e,t)=>(typeof e=="string"?e:Do(e)).indexOf(" "+t+" ")>=0,Kn=(e,t)=>{const l=Do(e),i=l+t;La(l,t)||(e.className=i.substring(1))},Gn=(e,t)=>{const l=Do(e);if(!La(e,t))return;const i=l.replace(" "+t+" "," ");e.className=i.substring(1,i.length-1)},Do=e=>(" "+(e.className||"")+" ").replace(/\s+/gi," "),au=e=>{e&&e.parentNode&&e.parentNode.removeChild(e)};const su=()=>{Ze(()=>{const e=Jt(),t=new Set;t.add(e.currentRoute.value.path),e.beforeEach(l=>{t.has(l.path)||me.start()}),e.afterEach(l=>{t.add(l.path),me.done()})})},cu=Mt({setup(){su()}}),hu=JSON.parse(`{"logo":"/images/logo.png","repo":"https://github.com/fankes/YukiHookAPI","docsRepo":"https://github.com/fankes/YukiHookAPI","docsBranch":"master","docsDir":"docs/src","editLinkPattern":":repo/edit/:branch/:path","sidebar":{"/en/":[{"text":"Get Started","collapsible":true,"children":["/en/guide/home","/en/guide/knowledge","/en/guide/quick-start","/en/guide/example","/en/guide/move-to-new-api"]},{"text":"Configs","collapsible":true,"children":["/en/config/api-example","/en/config/api-exception","/en/config/xposed-using","/en/config/api-using","/en/config/r8-proguard"]},{"text":"Tools","collapsible":true,"children":["/en/tools/yukihookapi-projectbuilder"]},{"text":"API Document","collapsible":true,"children":["/en/api/home",{"text":"Public API\xA0","collapsible":true,"children":["/en/api/public/com/highcapable/yukihookapi/YukiHookAPI","/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam","/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam","/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed","/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData","/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel","/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData","/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent","/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory","/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory","/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory","/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker","/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator","/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules","/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass","/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass","/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass","/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass","/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources"]},{"text":"Special Features\xA0","collapsible":true,"children":["/en/api/special-features/reflection","/en/api/special-features/logger","/en/api/special-features/xposed-storage","/en/api/special-features/xposed-channel","/en/api/special-features/host-lifecycle","/en/api/special-features/host-inject"]}]},{"text":"About","collapsible":true,"children":["/en/about/changelog","/en/about/future","/en/about/contacts","/en/about/about"]}],"/zh-cn/":[{"text":"\u5165\u95E8","collapsible":true,"children":["/zh-cn/guide/home","/zh-cn/guide/knowledge","/zh-cn/guide/quick-start","/zh-cn/guide/example","/zh-cn/guide/move-to-new-api"]},{"text":"\u914D\u7F6E","collapsible":true,"children":["/zh-cn/config/api-example","/zh-cn/config/api-exception","/zh-cn/config/xposed-using","/zh-cn/config/api-using","/zh-cn/config/r8-proguard"]},{"text":"\u5DE5\u5177","collapsible":true,"children":["/zh-cn/tools/yukihookapi-projectbuilder"]},{"text":"API \u6587\u6863","collapsible":true,"children":["/zh-cn/api/home",{"text":"Public API\xA0","collapsible":true,"children":["/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI","/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam","/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam","/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources"]},{"text":"\u7279\u8272\u529F\u80FD\xA0","collapsible":true,"children":["/zh-cn/api/special-features/reflection","/zh-cn/api/special-features/logger","/zh-cn/api/special-features/xposed-storage","/zh-cn/api/special-features/xposed-channel","/zh-cn/api/special-features/host-lifecycle","/zh-cn/api/special-features/host-inject"]}]},{"text":"\u5173\u4E8E","collapsible":true,"children":["/zh-cn/about/changelog","/zh-cn/about/future","/zh-cn/about/contacts","/zh-cn/about/about"]}]},"sidebarDepth":2,"locales":{"/en/":{"navbar":[{"text":"Navigation","children":[{"text":"Get Started","children":[{"text":"Introduce","link":"/en/guide/home"},{"text":"Basic Knowledge","link":"/en/guide/knowledge"},{"text":"Quick Start","link":"/en/guide/quick-start"},{"text":"Usage Example","link":"/en/guide/example"},{"text":"Migrate from Xposed API","link":"/en/guide/move-to-new-api"}]},{"text":"Configs","children":[{"text":"API Basic Configs","link":"/en/config/api-example"},{"text":"API Exception Handling","link":"/en/config/api-exception"},{"text":"Use as Xposed Module Configs","link":"/en/config/xposed-using"},{"text":"Use as Hook API Configs","link":"/en/config/api-using"},{"text":"R8 & Proguard Obfuscate","link":"/en/config/r8-proguard"}]},{"text":"Tools","children":[{"text":"YukiHookAPI Project Builder","link":"/en/tools/yukihookapi-projectbuilder"}]},{"text":"API Document","children":[{"text":"Document Introduction","link":"/en/api/home"},{"text":"Public API","link":"/en/api/public/com/highcapable/yukihookapi/YukiHookAPI","activeMatch":"/en/api/public/"},{"text":"Special Features","link":"/en/api/special-features/reflection","activeMatch":"/en/api/special-features/"}]},{"text":"About","children":[{"text":"Changelog","link":"/en/about/changelog"},{"text":"Looking for Future","link":"/en/about/future"},{"text":"Contact Us","link":"/en/about/contacts"},{"text":"About this Document","link":"/en/about/about"}]}]},{"text":"Contact Us","link":"/en/about/contacts"}],"selectLanguageText":"English (US)","selectLanguageName":"English","editLinkText":"Edit this page on Github","tip":"Tips","warning":"Notice","danger":"Pay Attention"},"/zh-cn/":{"navbar":[{"text":"\u5BFC\u822A","children":[{"text":"\u5165\u95E8","children":[{"text":"\u4ECB\u7ECD","link":"/zh-cn/guide/home"},{"text":"\u57FA\u7840\u77E5\u8BC6","link":"/zh-cn/guide/knowledge"},{"text":"\u5FEB\u901F\u5F00\u59CB","link":"/zh-cn/guide/quick-start"},{"text":"\u7528\u6CD5\u793A\u4F8B","link":"/zh-cn/guide/example"},{"text":"\u4ECE Xposed API \u8FC1\u79FB","link":"/zh-cn/guide/move-to-new-api"}]},{"text":"\u914D\u7F6E","children":[{"text":"API \u57FA\u672C\u914D\u7F6E","link":"/zh-cn/config/api-example"},{"text":"API \u5F02\u5E38\u5904\u7406","link":"/zh-cn/config/api-exception"},{"text":"\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E","link":"/zh-cn/config/xposed-using"},{"text":"\u4F5C\u4E3A Hook API \u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E","link":"/zh-cn/config/api-using"},{"text":"R8 \u4E0E Proguard \u6DF7\u6DC6","link":"/zh-cn/config/r8-proguard"}]},{"text":"\u5DE5\u5177","children":[{"text":"YukiHookAPI \u6784\u5EFA\u5DE5\u5177","link":"/zh-cn/tools/yukihookapi-projectbuilder"}]},{"text":"API \u6587\u6863","children":[{"text":"\u6587\u6863\u4ECB\u7ECD","link":"/zh-cn/api/home"},{"text":"Public API","link":"/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI","activeMatch":"/zh-cn/api/public/"},{"text":"\u7279\u8272\u529F\u80FD","link":"/zh-cn/api/special-features/reflection","activeMatch":"/zh-cn/api/special-features/"}]},{"text":"\u5173\u4E8E","children":[{"text":"\u66F4\u65B0\u65E5\u5FD7","link":"/zh-cn/about/changelog"},{"text":"\u5C55\u671B\u672A\u6765","link":"/zh-cn/about/future"},{"text":"\u8054\u7CFB\u6211\u4EEC","link":"/zh-cn/about/contacts"},{"text":"\u5173\u4E8E\u6B64\u6587\u6863","link":"/zh-cn/about/about"}]}]},{"text":"\u8054\u7CFB\u6211\u4EEC","link":"/zh-cn/about/contacts"}],"selectLanguageText":"\u7B80\u4F53\u4E2D\u6587 (CN)","selectLanguageName":"\u7B80\u4F53\u4E2D\u6587","editLinkText":"\u5728 Github \u4E0A\u7F16\u8F91\u6B64\u9875","notFound":["\u8FD9\u91CC\u4EC0\u4E48\u90FD\u6CA1\u6709","\u6211\u4EEC\u600E\u4E48\u5230\u8FD9\u6765\u4E86\uFF1F","\u8FD9\u662F\u4E00\u4E2A 404 \u9875\u9762","\u770B\u8D77\u6765\u6211\u4EEC\u8FDB\u5165\u4E86\u9519\u8BEF\u7684\u94FE\u63A5"],"backToHome":"\u56DE\u5230\u9996\u9875","contributorsText":"\u8D21\u732E\u8005","lastUpdatedText":"\u4E0A\u6B21\u66F4\u65B0","tip":"\u5C0F\u63D0\u793A","warning":"\u6CE8\u610F","danger":"\u7279\u522B\u6CE8\u610F","openInNewWindow":"\u5728\u65B0\u7A97\u53E3\u4E2D\u6253\u5F00","toggleColorMode":"\u5207\u6362\u989C\u8272\u6A21\u5F0F"},"/":{"selectLanguageName":"English"}},"colorMode":"auto","colorModeSwitch":true,"navbar":[],"selectLanguageText":"Languages","selectLanguageAriaLabel":"Select language","editLink":true,"editLinkText":"Edit this page","lastUpdated":true,"lastUpdatedText":"Last Updated","contributors":true,"contributorsText":"Contributors","notFound":["There's nothing here.","How did we get here?","That's a Four-Oh-Four.","Looks like we've got some broken links."],"backToHome":"Take me home","openInNewWindow":"open in new window","toggleColorMode":"toggle color mode","toggleSidebar":"toggle sidebar"}`),Aa=ye(hu),du=()=>Aa;import.meta.webpackHot&&(__VUE_HMR_RUNTIME__.updateThemeData=e=>{Aa.value=e});const Ta=Symbol(""),uu=()=>{const e=He(Ta);if(!e)throw new Error("useThemeLocaleData() is called without provider.");return e},pu=(e,t)=>{var l;return{...e,...(l=e.locales)==null?void 0:l[t]}},mu=Mt({enhance({app:e}){const t=du(),l=e._context.provides[No],i=Y(()=>pu(t.value,l.value));e.provide(Ta,i),Object.defineProperties(e.config.globalProperties,{$theme:{get(){return t.value}},$themeLocale:{get(){return i.value}}})}}),fu=ue({__name:"Badge",props:{type:{type:String,required:!1,default:"tip"},text:{type:String,required:!1,default:""},vertical:{type:String,required:!1,default:void 0}},setup(e){return(t,l)=>(N(),J("span",{class:Ke(["badge",e.type]),style:Sl({verticalAlign:e.vertical})},[Ce(t.$slots,"default",{},()=>[Ht(ze(e.text),1)])],6))}}),Ae=(e,t)=>{const l=e.__vccOpts||e;for(const[i,o]of t)l[i]=o;return l},gu=Ae(fu,[["__file","Badge.vue"]]),ku=ue({name:"CodeGroup",setup(e,{slots:t}){const l=ye(-1),i=ye([]),o=(a=l.value)=>{a{a>0?l.value=a-1:l.value=i.value.length-1,i.value[l.value].focus()},r=(a,s)=>{a.key===" "||a.key==="Enter"?(a.preventDefault(),l.value=s):a.key==="ArrowRight"?(a.preventDefault(),o(s)):a.key==="ArrowLeft"&&(a.preventDefault(),n(s))};return()=>{var s;const a=(((s=t.default)==null?void 0:s.call(t))||[]).filter(c=>c.type.name==="CodeGroupItem").map(c=>(c.props===null&&(c.props={}),c));return a.length===0?null:(l.value<0||l.value>a.length-1?(l.value=a.findIndex(c=>c.props.active===""||c.props.active===!0),l.value===-1&&(l.value=0)):a.forEach((c,h)=>{c.props.active=h===l.value}),he("div",{class:"code-group"},[he("div",{class:"code-group__nav"},he("ul",{class:"code-group__ul"},a.map((c,h)=>{const p=h===l.value;return he("li",{class:"code-group__li"},he("button",{ref:m=>{m&&(i.value[h]=m)},class:{"code-group__nav-tab":!0,"code-group__nav-tab-active":p},ariaPressed:p,ariaExpanded:p,onClick:()=>l.value=h,onKeydown:m=>r(m,h)},c.props.title))}))),a]))}}}),vu=["aria-selected"],bu=ue({name:"CodeGroupItem"}),_u=ue({...bu,props:{title:{type:String,required:!0},active:{type:Boolean,required:!1,default:!1}},setup(e){return(t,l)=>(N(),J("div",{class:Ke(["code-group-item",{"code-group-item__active":e.active}]),"aria-selected":e.active},[Ce(t.$slots,"default")],10,vu))}}),yu=Ae(_u,[["__file","CodeGroupItem.vue"]]);var Qn;const Ia=typeof window<"u",xu=e=>typeof e=="function",Eu=e=>typeof e=="string",Bi=()=>{};Ia&&((Qn=window==null?void 0:window.navigator)==null?void 0:Qn.userAgent)&&/iP(ad|hone|od)/.test(window.navigator.userAgent);function gi(e){return typeof e=="function"?e():O(e)}function Ru(e,t){function l(...i){e(()=>t.apply(this,i),{fn:t,thisArg:this,args:i})}return l}const wa=e=>e();function Cu(e=wa){const t=ye(!0);function l(){t.value=!1}function i(){t.value=!0}return{isActive:t,pause:l,resume:i,eventFilter:(...n)=>{t.value&&e(...n)}}}function Pu(e){return e}function Oa(e){return fs()?(gs(e),!0):!1}function Lu(e,t=!0){wo()?Xr(e):t?e():jl(e)}function Au(e,t=!0){wo()?Ze(e):t?e():jl(e)}function Tu(e=!1,t={}){const{truthyValue:l=!0,falsyValue:i=!1}=t,o=De(e),n=ye(e);function r(a){if(arguments.length)return n.value=a,n.value;{const s=gi(l);return n.value=n.value===s?gi(i):s,n.value}}return o?r:[n,r]}var Zn=Object.getOwnPropertySymbols,Iu=Object.prototype.hasOwnProperty,wu=Object.prototype.propertyIsEnumerable,Ou=(e,t)=>{var l={};for(var i in e)Iu.call(e,i)&&t.indexOf(i)<0&&(l[i]=e[i]);if(e!=null&&Zn)for(var i of Zn(e))t.indexOf(i)<0&&wu.call(e,i)&&(l[i]=e[i]);return l};function Fu(e,t,l={}){const i=l,{eventFilter:o=wa}=i,n=Ou(i,["eventFilter"]);return dt(e,Ru(o,t),n)}var zu=Object.defineProperty,Du=Object.defineProperties,Hu=Object.getOwnPropertyDescriptors,ki=Object.getOwnPropertySymbols,Fa=Object.prototype.hasOwnProperty,za=Object.prototype.propertyIsEnumerable,Jn=(e,t,l)=>t in e?zu(e,t,{enumerable:!0,configurable:!0,writable:!0,value:l}):e[t]=l,Mu=(e,t)=>{for(var l in t||(t={}))Fa.call(t,l)&&Jn(e,l,t[l]);if(ki)for(var l of ki(t))za.call(t,l)&&Jn(e,l,t[l]);return e},Su=(e,t)=>Du(e,Hu(t)),Vu=(e,t)=>{var l={};for(var i in e)Fa.call(e,i)&&t.indexOf(i)<0&&(l[i]=e[i]);if(e!=null&&ki)for(var i of ki(e))t.indexOf(i)<0&&za.call(e,i)&&(l[i]=e[i]);return l};function Nu(e,t,l={}){const i=l,{eventFilter:o}=i,n=Vu(i,["eventFilter"]),{eventFilter:r,pause:a,resume:s,isActive:c}=Cu(o);return{stop:Fu(e,t,Su(Mu({},n),{eventFilter:r})),pause:a,resume:s,isActive:c}}function ju(e){var t;const l=gi(e);return(t=l==null?void 0:l.$el)!=null?t:l}const vi=Ia?window:void 0;function $u(...e){let t,l,i,o;if(Eu(e[0])?([l,i,o]=e,t=vi):[t,l,i,o]=e,!t)return Bi;let n=Bi;const r=dt(()=>ju(t),s=>{n(),s&&(s.addEventListener(l,i,o),n=()=>{s.removeEventListener(l,i,o),n=Bi})},{immediate:!0,flush:"post"}),a=()=>{r(),n()};return Oa(a),a}function Yu(e,t=!1){const l=ye(),i=()=>l.value=Boolean(e());return i(),Au(i,t),l}function Bu(e,t={}){const{window:l=vi}=t,i=Yu(()=>l&&"matchMedia"in l&&typeof l.matchMedia=="function");let o;const n=ye(!1),r=()=>{!i.value||(o||(o=l.matchMedia(e)),n.value=o.matches)};return Lu(()=>{r(),o&&("addEventListener"in o?o.addEventListener("change",r):o.addListener(r),Oa(()=>{"removeEventListener"in o?o.removeEventListener("change",r):o.removeListener(r)}))}),n}const uo=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},po="__vueuse_ssr_handlers__";uo[po]=uo[po]||{};const Uu=uo[po];function Wu(e,t){return Uu[e]||t}function Xu(e){return e==null?"any":e instanceof Set?"set":e instanceof Map?"map":e instanceof Date?"date":typeof e=="boolean"?"boolean":typeof e=="string"?"string":typeof e=="object"||Array.isArray(e)?"object":Number.isNaN(e)?"any":"number"}var qu=Object.defineProperty,er=Object.getOwnPropertySymbols,Ku=Object.prototype.hasOwnProperty,Gu=Object.prototype.propertyIsEnumerable,tr=(e,t,l)=>t in e?qu(e,t,{enumerable:!0,configurable:!0,writable:!0,value:l}):e[t]=l,lr=(e,t)=>{for(var l in t||(t={}))Ku.call(t,l)&&tr(e,l,t[l]);if(er)for(var l of er(t))Gu.call(t,l)&&tr(e,l,t[l]);return e};const Qu={boolean:{read:e=>e==="true",write:e=>String(e)},object:{read:e=>JSON.parse(e),write:e=>JSON.stringify(e)},number:{read:e=>Number.parseFloat(e),write:e=>String(e)},any:{read:e=>e,write:e=>String(e)},string:{read:e=>e,write:e=>String(e)},map:{read:e=>new Map(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e.entries()))},set:{read:e=>new Set(JSON.parse(e)),write:e=>JSON.stringify(Array.from(e))},date:{read:e=>new Date(e),write:e=>e.toISOString()}};function Zu(e,t,l,i={}){var o;const{flush:n="pre",deep:r=!0,listenToStorageChanges:a=!0,writeDefaults:s=!0,mergeDefaults:c=!1,shallow:h,window:p=vi,eventFilter:m,onError:g=w=>{console.error(w)}}=i,x=(h?wr:ye)(t);if(!l)try{l=Wu("getDefaultStorage",()=>{var w;return(w=vi)==null?void 0:w.localStorage})()}catch(w){g(w)}if(!l)return x;const P=gi(t),E=Xu(P),k=(o=i.serializer)!=null?o:Qu[E],{pause:b,resume:L}=Nu(x,()=>M(x.value),{flush:n,deep:r,eventFilter:m});return p&&a&&$u(p,"storage",ee),ee(),x;function M(w){try{w==null?l.removeItem(e):l.setItem(e,k.write(w))}catch(v){g(v)}}function U(w){if(!(w&&w.key!==e)){b();try{const v=w?w.newValue:l.getItem(e);if(v==null)return s&&P!==null&&l.setItem(e,k.write(P)),P;if(!w&&c){const q=k.read(v);return xu(c)?c(q,P):E==="object"&&!Array.isArray(q)?lr(lr({},P),q):q}else return typeof v!="string"?v:k.read(v)}catch(v){g(v)}finally{L()}}}function ee(w){w&&w.key!==e||(x.value=U(w))}}function Ju(e){return Bu("(prefers-color-scheme: dark)",e)}var ir;(function(e){e.UP="UP",e.RIGHT="RIGHT",e.DOWN="DOWN",e.LEFT="LEFT",e.NONE="NONE"})(ir||(ir={}));var ep=Object.defineProperty,or=Object.getOwnPropertySymbols,tp=Object.prototype.hasOwnProperty,lp=Object.prototype.propertyIsEnumerable,nr=(e,t,l)=>t in e?ep(e,t,{enumerable:!0,configurable:!0,writable:!0,value:l}):e[t]=l,ip=(e,t)=>{for(var l in t||(t={}))tp.call(t,l)&&nr(e,l,t[l]);if(or)for(var l of or(t))lp.call(t,l)&&nr(e,l,t[l]);return e};const op={easeInSine:[.12,0,.39,0],easeOutSine:[.61,1,.88,1],easeInOutSine:[.37,0,.63,1],easeInQuad:[.11,0,.5,0],easeOutQuad:[.5,1,.89,1],easeInOutQuad:[.45,0,.55,1],easeInCubic:[.32,0,.67,0],easeOutCubic:[.33,1,.68,1],easeInOutCubic:[.65,0,.35,1],easeInQuart:[.5,0,.75,0],easeOutQuart:[.25,1,.5,1],easeInOutQuart:[.76,0,.24,1],easeInQuint:[.64,0,.78,0],easeOutQuint:[.22,1,.36,1],easeInOutQuint:[.83,0,.17,1],easeInExpo:[.7,0,.84,0],easeOutExpo:[.16,1,.3,1],easeInOutExpo:[.87,0,.13,1],easeInCirc:[.55,0,1,.45],easeOutCirc:[0,.55,.45,1],easeInOutCirc:[.85,0,.15,1],easeInBack:[.36,0,.66,-.56],easeOutBack:[.34,1.56,.64,1],easeInOutBack:[.68,-.6,.32,1.6]};ip({linear:Pu},op);const $e=()=>uu(),Da=Symbol(""),Ho=()=>{const e=He(Da);if(!e)throw new Error("useDarkMode() is called without provider.");return e},np=()=>{const e=$e(),t=Ju(),l=Zu("vuepress-color-scheme",e.value.colorMode),i=Y({get(){return e.value.colorModeSwitch?l.value==="auto"?t.value:l.value==="dark":e.value.colorMode==="dark"},set(o){o===t.value?l.value="auto":l.value=o?"dark":"light"}});Gt(Da,i),rp(i)},rp=e=>{const t=(l=e.value)=>{const i=window==null?void 0:window.document.querySelector("html");i==null||i.classList.toggle("dark",l)};Ze(()=>{dt(e,t,{immediate:!0})}),Li(()=>t())},Ha=(...e)=>{const l=Jt().resolve(...e),i=l.matched[l.matched.length-1];if(!(i!=null&&i.redirect))return l;const{redirect:o}=i,n=re(o)?o(l):o,r=be(n)?{path:n}:n;return Ha({hash:l.hash,query:l.query,params:l.params,...r})},Mo=e=>{const t=Ha(encodeURI(e));return{text:t.meta.title||e,link:t.name==="404"?e:t.fullPath}};let Ui=null,yl=null;const ap={wait:()=>Ui,pending:()=>{Ui=new Promise(e=>yl=e)},resolve:()=>{yl==null||yl(),Ui=null,yl=null}},Ma=()=>ap,Sa=Symbol("sidebarItems"),So=()=>{const e=He(Sa);if(!e)throw new Error("useSidebarItems() is called without provider.");return e},sp=()=>{const e=$e(),t=vt(),l=Y(()=>cp(t.value,e.value));Gt(Sa,l)},cp=(e,t)=>{var o,n,r,a;const l=(n=(o=e.sidebar)!=null?o:t.sidebar)!=null?n:"auto",i=(a=(r=e.sidebarDepth)!=null?r:t.sidebarDepth)!=null?a:2;return e.home||l===!1?[]:l==="auto"?dp(i):te(l)?Va(l,i):Oo(l)?up(l,i):[]},hp=(e,t)=>({text:e.title,link:e.link,children:Vo(e.children,t)}),Vo=(e,t)=>t>0?e.map(l=>hp(l,t-1)):[],dp=e=>{const t=Ot();return[{text:t.value.title,children:Vo(t.value.headers,e)}]},Va=(e,t)=>{const l=St(),i=Ot(),o=n=>{var a;let r;if(be(n)?r=Mo(n):r=n,r.children)return{...r,children:r.children.map(s=>o(s))};if(r.link===l.path){const s=((a=i.value.headers[0])==null?void 0:a.level)===1?i.value.headers[0].children:i.value.headers;return{...r,children:Vo(s,t)}}return r};return e.map(n=>o(n))},up=(e,t)=>{var n;const l=St(),i=pa(e,l.path),o=(n=e[i])!=null?n:[];return Va(o,t)},pp={},mp={class:"theme-default-content"};function fp(e,t){const l=_t("Content");return N(),J("div",mp,[oe(l)])}const gp=Ae(pp,[["render",fp],["__file","HomeContent.vue"]]),kp={key:0,class:"features"},vp=ue({__name:"HomeFeatures",setup(e){const t=vt(),l=Y(()=>te(t.value.features)?t.value.features:[]);return(i,o)=>O(l).length?(N(),J("div",kp,[(N(!0),J(Pe,null,zt(O(l),n=>(N(),J("div",{key:n.title,class:"feature"},[fe("h2",null,ze(n.title),1),fe("p",null,ze(n.details),1)]))),128))])):Te("v-if",!0)}}),bp=Ae(vp,[["__file","HomeFeatures.vue"]]),_p=["innerHTML"],yp=["textContent"],xp=ue({__name:"HomeFooter",setup(e){const t=vt(),l=Y(()=>t.value.footer),i=Y(()=>t.value.footerHtml);return(o,n)=>O(l)?(N(),J(Pe,{key:0},[Te(" eslint-disable-next-line vue/no-v-html "),O(i)?(N(),J("div",{key:0,class:"footer",innerHTML:O(l)},null,8,_p)):(N(),J("div",{key:1,class:"footer",textContent:ze(O(l))},null,8,yp))],64)):Te("v-if",!0)}}),Ep=Ae(xp,[["__file","HomeFooter.vue"]]),Rp=["href","rel","target","aria-label"],Cp=ue({inheritAttrs:!1}),Pp=ue({...Cp,__name:"AutoLink",props:{item:{type:Object,required:!0}},setup(e){const t=e,l=St(),i=Ga(),{item:o}=Ei(t),n=Y(()=>Ul(o.value.link)),r=Y(()=>wh(o.value.link)||Oh(o.value.link)),a=Y(()=>{if(!r.value){if(o.value.target)return o.value.target;if(n.value)return"_blank"}}),s=Y(()=>a.value==="_blank"),c=Y(()=>!n.value&&!r.value&&!s.value),h=Y(()=>{if(!r.value){if(o.value.rel)return o.value.rel;if(s.value)return"noopener noreferrer"}}),p=Y(()=>o.value.ariaLabel||o.value.text),m=Y(()=>{const P=Object.keys(i.value.locales);return P.length?!P.some(E=>E===o.value.link):o.value.link!=="/"}),g=Y(()=>m.value?l.path.startsWith(o.value.link):!1),x=Y(()=>c.value?o.value.activeMatch?new RegExp(o.value.activeMatch).test(l.path):g.value:!1);return(P,E)=>{const k=_t("RouterLink"),b=_t("AutoLinkExternalIcon");return O(c)?(N(),we(k,no({key:0,class:{"router-link-active":O(x)},to:O(o).link,"aria-label":O(p)},P.$attrs),{default:Me(()=>[Ce(P.$slots,"before"),Ht(" "+ze(O(o).text)+" ",1),Ce(P.$slots,"after")]),_:3},16,["class","to","aria-label"])):(N(),J("a",no({key:1,class:"external-link",href:O(o).link,rel:O(h),target:O(a),"aria-label":O(p)},P.$attrs),[Ce(P.$slots,"before"),Ht(" "+ze(O(o).text)+" ",1),O(s)?(N(),we(b,{key:0})):Te("v-if",!0),Ce(P.$slots,"after")],16,Rp))}}}),kt=Ae(Pp,[["__file","AutoLink.vue"]]),Lp={class:"hero"},Ap={key:0,id:"main-title"},Tp={key:1,class:"description"},Ip={key:2,class:"actions"},wp=ue({__name:"HomeHero",setup(e){const t=vt(),l=jo(),i=Ho(),o=Y(()=>i.value&&t.value.heroImageDark!==void 0?t.value.heroImageDark:t.value.heroImage),n=Y(()=>t.value.heroText===null?null:t.value.heroText||l.value.title||"Hello"),r=Y(()=>t.value.heroAlt||n.value||"hero"),a=Y(()=>t.value.tagline===null?null:t.value.tagline||l.value.description||"Welcome to your VuePress site"),s=Y(()=>te(t.value.actions)?t.value.actions.map(({text:h,link:p,type:m="primary"})=>({text:h,link:p,type:m})):[]),c=()=>{if(!o.value)return null;const h=he("img",{src:Yo(o.value),alt:r.value});return t.value.heroImageDark===void 0?h:he($o,()=>h)};return(h,p)=>(N(),J("header",Lp,[oe(c),O(n)?(N(),J("h1",Ap,ze(O(n)),1)):Te("v-if",!0),O(a)?(N(),J("p",Tp,ze(O(a)),1)):Te("v-if",!0),O(s).length?(N(),J("p",Ip,[(N(!0),J(Pe,null,zt(O(s),m=>(N(),we(kt,{key:m.text,class:Ke(["action-button",[m.type]]),item:m},null,8,["class","item"]))),128))])):Te("v-if",!0)]))}}),Op=Ae(wp,[["__file","HomeHero.vue"]]),Fp={class:"home"},zp=ue({__name:"Home",setup(e){return(t,l)=>(N(),J("main",Fp,[oe(Op),oe(bp),oe(gp),oe(Ep)]))}}),Dp=Ae(zp,[["__file","Home.vue"]]),Hp=ue({__name:"NavbarBrand",setup(e){const t=Wl(),l=jo(),i=$e(),o=Ho(),n=Y(()=>i.value.home||t.value),r=Y(()=>l.value.title),a=Y(()=>o.value&&i.value.logoDark!==void 0?i.value.logoDark:i.value.logo),s=()=>{if(!a.value)return null;const c=he("img",{class:"logo",src:Yo(a.value),alt:r.value});return i.value.logoDark===void 0?c:he($o,()=>c)};return(c,h)=>{const p=_t("RouterLink");return N(),we(p,{to:O(n)},{default:Me(()=>[oe(s),O(r)?(N(),J("span",{key:0,class:Ke(["site-name",{"can-hide":O(a)}])},ze(O(r)),3)):Te("v-if",!0)]),_:1},8,["to"])}}}),Mp=Ae(Hp,[["__file","NavbarBrand.vue"]]),Sp=ue({__name:"DropdownTransition",setup(e){const t=i=>{i.style.height=i.scrollHeight+"px"},l=i=>{i.style.height=""};return(i,o)=>(N(),we(Bl,{name:"dropdown",onEnter:t,onAfterEnter:l,onBeforeLeave:t},{default:Me(()=>[Ce(i.$slots,"default")]),_:3}))}}),Na=Ae(Sp,[["__file","DropdownTransition.vue"]]),Vp=["aria-label"],Np={class:"title"},jp=fe("span",{class:"arrow down"},null,-1),$p=["aria-label"],Yp={class:"title"},Bp={class:"navbar-dropdown"},Up={class:"navbar-dropdown-subtitle"},Wp={key:1},Xp={class:"navbar-dropdown-subitem-wrapper"},qp=ue({__name:"NavbarDropdown",props:{item:{type:Object,required:!0}},setup(e){const t=e,{item:l}=Ei(t),i=Y(()=>l.value.ariaLabel||l.value.text),o=ye(!1),n=St();dt(()=>n.path,()=>{o.value=!1});const r=s=>{s.detail===0?o.value=!o.value:o.value=!1},a=(s,c)=>c[c.length-1]===s;return(s,c)=>(N(),J("div",{class:Ke(["navbar-dropdown-wrapper",{open:o.value}])},[fe("button",{class:"navbar-dropdown-title",type:"button","aria-label":O(i),onClick:r},[fe("span",Np,ze(O(l).text),1),jp],8,Vp),fe("button",{class:"navbar-dropdown-title-mobile",type:"button","aria-label":O(i),onClick:c[0]||(c[0]=h=>o.value=!o.value)},[fe("span",Yp,ze(O(l).text),1),fe("span",{class:Ke(["arrow",o.value?"down":"right"])},null,2)],8,$p),oe(Na,null,{default:Me(()=>[ci(fe("ul",Bp,[(N(!0),J(Pe,null,zt(O(l).children,h=>(N(),J("li",{key:h.text,class:"navbar-dropdown-item"},[h.children?(N(),J(Pe,{key:0},[fe("h4",Up,[h.link?(N(),we(kt,{key:0,item:h,onFocusout:p=>a(h,O(l).children)&&h.children.length===0&&(o.value=!1)},null,8,["item","onFocusout"])):(N(),J("span",Wp,ze(h.text),1))]),fe("ul",Xp,[(N(!0),J(Pe,null,zt(h.children,p=>(N(),J("li",{key:p.link,class:"navbar-dropdown-subitem"},[oe(kt,{item:p,onFocusout:m=>a(p,h.children)&&a(h,O(l).children)&&(o.value=!1)},null,8,["item","onFocusout"])]))),128))])],64)):(N(),we(kt,{key:1,item:h,onFocusout:p=>a(h,O(l).children)&&(o.value=!1)},null,8,["item","onFocusout"]))]))),128))],512),[[mi,o.value]])]),_:1})],2))}}),Kp=Ae(qp,[["__file","NavbarDropdown.vue"]]),rr=e=>decodeURI(e).replace(/#.*$/,"").replace(/(index)?\.(md|html)$/,""),Gp=(e,t)=>{if(t.hash===e)return!0;const l=rr(t.path),i=rr(e);return l===i},ja=(e,t)=>e.link&&Gp(e.link,t)?!0:e.children?e.children.some(l=>ja(l,t)):!1,$a=e=>!Ul(e)||/github\.com/.test(e)?"GitHub":/bitbucket\.org/.test(e)?"Bitbucket":/gitlab\.com/.test(e)?"GitLab":/gitee\.com/.test(e)?"Gitee":null,Qp={GitHub:":repo/edit/:branch/:path",GitLab:":repo/-/edit/:branch/:path",Gitee:":repo/edit/:branch/:path",Bitbucket:":repo/src/:branch/:path?mode=edit&spa=0&at=:branch&fileviewer=file-view-default"},Zp=({docsRepo:e,editLinkPattern:t})=>{if(t)return t;const l=$a(e);return l!==null?Qp[l]:null},Jp=({docsRepo:e,docsBranch:t,docsDir:l,filePathRelative:i,editLinkPattern:o})=>{if(!i)return null;const n=Zp({docsRepo:e,editLinkPattern:o});return n?n.replace(/:repo/,Ul(e)?e:`https://github.com/${e}`).replace(/:branch/,t).replace(/:path/,ua(`${da(l)}/${i}`)):null},em={key:0,class:"navbar-items"},tm=ue({__name:"NavbarItems",setup(e){const t=()=>{const c=Jt(),h=Wl(),p=jo(),m=$e();return Y(()=>{var b,L,M;const g=Object.keys(p.value.locales);if(g.length<2)return[];const x=c.currentRoute.value.path,P=c.currentRoute.value.fullPath,E=c.currentRoute.value.hash;return[{text:(b=m.value.selectLanguageText)!=null?b:"unknown language",ariaLabel:(M=(L=m.value.selectLanguageAriaLabel)!=null?L:m.value.selectLanguageText)!=null?M:"unknown language",children:g.map(U=>{var G,R,S,F,ae,j;const ee=(R=(G=p.value.locales)==null?void 0:G[U])!=null?R:{},w=(F=(S=m.value.locales)==null?void 0:S[U])!=null?F:{},v=`${ee.lang}`,q=(ae=w.selectLanguageName)!=null?ae:v;let B;if(v===p.value.lang)B=P;else{const le=x.replace(h.value,U);c.getRoutes().some(se=>se.path===le)?B=`${le}${E}`:B=(j=w.home)!=null?j:U}return{text:q,link:B}})}]})},l=()=>{const c=$e(),h=Y(()=>c.value.repo),p=Y(()=>h.value?$a(h.value):null),m=Y(()=>h.value&&!Ul(h.value)?`https://github.com/${h.value}`:h.value),g=Y(()=>m.value?c.value.repoLabel?c.value.repoLabel:p.value===null?"Source":p.value:null);return Y(()=>!m.value||!g.value?[]:[{text:g.value,link:m.value}])},i=c=>be(c)?Mo(c):c.children?{...c,children:c.children.map(i)}:c,n=(()=>{const c=$e();return Y(()=>(c.value.navbar||[]).map(i))})(),r=t(),a=l(),s=Y(()=>[...n.value,...r.value,...a.value]);return(c,h)=>O(s).length?(N(),J("nav",em,[(N(!0),J(Pe,null,zt(O(s),p=>(N(),J("div",{key:p.text,class:"navbar-item"},[p.children?(N(),we(Kp,{key:0,item:p},null,8,["item"])):(N(),we(kt,{key:1,item:p},null,8,["item"]))]))),128))])):Te("v-if",!0)}}),Ya=Ae(tm,[["__file","NavbarItems.vue"]]),lm=["title"],im={class:"icon",focusable:"false",viewBox:"0 0 32 32"},om=jc('',9),nm=[om],rm={class:"icon",focusable:"false",viewBox:"0 0 32 32"},am=fe("path",{d:"M13.502 5.414a15.075 15.075 0 0 0 11.594 18.194a11.113 11.113 0 0 1-7.975 3.39c-.138 0-.278.005-.418 0a11.094 11.094 0 0 1-3.2-21.584M14.98 3a1.002 1.002 0 0 0-.175.016a13.096 13.096 0 0 0 1.825 25.981c.164.006.328 0 .49 0a13.072 13.072 0 0 0 10.703-5.555a1.01 1.01 0 0 0-.783-1.565A13.08 13.08 0 0 1 15.89 4.38A1.015 1.015 0 0 0 14.98 3z",fill:"currentColor"},null,-1),sm=[am],cm=ue({__name:"ToggleColorModeButton",setup(e){const t=$e(),l=Ho(),i=()=>{l.value=!l.value};return(o,n)=>(N(),J("button",{class:"toggle-color-mode-button",title:O(t).toggleColorMode,onClick:i},[ci((N(),J("svg",im,nm,512)),[[mi,!O(l)]]),ci((N(),J("svg",rm,sm,512)),[[mi,O(l)]])],8,lm))}}),hm=Ae(cm,[["__file","ToggleColorModeButton.vue"]]),dm=["title"],um=fe("div",{class:"icon","aria-hidden":"true"},[fe("span"),fe("span"),fe("span")],-1),pm=[um],mm=ue({__name:"ToggleSidebarButton",emits:["toggle"],setup(e){const t=$e();return(l,i)=>(N(),J("div",{class:"toggle-sidebar-button",title:O(t).toggleSidebar,"aria-expanded":"false",role:"button",tabindex:"0",onClick:i[0]||(i[0]=o=>l.$emit("toggle"))},pm,8,dm))}}),fm=Ae(mm,[["__file","ToggleSidebarButton.vue"]]),gm=ue({__name:"Navbar",emits:["toggle-sidebar"],setup(e){const t=$e(),l=ye(null),i=ye(null),o=ye(0),n=Y(()=>o.value?{maxWidth:o.value+"px"}:{});Ze(()=>{const s=r(l.value,"paddingLeft")+r(l.value,"paddingRight"),c=()=>{var h;window.innerWidth<=719?o.value=0:o.value=l.value.offsetWidth-s-(((h=i.value)==null?void 0:h.offsetWidth)||0)};c(),window.addEventListener("resize",c,!1),window.addEventListener("orientationchange",c,!1)});function r(a,s){var p,m,g;const c=(g=(m=(p=a==null?void 0:a.ownerDocument)==null?void 0:p.defaultView)==null?void 0:m.getComputedStyle(a,null))==null?void 0:g[s],h=Number.parseInt(c,10);return Number.isNaN(h)?0:h}return(a,s)=>{const c=_t("NavbarSearch");return N(),J("header",{ref_key:"navbar",ref:l,class:"navbar"},[oe(fm,{onToggle:s[0]||(s[0]=h=>a.$emit("toggle-sidebar"))}),fe("span",{ref_key:"navbarBrand",ref:i},[oe(Mp)],512),fe("div",{class:"navbar-items-wrapper",style:Sl(O(n))},[Ce(a.$slots,"before"),oe(Ya,{class:"can-hide"}),Ce(a.$slots,"after"),O(t).colorModeSwitch?(N(),we(hm,{key:0})):Te("v-if",!0),oe(c)],4)],512)}}}),km=Ae(gm,[["__file","Navbar.vue"]]),vm={class:"page-meta"},bm={key:0,class:"meta-item edit-link"},_m={key:1,class:"meta-item last-updated"},ym={class:"meta-item-label"},xm={class:"meta-item-info"},Em={key:2,class:"meta-item contributors"},Rm={class:"meta-item-label"},Cm={class:"meta-item-info"},Pm=["title"],Lm=Ht(", "),Am=ue({__name:"PageMeta",setup(e){const t=()=>{const s=$e(),c=Ot(),h=vt();return Y(()=>{var b,L,M;if(!((L=(b=h.value.editLink)!=null?b:s.value.editLink)!=null?L:!0))return null;const{repo:m,docsRepo:g=m,docsBranch:x="main",docsDir:P="",editLinkText:E}=s.value;if(!g)return null;const k=Jp({docsRepo:g,docsBranch:x,docsDir:P,filePathRelative:c.value.filePathRelative,editLinkPattern:(M=h.value.editLinkPattern)!=null?M:s.value.editLinkPattern});return k?{text:E!=null?E:"Edit this page",link:k}:null})},l=()=>{const s=$e(),c=Ot(),h=vt();return Y(()=>{var g,x,P,E;return!((x=(g=h.value.lastUpdated)!=null?g:s.value.lastUpdated)!=null?x:!0)||!((P=c.value.git)!=null&&P.updatedTime)?null:new Date((E=c.value.git)==null?void 0:E.updatedTime).toLocaleString()})},i=()=>{const s=$e(),c=Ot(),h=vt();return Y(()=>{var m,g,x,P;return((g=(m=h.value.contributors)!=null?m:s.value.contributors)!=null?g:!0)&&(P=(x=c.value.git)==null?void 0:x.contributors)!=null?P:null})},o=$e(),n=t(),r=l(),a=i();return(s,c)=>{const h=_t("ClientOnly");return N(),J("footer",vm,[O(n)?(N(),J("div",bm,[oe(kt,{class:"meta-item-label",item:O(n)},null,8,["item"])])):Te("v-if",!0),O(r)?(N(),J("div",_m,[fe("span",ym,ze(O(o).lastUpdatedText)+": ",1),oe(h,null,{default:Me(()=>[fe("span",xm,ze(O(r)),1)]),_:1})])):Te("v-if",!0),O(a)&&O(a).length?(N(),J("div",Em,[fe("span",Rm,ze(O(o).contributorsText)+": ",1),fe("span",Cm,[(N(!0),J(Pe,null,zt(O(a),(p,m)=>(N(),J(Pe,{key:m},[fe("span",{class:"contributor",title:`email: ${p.email}`},ze(p.name),9,Pm),m!==O(a).length-1?(N(),J(Pe,{key:0},[Lm],64)):Te("v-if",!0)],64))),128))])])):Te("v-if",!0)])}}}),Tm=Ae(Am,[["__file","PageMeta.vue"]]),Im={key:0,class:"page-nav"},wm={class:"inner"},Om={key:0,class:"prev"},Fm={key:1,class:"next"},zm=ue({__name:"PageNav",setup(e){const t=s=>s===!1?null:be(s)?Mo(s):Oo(s)?s:!1,l=(s,c,h)=>{const p=s.findIndex(m=>m.link===c);if(p!==-1){const m=s[p+h];return m!=null&&m.link?m:null}for(const m of s)if(m.children){const g=l(m.children,c,h);if(g)return g}return null},i=vt(),o=So(),n=St(),r=Y(()=>{const s=t(i.value.prev);return s!==!1?s:l(o.value,n.path,-1)}),a=Y(()=>{const s=t(i.value.next);return s!==!1?s:l(o.value,n.path,1)});return(s,c)=>O(r)||O(a)?(N(),J("nav",Im,[fe("p",wm,[O(r)?(N(),J("span",Om,[oe(kt,{item:O(r)},null,8,["item"])])):Te("v-if",!0),O(a)?(N(),J("span",Fm,[oe(kt,{item:O(a)},null,8,["item"])])):Te("v-if",!0)])])):Te("v-if",!0)}}),Dm=Ae(zm,[["__file","PageNav.vue"]]),Hm={class:"page"},Mm={class:"theme-default-content"},Sm=ue({__name:"Page",setup(e){return(t,l)=>{const i=_t("Content");return N(),J("main",Hm,[Ce(t.$slots,"top"),fe("div",Mm,[Ce(t.$slots,"content-top"),oe(i),Ce(t.$slots,"content-bottom")]),oe(Tm),oe(Dm),Ce(t.$slots,"bottom")])}}}),Vm=Ae(Sm,[["__file","Page.vue"]]),Nm=["onKeydown"],jm={class:"sidebar-item-children"},$m=ue({__name:"SidebarItem",props:{item:{type:Object,required:!0},depth:{type:Number,required:!1,default:0}},setup(e){const t=e,{item:l,depth:i}=Ei(t),o=St(),n=Jt(),r=Y(()=>ja(l.value,o)),a=Y(()=>({"sidebar-item":!0,"sidebar-heading":i.value===0,active:r.value,collapsible:l.value.collapsible})),s=Y(()=>l.value.collapsible?r.value:!0),[c,h]=Tu(s.value),p=g=>{l.value.collapsible&&(g.preventDefault(),h())},m=n.afterEach(g=>{jl(()=>{c.value=s.value})});return Yl(()=>{m()}),(g,x)=>{var E;const P=_t("SidebarItem",!0);return N(),J("li",null,[O(l).link?(N(),we(kt,{key:0,class:Ke(O(a)),item:O(l)},null,8,["class","item"])):(N(),J("p",{key:1,tabindex:"0",class:Ke(O(a)),onClick:p,onKeydown:Eh(p,["enter"])},[Ht(ze(O(l).text)+" ",1),O(l).collapsible?(N(),J("span",{key:0,class:Ke(["arrow",O(c)?"down":"right"])},null,2)):Te("v-if",!0)],42,Nm)),(E=O(l).children)!=null&&E.length?(N(),we(Na,{key:2},{default:Me(()=>[ci(fe("ul",jm,[(N(!0),J(Pe,null,zt(O(l).children,k=>(N(),we(P,{key:`${O(i)}${k.text}${k.link}`,item:k,depth:O(i)+1},null,8,["item","depth"]))),128))],512),[[mi,O(c)]])]),_:1})):Te("v-if",!0)])}}}),Ym=Ae($m,[["__file","SidebarItem.vue"]]),Bm={key:0,class:"sidebar-items"},Um=ue({__name:"SidebarItems",setup(e){const t=St(),l=So();return Ze(()=>{dt(()=>t.hash,i=>{const o=document.querySelector(".sidebar");if(!o)return;const n=document.querySelector(`.sidebar a.sidebar-item[href="${t.path}${i}"]`);if(!n)return;const{top:r,height:a}=o.getBoundingClientRect(),{top:s,height:c}=n.getBoundingClientRect();sr+a&&n.scrollIntoView(!1)})}),(i,o)=>O(l).length?(N(),J("ul",Bm,[(N(!0),J(Pe,null,zt(O(l),n=>(N(),we(Ym,{key:`${n.text}${n.link}`,item:n},null,8,["item"]))),128))])):Te("v-if",!0)}}),Wm=Ae(Um,[["__file","SidebarItems.vue"]]),Xm={class:"sidebar"},qm=ue({__name:"Sidebar",setup(e){return(t,l)=>(N(),J("aside",Xm,[oe(Ya),Ce(t.$slots,"top"),oe(Wm),Ce(t.$slots,"bottom")]))}}),Km=Ae(qm,[["__file","Sidebar.vue"]]),Gm=ue({__name:"Layout",setup(e){const t=Ot(),l=vt(),i=$e(),o=Y(()=>l.value.navbar!==!1&&i.value.navbar!==!1),n=So(),r=ye(!1),a=E=>{r.value=typeof E=="boolean"?E:!r.value},s={x:0,y:0},c=E=>{s.x=E.changedTouches[0].clientX,s.y=E.changedTouches[0].clientY},h=E=>{const k=E.changedTouches[0].clientX-s.x,b=E.changedTouches[0].clientY-s.y;Math.abs(k)>Math.abs(b)&&Math.abs(k)>40&&(k>0&&s.x<=80?a(!0):a(!1))},p=Y(()=>[{"no-navbar":!o.value,"no-sidebar":!n.value.length,"sidebar-open":r.value},l.value.pageClass]);let m;Ze(()=>{m=Jt().afterEach(()=>{a(!1)})}),Li(()=>{m()});const g=Ma(),x=g.resolve,P=g.pending;return(E,k)=>(N(),J("div",{class:Ke(["theme-container",O(p)]),onTouchstart:c,onTouchend:h},[Ce(E.$slots,"navbar",{},()=>[O(o)?(N(),we(km,{key:0,onToggleSidebar:a},{before:Me(()=>[Ce(E.$slots,"navbar-before")]),after:Me(()=>[Ce(E.$slots,"navbar-after")]),_:3})):Te("v-if",!0)]),fe("div",{class:"sidebar-mask",onClick:k[0]||(k[0]=b=>a(!1))}),Ce(E.$slots,"sidebar",{},()=>[oe(Km,null,{top:Me(()=>[Ce(E.$slots,"sidebar-top")]),bottom:Me(()=>[Ce(E.$slots,"sidebar-bottom")]),_:3})]),Ce(E.$slots,"page",{},()=>[O(l).home?(N(),we(Dp,{key:0})):(N(),we(Bl,{key:1,name:"fade-slide-y",mode:"out-in",onBeforeEnter:O(x),onBeforeLeave:O(P)},{default:Me(()=>[(N(),we(Vm,{key:O(t).path},{top:Me(()=>[Ce(E.$slots,"page-top")]),"content-top":Me(()=>[Ce(E.$slots,"page-content-top")]),"content-bottom":Me(()=>[Ce(E.$slots,"page-content-bottom")]),bottom:Me(()=>[Ce(E.$slots,"page-bottom")]),_:3}))]),_:3},8,["onBeforeEnter","onBeforeLeave"]))])],34))}}),Qm=Ae(Gm,[["__file","Layout.vue"]]),Zm={class:"theme-container"},Jm={class:"page"},ef={class:"theme-default-content"},tf=fe("h1",null,"404",-1),lf=ue({__name:"NotFound",setup(e){var a,s,c;const t=Wl(),l=$e(),i=(a=l.value.notFound)!=null?a:["Not Found"],o=()=>i[Math.floor(Math.random()*i.length)],n=(s=l.value.home)!=null?s:t.value,r=(c=l.value.backToHome)!=null?c:"Back to home";return(h,p)=>{const m=_t("RouterLink");return N(),J("div",Zm,[fe("main",Jm,[fe("div",ef,[tf,fe("blockquote",null,ze(o()),1),oe(m,{to:O(n)},{default:Me(()=>[Ht(ze(O(r)),1)]),_:1},8,["to"])])])])}}}),of=Ae(lf,[["__file","NotFound.vue"]]);const nf=Mt({enhance({app:e,router:t}){e.component("Badge",gu),e.component("CodeGroup",ku),e.component("CodeGroupItem",yu),e.component("AutoLinkExternalIcon",()=>{const i=e.component("ExternalLinkIcon");return i?he(i):null}),e.component("NavbarSearch",()=>{const i=e.component("Docsearch")||e.component("SearchBox");return i?he(i):null});const l=t.options.scrollBehavior;t.options.scrollBehavior=async(...i)=>(await Ma().wait(),l(...i))},setup(){np(),sp()},layouts:{Layout:Qm,NotFound:of}}),rf=(e,t)=>t.some(l=>{if(be(l))return l===e.key;const{key:i,ctrl:o=!1,shift:n=!1,alt:r=!1}=l;return i===e.key&&o===e.ctrlKey&&n===e.shiftKey&&r===e.altKey}),af=/[^\x00-\x7F]/,sf=e=>e.split(/\s+/g).map(t=>t.trim()).filter(t=>!!t),ar=e=>e.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"),sr=(e,t)=>{const l=t.join(" "),i=sf(e);if(af.test(e))return i.some(r=>l.toLowerCase().indexOf(r)>-1);const o=e.endsWith(" ");return new RegExp(i.map((r,a)=>i.length===a+1&&!o?`(?=.*\\b${ar(r)})`:`(?=.*\\b${ar(r)}\\b)`).join("")+".+","gi").test(l)},cf=({input:e,hotKeys:t})=>{if(t.value.length===0)return;const l=i=>{!e.value||rf(i,t.value)&&!e.value.contains(i.target)&&(i.preventDefault(),e.value.focus())};Ze(()=>{document.addEventListener("keydown",l)}),Yl(()=>{document.removeEventListener("keydown",l)})},hf=[{title:"Home",headers:[{level:3,title:"All Hook process in one step, everything is simplified",slug:"all-hook-process-in-one-step-everything-is-simplified",link:"#all-hook-process-in-one-step-everything-is-simplified",children:[]}],path:"/en/",pathLocale:"/en/",extraFields:[]},{title:"\u9996\u9875",headers:[{level:3,title:"\u6240\u6709 Hook \u6D41\u7A0B\u4E00\u6B65\u5230\u4F4D\uFF0C\u62D2\u7EDD\u7E41\u7410",slug:"\u6240\u6709-hook-\u6D41\u7A0B\u4E00\u6B65\u5230\u4F4D-\u62D2\u7EDD\u7E41\u7410",link:"#\u6240\u6709-hook-\u6D41\u7A0B\u4E00\u6B65\u5230\u4F4D-\u62D2\u7EDD\u7E41\u7410",children:[]}],path:"/zh-cn/",pathLocale:"/zh-cn/",extraFields:[]},{title:"About this Document",headers:[{level:2,title:"License",slug:"license",link:"#license",children:[]}],path:"/en/about/about.html",pathLocale:"/en/",extraFields:[]},{title:"Changelog",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:[]}],path:"/en/about/changelog.html",pathLocale:"/en/",extraFields:[]},{title:"Contact Us",headers:[{level:2,title:"Help with Maintenance",slug:"help-with-maintenance",link:"#help-with-maintenance",children:[]}],path:"/en/about/contacts.html",pathLocale:"/en/",extraFields:[]},{title:"Looking for Future",headers:[{level:2,title:"Unresolved Issues",slug:"unresolved-issues",link:"#unresolved-issues",children:[{level:3,title:"YukiHookModulePrefs",slug:"yukihookmoduleprefs",link:"#yukihookmoduleprefs",children:[]}]},{level:2,title:"Future Plans",slug:"future-plans",link:"#future-plans",children:[{level:3,title:"Lite Version Supported for Standalone Use",slug:"lite-version-supported-for-standalone-use",link:"#lite-version-supported-for-standalone-use",children:[]},{level:3,title:"Support for More Hook Framework",slug:"support-for-more-hook-framework",link:"#support-for-more-hook-framework",children:[]}]}],path:"/en/about/future.html",pathLocale:"/en/",extraFields:[]},{title:"Document Introduce",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:[]}],path:"/en/api/home.html",pathLocale:"/en/",extraFields:[]},{title:"API Basic Configs",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:[]}],path:"/en/config/api-example.html",pathLocale:"/en/",extraFields:[]},{title:"API Exception Handling",headers:[{level:2,title:"Non-Blocking Exceptions",slug:"non-blocking-exceptions",link:"#non-blocking-exceptions",children:[]},{level:2,title:"Blocking Exceptions",slug:"blocking-exceptions",link:"#blocking-exceptions",children:[]}],path:"/en/config/api-exception.html",pathLocale:"/en/",extraFields:[]},{title:"Use as Hook API Configs",headers:[{level:2,title:"Dependency Configs",slug:"dependency-configs",link:"#dependency-configs",children:[]},{level:2,title:"Entry Configs",slug:"entry-configs",link:"#entry-configs",children:[]},{level:2,title:"Hook Framework",slug:"hook-framework",link:"#hook-framework",children:[{level:3,title:"Pine",slug:"pine",link:"#pine",children:[]},{level:3,title:"SandHook",slug:"sandhook",link:"#sandhook",children:[]},{level:3,title:"Whale",slug:"whale",link:"#whale",children:[]}]}],path:"/en/config/api-using.html",pathLocale:"/en/",extraFields:[]},{title:"R8 & Proguard Obfuscate",headers:[{level:2,title:"R8",slug:"r8",link:"#r8",children:[]},{level:2,title:"Proguard",slug:"proguard",link:"#proguard",children:[]}],path:"/en/config/r8-proguard.html",pathLocale:"/en/",extraFields:[]},{title:"Use as Xposed Module Configs",headers:[{level:2,title:"Dependency Configs",slug:"dependency-configs",link:"#dependency-configs",children:[]},{level:2,title:"Custom Automatic Builder",slug:"custom-automatic-builder",link:"#custom-automatic-builder",children:[{level:3,title:"InjectYukiHookWithXposed Annotation",slug:"injectyukihookwithxposed-annotation",link:"#injectyukihookwithxposed-annotation",children:[]},{level:3,title:"IYukiHookXposedInit Interface",slug:"iyukihookxposedinit-interface",link:"#iyukihookxposedinit-interface",children:[]}]},{level:2,title:"Native Xposed API Events",slug:"native-xposed-api-events",link:"#native-xposed-api-events",children:[]}],path:"/en/config/xposed-using.html",pathLocale:"/en/",extraFields:[]},{title:"Usage Example",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:[]}],path:"/en/guide/example.html",pathLocale:"/en/",extraFields:[]},{title:"Introduce",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:[]}],path:"/en/guide/home.html",pathLocale:"/en/",extraFields:[]},{title:"Basic Knowledge",headers:[{level:2,title:"Related Introduction",slug:"related-introduction",link:"#related-introduction",children:[{level:3,title:"What is Xposed",slug:"what-is-xposed",link:"#what-is-xposed",children:[]},{level:3,title:"What can Xposed do",slug:"what-can-xposed-do",link:"#what-can-xposed-do",children:[]},{level:3,title:"Development Process",slug:"development-process",link:"#development-process",children:[]},{level:3,title:"Derivatives",slug:"derivatives",link:"#derivatives",children:[]},{level:3,title:"What YukiHookAPI does",slug:"what-yukihookapi-does",link:"#what-yukihookapi-does",children:[]}]},{level:2,title:"Let's Started",slug:"let-s-started",link:"#let-s-started",children:[]}],path:"/en/guide/knowledge.html",pathLocale:"/en/",extraFields:[]},{title:"Migrate from Xposed API",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:[]}],path:"/en/guide/move-to-new-api.html",pathLocale:"/en/",extraFields:[]},{title:"Quick Start",headers:[{level:2,title:"Environment Requirements",slug:"environment-requirements",link:"#environment-requirements",children:[]},{level:2,title:"Automatically Build Project",slug:"automatically-build-project",link:"#automatically-build-project",children:[]},{level:2,title:"Manually Configure Project",slug:"manually-configure-project",link:"#manually-configure-project",children:[{level:3,title:"Create Project",slug:"create-project",link:"#create-project",children:[]},{level:3,title:"Integration Dependencies",slug:"integration-dependencies",link:"#integration-dependencies",children:[]},{level:3,title:"Use as Xposed Module",slug:"use-as-xposed-module",link:"#use-as-xposed-module",children:[]},{level:3,title:"Use as Hook API",slug:"use-as-hook-api",link:"#use-as-hook-api",children:[]}]}],path:"/en/guide/quick-start.html",pathLocale:"/en/",extraFields:[]},{title:"YukiHookAPI Project Builder",headers:[{level:2,title:"Get Project",slug:"get-project",link:"#get-project",children:[]},{level:2,title:"Usage",slug:"usage",link:"#usage",children:[{level:3,title:"Basic Usage",slug:"basic-usage",link:"#basic-usage",children:[]},{level:3,title:"Config Template",slug:"config-template",link:"#config-template",children:[]},{level:3,title:"Multilingual Support",slug:"multilingual-support",link:"#multilingual-support",children:[]}]}],path:"/en/tools/yukihookapi-projectbuilder.html",pathLocale:"/en/",extraFields:[]},{title:"\u5173\u4E8E\u6B64\u6587\u6863",headers:[{level:2,title:"License",slug:"license",link:"#license",children:[]}],path:"/zh-cn/about/about.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u66F4\u65B0\u65E5\u5FD7",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:[]}],path:"/zh-cn/about/changelog.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u8054\u7CFB\u6211\u4EEC",headers:[{level:2,title:"\u52A9\u529B\u7EF4\u62A4",slug:"\u52A9\u529B\u7EF4\u62A4",link:"#\u52A9\u529B\u7EF4\u62A4",children:[]}],path:"/zh-cn/about/contacts.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u5C55\u671B\u672A\u6765",headers:[{level:2,title:"\u672A\u89E3\u51B3\u7684\u95EE\u9898",slug:"\u672A\u89E3\u51B3\u7684\u95EE\u9898",link:"#\u672A\u89E3\u51B3\u7684\u95EE\u9898",children:[{level:3,title:"YukiHookModulePrefs",slug:"yukihookmoduleprefs",link:"#yukihookmoduleprefs",children:[]}]},{level:2,title:"\u672A\u6765\u7684\u8BA1\u5212",slug:"\u672A\u6765\u7684\u8BA1\u5212",link:"#\u672A\u6765\u7684\u8BA1\u5212",children:[{level:3,title:"\u652F\u6301\u72EC\u7ACB\u4F7F\u7528\u7684 Lite \u7248\u672C",slug:"\u652F\u6301\u72EC\u7ACB\u4F7F\u7528\u7684-lite-\u7248\u672C",link:"#\u652F\u6301\u72EC\u7ACB\u4F7F\u7528\u7684-lite-\u7248\u672C",children:[]},{level:3,title:"\u652F\u6301\u66F4\u591A Hook Framework",slug:"\u652F\u6301\u66F4\u591A-hook-framework",link:"#\u652F\u6301\u66F4\u591A-hook-framework",children:[]}]}],path:"/zh-cn/about/future.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u6587\u6863\u4ECB\u7ECD",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:[]}],path:"/zh-cn/api/home.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"API \u57FA\u672C\u914D\u7F6E",headers:[{level:2,title:"\u529F\u80FD\u914D\u7F6E",slug:"\u529F\u80FD\u914D\u7F6E",link:"#\u529F\u80FD\u914D\u7F6E",children:[{level:3,title:"configs \u65B9\u6CD5",slug:"configs-\u65B9\u6CD5",link:"#configs-\u65B9\u6CD5",children:[]}]},{level:2,title:"Hooker \u914D\u7F6E",slug:"hooker-\u914D\u7F6E",link:"#hooker-\u914D\u7F6E",children:[{level:3,title:"\u901A\u8FC7 lambda \u521B\u5EFA",slug:"\u901A\u8FC7-lambda-\u521B\u5EFA",link:"#\u901A\u8FC7-lambda-\u521B\u5EFA",children:[]},{level:3,title:"\u901A\u8FC7\u81EA\u5B9A\u4E49 Hooker \u521B\u5EFA",slug:"\u901A\u8FC7\u81EA\u5B9A\u4E49-hooker-\u521B\u5EFA",link:"#\u901A\u8FC7\u81EA\u5B9A\u4E49-hooker-\u521B\u5EFA",children:[]},{level:3,title:"\u6269\u5C55\u7279\u6027",slug:"\u6269\u5C55\u7279\u6027",link:"#\u6269\u5C55\u7279\u6027",children:[]},{level:3,title:"\u6CE8\u610F\u4E8B\u9879",slug:"\u6CE8\u610F\u4E8B\u9879",link:"#\u6CE8\u610F\u4E8B\u9879",children:[]}]},{level:2,title:"\u4F5C\u4E3A Hook API \u4F7F\u7528\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9",slug:"\u4F5C\u4E3A-hook-api-\u4F7F\u7528\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9",link:"#\u4F5C\u4E3A-hook-api-\u4F7F\u7528\u9700\u8981\u6CE8\u610F\u7684\u5730\u65B9",children:[]}],path:"/zh-cn/config/api-example.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"API \u5F02\u5E38\u5904\u7406",headers:[{level:2,title:"\u975E\u963B\u65AD\u5F02\u5E38",slug:"\u975E\u963B\u65AD\u5F02\u5E38",link:"#\u975E\u963B\u65AD\u5F02\u5E38",children:[]},{level:2,title:"\u963B\u65AD\u5F02\u5E38",slug:"\u963B\u65AD\u5F02\u5E38",link:"#\u963B\u65AD\u5F02\u5E38",children:[]}],path:"/zh-cn/config/api-exception.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u4F5C\u4E3A Hook API \u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E",headers:[{level:2,title:"\u4F9D\u8D56\u914D\u7F6E",slug:"\u4F9D\u8D56\u914D\u7F6E",link:"#\u4F9D\u8D56\u914D\u7F6E",children:[]},{level:2,title:"\u5165\u53E3\u914D\u7F6E",slug:"\u5165\u53E3\u914D\u7F6E",link:"#\u5165\u53E3\u914D\u7F6E",children:[]},{level:2,title:"Hook Framework",slug:"hook-framework",link:"#hook-framework",children:[{level:3,title:"Pine",slug:"pine",link:"#pine",children:[]},{level:3,title:"SandHook",slug:"sandhook",link:"#sandhook",children:[]},{level:3,title:"Whale",slug:"whale",link:"#whale",children:[]}]}],path:"/zh-cn/config/api-using.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"R8 \u4E0E Proguard \u6DF7\u6DC6",headers:[{level:2,title:"R8",slug:"r8",link:"#r8",children:[]},{level:2,title:"Proguard",slug:"proguard",link:"#proguard",children:[]}],path:"/zh-cn/config/r8-proguard.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E",headers:[{level:2,title:"\u4F9D\u8D56\u914D\u7F6E",slug:"\u4F9D\u8D56\u914D\u7F6E",link:"#\u4F9D\u8D56\u914D\u7F6E",children:[]},{level:2,title:"\u81EA\u5B9A\u4E49\u5904\u7406\u7A0B\u5E8F",slug:"\u81EA\u5B9A\u4E49\u5904\u7406\u7A0B\u5E8F",link:"#\u81EA\u5B9A\u4E49\u5904\u7406\u7A0B\u5E8F",children:[{level:3,title:"InjectYukiHookWithXposed \u6CE8\u89E3",slug:"injectyukihookwithxposed-\u6CE8\u89E3",link:"#injectyukihookwithxposed-\u6CE8\u89E3",children:[]},{level:3,title:"IYukiHookXposedInit \u63A5\u53E3",slug:"iyukihookxposedinit-\u63A5\u53E3",link:"#iyukihookxposedinit-\u63A5\u53E3",children:[]}]},{level:2,title:"\u539F\u751F Xposed API \u4E8B\u4EF6",slug:"\u539F\u751F-xposed-api-\u4E8B\u4EF6",link:"#\u539F\u751F-xposed-api-\u4E8B\u4EF6",children:[]}],path:"/zh-cn/config/xposed-using.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u7528\u6CD5\u793A\u4F8B",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:[]}],path:"/zh-cn/guide/example.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u4ECB\u7ECD",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:[]}],path:"/zh-cn/guide/home.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u57FA\u7840\u77E5\u8BC6",headers:[{level:2,title:"\u76F8\u5173\u4ECB\u7ECD",slug:"\u76F8\u5173\u4ECB\u7ECD",link:"#\u76F8\u5173\u4ECB\u7ECD",children:[{level:3,title:"Xposed \u662F\u4EC0\u4E48",slug:"xposed-\u662F\u4EC0\u4E48",link:"#xposed-\u662F\u4EC0\u4E48",children:[]},{level:3,title:"Xposed \u80FD\u505A\u4EC0\u4E48",slug:"xposed-\u80FD\u505A\u4EC0\u4E48",link:"#xposed-\u80FD\u505A\u4EC0\u4E48",children:[]},{level:3,title:"\u53D1\u5C55\u8FC7\u7A0B",slug:"\u53D1\u5C55\u8FC7\u7A0B",link:"#\u53D1\u5C55\u8FC7\u7A0B",children:[]},{level:3,title:"\u884D\u751F\u4EA7\u54C1",slug:"\u884D\u751F\u4EA7\u54C1",link:"#\u884D\u751F\u4EA7\u54C1",children:[]},{level:3,title:"YukiHookAPI \u505A\u4E86\u4EC0\u4E48",slug:"yukihookapi-\u505A\u4E86\u4EC0\u4E48",link:"#yukihookapi-\u505A\u4E86\u4EC0\u4E48",children:[]}]},{level:2,title:"\u8BA9\u6211\u4EEC\u5F00\u59CB\u5427",slug:"\u8BA9\u6211\u4EEC\u5F00\u59CB\u5427",link:"#\u8BA9\u6211\u4EEC\u5F00\u59CB\u5427",children:[]}],path:"/zh-cn/guide/knowledge.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u4ECE Xposed API \u8FC1\u79FB",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:[]}],path:"/zh-cn/guide/move-to-new-api.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u5FEB\u901F\u5F00\u59CB",headers:[{level:2,title:"\u73AF\u5883\u8981\u6C42",slug:"\u73AF\u5883\u8981\u6C42",link:"#\u73AF\u5883\u8981\u6C42",children:[]},{level:2,title:"\u81EA\u52A8\u6784\u5EFA\u9879\u76EE",slug:"\u81EA\u52A8\u6784\u5EFA\u9879\u76EE",link:"#\u81EA\u52A8\u6784\u5EFA\u9879\u76EE",children:[]},{level:2,title:"\u624B\u52A8\u914D\u7F6E\u9879\u76EE",slug:"\u624B\u52A8\u914D\u7F6E\u9879\u76EE",link:"#\u624B\u52A8\u914D\u7F6E\u9879\u76EE",children:[{level:3,title:"\u521B\u5EFA\u9879\u76EE",slug:"\u521B\u5EFA\u9879\u76EE",link:"#\u521B\u5EFA\u9879\u76EE",children:[]},{level:3,title:"\u96C6\u6210\u4F9D\u8D56",slug:"\u96C6\u6210\u4F9D\u8D56",link:"#\u96C6\u6210\u4F9D\u8D56",children:[]},{level:3,title:"\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528",slug:"\u4F5C\u4E3A-xposed-\u6A21\u5757\u4F7F\u7528",link:"#\u4F5C\u4E3A-xposed-\u6A21\u5757\u4F7F\u7528",children:[]},{level:3,title:"\u4F5C\u4E3A Hook API \u4F7F\u7528",slug:"\u4F5C\u4E3A-hook-api-\u4F7F\u7528",link:"#\u4F5C\u4E3A-hook-api-\u4F7F\u7528",children:[]}]}],path:"/zh-cn/guide/quick-start.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiHookAPI \u6784\u5EFA\u5DE5\u5177",headers:[{level:2,title:"\u83B7\u53D6\u9879\u76EE",slug:"\u83B7\u53D6\u9879\u76EE",link:"#\u83B7\u53D6\u9879\u76EE",children:[]},{level:2,title:"\u4F7F\u7528\u65B9\u6CD5",slug:"\u4F7F\u7528\u65B9\u6CD5",link:"#\u4F7F\u7528\u65B9\u6CD5",children:[{level:3,title:"\u57FA\u672C\u7528\u6CD5",slug:"\u57FA\u672C\u7528\u6CD5",link:"#\u57FA\u672C\u7528\u6CD5",children:[]},{level:3,title:"\u914D\u7F6E\u6A21\u677F",slug:"\u914D\u7F6E\u6A21\u677F",link:"#\u914D\u7F6E\u6A21\u677F",children:[]},{level:3,title:"\u591A\u8BED\u8A00\u652F\u6301",slug:"\u591A\u8BED\u8A00\u652F\u6301",link:"#\u591A\u8BED\u8A00\u652F\u6301",children:[]}]}],path:"/zh-cn/tools/yukihookapi-projectbuilder.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"Host Resource Injection Extension",headers:[{level:2,title:"Inject Module App's Resources",slug:"inject-module-app-s-resources",link:"#inject-module-app-s-resources",children:[]},{level:2,title:"Register Module App's Activity",slug:"register-module-app-s-activity",link:"#register-module-app-s-activity",children:[]},{level:2,title:"Create ContextThemeWrapper Proxy",slug:"create-contextthemewrapper-proxy",link:"#create-contextthemewrapper-proxy",children:[]}],path:"/en/api/special-features/host-inject.html",pathLocale:"/en/",extraFields:[]},{title:"Host Lifecycle Extension",headers:[{level:2,title:"Monitor Lifecycle",slug:"monitor-lifecycle",link:"#monitor-lifecycle",children:[]},{level:2,title:"Register System Broadcast",slug:"register-system-broadcast",link:"#register-system-broadcast",children:[]}],path:"/en/api/special-features/host-lifecycle.html",pathLocale:"/en/",extraFields:[]},{title:"Debug Logs",headers:[{level:2,title:"Normal Logs",slug:"normal-logs",link:"#normal-logs",children:[]},{level:2,title:"Error Logs",slug:"error-logs",link:"#error-logs",children:[]},{level:2,title:"Save Logs and Custom Elements",slug:"save-logs-and-custom-elements",link:"#save-logs-and-custom-elements",children:[]}],path:"/en/api/special-features/logger.html",pathLocale:"/en/",extraFields:[]},{title:"Reflection Extensions",headers:[{level:2,title:"Class Extensions",slug:"class-extensions",link:"#class-extensions",children:[{level:3,title:"Object Conversion",slug:"object-conversion",link:"#object-conversion",children:[]},{level:3,title:"Existential Judgment",slug:"existential-judgment",link:"#existential-judgment",children:[]},{level:3,title:"Vague Search",slug:"vague-search",link:"#vague-search",children:[]}]},{level:2,title:"Member Extensions",slug:"member-extensions",link:"#member-extensions",children:[{level:3,title:"Find and Reflection",slug:"find-and-reflection",link:"#find-and-reflection",children:[]},{level:3,title:"Optional Find Conditions",slug:"optional-find-conditions",link:"#optional-find-conditions",children:[]},{level:3,title:"Find in Super Class",slug:"find-in-super-class",link:"#find-in-super-class",children:[]},{level:3,title:"Vague Find",slug:"vague-find",link:"#vague-find",children:[]},{level:3,title:"Multiple Find",slug:"multiple-find",link:"#multiple-find",children:[]},{level:3,title:"Static Bytecode",slug:"static-bytecode",link:"#static-bytecode",children:[]},{level:3,title:"Obfuscated Bytecode",slug:"obfuscated-bytecode",link:"#obfuscated-bytecode",children:[]},{level:3,title:"Directly Called",slug:"directly-called",link:"#directly-called",children:[]},{level:3,title:"Original Called",slug:"original-called",link:"#original-called",children:[]},{level:3,title:"Find Again",slug:"find-again",link:"#find-again",children:[]},{level:3,title:"Relative Matching",slug:"relative-matching",link:"#relative-matching",children:[]},{level:3,title:"Calling Generics",slug:"calling-generics",link:"#calling-generics",children:[]},{level:3,title:"Pay Attention of Trap",slug:"pay-attention-of-trap",link:"#pay-attention-of-trap",children:[]}]},{level:2,title:"Common Type Extensions",slug:"common-type-extensions",link:"#common-type-extensions",children:[]}],path:"/en/api/special-features/reflection.html",pathLocale:"/en/",extraFields:[]},{title:"Xposed Module and Host Channel",headers:[{level:2,title:"Basic Usage",slug:"basic-usage",link:"#basic-usage",children:[]},{level:2,title:"Determine Module App and Host App Version Match",slug:"determine-module-app-and-host-app-version-match",link:"#determine-module-app-and-host-app-version-match",children:[]},{level:2,title:"Rules for Callback Event Response",slug:"rules-for-callback-event-response",link:"#rules-for-callback-event-response",children:[]},{level:2,title:"Security Instructions",slug:"security-instructions",link:"#security-instructions",children:[]}],path:"/en/api/special-features/xposed-channel.html",pathLocale:"/en/",extraFields:[]},{title:"Xposed Module Data Storage",headers:[{level:2,title:"Use in Activity",slug:"use-in-activity",link:"#use-in-activity",children:[]},{level:2,title:"Use in PreferenceFragment",slug:"use-in-preferencefragment",link:"#use-in-preferencefragment",children:[]}],path:"/en/api/special-features/xposed-storage.html",pathLocale:"/en/",extraFields:[]},{title:"\u5BBF\u4E3B\u8D44\u6E90\u6CE8\u5165\u6269\u5C55",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:[]}],path:"/zh-cn/api/special-features/host-inject.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u5BBF\u4E3B\u751F\u547D\u5468\u671F\u6269\u5C55",headers:[{level:2,title:"\u76D1\u542C\u751F\u547D\u5468\u671F",slug:"\u76D1\u542C\u751F\u547D\u5468\u671F",link:"#\u76D1\u542C\u751F\u547D\u5468\u671F",children:[]},{level:2,title:"\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD",slug:"\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD",link:"#\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD",children:[]}],path:"/zh-cn/api/special-features/host-lifecycle.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u8C03\u8BD5\u65E5\u5FD7",headers:[{level:2,title:"\u666E\u901A\u65E5\u5FD7",slug:"\u666E\u901A\u65E5\u5FD7",link:"#\u666E\u901A\u65E5\u5FD7",children:[]},{level:2,title:"\u9519\u8BEF\u65E5\u5FD7",slug:"\u9519\u8BEF\u65E5\u5FD7",link:"#\u9519\u8BEF\u65E5\u5FD7",children:[]},{level:2,title:"\u4FDD\u5B58\u65E5\u5FD7\u4E0E\u81EA\u5B9A\u4E49\u5143\u7D20",slug:"\u4FDD\u5B58\u65E5\u5FD7\u4E0E\u81EA\u5B9A\u4E49\u5143\u7D20",link:"#\u4FDD\u5B58\u65E5\u5FD7\u4E0E\u81EA\u5B9A\u4E49\u5143\u7D20",children:[]}],path:"/zh-cn/api/special-features/logger.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"\u5B57\u8282\u7801\u4E0E\u53CD\u5C04\u6269\u5C55",headers:[{level:2,title:"Class \u6269\u5C55",slug:"class-\u6269\u5C55",link:"#class-\u6269\u5C55",children:[{level:3,title:"\u5BF9\u8C61\u8F6C\u6362",slug:"\u5BF9\u8C61\u8F6C\u6362",link:"#\u5BF9\u8C61\u8F6C\u6362",children:[]},{level:3,title:"\u5B58\u5728\u5224\u65AD",slug:"\u5B58\u5728\u5224\u65AD",link:"#\u5B58\u5728\u5224\u65AD",children:[]},{level:3,title:"\u6A21\u7CCA\u67E5\u627E",slug:"\u6A21\u7CCA\u67E5\u627E",link:"#\u6A21\u7CCA\u67E5\u627E",children:[]}]},{level:2,title:"Member \u6269\u5C55",slug:"member-\u6269\u5C55",link:"#member-\u6269\u5C55",children:[{level:3,title:"\u67E5\u627E\u4E0E\u53CD\u5C04\u8C03\u7528",slug:"\u67E5\u627E\u4E0E\u53CD\u5C04\u8C03\u7528",link:"#\u67E5\u627E\u4E0E\u53CD\u5C04\u8C03\u7528",children:[]},{level:3,title:"\u53EF\u9009\u7684\u67E5\u627E\u6761\u4EF6",slug:"\u53EF\u9009\u7684\u67E5\u627E\u6761\u4EF6",link:"#\u53EF\u9009\u7684\u67E5\u627E\u6761\u4EF6",children:[]},{level:3,title:"\u5728\u7236\u7C7B\u67E5\u627E",slug:"\u5728\u7236\u7C7B\u67E5\u627E",link:"#\u5728\u7236\u7C7B\u67E5\u627E",children:[]},{level:3,title:"\u6A21\u7CCA\u67E5\u627E",slug:"\u6A21\u7CCA\u67E5\u627E-1",link:"#\u6A21\u7CCA\u67E5\u627E-1",children:[]},{level:3,title:"\u591A\u91CD\u67E5\u627E",slug:"\u591A\u91CD\u67E5\u627E-1",link:"#\u591A\u91CD\u67E5\u627E-1",children:[]},{level:3,title:"\u9759\u6001\u5B57\u8282\u7801",slug:"\u9759\u6001\u5B57\u8282\u7801",link:"#\u9759\u6001\u5B57\u8282\u7801",children:[]},{level:3,title:"\u6DF7\u6DC6\u7684\u5B57\u8282\u7801",slug:"\u6DF7\u6DC6\u7684\u5B57\u8282\u7801",link:"#\u6DF7\u6DC6\u7684\u5B57\u8282\u7801",children:[]},{level:3,title:"\u76F4\u63A5\u8C03\u7528",slug:"\u76F4\u63A5\u8C03\u7528",link:"#\u76F4\u63A5\u8C03\u7528",children:[]},{level:3,title:"\u539F\u59CB\u8C03\u7528",slug:"\u539F\u59CB\u8C03\u7528",link:"#\u539F\u59CB\u8C03\u7528",children:[]},{level:3,title:"\u518D\u6B21\u67E5\u627E",slug:"\u518D\u6B21\u67E5\u627E",link:"#\u518D\u6B21\u67E5\u627E",children:[]},{level:3,title:"\u76F8\u5BF9\u5339\u914D",slug:"\u76F8\u5BF9\u5339\u914D",link:"#\u76F8\u5BF9\u5339\u914D",children:[]},{level:3,title:"\u8C03\u7528\u6CDB\u578B",slug:"\u8C03\u7528\u6CDB\u578B",link:"#\u8C03\u7528\u6CDB\u578B",children:[]},{level:3,title:"\u6CE8\u610F\u8BEF\u533A",slug:"\u6CE8\u610F\u8BEF\u533A",link:"#\u6CE8\u610F\u8BEF\u533A",children:[]}]},{level:2,title:"\u5E38\u7528\u7C7B\u578B\u6269\u5C55",slug:"\u5E38\u7528\u7C7B\u578B\u6269\u5C55",link:"#\u5E38\u7528\u7C7B\u578B\u6269\u5C55",children:[]}],path:"/zh-cn/api/special-features/reflection.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"Xposed \u6A21\u5757\u4E0E\u5BBF\u4E3B\u901A\u8BAF\u6865",headers:[{level:2,title:"\u57FA\u672C\u7528\u6CD5",slug:"\u57FA\u672C\u7528\u6CD5",link:"#\u57FA\u672C\u7528\u6CD5",children:[]},{level:2,title:"\u5224\u65AD\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7248\u672C\u662F\u5426\u5339\u914D",slug:"\u5224\u65AD\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7248\u672C\u662F\u5426\u5339\u914D",link:"#\u5224\u65AD\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7248\u672C\u662F\u5426\u5339\u914D",children:[]},{level:2,title:"\u56DE\u8C03\u4E8B\u4EF6\u54CD\u5E94\u7684\u89C4\u5219",slug:"\u56DE\u8C03\u4E8B\u4EF6\u54CD\u5E94\u7684\u89C4\u5219",link:"#\u56DE\u8C03\u4E8B\u4EF6\u54CD\u5E94\u7684\u89C4\u5219",children:[]},{level:2,title:"\u5B89\u5168\u6027\u8BF4\u660E",slug:"\u5B89\u5168\u6027\u8BF4\u660E",link:"#\u5B89\u5168\u6027\u8BF4\u660E",children:[]}],path:"/zh-cn/api/special-features/xposed-channel.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"Xposed \u6A21\u5757\u6570\u636E\u5B58\u50A8",headers:[{level:2,title:"\u5728 Activity \u4E2D\u4F7F\u7528",slug:"\u5728-activity-\u4E2D\u4F7F\u7528",link:"#\u5728-activity-\u4E2D\u4F7F\u7528",children:[]},{level:2,title:"\u5728 PreferenceFragment \u4E2D\u4F7F\u7528",slug:"\u5728-preferencefragment-\u4E2D\u4F7F\u7528",link:"#\u5728-preferencefragment-\u4E2D\u4F7F\u7528",children:[]}],path:"/zh-cn/api/special-features/xposed-storage.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiHookAPI - object",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.html",pathLocale:"/en/",extraFields:[]},{title:"YukiHookAPI - object",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"InjectYukiHookWithXposed - annotation",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html",pathLocale:"/en/",extraFields:[]},{title:"CurrentClass - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html",pathLocale:"/en/",extraFields:[]},{title:"GenericClass - class",headers:[{level:2,title:"argument - method",slug:"argument-method",link:"#argument-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html",pathLocale:"/en/",extraFields:[]},{title:"HookClass - class",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html",pathLocale:"/en/",extraFields:[]},{title:"HookResources - class",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html",pathLocale:"/en/",extraFields:[]},{title:"VariousClass - class",headers:[{level:2,title:"get - method",slug:"get-method",link:"#get-method",children:[]},{level:2,title:"getOrNull - method",slug:"getornull-method",link:"#getornull-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html",pathLocale:"/en/",extraFields:[]},{title:"YukiMemberHookCreator - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html",pathLocale:"/en/",extraFields:[]},{title:"YukiResourcesHookCreator - class",headers:[{level:2,title:"injectResource - method",slug:"injectresource-method",link:"#injectresource-method",children:[]},{level:2,title:"ResourcesHookCreator - class",slug:"resourceshookcreator-class",link:"#resourceshookcreator-class",children:[{level:3,title:"resourceId - field",slug:"resourceid-field",link:"#resourceid-field",children:[]},{level:3,title:"conditions - method",slug:"conditions-method",link:"#conditions-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:"replaceToModuleResource - method",slug:"replacetomoduleresource-method",link:"#replacetomoduleresource-method",children:[]},{level:3,title:"injectAsLayout - method",slug:"injectaslayout-method",link:"#injectaslayout-method",children:[]},{level:3,title:"ConditionFinder - class",slug:"conditionfinder-class",link:"#conditionfinder-class",children:[]},{level:3,title:"Result - class",slug:"result-class",link:"#result-class",children:[]},{level:3,title:"onHookingFailure - method",slug:"onhookingfailure-method",link:"#onhookingfailure-method",children:[]},{level:3,title:"ignoredHookingFailure - method",slug:"ignoredhookingfailure-method",link:"#ignoredhookingfailure-method",children:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html",pathLocale:"/en/",extraFields:[]},{title:"YukiBaseHooker - class",headers:[{level:2,title:"onHook - method",slug:"onhook-method",link:"#onhook-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html",pathLocale:"/en/",extraFields:[]},{title:"ReflectionFactory - kt",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html",pathLocale:"/en/",extraFields:[]},{title:"YukiHookFactory - kt",headers:[{level:2,title:"IYukiHookXposedInit.configs - ext-method",slug:"iyukihookxposedinit-configs-ext-method",link:"#iyukihookxposedinit-configs-ext-method",children:[]},{level:2,title:"IYukiHookXposedInit.encase - ext-method",slug:"iyukihookxposedinit-encase-ext-method",link:"#iyukihookxposedinit-encase-ext-method",children:[]},{level:2,title:"Context.modulePrefs - ext-field",slug:"context-moduleprefs-ext-field",link:"#context-moduleprefs-ext-field",children:[]},{level:2,title:"Context.modulePrefs - ext-method",slug:"context-moduleprefs-ext-method",link:"#context-moduleprefs-ext-method",children:[]},{level:2,title:"Context.dataChannel - ext-method",slug:"context-datachannel-ext-method",link:"#context-datachannel-ext-method",children:[]},{level:2,title:"Context.processName - ext-field",slug:"context-processname-ext-field",link:"#context-processname-ext-field",children:[]},{level:2,title:"Context+Resources.injectModuleAppResources - ext-method",slug:"context-resources-injectmoduleappresources-ext-method",link:"#context-resources-injectmoduleappresources-ext-method",children:[]},{level:2,title:"Context.registerModuleAppActivities - ext-method",slug:"context-registermoduleappactivities-ext-method",link:"#context-registermoduleappactivities-ext-method",children:[]},{level:2,title:"Context.applyModuleTheme - ext-method",slug:"context-applymoduletheme-ext-method",link:"#context-applymoduletheme-ext-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html",pathLocale:"/en/",extraFields:[]},{title:"LoggerFactory - kt",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html",pathLocale:"/en/",extraFields:[]},{title:"HookParam - class",headers:[{level:2,title:"args - field",slug:"args-field",link:"#args-field",children:[]},{level:2,title:"instance - field",slug:"instance-field",link:"#instance-field",children:[]},{level:2,title:"instanceClass - field",slug:"instanceclass-field",link:"#instanceclass-field",children:[]},{level:2,title:"member - field",slug:"member-field",link:"#member-field",children:[]},{level:2,title:"method - field",slug:"method-field",link:"#method-field",children:[]},{level:2,title:"constructor - field",slug:"constructor-field",link:"#constructor-field",children:[]},{level:2,title:"result - field",slug:"result-field",link:"#result-field",children:[]},{level:2,title:"hasThrowable - field",slug:"hasthrowable-field",link:"#hasthrowable-field",children:[]},{level:2,title:"throwable - field",slug:"throwable-field",link:"#throwable-field",children:[]},{level:2,title:"Throwable.throwToApp - i-ext-method",slug:"throwable-throwtoapp-i-ext-method",link:"#throwable-throwtoapp-i-ext-method",children:[]},{level:2,title:"result - method",slug:"result-method",link:"#result-method",children:[]},{level:2,title:"instance - method",slug:"instance-method",link:"#instance-method",children:[]},{level:2,title:"args - method",slug:"args-method",link:"#args-method",children:[]},{level:2,title:"args - method",slug:"args-method-1",link:"#args-method-1",children:[]},{level:2,title:"callOriginal - method",slug:"calloriginal-method",link:"#calloriginal-method",children:[]},{level:2,title:"invokeOriginal - method",slug:"invokeoriginal-method",link:"#invokeoriginal-method",children:[]},{level:2,title:"resultTrue - method",slug:"resulttrue-method",link:"#resulttrue-method",children:[]},{level:2,title:"resultFalse - method",slug:"resultfalse-method",link:"#resultfalse-method",children:[]},{level:2,title:"resultNull - method",slug:"resultnull-method",link:"#resultnull-method",children:[]},{level:2,title:"ArgsIndexCondition - class",slug:"argsindexcondition-class",link:"#argsindexcondition-class",children:[{level:3,title:"first - method",slug:"first-method",link:"#first-method",children:[]},{level:3,title:"last - method",slug:"last-method",link:"#last-method",children:[]}]},{level:2,title:"ArgsModifyer - class",slug:"argsmodifyer-class",link:"#argsmodifyer-class",children:[{level:3,title:"cast - method",slug:"cast-method",link:"#cast-method",children:[]},{level:3,title:"byte - method",slug:"byte-method",link:"#byte-method",children:[]},{level:3,title:"int - method",slug:"int-method",link:"#int-method",children:[]},{level:3,title:"long - method",slug:"long-method",link:"#long-method",children:[]},{level:3,title:"short - method",slug:"short-method",link:"#short-method",children:[]},{level:3,title:"double - method",slug:"double-method",link:"#double-method",children:[]},{level:3,title:"float - method",slug:"float-method",link:"#float-method",children:[]},{level:3,title:"string - method",slug:"string-method",link:"#string-method",children:[]},{level:3,title:"char - method",slug:"char-method",link:"#char-method",children:[]},{level:3,title:"boolean - method",slug:"boolean-method",link:"#boolean-method",children:[]},{level:3,title:"any - method",slug:"any-method",link:"#any-method",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:[]},{level:3,title:"set - method",slug:"set-method",link:"#set-method",children:[]},{level:3,title:"setNull - method",slug:"setnull-method",link:"#setnull-method",children:[]},{level:3,title:"setTrue - method",slug:"settrue-method",link:"#settrue-method",children:[]},{level:3,title:"setFalse - method",slug:"setfalse-method",link:"#setfalse-method",children:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html",pathLocale:"/en/",extraFields:[]},{title:"PackageParam - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html",pathLocale:"/en/",extraFields:[]},{title:"CurrentClass - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"GenericClass - class",headers:[{level:2,title:"argument - method",slug:"argument-method",link:"#argument-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"HookClass - class",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"HookResources - class",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"VariousClass - class",headers:[{level:2,title:"get - method",slug:"get-method",link:"#get-method",children:[]},{level:2,title:"getOrNull - method",slug:"getornull-method",link:"#getornull-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"InjectYukiHookWithXposed - annotation",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiMemberHookCreator - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiResourcesHookCreator - class",headers:[{level:2,title:"injectResource - method",slug:"injectresource-method",link:"#injectresource-method",children:[]},{level:2,title:"ResourcesHookCreator - class",slug:"resourceshookcreator-class",link:"#resourceshookcreator-class",children:[{level:3,title:"resourceId - field",slug:"resourceid-field",link:"#resourceid-field",children:[]},{level:3,title:"conditions - method",slug:"conditions-method",link:"#conditions-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:"replaceToModuleResource - method",slug:"replacetomoduleresource-method",link:"#replacetomoduleresource-method",children:[]},{level:3,title:"injectAsLayout - method",slug:"injectaslayout-method",link:"#injectaslayout-method",children:[]},{level:3,title:"ConditionFinder - class",slug:"conditionfinder-class",link:"#conditionfinder-class",children:[]},{level:3,title:"Result - class",slug:"result-class",link:"#result-class",children:[]},{level:3,title:"onHookingFailure - method",slug:"onhookingfailure-method",link:"#onhookingfailure-method",children:[]},{level:3,title:"ignoredHookingFailure - method",slug:"ignoredhookingfailure-method",link:"#ignoredhookingfailure-method",children:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiBaseHooker - class",headers:[{level:2,title:"onHook - method",slug:"onhook-method",link:"#onhook-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ReflectionFactory - kt",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiHookFactory - kt",headers:[{level:2,title:"IYukiHookXposedInit.configs - ext-method",slug:"iyukihookxposedinit-configs-ext-method",link:"#iyukihookxposedinit-configs-ext-method",children:[]},{level:2,title:"IYukiHookXposedInit.encase - ext-method",slug:"iyukihookxposedinit-encase-ext-method",link:"#iyukihookxposedinit-encase-ext-method",children:[]},{level:2,title:"Context.modulePrefs - ext-field",slug:"context-moduleprefs-ext-field",link:"#context-moduleprefs-ext-field",children:[]},{level:2,title:"Context.modulePrefs - ext-method",slug:"context-moduleprefs-ext-method",link:"#context-moduleprefs-ext-method",children:[]},{level:2,title:"Context.dataChannel - ext-method",slug:"context-datachannel-ext-method",link:"#context-datachannel-ext-method",children:[]},{level:2,title:"Context.processName - ext-field",slug:"context-processname-ext-field",link:"#context-processname-ext-field",children:[]},{level:2,title:"Context+Resources.injectModuleAppResources - ext-method",slug:"context-resources-injectmoduleappresources-ext-method",link:"#context-resources-injectmoduleappresources-ext-method",children:[]},{level:2,title:"Context.registerModuleAppActivities - ext-method",slug:"context-registermoduleappactivities-ext-method",link:"#context-registermoduleappactivities-ext-method",children:[]},{level:2,title:"Context.applyModuleTheme - ext-method",slug:"context-applymoduletheme-ext-method",link:"#context-applymoduletheme-ext-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"LoggerFactory - kt",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"HookParam - class",headers:[{level:2,title:"args - field",slug:"args-field",link:"#args-field",children:[]},{level:2,title:"instance - field",slug:"instance-field",link:"#instance-field",children:[]},{level:2,title:"instanceClass - field",slug:"instanceclass-field",link:"#instanceclass-field",children:[]},{level:2,title:"member - field",slug:"member-field",link:"#member-field",children:[]},{level:2,title:"method - field",slug:"method-field",link:"#method-field",children:[]},{level:2,title:"constructor - field",slug:"constructor-field",link:"#constructor-field",children:[]},{level:2,title:"result - field",slug:"result-field",link:"#result-field",children:[]},{level:2,title:"hasThrowable - field",slug:"hasthrowable-field",link:"#hasthrowable-field",children:[]},{level:2,title:"throwable - field",slug:"throwable-field",link:"#throwable-field",children:[]},{level:2,title:"Throwable.throwToApp - i-ext-method",slug:"throwable-throwtoapp-i-ext-method",link:"#throwable-throwtoapp-i-ext-method",children:[]},{level:2,title:"result - method",slug:"result-method",link:"#result-method",children:[]},{level:2,title:"instance - method",slug:"instance-method",link:"#instance-method",children:[]},{level:2,title:"args - method",slug:"args-method",link:"#args-method",children:[]},{level:2,title:"args - method",slug:"args-method-1",link:"#args-method-1",children:[]},{level:2,title:"callOriginal - method",slug:"calloriginal-method",link:"#calloriginal-method",children:[]},{level:2,title:"invokeOriginal - method",slug:"invokeoriginal-method",link:"#invokeoriginal-method",children:[]},{level:2,title:"resultTrue - method",slug:"resulttrue-method",link:"#resulttrue-method",children:[]},{level:2,title:"resultFalse - method",slug:"resultfalse-method",link:"#resultfalse-method",children:[]},{level:2,title:"resultNull - method",slug:"resultnull-method",link:"#resultnull-method",children:[]},{level:2,title:"ArgsIndexCondition - class",slug:"argsindexcondition-class",link:"#argsindexcondition-class",children:[{level:3,title:"first - method",slug:"first-method",link:"#first-method",children:[]},{level:3,title:"last - method",slug:"last-method",link:"#last-method",children:[]}]},{level:2,title:"ArgsModifyer - class",slug:"argsmodifyer-class",link:"#argsmodifyer-class",children:[{level:3,title:"cast - method",slug:"cast-method",link:"#cast-method",children:[]},{level:3,title:"byte - method",slug:"byte-method",link:"#byte-method",children:[]},{level:3,title:"int - method",slug:"int-method",link:"#int-method",children:[]},{level:3,title:"long - method",slug:"long-method",link:"#long-method",children:[]},{level:3,title:"short - method",slug:"short-method",link:"#short-method",children:[]},{level:3,title:"double - method",slug:"double-method",link:"#double-method",children:[]},{level:3,title:"float - method",slug:"float-method",link:"#float-method",children:[]},{level:3,title:"string - method",slug:"string-method",link:"#string-method",children:[]},{level:3,title:"char - method",slug:"char-method",link:"#char-method",children:[]},{level:3,title:"boolean - method",slug:"boolean-method",link:"#boolean-method",children:[]},{level:3,title:"any - method",slug:"any-method",link:"#any-method",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:[]},{level:3,title:"set - method",slug:"set-method",link:"#set-method",children:[]},{level:3,title:"setNull - method",slug:"setnull-method",link:"#setnull-method",children:[]},{level:3,title:"setTrue - method",slug:"settrue-method",link:"#settrue-method",children:[]},{level:3,title:"setFalse - method",slug:"setfalse-method",link:"#setfalse-method",children:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"PackageParam - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ComponentTypeFactory - kt",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html",pathLocale:"/en/",extraFields:[]},{title:"GraphicsTypeFactory - kt",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html",pathLocale:"/en/",extraFields:[]},{title:"ViewTypeFactory - kt",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html",pathLocale:"/en/",extraFields:[]},{title:"DefinedTypeFactory - kt",headers:[{level:2,title:"VagueType - field",slug:"vaguetype-field",link:"#vaguetype-field",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html",pathLocale:"/en/",extraFields:[]},{title:"VariableTypeFactory - kt",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html",pathLocale:"/en/",extraFields:[]},{title:"ModuleApplication - class",headers:[{level:2,title:"appContext - field",slug:"appcontext-field",link:"#appcontext-field",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html",pathLocale:"/en/",extraFields:[]},{title:"YukiHookDataChannel - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html",pathLocale:"/en/",extraFields:[]},{title:"YukiHookModulePrefs - class",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html",pathLocale:"/en/",extraFields:[]},{title:"IYukiHookXposedInit - interface",headers:[{level:2,title:"onInit - method",slug:"oninit-method",link:"#oninit-method",children:[]},{level:2,title:"onHook - method",slug:"onhook-method",link:"#onhook-method",children:[]},{level:2,title:"onXposedEvent - method",slug:"onxposedevent-method",link:"#onxposedevent-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html",pathLocale:"/en/",extraFields:[]},{title:"ComponentTypeFactory - kt",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"GraphicsTypeFactory - kt",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ViewTypeFactory - kt",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"DefinedTypeFactory - kt",headers:[{level:2,title:"VagueType - field",slug:"vaguetype-field",link:"#vaguetype-field",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"VariableTypeFactory - kt",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ModuleApplication - class",headers:[{level:2,title:"appContext - field",slug:"appcontext-field",link:"#appcontext-field",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiHookDataChannel - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiHookModulePrefs - class",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"IYukiHookXposedInit - interface",headers:[{level:2,title:"onInit - method",slug:"oninit-method",link:"#oninit-method",children:[]},{level:2,title:"onHook - method",slug:"onhook-method",link:"#onhook-method",children:[]},{level:2,title:"onXposedEvent - method",slug:"onxposedevent-method",link:"#onxposedevent-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"BaseFinder - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html",pathLocale:"/en/",extraFields:[]},{title:"DexClassFinder - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html",pathLocale:"/en/",extraFields:[]},{title:"ConstructorFinder - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html",pathLocale:"/en/",extraFields:[]},{title:"FieldFinder - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html",pathLocale:"/en/",extraFields:[]},{title:"MethodFinder - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html",pathLocale:"/en/",extraFields:[]},{title:"YukiModuleResources - class",headers:[{level:2,title:"fwd - method",slug:"fwd-method",link:"#fwd-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html",pathLocale:"/en/",extraFields:[]},{title:"YukiResForwarder - class",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html",pathLocale:"/en/",extraFields:[]},{title:"YukiResources - class",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:[]}]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html",pathLocale:"/en/",extraFields:[]},{title:"YukiXposedEvent - object",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html",pathLocale:"/en/",extraFields:[]},{title:"ChannelData - class",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html",pathLocale:"/en/",extraFields:[]},{title:"PrefsData - class",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html",pathLocale:"/en/",extraFields:[]},{title:"ModulePreferenceFragment - class",headers:[{level:2,title:"onCreatePreferencesInModuleApp - method",slug:"oncreatepreferencesinmoduleapp-method",link:"#oncreatepreferencesinmoduleapp-method",children:[]},{level:2,title:"onSharedPreferenceChanged - method",slug:"onsharedpreferencechanged-method",link:"#onsharedpreferencechanged-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html",pathLocale:"/en/",extraFields:[]},{title:"BaseFinder - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"DexClassFinder - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ConstructorFinder - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"FieldFinder - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"MethodFinder - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiModuleResources - class",headers:[{level:2,title:"fwd - method",slug:"fwd-method",link:"#fwd-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiResForwarder - class",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiResources - class",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:[]}]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"YukiXposedEvent - object",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ChannelData - class",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"PrefsData - class",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ModulePreferenceFragment - class",headers:[{level:2,title:"onCreatePreferencesInModuleApp - method",slug:"oncreatepreferencesinmoduleapp-method",link:"#oncreatepreferencesinmoduleapp-method",children:[]},{level:2,title:"onSharedPreferenceChanged - method",slug:"onsharedpreferencechanged-method",link:"#onsharedpreferencechanged-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"CountRules - class",headers:[{level:2,title:"Int.isZero - i-ext-method",slug:"int-iszero-i-ext-method",link:"#int-iszero-i-ext-method",children:[]},{level:2,title:"Int.moreThan - i-ext-method",slug:"int-morethan-i-ext-method",link:"#int-morethan-i-ext-method",children:[]},{level:2,title:"Int.lessThan - i-ext-method",slug:"int-lessthan-i-ext-method",link:"#int-lessthan-i-ext-method",children:[]},{level:2,title:"Int.inInterval - i-ext-method",slug:"int-ininterval-i-ext-method",link:"#int-ininterval-i-ext-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html",pathLocale:"/en/",extraFields:[]},{title:"ModifierRules - class",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html",pathLocale:"/en/",extraFields:[]},{title:"NameRules - class",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html",pathLocale:"/en/",extraFields:[]},{title:"ConstructorRules - class",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html",pathLocale:"/en/",extraFields:[]},{title:"FieldRules - class",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html",pathLocale:"/en/",extraFields:[]},{title:"MemberRules - class",headers:[{level:2,title:"modifiers - method",slug:"modifiers-method",link:"#modifiers-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html",pathLocale:"/en/",extraFields:[]},{title:"MethodRules - class",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html",pathLocale:"/en/",extraFields:[]},{title:"ModuleAppActivity - class",headers:[],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html",pathLocale:"/en/",extraFields:[]},{title:"ModuleAppCompatActivity - class",headers:[{level:2,title:"moduleTheme - field",slug:"moduletheme-field",link:"#moduletheme-field",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html",pathLocale:"/en/",extraFields:[]},{title:"ModuleContextThemeWrapper - class",headers:[{level:2,title:"applyConfiguration - method",slug:"applyconfiguration-method",link:"#applyconfiguration-method",children:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html",pathLocale:"/en/",extraFields:[]},{title:"CountRules - class",headers:[{level:2,title:"Int.isZero - i-ext-method",slug:"int-iszero-i-ext-method",link:"#int-iszero-i-ext-method",children:[]},{level:2,title:"Int.moreThan - i-ext-method",slug:"int-morethan-i-ext-method",link:"#int-morethan-i-ext-method",children:[]},{level:2,title:"Int.lessThan - i-ext-method",slug:"int-lessthan-i-ext-method",link:"#int-lessthan-i-ext-method",children:[]},{level:2,title:"Int.inInterval - i-ext-method",slug:"int-ininterval-i-ext-method",link:"#int-ininterval-i-ext-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ModifierRules - class",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"NameRules - class",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ConstructorRules - class",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"FieldRules - class",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"MemberRules - class",headers:[{level:2,title:"modifiers - method",slug:"modifiers-method",link:"#modifiers-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"MethodRules - class",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ModuleContextThemeWrapper - class",headers:[{level:2,title:"applyConfiguration - method",slug:"applyconfiguration-method",link:"#applyconfiguration-method",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ModuleAppActivity - class",headers:[],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"ModuleAppCompatActivity - class",headers:[{level:2,title:"moduleTheme - field",slug:"moduletheme-field",link:"#moduletheme-field",children:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"MemberRulesResult - class",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:[]}],path:"/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html",pathLocale:"/en/",extraFields:[]},{title:"MemberRulesResult - class",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:[]}],path:"/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html",pathLocale:"/zh-cn/",extraFields:[]},{title:"",headers:[],path:"/404.html",pathLocale:"/",extraFields:[]}],Ba=ye(hf),df=()=>Ba;import.meta.webpackHot&&(__VUE_HMR_RUNTIME__.updateSearchIndex=e=>{Ba.value=e});const uf=({searchIndex:e,routeLocale:t,query:l,maxSuggestions:i})=>{const o=Y(()=>e.value.filter(n=>n.pathLocale===t.value));return Y(()=>{const n=l.value.trim().toLowerCase();if(!n)return[];const r=[],a=(s,c)=>{sr(n,[c.title])&&r.push({link:`${s.path}#${c.slug}`,title:s.title,header:c.title});for(const h of c.children){if(r.length>=i.value)return;a(s,h)}};for(const s of o.value){if(r.length>=i.value)break;if(sr(n,[s.title,...s.extraFields])){r.push({link:s.path,title:s.title});continue}for(const c of s.headers){if(r.length>=i.value)break;a(s,c)}}return r})},pf=e=>{const t=ye(0);return{focusIndex:t,focusNext:()=>{t.value{t.value>0?t.value-=1:t.value=e.value.length-1}}},mf=ue({name:"SearchBox",props:{locales:{type:Object,required:!1,default:()=>({})},hotKeys:{type:Array,required:!1,default:()=>[]},maxSuggestions:{type:Number,required:!1,default:5}},setup(e){const{locales:t,hotKeys:l,maxSuggestions:i}=Ei(e),o=Jt(),n=Wl(),r=df(),a=ye(null),s=ye(!1),c=ye(""),h=Y(()=>{var L;return(L=t.value[n.value])!=null?L:{}}),p=uf({searchIndex:r,routeLocale:n,query:c,maxSuggestions:i}),{focusIndex:m,focusNext:g,focusPrev:x}=pf(p);cf({input:a,hotKeys:l});const P=Y(()=>s.value&&!!p.value.length),E=()=>{!P.value||x()},k=()=>{!P.value||g()},b=L=>{if(!P.value)return;const M=p.value[L];!M||o.push(M.link).then(()=>{c.value="",m.value=0})};return()=>he("form",{class:"search-box",role:"search"},[he("input",{ref:a,type:"search",placeholder:h.value.placeholder,autocomplete:"off",spellcheck:!1,value:c.value,onFocus:()=>s.value=!0,onBlur:()=>s.value=!1,onInput:L=>c.value=L.target.value,onKeydown:L=>{switch(L.key){case"ArrowUp":{E();break}case"ArrowDown":{k();break}case"Enter":{L.preventDefault(),b(m.value);break}}}}),P.value&&he("ul",{class:"suggestions",onMouseleave:()=>m.value=-1},p.value.map(({link:L,title:M,header:U},ee)=>he("li",{class:["suggestion",{focus:m.value===ee}],onMouseenter:()=>m.value=ee,onMousedown:()=>b(ee)},he("a",{href:L,onClick:w=>w.preventDefault()},[he("span",{class:"page-title"},M),U&&he("span",{class:"page-header"},`> ${U}`)]))))])}});const ff={"/en/":{placeholder:"Search"},"/zh-cn/":{placeholder:"\u641C\u7D22"}},gf=["s","/"],kf=5,vf=Mt({enhance({app:e}){e.component("SearchBox",t=>he(mf,{locales:ff,hotKeys:gf,maxSuggestions:kf,...t}))}}),oi=[Nd,Yd,Xd,nu,cu,mu,nf,vf];var Ua=ye(es),Wa=Ro({key:"",path:"",title:"",lang:"",frontmatter:{},excerpt:"",headers:[]}),gt=ye(Wa),Ot=()=>gt;import.meta.webpackHot&&(__VUE_HMR_RUNTIME__.updatePageData=e=>{Ua.value[e.key]=()=>Promise.resolve(e),e.key===gt.value.key&&(gt.value=e)});var Xa=Symbol(""),vt=()=>{const e=He(Xa);if(!e)throw new Error("usePageFrontmatter() is called without provider.");return e},qa=Symbol(""),bf=()=>{const e=He(qa);if(!e)throw new Error("usePageHead() is called without provider.");return e},_f=Symbol(""),Ka=Symbol(""),yf=()=>{const e=He(Ka);if(!e)throw new Error("usePageLang() is called without provider.");return e},No=Symbol(""),Wl=()=>{const e=He(No);if(!e)throw new Error("useRouteLocale() is called without provider.");return e},Tt=ye(Ah),Ga=()=>Tt;import.meta.webpackHot&&(__VUE_HMR_RUNTIME__.updateSiteData=e=>{Tt.value=e});var Qa=Symbol(""),jo=()=>{const e=He(Qa);if(!e)throw new Error("useSiteLocaleData() is called without provider.");return e},xf=Symbol(""),Ut=gl({resolvePageData:async e=>{const t=Ua.value[e],l=await(t==null?void 0:t());return l!=null?l:Wa},resolvePageFrontmatter:e=>e.frontmatter,resolvePageHead:(e,t,l)=>{const i=be(t.description)?t.description:l.description,o=[...te(t.head)?t.head:[],...l.head,["title",{},e],["meta",{name:"description",content:i}]];return Ih(o)},resolvePageHeadTitle:(e,t)=>`${e.title?`${e.title} | `:""}${t.title}`,resolvePageLang:e=>e.lang||"en",resolveRouteLocale:(e,t)=>pa(e,t),resolveSiteLocaleData:(e,t)=>({...e,...e.locales[t]})}),$o=ue({name:"ClientOnly",setup(e,t){const l=ye(!1);return Ze(()=>{l.value=!0}),()=>{var i,o;return l.value?(o=(i=t.slots).default)==null?void 0:o.call(i):null}}}),Ef=ue({name:"Content",props:{pageKey:{type:String,required:!1,default:""}},setup(e){const t=Ot(),l=Y(()=>ma[e.pageKey||t.value.key]);return()=>l.value?he(l.value):he("div","404 Not Found")}}),Rf="Layout",Cf="NotFound",Pf=oi.reduce((e,t)=>({...e,...t.layouts}),{}),cr=ue({name:"Vuepress",setup(){const e=Ot(),t=Y(()=>{let l;if(e.value.path){const i=e.value.frontmatter.layout;be(i)?l=i:l=Rf}else l=Cf;return Pf[l]});return()=>he(t.value)}}),Yo=e=>Ul(e)?e:`${Ga().value.base}${ua(e)}`;const Lf=[["v-8daa1a0e","/",{title:""},["/index.html","/index.md"]],["v-2d0a870d","/en/",{title:"Home"},["/en/index.html","/en/index.md"]],["v-c0c85b84","/zh-cn/",{title:"\u9996\u9875"},["/zh-cn/index.html","/zh-cn/index.md"]],["v-7a15fe3b","/en/about/about.html",{title:"About this Document"},["/en/about/about","/en/about/about.md"]],["v-3f851d14","/en/about/changelog.html",{title:"Changelog"},["/en/about/changelog","/en/about/changelog.md"]],["v-193cf592","/en/about/contacts.html",{title:"Contact Us"},["/en/about/contacts","/en/about/contacts.md"]],["v-ae7b83f2","/en/about/future.html",{title:"Looking for Future"},["/en/about/future","/en/about/future.md"]],["v-64fc7bb8","/en/api/home.html",{title:"Document Introduce"},["/en/api/home","/en/api/home.md"]],["v-9cfea7fc","/en/config/api-example.html",{title:"API Basic Configs"},["/en/config/api-example","/en/config/api-example.md"]],["v-72c12b7d","/en/config/api-exception.html",{title:"API Exception Handling"},["/en/config/api-exception","/en/config/api-exception.md"]],["v-793879e8","/en/config/api-using.html",{title:"Use as Hook API Configs"},["/en/config/api-using","/en/config/api-using.md"]],["v-29d6c1ba","/en/config/r8-proguard.html",{title:"R8 & Proguard Obfuscate"},["/en/config/r8-proguard","/en/config/r8-proguard.md"]],["v-24e71de7","/en/config/xposed-using.html",{title:"Use as Xposed Module Configs"},["/en/config/xposed-using","/en/config/xposed-using.md"]],["v-7b22efaf","/en/guide/example.html",{title:"Usage Example"},["/en/guide/example","/en/guide/example.md"]],["v-efb45d4c","/en/guide/home.html",{title:"Introduce"},["/en/guide/home","/en/guide/home.md"]],["v-277b35ca","/en/guide/knowledge.html",{title:"Basic Knowledge"},["/en/guide/knowledge","/en/guide/knowledge.md"]],["v-77d752a2","/en/guide/move-to-new-api.html",{title:"Migrate from Xposed API"},["/en/guide/move-to-new-api","/en/guide/move-to-new-api.md"]],["v-72889797","/en/guide/quick-start.html",{title:"Quick Start"},["/en/guide/quick-start","/en/guide/quick-start.md"]],["v-55c11626","/en/tools/yukihookapi-projectbuilder.html",{title:"YukiHookAPI Project Builder"},["/en/tools/yukihookapi-projectbuilder","/en/tools/yukihookapi-projectbuilder.md"]],["v-41967128","/zh-cn/about/about.html",{title:"\u5173\u4E8E\u6B64\u6587\u6863"},["/zh-cn/about/about","/zh-cn/about/about.md"]],["v-0e6c3476","/zh-cn/about/changelog.html",{title:"\u66F4\u65B0\u65E5\u5FD7"},["/zh-cn/about/changelog","/zh-cn/about/changelog.md"]],["v-6cf86266","/zh-cn/about/contacts.html",{title:"\u8054\u7CFB\u6211\u4EEC"},["/zh-cn/about/contacts","/zh-cn/about/contacts.md"]],["v-3106ca14","/zh-cn/about/future.html",{title:"\u5C55\u671B\u672A\u6765"},["/zh-cn/about/future","/zh-cn/about/future.md"]],["v-c8deafb2","/zh-cn/api/home.html",{title:"\u6587\u6863\u4ECB\u7ECD"},["/zh-cn/api/home","/zh-cn/api/home.md"]],["v-c6114c9e","/zh-cn/config/api-example.html",{title:"API \u57FA\u672C\u914D\u7F6E"},["/zh-cn/config/api-example","/zh-cn/config/api-example.md"]],["v-5b43296c","/zh-cn/config/api-exception.html",{title:"API \u5F02\u5E38\u5904\u7406"},["/zh-cn/config/api-exception","/zh-cn/config/api-exception.md"]],["v-2ee67152","/zh-cn/config/api-using.html",{title:"\u4F5C\u4E3A Hook API \u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E"},["/zh-cn/config/api-using","/zh-cn/config/api-using.md"]],["v-154d6f69","/zh-cn/config/r8-proguard.html",{title:"R8 \u4E0E Proguard \u6DF7\u6DC6"},["/zh-cn/config/r8-proguard","/zh-cn/config/r8-proguard.md"]],["v-af73b3d0","/zh-cn/config/xposed-using.html",{title:"\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E"},["/zh-cn/config/xposed-using","/zh-cn/config/xposed-using.md"]],["v-13b430a0","/zh-cn/guide/example.html",{title:"\u7528\u6CD5\u793A\u4F8B"},["/zh-cn/guide/example","/zh-cn/guide/example.md"]],["v-6a609e09","/zh-cn/guide/home.html",{title:"\u4ECB\u7ECD"},["/zh-cn/guide/home","/zh-cn/guide/home.md"]],["v-b4f1a468","/zh-cn/guide/knowledge.html",{title:"\u57FA\u7840\u77E5\u8BC6"},["/zh-cn/guide/knowledge","/zh-cn/guide/knowledge.md"]],["v-c0d5dada","/zh-cn/guide/move-to-new-api.html",{title:"\u4ECE Xposed API \u8FC1\u79FB"},["/zh-cn/guide/move-to-new-api","/zh-cn/guide/move-to-new-api.md"]],["v-24840ff0","/zh-cn/guide/quick-start.html",{title:"\u5FEB\u901F\u5F00\u59CB"},["/zh-cn/guide/quick-start","/zh-cn/guide/quick-start.md"]],["v-a2fab4d6","/zh-cn/tools/yukihookapi-projectbuilder.html",{title:"YukiHookAPI \u6784\u5EFA\u5DE5\u5177"},["/zh-cn/tools/yukihookapi-projectbuilder","/zh-cn/tools/yukihookapi-projectbuilder.md"]],["v-12042f1f","/en/api/special-features/host-inject.html",{title:"Host Resource Injection Extension"},["/en/api/special-features/host-inject","/en/api/special-features/host-inject.md"]],["v-deaff1d0","/en/api/special-features/host-lifecycle.html",{title:"Host Lifecycle Extension"},["/en/api/special-features/host-lifecycle","/en/api/special-features/host-lifecycle.md"]],["v-33c1dc26","/en/api/special-features/logger.html",{title:"Debug Logs"},["/en/api/special-features/logger","/en/api/special-features/logger.md"]],["v-581ddb9c","/en/api/special-features/reflection.html",{title:"Reflection Extensions"},["/en/api/special-features/reflection","/en/api/special-features/reflection.md"]],["v-2e6ad66c","/en/api/special-features/xposed-channel.html",{title:"Xposed Module and Host Channel"},["/en/api/special-features/xposed-channel","/en/api/special-features/xposed-channel.md"]],["v-68bebbf4","/en/api/special-features/xposed-storage.html",{title:"Xposed Module Data Storage"},["/en/api/special-features/xposed-storage","/en/api/special-features/xposed-storage.md"]],["v-6ac5be8e","/zh-cn/api/special-features/host-inject.html",{title:"\u5BBF\u4E3B\u8D44\u6E90\u6CE8\u5165\u6269\u5C55"},["/zh-cn/api/special-features/host-inject","/zh-cn/api/special-features/host-inject.md"]],["v-357a8d49","/zh-cn/api/special-features/host-lifecycle.html",{title:"\u5BBF\u4E3B\u751F\u547D\u5468\u671F\u6269\u5C55"},["/zh-cn/api/special-features/host-lifecycle","/zh-cn/api/special-features/host-lifecycle.md"]],["v-1f0f591e","/zh-cn/api/special-features/logger.html",{title:"\u8C03\u8BD5\u65E5\u5FD7"},["/zh-cn/api/special-features/logger","/zh-cn/api/special-features/logger.md"]],["v-001858e3","/zh-cn/api/special-features/reflection.html",{title:"\u5B57\u8282\u7801\u4E0E\u53CD\u5C04\u6269\u5C55"},["/zh-cn/api/special-features/reflection","/zh-cn/api/special-features/reflection.md"]],["v-598546c6","/zh-cn/api/special-features/xposed-channel.html",{title:"Xposed \u6A21\u5757\u4E0E\u5BBF\u4E3B\u901A\u8BAF\u6865"},["/zh-cn/api/special-features/xposed-channel","/zh-cn/api/special-features/xposed-channel.md"]],["v-0d914225","/zh-cn/api/special-features/xposed-storage.html",{title:"Xposed \u6A21\u5757\u6570\u636E\u5B58\u50A8"},["/zh-cn/api/special-features/xposed-storage","/zh-cn/api/special-features/xposed-storage.md"]],["v-053599a5","/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.html",{title:"YukiHookAPI - object"},["/en/api/public/com/highcapable/yukihookapi/YukiHookAPI","/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.md"]],["v-6931cb54","/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.html",{title:"YukiHookAPI - object"},["/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI","/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.md"]],["v-818b3ca6","/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html",{title:"InjectYukiHookWithXposed - annotation"},["/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed","/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.md"]],["v-b6a815c4","/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html",{title:"CurrentClass - class"},["/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass","/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.md"]],["v-0183e3fc","/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html",{title:"GenericClass - class"},["/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass","/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.md"]],["v-57506200","/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html",{title:"HookClass - class"},["/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass","/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.md"]],["v-9af56c1a","/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html",{title:"HookResources - class"},["/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources","/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.md"]],["v-032b1710","/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html",{title:"VariousClass - class"},["/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass","/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.md"]],["v-71147891","/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html",{title:"YukiMemberHookCreator - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator","/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md"]],["v-5ed1ceee","/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html",{title:"YukiResourcesHookCreator - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator","/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.md"]],["v-e288ce96","/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html",{title:"YukiBaseHooker - class"},["/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker","/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.md"]],["v-0d0fcec2","/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html",{title:"ReflectionFactory - kt"},["/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory","/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.md"]],["v-65091354","/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html",{title:"YukiHookFactory - kt"},["/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory","/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.md"]],["v-36aec5ad","/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html",{title:"LoggerFactory - kt"},["/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory","/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.md"]],["v-60cbe1b4","/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html",{title:"HookParam - class"},["/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam","/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md"]],["v-b381a126","/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html",{title:"PackageParam - class"},["/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam","/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.md"]],["v-6e47300f","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html",{title:"CurrentClass - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.md"]],["v-69c1c226","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html",{title:"GenericClass - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.md"]],["v-735374af","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html",{title:"HookClass - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.md"]],["v-1c516d22","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html",{title:"HookResources - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.md"]],["v-66735bfe","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html",{title:"VariousClass - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass","/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.md"]],["v-30f3ba1e","/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html",{title:"InjectYukiHookWithXposed - annotation"},["/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed","/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.md"]],["v-3ac40680","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html",{title:"YukiMemberHookCreator - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.md"]],["v-5e81af42","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html",{title:"YukiResourcesHookCreator - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.md"]],["v-516df326","/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html",{title:"YukiBaseHooker - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker","/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.md"]],["v-213d88b3","/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html",{title:"ReflectionFactory - kt"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.md"]],["v-448e9585","/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html",{title:"YukiHookFactory - kt"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.md"]],["v-004a009e","/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html",{title:"LoggerFactory - kt"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.md"]],["v-75a9b636","/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html",{title:"HookParam - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam","/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.md"]],["v-100b529c","/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html",{title:"PackageParam - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam","/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.md"]],["v-8293d958","/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html",{title:"ComponentTypeFactory - kt"},["/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.md"]],["v-7b0abf86","/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html",{title:"GraphicsTypeFactory - kt"},["/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.md"]],["v-5309e4a0","/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html",{title:"ViewTypeFactory - kt"},["/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.md"]],["v-a2615d0c","/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html",{title:"DefinedTypeFactory - kt"},["/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.md"]],["v-ba01a600","/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html",{title:"VariableTypeFactory - kt"},["/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory","/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.md"]],["v-7fec5836","/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html",{title:"ModuleApplication - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication","/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.md"]],["v-7414265a","/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html",{title:"YukiHookDataChannel - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel","/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.md"]],["v-003862c2","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html",{title:"YukiHookModulePrefs - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.md"]],["v-1d680acc","/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html",{title:"IYukiHookXposedInit - interface"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit","/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.md"]],["v-5e874c45","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html",{title:"ComponentTypeFactory - kt"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.md"]],["v-4ea62475","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html",{title:"GraphicsTypeFactory - kt"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.md"]],["v-ef79cde2","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html",{title:"ViewTypeFactory - kt"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.md"]],["v-5acc12ab","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html",{title:"DefinedTypeFactory - kt"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.md"]],["v-14ec8671","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html",{title:"VariableTypeFactory - kt"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory","/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.md"]],["v-4709ad58","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html",{title:"ModuleApplication - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.md"]],["v-632be8ee","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html",{title:"YukiHookDataChannel - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.md"]],["v-5858709e","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html",{title:"YukiHookModulePrefs - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.md"]],["v-763140ee","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html",{title:"IYukiHookXposedInit - interface"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.md"]],["v-4fca92c0","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html",{title:"BaseFinder - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.md"]],["v-2a898c66","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html",{title:"DexClassFinder - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.md"]],["v-a71937aa","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html",{title:"ConstructorFinder - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.md"]],["v-42e0f0ab","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html",{title:"FieldFinder - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.md"]],["v-a4aa4d00","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html",{title:"MethodFinder - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.md"]],["v-0f1e3594","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html",{title:"YukiModuleResources - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.md"]],["v-35faec91","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html",{title:"YukiResForwarder - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.md"]],["v-2c04b82a","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html",{title:"YukiResources - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.md"]],["v-19e7277e","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html",{title:"YukiXposedEvent - object"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent","/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.md"]],["v-2f64a2d4","/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html",{title:"ChannelData - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData","/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.md"]],["v-58ed8298","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html",{title:"PrefsData - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.md"]],["v-23e1a817","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html",{title:"ModulePreferenceFragment - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment","/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.md"]],["v-0f719471","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html",{title:"BaseFinder - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.md"]],["v-45111efc","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html",{title:"DexClassFinder - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.md"]],["v-1e2cbc9c","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html",{title:"ConstructorFinder - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.md"]],["v-22449c48","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html",{title:"FieldFinder - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.md"]],["v-fd738322","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html",{title:"MethodFinder - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.md"]],["v-3d943532","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html",{title:"YukiModuleResources - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.md"]],["v-526c4200","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html",{title:"YukiResForwarder - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.md"]],["v-68541dca","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html",{title:"YukiResources - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.md"]],["v-0a4de82f","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html",{title:"YukiXposedEvent - object"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.md"]],["v-493d37f6","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html",{title:"ChannelData - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.md"]],["v-d99f7f36","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html",{title:"PrefsData - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.md"]],["v-53bcae06","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html",{title:"ModulePreferenceFragment - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.md"]],["v-52995ef7","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html",{title:"CountRules - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.md"]],["v-8d5ce71a","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html",{title:"ModifierRules - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.md"]],["v-f5b1ffb2","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html",{title:"NameRules - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.md"]],["v-08b70f7f","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html",{title:"ConstructorRules - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.md"]],["v-21f64ebf","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html",{title:"FieldRules - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.md"]],["v-77f11cf9","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html",{title:"MemberRules - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.md"]],["v-64827680","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html",{title:"MethodRules - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.md"]],["v-2d5d16db","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html",{title:"ModuleAppActivity - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.md"]],["v-cadbe48e","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html",{title:"ModuleAppCompatActivity - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.md"]],["v-78731c50","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html",{title:"ModuleContextThemeWrapper - class"},["/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper","/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.md"]],["v-1b2ad030","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html",{title:"CountRules - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.md"]],["v-547a3c3c","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html",{title:"ModifierRules - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.md"]],["v-58c26516","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html",{title:"NameRules - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.md"]],["v-a42f54a4","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html",{title:"ConstructorRules - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.md"]],["v-3e67a42e","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html",{title:"FieldRules - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.md"]],["v-2cab152c","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html",{title:"MemberRules - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.md"]],["v-5388621e","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html",{title:"MethodRules - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.md"]],["v-44efb702","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html",{title:"ModuleContextThemeWrapper - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.md"]],["v-1446bdca","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html",{title:"ModuleAppActivity - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.md"]],["v-c7cef530","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html",{title:"ModuleAppCompatActivity - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity","/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.md"]],["v-5e375d98","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html",{title:"MemberRulesResult - class"},["/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult","/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.md"]],["v-b8000f3a","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html",{title:"MemberRulesResult - class"},["/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult","/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.md"]],["v-3706649a","/404.html",{title:""},["/404"]]];var Af=()=>Lf.reduce((e,[t,l,i,o])=>(e.push({name:t,path:l,component:cr,meta:i},...o.map(n=>({path:n,redirect:l}))),e),[{name:"404",path:"/:catchAll(.*)",component:cr}]),Tf=Gh,If=()=>{const e=Fd({history:Tf(da(Tt.value.base)),routes:Af(),scrollBehavior:(t,l,i)=>i||(t.hash?{el:t.hash}:{top:0})});return e.beforeResolve(async(t,l)=>{var i;(t.path!==l.path||l===mt)&&([gt.value]=await Promise.all([Ut.resolvePageData(t.name),(i=ma[t.name])==null?void 0:i.__asyncLoader()]))}),e},wf=e=>{e.component("ClientOnly",$o),e.component("Content",Ef)},Of=(e,t)=>{const l=Y(()=>Ut.resolveRouteLocale(Tt.value.locales,t.currentRoute.value.path)),i=Y(()=>Ut.resolveSiteLocaleData(Tt.value,l.value)),o=Y(()=>Ut.resolvePageFrontmatter(gt.value)),n=Y(()=>Ut.resolvePageHeadTitle(gt.value,i.value)),r=Y(()=>Ut.resolvePageHead(n.value,o.value,i.value)),a=Y(()=>Ut.resolvePageLang(gt.value));return e.provide(No,l),e.provide(Qa,i),e.provide(Xa,o),e.provide(_f,n),e.provide(qa,r),e.provide(Ka,a),Object.defineProperties(e.config.globalProperties,{$frontmatter:{get:()=>o.value},$head:{get:()=>r.value},$headTitle:{get:()=>n.value},$lang:{get:()=>a.value},$page:{get:()=>gt.value},$routeLocale:{get:()=>l.value},$site:{get:()=>Tt.value},$siteLocale:{get:()=>i.value},$withBase:{get:()=>Yo}}),{pageData:gt,pageFrontmatter:o,pageHead:r,pageHeadTitle:n,pageLang:a,routeLocale:l,siteData:Tt,siteLocaleData:i}},Ff=()=>{const e=St(),t=bf(),l=yf(),i=ye([]),o=()=>{t.value.forEach(r=>{const a=zf(r);a&&i.value.push(a)})},n=()=>{document.documentElement.lang=l.value,i.value.forEach(r=>{r.parentNode===document.head&&document.head.removeChild(r)}),i.value.splice(0,i.value.length),t.value.forEach(r=>{const a=Df(r);a!==null&&(document.head.appendChild(a),i.value.push(a))})};Gt(xf,n),Ze(()=>{o(),n(),dt(()=>e.path,()=>n())})},zf=([e,t,l=""])=>{const i=Object.entries(t).map(([a,s])=>be(s)?`[${a}="${s}"]`:s===!0?`[${a}]`:"").join(""),o=`head > ${e}${i}`;return Array.from(document.querySelectorAll(o)).find(a=>a.innerText===l)||null},Df=([e,t,l])=>{if(!be(e))return null;const i=document.createElement(e);return Oo(t)&&Object.entries(t).forEach(([o,n])=>{be(n)?i.setAttribute(o,n):n===!0&&i.setAttribute(o,"")}),be(l)&&i.appendChild(document.createTextNode(l)),i},Hf=Ph,Mf=async()=>{var l;const e=Hf({name:"VuepressApp",setup(){var i;Ff();for(const o of oi)(i=o.setup)==null||i.call(o);return()=>[he(Pa),...oi.flatMap(({rootComponents:o=[]})=>o.map(n=>he(n)))]}}),t=If();wf(e),Of(e,t);for(const i of oi)await((l=i.enhance)==null?void 0:l.call(i,{app:e,router:t,siteData:Tt}));return e.use(t),{app:e,router:t}};Mf().then(({app:e,router:t})=>{t.isReady().then(()=>{e.mount("#app")})});export{Ae as _,jc as a,fe as b,J as c,Mf as createVueApp,oe as d,Ht as e,N as o,_t as r,Me as w}; diff --git a/docs/assets/back-to-top.8efcbe56.svg b/docs/assets/back-to-top.8efcbe56.svg new file mode 100644 index 00000000..83236781 --- /dev/null +++ b/docs/assets/back-to-top.8efcbe56.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/assets/changelog.html.05a4745e.js b/docs/assets/changelog.html.05a4745e.js new file mode 100644 index 00000000..7993200a --- /dev/null +++ b/docs/assets/changelog.html.05a4745e.js @@ -0,0 +1 @@ +const l=JSON.parse('{"key":"v-0e6c3476","path":"/zh-cn/about/changelog.html","title":"\u66F4\u65B0\u65E5\u5FD7","lang":"zh-CN","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":3}]},"filePathRelative":"zh-cn/about/changelog.md"}');export{l as data}; diff --git a/docs/assets/changelog.html.22a53013.js b/docs/assets/changelog.html.22a53013.js new file mode 100644 index 00000000..a11176d5 --- /dev/null +++ b/docs/assets/changelog.html.22a53013.js @@ -0,0 +1 @@ +import{_ as s,r as c,o as a,c as l,b as e,d as t,a as n,e as o}from"./app.fb8271cf.js";const r={},h=n('

    Changelog

    The version update history of YukiHookAPI is recorded here.

    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

    ',4),u={id:"_1-1-0-2022-09-28",tabindex:"-1"},_=e("a",{class:"header-anchor",href:"#_1-1-0-2022-09-28","aria-hidden":"true"},"#",-1),m=o(" 1.1.0 | 2022.09.28 \u2002"),p=e("li",null,[o("This is a major version update, please refer to "),e("a",{href:"../api/home"},"API Document"),o(" and "),e("a",{href:"../api/special-features/reflection"},"Special Features"),o(" for the changes and usage mentioned in the changelog")],-1),f=o("Change the help documentation framework to "),g={href:"https://v2.vuepress.vuejs.org",target:"_blank",rel:"noopener noreferrer"},k=o("VuePress"),b=n("
  • Unify and standardize the terms and nouns in the document, for example, "query" is always changed to "find", XposedHelper is misspelled and changed to XposedHelpers
  • Documentation Getting Started \u2192 Basic Knowledge page to add a link, Simplified Chinese only
  • Convert Class and Method of Hook App Demo to Java to provide better demo effect
  • Fixed code comment naming in Hook Module Demo
  • Refactored a lot of low-level Hook logic and the docking method of Xposed API
  • Removed HookParamWrapper, it now interfaces directly with YukiBridgeFactory
  • Moved methods in section YukiHookBridge to AppParasitics
  • Removed HookParam.args and the underlying direct connection method setArgs, directly get and set the object of the current array
  • Optimized automatic handler to merge referenced jar into stub project
  • ",9),y=o("Fix the problem that the module package name cannot be correctly matched when multi-project packaging, and modify the module package name matching logic of the automatic handler, thanks to "),x={href:"https://github.com/5ec1cff",target:"_blank",rel:"noopener noreferrer"},v=o("5ec1cff"),w=o(" for the feedback and solutions provided"),A=n("
  • Internal closure processing for the methods of API private tool classes to avoid polluting the top-level namespace
  • Fixed Creater naming to Creator for all reflection and Hook classes
  • Added YukiHookAPI.Status.compiledTimestamp function, which can get the compilation completion timestamp when used as an Xposed module
  • Added YukiHookAPI.Status.isXposedEnvironment function, which can determine whether the current (Xposed) host environment or module environment is
  • The debug logging function has been overhauled, and functions such as YukiHookAPI.Configs.debugTag have been merged into YukiHookLogger.Configs
  • The debug log can be added to specify the printing method as XposedBridge.log or Logd
  • The package name of the current host and the current user ID are added to the debug log by default for debugging, you can change it yourself in the debugLog configuration
  • Added generic function to reflect and call generics, you can use it in Class or CurrentClass
  • obsolete the buildOfAny method, now use the buildOf method directly (without generics) to use the constructor to create a new object and get the result Any
  • Fixed the issue of null pointer exception when using hasExtends
  • CurrentClass added non-lambda method of calling
  • CurrentClass adds name and simpleName functions
  • Completely rewrite the core method of ReflectionTool, sorting and classifying different search conditions
  • Fix the problem that Member obtained by directly calling declared in ReflectionTool throws an exception
  • Fix UndefinedType in ReflectionTool is not correctly judged in Method and Constructor conditions
  • Added a friendly prompt method when the reflection search result is abnormal, which can specifically locate the problem that Member cannot be found under specified conditions
  • Added VagueType condition in Method and Constructor for reflection search, which can be used in param condition to ignore parameters you don't want to fill in
  • Added paramCount { ... } condition in Method and Constructor of reflection search, now you can directly get it in it to customize your judgment condition
  • The current method is added to the FieldFinder result, which can directly create a call space for the result instance
  • Modified the modifiers 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 true
  • ",20),H=e("code",null,"as*",-1),P=o(" function in "),F=e("code",null,"ModifierRules",-1),C=o(" renamed to "),M=e("code",null,"is*",-1),I=o(", thanks to "),R={href:"https://github.com/KyuubiRan",target:"_blank",rel:"noopener noreferrer"},S=o("Kitsune"),Y=o(" suggestion"),X=n("
  • Added RemedyPlan feature in FieldFinder
  • Added Class fuzzy search function (Beta) in Dex, you can now directly use searchClass function to fuzzy search Class with specified conditions
  • ",2),T=o("Added multiple search function in reflection search, you can use relative search conditions to obtain multiple search results at the same time, thanks to "),z=e("strong",null,"AA",-1),L=o(" and "),W={href:"https://github.com/KyuubiRan",target:"_blank",rel:"noopener noreferrer"},D=o("Kitsune"),j=o(" for suggestions"),B=o("Fix the problem that the object obtained by "),N=e("code",null,"appClassLoader",-1),O=o(" is incorrect in system applications in some systems, thanks to "),U={href:"https://github.com/luckyzyx",target:"_blank",rel:"noopener noreferrer"},q=o("Luckyzyx"),E=o(" for the feedback"),V=e("li",null,[o("Modified the calling method of "),e("code",null,"XposedBridge.invokeOriginalMethod"),o(" and added "),e("code",null,"original"),o(" function in "),e("code",null,"MethodFinder.Result.Instance")],-1),K=o("Fix the problem of wrong value of "),Z=e("code",null,"getStringSet",-1),G=o(" method in "),J=e("code",null,"YukiHookModulePrefs",-1),Q=o(" and optimize the code style, thanks to "),$={href:"https://github.com/Teddy-Zhu",target:"_blank",rel:"noopener noreferrer"},ee=o("Teddy_Zhu"),oe=o(),te={href:"https://github.com/fankes/YukiHookAPI/pull/19",target:"_blank",rel:"noopener noreferrer"},de=o("PR"),ie=e("li",null,[o("Modify "),e("code",null,"YukiHookModulePrefs"),o(" to intercept exceptions that may not exist in "),e("code",null,"XSharePreference")],-1),ne=e("li",null,[o("Fixed the problem that "),e("code",null,"YukiHookDataChannel"),o(" could not be successfully registered in some third-party ROM system frameworks")],-1),ce=e("li",null,[o("Secured "),e("code",null,"YukiHookDataChannel"),o(", now it can only communicate between modules from the specified package name and the host")],-1),se=o("Added automatic hook "),ae=e("code",null,"SharedPreferences",-1),le=o(" to fix the problem that file permissions are not "),re=e("code",null,"0664",-1),he=o(" in some systems, thanks to "),ue={href:"https://github.com/5ec1cff",target:"_blank",rel:"noopener noreferrer"},_e=o("5ec1cff"),me=o(" for the feedback and implementation code provided"),pe=n("
  • Added YukiHookAPI.Configs.isEnableHookSharedPreferences function, which is disabled by default and can be enabled if the permission of SharedPreferences is incorrect
  • Fixed the bug that the no-parameter construction method cannot be found when searching for Constructor without filling in the search conditions, thanks B5 KAKA for the feedback
  • Detach Result instances located in method, constructor in injectMember to Process
  • Added the 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 declared
  • Added module resource injection and Activity proxy functions, you can call injectModuleAppResources and registerModuleAppActivities to use
  • Added ModuleContextThemeWrapper function, you can call applyModuleTheme to create the Context of a module in any Activity
  • Added ClassLoader.onLoadClass function, which can be used to listen for events when the loadClass method of ClassLoader is called
  • obsolete classOf and clazz extension methods, add toClass and toClassOrNull usage, please move to the new method now
  • VariousClass adds a getOrNull method, which can return null instead of throwing an exception when it can't match Class
  • Removed 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
  • no longer expose any methods in HookClass
  • Added throwToApp function in HookParam, which can throw exceptions directly to the host
  • The onFailureThrowToApp function is added to the Hook callback, which can be directly thrown to the host when an exception occurs
  • Modified the printing logic of the debug log, the time-consuming records in the reflection search function will only be printed during the Hook process
  • Added the function of removing Hook in the Hook process, you can use the remove and removeSelf methods to remove the hook
  • Fixed the issue that caused the host to throw an exception when ReplaceHook failed, and now it is modified to call the original method to ensure the normal operation of the host function
  • Added the function of checking the return value of the method in the Hook process. If the return value does not match, it will automatically throw an exception or print an error according to the situation
  • ",18),fe=o("Added "),ge=e("code",null,"array",-1),ke=o(" type to Resources Hook, thanks to "),be={href:"https://github.com/fankes/YukiHookAPI/pull/12",target:"_blank",rel:"noopener noreferrer"},ye=o("PR"),xe=o(" of "),ve={href:"https://github.com/GSWXXN",target:"_blank",rel:"noopener noreferrer"},we=o("GSWXXN"),Ae=e("li",null,[o("Moved "),e("code",null,"me.weishu.reflection"),o(" to "),e("code",null,"thirdparty"),o(" to prevent conflicting dependencies of the same name introduced at the same time")],-1),He=e("li",null,"Remove the exception thrown when the Hook method body is empty, and modify it to print the warning log",-1),Pe=e("li",null,[o("Modify the exception handling logic of "),e("code",null,"AppLifecycle"),o(" and throw it directly to the host when an exception occurs")],-1),Fe=e("li",null,"Updated Demo API version to 33",-1),Ce={id:"_1-0-92-2022-05-31",tabindex:"-1"},Me=e("a",{class:"header-anchor",href:"#_1-0-92-2022-05-31","aria-hidden":"true"},"#",-1),Ie=o(" 1.0.92 | 2022.05.31 \u2002"),Re=n("
    • Fixed the naming method of callback in a large number of methods
    • Changed the solution to fix the problem that YukiHookDataChannel cannot call back the current Activity broadcast on devices lower than Android 12
    • The InjectYukiHookWithXposed annotation adds the isUsingResourcesHook function, now you can selectively disable the dependency interface that automatically generates IXposedHookInitPackageResources
    ",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("
  • Fixed YukiHookDataChannel not being able to call back the current Activity broadcast on ZUI and systems below Android 12
  • Integrate the YukiHookModuleStatus 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
  • ",2),Ne={id:"_1-0-90-2022-05-27",tabindex:"-1"},Oe=e("a",{class:"header-anchor",href:"#_1-0-90-2022-05-27","aria-hidden":"true"},"#",-1),Ue=o(" 1.0.90 | 2022.05.27 \u2002"),qe=n("
    • Fixed YukiHookDataChannel crashing when the module sets the listener callback
    • Fixed YukiHookDataChannel still calling back when not in current Activity
    • Remove the default value of YukiHookDataChannel callback event, no callback
    • Removed YukiHookModulePrefs warning printed if XShare is unreadable
    • Added the isXSharePrefsReadable method in YukiHookModulePrefs to determine whether the current XShare is available
    ",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("
    • Fixed the problem that 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 function
    • Added YukiHookDataChannel repeated listening use case description document
    • Add the onAlreadyHooked method to determine whether the current method is repeated Hook
    • Modify part of the logic of repeatedly adding HashMap, remove the putIfAbsent method, allow to override the addition
    • Fixed several possible bugs
    ",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("
    • Fully decoupled from Xposed API
    • Added android type in type
    • Separate YukiHookModuleStatus from auto-generated code and add isEnableHookModuleStatus switch, it is up to you to enable or not
    • Internal closure processing for the constructors of a large number of classes in the API
    • Set YukiHookModulePrefs to run as a singleton to prevent repeated creation and waste of system resources
    • Fix the bug that Hook cannot be nested since version 1.0.80, and optimize the related functions of nested Hook
    • Modify the Hooker storage scheme from HashSet to HashMap to prevent the problem of repeatedly adding Hookers
    • Modify the core implementation method of Hook, add duplicate checking to avoid repeating the Hook multiple callbacks to the HookParam method
    • MethodFinder and FieldFinder add the function of finding fuzzy methods and variable names, you can call name { ... } to set search conditions, and support regular expressions
    • Optimize and modify the way to get appContext to reduce the possibility of getting empty
    • Modify the print TAG of logger in the automatically generated code to default to your custom name, which is convenient for debugging
    • Optimize the Hooker implementation of YukiHookBridge to improve Hook performance
    • PackageParam adds the onAppLifecycle method, which can natively monitor the life cycle of the host and implement the registration system broadcast function
    • Added YukiHookDataChannel function to communicate using system out-of-order broadcast while the module and the host remain alive
    • YukiHookDataChannel adds the checkingVersionEquals method, which can be monitored to verify that the host has not updated the version mismatch problem after the module is updated
    • Added Java version example in the example code of demo-module for reference only
    ",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("
  • The InjectYukiHookWithXposed annotation adds the entryClassName function, which can customize the generated xposed_init entry class name
  • YukiHookXposedInitProxy renamed to IYukiHookXposedInit, the original interface name has been invalidated and will be deleted directly in subsequent versions
  • Added initZygote and Resources Hook functions to support Hook Layout
  • Added onXposedEvent method to listen to all events of native Xposed API
  • Perform inline processing on the lambda of the Hook function to avoid generating excessively broken anonymous classes and improve the running performance after compilation
  • Fix PrefsData compiled method body copy is too large
  • Added XSharePreference readability test, which will automatically print a warning log if it fails
  • PackageParam adds appResources, moduleAppResources, moduleAppFilePath functions
  • loadApp of PackageParam adds the function of not writing name, and all APPs are filtered by default
  • PackageParam adds the loadZygote method, which can directly hook the system framework
  • PackageParam added resources().hook function
  • Optimization method, construction method, variable search function, the error log that cannot be found will display the set query conditions first
  • Added hasExtends extension method to determine whether the current Class has an inheritance relationship
  • Added isSupportResourcesHook function to determine whether resource hooks are currently supported (Resources Hook)
  • current function adds superClass method to call superclass
  • New superClass query conditions for search methods, construction methods and variables, you can continue to search in the parent class
  • YukiHookAPI lots of methods are decoupled from Xposed API
  • Added native Hook priority function of Xposed API
  • Fix the problem that isFirstApplication may be inaccurate
  • Block the problem that MiuiCatcherPatch repeatedly calls the Hook entry method on the MIUI system
  • Optimize Hook entry calling method to avoid multiple calls due to Hook Framework issues
  • ",21),Mo=o("Fix the problem that Hook "),Io=e("code",null,"ClassLoader",-1),Ro=o(" causes Hook to freeze, thanks to "),So={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},Yo=o("WankkoRee"),Xo=o(" for the feedback"),To=e("li",null,[o("Improve the performance after the "),e("code",null,"XC_Callback"),o(" interface is connected")],-1),zo=e("li",null,[o("Java "),e("code",null,"type"),o(" added "),e("code",null,"ClassLoader"),o(" type")],-1),Lo=e("li",null,"Optimize the API help documentation, fix the problem that the page may be continuously cached",-1),Wo={id:"_1-0-78-2022-04-18",tabindex:"-1"},Do=e("a",{class:"header-anchor",href:"#_1-0-78-2022-04-18","aria-hidden":"true"},"#",-1),jo=o(" 1.0.78 | 2022.04.18 \u2002"),Bo=n("
  • YukiHookModulePrefs adds isRunInNewXShareMode method, which can be used to determine whether the module is currently in New XSharePreference mode
  • Fixed YukiHookModulePrefs working in New XSharePreference mode
  • Added ModulePreferenceFragment, now you can completely replace PreferenceFragmentCompat and start using the new functionality
  • ",3),No=o("Adapt the Sp data storage solution of "),Oo=e("code",null,"PreferenceFragmentCompat",-1),Uo=o(", thanks to "),qo={href:"https://github.com/mahoshojoHCG",target:"_blank",rel:"noopener noreferrer"},Eo=o("mahoshojoHCG"),Vo=o(" for feedback"),Ko=e("li",null,[o("Update autohandlers and "),e("code",null,"Kotlin"),o(" dependencies to the latest version")],-1),Zo=e("li",null,"Fixed some bugs in documentation and code comments",-1),Go={id:"_1-0-77-2022-04-15",tabindex:"-1"},Jo=e("a",{class:"header-anchor",href:"#_1-0-77-2022-04-15","aria-hidden":"true"},"#",-1),Qo=o(" 1.0.77 | 2022.04.15 \u2002"),$o=e("code",null,"YukiHookModulePrefs",-1),et=o(" added "),ot=e("code",null,"clear",-1),tt=o(" method, thanks to "),dt={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},it=o("WankkoRee"),nt=o(" for the suggestion"),ct=n("
  • YukiHookModulePrefs added getStringSet, putStringSet, all methods
  • Added any method to args of HookParam
  • Added ModuleApplication, which can be inherited in modules to achieve more functions
  • Connect all findClass functions to the Xposed API, and continue to use native ClassLoader in non-hosted environments
  • Fixed some possible bugs
  • ",5),st={id:"_1-0-75-2022-04-13",tabindex:"-1"},at=e("a",{class:"header-anchor",href:"#_1-0-75-2022-04-13","aria-hidden":"true"},"#",-1),lt=o(" 1.0.75 | 2022.04.13 \u2002"),rt=o("Corrected the logic recognition part of the automatic handler, thanks to "),ht={href:"https://github.com/ApeaSuperz",target:"_blank",rel:"noopener noreferrer"},ut=o("ApeaSuperz"),_t=o(" contribution"),mt=n("
  • Fixed an issue where the reference to a doc comment was not changed
  • firstArgs and lastArgs methods have been removed from HookParam, now you can use args().first() and args().last() instead of it
  • Removed default parameter index = 0 in args() in HookParam, now you can use args().first() or args(index = 0) to replace it
  • The result function in HookParam adds generic matching, now you can use result<T> to match the known return value type of your target method
  • The emptyParam 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 improved
  • Added android type in type
  • ",6),pt={id:"_1-0-73-2022-04-10",tabindex:"-1"},ft=e("a",{class:"header-anchor",href:"#_1-0-73-2022-04-10","aria-hidden":"true"},"#",-1),gt=o(" 1.0.73 | 2022.04.10 \u2002"),kt=o("Fixed some Chinese translation errors in documents, thanks to "),bt={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},yt=o("WankkoRee"),xt=o(" for their contributions"),vt=o("Fix the problem that "),wt=e("code",null,"XC_LoadPackage.LoadPackageParam",-1),At=o(" throws an exception when the content is empty in some cases, thanks to "),Ht={href:"https://github.com/luckyzyx",target:"_blank",rel:"noopener noreferrer"},Pt=o("Luckyzyx"),Ft=o(" for the feedback"),Ct=e("li",null,"Fix some known bugs and improve Hook stability",-1),Mt={id:"_1-0-72-2022-04-09",tabindex:"-1"},It=e("a",{class:"header-anchor",href:"#_1-0-72-2022-04-09","aria-hidden":"true"},"#",-1),Rt=o(" 1.0.72 | 2022.04.09 \u2002"),St=e("ul",null,[e("li",null,"Update API documentation to new address"),e("li",null,[o("Add "),e("code",null,"appContext"),o(" function to "),e("code",null,"PackageParam")]),e("li",null,"Fix some known bugs and improve Hook stability")],-1),Yt={id:"_1-0-71-2022-04-04",tabindex:"-1"},Xt=e("a",{class:"header-anchor",href:"#_1-0-71-2022-04-04","aria-hidden":"true"},"#",-1),Tt=o(" 1.0.71 | 2022.04.04 \u2002"),zt=e("ul",null,[e("li",null,"Fixed a serious issue that would stop the Hook from throwing an exception when VariousClass could not be matched")],-1),Lt={id:"_1-0-70-2022-04-04",tabindex:"-1"},Wt=e("a",{class:"header-anchor",href:"#_1-0-70-2022-04-04","aria-hidden":"true"},"#",-1),Dt=o(" 1.0.70 | 2022.04.04 \u2002"),jt=e("li",null,[o("Fixed "),e("code",null,"instanceClass"),o(" reporting an error after being called in a static instance")],-1),Bt=o("Add "),Nt=e("code",null,"isUseAppClassLoader",-1),Ot=o(" function in Hook process, thanks to "),Ut={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},qt=o("WankkoRee"),Et=o(" for feedback"),Vt=e("li",null,[o("Added the "),e("code",null,"withProcess"),o(" function, which can be hooked according to the currently specified process of the APP")],-1),Kt=e("li",null,"Fixed critical logic errors in lookup methods, constructor classes and variables",-1),Zt=e("li",null,"Fixed the problem that the abnormal output cannot be ignored when the Hook target class does not exist",-1),Gt=e("li",null,"Fixed the problem that the Hook could not take effect due to the fast loading of the APP startup method in some cases",-1),Jt=o("Fixed "),Qt=e("code",null,"allMethods",-1),$t=o(" not throwing an exception when it is not hooked to a method, thanks to "),ed={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},od=o("WankkoRee"),td=o(" for the feedback"),dd=o("Added Hook status monitoring function, thanks to "),id={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},nd=o("WankkoRee"),cd=o(" for the suggestion"),sd=e("li",null,"Modify the way the Xposed entry is injected into the class, and redefine the definition domain of the API",-1),ad=o("Added obfuscated method and variable lookup function, you can use different types of filter "),ld=e("code",null,"index",-1),rd=o(" to locate the specified method and variable, thanks to "),hd={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},ud=o("WankkoRee"),_d=o(" for the ideas provided"),md=e("li",null,[o("When looking for methods and variables, multiple types are allowed, such as the class name declared by "),e("code",null,"String"),o(" and "),e("code",null,"VariousClass")],-1),pd=e("li",null,[o("Add a new "),e("code",null,"current"),o(" function, which can build a reflection method operation space for any class, and easily call and modify the methods and variables in it")],-1),fd=o("Fixed a lot of bugs in the hook process, thanks to "),gd={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},kd=o("WankkoRee"),bd=o(" for contributing to this project"),yd={id:"_1-0-69-2022-03-30",tabindex:"-1"},xd=e("a",{class:"header-anchor",href:"#_1-0-69-2022-03-30","aria-hidden":"true"},"#",-1),vd=o(" 1.0.69 | 2022.03.30 \u2002"),wd=e("li",null,"Added and improved annotations for some method functions",-1),Ad=e("li",null,"Added more example Hook content in Demo",-1),Hd=o("Fixed the issue that only the last one takes effect when "),Pd=e("code",null,"allMethods",-1),Fd=o(" is used multiple times in a Hook instance, thanks to "),Cd={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},Md=o("WankkoRee"),Id=o(" for the feedback"),Rd={id:"_1-0-68-2022-03-29",tabindex:"-1"},Sd=e("a",{class:"header-anchor",href:"#_1-0-68-2022-03-29","aria-hidden":"true"},"#",-1),Yd=o(" 1.0.68 | 2022.03.29 \u2002"),Xd=n("
    • Added new use case and LSPosed scope in Demo
    • Added Member lookup cache and lookup cache configuration switches
    • Removed and modified MethodFinder, FieldFinder and HookParam related method calls
    • Add more cast types in Finder and support cast as array
    • Overall performance and stability improvements
    • Fix bugs that may exist in the previous version
    ",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("
    • Added three modifiers functions in Finder, which can filter static, native, public, abstract and many other description types
    • When searching for methods and constructors, the method parameter type can be blurred to a specified number for searching
    • Added hasModifiers extension for Member
    • Added give method in MethodFinder and ConstructorFinder to get primitive types
    • Added PrefsData template function in YukiHookModulePrefs
    • Completely refactored method, constructor and variable lookup scheme
    • Optimized code comments and fixed possible bugs
    ",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("
    • Republished version to fix the incorrect new version of the Maven repository due to cache issues
    • Added MethodFinder and FieldFinder new return value calling methods
    • Fix possible problems and fix possible problems during the use of Tai Chi
    • Fixed possible problems with auto-generated Xposed entry classes
    • Added android type and java type in type
    ",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("
    • Fixed YukiHookModulePrefs being ignored every time after using direct once to ignore cache
    • Added new API, abolished the traditional usage of isActive to judge module activation
    • Fixed the issue of printing debug logs when using the API in a non-Xposed environment
    • Fixed log output issue and unintercepted exception issue when looking for Field
    • Decoupling Xposed API in ReflectionUtils
    • Added YukiHookModuleStatus method name confusion to reduce the size of module generation
    • The welcome message will no longer be printed when loading the module's own Hook
    • Fix some bugs that still exist in the previous version
    ",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("
    • Fixed the problem that the welcome message was printed multiple times in the case of the old version of the LSPosed framework
    • Added onInit method to configure YukiHookAPI
    • Added executorName and executorVersion to get the name and version number of the current hook framework
    • Added by method to set the timing and condition of Hook
    • YukiHookModulePrefs adds a controllable key-value cache, which can dynamically update data when the host is running
    • Fixed some possible bugs
    ",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("
    • Fix LSPosed cannot find XposedBridge after enabling "Only module classloader can use Xposed API" option in latest version
    • Added constant version name and version number for YukiHookAPI
    • Added hasField method and isAllowPrintingLogs configuration parameter
    • Added isDebug to enable the API to automatically print the welcome message to test whether the module is valid
    ",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("
    • Fixed a potential exception not intercepted BUG
    • Added ignoredError function
    • Added android type in type
    • Added ClassNotFound function after listening to hook
    ",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("
  • \u7EDF\u4E00\u5E76\u89C4\u8303\u6587\u6863\u4E2D\u7684\u672F\u8BED\u540D\u8BCD\uFF0C\u4F8B\u5982\u201C\u67E5\u8BE2\u201D\u4E00\u5F8B\u66F4\u6539\u4E3A\u4E86\u201C\u67E5\u627E\u201D\uFF0CXposedHelper \u62FC\u5199\u9519\u8BEF\u4FEE\u6539\u4E3A\u4E86 XposedHelpers
  • \u6587\u6863 \u5165\u95E8 \u2192 \u57FA\u7840\u77E5\u8BC6 \u9875\u9762\u52A0\u5165\u53CB\u60C5\u94FE\u63A5\uFF0C\u4EC5\u9650\u7B80\u4F53\u4E2D\u6587
  • \u5C06 Hook App Demo \u7684 Class \u4E0E Method \u8F6C\u4E3A Java \u4EE5\u63D0\u4F9B\u66F4\u597D\u7684\u6F14\u793A\u6548\u679C
  • \u4FEE\u6B63\u4E86 Hook Module Demo \u4E2D\u7684\u4EE3\u7801\u6CE8\u91CA\u547D\u540D
  • \u91CD\u6784\u4E86\u5927\u91CF\u5E95\u5C42 Hook \u903B\u8F91\u53CA Xposed API \u7684\u5BF9\u63A5\u65B9\u5F0F
  • \u79FB\u9664\u4E86 HookParamWrapper\uFF0C\u73B0\u5DF2\u5C06\u5176\u76F4\u63A5\u4E0E YukiBridgeFactory \u5BF9\u63A5
  • \u79FB\u52A8\u90E8\u5206 YukiHookBridge \u4E2D\u7684\u65B9\u6CD5\u5230 AppParasitics
  • \u79FB\u9664\u4E86 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\u8C61
  • \u4F18\u5316\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\uFF0C\u5C06\u5F15\u7528\u7684 jar \u5408\u5E76\u5230 stub \u9879\u76EE
  • ",9),x=o("\u4FEE\u590D\u591A\u9879\u76EE\u6253\u5305\u65F6\u6A21\u5757\u5305\u540D\u65E0\u6CD5\u6B63\u786E\u5339\u914D\u7684\u95EE\u9898\u4EE5\u53CA\u4FEE\u6539\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u7684\u6A21\u5757\u5305\u540D\u5339\u914D\u903B\u8F91\uFF0C\u611F\u8C22 "),y={href:"https://github.com/5ec1cff",target:"_blank",rel:"noopener noreferrer"},A=o("5ec1cff"),C=o(" \u7684\u53CD\u9988\u53CA\u63D0\u4F9B\u7684\u89E3\u51B3\u65B9\u6848"),v=t("
  • \u5BF9 API \u79C1\u6709\u5DE5\u5177\u7C7B\u7684\u65B9\u6CD5\u8FDB\u884C\u4E86 internal \u95ED\u5305\u5904\u7406\uFF0C\u907F\u514D\u6C61\u67D3\u9876\u7EA7\u547D\u540D\u7A7A\u95F4
  • \u4FEE\u6B63\u4E86\u6240\u6709\u53CD\u5C04\u548C Hook \u7C7B\u7684 Creater \u547D\u540D\u5230 Creator
  • \u65B0\u589E 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\u6233
  • \u65B0\u589E YukiHookAPI.Status.isXposedEnvironment \u529F\u80FD\uFF0C\u53EF\u4EE5\u5224\u65AD\u5F53\u524D\u4E3A (Xposed) \u5BBF\u4E3B\u73AF\u5883\u8FD8\u662F\u6A21\u5757\u73AF\u5883
  • \u8C03\u8BD5\u65E5\u5FD7\u529F\u80FD\u8FDB\u884C\u4E86\u5927\u6539\u7248\uFF0C\u73B0\u5DF2\u5C06 YukiHookAPI.Configs.debugTag \u7B49\u529F\u80FD\u5408\u5E76\u5230 YukiHookLogger.Configs \u4E2D
  • \u8C03\u8BD5\u65E5\u5FD7\u65B0\u589E\u53EF\u6307\u5B9A\u6253\u5370\u4F7F\u7528\u7684\u65B9\u6CD5\u4E3A XposedBridge.log \u6216 Logd
  • \u8C03\u8BD5\u65E5\u5FD7\u4E2D\u9ED8\u8BA4\u52A0\u5165\u5F53\u524D\u5BBF\u4E3B\u7684\u5305\u540D\u4EE5\u53CA\u5F53\u524D\u7528\u6237 ID\uFF0C\u4EE5\u4F9B\u8C03\u8BD5\uFF0C\u4F60\u53EF\u4EE5\u5728 debugLog \u914D\u7F6E\u4E2D\u81EA\u884C\u66F4\u6539
  • \u65B0\u589E generic \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\u5B83
  • \u4F5C\u5E9F buildOfAny \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
  • \u4FEE\u590D hasExtends \u4F7F\u7528\u8FC7\u7A0B\u53D1\u751F\u7A7A\u6307\u9488\u5F02\u5E38\u7684\u95EE\u9898
  • CurrentClass \u65B0\u589E\u975E lambda \u65B9\u5F0F\u7684\u8C03\u7528\u65B9\u6CD5
  • CurrentClass \u65B0\u589E name \u4E0E simpleName \u529F\u80FD
  • \u5B8C\u5168\u91CD\u5199 ReflectionTool \u7684\u6838\u5FC3\u65B9\u6CD5\uFF0C\u5C06\u4E0D\u540C\u7684\u67E5\u627E\u6761\u4EF6\u8FDB\u884C\u4E86\u6574\u7406\u5206\u7C7B
  • \u4FEE\u590D ReflectionTool \u4E2D\u53EF\u80FD\u7684\u76F4\u63A5\u8C03\u7528 declared \u83B7\u53D6\u7684 Member \u629B\u51FA\u5F02\u5E38\u7684\u95EE\u9898
  • \u4FEE\u590D ReflectionTool \u4E2D UndefinedType \u672A\u5728 Method \u4E0E Constructor \u6761\u4EF6\u4E2D\u6B63\u786E\u5224\u65AD\u7684\u95EE\u9898
  • \u65B0\u589E\u53CD\u5C04\u67E5\u627E\u7ED3\u679C\u53D1\u751F\u5F02\u5E38\u65F6\u7684\u53CB\u597D\u63D0\u793A\u65B9\u5F0F\uFF0C\u53EF\u5177\u4F53\u5B9A\u4F4D\u5230\u6307\u5B9A\u6761\u4EF6\u627E\u4E0D\u5230 Member \u7684\u95EE\u9898
  • \u53CD\u5C04\u67E5\u627E Method\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\u6570
  • \u53CD\u5C04\u67E5\u627E Method\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\u4EF6
  • FieldFinder \u7ED3\u679C\u4E2D\u65B0\u589E current \u65B9\u6CD5\uFF0C\u53EF\u76F4\u63A5\u5BF9\u7ED3\u679C\u5B9E\u4F8B\u521B\u5EFA\u8C03\u7528\u7A7A\u95F4
  • \u4FEE\u6539\u4E86\u53CD\u5C04\u67E5\u627E\u529F\u80FD\u4E2D\u7684 modifiers \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\u7ACB
  • ",20),M=e("code",null,"ModifierRules",-1),I=o(" \u4E2D\u7684 "),R=e("code",null,"as*",-1),Y=o(" \u529F\u80FD\u6539\u540D\u4E3A "),S=e("code",null,"is*",-1),X=o("\uFF0C\u611F\u8C22 "),F={href:"https://github.com/KyuubiRan",target:"_blank",rel:"noopener noreferrer"},B=o("Kitsune"),L=o(" \u7684\u5EFA\u8BAE"),W=t("
  • FieldFinder \u4E2D\u65B0\u589E RemedyPlan \u529F\u80FD
  • \u65B0\u589E Dex \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
  • ",2),U=o("\u65B0\u589E\u53CD\u5C04\u67E5\u627E\u4E2D\u7684\u591A\u91CD\u67E5\u627E\u529F\u80FD\uFF0C\u53EF\u4F7F\u7528\u76F8\u5BF9\u67E5\u627E\u6761\u4EF6\u540C\u65F6\u83B7\u53D6\u591A\u4E2A\u67E5\u627E\u7ED3\u679C\uFF0C\u611F\u8C22 "),D=e("strong",null,"AA",-1),G=o(" \u4EE5\u53CA "),T={href:"https://github.com/KyuubiRan",target:"_blank",rel:"noopener noreferrer"},N=o("Kitsune"),E=o(" \u7684\u5EFA\u8BAE"),j=o("\u4FEE\u590D "),w=e("code",null,"appClassLoader",-1),z=o(" \u83B7\u53D6\u5230\u7684\u5BF9\u8C61\u5728\u67D0\u4E9B\u7CFB\u7EDF\u4E2D\u7684\u7CFB\u7EDF\u5E94\u7528\u4E2D\u4E0D\u6B63\u786E\u7684\u95EE\u9898\uFF0C\u611F\u8C22 "),V={href:"https://github.com/luckyzyx",target:"_blank",rel:"noopener noreferrer"},Z=o("Luckyzyx"),K=o(" \u7684\u53CD\u9988"),O=e("li",null,[o("\u4FEE\u6539\u4E86 "),e("code",null,"XposedBridge.invokeOriginalMethod"),o(" \u7684\u8C03\u7528\u65B9\u5F0F\u5E76\u5728 "),e("code",null,"MethodFinder.Result.Instance"),o(" \u4E2D\u589E\u52A0 "),e("code",null,"original"),o(" \u529F\u80FD")],-1),J=o("\u4FEE\u590D "),q=e("code",null,"YukiHookModulePrefs",-1),Q=o(" \u4E2D "),$=e("code",null,"getStringSet",-1),ee=o(" \u65B9\u6CD5\u53D6\u503C\u9519\u8BEF\u7684\u95EE\u9898\u5E76\u4F18\u5316\u4EE3\u7801\u98CE\u683C\uFF0C\u611F\u8C22 "),oe={href:"https://github.com/Teddy-Zhu",target:"_blank",rel:"noopener noreferrer"},de=o("Teddy_Zhu"),ce=o(" \u7684 "),ie={href:"https://github.com/fankes/YukiHookAPI/pull/19",target:"_blank",rel:"noopener noreferrer"},te=o("PR"),le=e("li",null,[o("\u4FEE\u6539 "),e("code",null,"YukiHookModulePrefs"),o("\uFF0C\u62E6\u622A "),e("code",null,"XSharePreference"),o(" \u53EF\u80FD\u4E0D\u5B58\u5728\u7684\u5F02\u5E38")],-1),se=e("li",null,[o("\u4FEE\u590D "),e("code",null,"YukiHookDataChannel"),o(" \u5728\u67D0\u4E9B\u7B2C\u4E09\u65B9 ROM \u7CFB\u7EDF\u6846\u67B6\u4E2D\u65E0\u6CD5\u6CE8\u518C\u6210\u529F\u7684\u95EE\u9898")],-1),ne=e("li",null,[o("\u5B89\u5168\u5316 "),e("code",null,"YukiHookDataChannel"),o("\uFF0C\u73B0\u5728\u5B83\u53EA\u80FD\u5728\u6765\u81EA\u6307\u5B9A\u5305\u540D\u7684\u6A21\u5757\u4E0E\u5BBF\u4E3B\u4E4B\u95F4\u901A\u4FE1")],-1),ae=o("\u65B0\u589E\u81EA\u52A8 Hook "),re=e("code",null,"SharedPreferences",-1),_e=o(" \u4EE5\u4FEE\u590D\u90E8\u5206\u7CFB\u7EDF\u4E2D\u6587\u4EF6\u6743\u9650\u4E0D\u662F "),he=e("code",null,"0664",-1),ue=o(" \u7684\u95EE\u9898\uFF0C\u611F\u8C22 "),ke={href:"https://github.com/5ec1cff",target:"_blank",rel:"noopener noreferrer"},pe=o("5ec1cff"),ge=o(" \u7684\u53CD\u9988\u53CA\u63D0\u4F9B\u7684\u5B9E\u73B0\u4EE3\u7801"),fe=t("
  • \u65B0\u589E YukiHookAPI.Configs.isEnableHookSharedPreferences \u529F\u80FD\uFF0C\u9ED8\u8BA4\u5173\u95ED\uFF0C\u82E5 SharedPreferences \u7684\u6743\u9650\u9519\u8BEF\u53EF\u8FDB\u884C\u542F\u7528
  • \u4FEE\u590D\u67E5\u627E Constructor \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\u9988
  • \u5206\u79BB\u4F4D\u4E8E injectMember \u4E2D method\u3001constructor \u7684 Result \u5B9E\u4F8B\u5230 Process
  • \u5728 Hook \u8FC7\u7A0B\u4E2D\u65B0\u589E 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\u8BEF
  • \u65B0\u589E\u6A21\u5757\u8D44\u6E90\u6CE8\u5165\u4E0E Activity \u4EE3\u7406\u529F\u80FD\uFF0C\u4F60\u53EF\u4EE5\u8C03\u7528 injectModuleAppResources \u53CA registerModuleAppActivities \u6765\u4F7F\u7528
  • \u65B0\u589E ModuleContextThemeWrapper \u529F\u80FD\uFF0C\u4F60\u53EF\u4EE5\u8C03\u7528 applyModuleTheme \u5728\u4EFB\u610F Activity \u4E2D\u521B\u5EFA\u6A21\u5757\u7684 Context
  • \u65B0\u589E ClassLoader.onLoadClass \u529F\u80FD\uFF0C\u53EF\u7528\u4E8E\u76D1\u542C ClassLoader \u7684 loadClass \u65B9\u6CD5\u88AB\u8C03\u7528\u7684\u4E8B\u4EF6
  • \u4F5C\u5E9F\u4E86 classOf \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\u6CD5
  • VariousClass \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
  • \u4E0D\u518D\u5BF9\u5916\u5F00\u653E HookClass \u4E2D\u7684\u4EFB\u4F55\u65B9\u6CD5
  • HookParam \u4E2D\u65B0\u589E throwToApp \u529F\u80FD\uFF0C\u53EF\u5C06\u5F02\u5E38\u76F4\u63A5\u629B\u7ED9\u5BBF\u4E3B
  • Hook \u56DE\u8C03\u4E2D\u65B0\u589E onFailureThrowToApp \u529F\u80FD\uFF0C\u53EF\u5728\u53D1\u751F\u5F02\u5E38\u65F6\u76F4\u63A5\u629B\u7ED9\u5BBF\u4E3B
  • \u4FEE\u6539\u4E86\u8C03\u8BD5\u65E5\u5FD7\u7684\u6253\u5370\u903B\u8F91\uFF0C\u53CD\u5C04\u67E5\u627E\u529F\u80FD\u4E2D\u7684\u8017\u65F6\u8BB0\u5F55\u4EC5\u4F1A\u5728 Hook \u8FC7\u7A0B\u4E2D\u8FDB\u884C\u6253\u5370
  • Hook \u8FC7\u7A0B\u4E2D\u65B0\u589E\u89E3\u9664 Hook \u529F\u80FD\uFF0C\u53EF\u4F7F\u7528 remove \u53CA removeSelf \u65B9\u6CD5\u89E3\u9664 Hook
  • \u4FEE\u590D\u5728 ReplaceHook \u5931\u8D25\u7684\u65F6\u5019\u5BFC\u81F4\u5BBF\u4E3B\u629B\u51FA\u5F02\u5E38\u7684\u95EE\u9898\uFF0C\u73B0\u4FEE\u6539\u4E3A\u8C03\u7528\u539F\u59CB\u65B9\u6CD5\u4FDD\u8BC1\u5BBF\u4E3B\u529F\u80FD\u6B63\u5E38\u8FD0\u884C
  • \u65B0\u589E Hook \u8FC7\u7A0B\u4E2D\u5BF9\u65B9\u6CD5\u8FD4\u56DE\u503C\u7684\u68C0\u67E5\u529F\u80FD\uFF0C\u5728\u8FD4\u56DE\u503C\u4E0D\u5339\u914D\u7684\u60C5\u51B5\u4E0B\u4F1A\u6839\u636E\u60C5\u666F\u81EA\u52A8\u629B\u51FA\u5F02\u5E38\u6216\u6253\u5370\u9519\u8BEF
  • ",18),me=o("Resources Hook \u4E2D\u65B0\u589E "),He=e("code",null,"array",-1),Pe=o(" \u7C7B\u578B\uFF0C\u611F\u8C22 "),be={href:"https://github.com/GSWXXN",target:"_blank",rel:"noopener noreferrer"},xe=o("GSWXXN"),ye=o(" \u7684 "),Ae={href:"https://github.com/fankes/YukiHookAPI/pull/12",target:"_blank",rel:"noopener noreferrer"},Ce=o("PR"),ve=e("li",null,[o("\u79FB\u52A8 "),e("code",null,"me.weishu.reflection"),o(" \u5230 "),e("code",null,"thirdparty"),o(" \u9632\u6B62\u540C\u65F6\u5F15\u5165\u7684\u540C\u540D\u4F9D\u8D56\u51B2\u7A81")],-1),Me=e("li",null,"\u79FB\u9664 Hook \u65B9\u6CD5\u4F53\u4E3A\u7A7A\u65F6\u629B\u51FA\u7684\u5F02\u5E38\uFF0C\u4FEE\u6539\u4E3A\u6253\u5370\u8B66\u544A\u65E5\u5FD7",-1),Ie=e("li",null,[o("\u4FEE\u6539 "),e("code",null,"AppLifecycle"),o(" \u7684\u5F02\u5E38\u5904\u7406\u903B\u8F91\uFF0C\u5F53\u5176\u53D1\u751F\u5F02\u5E38\u65F6\u76F4\u63A5\u629B\u7ED9\u5BBF\u4E3B")],-1),Re=e("li",null,"\u66F4\u65B0 Demo \u7684 API \u7248\u672C\u5230 33",-1),Ye={id:"_1-0-92-2022-05-31",tabindex:"-1"},Se=e("a",{class:"header-anchor",href:"#_1-0-92-2022-05-31","aria-hidden":"true"},"#",-1),Xe=o(" 1.0.92 | 2022.05.31 \u2002"),Fe=t("
    • \u4FEE\u6B63\u4E86\u5927\u91CF\u65B9\u6CD5\u4E2D callback \u7684\u547D\u540D\u65B9\u6CD5
    • \u66F4\u6362\u65B9\u6848\u518D\u6B21\u4FEE\u590D YukiHookDataChannel \u5728\u4F4E\u4E8E Android 12 \u7684\u8BBE\u5907\u4E0A\u4E0D\u80FD\u56DE\u8C03\u5F53\u524D Activity \u5E7F\u64AD\u7684\u95EE\u9898
    • InjectYukiHookWithXposed \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\u4E86
    ",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("
  • \u4FEE\u590D YukiHookDataChannel \u5728 ZUI \u4EE5\u53CA\u4F4E\u4E8E Android 12 \u7684\u7CFB\u7EDF\u4E0A\u4E0D\u80FD\u56DE\u8C03\u5F53\u524D Activity \u5E7F\u64AD\u7684\u95EE\u9898
  • \u6574\u5408 YukiHookModuleStatus \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
  • ",2),we={id:"_1-0-90-2022-05-27",tabindex:"-1"},ze=e("a",{class:"header-anchor",href:"#_1-0-90-2022-05-27","aria-hidden":"true"},"#",-1),Ve=o(" 1.0.90 | 2022.05.27 \u2002"),Ze=t("
    • \u4FEE\u590D YukiHookDataChannel \u5728\u6A21\u5757\u8BBE\u7F6E\u76D1\u542C\u56DE\u8C03\u65F6\u95EA\u9000\u7684\u95EE\u9898
    • \u4FEE\u590D YukiHookDataChannel \u5728\u975E\u5F53\u524D Activity \u60C5\u51B5\u4E0B\u4F9D\u7136\u4F1A\u56DE\u8C03\u7684\u95EE\u9898
    • \u79FB\u9664 YukiHookDataChannel \u56DE\u8C03\u4E8B\u4EF6\u7684\u9ED8\u8BA4\u503C\uFF0C\u6CA1\u6709\u5373\u4E0D\u56DE\u8C03
    • \u79FB\u9664 YukiHookModulePrefs \u5728 XShare \u4E0D\u53EF\u8BFB\u7684\u60C5\u51B5\u4E0B\u6253\u5370\u7684\u8B66\u544A
    • \u65B0\u589E YukiHookModulePrefs \u4E2D\u7684 isXSharePrefsReadable \u65B9\u6CD5\uFF0C\u53EF\u5224\u65AD\u5F53\u524D\u7684 XShare \u662F\u5426\u53EF\u7528
    ",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("
    • \u4FEE\u590D 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\u80FD
    • \u65B0\u589E YukiHookDataChannel \u91CD\u590D\u76D1\u542C\u7528\u4F8B\u8BF4\u660E\u6587\u6863
    • \u52A0\u5165 onAlreadyHooked \u65B9\u6CD5\uFF0C\u53EF\u5224\u65AD\u5F53\u524D\u65B9\u6CD5\u662F\u5426\u88AB\u91CD\u590D Hook
    • \u4FEE\u6539\u90E8\u5206\u91CD\u590D\u6DFB\u52A0 HashMap \u7684\u903B\u8F91\uFF0C\u79FB\u9664 putIfAbsent \u65B9\u6CD5\uFF0C\u5141\u8BB8\u8986\u76D6\u6DFB\u52A0
    • \u4FEE\u590D\u4E86\u51E0\u5904\u53EF\u80FD\u7684 BUG
    ",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("
    • \u5BF9 Xposed API \u5B8C\u5168\u89E3\u8026\u5408
    • \u589E\u52A0\u4E86 type \u4E2D\u7684 android \u7C7B\u578B
    • \u5C06 YukiHookModuleStatus \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\u7528
    • \u5BF9 API \u5927\u91CF\u7C7B\u7684\u6784\u9020\u65B9\u6CD5\u8FDB\u884C\u4E86 internal \u95ED\u5305\u5904\u7406
    • \u5C06 YukiHookModulePrefs \u8BBE\u7F6E\u4E3A\u5355\u4F8B\u8FD0\u884C\uFF0C\u9632\u6B62\u91CD\u590D\u521B\u5EFA\u6D6A\u8D39\u7CFB\u7EDF\u8D44\u6E90
    • \u4FEE\u590D\u81EA 1.0.80 \u7248\u672C\u540E\u65E0\u6CD5\u5D4C\u5957 Hook \u7684 BUG\uFF0C\u5E76\u4F18\u5316\u5D4C\u5957 Hook \u76F8\u5173\u529F\u80FD
    • \u4FEE\u6539 Hooker \u5B58\u50A8\u65B9\u6848\u7531 HashSet \u5230 HashMap\uFF0C\u9632\u6B62\u91CD\u590D\u6DFB\u52A0 Hooker \u7684\u95EE\u9898
    • \u4FEE\u6539 Hook \u6838\u5FC3\u5B9E\u73B0\u65B9\u6CD5\uFF0C\u52A0\u5165\u67E5\u91CD\uFF0C\u907F\u514D\u91CD\u590D Hook \u591A\u6B21\u56DE\u8C03 HookParam \u65B9\u6CD5
    • MethodFinder \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\u5219
    • \u4F18\u5316\u5E76\u4FEE\u6539 appContext \u7684\u83B7\u53D6\u65B9\u5F0F\uFF0C\u964D\u4F4E\u4F1A\u53D6\u5230\u7A7A\u7684\u95EE\u9898\u7684\u53EF\u80FD\u6027
    • \u4FEE\u6539\u81EA\u52A8\u751F\u6210\u7684\u4EE3\u7801\u4E2D logger \u7684\u6253\u5370 TAG \u9ED8\u8BA4\u4E3A\u4F60\u81EA\u5B9A\u4E49\u7684\u540D\u79F0\uFF0C\u65B9\u4FBF\u8FDB\u884C\u8C03\u8BD5
    • \u4F18\u5316 YukiHookBridge \u7684 Hooker \u5B9E\u73B0\u65B9\u5F0F\uFF0C\u63D0\u5347 Hook \u6027\u80FD
    • PackageParam \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\u80FD
    • \u65B0\u589E YukiHookDataChannel \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\u8BAF
    • YukiHookDataChannel \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\u9898
    • demo-module \u7684\u793A\u4F8B\u4EE3\u7801\u4E2D\u65B0\u589E Java \u7248\u672C\u7684\u793A\u4F8B\uFF0C\u4EC5\u4F9B\u53C2\u8003
    ",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("
    • \u4FEE\u590D\u65E0\u6CD5 Hook \u7CFB\u7EDF\u6846\u67B6\u7684\u4E25\u91CD\u95EE\u9898\uFF0C\u4ECE 1.0.80 \u5F00\u59CB\u51FA\u73B0
    • \u8C03\u8BD5\u65E5\u5FD7\u4E2D\u65B0\u589E\u533A\u5206 initZygote \u88C5\u8F7D\u7684\u5305\u540D\u4E3A android-zygote\uFF0CpackageName \u4FDD\u6301 android \u4E0D\u53D8
    ",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("
  • InjectYukiHookWithXposed \u6CE8\u89E3\u65B0\u589E entryClassName \u529F\u80FD\uFF0C\u53EF\u81EA\u5B9A\u4E49\u751F\u6210\u7684 xposed_init \u5165\u53E3\u7C7B\u540D
  • YukiHookXposedInitProxy \u66F4\u540D\u4E3A IYukiHookXposedInit\uFF0C\u539F\u63A5\u53E3\u540D\u79F0\u5DF2\u4F5C\u5E9F\uFF0C\u5C06\u5728\u540E\u7EED\u7248\u672C\u4E2D\u76F4\u63A5\u88AB\u5220\u9664
  • \u65B0\u589E initZygote \u4E0E Resources Hook \u529F\u80FD\uFF0C\u652F\u6301 Hook Layout
  • \u65B0\u589E onXposedEvent \u65B9\u6CD5\uFF0C\u53EF\u76D1\u542C\u539F\u751F Xposed API \u7684\u5168\u90E8\u4E8B\u4EF6
  • \u5BF9 Hook \u529F\u80FD\u7684 lambda \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\u80FD
  • \u4FEE\u590D PrefsData \u7F16\u8BD1\u540E\u7684\u65B9\u6CD5\u4F53\u590D\u5236\u8FC7\u5927\u7684\u95EE\u9898
  • \u589E\u52A0 XSharePreference \u53EF\u8BFB\u6027\u6D4B\u8BD5\uFF0C\u5931\u8D25\u540E\u4F1A\u81EA\u52A8\u6253\u5370\u8B66\u544A\u65E5\u5FD7
  • PackageParam \u65B0\u589E appResources\u3001moduleAppResources\u3001moduleAppFilePath \u529F\u80FD
  • PackageParam \u7684 loadApp \u65B0\u589E\u4E0D\u5199 name \u529F\u80FD\uFF0C\u9ED8\u8BA4\u7B5B\u9009\u5168\u90E8 APP
  • PackageParam \u65B0\u589E loadZygote \u65B9\u6CD5\uFF0C\u53EF\u76F4\u63A5 Hook \u7CFB\u7EDF\u6846\u67B6
  • PackageParam \u65B0\u589E resources().hook \u529F\u80FD
  • \u4F18\u5316\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u3001\u53D8\u91CF\u67E5\u627E\u529F\u80FD\uFF0C\u627E\u4E0D\u5230\u7684\u9519\u8BEF\u65E5\u5FD7\u5C06\u4F18\u5148\u663E\u793A\u5DF2\u8BBE\u7F6E\u7684\u67E5\u627E\u6761\u4EF6
  • \u589E\u52A0 hasExtends \u6269\u5C55\u65B9\u6CD5\uFF0C\u53EF\u5224\u65AD\u5F53\u524D Class \u662F\u5426\u6709\u7EE7\u627F\u5173\u7CFB
  • \u589E\u52A0 isSupportResourcesHook \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\u7C7B
  • \u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u3001\u53D8\u91CF\u65B0\u589E superClass \u67E5\u627E\u6761\u4EF6\uFF0C\u53EF\u7EE7\u7EED\u5728\u7236\u7C7B\u4E2D\u67E5\u627E
  • YukiHookAPI \u5927\u91CF\u65B9\u6CD5\u4E0E Xposed API \u89E3\u8026\u5408
  • \u65B0\u589E Xposed API \u7684\u539F\u751F Hook \u4F18\u5148\u7EA7\u529F\u80FD
  • \u4FEE\u590D isFirstApplication \u53EF\u80FD\u5224\u65AD\u4E0D\u51C6\u786E\u7684\u95EE\u9898
  • \u5C4F\u853D MIUI \u7CFB\u7EDF\u4E0A MiuiCatcherPatch \u91CD\u590D\u8C03\u7528 Hook \u5165\u53E3\u65B9\u6CD5\u7684\u95EE\u9898
  • \u4F18\u5316 Hook \u5165\u53E3\u8C03\u7528\u65B9\u6CD5\uFF0C\u907F\u514D\u56E0\u4E3A Hook Framework \u95EE\u9898\u5BFC\u81F4\u591A\u6B21\u8C03\u7528
  • ",21),So=o("\u4FEE\u590D Hook "),Xo=e("code",null,"ClassLoader",-1),Fo=o(" \u5BFC\u81F4 Hook \u5361\u6B7B\u7684\u95EE\u9898\uFF0C\u611F\u8C22 "),Bo={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},Lo=o("WankkoRee"),Wo=o(" \u7684\u53CD\u9988"),Uo=e("li",null,[o("\u63D0\u5347 "),e("code",null,"XC_Callback"),o(" \u63A5\u53E3\u5BF9\u63A5\u540E\u7684\u6027\u80FD")],-1),Do=e("li",null,[o("Java "),e("code",null,"type"),o(" \u65B0\u589E "),e("code",null,"ClassLoader"),o(" \u7C7B\u578B")],-1),Go=e("li",null,"\u4F18\u5316 API \u5E2E\u52A9\u6587\u6863\uFF0C\u4FEE\u590D\u53EF\u80FD\u6301\u7EED\u7F13\u5B58\u9875\u9762\u7684\u95EE\u9898",-1),To={id:"_1-0-78-2022-04-18",tabindex:"-1"},No=e("a",{class:"header-anchor",href:"#_1-0-78-2022-04-18","aria-hidden":"true"},"#",-1),Eo=o(" 1.0.78 | 2022.04.18 \u2002"),jo=t("
  • YukiHookModulePrefs \u65B0\u589E isRunInNewXShareMode \u65B9\u6CD5\uFF0C\u53EF\u7528\u4E8E\u5224\u65AD\u6A21\u5757\u5F53\u524D\u662F\u5426\u5904\u4E8E New XSharePreference \u6A21\u5F0F
  • \u4FEE\u590D YukiHookModulePrefs \u5728 New XSharePreference \u6A21\u5F0F\u4E0B\u5DE5\u4F5C\u7684\u90E8\u5206\u95EE\u9898
  • \u65B0\u589E ModulePreferenceFragment\uFF0C\u73B0\u5728\uFF0C\u4F60\u53EF\u4EE5\u5B8C\u5168\u66FF\u6362\u6389 PreferenceFragmentCompat \u5E76\u5F00\u59CB\u4F7F\u7528\u65B0\u7684\u529F\u80FD
  • ",3),wo=o("\u9002\u914D "),zo=e("code",null,"PreferenceFragmentCompat",-1),Vo=o(" \u7684 Sp \u6570\u636E\u5B58\u50A8\u89E3\u51B3\u65B9\u6848\uFF0C\u611F\u8C22 "),Zo={href:"https://github.com/mahoshojoHCG",target:"_blank",rel:"noopener noreferrer"},Ko=o("mahoshojoHCG"),Oo=o(" \u7684\u53CD\u9988"),Jo=e("li",null,[o("\u66F4\u65B0\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u4EE5\u53CA "),e("code",null,"Kotlin"),o(" \u4F9D\u8D56\u5230\u6700\u65B0\u7248\u672C")],-1),qo=e("li",null,"\u4FEE\u6B63\u90E8\u5206\u6587\u6863\u548C\u4EE3\u7801\u6CE8\u91CA\u4E2D\u7684\u9519\u8BEF",-1),Qo={id:"_1-0-77-2022-04-15",tabindex:"-1"},$o=e("a",{class:"header-anchor",href:"#_1-0-77-2022-04-15","aria-hidden":"true"},"#",-1),ed=o(" 1.0.77 | 2022.04.15 \u2002"),od=e("code",null,"YukiHookModulePrefs",-1),dd=o(" \u65B0\u589E "),cd=e("code",null,"clear",-1),id=o(" \u65B9\u6CD5\uFF0C\u611F\u8C22 "),td={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},ld=o("WankkoRee"),sd=o(" \u7684\u5EFA\u8BAE"),nd=t("
  • YukiHookModulePrefs \u65B0\u589E getStringSet\u3001putStringSet\u3001all \u65B9\u6CD5
  • HookParam \u7684 args \u589E\u52A0 any \u65B9\u6CD5
  • \u65B0\u589E ModuleApplication\uFF0C\u53EF\u5728\u6A21\u5757\u4E2D\u7EE7\u627F\u6B64\u7C7B\u5B9E\u73B0\u66F4\u591A\u529F\u80FD
  • \u5BF9\u63A5\u5168\u90E8\u7684 findClass \u529F\u80FD\u5230 Xposed API\uFF0C\u5728\u975E\u5BBF\u4E3B\u73AF\u5883\u7EE7\u7EED\u4F7F\u7528\u539F\u751F ClassLoader
  • \u4FEE\u590D\u4E86\u4E00\u4E9B\u53EF\u80FD\u5B58\u5728\u7684 BUG
  • ",5),ad={id:"_1-0-75-2022-04-13",tabindex:"-1"},rd=e("a",{class:"header-anchor",href:"#_1-0-75-2022-04-13","aria-hidden":"true"},"#",-1),_d=o(" 1.0.75 | 2022.04.13 \u2002"),hd=o("\u66F4\u6B63\u4E86\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u7684\u903B\u8F91\u8BC6\u522B\u90E8\u5206\uFF0C\u611F\u8C22 "),ud={href:"https://github.com/ApeaSuperz",target:"_blank",rel:"noopener noreferrer"},kd=o("ApeaSuperz"),pd=o(" \u7684\u8D21\u732E"),gd=t("
  • \u4FEE\u6B63\u4E00\u5904\u6587\u6863\u6CE8\u91CA\u7684\u5F15\u7528\u672A\u66F4\u6539\u7684\u95EE\u9898
  • 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\u5B83
  • HookParam \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\u5B83
  • HookParam \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\u4E86
  • \u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u67E5\u627E\u529F\u80FD\u65B0\u589E emptyParam \u6761\u4EF6\uFF0C\u5E76\u5B8C\u5584\u4E86\u6587\u6863\u76F8\u5173\u9700\u8981\u6CE8\u610F\u7684\u67E5\u627E\u6761\u4EF6\u8BEF\u533A
  • \u589E\u52A0\u4E86 type \u4E2D\u7684 android \u7C7B\u578B
  • ",6),fd=e("h3",{id:"_1-0-73-2022-04-10",tabindex:"-1"},[e("a",{class:"header-anchor",href:"#_1-0-73-2022-04-10","aria-hidden":"true"},"#"),o(" 1.0.73 | 2022.04.10")],-1),md=o("\u4FEE\u6B63\u51E0\u5904\u6587\u6863\u7684\u4E2D\u6587\u7FFB\u8BD1\u9519\u8BEF\uFF0C\u611F\u8C22 "),Hd={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},Pd=o("WankkoRee"),bd=o(" \u7684\u8D21\u732E"),xd=o("\u4FEE\u590D\u5728\u67D0\u4E9B\u60C5\u51B5\u4E0B "),yd=e("code",null,"XC_LoadPackage.LoadPackageParam",-1),Ad=o(" \u5185\u5BB9\u4E3A\u7A7A\u629B\u51FA\u5F02\u5E38\u7684\u95EE\u9898\uFF0C\u611F\u8C22 "),Cd={href:"https://github.com/luckyzyx",target:"_blank",rel:"noopener noreferrer"},vd=o("Luckyzyx"),Md=o(" \u7684\u53CD\u9988"),Id=e("li",null,"\u4FEE\u590D\u4E00\u4E9B\u5DF2\u77E5\u7684 BUG\uFF0C\u63D0\u5347 Hook \u7A33\u5B9A\u6027",-1),Rd={id:"_1-0-72-2022-04-09",tabindex:"-1"},Yd=e("a",{class:"header-anchor",href:"#_1-0-72-2022-04-09","aria-hidden":"true"},"#",-1),Sd=o(" 1.0.72 | 2022.04.09 \u2002"),Xd=e("ul",null,[e("li",null,"\u66F4\u65B0 API \u6587\u6863\u5230\u65B0\u7684\u5730\u5740"),e("li",null,[e("code",null,"PackageParam"),o(" \u4E2D\u52A0\u5165 "),e("code",null,"appContext"),o(" \u529F\u80FD")]),e("li",null,"\u4FEE\u590D\u4E00\u4E9B\u5DF2\u77E5\u7684 BUG\uFF0C\u63D0\u5347 Hook \u7A33\u5B9A\u6027")],-1),Fd={id:"_1-0-71-2022-04-04",tabindex:"-1"},Bd=e("a",{class:"header-anchor",href:"#_1-0-71-2022-04-04","aria-hidden":"true"},"#",-1),Ld=o(" 1.0.71 | 2022.04.04 \u2002"),Wd=e("ul",null,[e("li",null,"\u4FEE\u590D VariousClass \u65E0\u6CD5\u5339\u914D\u65F6\u4F1A\u505C\u6B62 Hook \u629B\u51FA\u5F02\u5E38\u7684\u4E25\u91CD\u95EE\u9898")],-1),Ud={id:"_1-0-70-2022-04-04",tabindex:"-1"},Dd=e("a",{class:"header-anchor",href:"#_1-0-70-2022-04-04","aria-hidden":"true"},"#",-1),Gd=o(" 1.0.70 | 2022.04.04 \u2002"),Td=e("li",null,[o("\u4FEE\u590D "),e("code",null,"instanceClass"),o(" \u5728\u9759\u6001\u5B9E\u4F8B\u4E2D\u8C03\u7528\u540E\u62A5\u9519\u95EE\u9898")],-1),Nd=o("\u5728 Hook \u8FC7\u7A0B\u4E2D\u52A0\u5165 "),Ed=e("code",null,"isUseAppClassLoader",-1),jd=o(" \u529F\u80FD\uFF0C\u611F\u8C22 "),wd={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},zd=o("WankkoRee"),Vd=o(" \u7684\u53CD\u9988"),Zd=e("li",null,[o("\u52A0\u5165 "),e("code",null,"withProcess"),o(" \u529F\u80FD\uFF0C\u53EF\u6839\u636E APP \u5F53\u524D\u6307\u5B9A\u8FDB\u7A0B\u8FDB\u884C Hook")],-1),Kd=e("li",null,"\u4FEE\u590D\u67E5\u627E\u65B9\u6CD5\u3001\u6784\u9020\u7C7B\u548C\u53D8\u91CF\u7684\u4E25\u91CD\u903B\u8F91\u9519\u8BEF\u95EE\u9898",-1),Od=e("li",null,"\u4FEE\u590D Hook \u76EE\u6807\u7C7B\u4E0D\u5B58\u5728\u7684\u65F6\u5019\u65E0\u6CD5\u5FFD\u7565\u5F02\u5E38\u8F93\u51FA\u7684\u95EE\u9898",-1),Jd=e("li",null,"\u4FEE\u590D\u90E8\u5206\u60C5\u51B5\u4E0B APP \u542F\u52A8\u65B9\u6CD5\u88C5\u8F7D\u8FC7\u5FEB\u5BFC\u81F4 Hook \u4E0D\u80FD\u751F\u6548\u7684\u95EE\u9898",-1),qd=o("\u4FEE\u590D "),Qd=e("code",null,"allMethods",-1),$d=o(" \u672A Hook \u5230\u65B9\u6CD5\u65F6\u4E0D\u4F1A\u629B\u51FA\u5F02\u5E38\u7684\u95EE\u9898\uFF0C\u611F\u8C22 "),ec={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},oc=o("WankkoRee"),dc=o(" \u7684\u53CD\u9988"),cc=o("\u52A0\u5165 Hook \u72B6\u6001\u76D1\u542C\u529F\u80FD\uFF0C\u611F\u8C22 "),ic={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},tc=o("WankkoRee"),lc=o(" \u7684\u5EFA\u8BAE"),sc=e("li",null,"\u4FEE\u6539 Xposed \u5165\u53E3\u6CE8\u5165\u7C7B\u7684\u65B9\u5F0F\uFF0C\u91CD\u65B0\u58F0\u660E API \u7684\u5B9A\u4E49\u57DF",-1),nc=o("\u52A0\u5165\u6DF7\u6DC6\u7684\u65B9\u6CD5\u4EE5\u53CA\u53D8\u91CF\u7684\u67E5\u627E\u529F\u80FD\uFF0C\u53EF\u4F7F\u7528\u4E0D\u540C\u7C7B\u578B\u7B5B\u9009 "),ac=e("code",null,"index",-1),rc=o(" \u5B9A\u4F4D\u6307\u5B9A\u7684\u65B9\u6CD5\u548C\u53D8\u91CF\uFF0C\u611F\u8C22 "),_c={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},hc=o("WankkoRee"),uc=o(" \u63D0\u4F9B\u7684\u601D\u8DEF"),kc=e("li",null,[o("\u67E5\u627E\u65B9\u6CD5\u3001\u53D8\u91CF\u65F6\u5141\u8BB8\u4F20\u5165\u591A\u79CD\u7C7B\u578B\uFF0C\u4F8B\u5982 "),e("code",null,"String"),o(" \u58F0\u660E\u7684\u7C7B\u540D\u548C "),e("code",null,"VariousClass")],-1),pc=e("li",null,[o("\u52A0\u5165\u5168\u65B0\u7684 "),e("code",null,"current"),o(" \u529F\u80FD\uFF0C\u53EF\u5BF9\u4EFB\u610F\u7684\u7C7B\u6784\u5EFA\u4E00\u4E2A\u53CD\u5C04\u65B9\u6CD5\u64CD\u4F5C\u7A7A\u95F4\uFF0C\u65B9\u4FBF\u5730\u8C03\u7528\u548C\u4FEE\u6539\u5176\u4E2D\u7684\u65B9\u6CD5\u548C\u53D8\u91CF")],-1),gc=o("\u4FEE\u590D\u4E86 Hook \u8FC7\u7A0B\u4E2D\u7684\u5927\u91CF BUG\uFF0C\u611F\u8C22 "),fc={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},mc=o("WankkoRee"),Hc=o(" \u5BF9\u6B64\u9879\u76EE\u6240\u505A\u51FA\u7684\u8D21\u732E"),Pc={id:"_1-0-69-2022-03-30",tabindex:"-1"},bc=e("a",{class:"header-anchor",href:"#_1-0-69-2022-03-30","aria-hidden":"true"},"#",-1),xc=o(" 1.0.69 | 2022.03.30 \u2002"),yc=e("li",null,"\u6DFB\u52A0\u5E76\u6539\u8FDB\u4E00\u4E9B\u65B9\u6CD5\u529F\u80FD\u7684\u6CE8\u91CA",-1),Ac=e("li",null,"\u589E\u52A0 Demo \u4E2D\u7684\u66F4\u591A\u793A\u4F8B Hook \u5185\u5BB9",-1),Cc=o("\u4FEE\u590D\u5728\u4E00\u4E2A Hook \u5B9E\u4F8B\u4E2D\uFF0C"),vc=e("code",null,"allMethods",-1),Mc=o(" \u591A\u6B21\u4F7F\u7528\u65F6\u53EA\u6709\u6700\u540E\u4E00\u4E2A\u751F\u6548\u7684\u95EE\u9898\uFF0C\u611F\u8C22 "),Ic={href:"https://github.com/WankkoRee",target:"_blank",rel:"noopener noreferrer"},Rc=o("WankkoRee"),Yc=o(" \u7684\u53CD\u9988"),Sc={id:"_1-0-68-2022-03-29",tabindex:"-1"},Xc=e("a",{class:"header-anchor",href:"#_1-0-68-2022-03-29","aria-hidden":"true"},"#",-1),Fc=o(" 1.0.68 | 2022.03.29 \u2002"),Bc=t("
    • \u589E\u52A0 Demo \u4E2D\u7684\u65B0\u7528\u4F8B\u548C LSPosed \u4F5C\u7528\u57DF
    • \u589E\u52A0 Member \u67E5\u627E\u7F13\u5B58\u548C\u67E5\u627E\u7F13\u5B58\u914D\u7F6E\u5F00\u5173
    • \u79FB\u9664\u548C\u4FEE\u6539 MethodFinder\u3001FieldFinder \u4EE5\u53CA HookParam \u76F8\u5173\u65B9\u6CD5\u7684\u8C03\u7528
    • \u589E\u52A0\u66F4\u591A Finder \u4E2D\u7684 cast \u7C7B\u578B\u5E76\u652F\u6301 cast \u4E3A\u6570\u7EC4
    • \u6574\u4F53\u7684\u6027\u80FD\u548C\u7A33\u5B9A\u6027\u63D0\u5347
    • \u4FEE\u590D\u4E0A\u4E00\u4E2A\u7248\u672C\u53EF\u80FD\u5B58\u5728\u7684 BUG
    ",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("
    • \u589E\u52A0\u4E09\u4E2A Finder \u4E2D\u7684 modifiers \u529F\u80FD\uFF0C\u53EF\u7B5B\u9009 static\u3001native\u3001public\u3001abstract \u7B49\u8BF8\u591A\u63CF\u8FF0\u7C7B\u578B
    • \u589E\u52A0\u65B9\u6CD5\u548C\u6784\u9020\u65B9\u6CD5\u67E5\u627E\u65F6\u53EF\u6A21\u7CCA\u65B9\u6CD5\u53C2\u6570\u7C7B\u578B\u4E3A\u6307\u5B9A\u4E2A\u6570\u8FDB\u884C\u67E5\u627E
    • \u589E\u52A0 Member \u7684 hasModifiers \u6269\u5C55\u529F\u80FD
    • \u589E\u52A0 MethodFinder \u548C ConstructorFinder \u4E2D\u7684 give \u65B9\u6CD5\uFF0C\u53EF\u83B7\u5F97\u539F\u59CB\u7C7B\u578B
    • \u589E\u52A0 YukiHookModulePrefs \u4E2D\u7684 PrefsData \u6A21\u677F\u529F\u80FD
    • \u5F7B\u5E95\u5BF9\u65B9\u6CD5\u3001\u6784\u9020\u65B9\u6CD5\u53CA\u53D8\u91CF\u7684\u67E5\u627E\u65B9\u6848\u8FDB\u884C\u91CD\u6784
    • \u4F18\u5316\u4EE3\u7801\u6CE8\u91CA\uFF0C\u4FEE\u590D\u4E86\u53EF\u80FD\u4EA7\u751F\u7684 BUG
    ",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("
    • \u91CD\u65B0\u53D1\u5E03\u7248\u672C\u4FEE\u590D Maven \u4ED3\u5E93\u56E0\u4E3A\u7F13\u5B58\u95EE\u9898\u65B0\u7248\u672C\u4E0D\u6B63\u786E\u7684\u60C5\u51B5
    • \u589E\u52A0 MethodFinder \u4E0E FieldFinder \u65B0\u7684\u8FD4\u56DE\u503C\u8C03\u7528\u65B9\u6CD5
    • \u4FEE\u590D\u53EF\u80FD\u5B58\u5728\u7684\u95EE\u9898\uFF0C\u5E76\u4FEE\u590D\u592A\u6781\u4F7F\u7528\u8FC7\u7A0B\u4E2D\u53EF\u80FD\u5B58\u5728\u7684\u95EE\u9898
    • \u4FEE\u590D\u81EA\u52A8\u751F\u6210 Xposed \u5165\u53E3\u7C7B\u53EF\u80FD\u53D1\u751F\u7684\u95EE\u9898
    • \u589E\u52A0\u4E86 type \u4E2D\u7684 android \u7C7B\u578B\u4EE5\u53CA java \u7C7B\u578B
    ",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("
    • \u4FEE\u590D YukiHookModulePrefs \u5728\u4F7F\u7528\u4E00\u6B21 direct \u5FFD\u7565\u7F13\u5B58\u540E\u6BCF\u6B21\u90FD\u5FFD\u7565\u7684 BUG
    • \u589E\u52A0\u65B0\u7684 API\uFF0C\u4F5C\u5E9F\u4E86 isActive \u5224\u65AD\u6A21\u5757\u6FC0\u6D3B\u7684\u4F20\u7EDF\u7528\u6CD5
    • \u4FEE\u590D\u975E Xposed \u73AF\u5883\u4F7F\u7528 API \u65F6\u6253\u5370\u8C03\u8BD5\u65E5\u5FD7\u7684\u95EE\u9898
    • \u4FEE\u590D\u67E5\u627E Field \u65F6\u7684\u65E5\u5FD7\u8F93\u51FA\u95EE\u9898\u548C\u672A\u62E6\u622A\u7684\u5F02\u5E38\u95EE\u9898
    • \u89E3\u8026\u5408 ReflectionUtils \u4E2D\u7684 Xposed API
    • \u589E\u52A0 YukiHookModuleStatus \u65B9\u6CD5\u540D\u79F0\u7684\u6DF7\u6DC6\uFF0C\u4EE5\u7CBE\u7B80\u6A21\u5757\u751F\u6210\u7684\u4F53\u79EF
    • \u88C5\u8F7D\u6A21\u5757\u81EA\u8EAB Hook \u65F6\u5C06\u4E0D\u518D\u6253\u5370\u6B22\u8FCE\u4FE1\u606F
    • \u4FEE\u590D\u4E0A\u4E00\u4E2A\u7248\u672C\u4ECD\u7136\u5B58\u5728\u7684\u67D0\u4E9B BUG
    ",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("
    • \u4FEE\u590D\u65E7\u7248\u672C LSPosed \u6846\u67B6\u60C5\u51B5\u4E0B\u6B22\u8FCE\u4FE1\u606F\u591A\u6B21\u6253\u5370\u7684\u95EE\u9898
    • \u6DFB\u52A0 onInit \u65B9\u6CD5\u6765\u914D\u7F6E YukiHookAPI
    • \u65B0\u589E executorName \u548C executorVersion \u6765\u83B7\u53D6\u5F53\u524D Hook \u6846\u67B6\u7684\u540D\u79F0\u548C\u7248\u672C\u53F7
    • \u65B0\u589E by \u65B9\u6CD5\u6765\u8BBE\u7F6E Hook \u7684\u65F6\u673A\u548C\u6761\u4EF6
    • YukiHookModulePrefs \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
    • \u4FEE\u590D\u4E86\u4E00\u4E9B\u53EF\u80FD\u5B58\u5728\u7684 BUG
    ",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("
    • \u4FEE\u590D LSPosed \u5728\u6700\u65B0\u7248\u672C\u4E2D\u542F\u7528\u201C\u53EA\u6709\u6A21\u5757classloader\u53EF\u4EE5\u4F7F\u7528Xposed API\u201D\u9009\u9879\u540E\u627E\u4E0D\u5230 XposedBridge \u7684\u95EE\u9898
    • \u6DFB\u52A0 YukiHookAPI \u7684\u5E38\u91CF\u7248\u672C\u540D\u79F0\u548C\u7248\u672C\u53F7
    • \u65B0\u589E hasField \u65B9\u6CD5\u4EE5\u53CA isAllowPrintingLogs \u914D\u7F6E\u53C2\u6570
    • \u65B0\u589E isDebug \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),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("
    • \u4FEE\u590D\u4E00\u4E2A\u6F5C\u5728\u6027\u7684\u5F02\u5E38\u672A\u62E6\u622A BUG
    • \u589E\u52A0 ignoredError \u529F\u80FD
    • \u589E\u52A0\u4E86 type \u4E2D\u7684 android \u7C7B\u578B
    • \u589E\u52A0\u76D1\u542C hook \u540E\u7684 ClassNotFound \u529F\u80FD
    ",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("
    • RemedyPlan \u589E\u52A0 onFind \u529F\u80FD
    • \u6574\u5408\u5E76\u4FEE\u6539\u4E86\u90E8\u5206\u53CD\u5C04 API \u4EE3\u7801
    • \u589E\u52A0\u4E86 type \u4E2D\u7684 java \u7C7B\u578B
    • \u4FEE\u590D\u5FFD\u7565\u9519\u8BEF\u5728\u63A7\u5236\u53F0\u4ECD\u7136\u8F93\u51FA\u7684\u95EE\u9898
    ",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(`

    \u7528\u6CD5\u793A\u4F8B

    \u8FD9\u91CC\u4ECB\u7ECD\u4E86 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

    \u4E0B\u65B9\u7684\u7ED3\u6784\u63CF\u8FF0\u4E86 YukiHookAPI \u7684\u57FA\u672C\u5DE5\u4F5C\u65B9\u5F0F\u548C\u539F\u7406\u3002

    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
    +            ...
    +

    \u4E0A\u65B9\u7684\u7ED3\u6784\u6362\u505A\u4EE3\u7801\u5C06\u53EF\u5199\u4E3A\u5982\u4E0B\u5F62\u5F0F\u3002

    TargetClass.hook { 
    +    injectMember { 
    +        method { 
    +            // Your code here.
    +        }
    +        beforeHook {
    +            // Your code here.
    +        }
    +        afterHook {
    +            // Your code here.
    +        }
    +    }
    +}
    +resources().hook {
    +    injectResource {
    +        conditions {
    +            // Your code here.
    +        }
    +        replaceTo(...)
    +    }
    +}
    +

    Demo

    \u4F60\u53EF\u4EE5\u5728\u4E0B\u65B9\u627E\u5230 API \u63D0\u4F9B\u7684 Demo \u6765\u5B66\u4E60 YukiHookAPI \u7684\u4F7F\u7528\u65B9\u6CD5\u3002

    `,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(`

    \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

    \u4E00\u4E2A\u7B80\u5355\u7684 Hook \u4F8B\u5B50

    \u8FD9\u91CC\u7ED9\u51FA\u4E86 Hook APP\u3001Hook \u7CFB\u7EDF\u6846\u67B6\u4E0E Hook Resources \u7B49\u4F8B\u5B50\uFF0C\u53EF\u4F9B\u53C2\u8003\u3002

    Hook APP

    \u5047\u8BBE\uFF0C\u6211\u4EEC\u8981 Hook com.android.browser \u4E2D\u7684 onCreate \u65B9\u6CD5\u5E76\u5F39\u51FA\u4E00\u4E2A\u5BF9\u8BDD\u6846\u3002

    \u5728 encase \u65B9\u6CD5\u4F53\u4E2D\u6DFB\u52A0\u4EE3\u7801\u3002

    \u793A\u4F8B\u5982\u4E0B

    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()
    +            }
    +        }
    +    }
    +}
    +

    \u81F3\u6B64\uFF0ConCreate \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\u3002

    \u90A3\u4E48\uFF0C\u6211\u60F3\u7EE7\u7EED Hook onStart \u65B9\u6CD5\u8981\u600E\u4E48\u505A\u5462\uFF1F

    \u5728\u521A\u521A\u7684\u4EE3\u7801\u4E2D\uFF0C\u7EE7\u7EED\u63D2\u5165\u4E00\u4E2A injectMember \u65B9\u6CD5\u4F53\u5373\u53EF\u3002

    \u793A\u4F8B\u5982\u4E0B

    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.
    +            }
    +        }
    +    }
    +}
    +

    \u5BF9\u4E8E\u5F53\u524D\u9879\u76EE\u4E0B\u6CA1\u6709\u7684 Class\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 stub \u65B9\u5F0F\u6216 findClass \u65B9\u6CD5\u6765\u5F97\u5230\u9700\u8981 Hook \u7684\u7C7B\u3002

    \u6BD4\u5982\uFF0C\u6211\u8981\u5F97\u5230 com.example.demo.TestClass\u3002

    \u793A\u4F8B\u5982\u4E0B

    findClass(name = "com.example.demo.TestClass").hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    \u82E5 com.example.demo \u662F\u4F60\u8981 Hook \u7684 APP\uFF0C\u90A3\u4E48\u5199\u6CD5\u53EF\u4EE5\u66F4\u7B80\u5355\u3002

    \u793A\u4F8B\u5982\u4E0B

    findClass(name = "$packageName.TestClass").hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    \u5230\u8FD9\u91CC\u6709\u4E9B\u540C\u5B66\u53EF\u80FD\u5C31\u5F00\u59CB\u8BF4\u4E86\uFF0C\u5728\u67D0\u4E9B\u573A\u666F\u4E0B findClass \u663E\u5F97\u6709\u4E9B\u7E41\u7410\u3002

    \u56E0\u4E3A\u53EF\u80FD\u6709\u4E9B\u540C\u5B66\u6709\u5982\u4E0B\u9700\u6C42\u3002

    \u793A\u4F8B\u5982\u4E0B

    const val TestClass = "com.example.demo.TestClass"
    +
    +TestClass.hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    \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

    "$packageName.TestClass".hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MemberHookCreator\u3002

    Hook Zygote

    \u5728 APP \u542F\u52A8\u65F6\uFF0C\u65B0\u7684\u8FDB\u7A0B\u88AB fork \u540E\u7684\u7B2C\u4E00\u4E2A\u4E8B\u4EF6 initZygote\u3002

    \u5047\u8BBE\u6211\u4EEC\u8981\u5168\u5C40 Hook \u4E00\u4E2A APP Activity \u7684 onCreate \u4E8B\u4EF6

    \u5728 encase \u65B9\u6CD5\u4F53\u4E2D\u6DFB\u52A0\u4EE3\u7801\u3002

    \u793A\u4F8B\u5982\u4E0B

    loadZygote {
    +    ActivityClass.hook { 
    +        injectMember { 
    +            method { 
    +                name = "onCreate"
    +                param(BundleClass)
    +                returnType = UnitType
    +            }
    +            afterHook {
    +                // Your code here.
    +            }
    +        }
    +    }
    +}
    +

    \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

    Hook \u7CFB\u7EDF\u6846\u67B6

    \u5728 YukiHookAPI \u4E2D\uFF0CHook \u7CFB\u7EDF\u6846\u67B6\u7684\u5B9E\u73B0\u975E\u5E38\u7B80\u5355\u3002

    \u5047\u8BBE\uFF0C\u4F60\u8981\u5F97\u5230 ApplicationInfo \u4E0E PackageInfo \u5E76\u5BF9\u5B83\u4EEC\u8FDB\u884C\u4E00\u4E9B\u64CD\u4F5C\u3002

    \u5728 encase \u65B9\u6CD5\u4F53\u4E2D\u6DFB\u52A0\u4EE3\u7801\u3002

    \u793A\u4F8B\u5982\u4E0B

    loadSystem {
    +    ApplicationInfoClass.hook {
    +        // Your code here.
    +    }
    +    PackageInfoClass.hook {
    +        // Your code here.
    +    }
    +}
    +

    \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

    Hook Resources

    \u5047\u8BBE\uFF0C\u6211\u4EEC\u8981 Hook com.android.browser \u4E2D string \u7C7B\u578B\u7684 app_name \u5185\u5BB9\u66FF\u6362\u4E3A 123\u3002

    \u5728 encase \u65B9\u6CD5\u4F53\u4E2D\u6DFB\u52A0\u4EE3\u7801\u3002

    \u793A\u4F8B\u5982\u4E0B

    loadApp(name = "com.android.browser") {
    +    resources().hook {
    +        injectResource {
    +            conditions {
    +                name = "app_name"
    +                string()
    +            }
    +            replaceTo("123")
    +        }
    +    }
    +}
    +

    \u82E5\u5F53\u524D APP \u4F7F\u7528 app_name \u8BBE\u7F6E\u4E86\u6807\u9898\u680F\u6587\u672C\uFF0C\u5219\u5B83\u5C31\u4F1A\u53D8\u6210\u6211\u4EEC\u7684 123\u3002

    \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 com.android.browser \u4E2D mipmap \u7C7B\u578B\u7684 ic_launcher\u3002

    \u793A\u4F8B\u5982\u4E0B

    loadApp(name = "com.android.browser") {
    +    resources().hook {
    +        injectResource {
    +            conditions {
    +                name = "ic_launcher"
    +                mipmap()
    +            }
    +            replaceToModuleResource(R.mipmap.ic_launcher)
    +        }
    +    }
    +}
    +

    \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 loadApp \u6362\u6210 loadZygote \u5373\u53EF\u3002

    \u793A\u4F8B\u5982\u4E0B

    loadZygote {
    +    resources().hook {
    +        // Your code here.
    +    }
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ResourcesHookCreator\u3002

    \u89E3\u9664 Hook

    \u539F\u751F\u7684 Xposed \u4E3A\u6211\u4EEC\u63D0\u4F9B\u4E86\u4E00\u4E2A 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\u3002

    \u7B2C\u4E00\u79CD\u65B9\u6CD5\uFF0C\u4FDD\u5B58\u5F53\u524D\u6CE8\u5165\u5BF9\u8C61\u7684 Result \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

    \u793A\u4F8B\u5982\u4E0B

    // \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()
    +

    \u7B2C\u4E8C\u79CD\u65B9\u6CD5\uFF0C\u5728 Hook \u56DE\u8C03\u65B9\u6CD5\u4E2D\u8C03\u7528 removeSelf \u79FB\u9664\u81EA\u8EAB\u3002

    \u793A\u4F8B\u5982\u4E0B

    injectMember { 
    +    method { 
    +        name = "test"
    +        returnType = UnitType
    +    }
    +    afterHook {
    +        // \u76F4\u63A5\u8C03\u7528\u5982\u4E0B\u65B9\u6CD5\u5373\u53EF
    +        removeSelf()
    +    }
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MemberHookCreator\u3002

    \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

    \u4F60\u53EF\u4EE5\u5904\u7406 Hook \u65B9\u6CD5\u8FC7\u7A0B\u53D1\u751F\u7684\u5F02\u5E38\u3002

    \u793A\u4F8B\u5982\u4E0B

    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 {}
    +    // ...
    +}
    +

    \u5728 Resources Hook \u65F6\u6B64\u65B9\u6CD5\u540C\u6837\u9002\u7528\u3002

    \u793A\u4F8B\u5982\u4E0B

    injectResource {
    +    // Your code here.
    +}.result {
    +    // \u5904\u7406 Hook \u65F6\u7684\u4EFB\u610F\u5F02\u5E38
    +    onHookingFailure {}
    +    // ...
    +}
    +

    \u4F60\u8FD8\u53EF\u4EE5\u5904\u7406 Hook \u7684 Class \u4E0D\u5B58\u5728\u65F6\u53D1\u751F\u7684\u5F02\u5E38\u3002

    \u793A\u4F8B\u5982\u4E0B

    TargetClass.hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}.onHookClassNotFoundFailure {
    +    // Your code here.
    +}
    +

    \u4F60\u8FD8\u53EF\u4EE5\u5904\u7406\u67E5\u627E\u65B9\u6CD5\u65F6\u7684\u5F02\u5E38\u3002

    \u793A\u4F8B\u5982\u4E0B

    method {
    +    // Your code here.
    +}.onNoSuchMethod {
    +    // Your code here.
    +}
    +

    \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

    \u629B\u51FA\u5F02\u5E38

    \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 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\u3002

    \u4EE5\u4E0B\u662F YukiHookAPI \u63A5\u7BA1\u65F6\u8FD9\u4E9B\u5F02\u5E38\u7684\u8FD0\u4F5C\u65B9\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    // <\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 -> }
    +}
    +

    \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 param.throwable \u65B9\u6CD5\uFF0CYukiHookAPI \u540C\u6837\u53EF\u4EE5\u5B9E\u73B0\u6B64\u529F\u80FD\u3002

    \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

    injectMember {
    +    method {
    +        // ...
    +    }
    +    afterHook {
    +        RuntimeException("Exception Test").throwToApp()
    +    }
    +}
    +

    \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

    injectMember {
    +    method {
    +        // ...
    +    }
    +    afterHook {
    +        throw RuntimeException("Exception Test")
    +    }.onFailureThrowToApp()
    +}
    +

    \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

    \u72B6\u6001\u76D1\u542C

    \u5728\u4F7F\u7528 XposedHelpers \u7684\u540C\u5B66\u5F80\u5F80\u4F1A\u5728 Hook \u540E\u6253\u5370 Unhook \u7684\u65B9\u6CD5\u786E\u5B9A\u662F\u5426 Hook \u6210\u529F\u3002

    \u5728 YukiHookAPI \u4E2D\uFF0C\u4F60\u53EF\u4EE5\u7528\u4EE5\u4E0B\u65B9\u6CD5\u65B9\u4FBF\u5730\u91CD\u65B0\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002

    \u9996\u5148\u6211\u4EEC\u53EF\u4EE5\u76D1\u542C Hook \u5DF2\u7ECF\u51C6\u5907\u5F00\u59CB\u3002

    \u793A\u4F8B\u5982\u4E0B

    YourClass.hook {
    +    // Your code here.
    +}.onPrepareHook {
    +    loggerD(msg = "$instanceClass hook start")
    +}
    +

    \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

    injectMember {
    +    // Your code here.
    +}.onHooked { member ->
    +    loggerD(msg = "$member has hooked")
    +}
    +

    \u6269\u5C55\u7528\u6CD5

    \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

    \u591A\u4E2A\u5BBF\u4E3B

    \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 loadApp \u65B9\u6CD5\u4F53\u6765\u533A\u5206\u4F60\u8981 Hook \u7684 APP\u3002

    \u793A\u4F8B\u5982\u4E0B

    loadApp(name = "com.android.browser") {
    +    // Your code here.
    +}
    +loadApp(name = "com.android.phone") {
    +    // Your code here.
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 PackageParam.loadApp\u3002

    \u591A\u4E2A\u8FDB\u7A0B

    \u5982\u679C\u4F60 Hook \u7684\u5BBF\u4E3B APP \u6709\u591A\u4E2A\u8FDB\u7A0B\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 withProcess \u65B9\u6CD5\u4F53\u6765\u5BF9\u5B83\u4EEC\u5206\u522B\u8FDB\u884C Hook\u3002

    \u793A\u4F8B\u5982\u4E0B

    withProcess(mainProcessName) {
    +    // Your code here.
    +}
    +withProcess(name = "$packageName:tool") {
    +    // Your code here.
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 PackageParam.withProcess\u3002

    \u5199\u6CD5\u4F18\u5316

    \u4E3A\u4E86\u4F7F\u4EE3\u7801\u66F4\u52A0\u7B80\u6D01\uFF0C\u4F60\u53EF\u4EE5\u5220\u53BB YukiHookAPI \u7684\u540D\u79F0\uFF0C\u5C06\u4F60\u7684 onHook \u5165\u53E3\u5199\u4F5C lambda \u5F62\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    override fun onHook() = encase {
    +    // Your code here.
    +}
    +

    Xposed \u6A21\u5757\u5224\u65AD\u81EA\u8EAB\u6FC0\u6D3B\u72B6\u6001

    \u901A\u5E38\u60C5\u51B5\u4E0B\uFF0C\u6211\u4EEC\u4F1A\u9009\u62E9\u5199\u4E00\u4E2A\u65B9\u6CD5\uFF0C\u4F7F\u5176\u8FD4\u56DE false\uFF0C\u7136\u540E Hook \u6389\u8FD9\u4E2A\u65B9\u6CD5\u4F7F\u5176\u8FD4\u56DE true \u6765\u8BC1\u660E Hook \u5DF2\u7ECF\u751F\u6548\u3002

    \u5728 YukiHookAPI \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\u3002

    \u73B0\u5728\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 YukiHookAPI.Status.isXposedModuleActive \u5728\u6A21\u5757\u4E2D\u5224\u65AD\u81EA\u8EAB\u662F\u5426\u88AB\u6FC0\u6D3B\u3002

    \u793A\u4F8B\u5982\u4E0B

    if(YukiHookAPI.Status.isXposedModuleActive) {
    +    // Your code here.
    +}
    +

    \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 YukiHookAPI.Status.isTaiChiModuleActive \u5224\u65AD\u81EA\u8EAB\u662F\u5426\u88AB\u6FC0\u6D3B\u3002

    \u793A\u4F8B\u5982\u4E0B

    if(YukiHookAPI.Status.isTaiChiModuleActive) {
    +    // Your code here.
    +}
    +

    \u82E5\u4F60\u60F3\u4F7F\u7528\u4E24\u8005\u5F97\u517C\u7684\u5224\u65AD\u65B9\u6848\uFF0CYukiHookAPI \u540C\u6837\u4E3A\u4F60\u5C01\u88C5\u4E86\u4FBF\u6377\u7684\u65B9\u5F0F\u3002

    \u6B64\u65F6\u4F60\u53EF\u4EE5\u4F7F\u7528 YukiHookAPI.Status.isModuleActive \u5224\u65AD\u81EA\u8EAB\u662F\u5426\u5728 Xposed \u6216\u592A\u6781\u3001\u65E0\u6781\u4E2D\u88AB\u6FC0\u6D3B\u3002

    \u793A\u4F8B\u5982\u4E0B

    if(YukiHookAPI.Status.isModuleActive) {
    +    // Your code here.
    +}
    +

    \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

    `,142);function k(D,C){const a=p("ExternalLinkIcon");return c(),i("div",null,[t,s("ul",null,[s("li",null,[s("p",null,[d,s("a",u,[A,e(a)])])]),s("li",null,[s("p",null,[v,s("a",y,[m,e(a)])])])]),b])}const h=o(r,[["render",k],["__file","example.html.vue"]]);export{h as default}; diff --git a/docs/assets/example.html.e66bd85b.js b/docs/assets/example.html.e66bd85b.js new file mode 100644 index 00000000..aaf886e2 --- /dev/null +++ b/docs/assets/example.html.e66bd85b.js @@ -0,0 +1,286 @@ +import{_ as o,r as p,o as i,c,b as s,d as a,a as l,e as n}from"./app.fb8271cf.js";const t={},r=l(`

    Usage Example

    Here is an introduction to the basic working method of YukiHookAPI and a list of simple Hook examples and common functions.

    Structure Diagram

    The structure below describes the basic working and principle of 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
    +            ...
    +

    The above structure can be written in the following form in code.

    TargetClass.hook {
    +    injectMember {
    +        method {
    +            // Your code here.
    +        }
    +        beforeHook {
    +            // Your code here.
    +        }
    +        afterHook {
    +            // Your code here.
    +        }
    +    }
    +}
    +resources().hook {
    +    injectResource {
    +        conditions {
    +            // Your code here.
    +        }
    +        replaceTo(...)
    +    }
    +}
    +

    Demo

    You can find the demo provided by the API below to learn how to use YukiHookAPI.

    `,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(`

    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.

    A Simple Hook Example

    Here are examples of Hook App, Hook System Framework and Hook Resources for reference.

    Hook App

    Suppose, we want to hook the onCreate method in com.android.browser and show a dialog.

    Add code in the body of the encase method.

    The following example

    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()
    +            }
    +        }
    +    }
    +}
    +

    At this point, the onCreate method will be successfully hooked and this dialog will show when every Activity in com.android.browser starts.

    So, what should I do if I want to continue the Hook onStart method?

    In the code just now, continue to insert an injectMember method body.

    The following example

    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.
    +            }
    +        }
    +    }
    +}
    +

    For the 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.

    For example, I want to get com.example.demo.TestClass.

    The following example

    findClass(name = "com.example.demo.TestClass").hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    If com.example.demo is the app you want to hook, then the writing method can be simpler.

    The following example

    findClass(name = "$packageName.TestClass").hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    Some people may have started to say that findClass is a bit cumbersome in some scenarios.

    Because some people may have the following needs.

    The following example

    const val TestClass = "com.example.demo.TestClass"
    +
    +TestClass.hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    That's okay, you can also create a Hook directly using the string class name.

    The following example

    "$packageName.TestClass".hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    Tips

    For more functions, please refer to MemberHookCreator.

    Hook Zygote

    The first event initZygote after the new process is forked when the app starts.

    Suppose we want to globally Hook the onCreate event of an app Activity

    Add code in the body of the encase method.

    The following example

    loadZygote {
    +    ActivityClass.hook {
    +        injectMember {
    +            method {
    +                name = "onCreate"
    +                param(BundleClass)
    +                returnType = UnitType
    +            }
    +            afterHook {
    +                // Your code here.
    +            }
    +        }
    +    }
    +}
    +

    Notice

    The functionality performed in loadZygote is very limited, and the loadZygote method is rarely needed.

    Hook System Framework

    In YukiHookAPI, the implementation of the Hook System Framework is very simple.

    Suppose, you want to get ApplicationInfo and PackageInfo and do something with them.

    Add code in the body of the encase method.

    The following example

    loadSystem {
    +    ApplicationInfoClass.hook {
    +        // Your code here.
    +    }
    +    PackageInfoClass.hook {
    +        // Your code here.
    +    }
    +}
    +

    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.

    Hook Resources

    Suppose, we want to replace the content of app_name of type string in Hook com.android.browser with 123.

    Add code in the body of the encase method.

    The following example

    loadApp(name = "com.android.browser") {
    +    resources().hook {
    +        injectResource {
    +            conditions {
    +                name = "app_name"
    +                string()
    +            }
    +            replaceTo("123")
    +        }
    +    }
    +}
    +

    If the current app has a title bar text set with app_name, it will become our 123.

    You can also replace the Hook App's Resources with the current Xposed Module's Resources.

    Suppose, we want to continue to hook ic_launcher of type mipmap in com.android.browser.

    The following example

    loadApp(name = "com.android.browser") {
    +    resources().hook {
    +        injectResource {
    +            conditions {
    +                name = "ic_launcher"
    +                mipmap()
    +            }
    +            replaceToModuleResource(R.mipmap.ic_launcher)
    +        }
    +    }
    +}
    +

    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 loadApp with loadZygote.

    The following example

    loadZygote {
    +    resources().hook {
    +        // Your code here.
    +    }
    +}
    +

    Tips

    For more functions, please refer to ResourcesHookCreator.

    Remove Hook

    The native Xposed provides us with a XC_MethodHook.Unhook function, which can remove the current Hook from the Hook queue, and YukiHookAPI can also implement this function.

    The first way, save the Result instance of the current injected object, and call remove at the appropriate time and place to remove the injected object.

    The following example

    // 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()
    +

    The second method, call removeSelf in the Hook callback method to remove itself.

    The following example

    injectMember {
    +    method {
    +        name = "test"
    +        returnType = UnitType
    +    }
    +    afterHook {
    +        // Just call the following method directly
    +        removeSelf()
    +    }
    +}
    +

    Tips

    For more functions, please refer to MemberHookCreator.

    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

    You can handle exceptions that occur during the Hook method.

    The following example

    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 {}
    +    // ...
    +}
    +

    This method also works in the Resources Hook.

    The following example

    injectResource {
    +    // Your code here.
    +}.result {
    +    // Handle arbitrary exceptions when hooking
    +    onHookingFailure {}
    +    // ...
    +}
    +

    You can also handle exceptions that occur when the Hook's Class does not exist.

    The following example

    TargetClass.hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}.onHookClassNotFoundFailure {
    +    // Your code here.
    +}
    +

    You can also handle exceptions when looking up methods.

    The following example

    method {
    +    // Your code here.
    +}.onNoSuchMethod {
    +    // Your code here.
    +}
    +

    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.

    Throw an Exception

    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 hook method body will be taken over by the YukiHookAPI to avoid interrupting the next Hook process and causing the Hook process to "die".

    Here's how these exceptions work when YukiHookAPI takes over.

    The following example

    // <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 -> }
    +}
    +

    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 param.throwable method, and YukiHookAPI can also implement this function.

    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

    injectMember {
    +    method {
    +        // ...
    +    }
    +    afterHook {
    +        RuntimeException("Exception Test").throwToApp()
    +    }
    +}
    +

    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

    injectMember {
    +    method {
    +        // ...
    +    }
    +    afterHook {
    +        throw RuntimeException("Exception Test")
    +    }.onFailureThrowToApp()
    +}
    +

    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.

    Status Monitor

    People who use XposedHelpers often print Unhook after the Hook to determine whether the Hook is successful.

    In YukiHookAPI, you can easily reimplement this functionality with the following methods.

    First we can monitor that the Hook is ready to start.

    The following example

    YourClass.hook {
    +    // Your code here.
    +}.onPrepareHook {
    +    loggerD(msg = "$instanceClass hook start")
    +}
    +

    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

    injectMember {
    +    // Your code here.
    +}.onHooked { member ->
    +    loggerD(msg = "$member has hooked")
    +}
    +

    Expansion Usage

    You can use the following methods to easily implement various judgments and functions in the Hook process.

    Multiple Hosts

    If your Module App needs to handle Hook events of multiple apps at the same time, you can use the loadApp method body to distinguish the app you want to hook.

    The following example

    loadApp(name = "com.android.browser") {
    +    // Your code here.
    +}
    +loadApp(name = "com.android.phone") {
    +    // Your code here.
    +}
    +

    Tips

    For more functions, please refer to PackageParam.loadApp.

    Multiple Processes

    If your Hook's Host App has multiple processes, you can use the withProcess method body to hook them separately.

    The following example

    withProcess(mainProcessName) {
    +    // Your code here.
    +}
    +withProcess(name = "$packageName:tool") {
    +    // Your code here.
    +}
    +

    Tips

    For more functions, please refer to PackageParam.withProcess.

    Writing Optimization

    To make the code more concise, you can omit the name of YukiHookAPI and write your onHook entry as lambda.

    The following example

    override fun onHook() = encase {
    +    // Your code here.
    +}
    +

    Xposed Module own Active State

    Usually, we choose to write a method that return false, and then Hook this method to return true to prove that the Hook has taken effect.

    In YukiHookAPI, you don't need to do this at all. YukiHookAPI has already encapsulated this operation for you, and you can use it directly.

    Now, you can use YukiHookAPI.Status.isXposedModuleActive directly in the Module App to determine whether it is active.

    The following example

    if(YukiHookAPI.Status.isXposedModuleActive) {
    +    // Your code here.
    +}
    +

    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 YukiHookAPI.Status.isTaiChiModuleActive to determine whether it is activated.

    The following example

    if(YukiHookAPI.Status.isTaiChiModuleActive) {
    +    // Your code here.
    +}
    +

    If you want to use both judgment schemes, YukiHookAPI also encapsulates a convenient way for you.

    At this point, you can use YukiHookAPI.Status.isModuleActive to determine whether you are activated in Xposed or TaiChi and Promise.

    The following example

    if(YukiHookAPI.Status.isModuleActive) {
    +    // Your code here.
    +}
    +

    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.

    `,142);function b(k,D){const e=p("ExternalLinkIcon");return i(),c("div",null,[r,s("ul",null,[s("li",null,[s("p",null,[d,s("a",u,[A,a(e)])])]),s("li",null,[s("p",null,[m,s("a",v,[y,a(e)])])])]),h])}const B=o(t,[["render",b],["__file","example.html.vue"]]);export{B as default}; diff --git a/docs/assets/future.html.2cf8d6de.js b/docs/assets/future.html.2cf8d6de.js new file mode 100644 index 00000000..4fee92bb --- /dev/null +++ b/docs/assets/future.html.2cf8d6de.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-3106ca14","path":"/zh-cn/about/future.html","title":"\u5C55\u671B\u672A\u6765","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u672A\u89E3\u51B3\u7684\u95EE\u9898","slug":"\u672A\u89E3\u51B3\u7684\u95EE\u9898","link":"#\u672A\u89E3\u51B3\u7684\u95EE\u9898","children":[{"level":3,"title":"YukiHookModulePrefs","slug":"yukihookmoduleprefs","link":"#yukihookmoduleprefs","children":[]}]},{"level":2,"title":"\u672A\u6765\u7684\u8BA1\u5212","slug":"\u672A\u6765\u7684\u8BA1\u5212","link":"#\u672A\u6765\u7684\u8BA1\u5212","children":[{"level":3,"title":"\u652F\u6301\u72EC\u7ACB\u4F7F\u7528\u7684 Lite \u7248\u672C","slug":"\u652F\u6301\u72EC\u7ACB\u4F7F\u7528\u7684-lite-\u7248\u672C","link":"#\u652F\u6301\u72EC\u7ACB\u4F7F\u7528\u7684-lite-\u7248\u672C","children":[]},{"level":3,"title":"\u652F\u6301\u66F4\u591A Hook Framework","slug":"\u652F\u6301\u66F4\u591A-hook-framework","link":"#\u652F\u6301\u66F4\u591A-hook-framework","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/about/future.md"}');export{e as data}; diff --git a/docs/assets/future.html.4da05d23.js b/docs/assets/future.html.4da05d23.js new file mode 100644 index 00000000..aec8bbc3 --- /dev/null +++ b/docs/assets/future.html.4da05d23.js @@ -0,0 +1 @@ +import{_ as e,o,c as a,a as d}from"./app.fb8271cf.js";const r={},c=d('

    \u5C55\u671B\u672A\u6765

    \u672A\u6765\u662F\u7F8E\u597D\u7684\uFF0C\u4E5F\u662F\u4E0D\u786E\u5B9A\u7684\uFF0C\u8BA9\u6211\u4EEC\u5171\u540C\u671F\u5F85 YukiHookAPI \u5728\u672A\u6765\u7684\u53D1\u5C55\u7A7A\u95F4\u3002

    \u672A\u89E3\u51B3\u7684\u95EE\u9898

    \u8FD9\u91CC\u6536\u5F55\u4E86 YukiHookAPI \u5C1A\u672A\u89E3\u51B3\u7684\u95EE\u9898\u3002

    YukiHookModulePrefs

    \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\uFF0Cselinux \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

    \u8FD9\u91CC\u6536\u5F55\u4E86 YukiHookAPI \u53EF\u80FD\u4F1A\u5728\u540E\u671F\u6DFB\u52A0\u7684\u529F\u80FD\u3002

    \u652F\u6301\u72EC\u7ACB\u4F7F\u7528\u7684 Lite \u7248\u672C

    \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

    \u652F\u6301\u66F4\u591A Hook Framework

    \u4F5C\u4E3A API \u6765\u8BB2\uFF0C\u76EE\u524D\u4EC5\u4EC5\u5BF9\u63A5 XposedBridge \u4F5C\u4E3A\u517C\u5BB9\u5C42\uFF0C\u8FD8\u662F\u6709\u4E00\u5B9A\u7684\u5C40\u9650\u6027\u3002

    \u5927\u90E8\u5206 inline 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

    ',17),i=[c];function t(s,h){return o(),a("div",null,i)}const p=e(r,[["render",t],["__file","future.html.vue"]]);export{p as default}; diff --git a/docs/assets/future.html.94bd226b.js b/docs/assets/future.html.94bd226b.js new file mode 100644 index 00000000..d8fb0804 --- /dev/null +++ b/docs/assets/future.html.94bd226b.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-ae7b83f2","path":"/en/about/future.html","title":"Looking for Future","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Unresolved Issues","slug":"unresolved-issues","link":"#unresolved-issues","children":[{"level":3,"title":"YukiHookModulePrefs","slug":"yukihookmoduleprefs","link":"#yukihookmoduleprefs","children":[]}]},{"level":2,"title":"Future Plans","slug":"future-plans","link":"#future-plans","children":[{"level":3,"title":"Lite Version Supported for Standalone Use","slug":"lite-version-supported-for-standalone-use","link":"#lite-version-supported-for-standalone-use","children":[]},{"level":3,"title":"Support for More Hook Framework","slug":"support-for-more-hook-framework","link":"#support-for-more-hook-framework","children":[]}]}],"git":{"updatedTime":1664300349000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"en/about/future.md"}');export{e as data}; diff --git a/docs/assets/future.html.e52259cf.js b/docs/assets/future.html.e52259cf.js new file mode 100644 index 00000000..150717e7 --- /dev/null +++ b/docs/assets/future.html.e52259cf.js @@ -0,0 +1 @@ +import{_ as e,o,c as t,a as r}from"./app.fb8271cf.js";const a={},i=r('

    Looking for Future

    The future is bright and uncertain, let us look forward to the future development space of YukiHookAPI.

    Unresolved Issues

    Here are the unresolved issues with YukiHookAPI.

    YukiHookModulePrefs

    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 selinux is a big problem currently facing, which needs to be discussed and studied.

    Future Plans

    Features that YukiHookAPI may add later are included here.

    Lite Version Supported for Standalone Use

    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.

    Support for More Hook Framework

    As an API, currently only docking XposedBridge as a compatibility layer still has certain limitations.

    Most inline hook do not have a Java compatibility layer, and the Java compatibility layer adaptation of native hook may be considered later.

    ',17),s=[i];function n(d,u){return o(),t("div",null,s)}const h=e(a,[["render",n],["__file","future.html.vue"]]);export{h as default}; diff --git a/docs/assets/home.html.06a0e41c.js b/docs/assets/home.html.06a0e41c.js new file mode 100644 index 00000000..6b70ca87 --- /dev/null +++ b/docs/assets/home.html.06a0e41c.js @@ -0,0 +1,107 @@ +import{_ as i,r as o,o as p,c as d,b as s,d as e,w as a,e as l,a as r}from"./app.fb8271cf.js";const A={},y=s("h1",{id:"\u4ECB\u7ECD",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#\u4ECB\u7ECD","aria-hidden":"true"},"#"),l(" \u4ECB\u7ECD")],-1),u=s("blockquote",null,[s("p",null,"\u8FD9\u662F\u4E00\u4E2A Hook API \u6846\u67B6\uFF0C\u672C\u8EAB\u4E0D\u63D0\u4F9B\u4EFB\u4F55 Hook \u529F\u80FD\uFF0C\u9700\u8981 Xposed \u57FA\u7840 API \u7684\u652F\u6301\u3002")],-1),D=s("h2",{id:"\u80CC\u666F",tabindex:"-1"},[s("a",{class:"header-anchor",href:"#\u80CC\u666F","aria-hidden":"true"},"#"),l(" \u80CC\u666F")],-1),C=s("p",null,[l("\u8FD9\u662F\u4E00\u4E2A\u4F7F\u7528 "),s("code",null,"Kotlin"),l(" \u91CD\u65B0\u6784\u5EFA\u7684\u9AD8\u6548 Xposed Hook API\u3002")],-1),h=l("\u540D\u79F0\u53D6\u81EA "),m={href:"https://www.bilibili.com/bangumi/play/ss5016",target:"_blank",rel:"noopener noreferrer"},B=l("\u300A\u3082\u3082\u304F\u308A\u300B\u5973\u4E3B \u6817\u539F \u96EA(Yuki)"),_=l("\u3002"),b=l("\u524D\u8EAB\u4E3A "),v={href:"https://github.com/fankes/TMore",target:"_blank",rel:"noopener noreferrer"},F=l("\u5F00\u53D1\u5B66\u4E60\u9879\u76EE"),k=l(" \u4E2D\u4F7F\u7528\u7684 Innocent Xposed API\uFF0C\u73B0\u5728\u91CD\u65B0\u547D\u540D\u5E76\u5F00\u6E90\u3002"),f=r('

    \u7528\u9014

    YukiHookAPI \u5B8C\u5168\u91C7\u7528 Kotlin lambda \u8BED\u6CD5\u6784\u5EFA\u3002

    \u629B\u5F03\u539F\u59CB\u4E0D\u592A\u53CB\u597D\u7684 XposedHelpers\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

    \u8BF7\u4F7F\u7528 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\u3002

    \u6587\u6863\u5168\u90E8\u7684 Demo \u793A\u4F8B\u4EE3\u7801\u90FD\u5C06\u4F7F\u7528 Kotlin \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

    ',6),g=l("\u90E8\u5206 Java Demo \u4EE3\u7801\u53EF\u5728 "),H={href:"https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/java",target:"_blank",rel:"noopener noreferrer"},P=l("\u8FD9\u91CC"),I=l(" \u627E\u5230\uFF0C\u4F46\u4E0D\u63A8\u8350\u4F7F\u7528\u3002"),X=r('

    \u7075\u611F\u6765\u6E90

    \u4EE5\u524D\uFF0C\u6211\u4EEC\u5728\u6784\u5EFA Xposed \u6A21\u5757\u7684\u65F6\u5019\uFF0C\u9996\u5148\u9700\u8981\u5728 assets \u4E0B\u521B\u5EFA xposed_init \u6587\u4EF6\u3002

    \u7136\u540E\uFF0C\u5C06\u81EA\u5DF1\u7684\u5165\u53E3\u7C7B\u540D\u624B\u52A8\u586B\u5165\u6587\u4EF6\u4E2D\uFF0C\u4F7F\u7528 XposedHelpers \u53BB\u5B9E\u73B0\u6211\u4EEC\u7684 Hook \u903B\u8F91\u3002

    \u81EA Kotlin \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\u3002

    \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\uFF0CYukiHookAPI \u8BDE\u751F\u4E86\u3002

    \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 Kotlin \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

    \u793A\u4F8B\u5982\u4E0B

    ',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.

    Abandoning the original less friendly XposedHelpers, you can use it to easily create Xposed Modules and easily implement custom Hook API.

    Language Requirement

    Please use 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.

    All demo code in this document will be described using Kotlin, if you don't know how to use Kotlin then you may not be able to use YukiHookAPI.

    ',6),g=e("Part of the Java Demo code can be found "),H={href:"https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/java",target:"_blank",rel:"noopener noreferrer"},P=e("here"),w=e(", but not recommended."),I=r('

    Source of Inspiration

    Previously, when we built an Xposed Module, we first needed to create an xposed_init file under assets.

    Then, manually fill in your own entry class name into the file and use XposedHelpers to implement our Hook logic.

    Since Kotlin is the main Android development language, this API is really not very elegant to use.

    Is there any easy to use, light, elegant solution?

    With this idea, YukiHookAPI was born.

    Now, we only need to write a small amount of code, and all the time and expense are handed over to automation.

    With Kotlin's elegant lambda writing and YukiHookAPI, you can make your Hook logic more beautiful and clear.

    The following example

    ',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

    \u8FD9\u91CC\u7684\u6587\u6863\u5C06\u540C\u6B65\u6700\u65B0 API \u7248\u672C\u7684\u76F8\u5173\u7528\u6CD5\uFF0C\u8BF7\u4FDD\u6301 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\u63CF\u8FF0\u4E3B\u8981\u4ECB\u7ECD\u5F53\u524D API \u7684\u76F8\u5173\u7528\u6CD5\u548C\u7528\u9014\u3002

    \u529F\u80FD\u793A\u4F8B\u8BF4\u660E

    \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

    \u53D8\u66F4\u8BB0\u5F55\u8BF4\u660E

    \u9996\u4E2A\u7248\u672C\u7684\u529F\u80FD\u5C06\u6807\u8BB0\u4E3A v<version> \u6DFB\u52A0\uFF1B

    \u540E\u671F\u65B0\u589E\u52A0\u7684\u529F\u80FD\u5C06\u6807\u8BB0\u4E3A v<version> \u65B0\u589E\uFF1B

    \u540E\u671F\u4FEE\u6539\u7684\u529F\u80FD\u5C06\u88AB\u8FFD\u52A0\u4E3A v<version> \u4FEE\u6539\uFF1B

    \u540E\u671F\u88AB\u4F5C\u5E9F\u7684\u529F\u80FD\u5C06\u6807\u8BB0\u4E3A v<version> \u4F5C\u5E9F \u5E76\u4F1A\u6807\u6CE8\u5220\u9664\u7EBF\uFF1B

    \u540E\u671F\u88AB\u5220\u9664\u7684\u529F\u80FD\u5C06\u6807\u8BB0\u4E3A v<version> \u79FB\u9664 \u5E76\u4F1A\u6807\u6CE8\u5220\u9664\u7EBF\u3002

    \u76F8\u5173\u7B26\u53F7\u8BF4\u660E

    • 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 get\u3001set \u65B9\u6CD5\u6216\u53EA\u8BFB\u7684 get \u65B9\u6CD5

    • 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)

    ',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('

    Document Introduce

    The document here will synchronize the relevant usage of the latest API version, please keep YukiHookAPI as the latest version to use the latest version of the function.

    Function Description

    The function description mainly introduces the related usage and purpose of the current API.

    Function Example Description

    The function examples mainly show the basic usage examples of the current API for reference.

    Change Record Description

    The function of the first version will be marked as v<version> first;

    New function added later will be marked as v<version> added;

    Later modified function will be appended as v<version> modified;

    Later deprecated function will be marked as v<version> deprecated and strikethrough;

    Later removed function will be marked as v<version> removed and strikethrough.

    • kt \xA0Kotlin Static File

    • annotation \xA0Annotation Class

    • interface \xA0Interface Class

    • object \xA0Class (Singleton)

    • class \xA0Class

    • field \xA0Field or get / set method or read-only get method

    • 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)

    ',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(`

    \u5BBF\u4E3B\u8D44\u6E90\u6CE8\u5165\u6269\u5C55

    \u8FD9\u662F\u4E00\u4E2A\u5C06\u6A21\u5757\u8D44\u6E90\u3001Activity \u7EC4\u4EF6\u4EE5\u53CA Context \u4E3B\u9898\u6CE8\u5165\u5230\u5BBF\u4E3B\u7684\u6269\u5C55\u529F\u80FD\u3002

    \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 build.gradle \u4E2D\u4FEE\u6539\u8D44\u6E90 ID\u3002

    • Kotlin Gradle DSL
    android {
    +    androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
    +}
    +
    • Groovy
    android {
    +    aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
    +}
    +

    \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

    \u6CE8\u5165\u6A21\u5757\u8D44\u6E90 (Resources)

    \u5728 Hook \u5BBF\u4E3B\u4E4B\u540E\uFF0C\u6211\u4EEC\u53EF\u4EE5\u76F4\u63A5\u5728 Hooker \u4E2D\u5F97\u5230\u7684 Context \u6CE8\u5165\u5F53\u524D\u6A21\u5757\u8D44\u6E90\u3002

    \u793A\u4F8B\u5982\u4E0B

    injectMember {
    +    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)
    +        }
    +    }
    +}
    +

    \u4F60\u8FD8\u53EF\u4EE5\u76F4\u63A5\u5728 AppLifecycle \u4E2D\u6CE8\u5165\u5F53\u524D\u6A21\u5757\u8D44\u6E90\u3002

    \u793A\u4F8B\u5982\u4E0B

    onAppLifecycle {
    +    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)
    +    }
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 Context+Resources.injectModuleAppResources \u65B9\u6CD5\u3002

    \u6CE8\u518C\u6A21\u5757 Activity

    \u5728 Android \u7CFB\u7EDF\u4E2D\u6240\u6709\u5E94\u7528\u7684 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\uFF1F

    \u5728 Hook \u5BBF\u4E3B\u4E4B\u540E\uFF0C\u6211\u4EEC\u53EF\u4EE5\u76F4\u63A5\u5728 Hooker \u4E2D\u5F97\u5230\u7684 Context \u6CE8\u518C\u5F53\u524D\u6A21\u5757\u7684 Activity \u4EE3\u7406\u3002

    \u793A\u4F8B\u5982\u4E0B

    injectMember {
    +    method {
    +        name = "onCreate"
    +        param(BundleClass)
    +    }
    +    afterHook {
    +        instance<Activity>().registerModuleAppActivities()
    +    }
    +}
    +

    \u4F60\u8FD8\u53EF\u4EE5\u76F4\u63A5\u5728 AppLifecycle \u4E2D\u6CE8\u518C\u5F53\u524D\u6A21\u5757\u7684 Activity \u4EE3\u7406\u3002

    \u793A\u4F8B\u5982\u4E0B

    onAppLifecycle {
    +    onCreate {
    +        registerModuleAppActivities()
    +    }
    +}
    +

    \u5982\u679C\u6CA1\u6709\u586B\u5199 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\u3002

    \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 Activity \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\u3002

    \u82E5\u672A\u6CE8\u518C\u7684 Activity \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\u3002

    \u4F60\u9700\u8981\u9009\u62E9\u4E00\u4E2A\u5F53\u524D\u5BBF\u4E3B\u53EF\u80FD\u7528\u4E0D\u5230\u7684\u3001\u4E0D\u9700\u8981\u7684 Activity \u4F5C\u4E3A\u4E00\u4E2A\u201C\u5080\u5121\u201D\u5C06\u5176\u8FDB\u884C\u4EE3\u7406\uFF0C\u901A\u5E38\u662F\u6709\u6548\u7684\u3002

    \u6BD4\u5982\u6211\u4EEC\u5DF2\u7ECF\u627E\u5230\u4E86\u80FD\u591F\u88AB\u4EE3\u7406\u7684\u5408\u9002 Activity\u3002

    \u793A\u4F8B\u5982\u4E0B

    <activity
    +    android:name="com.demo.test.activity.TestActivity"
    +    ...>
    +

    \u6839\u636E\u5176\u4E2D\u7684 name\uFF0C\u6211\u4EEC\u53EA\u9700\u8981\u5728\u65B9\u6CD5\u4E2D\u52A0\u5165\u8FD9\u4E2A\u53C2\u6570\u8FDB\u884C\u6CE8\u518C\u5373\u53EF\u3002

    \u793A\u4F8B\u5982\u4E0B

    registerModuleAppActivities(proxy = "com.demo.test.activity.TestActivity")
    +

    \u53E6\u4E00\u79CD\u60C5\u51B5\uFF0C\u5982\u679C\u4F60\u5BF9\u5BBF\u4E3B\u7684\u7C7B\u7F16\u5199\u4E86\u4E00\u4E2A stub\uFF0C\u90A3\u4E48\u4F60\u53EF\u4EE5\u76F4\u63A5\u901A\u8FC7 Class \u5BF9\u8C61\u6765\u8FDB\u884C\u6CE8\u518C\u3002

    \u793A\u4F8B\u5982\u4E0B

    registerModuleAppActivities(TestActivity::class.java)
    +

    \u6CE8\u518C\u5B8C\u6210\u540E\uFF0C\u8BF7\u5C06\u4F60\u9700\u8981\u4F7F\u7528\u5BBF\u4E3B\u542F\u52A8\u7684\u6A21\u5757\u4E2D\u7684 Activity \u7EE7\u627F\u4E8E ModuleAppActivity \u6216 ModuleAppCompatActivity\u3002

    \u8FD9\u4E9B Activity \u73B0\u5728\u65E0\u9700\u6CE8\u518C\u5373\u53EF\u65E0\u7F1D\u5B58\u6D3B\u4E8E\u5BBF\u4E3B\u4E2D\u3002

    \u793A\u4F8B\u5982\u4E0B

    class 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)
    +    }
    +}
    +

    \u82E5\u4F60\u9700\u8981\u7EE7\u627F\u4E8E ModuleAppCompatActivity\uFF0C\u4F60\u9700\u8981\u624B\u52A8\u8BBE\u7F6E AppCompat \u4E3B\u9898\u3002

    \u793A\u4F8B\u5982\u4E0B

    class 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)
    +    }
    +}
    +

    \u4EE5\u4E0A\u6B65\u9AA4\u5168\u90E8\u5B8C\u6210\u540E\uFF0C\u4F60\u5C31\u53EF\u4EE5\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4EFB\u610F\u5B58\u5728 Context \u7684\u5730\u65B9\u6109\u5FEB\u5730\u8C03\u7528 startActivity \u4E86\u3002

    \u793A\u4F8B\u5982\u4E0B

    val context: Context = ... // \u5047\u8BBE\u8FD9\u5C31\u662F\u4F60\u7684 Context
    +context.startActivity(context, HostTestActivity::class.java)
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 Context.registerModuleAppActivities \u65B9\u6CD5\u3002

    \u521B\u5EFA ContextThemeWrapper \u4EE3\u7406

    \u6709\u65F6\u5019\uFF0C\u6211\u4EEC\u9700\u8981\u4F7F\u7528 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\u3002

    • \u4F1A\u5F97\u5230\u5982\u4E0B\u5F02\u5E38
    The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
    +

    \u8FD9\u65F6\uFF0C\u6211\u4EEC\u60F3\u5728\u5BBF\u4E3B\u88AB Hook \u7684\u5F53\u524D Activity \u4E2D\u4F7F\u7528 MaterialAlertDialogBuilder \u6765\u521B\u5EFA\u5BF9\u8BDD\u6846\uFF0C\u5C31\u53EF\u4EE5\u6709\u5982\u4E0B\u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    injectMember {
    +    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()
    +    }
    +}
    +

    \u4F60\u8FD8\u53EF\u4EE5\u5BF9\u5F53\u524D 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\u3002

    \u793A\u4F8B\u5982\u4E0B

    injectMember {
    +    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()
    +    }
    +}
    +

    \u8FD9\u6837\uFF0C\u6211\u4EEC\u5C31\u53EF\u4EE5\u5728\u5BBF\u4E3B\u4E2D\u975E\u5E38\u7B80\u5355\u5730\u4F7F\u7528 MaterialAlertDialogBuilder \u521B\u5EFA\u5BF9\u8BDD\u6846\u4E86\u3002

    `,59),d={class:"custom-container warning"},A=s("p",{class:"custom-container-title"},"\u53EF\u80FD\u5B58\u5728\u7684\u95EE\u9898",-1),y=n("\u7531\u4E8E\u4E00\u4E9B APP \u81EA\u8EAB\u4F7F\u7528\u7684 "),u=s("strong",null,"androidx",-1),v=n(" \u4F9D\u8D56\u5E93\u6216\u81EA\u5B9A\u4E49\u4E3B\u9898\u53EF\u80FD\u4F1A\u5BF9\u5F53\u524D "),C=s("strong",null,"MaterialAlertDialog",-1),D=n(" \u5B9E\u9645\u6837\u5F0F\u9020\u6210\u5E72\u6270\uFF0C\u4F8B\u5982\u5BF9\u8BDD\u6846\u7684\u6309\u94AE\u6837\u5F0F\uFF0C\u8FD9\u79CD\u60C5\u51B5\u4F60\u53EF\u4EE5\u53C2\u8003 "),m=s("strong",null,"\u6A21\u5757 Demo",-1),B=n(" \u4E2D "),b={href:"https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/factory/ComponentCompatFactory.kt",target:"_blank",rel:"noopener noreferrer"},F=n("\u8FD9\u91CC\u7684\u793A\u4F8B\u4EE3\u7801"),h=n(" \u6765\u4FEE\u590D\u8FD9\u4E2A\u95EE\u9898\u3002"),k=s("p",null,[n("\u67D0\u4E9B APP \u5728\u521B\u5EFA\u65F6\u53EF\u80FD\u4F1A\u53D1\u751F "),s("strong",null,"ClassCastException"),n(" \u5F02\u5E38\uFF0C\u8BF7\u624B\u52A8\u6307\u5B9A\u65B0\u7684 "),s("strong",null,"Configuration"),n(" \u5B9E\u4F8B\u6765\u8FDB\u884C\u4FEE\u590D\u3002")],-1),g=s("div",{class:"custom-container tip"},[s("p",{class:"custom-container-title"},"\u5C0F\u63D0\u793A"),s("p",null,[n("\u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 "),s("a",{href:"../public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory#context-applymoduletheme-ext-method"},"Context.applyModuleTheme"),n(" \u65B9\u6CD5\u3002")])],-1);function x(_,q){const a=e("ExternalLinkIcon");return o(),p("div",null,[r,s("div",d,[A,s("p",null,[y,u,v,C,D,m,B,s("a",b,[F,c(a)]),h]),k]),g])}const M=l(i,[["render",x],["__file","host-inject.html.vue"]]);export{M as default}; diff --git a/docs/assets/host-inject.html.c5fc5faf.js b/docs/assets/host-inject.html.c5fc5faf.js new file mode 100644 index 00000000..cc30efcd --- /dev/null +++ b/docs/assets/host-inject.html.c5fc5faf.js @@ -0,0 +1 @@ +const e=JSON.parse(`{"key":"v-12042f1f","path":"/en/api/special-features/host-inject.html","title":"Host Resource Injection Extension","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Inject Module App's Resources","slug":"inject-module-app-s-resources","link":"#inject-module-app-s-resources","children":[]},{"level":2,"title":"Register Module App's Activity","slug":"register-module-app-s-activity","link":"#register-module-app-s-activity","children":[]},{"level":2,"title":"Create ContextThemeWrapper Proxy","slug":"create-contextthemewrapper-proxy","link":"#create-contextthemewrapper-proxy","children":[]}],"git":{"updatedTime":1664041274000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/special-features/host-inject.md"}`);export{e as data}; diff --git a/docs/assets/host-inject.html.e5c6c6ae.js b/docs/assets/host-inject.html.e5c6c6ae.js new file mode 100644 index 00000000..8b0ef12d --- /dev/null +++ b/docs/assets/host-inject.html.e5c6c6ae.js @@ -0,0 +1,122 @@ +import{_ as a,r as l,o,c as p,b as s,d as t,a as i,e}from"./app.fb8271cf.js";const c={},r=i(`

    Host Resource Injection Extension

    This is an extension that injects Module App's Resources, Activity components, and Context topics into the Host App.

    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 build.gradle of the current Xposed Module project.

    • Kotlin Gradle DSL
    android {
    +    androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
    +}
    +
    • Groovy
    android {
    +    aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
    +}
    +

    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.

    Inject Module App's Resources

    After the Host App is hooked, we can directly inject the Context obtained in the Hooker into the current Module App's Resources.

    The following example

    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)
    +        }
    +    }
    +}
    +

    You can also inject current Module App's Resources directly in AppLifecycle.

    The following example

    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)
    +    }
    +}
    +

    Tips

    For more functions, please refer to the Context+Resources.injectModuleAppResources method.

    Register Module App's Activity

    When the Activity of all applications in the Android system starts, it needs to be registered in AndroidManifest.xml.

    During the Hook process, if we want to directly start the unregistered Activity in the Module App through the Host App, what should we do?

    After the Host App is hooked, we can directly register the Activity proxy of the current Module App in the Context obtained in the Hooker.

    The following example

    injectMember {
    +    method {
    +        name = "onCreate"
    +        param(BundleClass)
    +    }
    +    afterHook {
    +        instance<Activity>().registerModuleAppActivities()
    +    }
    +}
    +

    You can also register the current Module App's Activity proxy directly in AppLifecycle.

    The following example

    onAppLifecycle {
    +    onCreate {
    +        registerModuleAppActivities()
    +    }
    +}
    +

    If the 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.

    Usually, it works, but the above situation will fail in some apps, for example, some Activity will add launching parameters to the registration list, so we need to use another solution.

    If the unregistered 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.

    You need to choose an unneeded Activity that may not be used by the current Host App as a "puppet" to proxy it, which usually works.

    For example, we have found a suitable Activity that can be proxied.

    The following example

    <activity
    +    android:name="com.demo.test.activity.TestActivity"
    +    ...>
    +

    According to the name, we only need to add this parameter to the method for registration.

    The following example

    registerModuleAppActivities(proxy = "com.demo.test.activity.TestActivity")
    +

    Alternatively, if you write a stub for the Host App's class, you can register it directly through the Class object.

    The following example

    registerModuleAppActivities(TestActivity::class.java)
    +

    After the registration is complete, extends the Activity in the Module App you need to use the Host App to start by ModuleAppActivity or ModuleAppCompatActivity.

    These Activity now live seamlessly in the Host App without registration.

    The following example

    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)
    +    }
    +}
    +

    If you need to extends ModuleAppCompatActivity, you need to set the AppCompat theme manually.

    The following example

    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)
    +    }
    +}
    +

    After all the above steps are completed, you can happily call startActivity anywhere in the (Xposed) Host environment where a Context exists.

    The following example

    val context: Context = ... // Assume this is your Context
    +context.startActivity(context, HostTestActivity::class.java)
    +

    Tips

    For more functions, please refer to the Context.registerModuleAppActivities method.

    Create ContextThemeWrapper Proxy

    Sometimes, we need to use MaterialAlertDialogBuilder to beautify our own dialogs in the Host App, but we can't create them without the AppCompat theme.

    • Will got the following exception
    The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
    +

    At this time, we want to use MaterialAlertDialogBuilder to create a dialog in the current Activity of the Host App being hooked, you can have the following methods.

    The following example

    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()
    +    }
    +}
    +

    You can also set the system (native) night mode and day mode on the current Context through uiMode.

    Which requires at least Android 10 and above system version support and the current theme contains night mode related elements.

    The following example

    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()
    +    }
    +}
    +

    This way, we can create dialogs in the Host App very simply using MaterialAlertDialogBuilder.

    `,61),d={class:"custom-container warning"},A=s("p",{class:"custom-container-title"},"Possible Problems",-1),u=s("p",null,[e("Because some "),s("strong",null,"androidx"),e(" dependent libraries or custom themes used by some apps may interfere with the actual style of the current "),s("strong",null,"MaterialAlertDialog"),e(", such as the button style of the dialog.")],-1),y=e("You can refer to the "),v=s("strong",null,"Module App Demo",-1),m=e(" in this case and see "),h={href:"https://github.com/fankes/YukiHookAPI/tree/master/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/factory/ComponentCompatFactory.kt",target:"_blank",rel:"noopener noreferrer"},C=e("here is the sample code"),D=e(" to fix this problem."),b=s("p",null,[s("strong",null,"ClassCastException"),e(" may occur when some apps are created, please manually specify a new "),s("strong",null,"Configuration"),e(" instance to fix.")],-1),B=s("div",{class:"custom-container tip"},[s("p",{class:"custom-container-title"},"Tips"),s("p",null,[e("For more functions, please refer to the "),s("a",{href:"../public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory#context-applymoduletheme-ext-method"},"Context.applyModuleTheme"),e(" method.")])],-1);function g(F,k){const n=l("ExternalLinkIcon");return o(),p("div",null,[r,s("div",d,[A,u,s("p",null,[y,v,m,s("a",h,[C,t(n)]),D]),b]),B])}const f=a(c,[["render",g],["__file","host-inject.html.vue"]]);export{f as default}; diff --git a/docs/assets/host-lifecycle.html.09c0b222.js b/docs/assets/host-lifecycle.html.09c0b222.js new file mode 100644 index 00000000..3b1f0926 --- /dev/null +++ b/docs/assets/host-lifecycle.html.09c0b222.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-357a8d49","path":"/zh-cn/api/special-features/host-lifecycle.html","title":"\u5BBF\u4E3B\u751F\u547D\u5468\u671F\u6269\u5C55","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u76D1\u542C\u751F\u547D\u5468\u671F","slug":"\u76D1\u542C\u751F\u547D\u5468\u671F","link":"#\u76D1\u542C\u751F\u547D\u5468\u671F","children":[]},{"level":2,"title":"\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD","slug":"\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD","link":"#\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD","children":[]}],"git":{"updatedTime":1664038384000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/special-features/host-lifecycle.md"}');export{e as data}; diff --git a/docs/assets/host-lifecycle.html.412bbdd6.js b/docs/assets/host-lifecycle.html.412bbdd6.js new file mode 100644 index 00000000..f6141944 --- /dev/null +++ b/docs/assets/host-lifecycle.html.412bbdd6.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-deaff1d0","path":"/en/api/special-features/host-lifecycle.html","title":"Host Lifecycle Extension","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Monitor Lifecycle","slug":"monitor-lifecycle","link":"#monitor-lifecycle","children":[]},{"level":2,"title":"Register System Broadcast","slug":"register-system-broadcast","link":"#register-system-broadcast","children":[]}],"git":{"updatedTime":1664038435000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/special-features/host-lifecycle.md"}');export{e as data}; diff --git a/docs/assets/host-lifecycle.html.56277eb5.js b/docs/assets/host-lifecycle.html.56277eb5.js new file mode 100644 index 00000000..378afa8a --- /dev/null +++ b/docs/assets/host-lifecycle.html.56277eb5.js @@ -0,0 +1,46 @@ +import{_ as s,o as n,c as a,a as l}from"./app.fb8271cf.js";const e={},p=l(`

    \u5BBF\u4E3B\u751F\u547D\u5468\u671F\u6269\u5C55

    \u8FD9\u662F\u4E00\u4E2A\u81EA\u52A8 Hook \u5BBF\u4E3B APP \u751F\u547D\u5468\u671F\u7684\u6269\u5C55\u529F\u80FD\u3002

    \u76D1\u542C\u751F\u547D\u5468\u671F

    \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 Application \u7684\u542F\u52A8\u548C\u751F\u547D\u5468\u671F\u65B9\u6CD5\uFF0C\u53EA\u9700\u8981\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u5B9E\u73B0\u3002

    \u793A\u4F8B\u5982\u4E0B

    loadApp(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 ->
    +            // ...
    +        }
    +    }
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 AppLifecycle\u3002

    \u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD

    \u901A\u8FC7 Application.onCreate \u65B9\u6CD5\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\uFF0C\u6765\u5B9E\u73B0\u5BF9\u7CFB\u7EDF\u5E7F\u64AD\u7684\u76D1\u542C\u3002

    \u6211\u4EEC\u8FD8\u53EF\u4EE5\u5728\u5BBF\u4E3B Application \u4E2D\u6CE8\u518C\u7CFB\u7EDF\u5E7F\u64AD\u3002

    \u793A\u4F8B\u5982\u4E0B

    loadApp(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 ->
    +            // ...
    +        }
    +    }
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 AppLifecycle\u3002

    `,14),o=[p];function c(i,r){return n(),a("div",null,o)}const d=s(e,[["render",c],["__file","host-lifecycle.html.vue"]]);export{d as default}; diff --git a/docs/assets/host-lifecycle.html.73e3c8fc.js b/docs/assets/host-lifecycle.html.73e3c8fc.js new file mode 100644 index 00000000..e46bf0c9 --- /dev/null +++ b/docs/assets/host-lifecycle.html.73e3c8fc.js @@ -0,0 +1,47 @@ +import{_ as s,o as n,c as e,a}from"./app.fb8271cf.js";const l={},p=a(`

    Host Lifecycle Extension

    This is an extension of the lifecycle of an automatic hooking Host App.

    Monitor Lifecycle

    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 Application, just use the following methods.

    The following example

    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 ->
    +            // ...
    +        }
    +    }
    +}
    +

    Tips

    For more functions, please refer to AppLifecycle.

    Register System Broadcast

    Register system broadcast through the Application.onCreate method to monitor system broadcast.

    We can also register system broadcast in the Host App's Application.

    The following example

    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 ->
    +            // ...
    +        }
    +    }
    +}
    +

    Tips

    For more functions, please refer to AppLifecycle.

    `,14),o=[p];function c(i,t){return n(),e("div",null,o)}const d=s(l,[["render",c],["__file","host-lifecycle.html.vue"]]);export{d as default}; diff --git a/docs/assets/index.html.1b76ac9e.js b/docs/assets/index.html.1b76ac9e.js new file mode 100644 index 00000000..285aac0f --- /dev/null +++ b/docs/assets/index.html.1b76ac9e.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-8daa1a0e","path":"/","title":"","lang":"en-US","frontmatter":{"home":true,"navbar":false,"sidebar":false,"title":null,"heroAlt":null,"heroText":null,"tagline":"Select a language","actions":[{"text":"English","link":"/en/","type":"secondary"},{"text":"\u7B80\u4F53\u4E2D\u6587","link":"/zh-cn/","type":"secondary"}],"footer":"MIT License | Copyright (C) 2019-2022 HighCapable"},"excerpt":"","headers":[],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"index.md"}');export{e as data}; diff --git a/docs/assets/index.html.6cc32291.js b/docs/assets/index.html.6cc32291.js new file mode 100644 index 00000000..ffe98ed2 --- /dev/null +++ b/docs/assets/index.html.6cc32291.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-c0c85b84","path":"/zh-cn/","title":"\u9996\u9875","lang":"zh-CN","frontmatter":{"home":true,"title":"\u9996\u9875","heroImage":"/images/logo.png","actions":[{"text":"\u5FEB\u901F\u4E0A\u624B","link":"/zh-cn/guide/home","type":"primary"},{"text":"\u66F4\u65B0\u65E5\u5FD7","link":"/zh-cn/about/changelog","type":"secondary"}],"features":[{"title":"Xposed \u6A21\u5757\u5F00\u53D1","details":"\u81EA\u52A8\u6784\u5EFA\u7A0B\u5E8F\u53EF\u4EE5\u5E2E\u4F60\u5FEB\u901F\u521B\u5EFA\u4E00\u4E2A Xposed \u6A21\u5757\uFF0C\u5B8C\u5168\u7701\u53BB\u914D\u7F6E\u5165\u53E3\u7C7B\u548C xposed_init \u6587\u4EF6\u3002"},{"title":"\u8F7B\u91CF\u4F18\u96C5","details":"\u62E5\u6709\u4E00\u5957\u5F3A\u5927\u3001\u4F18\u96C5\u3001\u4EBA\u6027\u5316\u3001\u5B8C\u5168\u4F7F\u7528 Kotlin lambda \u6253\u9020\u7684 API\uFF0C\u53EF\u4EE5\u5E2E\u4F60\u5FEB\u901F\u5B9E\u73B0\u5B57\u8282\u7801\u7684\u67E5\u627E\u4EE5\u53CA\u65B9\u6CD5 Hook\u3002"},{"title":"\u9AD8\u6548\u8C03\u8BD5","details":"\u62E5\u6709\u4E30\u5BCC\u7684\u8C03\u8BD5\u65E5\u5FD7\u529F\u80FD\uFF0C\u7EC6\u5230\u6BCF\u4E2A Hook \u65B9\u6CD5\u7684\u540D\u79F0\u3001\u6240\u5728\u7C7B\u4EE5\u53CA\u67E5\u627E\u8017\u65F6\uFF0C\u53EF\u8FDB\u884C\u5FEB\u901F\u8C03\u8BD5\u548C\u6392\u9519\u3002"},{"title":"\u65B9\u4FBF\u79FB\u690D","details":"\u539F\u751F\u652F\u6301 Xposed API \u7528\u6CD5\uFF0C\u5E76\u539F\u751F\u5BF9\u63A5 Xposed API\uFF0C\u62E5\u6709 Xposed API \u7684 Hook \u6846\u67B6\u90FD\u80FD\u8FDB\u884C\u5FEB\u901F\u5BF9\u63A5\u3002"},{"title":"\u652F\u6301\u6DF7\u6DC6","details":"\u6784\u5EFA\u7684 Xposed \u6A21\u5757\u539F\u751F\u652F\u6301 R8 \u538B\u7F29\u4F18\u5316\u6DF7\u6DC6\uFF0C\u6DF7\u6DC6\u4E0D\u4F1A\u7834\u574F Hook \u5165\u53E3\u70B9\uFF0CR8 \u4E0B\u65E0\u9700\u4EFB\u4F55\u5176\u5B83\u914D\u7F6E\u3002"},{"title":"\u5FEB\u901F\u4E0A\u624B","details":"\u7B80\u5355\u6613\u7528\uFF0C\u4E0D\u9700\u8981\u7E41\u7410\u7684\u914D\u7F6E\uFF0C\u4E0D\u9700\u8981\u5341\u8DB3\u7684\u5F00\u53D1\u7ECF\u9A8C\uFF0C\u642D\u5EFA\u73AF\u5883\u96C6\u6210\u4F9D\u8D56\u5373\u53EF\u7ACB\u5373\u5F00\u59CB\u4F7F\u7528\u3002"}],"footer":"MIT License | Copyright (C) 2019-2022 HighCapable"},"excerpt":"","headers":[{"level":3,"title":"\u6240\u6709 Hook \u6D41\u7A0B\u4E00\u6B65\u5230\u4F4D\uFF0C\u62D2\u7EDD\u7E41\u7410","slug":"\u6240\u6709-hook-\u6D41\u7A0B\u4E00\u6B65\u5230\u4F4D-\u62D2\u7EDD\u7E41\u7410","link":"#\u6240\u6709-hook-\u6D41\u7A0B\u4E00\u6B65\u5230\u4F4D-\u62D2\u7EDD\u7E41\u7410","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/index.md"}');export{e as data}; diff --git a/docs/assets/index.html.872aa7a1.js b/docs/assets/index.html.872aa7a1.js new file mode 100644 index 00000000..d4fe00f0 --- /dev/null +++ b/docs/assets/index.html.872aa7a1.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2d0a870d","path":"/en/","title":"Home","lang":"en-US","frontmatter":{"home":true,"title":"Home","heroImage":"/images/logo.png","actions":[{"text":"Get Started","link":"/en/guide/home","type":"primary"},{"text":"Changelog","link":"/en/about/changelog","type":"secondary"}],"features":[{"title":"Xposed Module Develop","details":"The automatic builder can help you quickly create an Xposed Module, automatic configure the entry class and xposed_init file."},{"title":"Light and Elegant","details":"A powerful, elegant, beautiful API built with Kotlin lambda can help you quickly implement members search and methods hooks."},{"title":"Debugging Efficient","details":"A rich debug log function, detailing the name of each hooked method, time-consuming to find the class can quickly debug and find errors."},{"title":"Easy to transplant","details":"Native support for Xposed API usage, in any case, the supported Hook Framework with Xposed API can be quickly spliced with it."},{"title":"Obfuscate Support","details":"The built Xposed Module simply supports R8, obfuscate will not destroy the hook entry point, and no other configuration is required under R8."},{"title":"Quickly Started","details":"Simple and easy to use it now! Do not need complex configuration and full development experience, Integrate dependencies and enjoy yourself."}],"footer":"MIT License | Copyright (C) 2019-2022 HighCapable"},"excerpt":"","headers":[{"level":3,"title":"All Hook process in one step, everything is simplified","slug":"all-hook-process-in-one-step-everything-is-simplified","link":"#all-hook-process-in-one-step-everything-is-simplified","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/index.md"}');export{e as data}; diff --git a/docs/assets/index.html.d735d08d.js b/docs/assets/index.html.d735d08d.js new file mode 100644 index 00000000..e530cfd4 --- /dev/null +++ b/docs/assets/index.html.d735d08d.js @@ -0,0 +1,26 @@ +import{_ as s,o as n,c as a,a as l}from"./app.fb8271cf.js";const e={},p=l(`

    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)
    +        }
    +    }
    +}
    +
    `,2),i=[p];function o(c,r){return n(),a("div",null,i)}const d=s(e,[["render",o],["__file","index.html.vue"]]);export{d as default}; diff --git a/docs/assets/index.html.f36dcd2e.js b/docs/assets/index.html.f36dcd2e.js new file mode 100644 index 00000000..9c2357b6 --- /dev/null +++ b/docs/assets/index.html.f36dcd2e.js @@ -0,0 +1,26 @@ +import{_ as s,o as n,c as a,a as l}from"./app.fb8271cf.js";const e={},p=l(`

    \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)
    +        }
    +    }
    +}
    +
    `,2),o=[p];function i(c,r){return n(),a("div",null,o)}const d=s(e,[["render",i],["__file","index.html.vue"]]);export{d as default}; diff --git a/docs/assets/index.html.f53b6095.js b/docs/assets/index.html.f53b6095.js new file mode 100644 index 00000000..d44e466d --- /dev/null +++ b/docs/assets/index.html.f53b6095.js @@ -0,0 +1 @@ +import{_ as e,o as c,c as t}from"./app.fb8271cf.js";const n={};function _(o,r){return c(),t("div")}const a=e(n,[["render",_],["__file","index.html.vue"]]);export{a as default}; diff --git a/docs/assets/knowledge.html.437816ed.js b/docs/assets/knowledge.html.437816ed.js new file mode 100644 index 00000000..b1efdb3f --- /dev/null +++ b/docs/assets/knowledge.html.437816ed.js @@ -0,0 +1 @@ +const e=JSON.parse(`{"key":"v-277b35ca","path":"/en/guide/knowledge.html","title":"Basic Knowledge","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Related Introduction","slug":"related-introduction","link":"#related-introduction","children":[{"level":3,"title":"What is Xposed","slug":"what-is-xposed","link":"#what-is-xposed","children":[]},{"level":3,"title":"What can Xposed do","slug":"what-can-xposed-do","link":"#what-can-xposed-do","children":[]},{"level":3,"title":"Development Process","slug":"development-process","link":"#development-process","children":[]},{"level":3,"title":"Derivatives","slug":"derivatives","link":"#derivatives","children":[]},{"level":3,"title":"What YukiHookAPI does","slug":"what-yukihookapi-does","link":"#what-yukihookapi-does","children":[]}]},{"level":2,"title":"Let's Started","slug":"let-s-started","link":"#let-s-started","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/guide/knowledge.md"}`);export{e as data}; diff --git a/docs/assets/knowledge.html.821f04b5.js b/docs/assets/knowledge.html.821f04b5.js new file mode 100644 index 00000000..58e9d2d1 --- /dev/null +++ b/docs/assets/knowledge.html.821f04b5.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-b4f1a468","path":"/zh-cn/guide/knowledge.html","title":"\u57FA\u7840\u77E5\u8BC6","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u76F8\u5173\u4ECB\u7ECD","slug":"\u76F8\u5173\u4ECB\u7ECD","link":"#\u76F8\u5173\u4ECB\u7ECD","children":[{"level":3,"title":"Xposed \u662F\u4EC0\u4E48","slug":"xposed-\u662F\u4EC0\u4E48","link":"#xposed-\u662F\u4EC0\u4E48","children":[]},{"level":3,"title":"Xposed \u80FD\u505A\u4EC0\u4E48","slug":"xposed-\u80FD\u505A\u4EC0\u4E48","link":"#xposed-\u80FD\u505A\u4EC0\u4E48","children":[]},{"level":3,"title":"\u53D1\u5C55\u8FC7\u7A0B","slug":"\u53D1\u5C55\u8FC7\u7A0B","link":"#\u53D1\u5C55\u8FC7\u7A0B","children":[]},{"level":3,"title":"\u884D\u751F\u4EA7\u54C1","slug":"\u884D\u751F\u4EA7\u54C1","link":"#\u884D\u751F\u4EA7\u54C1","children":[]},{"level":3,"title":"YukiHookAPI \u505A\u4E86\u4EC0\u4E48","slug":"yukihookapi-\u505A\u4E86\u4EC0\u4E48","link":"#yukihookapi-\u505A\u4E86\u4EC0\u4E48","children":[]}]},{"level":2,"title":"\u8BA9\u6211\u4EEC\u5F00\u59CB\u5427","slug":"\u8BA9\u6211\u4EEC\u5F00\u59CB\u5427","link":"#\u8BA9\u6211\u4EEC\u5F00\u59CB\u5427","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/guide/knowledge.md"}');export{e as data}; diff --git a/docs/assets/knowledge.html.a4616f5c.js b/docs/assets/knowledge.html.a4616f5c.js new file mode 100644 index 00000000..c53c1879 --- /dev/null +++ b/docs/assets/knowledge.html.a4616f5c.js @@ -0,0 +1,13 @@ +import{_ as n,r as a,o as r,c as i,b as e,d as t,a as d,e as o}from"./app.fb8271cf.js";const l={},p=d(`

    Basic Knowledge

    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.

    What is Xposed

    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.

    What can Xposed do

    The structure below describes the basic workings and principles of Xposed.

    Xposed Framework
    +\u2514\u2500\u2500 App's Environment
    +    \u2514\u2500\u2500 Hooker (Hooked)
    +        ...
    +    App's Environment
    +    \u2514\u2500\u2500 Hooker (Hooked)
    +        ...
    +    ...
    +

    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 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

    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)

    Derivatives

    The structure below describes how and how the Xposed-like Hook Framework works.

    App's Environment
    +\u2514\u2500\u2500 Hook Framework
    +    \u2514\u2500\u2500 Hooker (Hooked)
    +        ...
    +

    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.

    What YukiHookAPI does

    Since Xposed appeared until now, apart from XposedHelpers, which is well known to developers, there is still no set of syntactic sugar for Kotlin and API with complete usage encapsulation.

    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, 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

    Before starting, you need to have the following basics to better use YukiHookAPI.

    `,31),c=e("li",null,[e("p",null,"Grasp and understand Android development and simple system operation principles")],-1),h=o("To grasp and understand the internal structure of Android APK and simple decompilation knowledge, you can refer to "),u={href:"https://github.com/skylot/jadx",target:"_blank",rel:"noopener noreferrer"},g=o("Jadx"),m=o(" and "),f={href:"https://github.com/iBotPeaches/Apktool",target:"_blank",rel:"noopener noreferrer"},k=o("ApkTool"),b=e("li",null,[e("p",null,"Grasp and proficient in using Java reflection, understand simple Smali syntax, understand Dex file structure, and use reverse analysis to locate method locations")],-1),y=o("Grasp the basic native "),w={href:"https://api.xposed.info",target:"_blank",rel:"noopener noreferrer"},v=o("Xposed API"),_=o(" usage, understand the operation principle of Xposed"),x=e("li",null,[e("p",null,[o("Grasp Kotlin language and learn to use "),e("strong",null,"Kotlin lambda")])],-1),A=e("li",null,[e("p",null,"Grasp and understand Kotlin and Java mixing, calling each other, and Java bytecode generated by Kotlin")],-1);function X(H,T){const s=a("ExternalLinkIcon");return r(),i("div",null,[p,e("ul",null,[c,e("li",null,[e("p",null,[h,e("a",u,[g,t(s)]),m,e("a",f,[k,t(s)])])]),b,e("li",null,[e("p",null,[y,e("a",w,[v,t(s)]),_])]),x,A])])}const P=n(l,[["render",X],["__file","knowledge.html.vue"]]);export{P as default}; diff --git a/docs/assets/knowledge.html.e0a069f9.js b/docs/assets/knowledge.html.e0a069f9.js new file mode 100644 index 00000000..53f24580 --- /dev/null +++ b/docs/assets/knowledge.html.e0a069f9.js @@ -0,0 +1,13 @@ +import{_ as a,r as t,o as r,c as p,b as o,d as n,a as l,e}from"./app.fb8271cf.js";const d={},c=l(`

    \u57FA\u7840\u77E5\u8BC6

    \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

    \u76F8\u5173\u4ECB\u7ECD

    \u8FD9\u91CC\u4ECB\u7ECD\u4E86 Xposed \u4EE5\u53CA Hook \u7684\u5DE5\u4F5C\u539F\u7406\u3002

    Xposed \u662F\u4EC0\u4E48

    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

    Xposed \u80FD\u505A\u4EC0\u4E48

    \u4E0B\u65B9\u7684\u7ED3\u6784\u63CF\u8FF0\u4E86 Xposed \u7684\u57FA\u672C\u5DE5\u4F5C\u65B9\u5F0F\u548C\u539F\u7406\u3002

    Xposed Framework
    +\u2514\u2500\u2500 App's Environment
    +    \u2514\u2500\u2500 Hooker (Hooked)
    +        ...
    +    App's Environment
    +    \u2514\u2500\u2500 Hooker (Hooked)
    +        ...
    +    ...
    +

    \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 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

    \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)

    \u884D\u751F\u4EA7\u54C1

    \u4E0B\u65B9\u7684\u7ED3\u6784\u63CF\u8FF0\u4E86\u7C7B\u4F3C Xposed \u7684 Hook Framework \u7684\u5DE5\u4F5C\u65B9\u5F0F\u548C\u539F\u7406\u3002

    App's Environment
    +\u2514\u2500\u2500 Hook Framework
    +    \u2514\u2500\u2500 Hooker (Hooked)
    +        ...
    +

    \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

    YukiHookAPI \u505A\u4E86\u4EC0\u4E48

    \u81EA\u4ECE Xposed \u51FA\u73B0\u5230\u73B0\u5728\u4E3A\u6B62\uFF0C\u9664\u4E86\u5F00\u53D1\u8005\u4EBA\u4EBA\u7686\u77E5\u7684 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\u3002

    \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\uFF0CYukiHookAPI \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

    \u5728\u5F00\u59CB\u4E4B\u524D\uFF0C\u4F60\u9700\u8981\u62E5\u6709\u4EE5\u4E0B\u57FA\u7840\u624D\u80FD\u66F4\u597D\u5730\u4F7F\u7528 YukiHookAPI\u3002

    `,30),i=o("li",null,[o("p",null,"\u638C\u63E1\u5E76\u4E86\u89E3 Android \u5F00\u53D1\u53CA\u7B80\u5355\u7684\u7CFB\u7EDF\u8FD0\u884C\u539F\u7406")],-1),h=e("\u638C\u63E1\u5E76\u4E86\u89E3 Android APK \u5185\u90E8\u7ED3\u6784\u4EE5\u53CA\u7B80\u5355\u7684\u53CD\u7F16\u8BD1\u77E5\u8BC6\u8981\u9886\uFF0C\u53EF\u53C2\u8003 "),k={href:"https://github.com/skylot/jadx",target:"_blank",rel:"noopener noreferrer"},_=e("Jadx"),u=e(" \u4E0E "),g={href:"https://github.com/iBotPeaches/Apktool",target:"_blank",rel:"noopener noreferrer"},b=e("ApkTool"),A=o("li",null,[o("p",null,"\u638C\u63E1\u5E76\u719F\u7EC3\u4F7F\u7528 Java \u53CD\u5C04\uFF0C\u4E86\u89E3\u7B80\u5355\u7684 Smali \u8BED\u6CD5\uFF0C\u4E86\u89E3 DEX \u6587\u4EF6\u7ED3\u6784\uFF0C\u4F1A\u4F7F\u7528\u9006\u5411\u5206\u6790\u5B9A\u4F4D\u65B9\u6CD5\u4F4D\u7F6E")],-1),X=e("\u638C\u63E1\u57FA\u7840\u7684\u539F\u751F "),x={href:"https://api.xposed.info",target:"_blank",rel:"noopener noreferrer"},f=e("Xposed API"),P=e(" \u7528\u6CD5\uFF0C\u4E86\u89E3 Xposed \u7684\u8FD0\u884C\u539F\u7406\uFF0C\u53EF\u53C2\u8003\u672C\u6587\u4EE5\u53CA "),E={href:"https://blog.ketal.icu/2022/01/13/Xposed%E6%A8%A1%E5%9D%97%E5%BC%80%E5%8F%91%E5%85%A5%E9%97%A8%E4%BF%9D%E5%A7%86%E7%BA%A7%E6%95%99%E7%A8%8B",target:"_blank",rel:"noopener noreferrer"},m=e("\u8FD9\u91CC"),y=e(),H=o("strong",null,"(\u53CB\u60C5\u94FE\u63A5)",-1),v=e("\u638C\u63E1 Kotlin \u8BED\u8A00\uFF0C\u5B66\u4F1A\u7075\u6D3B\u8FD0\u7528 "),q={href:"https://blog.ketal.icu/2022/01/01/kotlin-lambda%E5%85%A5%E9%97%A8",target:"_blank",rel:"noopener noreferrer"},I=e("Kotlin lambda"),B=e(),K=o("strong",null,"(\u53CB\u60C5\u94FE\u63A5)",-1),R=o("li",null,[o("p",null,"\u638C\u63E1\u5E76\u4E86\u89E3 Kotlin \u4E0E Java \u6DF7\u7F16\u3001\u4E92\u76F8\u8C03\u7528\u4EE5\u53CA Kotlin \u751F\u6210\u7684 Java \u5B57\u8282\u7801")],-1);function V(w,F){const s=t("ExternalLinkIcon");return r(),p("div",null,[c,o("ul",null,[i,o("li",null,[o("p",null,[h,o("a",k,[_,n(s)]),u,o("a",g,[b,n(s)])])]),A,o("li",null,[o("p",null,[X,o("a",x,[f,n(s)]),P,o("a",E,[m,n(s)]),y,H])]),o("li",null,[o("p",null,[v,o("a",q,[I,n(s)]),B,K])]),R])])}const D=a(d,[["render",V],["__file","knowledge.html.vue"]]);export{D as default}; diff --git a/docs/assets/logger.html.2d57680b.js b/docs/assets/logger.html.2d57680b.js new file mode 100644 index 00000000..1e90df7b --- /dev/null +++ b/docs/assets/logger.html.2d57680b.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-33c1dc26","path":"/en/api/special-features/logger.html","title":"Debug Logs","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Normal Logs","slug":"normal-logs","link":"#normal-logs","children":[]},{"level":2,"title":"Error Logs","slug":"error-logs","link":"#error-logs","children":[]},{"level":2,"title":"Save Logs and Custom Elements","slug":"save-logs-and-custom-elements","link":"#save-logs-and-custom-elements","children":[]}],"git":{"updatedTime":1664014745000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/special-features/logger.md"}');export{e as data}; diff --git a/docs/assets/logger.html.55af0b09.js b/docs/assets/logger.html.55af0b09.js new file mode 100644 index 00000000..55631402 --- /dev/null +++ b/docs/assets/logger.html.55af0b09.js @@ -0,0 +1,33 @@ +import{_ as s,o as e,c as o,a}from"./app.fb8271cf.js";const l={},n=a(`

    Debug Logs

    Log is the most important part of the debugging process, YukiHookAPI encapsulates a set of stable and efficient debugging log functions for developers.

    Normal Logs

    You can call loggerD, loggerI, loggerW to print normal logs to the console.

    The usage method is as follows.

    The following example

    loggerD(msg = "This is a log")
    +

    At this point, YukiHookAPI will call android.util.Log and XposedBridge.log to print this log at the same time.

    The default TAG of the log is the value you set in YukiHookLogger.Configs.tag.

    You can also customize this value dynamically, but it is not recommended to modify TAG easily to prevent logs from being filtered.

    The following example

    loggerD(tag = "YukiHookAPI", msg = "This is a log")
    +

    The printed result is as shown below.

    The following example

    [YukiHookAPI][D][host package name]--> This is a log
    +

    You can also use LoggerType to customize the type of log printing.

    You can choose to use android.util.Log or XposedBridge.log to print logs.

    The default type is LoggerType.BOTH, which means that both methods are used to print logs.

    For example we only use android.util.Log to print logs.

    The following example

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.LOGD)
    +

    Or just use XposedBridge.log to print the log, this method can only be used in the (Xposed) Host environment.

    The following example

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.XPOSEDBRIDGE)
    +

    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

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
    +

    In this way, the API will intelligently select the specified method type to print this log in different environments.

    Tips

    For more functions, please refer to loggerD, loggerI and loggerW methods.

    Error Logs

    You can call loggerE to print E level logs to the console.

    The usage method is as follows.

    The following example

    loggerE(msg = "This is an error")
    +

    The error log is the highest level, regardless of whether you have filtered only E level logs.

    For error-level logging, you can also append an exception stack.

    // Assume this is the exception that was thrown
    +val throwable = Throwable(...)
    +// Print log
    +loggerE(msg = "This is an error", e = throwable)
    +

    The printed result is as shown below.

    The following example

    [YukiHookAPI][E][host package name]--> This is an error
    +

    At the same time, the log will help you print the entire exception stack.

    The following example

    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
    +

    In the error log, you can also use LoggerType to specify the method type currently used to print the log.

    Tips

    For more functions, please refer to the loggerE method.

    Save Logs and Custom Elements

    You can save all currently printed logs directly to a file using the YukiHookLogger.saveToFile method.

    The following example

    // 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")
    +

    You can also use YukiHookLogger.contents to get all the log file contents that have been printed so far.

    The following example

    // Get the contents of all log files that have been printed so far
    +val fileContent = YukiHookLogger.contents
    +

    The above features require YukiHookLogger.Configs.isRecord to be enabled.

    You can also use YukiHookLogger.Configs.elements to customize the elements that debug logs display externally.

    This function requires YukiHookAPI.Configs to be configured in onInit of the Hook entry class.

    The following example

    override fun onInit() = configs {
    +    debugLog {
    +        // ...
    +        elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
    +    }
    +    // ...
    +}
    +

    Tips

    For more functions, please refer to YukiHookLogger.contents, YukiHookLogger.saveToFile methods and YukiHookLogger.Configs.

    `,58),p=[n];function t(c,i){return e(),o("div",null,p)}const d=s(l,[["render",t],["__file","logger.html.vue"]]);export{d as default}; diff --git a/docs/assets/logger.html.e8fab6a3.js b/docs/assets/logger.html.e8fab6a3.js new file mode 100644 index 00000000..91a0b11f --- /dev/null +++ b/docs/assets/logger.html.e8fab6a3.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-1f0f591e","path":"/zh-cn/api/special-features/logger.html","title":"\u8C03\u8BD5\u65E5\u5FD7","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u666E\u901A\u65E5\u5FD7","slug":"\u666E\u901A\u65E5\u5FD7","link":"#\u666E\u901A\u65E5\u5FD7","children":[]},{"level":2,"title":"\u9519\u8BEF\u65E5\u5FD7","slug":"\u9519\u8BEF\u65E5\u5FD7","link":"#\u9519\u8BEF\u65E5\u5FD7","children":[]},{"level":2,"title":"\u4FDD\u5B58\u65E5\u5FD7\u4E0E\u81EA\u5B9A\u4E49\u5143\u7D20","slug":"\u4FDD\u5B58\u65E5\u5FD7\u4E0E\u81EA\u5B9A\u4E49\u5143\u7D20","link":"#\u4FDD\u5B58\u65E5\u5FD7\u4E0E\u81EA\u5B9A\u4E49\u5143\u7D20","children":[]}],"git":{"updatedTime":1664013967000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"zh-cn/api/special-features/logger.md"}');export{e as data}; diff --git a/docs/assets/logger.html.fd07b1ad.js b/docs/assets/logger.html.fd07b1ad.js new file mode 100644 index 00000000..8ff1d86b --- /dev/null +++ b/docs/assets/logger.html.fd07b1ad.js @@ -0,0 +1,31 @@ +import{_ as s,o,c as a,a as e}from"./app.fb8271cf.js";const n={},l=e(`

    \u8C03\u8BD5\u65E5\u5FD7

    \u65E5\u5FD7\u662F\u8C03\u8BD5\u8FC7\u7A0B\u6700\u91CD\u8981\u7684\u4E00\u73AF\uFF0CYukiHookAPI \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

    \u4F60\u53EF\u4EE5\u8C03\u7528 loggerD\u3001loggerI\u3001loggerW \u6765\u5411\u63A7\u5236\u53F0\u6253\u5370\u666E\u901A\u65E5\u5FD7\u3002

    \u4F7F\u7528\u65B9\u6CD5\u5982\u4E0B\u6240\u793A\u3002

    \u793A\u4F8B\u5982\u4E0B

    loggerD(msg = "This is a log")
    +

    \u6B64\u65F6\uFF0CYukiHookAPI \u4F1A\u8C03\u7528 android.util.Log \u4E0E XposedBridge.log \u540C\u65F6\u6253\u5370\u8FD9\u6761\u65E5\u5FD7\u3002

    \u65E5\u5FD7\u9ED8\u8BA4\u7684 TAG \u4E3A\u4F60\u5728 YukiHookLogger.Configs.tag \u4E2D\u8BBE\u7F6E\u7684\u503C\u3002

    \u4F60\u4E5F\u53EF\u4EE5\u52A8\u6001\u81EA\u5B9A\u4E49\u8FD9\u4E2A\u503C\uFF0C\u4F46\u662F\u4E0D\u5EFA\u8BAE\u8F7B\u6613\u4FEE\u6539 TAG \u9632\u6B62\u8FC7\u6EE4\u4E0D\u5230\u65E5\u5FD7\u3002

    \u793A\u4F8B\u5982\u4E0B

    loggerD(tag = "YukiHookAPI", msg = "This is a log")
    +

    \u6253\u5370\u7684\u7ED3\u679C\u4E3A\u5982\u4E0B\u6240\u793A\u3002

    \u793A\u4F8B\u5982\u4E0B

    [YukiHookAPI][D][\u5BBF\u4E3B\u5305\u540D]--> This is a log
    +

    \u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 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\u3002

    \u9ED8\u8BA4\u7C7B\u578B\u4E3A LoggerType.BOTH\uFF0C\u542B\u4E49\u4E3A\u540C\u65F6\u4F7F\u7528\u8FD9\u4E24\u4E2A\u65B9\u6CD5\u6765\u6253\u5370\u65E5\u5FD7\u3002

    \u6BD4\u5982\u6211\u4EEC\u4EC5\u4F7F\u7528 android.util.Log \u6765\u6253\u5370\u65E5\u5FD7\u3002

    \u793A\u4F8B\u5982\u4E0B

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.LOGD)
    +

    \u6216\u53C8\u4EC5\u4F7F\u7528 XposedBridge.log \u6765\u6253\u5370\u65E5\u5FD7\uFF0C\u6B64\u65B9\u6CD5\u4EC5\u53EF\u5728 (Xposed) \u5BBF\u4E3B\u73AF\u5883\u4F7F\u7528\u3002

    \u793A\u4F8B\u5982\u4E0B

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.XPOSEDBRIDGE)
    +

    \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

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
    +

    \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

    \u9519\u8BEF\u65E5\u5FD7

    \u4F60\u53EF\u4EE5\u8C03\u7528 loggerE \u6765\u5411\u63A7\u5236\u53F0\u6253\u5370 E \u7EA7\u522B\u7684\u65E5\u5FD7\u3002

    \u4F7F\u7528\u65B9\u6CD5\u5982\u4E0B\u6240\u793A\u3002

    \u793A\u4F8B\u5982\u4E0B

    loggerE(msg = "This is an error")
    +

    \u9519\u8BEF\u65E5\u5FD7\u7684\u7EA7\u522B\u662F\u6700\u9AD8\u7684\uFF0C\u65E0\u8BBA\u4F60\u6709\u6CA1\u6709\u8FC7\u6EE4\u4EC5\u4E3A E \u7EA7\u522B\u7684\u65E5\u5FD7\u3002

    \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

    // \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)
    +

    \u6253\u5370\u7684\u7ED3\u679C\u4E3A\u5982\u4E0B\u6240\u793A\u3002

    \u793A\u4F8B\u5982\u4E0B

    [YukiHookAPI][E][\u5BBF\u4E3B\u5305\u540D]--> This is an error
    +

    \u540C\u65F6\uFF0C\u65E5\u5FD7\u4F1A\u5E2E\u4F60\u6253\u5370\u6574\u4E2A\u5F02\u5E38\u5806\u6808\u3002

    \u793A\u4F8B\u5982\u4E0B

    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
    +

    \u5728\u9519\u8BEF\u65E5\u5FD7\u4E2D\uFF0C\u4F60\u540C\u6837\u4E5F\u53EF\u4EE5\u4F7F\u7528 LoggerType \u6765\u6307\u5B9A\u5F53\u524D\u6253\u5370\u65E5\u5FD7\u6240\u7528\u5230\u7684\u65B9\u6CD5\u7C7B\u578B\u3002

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 loggerE \u65B9\u6CD5\u3002

    \u4FDD\u5B58\u65E5\u5FD7\u4E0E\u81EA\u5B9A\u4E49\u5143\u7D20

    \u4F60\u53EF\u4EE5\u4F7F\u7528 YukiHookLogger.saveToFile \u65B9\u6CD5\u76F4\u63A5\u4FDD\u5B58\u5F53\u524D\u5DF2\u6253\u5370\u7684\u5168\u90E8\u65E5\u5FD7\u5230\u6587\u4EF6\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 YukiHookLogger.contents \u83B7\u53D6\u5F53\u524D\u5DF2\u6253\u5370\u7684\u5168\u90E8\u65E5\u5FD7\u6587\u4EF6\u5185\u5BB9\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \u83B7\u53D6\u5F53\u524D\u5DF2\u6253\u5370\u7684\u5168\u90E8\u65E5\u5FD7\u6587\u4EF6\u5185\u5BB9
    +val fileContent = YukiHookLogger.contents
    +

    \u4EE5\u4E0A\u529F\u80FD\u9700\u8981\u542F\u7528 YukiHookLogger.Configs.isRecord\u3002

    \u4F60\u8FD8\u53EF\u4EE5\u4F7F\u7528 YukiHookLogger.Configs.elements \u81EA\u5B9A\u4E49\u8C03\u8BD5\u65E5\u5FD7\u5BF9\u5916\u663E\u793A\u7684\u5143\u7D20\u3002

    \u6B64\u529F\u80FD\u9700\u8981\u5728 Hook \u5165\u53E3\u7C7B\u7684 onInit \u4E2D\u5BF9 YukiHookAPI.Configs \u8FDB\u884C\u914D\u7F6E\u3002

    \u793A\u4F8B\u5982\u4E0B

    override fun onInit() = configs {
    +    debugLog {
    +        // ...
    +        elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
    +    }
    +    // ...
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiHookLogger.contents\u3001YukiHookLogger.saveToFile \u65B9\u6CD5\u4EE5\u53CA YukiHookLogger.Configs\u3002

    `,57),p=[l];function c(i,r){return o(),a("div",null,p)}const d=s(n,[["render",c],["__file","logger.html.vue"]]);export{d as default}; diff --git a/docs/assets/move-to-new-api.html.2d2ee2a7.js b/docs/assets/move-to-new-api.html.2d2ee2a7.js new file mode 100644 index 00000000..79d6e4f2 --- /dev/null +++ b/docs/assets/move-to-new-api.html.2d2ee2a7.js @@ -0,0 +1,184 @@ +import{_ as p,r as c,o as i,c as t,d as n,w as e,a as r,b as s,e as l}from"./app.fb8271cf.js";const A={},y=r('

    \u4ECE Xposed API \u8FC1\u79FB

    \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 YukiHookAPI\u3002

    \u8FC1\u79FB Hook \u5165\u53E3\u70B9

    \u4ECE XC_LoadPackage.LoadPackageParam \u8FC1\u79FB\u81F3 PackageParam\u3002

    YukiHookAPI \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

    API \u529F\u80FD\u5DEE\u5F02\u5BF9\u6BD4\u5982\u4E0B

    ',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

    \u4ECE 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

    API \u529F\u80FD\u5DEE\u5F02\u5BF9\u6BD4\u5982\u4E0B

    ',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

    If you are familiar with Xposed API, you can refer to the same point below to quickly migrate your API to YukiHookAPI.

    Migrate Hook Entry Point

    Migrated from 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.

    The API function differences are compared as follows

    ',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

    Migrated from 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.

    The API function differences are compared as follows

    ',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

    \u96C6\u6210 YukiHookAPI \u5230\u4F60\u7684\u9879\u76EE\u4E2D\u3002

    \u73AF\u5883\u8981\u6C42

    • 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 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

    \u4F60\u53EF\u4EE5 \u70B9\u51FB\u8FD9\u91CC \u8FDB\u884C\u67E5\u770B\u3002

    \u624B\u52A8\u914D\u7F6E\u9879\u76EE

    \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

    \u521B\u5EFA\u9879\u76EE

    \u4F7F\u7528 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

    \u5728\u4F60\u7684\u9879\u76EE build.gradle \u4E2D\u6DFB\u52A0\u4F9D\u8D56\u3002

    \u793A\u4F8B\u5982\u4E0B

    repositories {
    +    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" }
    +}
    +

    \u5728\u4F60\u7684 app build.gradle \u4E2D\u6DFB\u52A0 plugin\u3002

    \u793A\u4F8B\u5982\u4E0B

    plugins {
    +    // \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>'
    +}
    +

    \u5728\u4F60\u7684 app build.gradle \u4E2D\u6DFB\u52A0\u4F9D\u8D56\u3002

    \u793A\u4F8B\u5982\u4E0B

    dependencies {
    +    // \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>'
    +}
    +
    `,21),d=s("\u8BF7\u5C06 "),u=n("strong",null,"",-1),v=s(" \u4FEE\u6539\u4E3A "),A={href:"https://github.com/google/ksp/releases",target:"_blank",rel:"noopener noreferrer"},y=s("\u8FD9\u91CC"),m=s(" \u7684\u6700\u65B0\u7248\u672C "),b=n("strong",null,"(\u8BF7\u6CE8\u610F\u9009\u62E9\u4F60\u5F53\u524D\u5BF9\u5E94\u7684 Kotlin \u7248\u672C)",-1),D=s("\u3002"),h=a(`

    \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 build.gradle \u4E2D\u4FEE\u6539 Kotlin \u7684 Jvm \u7248\u672C\u4E3A 11 \u53CA\u4EE5\u4E0A\u3002

    \u793A\u4F8B\u5982\u4E0B

    android {
    +    compileOptions {
    +        sourceCompatibility JavaVersion.VERSION_11
    +        targetCompatibility JavaVersion.VERSION_11
    +    }
    +    kotlinOptions {
    +        jvmTarget = '11'
    +    }
    +}
    +

    \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

    \u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528

    \u5728\u4F60\u7684 AndroidManifest.xml \u4E2D\u6DFB\u52A0\u57FA\u7840\u4EE3\u7801\u3002

    \u793A\u4F8B\u5982\u4E0B

    <!-- \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"/>
    +

    \u5728\u4F60\u7684\u9879\u76EE\u4E2D\u521B\u5EFA\u4E00\u4E2A Hook \u5165\u53E3\u7C7B\uFF0C\u7EE7\u627F\u4E8E IYukiHookXposedInit \u5E76\u52A0\u5165\u6CE8\u89E3 @InjectYukiHookWithXposed\u3002

    \u793A\u4F8B\u5982\u4E0B

    @InjectYukiHookWithXposed
    +class HookEntry : IYukiHookXposedInit {
    +
    +    override fun onHook() = YukiHookAPI.encase {
    +        // Your code here.
    +    }
    +}
    +

    \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

    \u4F5C\u4E3A Hook API \u4F7F\u7528

    \u96C6\u6210\u65B9\u5F0F

    \u521B\u5EFA\u4F60\u7684\u81EA\u5B9A\u4E49 Application\u3002

    \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 attachBaseContext \u4E2D\u6DFB\u52A0 YukiHookAPI.encase \u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    override fun attachBaseContext(base: Context?) {
    +    // \u88C5\u8F7D Hook Framework
    +    //
    +    // Your code here.
    +    //
    +    // \u88C5\u8F7D YukiHookAPI
    +    YukiHookAPI.encase(base) {
    +        // Your code here.
    +    }
    +    super.attachBaseContext(base)
    +}
    +

    \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

    `,27);function C(B,k){const e=o("ExternalLinkIcon");return p(),i("div",null,[t,n("p",null,[d,u,v,n("a",A,[y,c(e)]),m,b,D]),h])}const F=l(r,[["render",C],["__file","quick-start.html.vue"]]);export{F as default}; diff --git a/docs/assets/quick-start.html.749cf17e.js b/docs/assets/quick-start.html.749cf17e.js new file mode 100644 index 00000000..72dc8da4 --- /dev/null +++ b/docs/assets/quick-start.html.749cf17e.js @@ -0,0 +1,70 @@ +import{_ as o,r as l,o as i,c as p,b as n,d as t,a as e,e as s}from"./app.fb8271cf.js";const r={},c=e(`

    Quick Start

    Integrate YukiHookAPI into your project.

    Environment Requirements

    • 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 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.

    You can click here to check it out.

    Manually Configure Project

    If you don't want to use automated build tools, you can still manually configure project dependencies as follows.

    Create Project

    Use 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

    Add dependencies to your project build.gradle.

    The following example

    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" }
    +}
    +

    Add plugin to your app build.gradle.

    The following example

    plugins {
    +    // \u2757Be sure to add it as an Xposed Module, optional in other cases
    +    id 'com.google.devtools.ksp' version '<ksp-version>'
    +}
    +

    Add dependencies to your app build.gradle.

    The following example

    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>'
    +}
    +
    `,21),d=s("Please modify "),u=n("strong",null,"",-1),y=s(" to the latest version from "),v={href:"https://github.com/google/ksp/releases",target:"_blank",rel:"noopener noreferrer"},A=s("here"),m=s(),h=n("strong",null,"(Please choose your current corresponding Kotlin version)",-1),b=s("."),g=e(`

    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 Kotlin to 11 and above in your app build.gradle.

    The following example

    android {
    +    compileOptions {
    +        sourceCompatibility JavaVersion.VERSION_11
    +        targetCompatibility JavaVersion.VERSION_11
    +    }
    +    kotlinOptions {
    +        jvmTarget = '11'
    +    }
    +}
    +

    Notice

    Since API 1.0.80 version, the default JVM version is 11, and 1.8 and below are no longer supported.

    Use as Xposed Module

    Add the base code to your AndroidManifest.xml.

    The following example

    <!-- 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"/>
    +

    Create a Hook entry class in your project, implements IYukiHookXposedInit and add the annotation @InjectYukiHookWithXposed.

    The following example

    @InjectYukiHookWithXposed
    +class HookEntry : IYukiHookXposedInit {
    +
    +    override fun onHook() = YukiHookAPI.encase {
    +        // Your code here.
    +    }
    +}
    +

    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.

    Use as Hook API

    Integration

    Create your custom Application.

    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 YukiHookAPI.encase method to attachBaseContext.

    The following example

    override fun attachBaseContext(base: Context?) {
    +    // Load Hook Framework
    +    //
    +    // Your code here.
    +    //
    +    // Load YukiHookAPI
    +    YukiHookAPI.encase(base) {
    +        // Your code here.
    +    }
    +    super.attachBaseContext(base)
    +}
    +

    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.

    `,27);function D(C,B){const a=l("ExternalLinkIcon");return i(),p("div",null,[c,n("p",null,[d,u,y,n("a",v,[A,t(a)]),m,h,b]),g])}const F=o(r,[["render",D],["__file","quick-start.html.vue"]]);export{F as default}; diff --git a/docs/assets/quick-start.html.e309979a.js b/docs/assets/quick-start.html.e309979a.js new file mode 100644 index 00000000..68872866 --- /dev/null +++ b/docs/assets/quick-start.html.e309979a.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-72889797","path":"/en/guide/quick-start.html","title":"Quick Start","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Environment Requirements","slug":"environment-requirements","link":"#environment-requirements","children":[]},{"level":2,"title":"Automatically Build Project","slug":"automatically-build-project","link":"#automatically-build-project","children":[]},{"level":2,"title":"Manually Configure Project","slug":"manually-configure-project","link":"#manually-configure-project","children":[{"level":3,"title":"Create Project","slug":"create-project","link":"#create-project","children":[]},{"level":3,"title":"Integration Dependencies","slug":"integration-dependencies","link":"#integration-dependencies","children":[]},{"level":3,"title":"Use as Xposed Module","slug":"use-as-xposed-module","link":"#use-as-xposed-module","children":[]},{"level":3,"title":"Use as Hook API","slug":"use-as-hook-api","link":"#use-as-hook-api","children":[]}]}],"git":{"updatedTime":1664300349000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":4}]},"filePathRelative":"en/guide/quick-start.md"}');export{e as data}; diff --git a/docs/assets/quick-start.html.eacb83f2.js b/docs/assets/quick-start.html.eacb83f2.js new file mode 100644 index 00000000..ef24ac48 --- /dev/null +++ b/docs/assets/quick-start.html.eacb83f2.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-24840ff0","path":"/zh-cn/guide/quick-start.html","title":"\u5FEB\u901F\u5F00\u59CB","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u73AF\u5883\u8981\u6C42","slug":"\u73AF\u5883\u8981\u6C42","link":"#\u73AF\u5883\u8981\u6C42","children":[]},{"level":2,"title":"\u81EA\u52A8\u6784\u5EFA\u9879\u76EE","slug":"\u81EA\u52A8\u6784\u5EFA\u9879\u76EE","link":"#\u81EA\u52A8\u6784\u5EFA\u9879\u76EE","children":[]},{"level":2,"title":"\u624B\u52A8\u914D\u7F6E\u9879\u76EE","slug":"\u624B\u52A8\u914D\u7F6E\u9879\u76EE","link":"#\u624B\u52A8\u914D\u7F6E\u9879\u76EE","children":[{"level":3,"title":"\u521B\u5EFA\u9879\u76EE","slug":"\u521B\u5EFA\u9879\u76EE","link":"#\u521B\u5EFA\u9879\u76EE","children":[]},{"level":3,"title":"\u96C6\u6210\u4F9D\u8D56","slug":"\u96C6\u6210\u4F9D\u8D56","link":"#\u96C6\u6210\u4F9D\u8D56","children":[]},{"level":3,"title":"\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528","slug":"\u4F5C\u4E3A-xposed-\u6A21\u5757\u4F7F\u7528","link":"#\u4F5C\u4E3A-xposed-\u6A21\u5757\u4F7F\u7528","children":[]},{"level":3,"title":"\u4F5C\u4E3A Hook API \u4F7F\u7528","slug":"\u4F5C\u4E3A-hook-api-\u4F7F\u7528","link":"#\u4F5C\u4E3A-hook-api-\u4F7F\u7528","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/guide/quick-start.md"}');export{e as data}; diff --git a/docs/assets/r8-proguard.html.15e04e11.js b/docs/assets/r8-proguard.html.15e04e11.js new file mode 100644 index 00000000..0b715ad6 --- /dev/null +++ b/docs/assets/r8-proguard.html.15e04e11.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-29d6c1ba","path":"/en/config/r8-proguard.html","title":"R8 & Proguard Obfuscate","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"R8","slug":"r8","link":"#r8","children":[]},{"level":2,"title":"Proguard","slug":"proguard","link":"#proguard","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/config/r8-proguard.md"}');export{e as data}; diff --git a/docs/assets/r8-proguard.html.1ec215bf.js b/docs/assets/r8-proguard.html.1ec215bf.js new file mode 100644 index 00000000..b55aa44f --- /dev/null +++ b/docs/assets/r8-proguard.html.1ec215bf.js @@ -0,0 +1,2 @@ +import{_ as e,o,c as a,a as r}from"./app.fb8271cf.js";const n={},s=r(`

    R8 & Proguard Obfuscate

    In most scenarios, the Xposed Module can be compressed by native obfuscation.

    Here is the configuration method of obfuscation.

    R8

    If you are using 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.

    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 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
    +
    `,9),t=[s];function d(c,i){return o(),a("div",null,t)}const u=e(n,[["render",d],["__file","r8-proguard.html.vue"]]);export{u as default}; diff --git a/docs/assets/r8-proguard.html.44d498ce.js b/docs/assets/r8-proguard.html.44d498ce.js new file mode 100644 index 00000000..67d03bda --- /dev/null +++ b/docs/assets/r8-proguard.html.44d498ce.js @@ -0,0 +1,2 @@ +import{_ as e,o,c as r,a}from"./app.fb8271cf.js";const d={},s=a(`

    R8 \u4E0E Proguard \u6DF7\u6DC6

    \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

    R8

    \u5982\u679C\u4F60\u4F7F\u7528\u7684\u662F 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\u3002

    \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 R8\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\u3002

    android.enableR8=true
    +
    `,9),n=[s];function c(l,t){return o(),r("div",null,n)}const p=e(d,[["render",c],["__file","r8-proguard.html.vue"]]);export{p as default}; diff --git a/docs/assets/r8-proguard.html.683a5429.js b/docs/assets/r8-proguard.html.683a5429.js new file mode 100644 index 00000000..56f4ed49 --- /dev/null +++ b/docs/assets/r8-proguard.html.683a5429.js @@ -0,0 +1 @@ +const r=JSON.parse('{"key":"v-154d6f69","path":"/zh-cn/config/r8-proguard.html","title":"R8 \u4E0E Proguard \u6DF7\u6DC6","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"R8","slug":"r8","link":"#r8","children":[]},{"level":2,"title":"Proguard","slug":"proguard","link":"#proguard","children":[]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/config/r8-proguard.md"}');export{r as data}; diff --git a/docs/assets/reflection.html.2e612549.js b/docs/assets/reflection.html.2e612549.js new file mode 100644 index 00000000..28f3209b --- /dev/null +++ b/docs/assets/reflection.html.2e612549.js @@ -0,0 +1 @@ +const l=JSON.parse('{"key":"v-001858e3","path":"/zh-cn/api/special-features/reflection.html","title":"\u5B57\u8282\u7801\u4E0E\u53CD\u5C04\u6269\u5C55","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Class \u6269\u5C55","slug":"class-\u6269\u5C55","link":"#class-\u6269\u5C55","children":[{"level":3,"title":"\u5BF9\u8C61\u8F6C\u6362","slug":"\u5BF9\u8C61\u8F6C\u6362","link":"#\u5BF9\u8C61\u8F6C\u6362","children":[]},{"level":3,"title":"\u5B58\u5728\u5224\u65AD","slug":"\u5B58\u5728\u5224\u65AD","link":"#\u5B58\u5728\u5224\u65AD","children":[]},{"level":3,"title":"\u6A21\u7CCA\u67E5\u627E","slug":"\u6A21\u7CCA\u67E5\u627E","link":"#\u6A21\u7CCA\u67E5\u627E","children":[]}]},{"level":2,"title":"Member \u6269\u5C55","slug":"member-\u6269\u5C55","link":"#member-\u6269\u5C55","children":[{"level":3,"title":"\u67E5\u627E\u4E0E\u53CD\u5C04\u8C03\u7528","slug":"\u67E5\u627E\u4E0E\u53CD\u5C04\u8C03\u7528","link":"#\u67E5\u627E\u4E0E\u53CD\u5C04\u8C03\u7528","children":[]},{"level":3,"title":"\u53EF\u9009\u7684\u67E5\u627E\u6761\u4EF6","slug":"\u53EF\u9009\u7684\u67E5\u627E\u6761\u4EF6","link":"#\u53EF\u9009\u7684\u67E5\u627E\u6761\u4EF6","children":[]},{"level":3,"title":"\u5728\u7236\u7C7B\u67E5\u627E","slug":"\u5728\u7236\u7C7B\u67E5\u627E","link":"#\u5728\u7236\u7C7B\u67E5\u627E","children":[]},{"level":3,"title":"\u6A21\u7CCA\u67E5\u627E","slug":"\u6A21\u7CCA\u67E5\u627E-1","link":"#\u6A21\u7CCA\u67E5\u627E-1","children":[]},{"level":3,"title":"\u591A\u91CD\u67E5\u627E","slug":"\u591A\u91CD\u67E5\u627E-1","link":"#\u591A\u91CD\u67E5\u627E-1","children":[]},{"level":3,"title":"\u9759\u6001\u5B57\u8282\u7801","slug":"\u9759\u6001\u5B57\u8282\u7801","link":"#\u9759\u6001\u5B57\u8282\u7801","children":[]},{"level":3,"title":"\u6DF7\u6DC6\u7684\u5B57\u8282\u7801","slug":"\u6DF7\u6DC6\u7684\u5B57\u8282\u7801","link":"#\u6DF7\u6DC6\u7684\u5B57\u8282\u7801","children":[]},{"level":3,"title":"\u76F4\u63A5\u8C03\u7528","slug":"\u76F4\u63A5\u8C03\u7528","link":"#\u76F4\u63A5\u8C03\u7528","children":[]},{"level":3,"title":"\u539F\u59CB\u8C03\u7528","slug":"\u539F\u59CB\u8C03\u7528","link":"#\u539F\u59CB\u8C03\u7528","children":[]},{"level":3,"title":"\u518D\u6B21\u67E5\u627E","slug":"\u518D\u6B21\u67E5\u627E","link":"#\u518D\u6B21\u67E5\u627E","children":[]},{"level":3,"title":"\u76F8\u5BF9\u5339\u914D","slug":"\u76F8\u5BF9\u5339\u914D","link":"#\u76F8\u5BF9\u5339\u914D","children":[]},{"level":3,"title":"\u8C03\u7528\u6CDB\u578B","slug":"\u8C03\u7528\u6CDB\u578B","link":"#\u8C03\u7528\u6CDB\u578B","children":[]},{"level":3,"title":"\u6CE8\u610F\u8BEF\u533A","slug":"\u6CE8\u610F\u8BEF\u533A","link":"#\u6CE8\u610F\u8BEF\u533A","children":[]}]},{"level":2,"title":"\u5E38\u7528\u7C7B\u578B\u6269\u5C55","slug":"\u5E38\u7528\u7C7B\u578B\u6269\u5C55","link":"#\u5E38\u7528\u7C7B\u578B\u6269\u5C55","children":[]}],"git":{"updatedTime":1664281516000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":6}]},"filePathRelative":"zh-cn/api/special-features/reflection.md"}');export{l as data}; diff --git a/docs/assets/reflection.html.3174ec77.js b/docs/assets/reflection.html.3174ec77.js new file mode 100644 index 00000000..1b570e45 --- /dev/null +++ b/docs/assets/reflection.html.3174ec77.js @@ -0,0 +1,812 @@ +import{_ as l,r as e,o as p,c as o,b as s,d as c,a as n,e as r}from"./app.fb8271cf.js";const i={},t=n(`

    \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

    \u8FD9\u91CC\u662F Class \u5BF9\u8C61\u81EA\u8EAB\u76F8\u5173\u7684\u6269\u5C55\u529F\u80FD\u3002

    \u5BF9\u8C61\u8F6C\u6362

    \u5047\u8BBE\u6211\u4EEC\u8981\u5F97\u5230\u4E00\u4E2A\u4E0D\u80FD\u76F4\u63A5\u8C03\u7528\u7684 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

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u8FD9\u79CD\u5199\u6CD5\u5927\u6982\u4E0D\u662F\u5F88\u53CB\u597D\uFF0C\u6B64\u65F6 YukiHookAPI \u5C31\u4E3A\u4F60\u63D0\u4F9B\u4E86\u4E00\u4E2A\u53EF\u5728\u4EFB\u610F\u5730\u65B9\u4F7F\u7528\u7684\u8BED\u6CD5\u7CD6\u3002

    \u4EE5\u4E0A\u5199\u6CD5\u6362\u505A YukiHookAPI \u53EF\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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)
    +

    \u5982\u679C\u5F53\u524D 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

    \u793A\u4F8B\u5982\u4E0B

    // \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)
    +

    \u6211\u4EEC\u8FD8\u53EF\u4EE5\u901A\u8FC7\u6620\u5C04\u6765\u5F97\u5230\u4E00\u4E2A\u5B58\u5728\u7684 Class \u5BF9\u8C61\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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)
    +

    \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

    \u5B58\u5728\u5224\u65AD

    \u5047\u8BBE\u6211\u4EEC\u8981\u5224\u65AD\u4E00\u4E2A 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

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +}
    +

    \u8FD9\u79CD\u5199\u6CD5\u5927\u6982\u4E0D\u662F\u5F88\u53CB\u597D\uFF0C\u6B64\u65F6 YukiHookAPI \u5C31\u4E3A\u4F60\u63D0\u4F9B\u4E86\u4E00\u4E2A\u53EF\u5728\u4EFB\u610F\u5730\u65B9\u4F7F\u7528\u7684\u8BED\u6CD5\u7CD6\u3002

    \u4EE5\u4E0A\u5199\u6CD5\u6362\u505A YukiHookAPI \u53EF\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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)
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 String.hasClass\u3001PackageParam \u2192 String.hasClass \u65B9\u6CD5\u3002

    `,28),d={id:"\u6A21\u7CCA\u67E5\u627E",tabindex:"-1"},A=s("a",{class:"header-anchor",href:"#\u6A21\u7CCA\u67E5\u627E","aria-hidden":"true"},"#",-1),y=r(" \u6A21\u7CCA\u67E5\u627E\u2002"),u=n(`

    \u5728 R8 \u7B49\u5DE5\u5177\u6DF7\u6DC6\u540E\u7684\u5BBF\u4E3B Dex \u4E2D\u7684 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\u3002

    \u6B64\u65F6\u5C31\u6709\u4E86 DexClassFinder\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

    \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

    \u5F00\u59CB\u4F7F\u7528

    \u4E0B\u9762\u662F\u4E00\u4E2A\u7B80\u5355\u7684\u7528\u6CD5\u793A\u4F8B\u3002

    \u5047\u8BBE\u4E0B\u9762\u8FD9\u4E2A 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\u3002

    \u793A\u4F8B\u5982\u4E0B

    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) {
    +        // ...
    +    }
    +}
    +

    \u6B64\u65F6\uFF0C\u6211\u4EEC\u60F3\u5F97\u5230\u8FD9\u4E2A Class\uFF0C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 ClassLoader.searchClass \u65B9\u6CD5\u3002

    \u5728 PackageParam \u4E2D\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 searchClass \u65B9\u6CD5\uFF0C\u5B83\u5C06\u81EA\u52A8\u6307\u5B9A appClassLoader\u3002

    \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

    searchClass {
    +    // \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
    +

    \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

    \u5F02\u6B65\u67E5\u627E

    \u9ED8\u8BA4\u60C5\u51B5\u4E0B 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\u3002

    \u9488\u5BF9\u4E0A\u8FF0\u95EE\u9898\uFF0C\u6211\u4EEC\u53EF\u4EE5\u542F\u7528\u5F02\u6B65\uFF0C\u53EA\u9700\u8981\u52A0\u5165\u53C2\u6570 async = 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\u3002

    \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

    searchClass(async = true) {
    +    // ...
    +}.wait { class1 ->
    +    // \u5F97\u5230\u5F02\u6B65\u7ED3\u679C
    +}
    +searchClass(async = true) {
    +    // ...
    +}.wait { class2 ->
    +    // \u5F97\u5230\u5F02\u6B65\u7ED3\u679C
    +}
    +

    \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

    \u672C\u5730\u7F13\u5B58

    \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 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\u3002

    \u672C\u5730\u7F13\u5B58\u4F7F\u7528\u7684\u662F SharedPreferences\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\u3002

    \u542F\u7528\u672C\u5730\u7F13\u5B58\u540E\uFF0C\u5C06\u540C\u65F6\u8BBE\u7F6E async = true\uFF0C\u4F60\u53EF\u4EE5\u4E0D\u9700\u8981\u518D\u624B\u52A8\u8FDB\u884C\u8BBE\u7F6E\u3002

    \u793A\u4F8B\u5982\u4E0B

    searchClass(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
    +}
    +

    \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

    // \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)
    +    }
    +}
    +

    \u4F60\u8FD8\u53EF\u4EE5\u6E05\u9664\u6307\u5B9A\u7248\u672C\u7684\u5BBF\u4E3B\u7F13\u5B58\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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

    \u5982\u679C\u4F60\u9700\u8981\u4F7F\u7528\u56FA\u5B9A\u7684\u6761\u4EF6\u540C\u65F6\u67E5\u627E\u4E00\u7EC4 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
    +    }
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ClassLoader.searchClass\u3001PackageParam.searchClass \u65B9\u6CD5\u3002

    Member \u6269\u5C55

    \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 Class\u3002

    \u793A\u4F8B\u5982\u4E0B

    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) {
    +        // ...
    +    }
    +}
    +

    \u67E5\u627E\u4E0E\u53CD\u5C04\u8C03\u7528

    \u5047\u8BBE\u6211\u4EEC\u8981\u5F97\u5230 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

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u8FD9\u79CD\u5199\u6CD5\u5927\u6982\u4E0D\u662F\u5F88\u53CB\u597D\uFF0C\u6B64\u65F6 YukiHookAPI \u5C31\u4E3A\u4F60\u63D0\u4F9B\u4E86\u4E00\u4E2A\u53EF\u5728\u4EFB\u610F\u5730\u65B9\u4F7F\u7528\u7684\u8BED\u6CD5\u7CD6\u3002

    \u4EE5\u4E0A\u5199\u6CD5\u6362\u505A YukiHookAPI \u53EF\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MethodFinder\u3002

    \u540C\u6837\u5730\uFF0C\u6211\u4EEC\u9700\u8981\u5F97\u5230 isTaskRunning \u53D8\u91CF\u4E5F\u53EF\u4EE5\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 FieldFinder\u3002

    \u4E5F\u8BB8\u4F60\u8FD8\u60F3\u5F97\u5230\u5F53\u524D Class \u7684\u6784\u9020\u65B9\u6CD5\uFF0C\u540C\u6837\u53EF\u4EE5\u5B9E\u73B0\u3002

    \u793A\u4F8B\u5982\u4E0B

    Test::class.java.constructor {
    +    param(BooleanType)
    +}.get().call(true) // \u53EF\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684\u5B9E\u4F8B
    +

    \u82E5\u60F3\u5F97\u5230\u7684\u662F Class \u7684\u65E0\u53C2\u6784\u9020\u65B9\u6CD5\uFF0C\u53EF\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    Test::class.java.constructor().get().call() // \u53EF\u521B\u5EFA\u4E00\u4E2A\u65B0\u7684\u5B9E\u4F8B
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 ConstructorFinder\u3002

    \u53EF\u9009\u7684\u67E5\u627E\u6761\u4EF6

    \u5047\u8BBE\u6211\u4EEC\u8981\u5F97\u5230 Class \u4E2D\u7684 getName \u65B9\u6CD5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5B9E\u73B0\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +

    \u901A\u8FC7\u89C2\u5BDF\u53D1\u73B0\uFF0C\u8FD9\u4E2A 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

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +

    \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 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\u3002

    \u95EE\u9898\u53C8\u6765\u4E86\uFF0C\u8FD9\u4E2A Class \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\u3002

    \u901A\u5E38\u60C5\u51B5\u4E0B\u6211\u4EEC\u4F1A\u4F7F\u7528 param(...) \u6765\u67E5\u627E\u8FD9\u4E2A\u65B9\u6CD5\uFF0C\u4F46\u662F\u6709\u6CA1\u6709\u66F4\u7B80\u5355\u7684\u65B9\u6CD5\u5462\u3002

    \u6B64\u65F6\uFF0C\u5728\u786E\u5B9A\u65B9\u6CD5\u552F\u4E00\u6027\u540E\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 paramCount \u6765\u67E5\u627E\u5230\u8FD9\u4E2A\u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +

    \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 VagueType \u6765\u586B\u5145\u4F60\u4E0D\u60F3\u586B\u5199\u7684\u65B9\u6CD5\u53C2\u6570\u7C7B\u578B\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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

    \u4F60\u4F1A\u6CE8\u610F\u5230 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\uFF1F

    \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 superClass \u5373\u53EF\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u5C31\u53EF\u4EE5\u5728\u7236\u7C7B\u4E2D\u53D6\u5230\u8FD9\u4E2A\u65B9\u6CD5\u4E86\u3002

    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\u3002

    \u7531\u4E8E\u6211\u4EEC\u73B0\u5728\u5DF2\u77E5 doBaseTask \u65B9\u6CD5\u53EA\u5B58\u5728\u4E8E\u7236\u7C7B\uFF0C\u53EF\u4EE5\u52A0\u4E0A\u8FD9\u4E2A\u6761\u4EF6\u8282\u7701\u67E5\u627E\u65F6\u95F4\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u540C\u6837\u53EF\u4EE5\u5F97\u5230\u7236\u7C7B\u4E2D\u7684\u8FD9\u4E2A\u65B9\u6CD5\u3002

    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

    \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

    \u6A21\u7CCA\u67E5\u627E

    \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 Class \u4E2D\u7684 doTask \u65B9\u6CD5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5B9E\u73B0\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u5DF2\u77E5\u5F53\u524D 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

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u6211\u4EEC\u8FD8\u53EF\u4EE5\u6839\u636E\u9996\u5C3E\u5B57\u7B26\u4E32\u8FDB\u884C\u5224\u65AD\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \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

    // \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")
    +

    \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

    \u591A\u91CD\u67E5\u627E

    \u6709\u4E9B\u65F6\u5019\uFF0C\u6211\u4EEC\u53EF\u80FD\u9700\u8981\u67E5\u627E\u4E00\u4E2A 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\u3002

    \u5728\u67E5\u627E\u6761\u4EF6\u7ED3\u679C\u7684\u57FA\u7840\u4E0A\uFF0C\u6211\u4EEC\u53EA\u9700\u8981\u628A get \u6362\u4E3A all \u5373\u53EF\u5F97\u5230\u5339\u914D\u6761\u4EF6\u7684\u5168\u90E8\u5B57\u8282\u7801\u3002

    \u5047\u8BBE\u8FD9\u6B21\u6211\u4EEC\u8981\u5F97\u5230 Class \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

    \u793A\u4F8B\u5982\u4E0B

    // \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(...)
    +}
    +

    \u4E0A\u8FF0\u793A\u4F8B\u53EF\u5B8C\u7F8E\u5339\u914D\u5230\u5982\u4E0B 3 \u4E2A\u65B9\u6CD5\u3002

    private void doTask(String taskName)

    private void release(String taskName, Function<boolean, String> task, boolean isFinish)

    private void b(String a)

    \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

    // \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(...)
    +}
    +

    \u4E0A\u8FF0\u793A\u4F8B\u53EF\u5B8C\u7F8E\u5339\u914D\u5230\u5982\u4E0B 6 \u4E2A\u65B9\u6CD5\u3002

    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)

    \u901A\u8FC7\u89C2\u5BDF Class \u4E2D\u6709\u4E24\u4E2A\u540D\u79F0\u4E3A b \u7684\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u5B9E\u73B0\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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(...)
    +}
    +

    \u4E0A\u8FF0\u793A\u4F8B\u53EF\u5B8C\u7F8E\u5339\u914D\u5230\u5982\u4E0B 2 \u4E2A\u65B9\u6CD5\u3002

    private void b()

    private void b(String a)

    \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

    \u9759\u6001\u5B57\u8282\u7801

    \u6709\u4E9B\u65B9\u6CD5\u548C\u53D8\u91CF\u5728 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\u3002

    \u5047\u8BBE\u6211\u4EEC\u8FD9\u6B21\u8981\u5F97\u5230\u9759\u6001\u53D8\u91CF TAG \u7684\u5185\u5BB9\u3002

    \u793A\u4F8B\u5982\u4E0B

    Test::class.java.field {
    +    name = "TAG"
    +    type = StringType
    +}.get().string() // Field \u7684\u7C7B\u578B\u662F\u5B57\u7B26\u4E32\uFF0C\u53EF\u76F4\u63A5\u8FDB\u884C cast
    +

    \u5047\u8BBE Class \u4E2D\u5B58\u5728\u540C\u540D\u7684\u975E\u9759\u6001 TAG \u53D8\u91CF\uFF0C\u8FD9\u4E2A\u65F6\u5019\u600E\u4E48\u529E\u5462\uFF1F

    \u52A0\u5165\u4E00\u4E2A\u7B5B\u9009\u6761\u4EF6\u5373\u53EF\u3002

    \u793A\u4F8B\u5982\u4E0B

    Test::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
    +

    \u6211\u4EEC\u8FD8\u53EF\u4EE5\u8C03\u7528\u540D\u4E3A init \u7684\u9759\u6001\u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    Test::class.java.method {
    +    name = "init"
    +    emptyParam()
    +}.get().call()
    +

    \u540C\u6837\u5730\uFF0C\u4F60\u53EF\u4EE5\u6807\u8BC6\u5B83\u662F\u4E00\u4E2A\u9759\u6001\u3002

    \u793A\u4F8B\u5982\u4E0B

    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()
    +

    \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

    \u6DF7\u6DC6\u7684\u5B57\u8282\u7801

    \u4F60\u53EF\u80FD\u5DF2\u7ECF\u6CE8\u610F\u5230\u4E86\uFF0C\u8FD9\u91CC\u7ED9\u51FA\u7684\u793A\u4F8B 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

    \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

    // \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
    +

    \u7B2C\u4E8C\u79CD\u65B9\u6848\uFF0C\u786E\u5B9A\u53D8\u91CF\u7684\u7C7B\u578B\u6240\u5728\u7684\u4F4D\u7F6E\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +

    \u4EE5\u4E0A\u4E24\u79CD\u60C5\u51B5\u5747\u53EF\u5F97\u5230\u5BF9\u5E94\u7684\u53D8\u91CF private boolean a\u3002

    \u540C\u6837\u5730\uFF0C\u8FD9\u4E2A Class \u4E2D\u4E5F\u6709\u4E24\u4E2A\u6DF7\u6DC6\u7684\u65B9\u6CD5\u540D\u79F0\uFF0C\u5B83\u4EEC\u90FD\u662F b\u3002

    \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

    // \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
    +

    \u7B2C\u4E8C\u79CD\u65B9\u6848\uFF0C\u786E\u5B9A\u65B9\u6CD5\u7684\u53C2\u6570\u6240\u5728\u7684\u4F4D\u7F6E\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +

    \u7531\u4E8E\u89C2\u5BDF\u5230\u8FD9\u4E2A\u65B9\u6CD5\u5728 Class \u7684\u6700\u540E\u4E00\u4E2A\uFF0C\u90A3\u6211\u4EEC\u8FD8\u6709\u4E00\u4E2A\u5907\u9009\u65B9\u6848\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +

    \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

    \u76F4\u63A5\u8C03\u7528

    \u4E0A\u9762\u4ECB\u7ECD\u7684\u8C03\u7528\u5B57\u8282\u7801\u7684\u65B9\u6CD5\u90FD\u9700\u8981\u4F7F\u7528 get(instance) \u624D\u80FD\u8C03\u7528\u5BF9\u5E94\u7684\u65B9\u6CD5\uFF0C\u6709\u6CA1\u6709\u7B80\u5355\u4E00\u70B9\u7684\u529E\u6CD5\u5462\uFF1F

    \u6B64\u65F6\uFF0C\u4F60\u53EF\u4EE5\u5728\u4EFB\u610F\u5B9E\u4F8B\u4E0A\u4F7F\u7528 current \u65B9\u6CD5\u6765\u521B\u5EFA\u4E00\u4E2A\u8C03\u7528\u7A7A\u95F4\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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()
    +}
    +

    \u6211\u4EEC\u8FD8\u53EF\u4EE5\u7528 superClass \u8C03\u7528\u5F53\u524D Class \u7236\u7C7B\u7684\u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +}
    +

    \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 current() \u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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()
    +

    \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

    // \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()
    +

    \u9488\u5BF9 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

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +}
    +

    \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

    Test(true).doTask("task_name")
    +

    \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

    "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")
    +    }
    +

    \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 buildOf \u65B9\u6CD5\u6765\u521B\u5EFA\u4E00\u4E2A\u5B9E\u4F8B\u3002

    \u793A\u4F8B\u5982\u4E0B

    "com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
    +    method {
    +        name = "doTask"
    +        param(StringType)
    +    }.call("task_name")
    +}
    +

    \u82E5\u4F60\u5E0C\u671B 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

    \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

    // \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")
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 CurrentClass \u4EE5\u53CA Class.buildOf \u65B9\u6CD5\u3002

    \u539F\u59CB\u8C03\u7528

    \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 XposedBridge \u4E3A\u6211\u4EEC\u63D0\u4F9B\u4E86\u4E00\u4E2A XposedBridge.invokeOriginalMethod \u529F\u80FD\u3002

    \u73B0\u5728\uFF0C\u5728 YukiHookAPI \u4E2D\u4F60\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u65B9\u6CD5\u4FBF\u6377\u5730\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002

    \u5047\u8BBE\u4E0B\u9762\u662F\u6211\u4EEC\u8981\u6F14\u793A\u7684 Class\u3002

    \u793A\u4F8B\u5982\u4E0B

    public class Test {
    +
    +    public static String getString() {
    +        return "Original";
    +    }
    +}
    +

    \u4E0B\u9762\u662F Hook \u8FD9\u4E2A Class \u4E2D getString \u65B9\u6CD5\u7684\u65B9\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    Test::class.java.hook {
    +    injectMember {
    +        method {
    +            name = "getString"
    +            emptyParam()
    +            returnType = StringType
    +        }
    +        replaceTo("Hooked")
    +    }
    +}
    +

    \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 "Hooked"\u3002

    \u793A\u4F8B\u5982\u4E0B

    // result \u7684\u7ED3\u679C\u4F1A\u662F "Hooked"
    +val result = Test::class.java.method {
    +    name = "getString"
    +    emptyParam()
    +    returnType = StringType
    +}.get().string()
    +

    \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 original \u5373\u53EF\u3002

    \u793A\u4F8B\u5982\u4E0B

    // result \u7684\u7ED3\u679C\u4F1A\u662F "Original"
    +val result = Test::class.java.method {
    +    name = "getString"
    +    emptyParam()
    +    returnType = StringType
    +}.get().original().string()
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 MethodFinder.Result.original \u65B9\u6CD5\u3002

    \u518D\u6B21\u67E5\u627E

    \u5047\u8BBE\u6709\u4E09\u4E2A\u4E0D\u540C\u7248\u672C\u7684 Class\uFF0C\u5B83\u4EEC\u90FD\u662F\u8FD9\u4E2A\u5BBF\u4E3B\u4E0D\u540C\u7248\u672C\u76F8\u540C\u7684 Class\u3002

    \u8FD9\u91CC\u9762\u540C\u6837\u90FD\u6709\u4E00\u4E2A\u65B9\u6CD5 doTask\uFF0C\u5047\u8BBE\u5B83\u4EEC\u7684\u529F\u80FD\u662F\u4E00\u6837\u7684\u3002

    \u7248\u672C A \u793A\u4F8B\u5982\u4E0B

    public class Test {
    +
    +    public void doTask() {
    +        // ...
    +    }
    +}
    +

    \u7248\u672C B \u793A\u4F8B\u5982\u4E0B

    public class Test {
    +
    +    public void doTask(String taskName) {
    +        // ...
    +    }
    +}
    +

    \u7248\u672C C \u793A\u4F8B\u5982\u4E0B

    public class Test {
    +
    +    public void doTask(String taskName, int type) {
    +        // ...
    +    }
    +}
    +

    \u6211\u4EEC\u9700\u8981\u5728\u4E0D\u540C\u7684\u7248\u672C\u4E2D\u5F97\u5230\u8FD9\u4E2A\u76F8\u540C\u529F\u80FD\u7684 doTask \u65B9\u6CD5\uFF0C\u8981\u600E\u4E48\u505A\u5462\uFF1F

    \u6B64\u65F6\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 RemedyPlan \u5B8C\u6210\u4F60\u7684\u9700\u6C42\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +}
    +

    \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 RemedyPlan\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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
    +}
    +

    \u4EE5\u5F53\u524D 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\u3002

    \u793A\u4F8B\u5982\u4E0B

    injectMember {
    +    method {
    +        name = "doTask"
    +        emptyParam()
    +    }.remedys {
    +        method {
    +            name = "doTask"
    +            paramCount(0..1)
    +        }
    +        method {
    +            name = "doTask"
    +            paramCount(1..2)
    +        }
    +    }.all()
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    \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

    \u76F8\u5BF9\u5339\u914D

    \u5047\u8BBE\u5BBF\u4E3B\u4E2D\u4E0D\u540C\u7248\u672C\u4E2D\u5B58\u5728\u529F\u80FD\u76F8\u540C\u7684 Class \u4F46\u4EC5\u6709 Class \u7684\u540D\u79F0\u4E0D\u4E00\u6837\u3002

    \u7248\u672C A \u793A\u4F8B\u5982\u4E0B

    public class ATest {
    +
    +    public static void doTask() {
    +        // ...
    +    }
    +}
    +

    \u7248\u672C B \u793A\u4F8B\u5982\u4E0B

    public class BTest {
    +
    +    public static void doTask() {
    +        // ...
    +    }
    +}
    +

    \u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u60F3\u5728\u6BCF\u4E2A\u7248\u672C\u90FD\u8C03\u7528\u8FD9\u4E2A Class \u91CC\u7684 doTask \u65B9\u6CD5\u8BE5\u600E\u4E48\u505A\u5462\uFF1F

    \u901A\u5E38\u505A\u6CD5\u662F\u5224\u65AD Class \u662F\u5426\u5B58\u5728\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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()
    +

    \u611F\u89C9\u8FD9\u79CD\u65B9\u6848\u975E\u5E38\u7684\u4E0D\u4F18\u96C5\u4E14\u7E41\u7410\uFF0C\u90A3\u4E48\u6B64\u65F6 YukiHookAPI \u5C31\u4E3A\u4F60\u63D0\u4F9B\u4E86\u4E00\u4E2A\u975E\u5E38\u65B9\u4FBF\u7684 VariousClass \u4E13\u95E8\u6765\u89E3\u51B3\u8FD9\u4E2A\u95EE\u9898\u3002

    \u73B0\u5728\uFF0C\u4F60\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528\u4EE5\u4E0B\u65B9\u5F0F\u83B7\u53D6\u5230\u8FD9\u4E2A Class\u3002

    \u793A\u4F8B\u5982\u4E0B

    VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
    +    name = "doTask"
    +    emptyParam()
    +}.get().call()
    +

    \u82E5\u5F53\u524D Class \u5728\u6307\u5B9A\u7684 ClassLoader \u4E2D\u5B58\u5728\uFF0C\u4F60\u53EF\u4EE5\u5728 get \u4E2D\u586B\u5165\u4F60\u7684 ClassLoader\u3002

    \u793A\u4F8B\u5982\u4E0B

    val 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()
    +

    \u82E5\u4F60\u4E0D\u786E\u5B9A\u6240\u6709\u7684 Class \u4E00\u5B9A\u4F1A\u88AB\u5339\u914D\u5230\uFF0C\u4F60\u53EF\u4EE5\u4F7F\u7528 getOrNull \u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    val 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()
    +

    \u82E5\u4F60\u6B63\u5728 PackageParam \u4E2D\u64CD\u4F5C (Xposed) \u5BBF\u4E3B\u73AF\u5883\u7684 Class\uFF0C\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 toClass() \u8FDB\u884C\u8BBE\u7F6E\u3002

    \u793A\u4F8B\u5982\u4E0B

    VariousClass("com.demo.ATest", "com.demo.BTest").toClass().method {
    +    name = "doTask"
    +    emptyParam()
    +}.get().call()
    +

    \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 Class \u7684\u5F02\u5E38\u3002

    \u793A\u4F8B\u5982\u4E0B

    findClass("com.demo.ATest", "com.demo.BTest").hook {
    +    // Your code here.
    +}
    +

    \u4F60\u8FD8\u53EF\u4EE5\u628A\u8FD9\u4E2A Class \u5B9A\u4E49\u4E3A\u4E00\u4E2A\u5E38\u91CF\u7C7B\u578B\u6765\u4F7F\u7528\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \u5B9A\u4E49\u5E38\u91CF\u7C7B\u578B
    +val ABTestClass = VariousClass("com.demo.ATest", "com.demo.BTest")
    +// \u76F4\u63A5\u4F7F\u7528
    +ABTestClass.hook {
    +    // Your code here.
    +}
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 PackageParam.findClass \u65B9\u6CD5\u3002

    \u8C03\u7528\u6CDB\u578B

    \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\uFF0CYukiHookAPI \u540C\u6837\u63D0\u4F9B\u4E86\u4E00\u4E2A\u53EF\u5728\u4EFB\u610F\u5730\u65B9\u4F7F\u7528\u7684\u8BED\u6CD5\u7CD6\u3002

    \u4F8B\u5982\u6211\u4EEC\u6709\u5982\u4E0B\u7684\u6CDB\u578B\u7C7B\u3002

    \u793A\u4F8B\u5982\u4E0B

    class TestGeneric<T, R> (t: T, r: R) {
    +
    +    fun foo() {
    +        // ...
    +    }
    +}
    +

    \u5F53\u6211\u4EEC\u60F3\u5728\u5F53\u524D Class \u4E2D\u83B7\u5F97\u6CDB\u578B T \u6216 R \u7684 Class \u5B9E\u4F8B\uFF0C\u53EA\u9700\u8981\u5982\u4E0B\u5B9E\u73B0\u3002

    \u793A\u4F8B\u5982\u4E0B

    class 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)
    +        }
    +    }
    +}
    +

    \u5F53\u6211\u4EEC\u60F3\u5728\u5916\u90E8\u8C03\u7528\u8FD9\u4E2A Class \u65F6\uFF0C\u5C31\u53EF\u4EE5\u6709\u5982\u4E0B\u5B9E\u73B0\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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>()
    +

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 CurrentClass.generic\u3001Class.generic \u65B9\u6CD5\u4EE5\u53CA GenericClass\u3002

    \u6CE8\u610F\u8BEF\u533A

    \u8FD9\u91CC\u5217\u4E3E\u4E86\u4F7F\u7528\u65F6\u53EF\u80FD\u4F1A\u9047\u5230\u7684\u8BEF\u533A\u90E8\u5206\uFF0C\u53EF\u4F9B\u53C2\u8003\u3002

    \u9650\u5236\u6027\u67E5\u627E\u6761\u4EF6

    \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

    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)
    +}
    +

    \u4EE5\u4E0B\u67E5\u627E\u6761\u4EF6\u7684\u4F7F\u7528\u662F\u6CA1\u6709\u4EFB\u4F55\u95EE\u9898\u7684\u3002

    \u793A\u4F8B\u5982\u4E0B

    method {
    +    name = "test"
    +    param(BooleanType).index(num = 2)
    +    order().index(num = 1)
    +}
    +

    \u5FC5\u8981\u7684\u67E5\u627E\u6761\u4EF6

    \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 Class\u3002

    \u793A\u4F8B\u5982\u4E0B

    public class TestFoo {
    +
    +    public void foo(String string) {
    +        // ...
    +    }
    +
    +    public void foo() {
    +        // ...
    +    }
    +}
    +

    \u6211\u4EEC\u8981\u5F97\u5230\u5176\u4E2D\u7684 public void foo() \u65B9\u6CD5\uFF0C\u53EF\u4EE5\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    TestFoo::class.java.method {
    +    name = "foo"
    +}
    +

    \u4F46\u662F\uFF0C\u4E0A\u9762\u7684\u4F8B\u5B50\u662F\u9519\u8BEF\u7684\u3002

    \u4F60\u4F1A\u53D1\u73B0\u8FD9\u4E2A Class \u4E2D\u6709\u4E24\u4E2A foo \u65B9\u6CD5\uFF0C\u5176\u4E2D\u4E00\u4E2A\u5E26\u6709\u65B9\u6CD5\u53C2\u6570\u3002

    \u7531\u4E8E\u4E0A\u8FF0\u4F8B\u5B50\u6CA1\u6709\u8BBE\u7F6E param \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\u3002

    \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

    TestFoo::class.java.method {
    +    name = "foo"
    +    // \u2705 \u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\uFF0C\u6DFB\u52A0\u8BE6\u7EC6\u7684\u7B5B\u9009\u6761\u4EF6
    +    emptyParam()
    +}
    +

    \u81F3\u6B64\uFF0C\u4E0A\u8FF0\u7684\u793A\u4F8B\u5C06\u53EF\u4EE5\u5B8C\u7F8E\u5730\u5339\u914D\u5230 public void foo() \u65B9\u6CD5\u3002

    \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

    \u53EF\u7B80\u5199\u67E5\u627E\u6761\u4EF6

    \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 Class\u3002

    \u793A\u4F8B\u5982\u4E0B

    public class TestFoo {
    +
    +    public TestFoo() {
    +        // ...
    +    }
    +}
    +

    \u6211\u4EEC\u8981\u5F97\u5230\u5176\u4E2D\u7684 public TestFoo() \u6784\u9020\u65B9\u6CD5\uFF0C\u53EF\u4EE5\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u3002

    \u793A\u4F8B\u5982\u4E0B

    TestFoo::class.java.constructor { emptyParam() }
    +

    \u4E0A\u9762\u7684\u4F8B\u5B50\u53EF\u4EE5\u6210\u529F\u83B7\u53D6\u5230 public TestFoo() \u6784\u9020\u65B9\u6CD5\uFF0C\u4F46\u662F\u611F\u89C9\u6709\u4E00\u4E9B\u7E41\u7410\u3002

    \u4E0E\u666E\u901A\u65B9\u6CD5\u4E0D\u540C\uFF0C\u7531\u4E8E\u6784\u9020\u65B9\u6CD5\u4E0D\u9700\u8981\u8003\u8651 name \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\u3002

    \u793A\u4F8B\u5982\u4E0B

    TestFoo::class.java.constructor()
    +

    \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

    \u5B57\u8282\u7801\u7C7B\u578B

    \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 Boolean \u7C7B\u578B\u7684\u53D8\u91CF\uFF0C\u628A\u4ED6\u8F6C\u6362\u4E3A String\u3002

    \u4EE5\u4E0B\u662F\u9519\u8BEF\u7684\u4F7F\u7528\u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    field {
    +    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
    +

    \u4EE5\u4E0B\u662F\u6B63\u786E\u7684\u4F7F\u7528\u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    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

    \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

    field {
    +    name = "test"
    +    type = Boolean::class.java
    +}
    +

    \u5728 Kotlin \u4E2D\u8868\u8FBE\u51FA Boolean::class.java \u8FD9\u4E2A\u7C7B\u578B\u7684\u5199\u6CD5\u5F88\u957F\uFF0C\u611F\u89C9\u5E76\u4E0D\u65B9\u4FBF\u3002

    \u56E0\u6B64\uFF0CYukiHookAPI \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\u3002

    \u8FD9\u4E2A\u65F6\u5019\u4E0A\u9762\u7684\u7C7B\u578B\u5C31\u53EF\u4EE5\u5199\u4F5C\u5982\u4E0B\u5F62\u5F0F\u4E86\u3002

    \u793A\u4F8B\u5982\u4E0B

    field {
    +    name = "test"
    +    type = BooleanType
    +}
    +

    \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 IntType\u3001FloatType\u3002

    \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 String[] \u7C7B\u578B\u7684\u6570\u7EC4\u3002

    \u9700\u8981\u5199\u505A java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass \u624D\u80FD\u5F97\u5230\u8FD9\u4E2A\u7C7B\u578B\u3002

    \u611F\u89C9\u662F\u4E0D\u662F\u5F88\u9EBB\u70E6\uFF0C\u8FD9\u4E2A\u65F6\u5019\u6211\u4EEC\u53EF\u4EE5\u4F7F\u7528\u6269\u5C55\u65B9\u6CD5 ArrayClass(StringType) \u6765\u5F97\u5230\u8FD9\u4E2A\u7C7B\u578B\u3002

    \u540C\u65F6\u7531\u4E8E String \u662F\u5E38\u89C1\u7C7B\u578B\uFF0C\u6240\u4EE5\u8FD8\u53EF\u4EE5\u76F4\u63A5\u4F7F\u7528 StringArrayClass \u6765\u5F97\u5230\u8FD9\u4E2A\u7C7B\u578B\u3002

    \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 onCreate \u65B9\u6CD5\u9700\u8981\u67E5\u627E Bundle::class.java \u7C7B\u578B\u3002

    \u793A\u4F8B\u5982\u4E0B

    method {
    +    name = "onCreate"
    +    param(BundleClass)
    +}
    +

    \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

    `,358);function v(C,D){const a=e("Badge");return p(),o("div",null,[t,s("h3",d,[A,y,c(a,{type:"tip",text:"Beta",vertical:"middle"})]),u])}const m=l(i,[["render",v],["__file","reflection.html.vue"]]);export{m as default}; diff --git a/docs/assets/reflection.html.37e12a3d.js b/docs/assets/reflection.html.37e12a3d.js new file mode 100644 index 00000000..331ec8d7 --- /dev/null +++ b/docs/assets/reflection.html.37e12a3d.js @@ -0,0 +1,838 @@ +import{_ as e,r as l,o,c as p,b as s,d as t,a as n,e as c}from"./app.fb8271cf.js";const i={},r=n(`

    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

    Here are the extension functions related to the Class object itself.

    Object Conversion

    Suppose we want to get a Class that cannot be called directly.

    Normally, we can use the standard reflection API to find this Class.

    The following example

    // 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")
    +

    This is probably not very friendly, and YukiHookAPI provides you with a syntactic sugar that can be used anywhere.

    The above writing can be written as YukiHookAPI as follows.

    The following example

    // 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)
    +

    If the current Class does not exist, using the above method will throw an exception.

    If you are not sure whether the Class exists, you can refer to the following solutions.

    The following example

    // 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)
    +

    We can also get an existing Class object by mapping.

    The following example

    // 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

    Suppose we want to determine whether a Class exists.

    Usually, we can use the standard reflection API to find this Class to determine whether it exists by exception.

    The following example

    // 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
    +}
    +

    This is probably not very friendly, and YukiHookAPI provides you with a syntactic sugar that can be used anywhere.

    The above writing can be written as YukiHookAPI as follows.

    The following example

    // 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)
    +

    Tips

    For more functions, please refer to String.hasClass, PackageParam \u2192 String.hasClass methods.

    `,31),d={id:"vague-search",tabindex:"-1"},y=s("a",{class:"header-anchor",href:"#vague-search","aria-hidden":"true"},"#",-1),A=c(" Vague Search\u2002"),u=n(`

    The Class name in the Host App's Dex after being obfuscated by tools such as R8 will be difficult to distinguish.

    Its correct position is uncertain, and cannot be obtained directly through Object Conversion.

    At this point, there is DexClassFinder, its role is to determine the instance of this Class by the bytecode features in the Class that need to be searched.

    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.

    Get Started

    Below is a simple usage example.

    Suppose the following Class is what we want, the names are obfuscated and may be different in each version.

    The following example

    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) {
    +        // ...
    +    }
    +}
    +

    At this point, we want to get this Class, you can use the ClassLoader.searchClass method directly.

    In PackageParam you can use the searchClass method directly and it will automatically specify the appClassLoader.

    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

    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
    +

    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, DexClassFinder will use synchronous mode to search Class, which will block the current thread until it finds or finds an exception.

    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 async = true, which will not require you to start a thread again, the API has already handled the related problems for you.

    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

    searchClass(async = true) {
    +    // ...
    +}.wait { class1 ->
    +    // Get asynchronous result
    +}
    +searchClass(async = true) {
    +    // ...
    +}.wait { class2 ->
    +    // Get asynchronous result
    +}
    +

    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.

    Local Cache

    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 name parameter.

    Next time, the found class name will be directly read from the local cache.

    The local cache uses 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.

    After enabling the local cache, async = true will be set at the same time, you don't need to set it manually.

    The following example

    searchClass(name = "com.demo.class1") {
    +    // ...
    +}.wait { class1 ->
    +    // Get asynchronous result
    +}
    +searchClass(name = "com.demo.class2") {
    +    // ...
    +}.wait { class2 ->
    +    // Get asynchronous result
    +}
    +

    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

    // 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)
    +    }
    +}
    +

    You can also clear the Host App's cache for a specific version.

    The following example

    // 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)
    +    }
    +}
    +

    If you need to search a set of 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
    +    }
    +}
    +

    Tips

    For more functions, please refer to ClassLoader.searchClass, PackageParam.searchClass methods.

    Member Extensions

    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 Class.

    The following example

    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

    Suppose we want to get the doTask method of Test and execute it.

    Normally, we can use the standard reflection API to find this method.

    The following example

    // 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")
    +

    This is probably not very friendly, and YukiHookAPI provides you with a syntactic sugar that can be used anywhere.

    The above writing can be written as YukiHookAPI as follows.

    The following example

    // 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")
    +

    Tips

    For more features, please refer to MethodFinder.

    Similarly, we need to get the isTaskRunning field can also be written as follows.

    The following example

    // 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
    +

    Tips

    For more features, please refer to FieldFinder.

    Maybe you also want to get the current Class constructor, the same can be achieved.

    The following example

    Test::class.java.constructor {
    +    param(BooleanType)
    +}.get().call(true) // Can create a new instance
    +

    If you want to get the no-argument constructor of Class, you can write it as follows.

    The following example

    Test::class.java.constructor().get().call() // Create a new instance
    +

    Tips

    For more features, please refer to ConstructorFinder.

    Optional Find Conditions

    Suppose we want to get the getName method in Class, which can be implemented as follows.

    The following example

    // 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
    +

    Through observation, it is found that there is only one method named getName in this Class, so can we make it simpler?

    The following example

    // 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
    +

    Yes, you can refine your find criteria for methods that do not change exactly.

    When using only get or wait methods to get results, YukiHookAPI will match the first found result in bytecode order by default.

    The problem comes again, this Class has a release method, but its method parameters are very long, and some types may not be directly available.

    Normally we would use param(...) to find this method, but is there an easier way.

    At this point, after determining the uniqueness of the method, you can use paramCount to find the method.

    The following example

    // 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
    +

    Although the above example can be successfully matched, it is not accurate.

    At this time, you can also use VagueType to fill in the method parameter type that you do not want to fill in.

    The following example

    // 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

    You will notice that 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?

    Referring to the above find conditions, we only need to add a superClass to the find conditions to achieve this function.

    The following example

    // 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")
    +

    At this time, we can get this method in the super class.

    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.

    Since we now know that the doBaseTask method only exists in the super class, this condition can be added to save finding time.

    The following example

    // 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")
    +

    At this time, we can also get this method in the super class.

    Once 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).

    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.

    Vague Find

    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 doTask method in Class, which can be implemented as follows.

    The following example

    // 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")
    +

    Knowing that there is currently only one doTask method in Class, we can also judge that the method name contains only the characters specified in it.

    The following example

    // 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")
    +

    We can also judge based on the first and last strings.

    The following example

    // 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")
    +

    By observing that this method name contains only letters, we can add a precise search condition.

    The following example

    // 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")
    +

    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.

    Multiple Find

    Sometimes, we may need to find a set of methods, constructors, and fields with the same characteristics in a Class.

    At this time, we can use relative condition matching to complete.

    Based on the result of the find condition, we only need to replace get with all to get all the bytecodes that match the condition.

    Suppose this time we want to get all methods in Class with the number of method parameters in the range 1..3, you can use the following implementation.

    The following example

    // 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(...)
    +}
    +

    The above example can be perfectly matched to the following 3 methods.

    private void doTask(String taskName)

    private void release(String taskName, Function<boolean, String> task, boolean isFinish)

    private void b(String a)

    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

    // 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(...)
    +}
    +

    The above example can be perfectly matched to the following 6 methods.

    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)

    By observing that there are two methods named b in Class, you can use the following implementation.

    The following example

    // 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(...)
    +}
    +

    The above example can be perfectly matched to the following 2 methods.

    private void b()

    private void b(String a)

    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.

    Static Bytecode

    Some methods and fields are statically implemented in Class, at this time, we can call them without passing in an instance.

    Suppose we want to get the contents of the static field TAG this time.

    The following example

    Test::class.java.field {
    +    name = "TAG"
    +    type = StringType
    +}.get().string() // The type of Field is string and can be cast directly
    +

    Assuming that there is a non-static TAG field with the same name in Class, what should I do at this time?

    Just add a filter.

    The following example

    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
    +

    We can also call a static method called init.

    The following example

    Test::class.java.method {
    +    name = "init"
    +    emptyParam()
    +}.get().call()
    +

    Likewise, you can identify it as a static.

    The following example

    Test::class.java.method {
    +    name = "init"
    +    emptyParam()
    +    // This method of identity find needs to be static
    +    modifiers { isStatic }
    +}.get().call()
    +

    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.

    Obfuscated Bytecode

    You may have noticed that the example Class given here has two obfuscated field names, both of which are a, how do we get them at this time?

    There are two options.

    The first option is to determine the name and type of the field.

    The following example

    // 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
    +

    The second option is to determine where the type of the field is located.

    The following example

    // 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
    +

    In the above two cases, the corresponding field private boolean a can be obtained.

    Likewise, there are two obfuscated method names in this Class, both of which are b.

    You can also have two options to get them.

    The first option is to determine the method name and method parameters.

    The following example

    // 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]
    +

    The second option is to determine where the parameters of the method are located.

    The following example

    // 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]
    +

    Since it is observed that this method is last in Class, then we have an alternative.

    The following example

    // 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
    +

    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.

    Directly Called

    The methods of calling bytecode described above all need to use get(instance) to call the corresponding method.

    Is there a simpler way?

    At this point, you can use the current method on any instance to create a call space.

    The following example

    // 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()
    +}
    +

    We can also use superClass to call methods of the current Class super class.

    The following example

    // 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")
    +}
    +

    If you don't like to use a lambda to create the namespace of the current instance, you can use the current() method directly.

    The following example

    // 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()
    +

    Likewise, consecutive calls can be made between them, but inline calls are not allowed.

    The following example

    // 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()
    +

    For Field instances, there is also a convenience method that can directly get the object of the instance where Field is located.

    The following example

    // 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")
    +}
    +

    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

    Test(true).doTask("task_name")
    +

    Usually, we can use the standard reflection API to call.

    The following example

    "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")
    +    }
    +

    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 buildOf method to create an instance.

    The following example

    "com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
    +    method {
    +        name = "doTask"
    +        param(StringType)
    +    }.call("task_name")
    +}
    +

    If you want the 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.

    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

    // Assume this Class can be obtained directly
    +val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
    +test.doTask("task_name")
    +

    Tips

    For more functions, please refer to CurrentClass and Class.buildOf method.

    Original Called

    If you are using reflection to call a method that has been hooked, how do we call its original method?

    The native XposedBridge provides us with a XposedBridge.invokeOriginalMethod function.

    Now, in YukiHookAPI you can use the following method to implement this function conveniently.

    Suppose below is the Class we want to demonstrate.

    The following example

    public class Test {
    +
    +    public static String getString() {
    +        return "Original";
    +    }
    +}
    +

    Here's how the getString method in this Class Hooks.

    The following example

    Test::class.java.hook {
    +    injectMember {
    +        method {
    +            name = "getString"
    +            emptyParam()
    +            returnType = StringType
    +        }
    +        replaceTo("Hooked")
    +    }
    +}
    +

    At this point, we use reflection to call this method, and we will get the result of Hook "Hooked".

    The following example

    // Result will be "Hooked"
    +val result = Test::class.java.method {
    +    name = "getString"
    +    emptyParam()
    +    returnType = StringType
    +}.get().string()
    +

    If we want to get the original method and result of this method without hooking, we just need to add original to the result.

    The following example

    // Result will be "Original"
    +val result = Test::class.java.method {
    +    name = "getString"
    +    emptyParam()
    +    returnType = StringType
    +}.get().original().string()
    +

    Tips

    For more functions, please refer to the MethodFinder.Result.original method.

    Find Again

    Suppose there are three different versions of Class, all of which are the same Class for different versions of this Host App.

    There is also a method doTask in it, assuming they function the same.

    The following example of version A

    public class Test {
    +
    +    public void doTask() {
    +        // ...
    +    }
    +}
    +

    The following example of version B

    public class Test {
    +
    +    public void doTask(String taskName) {
    +        // ...
    +    }
    +}
    +

    The following example of version C

    public class Test {
    +
    +    public void doTask(String taskName, int type) {
    +        // ...
    +    }
    +}
    +

    We need to get this same functionality of the doTask method in a different version, how do we do it?

    At this point, you can use RemedyPlan to complete your needs.

    The following example

    // 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
    +}
    +

    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 RemedyPlan while using Multiple Find.

    The following example

    // 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
    +}
    +

    Take the current Class as an example, if Multiple Find is used in conjunction with RemedyPlan when creating a Hook, you need to change the usage slightly.

    The following example

    injectMember {
    +    method {
    +        name = "doTask"
    +        emptyParam()
    +    }.remedys {
    +        method {
    +            name = "doTask"
    +            paramCount(0..1)
    +        }
    +        method {
    +            name = "doTask"
    +            paramCount(1..2)
    +        }
    +    }.all()
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    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 .

    Relative Matching

    Suppose there is a Class with the same function in different versions of the Host App but only the name of the Class is different.

    The following example of version A

    public class ATest {
    +
    +    public static void doTask() {
    +        // ...
    +    }
    +}
    +

    The following example of version B

    public class BTest {
    +
    +    public static void doTask() {
    +        // ...
    +    }
    +}
    +

    At this time, what should we do if we want to call the doTask method in this Class in each version?

    The usual practice is to check if Class exists.

    The following example

    // 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()
    +

    I feel that this solution is very inelegant and cumbersome, then YukiHookAPI provides you with a very convenient VariousClass to solve this problem.

    Now, you can get this Class directly using the following methods.

    The following example

    VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
    +    name = "doTask"
    +    emptyParam()
    +}.get().call()
    +

    If the current Class exists in the specified ClassLoader, you can fill in your ClassLoader in get.

    The following example

    val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
    +VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
    +    name = "doTask"
    +    emptyParam()
    +}.get().call()
    +

    If you are not sure that all Class will be matched, you can use the getOrNull method.

    The following example

    val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
    +VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
    +     name = "doTask"
    +     emptyParam()
    +}?.get()?.call()
    +

    If you are using the Class of the (Xposed) Host environment in PackageParam, you can use toClass() to set it directly.

    The following example

    VariousClass("com.demo.ATest", "com.demo.BTest").toClass().method {
    +    name = "doTask"
    +    emptyParam()
    +}.get().call()
    +

    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 Class cannot be found.

    The following example

    findClass("com.demo.ATest", "com.demo.BTest").hook {
    +    // Your code here.
    +}
    +

    You can also define this Class as a constant type to use.

    The following example

    // Define constant type
    +val ABTestClass = VariousClass("com.demo.ATest", "com.demo.BTest")
    +// Use directly
    +ABTestClass.hook {
    +    // Your code here.
    +}
    +

    Tips

    For more functions, please refer to the PackageParam.findClass method.

    Calling Generics

    In the process of reflection, we may encounter generic problems.

    In the reflection processing of generics, YukiHookAPI also provides a syntactic sugar that can be used anywhere.

    For example we have the following generic class.

    The following example

    class TestGeneric<T, R> (t: T, r: R) {
    +
    +    fun foo() {
    +        // ...
    +    }
    +}
    +

    When we want to get a Class instance of the generic T or R in the current Class, only the following implementation is required.

    The following example

    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)
    +        }
    +    }
    +}
    +

    When we want to call this Class externally, it can be implemented as follows.

    The following example

    // 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>()
    +

    Tips

    For more functions, please refer to CurrentClass.generic, Class.generic methods and GenericClass.

    Pay Attention of Trap

    Here are some misunderstandings that may be encountered during use for reference.

    Restrictive Find Conditions

    Pay Attention

    In find conditions you can only use index function once except order.

    The following example

    method {
    +    name = "test"
    +    param(BooleanType).index(num = 2)
    +    // \u2757 Wrong usage, please keep only one index method
    +    returnType(StringType).index(num = 1)
    +}
    +

    The following find conditions can be used without any problems.

    The following example

    method {
    +    name = "test"
    +    param(BooleanType).index(num = 2)
    +    order().index(num = 1)
    +}
    +

    Necessary Find Conditions

    Pay Attention

    In common method find conditions, even methods without parameters need to set find conditions.

    Suppose we have the following Class.

    The following example

    public class TestFoo {
    +
    +    public void foo(String string) {
    +        // ...
    +    }
    +
    +    public void foo() {
    +        // ...
    +    }
    +}
    +

    We want to get the public void foo() method, which can be written as follows.

    The following example

    TestFoo::class.java.method {
    +    name = "foo"
    +}
    +

    However, the above example is wrong.

    You will find two foo methods in this Class, one of which takes a method parameter.

    Since the above example does not set the find conditions for 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.

    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

    TestFoo::class.java.method {
    +    name = "foo"
    +    // \u2705 Correct usage, add detailed filter conditions
    +    emptyParam()
    +}
    +

    At this point, the above example will perfectly match the public void foo() method.

    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.

    Abbreviated Find Conditions

    In the construction method find conditions, constructors without parameters do not need to fill in the find conditions.

    Suppose we have the following Class.

    The following example

    public class TestFoo {
    +
    +    public TestFoo() {
    +        // ...
    +    }
    +}
    +

    We want to get the public TestFoo() constructor, which can be written as follows.

    The following example

    TestFoo::class.java.constructor { emptyParam() }
    +

    The above example can successfully obtain the public TestFoo() constructor, but it feels a bit cumbersome.

    Unlike normal methods, since the constructor does not need to consider the name, when the constructor has no parameters, we can omit the emptyParam parameter.

    The following example

    TestFoo::class.java.constructor()
    +

    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.

    Bytecode Type

    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 Boolean and cast it to String.

    The following is the wrong way to use it.

    The following example

    field {
    +    name = "test"
    +    type = BooleanType
    +}.get().string() // \u2757 Wrong usage, must be cast to the bytecode target type
    +

    The following is the correct way to use it.

    The following example

    field {
    +    name = "test"
    +    type = BooleanType
    +}.get().boolean().toString() // \u2705 The correct way to use, get the type and then convert
    +

    Common Type Extensions

    When find methods and fields, we usually need to specify the type in find conditions.

    The following example

    field {
    +    name = "test"
    +    type = Boolean::class.java
    +}
    +

    Expressing the type Boolean::class.java in Kotlin is very long and not convenient.

    Therefore, YukiHookAPI encapsulates common type calls for developers, including Android's basic types and Java's basic types.

    At this time, the above type can be written in the following form.

    The following example

    field {
    +    name = "test"
    +    type = BooleanType
    +}
    +

    Common basic types in Java have been encapsulated as Name + Type, such as IntType, FloatType.

    Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type String[].

    You need to write java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass to get this type.

    Does it feel very troublesome? At this time, we can use the extension method ArrayClass(StringType) to get this type.

    At the same time, since String is a common type, you can also directly use StringArrayClass to get this type.

    Some common methods found in Hook have their corresponding encapsulation types for use, in the format Name + Class.

    For example, the Hook onCreate method needs to find the Bundle::class.java type.

    The following example

    method {
    +    name = "onCreate"
    +    param(BundleClass)
    +}
    +

    At the same time, you are welcome to contribute more commonly used types.

    `,367);function m(v,h){const a=l("Badge");return o(),p("div",null,[r,s("h3",d,[y,A,t(a,{type:"tip",text:"Beta",vertical:"middle"})]),u])}const D=e(i,[["render",m],["__file","reflection.html.vue"]]);export{D as default}; diff --git a/docs/assets/reflection.html.ff24950f.js b/docs/assets/reflection.html.ff24950f.js new file mode 100644 index 00000000..7373d71f --- /dev/null +++ b/docs/assets/reflection.html.ff24950f.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-581ddb9c","path":"/en/api/special-features/reflection.html","title":"Reflection Extensions","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Class Extensions","slug":"class-extensions","link":"#class-extensions","children":[{"level":3,"title":"Object Conversion","slug":"object-conversion","link":"#object-conversion","children":[]},{"level":3,"title":"Existential Judgment","slug":"existential-judgment","link":"#existential-judgment","children":[]},{"level":3,"title":"Vague Search","slug":"vague-search","link":"#vague-search","children":[]}]},{"level":2,"title":"Member Extensions","slug":"member-extensions","link":"#member-extensions","children":[{"level":3,"title":"Find and Reflection","slug":"find-and-reflection","link":"#find-and-reflection","children":[]},{"level":3,"title":"Optional Find Conditions","slug":"optional-find-conditions","link":"#optional-find-conditions","children":[]},{"level":3,"title":"Find in Super Class","slug":"find-in-super-class","link":"#find-in-super-class","children":[]},{"level":3,"title":"Vague Find","slug":"vague-find","link":"#vague-find","children":[]},{"level":3,"title":"Multiple Find","slug":"multiple-find","link":"#multiple-find","children":[]},{"level":3,"title":"Static Bytecode","slug":"static-bytecode","link":"#static-bytecode","children":[]},{"level":3,"title":"Obfuscated Bytecode","slug":"obfuscated-bytecode","link":"#obfuscated-bytecode","children":[]},{"level":3,"title":"Directly Called","slug":"directly-called","link":"#directly-called","children":[]},{"level":3,"title":"Original Called","slug":"original-called","link":"#original-called","children":[]},{"level":3,"title":"Find Again","slug":"find-again","link":"#find-again","children":[]},{"level":3,"title":"Relative Matching","slug":"relative-matching","link":"#relative-matching","children":[]},{"level":3,"title":"Calling Generics","slug":"calling-generics","link":"#calling-generics","children":[]},{"level":3,"title":"Pay Attention of Trap","slug":"pay-attention-of-trap","link":"#pay-attention-of-trap","children":[]}]},{"level":2,"title":"Common Type Extensions","slug":"common-type-extensions","link":"#common-type-extensions","children":[]}],"git":{"updatedTime":1664281530000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/special-features/reflection.md"}');export{e as data}; diff --git a/docs/assets/search.0782d0d1.svg b/docs/assets/search.0782d0d1.svg new file mode 100644 index 00000000..03d83913 --- /dev/null +++ b/docs/assets/search.0782d0d1.svg @@ -0,0 +1 @@ + diff --git a/docs/assets/style.e115708c.css b/docs/assets/style.e115708c.css new file mode 100644 index 00000000..150d2eab --- /dev/null +++ b/docs/assets/style.e115708c.css @@ -0,0 +1 @@ +:root{--back-to-top-z-index: 5;--back-to-top-color: #3eaf7c;--back-to-top-color-hover: #71cda3}.back-to-top{cursor:pointer;position:fixed;bottom:2rem;right:2.5rem;width:2rem;height:1.2rem;background-color:var(--back-to-top-color);-webkit-mask:url(/YukiHookAPI/assets/back-to-top.8efcbe56.svg) no-repeat;mask:url(/YukiHookAPI/assets/back-to-top.8efcbe56.svg) no-repeat;z-index:var(--back-to-top-z-index)}.back-to-top:hover{background-color:var(--back-to-top-color-hover)}@media (max-width: 959px){.back-to-top{display:none}}.back-to-top-enter-active,.back-to-top-leave-active{transition:opacity .3s}.back-to-top-enter-from,.back-to-top-leave-to{opacity:0}:root{--external-link-icon-color: #aaa}.external-link-icon{position:relative;display:inline-block;color:var(--external-link-icon-color);vertical-align:middle;top:-1px}.external-link-icon-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}:root{--medium-zoom-z-index: 100;--medium-zoom-bg-color: #ffffff;--medium-zoom-opacity: 1}.medium-zoom-overlay{background-color:var(--medium-zoom-bg-color)!important;z-index:var(--medium-zoom-z-index)}.medium-zoom-overlay~img{z-index:calc(var(--medium-zoom-z-index) + 1)}.medium-zoom--opened .medium-zoom-overlay{opacity:var(--medium-zoom-opacity)}:root{--nprogress-color: #29d;--nprogress-z-index: 1031}#nprogress{pointer-events:none}#nprogress .bar{background:var(--nprogress-color);position:fixed;z-index:var(--nprogress-z-index);top:0;left:0;width:100%;height:2px}:root{--c-brand: #3eaf7c;--c-brand-light: #4abf8a;--c-bg: #ffffff;--c-bg-light: #f3f4f5;--c-bg-lighter: #eeeeee;--c-bg-navbar: var(--c-bg);--c-bg-sidebar: var(--c-bg);--c-bg-arrow: #cccccc;--c-text: #2c3e50;--c-text-accent: var(--c-brand);--c-text-light: #3a5169;--c-text-lighter: #4e6e8e;--c-text-lightest: #6a8bad;--c-text-quote: #999999;--c-border: #eaecef;--c-border-dark: #dfe2e5;--c-tip: #42b983;--c-tip-bg: var(--c-bg-light);--c-tip-title: var(--c-text);--c-tip-text: var(--c-text);--c-tip-text-accent: var(--c-text-accent);--c-warning: #e7c000;--c-warning-bg: #fffae3;--c-warning-title: #ad9000;--c-warning-text: #746000;--c-warning-text-accent: var(--c-text);--c-danger: #cc0000;--c-danger-bg: #ffe0e0;--c-danger-title: #990000;--c-danger-text: #660000;--c-danger-text-accent: var(--c-text);--c-details-bg: #eeeeee;--c-badge-tip: var(--c-tip);--c-badge-warning: var(--c-warning);--c-badge-danger: var(--c-danger);--t-color: .3s ease;--t-transform: .3s ease;--code-bg-color: #282c34;--code-hl-bg-color: rgba(0, 0, 0, .66);--code-ln-color: #9e9e9e;--code-ln-wrapper-width: 3.5rem;--font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;--font-family-code: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;--navbar-height: 3.6rem;--navbar-padding-v: .7rem;--navbar-padding-h: 1.5rem;--sidebar-width: 20rem;--sidebar-width-mobile: calc(var(--sidebar-width) * .82);--content-width: 740px;--homepage-width: 960px}.back-to-top{--back-to-top-color: var(--c-brand);--back-to-top-color-hover: var(--c-brand-light)}.DocSearch{--docsearch-primary-color: var(--c-brand);--docsearch-text-color: var(--c-text);--docsearch-highlight-color: var(--c-brand);--docsearch-muted-color: var(--c-text-quote);--docsearch-container-background: rgba(9, 10, 17, .8);--docsearch-modal-background: var(--c-bg-light);--docsearch-searchbox-background: var(--c-bg-lighter);--docsearch-searchbox-focus-background: var(--c-bg);--docsearch-searchbox-shadow: inset 0 0 0 2px var(--c-brand);--docsearch-hit-color: var(--c-text-light);--docsearch-hit-active-color: var(--c-bg);--docsearch-hit-background: var(--c-bg);--docsearch-hit-shadow: 0 1px 3px 0 var(--c-border-dark);--docsearch-footer-background: var(--c-bg)}.external-link-icon{--external-link-icon-color: var(--c-text-quote)}.medium-zoom-overlay{--medium-zoom-bg-color: var(--c-bg)}#nprogress{--nprogress-color: var(--c-brand)}.pwa-popup{--pwa-popup-text-color: var(--c-text);--pwa-popup-bg-color: var(--c-bg);--pwa-popup-border-color: var(--c-brand);--pwa-popup-shadow: 0 4px 16px var(--c-brand);--pwa-popup-btn-text-color: var(--c-bg);--pwa-popup-btn-bg-color: var(--c-brand);--pwa-popup-btn-hover-bg-color: var(--c-brand-light)}.search-box{--search-bg-color: var(--c-bg);--search-accent-color: var(--c-brand);--search-text-color: var(--c-text);--search-border-color: var(--c-border);--search-item-text-color: var(--c-text-lighter);--search-item-focus-bg-color: var(--c-bg-light)}html.dark{--c-brand: #3aa675;--c-brand-light: #349469;--c-bg: #22272e;--c-bg-light: #2b313a;--c-bg-lighter: #262c34;--c-text: #adbac7;--c-text-light: #96a7b7;--c-text-lighter: #8b9eb0;--c-text-lightest: #8094a8;--c-border: #3e4c5a;--c-border-dark: #34404c;--c-tip: #318a62;--c-warning: #ceab00;--c-warning-bg: #7e755b;--c-warning-title: #ceac03;--c-warning-text: #362e00;--c-danger: #940000;--c-danger-bg: #806161;--c-danger-title: #610000;--c-danger-text: #3a0000;--c-details-bg: #323843;--code-hl-bg-color: #363b46}html.dark .DocSearch{--docsearch-logo-color: var(--c-text);--docsearch-modal-shadow: inset 1px 1px 0 0 #2c2e40, 0 3px 8px 0 #000309;--docsearch-key-shadow: inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px #51577d, 0 2px 2px 0 rgba(3, 4, 9, .3);--docsearch-key-gradient: linear-gradient(-225deg, #444950, #1c1e21);--docsearch-footer-shadow: inset 0 1px 0 0 rgba(73, 76, 106, .5), 0 -4px 8px 0 rgba(0, 0, 0, .2)}html,body{padding:0;margin:0;background-color:var(--c-bg);transition:background-color var(--t-color)}html.dark{color-scheme:dark}html{font-size:16px}body{font-family:var(--font-family);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-size:1rem;color:var(--c-text)}a{font-weight:500;color:var(--c-text-accent);text-decoration:none;overflow-wrap:break-word}p a code{font-weight:400;color:var(--c-text-accent)}kbd{font-family:var(--font-family-code);color:var(--c-text);background:var(--c-bg-lighter);border:solid .15rem var(--c-border-dark);border-bottom:solid .25rem var(--c-border-dark);border-radius:.15rem;padding:0 .15em}code{font-family:var(--font-family-code);color:var(--c-text-lighter);padding:.25rem .5rem;margin:0;font-size:.85em;background-color:var(--c-bg-lighter);border-radius:3px;overflow-wrap:break-word;transition:background-color var(--t-color)}blockquote{font-size:1rem;color:var(--c-text-quote);border-left:.2rem solid var(--c-border-dark);margin:1rem 0;padding:.25rem 0 .25rem 1rem}blockquote>p{margin:0}ul,ol{padding-left:1.2em}strong{font-weight:600}h1,h2,h3,h4,h5,h6{font-weight:600;line-height:1.25}h1:focus-visible,h2:focus-visible,h3:focus-visible,h4:focus-visible,h5:focus-visible,h6:focus-visible{outline:none}h1:hover .header-anchor,h2:hover .header-anchor,h3:hover .header-anchor,h4:hover .header-anchor,h5:hover .header-anchor,h6:hover .header-anchor{opacity:1}h1{font-size:2.2rem}h2{font-size:1.65rem;padding-bottom:.3rem;border-bottom:1px solid var(--c-border);transition:border-color var(--t-color)}h3{font-size:1.35rem}h4{font-size:1.15rem}h5{font-size:1.05rem}h6{font-size:1rem}a.header-anchor{font-size:.85em;float:left;margin-left:-.87em;padding-right:.23em;margin-top:.125em;opacity:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}a.header-anchor:hover{text-decoration:none}a.header-anchor:focus-visible{opacity:1}p,ul,ol{line-height:1.7}hr{border:0;border-top:1px solid var(--c-border)}table{border-collapse:collapse;margin:1rem 0;display:block;overflow-x:auto;transition:border-color var(--t-color)}tr{border-top:1px solid var(--c-border-dark);transition:border-color var(--t-color)}tr:nth-child(2n){background-color:var(--c-bg-light);transition:background-color var(--t-color)}th,td{padding:.6em 1em;border:1px solid var(--c-border-dark);transition:border-color var(--t-color)}.arrow{display:inline-block;width:0;height:0}.arrow.up{border-left:4px solid transparent;border-right:4px solid transparent;border-bottom:6px solid var(--c-bg-arrow)}.arrow.down{border-left:4px solid transparent;border-right:4px solid transparent;border-top:6px solid var(--c-bg-arrow)}.arrow.right{border-top:4px solid transparent;border-bottom:4px solid transparent;border-left:6px solid var(--c-bg-arrow)}.arrow.left{border-top:4px solid transparent;border-bottom:4px solid transparent;border-right:6px solid var(--c-bg-arrow)}.badge{display:inline-block;font-size:14px;height:18px;line-height:18px;border-radius:3px;padding:0 6px;color:var(--c-bg);vertical-align:top;transition:color var(--t-color),background-color var(--t-color)}.badge.tip{background-color:var(--c-badge-tip)}.badge.warning{background-color:var(--c-badge-warning)}.badge.danger{background-color:var(--c-badge-danger)}.badge+.badge{margin-left:5px}code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:var(--font-family-code);font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.comment,.token.block-comment,.token.prolog,.token.doctype,.token.cdata{color:#999}.token.punctuation{color:#ccc}.token.tag,.token.attr-name,.token.namespace,.token.deleted{color:#ec5975}.token.function-name{color:#6196cc}.token.boolean,.token.number,.token.function{color:#f08d49}.token.property,.token.class-name,.token.constant,.token.symbol{color:#f8c555}.token.selector,.token.important,.token.atrule,.token.keyword,.token.builtin{color:#cc99cd}.token.string,.token.char,.token.attr-value,.token.regex,.token.variable{color:#7ec699}.token.operator,.token.entity,.token.url{color:#67cdcc}.token.important,.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:#3eaf7c}.theme-default-content pre,.theme-default-content pre[class*=language-]{line-height:1.4;padding:1.3rem 1.5rem;margin:.85rem 0;border-radius:6px;overflow:auto}.theme-default-content pre code,.theme-default-content pre[class*=language-] code{color:#fff;padding:0;background-color:transparent;border-radius:0;overflow-wrap:unset;-webkit-font-smoothing:auto;-moz-osx-font-smoothing:auto}.theme-default-content .line-number{font-family:var(--font-family-code)}div[class*=language-]{position:relative;background-color:var(--code-bg-color);border-radius:6px}div[class*=language-]:before{position:absolute;z-index:3;top:.8em;right:1em;font-size:.75rem;color:var(--code-ln-color)}div[class*=language-] pre,div[class*=language-] pre[class*=language-]{background:transparent!important;position:relative;z-index:1}div[class*=language-] .highlight-lines{-webkit-user-select:none;-moz-user-select:none;user-select:none;padding-top:1.3rem;position:absolute;top:0;left:0;width:100%;line-height:1.4}div[class*=language-] .highlight-lines .highlight-line{background-color:var(--code-hl-bg-color)}div[class*=language-]:not(.line-numbers-mode) .line-numbers{display:none}div[class*=language-].line-numbers-mode .highlight-lines .highlight-line{position:relative}div[class*=language-].line-numbers-mode .highlight-lines .highlight-line:before{content:" ";position:absolute;z-index:2;left:0;top:0;display:block;width:var(--code-ln-wrapper-width);height:100%}div[class*=language-].line-numbers-mode pre{margin-left:var(--code-ln-wrapper-width);padding-left:1rem;vertical-align:middle}div[class*=language-].line-numbers-mode .line-numbers{position:absolute;top:0;width:var(--code-ln-wrapper-width);text-align:center;color:var(--code-ln-color);padding-top:1.25rem;line-height:1.4;counter-reset:line-number}div[class*=language-].line-numbers-mode .line-numbers .line-number{position:relative;z-index:3;-webkit-user-select:none;-moz-user-select:none;user-select:none;height:1.4em}div[class*=language-].line-numbers-mode .line-numbers .line-number:before{counter-increment:line-number;content:counter(line-number);font-size:.85em}div[class*=language-].line-numbers-mode:after{content:"";position:absolute;top:0;left:0;width:var(--code-ln-wrapper-width);height:100%;border-radius:6px 0 0 6px;border-right:1px solid var(--code-hl-bg-color)}div[class*=language-].ext-c:before{content:"c"}div[class*=language-].ext-cpp:before{content:"cpp"}div[class*=language-].ext-cs:before{content:"cs"}div[class*=language-].ext-css:before{content:"css"}div[class*=language-].ext-dart:before{content:"dart"}div[class*=language-].ext-docker:before{content:"docker"}div[class*=language-].ext-fs:before{content:"fs"}div[class*=language-].ext-go:before{content:"go"}div[class*=language-].ext-html:before{content:"html"}div[class*=language-].ext-java:before{content:"java"}div[class*=language-].ext-js:before{content:"js"}div[class*=language-].ext-json:before{content:"json"}div[class*=language-].ext-kt:before{content:"kt"}div[class*=language-].ext-less:before{content:"less"}div[class*=language-].ext-makefile:before{content:"makefile"}div[class*=language-].ext-md:before{content:"md"}div[class*=language-].ext-php:before{content:"php"}div[class*=language-].ext-py:before{content:"py"}div[class*=language-].ext-rb:before{content:"rb"}div[class*=language-].ext-rs:before{content:"rs"}div[class*=language-].ext-sass:before{content:"sass"}div[class*=language-].ext-scss:before{content:"scss"}div[class*=language-].ext-sh:before{content:"sh"}div[class*=language-].ext-styl:before{content:"styl"}div[class*=language-].ext-ts:before{content:"ts"}div[class*=language-].ext-toml:before{content:"toml"}div[class*=language-].ext-vue:before{content:"vue"}div[class*=language-].ext-yml:before{content:"yml"}@media (max-width: 419px){.theme-default-content div[class*=language-]{margin:.85rem -1.5rem;border-radius:0}}.code-group__nav{margin-top:.85rem;margin-bottom:calc(-1.7rem - 6px);padding-bottom:calc(1.7rem - 6px);padding-left:10px;padding-top:10px;border-top-left-radius:6px;border-top-right-radius:6px;background-color:var(--code-bg-color)}.code-group__ul{margin:auto 0;padding-left:0;display:inline-flex;list-style:none}.code-group__nav-tab{border:0;padding:5px;cursor:pointer;background-color:transparent;font-size:.85em;line-height:1.4;color:#ffffffe6;font-weight:600}.code-group__nav-tab:focus{outline:none}.code-group__nav-tab:focus-visible{outline:1px solid rgba(255,255,255,.9)}.code-group__nav-tab-active{border-bottom:var(--c-brand) 1px solid}@media (max-width: 419px){.code-group__nav{margin-left:-1.5rem;margin-right:-1.5rem;border-radius:0}}.code-group-item{display:none}.code-group-item__active{display:block}.code-group-item>pre{background-color:orange}.custom-container{transition:color var(--t-color),border-color var(--t-color),background-color var(--t-color)}.custom-container .custom-container-title{font-weight:600}.custom-container .custom-container-title:not(:only-child){margin-bottom:-.4rem}.custom-container.tip,.custom-container.warning,.custom-container.danger{padding:.1rem 1.5rem;border-left-width:.5rem;border-left-style:solid;margin:1rem 0}.custom-container.tip{border-color:var(--c-tip);background-color:var(--c-tip-bg);color:var(--c-tip-text)}.custom-container.tip .custom-container-title{color:var(--c-tip-title)}.custom-container.tip a{color:var(--c-tip-text-accent)}.custom-container.warning{border-color:var(--c-warning);background-color:var(--c-warning-bg);color:var(--c-warning-text)}.custom-container.warning .custom-container-title{color:var(--c-warning-title)}.custom-container.warning a{color:var(--c-warning-text-accent)}.custom-container.danger{border-color:var(--c-danger);background-color:var(--c-danger-bg);color:var(--c-danger-text)}.custom-container.danger .custom-container-title{color:var(--c-danger-title)}.custom-container.danger a{color:var(--c-danger-text-accent)}.custom-container.details{display:block;position:relative;border-radius:2px;margin:1.6em 0;padding:1.6em;background-color:var(--c-details-bg)}.custom-container.details h4{margin-top:0}.custom-container.details figure:last-child,.custom-container.details p:last-child{margin-bottom:0;padding-bottom:0}.custom-container.details summary{outline:none;cursor:pointer}.home{padding:var(--navbar-height) 2rem 0;max-width:var(--homepage-width);margin:0 auto;display:block}.home .hero{text-align:center}.home .hero img{max-width:100%;max-height:280px;display:block;margin:3rem auto 1.5rem}.home .hero h1{font-size:3rem}.home .hero h1,.home .hero .description,.home .hero .actions{margin:1.8rem auto}.home .hero .actions{display:flex;flex-wrap:wrap;gap:1rem;justify-content:center}.home .hero .description{max-width:35rem;font-size:1.6rem;line-height:1.3;color:var(--c-text-lightest)}.home .hero .action-button{display:inline-block;font-size:1.2rem;padding:.8rem 1.6rem;border-width:2px;border-style:solid;border-radius:4px;transition:background-color var(--t-color);box-sizing:border-box}.home .hero .action-button.primary{color:var(--c-bg);background-color:var(--c-brand);border-color:var(--c-brand)}.home .hero .action-button.primary:hover{background-color:var(--c-brand-light)}.home .hero .action-button.secondary{color:var(--c-brand);background-color:var(--c-bg);border-color:var(--c-brand)}.home .hero .action-button.secondary:hover{color:var(--c-bg);background-color:var(--c-brand-light)}.home .features{border-top:1px solid var(--c-border);transition:border-color var(--t-color);padding:1.2rem 0;margin-top:2.5rem;display:flex;flex-wrap:wrap;align-items:flex-start;align-content:stretch;justify-content:space-between}.home .feature{flex-grow:1;flex-basis:30%;max-width:30%}.home .feature h2{font-size:1.4rem;font-weight:500;border-bottom:none;padding-bottom:0;color:var(--c-text-light)}.home .feature p{color:var(--c-text-lighter)}.home .theme-default-content{padding:0;margin:0}.home .footer{padding:2.5rem;border-top:1px solid var(--c-border);text-align:center;color:var(--c-text-lighter);transition:border-color var(--t-color)}@media (max-width: 719px){.home .features{flex-direction:column}.home .feature{max-width:100%;padding:0 2.5rem}}@media (max-width: 419px){.home{padding-left:1.5rem;padding-right:1.5rem}.home .hero img{max-height:210px;margin:2rem auto 1.2rem}.home .hero h1{font-size:2rem}.home .hero h1,.home .hero .description,.home .hero .actions{margin:1.2rem auto}.home .hero .description{font-size:1.2rem}.home .hero .action-button{font-size:1rem;padding:.6rem 1.2rem}.home .feature h2{font-size:1.25rem}}.page{padding-top:var(--navbar-height);padding-left:var(--sidebar-width)}.navbar{position:fixed;z-index:20;top:0;left:0;right:0;height:var(--navbar-height);box-sizing:border-box;border-bottom:1px solid var(--c-border);background-color:var(--c-bg-navbar);transition:background-color var(--t-color),border-color var(--t-color)}.sidebar{font-size:16px;width:var(--sidebar-width);position:fixed;z-index:10;margin:0;top:var(--navbar-height);left:0;bottom:0;box-sizing:border-box;border-right:1px solid var(--c-border);overflow-y:auto;scrollbar-width:thin;scrollbar-color:var(--c-brand) var(--c-border);background-color:var(--c-bg-sidebar);transition:transform var(--t-transform),background-color var(--t-color),border-color var(--t-color)}.sidebar::-webkit-scrollbar{width:7px}.sidebar::-webkit-scrollbar-track{background-color:var(--c-border)}.sidebar::-webkit-scrollbar-thumb{background-color:var(--c-brand)}.sidebar-mask{position:fixed;z-index:9;top:0;left:0;width:100vw;height:100vh;display:none}.theme-container.sidebar-open .sidebar-mask{display:block}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(1){transform:rotate(45deg) translate3d(5.5px,5.5px,0)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(2){transform:scale3d(0,1,1)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(3){transform:rotate(-45deg) translate3d(6px,-6px,0)}.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(1),.theme-container.sidebar-open .navbar>.toggle-sidebar-button .icon span:nth-child(3){transform-origin:center}.theme-container.no-navbar .theme-default-content h1,.theme-container.no-navbar .theme-default-content h2,.theme-container.no-navbar .theme-default-content h3,.theme-container.no-navbar .theme-default-content h4,.theme-container.no-navbar .theme-default-content h5,.theme-container.no-navbar .theme-default-content h6{margin-top:1.5rem;padding-top:0}.theme-container.no-navbar .page{padding-top:0}.theme-container.no-navbar .sidebar{top:0}@media (min-width: 720px){.theme-container.no-sidebar .sidebar{display:none}.theme-container.no-sidebar .page{padding-left:0}}.theme-default-content a:hover{text-decoration:underline}.theme-default-content img{max-width:100%}.theme-default-content h1,.theme-default-content h2,.theme-default-content h3,.theme-default-content h4,.theme-default-content h5,.theme-default-content h6{margin-top:calc(.5rem - var(--navbar-height));padding-top:calc(1rem + var(--navbar-height));margin-bottom:0}.theme-default-content h1:first-child,.theme-default-content h2:first-child,.theme-default-content h3:first-child,.theme-default-content h4:first-child,.theme-default-content h5:first-child,.theme-default-content h6:first-child{margin-bottom:1rem}.theme-default-content h1:first-child+p,.theme-default-content h1:first-child+pre,.theme-default-content h1:first-child+.custom-container,.theme-default-content h2:first-child+p,.theme-default-content h2:first-child+pre,.theme-default-content h2:first-child+.custom-container,.theme-default-content h3:first-child+p,.theme-default-content h3:first-child+pre,.theme-default-content h3:first-child+.custom-container,.theme-default-content h4:first-child+p,.theme-default-content h4:first-child+pre,.theme-default-content h4:first-child+.custom-container,.theme-default-content h5:first-child+p,.theme-default-content h5:first-child+pre,.theme-default-content h5:first-child+.custom-container,.theme-default-content h6:first-child+p,.theme-default-content h6:first-child+pre,.theme-default-content h6:first-child+.custom-container{margin-top:2rem}@media (max-width: 959px){.sidebar{font-size:15px;width:var(--sidebar-width-mobile)}.page{padding-left:var(--sidebar-width-mobile)}}@media (max-width: 719px){.sidebar{top:0;padding-top:var(--navbar-height);transform:translate(-100%)}.page{padding-left:0}.theme-container.sidebar-open .sidebar{transform:translate(0)}.theme-container.no-navbar .sidebar{padding-top:0}}@media (max-width: 419px){h1{font-size:1.9rem}}.navbar{--navbar-line-height: calc( var(--navbar-height) - 2 * var(--navbar-padding-v) );padding:var(--navbar-padding-v) var(--navbar-padding-h);line-height:var(--navbar-line-height)}.navbar .logo{height:var(--navbar-line-height);margin-right:var(--navbar-padding-v);vertical-align:top}.navbar .site-name{font-size:1.3rem;font-weight:600;color:var(--c-text);position:relative}.navbar .navbar-items-wrapper{display:flex;position:absolute;box-sizing:border-box;top:var(--navbar-padding-v);right:var(--navbar-padding-h);height:var(--navbar-line-height);padding-left:var(--navbar-padding-h);white-space:nowrap;font-size:.9rem}.navbar .navbar-items-wrapper .search-box{flex:0 0 auto;vertical-align:top}@media (max-width: 719px){.navbar{padding-left:4rem}.navbar .can-hide{display:none}.navbar .site-name{width:calc(100vw - 9.4rem);overflow:hidden;white-space:nowrap;text-overflow:ellipsis}}.navbar-items{display:inline-block}.navbar-items a{display:inline-block;line-height:1.4rem;color:inherit}.navbar-items a:hover,.navbar-items a.router-link-active{color:var(--c-text-accent)}.navbar-items .navbar-item{position:relative;display:inline-block;margin-left:1.5rem;line-height:var(--navbar-line-height)}.navbar-items .navbar-item:first-child{margin-left:0}@media (max-width: 719px){.navbar-items .navbar-item{margin-left:0}}@media (min-width: 719px){.navbar-items a:hover,.navbar-items a.router-link-active{color:var(--c-text)}.navbar-item>a:hover,.navbar-item>a.router-link-active{margin-bottom:-2px;border-bottom:2px solid var(--c-text-accent)}}.toggle-sidebar-button{position:absolute;top:.6rem;left:1rem;display:none;padding:.6rem;cursor:pointer}.toggle-sidebar-button .icon{display:flex;flex-direction:column;justify-content:center;align-items:center;width:1.25rem;height:1.25rem;cursor:inherit}.toggle-sidebar-button .icon span{display:inline-block;width:100%;height:2px;border-radius:2px;background-color:var(--c-text);transition:transform var(--t-transform)}.toggle-sidebar-button .icon span:nth-child(2){margin:6px 0}@media screen and (max-width: 719px){.toggle-sidebar-button{display:block}}.toggle-color-mode-button{display:flex;margin:auto;margin-left:1rem;border:0;background:none;color:var(--c-text);opacity:.8;cursor:pointer}.toggle-color-mode-button:hover{opacity:1}.toggle-color-mode-button .icon{width:1.25rem;height:1.25rem}.DocSearch{transition:background-color var(--t-color)}.navbar-dropdown-wrapper{cursor:pointer}.navbar-dropdown-wrapper .navbar-dropdown-title,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:block;font-size:.9rem;font-family:inherit;cursor:inherit;padding:inherit;line-height:1.4rem;background:transparent;border:none;font-weight:500;color:var(--c-text)}.navbar-dropdown-wrapper .navbar-dropdown-title:hover,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile:hover{border-color:transparent}.navbar-dropdown-wrapper .navbar-dropdown-title .arrow,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile .arrow{vertical-align:middle;margin-top:-1px;margin-left:.4rem}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:none;font-weight:600;font-size:inherit}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile:hover{color:var(--c-text-accent)}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item{color:inherit;line-height:1.7rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle{margin:.45rem 0 0;border-top:1px solid var(--c-border);padding:1rem 0 .45rem;font-size:.9rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>span{padding:0 1.5rem 0 1.25rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>a{font-weight:inherit}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle>a.router-link-active:after{display:none}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem-wrapper{padding:0;list-style:none}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem-wrapper .navbar-dropdown-subitem{font-size:.9em}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a{display:block;line-height:1.7rem;position:relative;border-bottom:none;font-weight:400;margin-bottom:0;padding:0 1.5rem 0 1.25rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a:hover,.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active{color:var(--c-text-accent)}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active:after{content:"";width:0;height:0;border-left:5px solid var(--c-text-accent);border-top:3px solid transparent;border-bottom:3px solid transparent;position:absolute;top:calc(50% - 2px);left:9px}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item:first-child .navbar-dropdown-subtitle{margin-top:0;padding-top:0;border-top:0}@media (max-width: 719px){.navbar-dropdown-wrapper.open .navbar-dropdown-title,.navbar-dropdown-wrapper.open .navbar-dropdown-title-mobile{margin-bottom:.5rem}.navbar-dropdown-wrapper .navbar-dropdown-title,.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:none}.navbar-dropdown-wrapper .navbar-dropdown-title-mobile{display:block}.navbar-dropdown-wrapper .navbar-dropdown{transition:height .1s ease-out;overflow:hidden}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle{border-top:0;margin-top:0;padding-top:0;padding-bottom:0}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subtitle,.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item>a{font-size:15px;line-height:2rem}.navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item .navbar-dropdown-subitem{font-size:14px;padding-left:1rem}}@media (min-width: 720px){.navbar-dropdown-wrapper{height:1.8rem}.navbar-dropdown-wrapper:hover .navbar-dropdown,.navbar-dropdown-wrapper.open .navbar-dropdown{display:block!important}.navbar-dropdown-wrapper.open:blur{display:none}.navbar-dropdown-wrapper .navbar-dropdown{display:none;height:auto!important;box-sizing:border-box;max-height:calc(100vh - 2.7rem);overflow-y:auto;position:absolute;top:100%;right:0;background-color:var(--c-bg-navbar);padding:.6rem 0;border:1px solid var(--c-border);border-bottom-color:var(--c-border-dark);text-align:left;border-radius:.25rem;white-space:nowrap;margin:0}}.page{padding-bottom:2rem;display:block}.page .theme-default-content{max-width:var(--content-width);margin:0 auto;padding:2rem 2.5rem;padding-top:0}@media (max-width: 959px){.page .theme-default-content{padding:2rem}}@media (max-width: 419px){.page .theme-default-content{padding:1.5rem}}.page-meta{max-width:var(--content-width);margin:0 auto;padding:1rem 2.5rem;overflow:auto}@media (max-width: 959px){.page-meta{padding:2rem}}@media (max-width: 419px){.page-meta{padding:1.5rem}}.page-meta .meta-item{cursor:default;margin-top:.8rem}.page-meta .meta-item .meta-item-label{font-weight:500;color:var(--c-text-lighter)}.page-meta .meta-item .meta-item-info{font-weight:400;color:var(--c-text-quote)}.page-meta .edit-link{display:inline-block;margin-right:.25rem}.page-meta .last-updated{float:right}@media (max-width: 719px){.page-meta .last-updated{font-size:.8em;float:none}.page-meta .contributors{font-size:.8em}}.page-nav{max-width:var(--content-width);margin:0 auto;padding:1rem 2.5rem 2rem;padding-bottom:0}@media (max-width: 959px){.page-nav{padding:2rem}}@media (max-width: 419px){.page-nav{padding:1.5rem}}.page-nav .inner{min-height:2rem;margin-top:0;border-top:1px solid var(--c-border);transition:border-color var(--t-color);padding-top:1rem;overflow:auto}.page-nav .prev a:before{content:"\2190"}.page-nav .next{float:right}.page-nav .next a:after{content:"\2192"}.sidebar ul{padding:0;margin:0;list-style-type:none}.sidebar a{display:inline-block}.sidebar .navbar-items{display:none;border-bottom:1px solid var(--c-border);transition:border-color var(--t-color);padding:.5rem 0 .75rem}.sidebar .navbar-items a{font-weight:600}.sidebar .navbar-items .navbar-item{display:block;line-height:1.25rem;font-size:1.1em;padding:.5rem 0 .5rem 1.5rem}.sidebar .sidebar-items{padding:1.5rem 0}@media (max-width: 719px){.sidebar .navbar-items{display:block}.sidebar .navbar-items .navbar-dropdown-wrapper .navbar-dropdown .navbar-dropdown-item a.router-link-active:after{top:calc(1rem - 2px)}.sidebar .sidebar-items{padding:1rem 0}}.sidebar-item{cursor:default;border-left:.25rem solid transparent;color:var(--c-text)}.sidebar-item:focus-visible{outline-width:1px;outline-offset:-1px}.sidebar-item.active:not(p.sidebar-heading){font-weight:600;color:var(--c-text-accent);border-left-color:var(--c-text-accent)}.sidebar-item.sidebar-heading{transition:color .15s ease;font-size:1.1em;font-weight:700;padding:.35rem 1.5rem .35rem 1.25rem;width:100%;box-sizing:border-box;margin:0}.sidebar-item.sidebar-heading+.sidebar-item-children{transition:height .1s ease-out;overflow:hidden;margin-bottom:.75rem}.sidebar-item.sidebar-heading.collapsible{cursor:pointer}.sidebar-item.sidebar-heading.collapsible .arrow{position:relative;top:-.12em;left:.5em}.sidebar-item:not(.sidebar-heading){font-size:1em;font-weight:400;display:inline-block;margin:0;padding:.35rem 1rem .35rem 2rem;line-height:1.4;width:100%;box-sizing:border-box}.sidebar-item:not(.sidebar-heading)+.sidebar-item-children{padding-left:1rem;font-size:.95em}.sidebar-item-children .sidebar-item-children .sidebar-item:not(.sidebar-heading){padding:.25rem 1rem .25rem 1.75rem}.sidebar-item-children .sidebar-item-children .sidebar-item:not(.sidebar-heading).active{font-weight:500;border-left-color:transparent}a.sidebar-heading+.sidebar-item-children .sidebar-item:not(.sidebar-heading).active{border-left-color:transparent}a.sidebar-item{cursor:pointer}a.sidebar-item:hover{color:var(--c-text-accent)}.table-of-contents .badge{vertical-align:middle}.dropdown-enter-from,.dropdown-leave-to{height:0!important}.fade-slide-y-enter-active{transition:all .2s ease}.fade-slide-y-leave-active{transition:all .2s cubic-bezier(1,.5,.8,1)}.fade-slide-y-enter-from,.fade-slide-y-leave-to{transform:translateY(10px);opacity:0}:root{--c-brand: rgb(237, 150, 73);--c-brand-light: rgb(244, 200, 161);--content-width: 965px}code{padding:3px 5px;border-radius:5px}.badge{margin-bottom:5px}.custom-container{border-radius:5px}.sidebar-item{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.language-text ::-webkit-scrollbar-track{background:rgb(86,96,110);border-radius:50px}.language-text ::-webkit-scrollbar-thumb:hover{background:rgb(121,135,155)}.language-kotlin ::-webkit-scrollbar-track{background:rgb(86,96,110);border-radius:50px}.language-kotlin ::-webkit-scrollbar-thumb:hover{background:rgb(121,135,155)}.language-java ::-webkit-scrollbar-track{background:rgb(86,96,110);border-radius:50px}.language-java ::-webkit-scrollbar-thumb:hover{background:rgb(121,135,155)}.language-groovy ::-webkit-scrollbar-track{background:rgb(86,96,110);border-radius:50px}.language-groovy ::-webkit-scrollbar-thumb:hover{background:rgb(121,135,155)}.language-xml ::-webkit-scrollbar-track{background:rgb(86,96,110);border-radius:50px}.language-xml ::-webkit-scrollbar-thumb:hover{background:rgb(121,135,155)}.hidden-anchor-page h6{color:transparent;margin-bottom:-35px;padding-top:50px}.code-page h1{font-size:24pt}.code-page h2{font-size:18pt}.code-page h3{font-size:15pt}.code-page h4{font-size:12pt}.code-page h5{font-size:9.6pt}.code-page h6{font-size:8.4pt}.code-page .symbol{color:#8e9ba8}.code-page .deprecated{color:#8e9ba8;text-decoration:line-through}html{scroll-behavior:smooth}html ::-webkit-scrollbar{width:8px;height:6.5px}html ::-webkit-scrollbar-track{background:rgb(234,236,239)}html ::-webkit-scrollbar-thumb{background:rgb(189,189,189);border-radius:50px}html ::-webkit-scrollbar-thumb:hover{background:rgb(133,133,133);border-radius:50px}html.dark{--c-brand: rgb(237, 150, 73);--c-brand-light: rgb(244, 200, 161);--content-width: 965px}html.dark ::-webkit-scrollbar{width:8px;height:6.5px}html.dark ::-webkit-scrollbar-track{background:rgb(41,46,53)}html.dark ::-webkit-scrollbar-thumb{background:rgb(65,72,83);border-radius:50px}html.dark ::-webkit-scrollbar-thumb:hover{background:rgb(56,62,72);border-radius:50px}:root{--search-bg-color: #ffffff;--search-accent-color: #3eaf7c;--search-text-color: #2c3e50;--search-border-color: #eaecef;--search-item-text-color: #5d81a5;--search-item-focus-bg-color: #f3f4f5;--search-input-width: 8rem;--search-result-width: 20rem}.search-box{display:inline-block;position:relative;margin-left:1rem}.search-box input{cursor:text;width:var(--search-input-width);height:2rem;color:var(--search-text-color);display:inline-block;border:1px solid var(--search-border-color);border-radius:2rem;font-size:.9rem;line-height:2rem;padding:0 .5rem 0 2rem;outline:none;transition:all ease .3s;background:var(--search-bg-color) url(/YukiHookAPI/assets/search.0782d0d1.svg) .6rem .5rem no-repeat;background-size:1rem}.search-box input:focus{cursor:auto;border-color:var(--search-accent-color)}.search-box .suggestions{background:var(--search-bg-color);width:var(--search-result-width);position:absolute;top:2rem;right:0;border:1px solid var(--search-border-color);border-radius:6px;padding:.4rem;list-style-type:none}.search-box .suggestion{line-height:1.4;padding:.4rem .6rem;border-radius:4px;cursor:pointer}.search-box .suggestion.focus{background-color:var(--search-item-focus-bg-color)}.search-box .suggestion.focus a{color:var(--search-accent-color)}.search-box .suggestion a{white-space:normal;color:var(--search-item-text-color)}.search-box .suggestion .page-title{font-weight:600}.search-box .suggestion .page-header{font-size:.9em;margin-left:.25em}@media (max-width: 720px){.search-box input{cursor:pointer;width:0;border-color:transparent;position:relative}.search-box input:focus{cursor:text;left:0;width:10rem}}@media (max-width: 420px){.search-box input:focus{width:8rem}.search-box .suggestions{width:calc(100vw - 4rem);right:-.5rem}} diff --git a/docs/assets/xposed-channel.html.18cd2bdb.js b/docs/assets/xposed-channel.html.18cd2bdb.js new file mode 100644 index 00000000..92bc5488 --- /dev/null +++ b/docs/assets/xposed-channel.html.18cd2bdb.js @@ -0,0 +1,62 @@ +import{_ as s,o as n,c as a,a as l}from"./app.fb8271cf.js";const e={},o=l(`

    Xposed \u6A21\u5757\u4E0E\u5BBF\u4E3B\u901A\u8BAF\u6865

    \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

    \u57FA\u672C\u7528\u6CD5

    \u8FD9\u91CC\u63CF\u8FF0\u4E86 wait \u4E0E put \u65B9\u6CD5\u7684\u57FA\u672C\u4F7F\u7528\u65B9\u6CD5\u3002

    \u901A\u8FC7\u4F7F\u7528 dataChannel \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

    \u6A21\u5757\u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u5BBF\u4E3B\u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u4F60\u53EF\u4EE5\u4E0D\u8BBE\u7F6E dataChannel \u7684 value \u6765\u8FBE\u5230\u4EC5\u901A\u77E5\u6A21\u5757\u6216\u5BBF\u4E3B\u56DE\u8C03 wait \u65B9\u6CD5\u3002

    \u6A21\u5757\u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u5BBF\u4E3B\u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \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

    \u5224\u65AD\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7248\u672C\u662F\u5426\u5339\u914D

    \u901A\u8FC7\u901A\u8BAF\u6865\u529F\u80FD\uFF0CYukiHookAPI \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\u3002

    \u6211\u4EEC\u53EA\u9700\u8981\u8C03\u7528 checkingVersionEquals \u65B9\u6CD5\uFF0C\u5373\u53EF\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002

    \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

    // \u4ECE\u6307\u5B9A\u5305\u540D\u7684\u5BBF\u4E3B\u83B7\u53D6
    +dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
    +    // Your code here.
    +}
    +

    \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

    // \u4ECE\u6A21\u5757\u83B7\u53D6
    +dataChannel.checkingVersionEquals { isEquals ->
    +    // Your code here.
    +}
    +

    \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

    \u56DE\u8C03\u4E8B\u4EF6\u54CD\u5E94\u7684\u89C4\u5219

    \u8FD9\u91CC\u53EA\u5217\u51FA\u4E86\u5728\u6A21\u5757\u4E2D\u4F7F\u7528\u7684\u4F8B\u5B50\uFF0C\u5728\u5BBF\u4E3B\u4E2D\u76F8\u540C\u7684 key \u59CB\u7EC8\u4E0D\u5141\u8BB8\u91CD\u590D\u521B\u5EFA\u3002

    \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

    class 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.
    +        }
    +    }
    +}
    +

    \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 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

    \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

    \u5B89\u5168\u6027\u8BF4\u660E

    \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

    `,39),p=[o];function t(c,r){return n(),a("div",null,p)}const d=s(e,[["render",t],["__file","xposed-channel.html.vue"]]);export{d as default}; diff --git a/docs/assets/xposed-channel.html.96712a39.js b/docs/assets/xposed-channel.html.96712a39.js new file mode 100644 index 00000000..4f0b5515 --- /dev/null +++ b/docs/assets/xposed-channel.html.96712a39.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-2e6ad66c","path":"/en/api/special-features/xposed-channel.html","title":"Xposed Module and Host Channel","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Basic Usage","slug":"basic-usage","link":"#basic-usage","children":[]},{"level":2,"title":"Determine Module App and Host App Version Match","slug":"determine-module-app-and-host-app-version-match","link":"#determine-module-app-and-host-app-version-match","children":[]},{"level":2,"title":"Rules for Callback Event Response","slug":"rules-for-callback-event-response","link":"#rules-for-callback-event-response","children":[]},{"level":2,"title":"Security Instructions","slug":"security-instructions","link":"#security-instructions","children":[]}],"git":{"updatedTime":1664028585000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/special-features/xposed-channel.md"}');export{e as data}; diff --git a/docs/assets/xposed-channel.html.b798a8f8.js b/docs/assets/xposed-channel.html.b798a8f8.js new file mode 100644 index 00000000..0edffd21 --- /dev/null +++ b/docs/assets/xposed-channel.html.b798a8f8.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-598546c6","path":"/zh-cn/api/special-features/xposed-channel.html","title":"Xposed \u6A21\u5757\u4E0E\u5BBF\u4E3B\u901A\u8BAF\u6865","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u57FA\u672C\u7528\u6CD5","slug":"\u57FA\u672C\u7528\u6CD5","link":"#\u57FA\u672C\u7528\u6CD5","children":[]},{"level":2,"title":"\u5224\u65AD\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7248\u672C\u662F\u5426\u5339\u914D","slug":"\u5224\u65AD\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7248\u672C\u662F\u5426\u5339\u914D","link":"#\u5224\u65AD\u6A21\u5757\u4E0E\u5BBF\u4E3B\u7248\u672C\u662F\u5426\u5339\u914D","children":[]},{"level":2,"title":"\u56DE\u8C03\u4E8B\u4EF6\u54CD\u5E94\u7684\u89C4\u5219","slug":"\u56DE\u8C03\u4E8B\u4EF6\u54CD\u5E94\u7684\u89C4\u5219","link":"#\u56DE\u8C03\u4E8B\u4EF6\u54CD\u5E94\u7684\u89C4\u5219","children":[]},{"level":2,"title":"\u5B89\u5168\u6027\u8BF4\u660E","slug":"\u5B89\u5168\u6027\u8BF4\u660E","link":"#\u5B89\u5168\u6027\u8BF4\u660E","children":[]}],"git":{"updatedTime":1664028301000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/special-features/xposed-channel.md"}');export{e as data}; diff --git a/docs/assets/xposed-channel.html.ea22e7ce.js b/docs/assets/xposed-channel.html.ea22e7ce.js new file mode 100644 index 00000000..3011356c --- /dev/null +++ b/docs/assets/xposed-channel.html.ea22e7ce.js @@ -0,0 +1,62 @@ +import{_ as s,o as e,c as n,a}from"./app.fb8271cf.js";const l={},o=a(`

    Xposed Module and Host Channel

    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.

    Basic Usage

    The basic usage of the wait and put methods is described here.

    By using 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.

    The Module App example is as follows

    // 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")
    +

    The Host App example is as follows

    // 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")
    +

    You can leave the value of dataChannel unset to only notify the Module App or Host App to call back the wait method.

    The Module App example is as follows

    // 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")
    +

    The Host App example is as follows

    // 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")
    +

    Pay Attention

    The receiver needs to stay alive to receive the communication data.

    Tips

    For more functions, please refer to YukiHookDataChannel.

    Determine Module App and Host App Version Match

    Through the communication bridge function, 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.

    We only need to call the checkingVersionEquals method to achieve this function.

    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

    // Get from the Host App of the specified package name
    +dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
    +    // Your code here.
    +}
    +

    You can also determine in the Host App whether it matches the current Module App version.

    The following example

    // Get from the Module App
    +dataChannel.checkingVersionEquals { isEquals ->
    +    // Your code here.
    +}
    +

    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.

    Rules for Callback Event Response

    Only examples used in Module App are listed here, the same key in the Host App is always not allowed to be created repeatedly.

    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

    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.
    +        }
    +    }
    +}
    +

    In the above example, the callback event A will be replaced by the callback event B, the 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.

    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(...).

    Security Instructions

    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.

    `,39),t=[o];function p(c,i){return e(),n("div",null,t)}const d=s(l,[["render",p],["__file","xposed-channel.html.vue"]]);export{d as default}; diff --git a/docs/assets/xposed-storage.html.5fd9a913.js b/docs/assets/xposed-storage.html.5fd9a913.js new file mode 100644 index 00000000..6cf4d6a8 --- /dev/null +++ b/docs/assets/xposed-storage.html.5fd9a913.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-0d914225","path":"/zh-cn/api/special-features/xposed-storage.html","title":"Xposed \u6A21\u5757\u6570\u636E\u5B58\u50A8","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u5728 Activity \u4E2D\u4F7F\u7528","slug":"\u5728-activity-\u4E2D\u4F7F\u7528","link":"#\u5728-activity-\u4E2D\u4F7F\u7528","children":[]},{"level":2,"title":"\u5728 PreferenceFragment \u4E2D\u4F7F\u7528","slug":"\u5728-preferencefragment-\u4E2D\u4F7F\u7528","link":"#\u5728-preferencefragment-\u4E2D\u4F7F\u7528","children":[]}],"git":{"updatedTime":1664015825000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/api/special-features/xposed-storage.md"}');export{e as data}; diff --git a/docs/assets/xposed-storage.html.6926bcf4.js b/docs/assets/xposed-storage.html.6926bcf4.js new file mode 100644 index 00000000..f4346a72 --- /dev/null +++ b/docs/assets/xposed-storage.html.6926bcf4.js @@ -0,0 +1,12 @@ +import{_ as e,o as s,c as o,a}from"./app.fb8271cf.js";const n={},l=a(`

    Xposed \u6A21\u5757\u6570\u636E\u5B58\u50A8

    \u8FD9\u662F\u4E00\u4E2A\u81EA\u52A8\u5BF9\u63A5 SharedPreferences \u548C XSharedPreferences \u7684\u9AD8\u6548\u6A21\u5757\u6570\u636E\u5B58\u50A8\u89E3\u51B3\u65B9\u6848\u3002

    \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 Sp \u5B58\u50A8\u7684\u6570\u636E\u4E92\u901A\u963B\u788D\u3002

    \u539F\u751F\u7684 Xposed \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

    \u8FD9\u91CC\u63CF\u8FF0\u4E86\u5728 Activity \u4E2D\u88C5\u8F7D YukiHookModulePrefs \u7684\u573A\u666F\u3002

    \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

    XSharedPreferences(BuildConfig.APPLICATION_ID)
    +

    \u6709\u6CA1\u6709\u65B9\u4FBF\u5FEB\u6377\u7684\u89E3\u51B3\u65B9\u6848\u5462\uFF0C\u6B64\u65F6\u4F60\u5C31\u53EF\u4EE5\u4F7F\u7528 YukiHookAPI \u7684\u6269\u5C55\u80FD\u529B\u5FEB\u901F\u5B9E\u73B0\u8FD9\u4E2A\u529F\u80FD\u3002

    \u5F53\u4F60\u5728\u6A21\u5757\u4E2D\u5B58\u50A8\u6570\u636E\u7684\u65F6\u5019\uFF0C\u82E5\u5F53\u524D\u5904\u4E8E Activity \u5185\uFF0C\u53EF\u4EE5\u4F7F\u7528\u5982\u4E0B\u65B9\u6CD5\u3002

    \u793A\u4F8B\u5982\u4E0B

    modulePrefs.putString("test_name", "saved_value")
    +

    \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

    val testName = prefs.getString("test_name", "default_value")
    +

    \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 YukiHookModulePrefs \u6765\u5904\u7406\u3002

    \u82E5\u8981\u5B9E\u73B0\u5B58\u50A8\u7684\u533A\u57DF\u5212\u5206\uFF0C\u4F60\u53EF\u4EE5\u6307\u5B9A\u6BCF\u4E2A prefs \u6587\u4EF6\u7684\u540D\u79F0\u3002

    \u5728\u6A21\u5757\u7684 Activity \u4E2D\u8FD9\u6837\u4F7F\u7528\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \u5728 Hook APP (\u5BBF\u4E3B) \u4E2D\u8FD9\u6837\u8BFB\u53D6\u3002

    \u793A\u4F8B\u5982\u4E0B

    // \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")
    +

    \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 PrefsData \u6765\u521B\u5EFA\u6A21\u677F\u3002

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 YukiHookModulePrefs\u3001PrefsData\u3002

    \u5728 PreferenceFragment \u4E2D\u4F7F\u7528

    \u8FD9\u91CC\u63CF\u8FF0\u4E86\u5728 PreferenceFragment \u4E2D\u88C5\u8F7D YukiHookModulePrefs \u7684\u573A\u666F\u3002

    \u82E5\u4F60\u7684\u6A21\u5757\u4F7F\u7528\u4E86 PreferenceFragmentCompat\uFF0C\u4F60\u73B0\u5728\u53EF\u4EE5\u5C06\u5176\u7EE7\u627F\u7C7B\u5F00\u59CB\u8FC1\u79FB\u5230 ModulePreferenceFragment\u3002

    \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

    `,31),p=[l];function c(t,r){return s(),o("div",null,p)}const d=e(n,[["render",c],["__file","xposed-storage.html.vue"]]);export{d as default}; diff --git a/docs/assets/xposed-storage.html.c35a7041.js b/docs/assets/xposed-storage.html.c35a7041.js new file mode 100644 index 00000000..961ee492 --- /dev/null +++ b/docs/assets/xposed-storage.html.c35a7041.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-68bebbf4","path":"/en/api/special-features/xposed-storage.html","title":"Xposed Module Data Storage","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Use in Activity","slug":"use-in-activity","link":"#use-in-activity","children":[]},{"level":2,"title":"Use in PreferenceFragment","slug":"use-in-preferencefragment","link":"#use-in-preferencefragment","children":[]}],"git":{"updatedTime":1664015967000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/api/special-features/xposed-storage.md"}');export{e as data}; diff --git a/docs/assets/xposed-storage.html.cd1e83bb.js b/docs/assets/xposed-storage.html.cd1e83bb.js new file mode 100644 index 00000000..033faa43 --- /dev/null +++ b/docs/assets/xposed-storage.html.cd1e83bb.js @@ -0,0 +1,12 @@ +import{_ as e,o as s,c as o,a}from"./app.fb8271cf.js";const n={},t=a(`

    Xposed Module Data Storage

    This is an efficient Module App data storage solution that automatically connects SharedPreferences and XSharedPreferences.

    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 Sp storage.

    The native Xposed provides us with a XSharedPreferences for reading the Sp data of the Module App.

    Use in Activity

    Loading YukiHookModulePrefs in Activity is described here.

    Usually we can initialize it in Host App like this.

    The following example

    XSharedPreferences(BuildConfig.APPLICATION_ID)
    +

    Is there a convenient and quick solution?

    At this point, you can use the extension capability of YukiHookAPI to quickly implement this function.

    When you store data in a Module App, you can use the following methods if you are currently in an Activity.

    The following example

    modulePrefs.putString("test_name", "saved_value")
    +

    When you read data in a Host App, you can use the following methods.

    The following example

    val testName = prefs.getString("test_name", "default_value")
    +

    You don't need to consider the module package name and a series of complicated permission configurations, everything is handled by YukiHookModulePrefs.

    To achieve localization of storage, you can specify the name of each prefs file.

    This is used in the Activity of the Module App.

    The following example

    // 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")
    +

    Read like this in Host App.

    The following example

    // 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")
    +

    If your project has a lot of fixed data that needs to be stored and read, it is recommended to use PrefsData to create templates.

    Tips

    For more functions, please refer to YukiHookModulePrefs, PrefsData.

    Use in PreferenceFragment

    Loading YukiHookModulePrefs in PreferenceFragment is described here.

    If your Module App uses PreferenceFragmentCompat, you can now start migrating its extends ModulePreferenceFragment.

    Pay Attention

    You must extends ModulePreferenceFragment to implement the module storage function of YukiHookModulePrefs.

    Tips

    For more functions, please refer to ModulePreferenceFragment.

    `,33),l=[t];function p(i,c){return s(),o("div",null,l)}const d=e(n,[["render",p],["__file","xposed-storage.html.vue"]]);export{d as default}; diff --git a/docs/assets/xposed-using.html.557dcdf1.js b/docs/assets/xposed-using.html.557dcdf1.js new file mode 100644 index 00000000..e3b88414 --- /dev/null +++ b/docs/assets/xposed-using.html.557dcdf1.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-af73b3d0","path":"/zh-cn/config/xposed-using.html","title":"\u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u4F9D\u8D56\u914D\u7F6E","slug":"\u4F9D\u8D56\u914D\u7F6E","link":"#\u4F9D\u8D56\u914D\u7F6E","children":[]},{"level":2,"title":"\u81EA\u5B9A\u4E49\u5904\u7406\u7A0B\u5E8F","slug":"\u81EA\u5B9A\u4E49\u5904\u7406\u7A0B\u5E8F","link":"#\u81EA\u5B9A\u4E49\u5904\u7406\u7A0B\u5E8F","children":[{"level":3,"title":"InjectYukiHookWithXposed \u6CE8\u89E3","slug":"injectyukihookwithxposed-\u6CE8\u89E3","link":"#injectyukihookwithxposed-\u6CE8\u89E3","children":[]},{"level":3,"title":"IYukiHookXposedInit \u63A5\u53E3","slug":"iyukihookxposedinit-\u63A5\u53E3","link":"#iyukihookxposedinit-\u63A5\u53E3","children":[]}]},{"level":2,"title":"\u539F\u751F Xposed API \u4E8B\u4EF6","slug":"\u539F\u751F-xposed-api-\u4E8B\u4EF6","link":"#\u539F\u751F-xposed-api-\u4E8B\u4EF6","children":[]}],"git":{"updatedTime":1663945172000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"zh-cn/config/xposed-using.md"}');export{e as data}; diff --git a/docs/assets/xposed-using.html.701123e9.js b/docs/assets/xposed-using.html.701123e9.js new file mode 100644 index 00000000..e8b9cd22 --- /dev/null +++ b/docs/assets/xposed-using.html.701123e9.js @@ -0,0 +1,77 @@ +import{_ as s,o as n,c as a,a as o}from"./app.fb8271cf.js";const e={},l=o(`

    \u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E

    \u8FD9\u91CC\u4ECB\u7ECD\u4E86 YukiHookAPI \u4F5C\u4E3A Xposed \u6A21\u5757\u4F7F\u7528\u7684\u76F8\u5173\u914D\u7F6E\u65B9\u6CD5\u3002

    \u4F9D\u8D56\u914D\u7F6E

    \u4F5C\u4E3A Xposed \u6A21\u5757\uFF0CYukiHookAPI \u63D0\u4F9B\u4E86\u4E00\u4E2A\u81EA\u52A8\u5904\u7406\u7A0B\u5E8F\u3002

    \u4F60\u9700\u8981\u5728\u4F60\u7684 build.gradle \u4E2D\u96C6\u6210 com.highcapable.yukihookapi:ksp-xposed \u4F9D\u8D56\u7684\u6700\u65B0\u7248\u672C\u3002

    \u81EA\u5B9A\u4E49\u5904\u7406\u7A0B\u5E8F

    \u4F60\u53EF\u4EE5\u5BF9 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

    \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

    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

    \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

    @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\u3002

    \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 com.example.demo\uFF0C\u4EE5\u4E0B\u5B9A\u4E49\u65B9\u5F0F\u4EFB\u9009\u5176\u4E00\u3002

    \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 BuildConfig.java \u6587\u4EF6\uFF0C\u5C31\u4E0D\u9700\u8981\u505A\u989D\u5916\u64CD\u4F5C\u3002

    AndroidManifest.xml \u793A\u4F8B

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    +    package="com.example.demo">
    +

    build.gradle \u793A\u4F8B

    android {
    +    namespace 'com.example.demo'
    +}
    +

    build.gradle.kts \u793A\u4F8B

    android {
    +    namespace = "com.example.demo"
    +}
    +

    \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 modulePackageName \u7684\u53C2\u6570\u3002

    \u793A\u4F8B\u5982\u4E0B

    @InjectYukiHookWithXposed(modulePackageName = "com.example.demo")
    +

    \u53EA\u8981\u4F60\u81EA\u5B9A\u4E49\u4E86 modulePackageName \u7684\u53C2\u6570\uFF0C\u4F60\u5C31\u4F1A\u5728\u7F16\u8BD1\u65F6\u6536\u5230\u8B66\u544A\u3002

    \u793A\u4F8B\u5982\u4E0B

    You set the customize module package name to "com.example.demo", please check for yourself if it is correct
    +

    \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

    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

    \u5047\u8BBE\u8FD9\u662F\u4F60\u7684\u5165\u53E3\u7C7B\u3002

    \u793A\u4F8B\u5982\u4E0B

    @InjectYukiHookWithXposed
    +class HookEntry: IYukiHookXposedInit
    +

    Xposed \u5165\u53E3\u7C7B\u5904\u7406\u5982\u4E0B\u3002

    \u793A\u4F8B\u5982\u4E0B

    class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
    +

    \u7F16\u8BD1\u540E\u7684\u7C7B\u540D\u7ED3\u6784\u5982\u4E0B\u3002

    \u793A\u4F8B\u5982\u4E0B

    ...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
    +

    \u6211\u4EEC\u73B0\u5728\u5B9A\u4E49\u5165\u53E3\u7C7B\u540D\u79F0\u4E3A HookXposedEntry\u3002

    \u793A\u4F8B\u5982\u4E0B

    @InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
    +class HookEntry: IYukiHookXposedInit
    +

    Xposed \u5165\u53E3\u7C7B\u5904\u7406\u5982\u4E0B\u3002

    \u793A\u4F8B\u5982\u4E0B

    class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
    +

    \u7F16\u8BD1\u540E\u7684\u7C7B\u540D\u7ED3\u6784\u5982\u4E0B\u3002

    \u793A\u4F8B\u5982\u4E0B

    ...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
    +

    \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

    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\u3002

    \u542F\u7528\u540E\u751F\u6210\u7684\u5165\u53E3\u7C7B\u5C06\u4E3A\u5982\u4E0B\u6240\u793A\u3002

    \u793A\u4F8B\u5982\u4E0B

    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?) {
    +        // ...
    +    }
    +}
    +

    \u82E5\u4F60\u5F53\u524D\u7684\u9879\u76EE\u5E76\u4E0D\u9700\u8981\u7528\u5230 Reources Hook\uFF0C\u53EF\u4EE5\u8BBE\u7F6E isUsingResourcesHook = false \u6765\u5173\u95ED\u81EA\u52A8\u751F\u6210\u3002

    \u793A\u4F8B\u5982\u4E0B

    @InjectYukiHookWithXposed(isUsingResourcesHook = false)
    +

    \u5173\u95ED\u540E\u751F\u6210\u7684\u5165\u53E3\u7C7B\u5C06\u4E3A\u5982\u4E0B\u6240\u793A\u3002

    \u793A\u4F8B\u5982\u4E0B

    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\u3002

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 IYukiHookXposedInit\u3002

    \u5F53\u4F60\u7684\u6A21\u5757\u88AB Xposed \u88C5\u8F7D\u540E\uFF0ConHook \u65B9\u6CD5\u5C06\u4F1A\u88AB\u56DE\u8C03\uFF0C\u4F60\u9700\u8981\u5728\u6B64\u65B9\u6CD5\u4E2D\u5F00\u59CB\u4F7F\u7528 YukiHookAPI\u3002

    \u57FA\u672C\u7684\u8C03\u7528\u6D41\u7A0B\u4E3A _YukiHookXposedInit \u2192 IYukiHookXposedInit.onXposedEvent \u2192 IYukiHookXposedInit.onInit \u2192 IYukiHookXposedInit.onHook

    \u8BE6\u60C5\u8BF7\u53C2\u8003 API \u57FA\u672C\u914D\u7F6E\u3002

    \u539F\u751F Xposed API \u4E8B\u4EF6

    \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 onXposedEvent \u5B9E\u73B0\u76D1\u542C\u539F\u751F Xposed API \u7684\u5168\u90E8\u88C5\u8F7D\u4E8B\u4EF6\u3002

    \u793A\u4F8B\u5982\u4E0B

    @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

    \u5C0F\u63D0\u793A

    \u66F4\u591A\u529F\u80FD\u8BF7\u53C2\u8003 IYukiHookXposedInit.onXposedEvent \u65B9\u6CD5\u3002

    `,79),p=[l];function c(t,r){return n(),a("div",null,p)}const d=s(e,[["render",c],["__file","xposed-using.html.vue"]]);export{d as default}; diff --git a/docs/assets/xposed-using.html.cd65195d.js b/docs/assets/xposed-using.html.cd65195d.js new file mode 100644 index 00000000..d26b32dc --- /dev/null +++ b/docs/assets/xposed-using.html.cd65195d.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-24e71de7","path":"/en/config/xposed-using.html","title":"Use as Xposed Module Configs","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Dependency Configs","slug":"dependency-configs","link":"#dependency-configs","children":[]},{"level":2,"title":"Custom Automatic Builder","slug":"custom-automatic-builder","link":"#custom-automatic-builder","children":[{"level":3,"title":"InjectYukiHookWithXposed Annotation","slug":"injectyukihookwithxposed-annotation","link":"#injectyukihookwithxposed-annotation","children":[]},{"level":3,"title":"IYukiHookXposedInit Interface","slug":"iyukihookxposedinit-interface","link":"#iyukihookxposedinit-interface","children":[]}]},{"level":2,"title":"Native Xposed API Events","slug":"native-xposed-api-events","link":"#native-xposed-api-events","children":[]}],"git":{"updatedTime":1663945651000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":2}]},"filePathRelative":"en/config/xposed-using.md"}');export{e as data}; diff --git a/docs/assets/xposed-using.html.f07fa93e.js b/docs/assets/xposed-using.html.f07fa93e.js new file mode 100644 index 00000000..0ebf9c65 --- /dev/null +++ b/docs/assets/xposed-using.html.f07fa93e.js @@ -0,0 +1,77 @@ +import{_ as s,o as e,c as a,a as n}from"./app.fb8271cf.js";const o={},l=n(`

    Use as Xposed Module Configs

    Here are the related configuration methods used by YukiHookAPI as an Xposed Module.

    Dependency Configs

    As an Xposed Module, YukiHookAPI provides an automatic builder.

    You need to integrate the latest version of the com.highcapable.yukihookapi:ksp-xposed dependency in your build.gradle.

    Custom Automatic Builder

    You can configure how 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
    +)
    +

    The @InjectYukiHookWithXposed annotation is an important annotation to mark the entry point of a Module App's Hook.

    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.

    sourcePath Parameter

    The sourcePath parameter determines the important identifier for the automatic builder to automatically find and match your current project path.

    The content of this parameter is a relative path match, and the default parameter is src/main.

    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

    @InjectYukiHookWithXposed(sourcePath = "src/custom")
    +

    The file path separator used by 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).

    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 com.example.demo, any one of the following definitions.

    The following definitions are for reference only, usually as long as your project can generate the 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 example

    android {
    +    namespace 'com.example.demo'
    +}
    +

    build.gradle.kts example

    android {
    +    namespace = "com.example.demo"
    +}
    +

    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 modulePackageName parameter.

    The following example

    @InjectYukiHookWithXposed(modulePackageName = "com.example.demo")
    +

    As long as you customize the modulePackageName parameter, you will get a warning at compile time.

    The following example

    You set the customize module package name to "com.example.demo", please check for yourself if it is correct
    +

    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.

    entryClassName Parameter

    entryClassName determines how the automatic builder generates the entry class name in xposed_init.

    By default, it will use your entry class package name to insert the _YukiHookXposedInit suffix for generation.

    Suppose this is your entry class.

    The following example

    @InjectYukiHookWithXposed
    +class HookEntry: IYukiHookXposedInit
    +

    The Xposed entry class is handled as follows.

    The following example

    class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
    +

    The compiled class name structure is as follows.

    The following example

    ...hook.HookEntry \u2190 Your entry class
    +...hook.HookEntry_Impl \u2190 Auto-generated Impl class
    +...hook.HookEntry_YukiHookXposedInit \u2190 Automatically generated Xposed entry class
    +

    We now define the entry class name as HookXposedEntry.

    The following example

    @InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
    +class HookEntry: IYukiHookXposedInit
    +

    The Xposed entry class is handled as follows.

    The following example

    class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
    +

    The compiled class name structure is as follows.

    The following example

    ...hook.HookEntry \u2190 Your entry class
    +...hook.HookEntry_Impl \u2190 Auto-generated Impl class
    +...hook.HookXposedEntry \u2190 Automatically generated Xposed entry class
    +

    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.

    isUsingResourcesHook Parameter

    isUsingResourcesHook determines whether the automatic builder generates relevant code for the Resources Hook, this feature is enabled by default.

    The generated entry class after enabling it will look like the following.

    The following example

    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?) {
    +        // ...
    +    }
    +}
    +

    If your current project does not need to use Reources Hook, you can set isUsingResourcesHook = false to disable automatic generation.

    The following example

    @InjectYukiHookWithXposed(isUsingResourcesHook = false)
    +

    The resulting entry class after closing will look like the following.

    The following example

    class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
    +
    +    override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
    +        // ...
    +    }
    +
    +    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
    +        // ...
    +    }
    +}
    +

    IYukiHookXposedInit Interface

    The IYukiHookXposedInit interface that your HookEntryClass must implements it, which is the entry point for your Module App to start hooking.

    Tips

    For more functions, please refer to IYukiHookXposedInit.

    When your Module App is loaded by Xposed, the onHook method will be called back, you need to start using YukiHookAPI in this method.

    The basic calling process is _YukiHookXposedInit \u2192 IYukiHookXposedInit.onXposedEvent \u2192 IYukiHookXposedInit.onInit \u2192 IYukiHookXposedInit.onHook

    For details, please refer to API Basic Configs.

    Native Xposed API Events

    If your current Xposed Module uses third-party resources, but may not be able to transfer them in a short time, you can use onXposedEvent to monitor all loading events of the native Xposed API.

    The following example

    @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.

    Tips

    For more functions, please refer to the IYukiHookXposedInit.onXposedEvent method.

    `,82),p=[l];function t(c,r){return e(),a("div",null,p)}const d=s(o,[["render",t],["__file","xposed-using.html.vue"]]);export{d as default}; diff --git a/docs/assets/yukihookapi-projectbuilder.html.ae5d1a49.js b/docs/assets/yukihookapi-projectbuilder.html.ae5d1a49.js new file mode 100644 index 00000000..ded7522c --- /dev/null +++ b/docs/assets/yukihookapi-projectbuilder.html.ae5d1a49.js @@ -0,0 +1 @@ +import{_ as i,r as n,o as s,c as d,b as o,d as r,a,e}from"./app.fb8271cf.js";const h="/YukiHookAPI/images/yukihookapi-projectbuilder-zh-cn.png",c={},l=a('

    YukiHookAPI \u6784\u5EFA\u5DE5\u5177

    \u8FD9\u662F\u4E00\u4E2A\u4F7F\u7528 YukiHookAPI \u4F5C\u4E3A\u6838\u5FC3\u7684 Xposed \u6A21\u5757\u81EA\u52A8\u6784\u5EFA\u5DE5\u5177\u3002

    \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

    \u83B7\u53D6\u9879\u76EE

    \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

    ',5),p=e("\u9879\u76EE\u5730\u5740 "),u={href:"https://github.com/fankes/YukiHookAPI-ProjectBuilder",target:"_blank",rel:"noopener noreferrer"},_=e("YukiHookAPI-ProjectBuilder"),k=e("\u3002"),g=e("\u82E5\u4F60\u60F3\u76F4\u63A5\u4E0B\u8F7D\u53EF\u4EE5 "),f={href:"https://github.com/fankes/YukiHookAPI-ProjectBuilder/releases",target:"_blank",rel:"noopener noreferrer"},b=e("\u70B9\u51FB\u8FD9\u91CC"),m=e(" \u524D\u5F80 Release \u53D1\u5E03\u5730\u5740\u3002"),x=a('

    \u4F7F\u7528\u65B9\u6CD5

    \u8FD9\u91CC\u5305\u542B\u4E86\u57FA\u672C\u7684\u4F7F\u7528\u65B9\u6CD5\u548C\u529F\u80FD\u8BB2\u89E3\u3002

    \u57FA\u672C\u7528\u6CD5

    • \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

    \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

    \u591A\u8BED\u8A00\u652F\u6301

    \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

    ',8);function P(I,A){const t=n("ExternalLinkIcon");return s(),d("div",null,[l,o("p",null,[p,o("a",u,[_,r(t)]),k]),o("p",null,[g,o("a",f,[b,r(t)]),m]),x])}const j=i(c,[["render",P],["__file","yukihookapi-projectbuilder.html.vue"]]);export{j as default}; diff --git a/docs/assets/yukihookapi-projectbuilder.html.c5d87cd3.js b/docs/assets/yukihookapi-projectbuilder.html.c5d87cd3.js new file mode 100644 index 00000000..3cf05448 --- /dev/null +++ b/docs/assets/yukihookapi-projectbuilder.html.c5d87cd3.js @@ -0,0 +1 @@ +import{_ as n,r as i,o as c,c as s,b as t,d as a,a as r,e}from"./app.fb8271cf.js";const l="/YukiHookAPI/images/yukihookapi-projectbuilder-en.png",d={},u=r('

    YukiHookAPI Project Builder

    This is an automatic building tool for Xposed Modules using YukiHookAPI as the core.

    Implementing automated search relies on quickly building an Android project template that includes a Xposed Module environment.

    Get Project

    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.

    ',6),h=e("Project Address "),p={href:"https://github.com/fankes/YukiHookAPI-ProjectBuilder",target:"_blank",rel:"noopener noreferrer"},g=e("YukiHookAPI-ProjectBuilder"),f=e("\u3002"),m=e("If you want to download directly, you can "),k={href:"https://github.com/fankes/YukiHookAPI-ProjectBuilder/releases",target:"_blank",rel:"noopener noreferrer"},_=e("click here"),b=e(" to go to the Release address."),y=r('

    Usage

    Here contains the basic usage and function explanation.

    Basic Usage

    • 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

    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.

    Multilingual Support

    The software language follows the current system, and you can manually select the software interface language in the Language column of the menu bar.

    ',9);function j(w,x){const o=i("ExternalLinkIcon");return c(),s("div",null,[u,t("p",null,[h,t("a",p,[g,a(o)]),f]),t("p",null,[m,t("a",k,[_,a(o)]),b]),y])}const A=n(d,[["render",j],["__file","yukihookapi-projectbuilder.html.vue"]]);export{A as default}; diff --git a/docs/assets/yukihookapi-projectbuilder.html.d499d226.js b/docs/assets/yukihookapi-projectbuilder.html.d499d226.js new file mode 100644 index 00000000..de60e82e --- /dev/null +++ b/docs/assets/yukihookapi-projectbuilder.html.d499d226.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-a2fab4d6","path":"/zh-cn/tools/yukihookapi-projectbuilder.html","title":"YukiHookAPI \u6784\u5EFA\u5DE5\u5177","lang":"zh-CN","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"\u83B7\u53D6\u9879\u76EE","slug":"\u83B7\u53D6\u9879\u76EE","link":"#\u83B7\u53D6\u9879\u76EE","children":[]},{"level":2,"title":"\u4F7F\u7528\u65B9\u6CD5","slug":"\u4F7F\u7528\u65B9\u6CD5","link":"#\u4F7F\u7528\u65B9\u6CD5","children":[{"level":3,"title":"\u57FA\u672C\u7528\u6CD5","slug":"\u57FA\u672C\u7528\u6CD5","link":"#\u57FA\u672C\u7528\u6CD5","children":[]},{"level":3,"title":"\u914D\u7F6E\u6A21\u677F","slug":"\u914D\u7F6E\u6A21\u677F","link":"#\u914D\u7F6E\u6A21\u677F","children":[]},{"level":3,"title":"\u591A\u8BED\u8A00\u652F\u6301","slug":"\u591A\u8BED\u8A00\u652F\u6301","link":"#\u591A\u8BED\u8A00\u652F\u6301","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"zh-cn/tools/yukihookapi-projectbuilder.md"}');export{e as data}; diff --git a/docs/assets/yukihookapi-projectbuilder.html.ed4fa356.js b/docs/assets/yukihookapi-projectbuilder.html.ed4fa356.js new file mode 100644 index 00000000..08dda321 --- /dev/null +++ b/docs/assets/yukihookapi-projectbuilder.html.ed4fa356.js @@ -0,0 +1 @@ +const e=JSON.parse('{"key":"v-55c11626","path":"/en/tools/yukihookapi-projectbuilder.html","title":"YukiHookAPI Project Builder","lang":"en-US","frontmatter":{},"excerpt":"","headers":[{"level":2,"title":"Get Project","slug":"get-project","link":"#get-project","children":[]},{"level":2,"title":"Usage","slug":"usage","link":"#usage","children":[{"level":3,"title":"Basic Usage","slug":"basic-usage","link":"#basic-usage","children":[]},{"level":3,"title":"Config Template","slug":"config-template","link":"#config-template","children":[]},{"level":3,"title":"Multilingual Support","slug":"multilingual-support","link":"#multilingual-support","children":[]}]}],"git":{"updatedTime":1663397167000,"contributors":[{"name":"fankesyooni","email":"qzmmcn@163.com","commits":1}]},"filePathRelative":"en/tools/yukihookapi-projectbuilder.md"}');export{e as data}; diff --git a/docs/en/about/about.html b/docs/en/about/about.html new file mode 100644 index 00000000..8ed782bb --- /dev/null +++ b/docs/en/about/about.html @@ -0,0 +1,54 @@ + + + + + + + + + About this Document | Yuki Hook API + + + + +

    About this Document

    This document is powered by VuePressopen in new window.

    License

    The MIT License (MIT)open in new window

    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 © 2019-2022 HighCapable

    + + + diff --git a/docs/en/about/changelog.html b/docs/en/about/changelog.html new file mode 100644 index 00000000..8db6d8fb --- /dev/null +++ b/docs/en/about/changelog.html @@ -0,0 +1,33 @@ + + + + + + + + + Changelog | Yuki Hook API + + + + +

    Changelog

    The version update history of YukiHookAPI is recorded here.

    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

    1.1.0 | 2022.09.28  latest

    • This is a major version update, please refer to API Document and Special Features for the changes and usage mentioned in the changelog
    • Change the help documentation framework to VuePressopen in new window
    • Unify and standardize the terms and nouns in the document, for example, "query" is always changed to "find", XposedHelper is misspelled and changed to XposedHelpers
    • Documentation Getting Started → Basic Knowledge page to add a link, Simplified Chinese only
    • Convert Class and Method of Hook App Demo to Java to provide better demo effect
    • Fixed code comment naming in Hook Module Demo
    • Refactored a lot of low-level Hook logic and the docking method of Xposed API
    • Removed HookParamWrapper, it now interfaces directly with YukiBridgeFactory
    • Moved methods in section YukiHookBridge to AppParasitics
    • Removed HookParam.args and the underlying direct connection method setArgs, directly get and set the object of the current array
    • Optimized automatic handler to merge referenced jar into stub project
    • Fix the problem that the module package name cannot be correctly matched when multi-project packaging, and modify the module package name matching logic of the automatic handler, thanks to 5ec1cffopen in new window for the feedback and solutions provided
    • Internal closure processing for the methods of API private tool classes to avoid polluting the top-level namespace
    • Fixed Creater naming to Creator for all reflection and Hook classes
    • Added YukiHookAPI.Status.compiledTimestamp function, which can get the compilation completion timestamp when used as an Xposed module
    • Added YukiHookAPI.Status.isXposedEnvironment function, which can determine whether the current (Xposed) host environment or module environment is
    • The debug logging function has been overhauled, and functions such as YukiHookAPI.Configs.debugTag have been merged into YukiHookLogger.Configs
    • The debug log can be added to specify the printing method as XposedBridge.log or Logd
    • The package name of the current host and the current user ID are added to the debug log by default for debugging, you can change it yourself in the debugLog configuration
    • Added generic function to reflect and call generics, you can use it in Class or CurrentClass
    • obsolete the buildOfAny method, now use the buildOf method directly (without generics) to use the constructor to create a new object and get the result Any
    • Fixed the issue of null pointer exception when using hasExtends
    • CurrentClass added non-lambda method of calling
    • CurrentClass adds name and simpleName functions
    • Completely rewrite the core method of ReflectionTool, sorting and classifying different search conditions
    • Fix the problem that Member obtained by directly calling declared in ReflectionTool throws an exception
    • Fix UndefinedType in ReflectionTool is not correctly judged in Method and Constructor conditions
    • Added a friendly prompt method when the reflection search result is abnormal, which can specifically locate the problem that Member cannot be found under specified conditions
    • Added VagueType condition in Method and Constructor for reflection search, which can be used in param condition to ignore parameters you don't want to fill in
    • Added paramCount { ... } condition in Method and Constructor of reflection search, now you can directly get it in it to customize your judgment condition
    • The current method is added to the FieldFinder result, which can directly create a call space for the result instance
    • Modified the modifiers 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 true
    • as* function in ModifierRules renamed to is*, thanks to Kitsuneopen in new window suggestion
    • Added RemedyPlan feature in FieldFinder
    • Added Class fuzzy search function (Beta) in Dex, you can now directly use searchClass function to fuzzy search Class with specified conditions
    • Added multiple search function in reflection search, you can use relative search conditions to obtain multiple search results at the same time, thanks to AA and Kitsuneopen in new window for suggestions
    • Fix the problem that the object obtained by appClassLoader is incorrect in system applications in some systems, thanks to Luckyzyxopen in new window for the feedback
    • Modified the calling method of XposedBridge.invokeOriginalMethod and added original function in MethodFinder.Result.Instance
    • Fix the problem of wrong value of getStringSet method in YukiHookModulePrefs and optimize the code style, thanks to Teddy_Zhuopen in new window PRopen in new window
    • Modify YukiHookModulePrefs to intercept exceptions that may not exist in XSharePreference
    • Fixed the problem that YukiHookDataChannel could not be successfully registered in some third-party ROM system frameworks
    • Secured YukiHookDataChannel, now it can only communicate between modules from the specified package name and the host
    • Added automatic hook SharedPreferences to fix the problem that file permissions are not 0664 in some systems, thanks to 5ec1cffopen in new window for the feedback and implementation code provided
    • Added YukiHookAPI.Configs.isEnableHookSharedPreferences function, which is disabled by default and can be enabled if the permission of SharedPreferences is incorrect
    • Fixed the bug that the no-parameter construction method cannot be found when searching for Constructor without filling in the search conditions, thanks B5 KAKA for the feedback
    • Detach Result instances located in method, constructor in injectMember to Process
    • Added the 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 declared
    • Added module resource injection and Activity proxy functions, you can call injectModuleAppResources and registerModuleAppActivities to use
    • Added ModuleContextThemeWrapper function, you can call applyModuleTheme to create the Context of a module in any Activity
    • Added ClassLoader.onLoadClass function, which can be used to listen for events when the loadClass method of ClassLoader is called
    • obsolete classOf and clazz extension methods, add toClass and toClassOrNull usage, please move to the new method now
    • VariousClass adds a getOrNull method, which can return null instead of throwing an exception when it can't match Class
    • Removed 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
    • no longer expose any methods in HookClass
    • Added throwToApp function in HookParam, which can throw exceptions directly to the host
    • The onFailureThrowToApp function is added to the Hook callback, which can be directly thrown to the host when an exception occurs
    • Modified the printing logic of the debug log, the time-consuming records in the reflection search function will only be printed during the Hook process
    • Added the function of removing Hook in the Hook process, you can use the remove and removeSelf methods to remove the hook
    • Fixed the issue that caused the host to throw an exception when ReplaceHook failed, and now it is modified to call the original method to ensure the normal operation of the host function
    • Added the function of checking the return value of the method in the Hook process. If the return value does not match, it will automatically throw an exception or print an error according to the situation
    • Added array type to Resources Hook, thanks to PRopen in new window of GSWXXNopen in new window
    • Moved me.weishu.reflection to thirdparty to prevent conflicting dependencies of the same name introduced at the same time
    • Remove the exception thrown when the Hook method body is empty, and modify it to print the warning log
    • Modify the exception handling logic of AppLifecycle and throw it directly to the host when an exception occurs
    • Updated Demo API version to 33

    1.0.92 | 2022.05.31  stale

    • Fixed the naming method of callback in a large number of methods
    • Changed the solution to fix the problem that YukiHookDataChannel cannot call back the current Activity broadcast on devices lower than Android 12
    • The InjectYukiHookWithXposed annotation adds the isUsingResourcesHook function, now you can selectively disable the dependency interface that automatically generates IXposedHookInitPackageResources

    1.0.91 | 2022.05.29  outdate

    • Fixed the ClassLoader error when the customized system of some devices is booted in the LSPosed environment, thanks to Luckyzyxopen in new window for the feedback
    • Fixed YukiHookDataChannel not being able to call back the current Activity broadcast on ZUI and systems below Android 12
    • Integrate the YukiHookModuleStatus 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.0.90 | 2022.05.27  outdate

    • Fixed YukiHookDataChannel crashing when the module sets the listener callback
    • Fixed YukiHookDataChannel still calling back when not in current Activity
    • Remove the default value of YukiHookDataChannel callback event, no callback
    • Removed YukiHookModulePrefs warning printed if XShare is unreadable
    • Added the isXSharePrefsReadable method in YukiHookModulePrefs to determine whether the current XShare is available

    1.0.89 | 2022.05.26  outdate

    • Fixed the problem that 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 function
    • Added YukiHookDataChannel repeated listening use case description document
    • Add the onAlreadyHooked method to determine whether the current method is repeated Hook
    • Modify part of the logic of repeatedly adding HashMap, remove the putIfAbsent method, allow to override the addition
    • Fixed several possible bugs

    1.0.88 | 2022.05.25  outdate

    • Fully decoupled from Xposed API
    • Added android type in type
    • Separate YukiHookModuleStatus from auto-generated code and add isEnableHookModuleStatus switch, it is up to you to enable or not
    • Internal closure processing for the constructors of a large number of classes in the API
    • Set YukiHookModulePrefs to run as a singleton to prevent repeated creation and waste of system resources
    • Fix the bug that Hook cannot be nested since version 1.0.80, and optimize the related functions of nested Hook
    • Modify the Hooker storage scheme from HashSet to HashMap to prevent the problem of repeatedly adding Hookers
    • Modify the core implementation method of Hook, add duplicate checking to avoid repeating the Hook multiple callbacks to the HookParam method
    • MethodFinder and FieldFinder add the function of finding fuzzy methods and variable names, you can call name { ... } to set search conditions, and support regular expressions
    • Optimize and modify the way to get appContext to reduce the possibility of getting empty
    • Modify the print TAG of logger in the automatically generated code to default to your custom name, which is convenient for debugging
    • Optimize the Hooker implementation of YukiHookBridge to improve Hook performance
    • PackageParam adds the onAppLifecycle method, which can natively monitor the life cycle of the host and implement the registration system broadcast function
    • Added YukiHookDataChannel function to communicate using system out-of-order broadcast while the module and the host remain alive
    • YukiHookDataChannel adds the checkingVersionEquals method, which can be monitored to verify that the host has not updated the version mismatch problem after the module is updated
    • Added Java version example in the example code of demo-module for reference only

    1.0.87 | 2022.05.10  outdate

    • Added refreshModuleAppResources function to adapt Resources refresh when the language region, font size, resolution changes, etc.
    • Added isEnableModuleAppResourcesCache function, you can set whether to automatically cache the resources of the current module

    1.0.86 | 2022.05.06  outdate

    • Fixed the problem of continuous error reporting during initZygote when Resources Hook is not supported, reproduced in ZUI/LSPosed CI(1.8.3-6550)
    • Optimize and handle exceptions for Resources Hook, only print errors and warnings if they are used and not supported

    1.0.85 | 2022.05.04  outdate

    • Fixed a serious problem of not being able to hook the system framework, since 1.0.80
    • Added in the debug log to distinguish the package name loaded by initZygote as android-zygote, packageName keeps android unchanged

    1.0.83 | 2022.05.04  outdate

    • Fixed YukiHookModuleStatus reporting a lot of errors after loadSystem
    • Added android type in type
    • Updated example descriptions in help documentation

    1.0.82 | 2022.05.04  outdate

    • Fixed a concept confusion error, distinguishing the relationship between initZygote and the system framework, there are problems with the previous comments and documentation, I am very sorry
    • PackageParam adds loadSystem method, no need to write loadApp(name = "android") to hook the system framework

    1.0.81 | 2022.05.04  outdate

    • 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 by method
    • 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.0.80 | 2022.05.01  outdate

    • The InjectYukiHookWithXposed annotation adds the entryClassName function, which can customize the generated xposed_init entry class name
    • YukiHookXposedInitProxy renamed to IYukiHookXposedInit, the original interface name has been invalidated and will be deleted directly in subsequent versions
    • Added initZygote and Resources Hook functions to support Hook Layout
    • Added onXposedEvent method to listen to all events of native Xposed API
    • Perform inline processing on the lambda of the Hook function to avoid generating excessively broken anonymous classes and improve the running performance after compilation
    • Fix PrefsData compiled method body copy is too large
    • Added XSharePreference readability test, which will automatically print a warning log if it fails
    • PackageParam adds appResources, moduleAppResources, moduleAppFilePath functions
    • loadApp of PackageParam adds the function of not writing name, and all APPs are filtered by default
    • PackageParam adds the loadZygote method, which can directly hook the system framework
    • PackageParam added resources().hook function
    • Optimization method, construction method, variable search function, the error log that cannot be found will display the set query conditions first
    • Added hasExtends extension method to determine whether the current Class has an inheritance relationship
    • Added isSupportResourcesHook function to determine whether resource hooks are currently supported (Resources Hook)
    • current function adds superClass method to call superclass
    • New superClass query conditions for search methods, construction methods and variables, you can continue to search in the parent class
    • YukiHookAPI lots of methods are decoupled from Xposed API
    • Added native Hook priority function of Xposed API
    • Fix the problem that isFirstApplication may be inaccurate
    • Block the problem that MiuiCatcherPatch repeatedly calls the Hook entry method on the MIUI system
    • Optimize Hook entry calling method to avoid multiple calls due to Hook Framework issues
    • Fix the problem that Hook ClassLoader causes Hook to freeze, thanks to WankkoReeopen in new window for the feedback
    • Improve the performance after the XC_Callback interface is connected
    • Java type added ClassLoader type
    • Optimize the API help documentation, fix the problem that the page may be continuously cached

    1.0.78 | 2022.04.18  outdate

    • YukiHookModulePrefs adds isRunInNewXShareMode method, which can be used to determine whether the module is currently in New XSharePreference mode
    • Fixed YukiHookModulePrefs working in New XSharePreference mode
    • Added ModulePreferenceFragment, now you can completely replace PreferenceFragmentCompat and start using the new functionality
    • Adapt the Sp data storage solution of PreferenceFragmentCompat, thanks to mahoshojoHCGopen in new window for feedback
    • Update autohandlers and Kotlin dependencies to the latest version
    • Fixed some bugs in documentation and code comments

    1.0.77 | 2022.04.15  outdate

    • YukiHookModulePrefs added clear method, thanks to WankkoReeopen in new window for the suggestion
    • YukiHookModulePrefs added getStringSet, putStringSet, all methods
    • Added any method to args of HookParam
    • Added ModuleApplication, which can be inherited in modules to achieve more functions
    • Connect all findClass functions to the Xposed API, and continue to use native ClassLoader in non-hosted environments
    • Fixed some possible bugs

    1.0.75 | 2022.04.13  outdate

    • Corrected the logic recognition part of the automatic handler, thanks to ApeaSuperzopen in new window contribution
    • Fixed an issue where the reference to a doc comment was not changed
    • firstArgs and lastArgs methods have been removed from HookParam, now you can use args().first() and args().last() instead of it
    • Removed default parameter index = 0 in args() in HookParam, now you can use args().first() or args(index = 0) to replace it
    • The result function in HookParam adds generic matching, now you can use result<T> to match the known return value type of your target method
    • The emptyParam 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 improved
    • Added android type in type

    1.0.73 | 2022.04.10  outdate

    • Fixed some Chinese translation errors in documents, thanks to WankkoReeopen in new window for their contributions
    • Fix the problem that XC_LoadPackage.LoadPackageParam throws an exception when the content is empty in some cases, thanks to Luckyzyxopen in new window for the feedback
    • Fix some known bugs and improve Hook stability

    1.0.72 | 2022.04.09  outdate

    • Update API documentation to new address
    • Add appContext function to PackageParam
    • Fix some known bugs and improve Hook stability

    1.0.71 | 2022.04.04  outdate

    • Fixed a serious issue that would stop the Hook from throwing an exception when VariousClass could not be matched

    1.0.70 | 2022.04.04  outdate

    • Fixed instanceClass reporting an error after being called in a static instance
    • Add isUseAppClassLoader function in Hook process, thanks to WankkoReeopen in new window for feedback
    • Added the withProcess function, which can be hooked according to the currently specified process of the APP
    • Fixed critical logic errors in lookup methods, constructor classes and variables
    • Fixed the problem that the abnormal output cannot be ignored when the Hook target class does not exist
    • Fixed the problem that the Hook could not take effect due to the fast loading of the APP startup method in some cases
    • Fixed allMethods not throwing an exception when it is not hooked to a method, thanks to WankkoReeopen in new window for the feedback
    • Added Hook status monitoring function, thanks to WankkoReeopen in new window for the suggestion
    • Modify the way the Xposed entry is injected into the class, and redefine the definition domain of the API
    • Added obfuscated method and variable lookup function, you can use different types of filter index to locate the specified method and variable, thanks to WankkoReeopen in new window for the ideas provided
    • When looking for methods and variables, multiple types are allowed, such as the class name declared by String and VariousClass
    • Add a new current function, which can build a reflection method operation space for any class, and easily call and modify the methods and variables in it
    • Fixed a lot of bugs in the hook process, thanks to WankkoReeopen in new window for contributing to this project

    1.0.69 | 2022.03.30  outdate

    • Added and improved annotations for some method functions
    • Added more example Hook content in Demo
    • Fixed the issue that only the last one takes effect when allMethods is used multiple times in a Hook instance, thanks to WankkoReeopen in new window for the feedback

    1.0.68 | 2022.03.29  outdate

    • Added new use case and LSPosed scope in Demo
    • Added Member lookup cache and lookup cache configuration switches
    • Removed and modified MethodFinder, FieldFinder and HookParam related method calls
    • Add more cast types in Finder and support cast as array
    • Overall performance and stability improvements
    • Fix bugs that may exist in the previous version

    1.0.67 | 2022.03.27  outdate

    • Added three modifiers functions in Finder, which can filter static, native, public, abstract and many other description types
    • When searching for methods and constructors, the method parameter type can be blurred to a specified number for searching
    • Added hasModifiers extension for Member
    • Added give method in MethodFinder and ConstructorFinder to get primitive types
    • Added PrefsData template function in YukiHookModulePrefs
    • Completely refactored method, constructor and variable lookup scheme
    • Optimized code comments and fixed possible bugs

    1.0.66 | 2022.03.25  outdate

    • Fixed a serious bug in MethodFinder
    • Added args call method in hookParam
    • Fix other possible problems and fix some class annotation problems

    1.0.65 | 2022.03.25  outdate

    • Republished version to fix the incorrect new version of the Maven repository due to cache issues
    • Added MethodFinder and FieldFinder new return value calling methods
    • Fix possible problems and fix possible problems during the use of Tai Chi
    • Fixed possible problems with auto-generated Xposed entry classes
    • Added android type and java type in type

    1.0.6 | 2022.03.20  outdate

    • Fixed YukiHookModulePrefs being ignored every time after using direct once to ignore cache
    • Added new API, abolished the traditional usage of isActive to judge module activation
    • Fixed the issue of printing debug logs when using the API in a non-Xposed environment
    • Fixed log output issue and unintercepted exception issue when looking for Field
    • Decoupling Xposed API in ReflectionUtils
    • Added YukiHookModuleStatus method name confusion to reduce the size of module generation
    • The welcome message will no longer be printed when loading the module's own Hook
    • Fix some bugs that still exist in the previous version

    1.0.55 | 2022.03.18  outdate

    • Fixed an annotation error
    • Temporarily fix a bug
    • Added a large number of android types in type and a small number of java types
    • Fix compatibility issues between new and old Kotlin APIs

    1.0.5 | 2022.03.18  outdate

    • Fixed the problem that the welcome message was printed multiple times in the case of the old version of the LSPosed framework
    • Added onInit method to configure YukiHookAPI
    • Added executorName and executorVersion to get the name and version number of the current hook framework
    • Added by method to set the timing and condition of Hook
    • YukiHookModulePrefs adds a controllable key-value cache, which can dynamically update data when the host is running
    • Fixed some possible bugs

    1.0.4 | 2022.03.06  outdate

    • Fix LSPosed cannot find XposedBridge after enabling "Only module classloader can use Xposed API" option in latest version
    • Added constant version name and version number for YukiHookAPI
    • Added hasField method and isAllowPrintingLogs configuration parameter
    • Added isDebug to enable the API to automatically print the welcome message to test whether the module is valid

    1.0.3 | 2022.03.02  outdate

    • Fixed a potential exception not intercepted BUG
    • Added ignoredError function
    • Added android type in type
    • Added ClassNotFound function after listening to hook

    1.0.2 | 2022.02.18  outdate

    • Fix the problem that the project path cannot be found under Windows
    • Remove part of reflection API, merge into BaseFinder for integration
    • Add a method to create Hook directly using string

    1.0.1 | 2022.02.15  outdate

    • RemedyPlan adds onFind function
    • Integrate and modify some reflection API code
    • Added java type in type
    • Fixed the issue that ignored errors still output in the console

    1.0 | 2022.02.14  outdate

    • The first version is submitted to Maven
    + + + diff --git a/docs/en/about/contacts.html b/docs/en/about/contacts.html new file mode 100644 index 00000000..6da9565c --- /dev/null +++ b/docs/en/about/contacts.html @@ -0,0 +1,33 @@ + + + + + + + + + Contact Us | Yuki Hook API + + + + +

    Contact Us

    If you have any questions in use, or have any constructive suggestions, you can contact us.

    Join us Click to join Telegram groupopen in new window

    Find me on Twitter @fankesyooniopen in new window

    Help with Maintenance

    Thank you for choosing and using YukiHookAPI.

    If you have code-related suggestions and requests, you can submit a Pull Request on Github.

    + + + diff --git a/docs/en/about/future.html b/docs/en/about/future.html new file mode 100644 index 00000000..0a66ca47 --- /dev/null +++ b/docs/en/about/future.html @@ -0,0 +1,33 @@ + + + + + + + + + Looking for Future | Yuki Hook API + + + + +

    Looking for Future

    The future is bright and uncertain, let us look forward to the future development space of YukiHookAPI.

    Unresolved Issues

    Here are the unresolved issues with YukiHookAPI.

    YukiHookModulePrefs

    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 selinux is a big problem currently facing, which needs to be discussed and studied.

    Future Plans

    Features that YukiHookAPI may add later are included here.

    Lite Version Supported for Standalone Use

    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.

    Support for More Hook Framework

    As an API, currently only docking XposedBridge as a compatibility layer still has certain limitations.

    Most inline hook do not have a Java compatibility layer, and the Java compatibility layer adaptation of native hook may be considered later.

    + + + diff --git a/docs/en/api/home.html b/docs/en/api/home.html new file mode 100644 index 00000000..90733304 --- /dev/null +++ b/docs/en/api/home.html @@ -0,0 +1,33 @@ + + + + + + + + + Document Introduce | Yuki Hook API + + + + +

    Document Introduce

    The document here will synchronize the relevant usage of the latest API version, please keep YukiHookAPI as the latest version to use the latest version of the function.

    Function Description

    The function description mainly introduces the related usage and purpose of the current API.

    Function Example Description

    The function examples mainly show the basic usage examples of the current API for reference.

    Change Record Description

    The function of the first version will be marked as v<version> first;

    New function added later will be marked as v<version> added;

    Later modified function will be appended as v<version> modified;

    Later deprecated function will be marked as v<version> deprecated and strikethrough;

    Later removed function will be marked as v<version> removed and strikethrough.

    • kt  Kotlin Static File

    • annotation  Annotation Class

    • interface  Interface Class

    • object  Class (Singleton)

    • class  Class

    • field  Field or get / set method or read-only get method

    • 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)

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.html b/docs/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.html new file mode 100644 index 00000000..dda84131 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.html @@ -0,0 +1,130 @@ + + + + + + + + + YukiHookAPI - object | Yuki Hook API + + + + +

    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.

    YukiHookAPI - object

    object YukiHookAPI
    +

    Change Records

    v1.0 first

    Function Illustrate

    这是 YukiHookAPI 的 API 调用总类,Hook 相关功能的开始、Hook 相关功能的配置都在这里。

    API_VERSION_NAME - field

    const val API_VERSION_NAME: String
    +

    Change Records

    v1.0.4 added

    Function Illustrate

    获取当前 YukiHookAPI 的版本。

    API_VERSION_CODE - field

    const val API_VERSION_CODE: Int
    +

    Change Records

    v1.0.4 added

    Function Illustrate

    获取当前 YukiHookAPI 的版本号。

    executorName - field

    Change Records

    v1.0.5 added

    v1.0.91 removed

    请转移到 Status.executorName

    executorVersion - field

    Change Records

    v1.0.5 added

    v1.0.91 removed

    请转移到 Status.executorVersion

    Status - object

    object Status
    +

    Change Records

    v1.0.91 added

    Function Illustrate

    当前 YukiHookAPI 的状态。

    compiledTimestamp - field

    val compiledTimestamp: Long
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获取项目编译完成的时间戳 (当前本地时间)。

    isXposedEnvironment - field

    val isXposedEnvironment: Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获取当前是否为 (Xposed) 宿主环境。

    executorName - field

    val executorName: String
    +

    Change Records

    v1.0.91 added

    Function Illustrate

    获取当前 Hook 框架的名称。

    无法获取会返回 unknownXposedBridge 不存在会返回 invalid

    Notice

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    executorVersion - field

    val executorVersion: Int
    +

    Change Records

    v1.0.91 added

    Function Illustrate

    获取当前 Hook 框架的版本。

    无法获取会返回 -1

    Notice

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    isModuleActive - field

    val isModuleActive: Boolean
    +

    Change Records

    v1.0.91 added

    Function Illustrate

    判断模块是否在 Xposed 或太极、无极中激活。

    Notice

    在模块环境中你需要将 Application 继承于 ModuleApplication

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    在 (Xposed) 宿主环境中仅返回非 isTaiChiModuleActive 的激活状态。

    isXposedModuleActive - field

    val isXposedModuleActive: Boolean
    +

    Change Records

    v1.0.91 added

    Function Illustrate

    仅判断模块是否在 Xposed 中激活。

    Notice

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    在 (Xposed) 宿主环境中始终返回 true。

    isTaiChiModuleActive - field

    val isTaiChiModuleActive: Boolean
    +

    Change Records

    v1.0.91 added

    Function Illustrate

    仅判断模块是否在太极、无极中激活。

    Notice

    在模块环境中你需要将 Application 继承于 ModuleApplication

    在 (Xposed) 宿主环境中始终返回 false。

    isSupportResourcesHook - field

    val isSupportResourcesHook: Boolean
    +

    Change Records

    v1.0.91 added

    Function Illustrate

    判断当前 Hook Framework 是否支持资源钩子(Resources Hook)。

    Notice

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    在 (Xposed) 宿主环境中可能会延迟等待事件回调后才会返回 true。

    请注意你需要确保 InjectYukiHookWithXposed.isUsingResourcesHook 已启用,否则始终返回 false。

    Configs - object

    object Configs
    +

    Change Records

    v1.0 first

    Function Illustrate

    对 API 相关功能的配置类。

    debugLog - method

    inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    配置 YukiHookLogger.Configs 相关参数。

    debugTag - field

    Change Records

    v1.0 first

    v1.1.0 deprecated

    请转移到 YukiHookLogger.Configs.tag

    isDebug - field

    var isDebug: Boolean
    +

    Change Records

    v1.0 first

    Function Illustrate

    是否启用 DEBUG 模式。

    默认为开启状态,开启后模块将会向 LogcatXposedBridge.log 打印详细的 Hook 日志,关闭后仅会打印 E 级别的日志。

    isAllowPrintingLogs - field

    Change Records

    v1.0.4 added

    v1.1.0 deprecated

    请转移到 YukiHookLogger.Configs.isEnable

    isEnableModulePrefsCache - field

    var isEnableModulePrefsCache: Boolean
    +

    Change Records

    v1.0.5 added

    Function Illustrate

    是否启用 YukiHookModulePrefs 的键值缓存功能。

    为防止内存复用过高问题,此功能默认启用。

    你可以手动在 YukiHookModulePrefs 中自由开启和关闭缓存功能以及清除缓存。

    isEnableModuleAppResourcesCache - field

    var isEnableModuleAppResourcesCache: Boolean
    +

    Change Records

    v1.0.87 added

    Function Illustrate

    是否启用当前 Xposed 模块自身 Resources 缓存功能。

    为防止内存复用过高问题,此功能默认启用。

    你可以手动调用 PackageParam.refreshModuleAppResources 来刷新缓存。

    Notice

    关闭后每次使用 PackageParam.moduleAppResources 都会重新创建,可能会造成运行缓慢。

    isEnableHookModuleStatus - field

    var isEnableHookModuleStatus: Boolean
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    是否启用 Hook Xposed 模块激活等状态功能.

    为原生支持 Xposed 模块激活状态检测,此功能默认启用。

    Notice

    关闭后你将不能再在模块环境中使用 YukiHookAPI.Status 中的激活状态判断功能。

    isEnableHookSharedPreferences - field

    var isEnableHookSharedPreferences: Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    是否启用 Hook SharedPreferences

    启用后将在模块启动时强制将 SharedPreferences 文件权限调整为 Context.MODE_WORLD_READABLE (0664)。

    Notice

    这是一个可选的实验性功能,此功能默认不启用。

    仅用于修复某些系统可能会出现在启用了 New XSharedPreferences 后依然出现文件权限错误问题,若你能正常使用 YukiHookModulePrefs 就不建议启用此功能。

    isEnableDataChannel - field

    var isEnableDataChannel: Boolean
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    是否启用当前 Xposed 模块与宿主交互的 YukiHookDataChannel 功能。

    请确保 Xposed 模块的 Application 继承于 ModuleApplication 才能有效。

    此功能默认启用,关闭后将不会在功能初始化的时候装载 YukiHookDataChannel

    isEnableMemberCache - field

    var isEnableMemberCache: Boolean
    +

    Change Records

    v1.0.68 added

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    是否启用 Member 缓存功能。

    为防止 Member 复用过高造成的系统 GC 问题,此功能默认启用。

    启用后会缓存已经找到的 MethodConstructorField

    缓存的 Member 都将处于 MemberCacheStore 的全局静态实例中。

    推荐使用 MethodFinderConstructorFinderFieldFinder 来获取 Member

    除非缓存的 Member 发生了混淆的问题,例如使用 R8 混淆后的 APP 的目标 Member,否则建议启用。

    configs - method

    inline fun configs(initiate: Configs.() -> Unit)
    +

    Change Records

    v1.0 first

    Function Illustrate

    Configs 类实现了一个 lambda 方法体。

    你可以轻松的调用它进行配置。

    Function Example

    你可以在 HookEntryClassonInit 方法中调用 configs 方法和 debugLog 方法完成对 API 的功能配置,实时生效。

    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.
    +    }
    +}
    +

    若觉得上面的写法不美观,你还可以写得更加简洁。

    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.
    +    }
    +}
    +

    你也可以不通过 configsdebugLog 方法,直接进行配置。

    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.
    +    }
    +}
    +

    encase - method

    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

    装载 Hook 入口的核心方法。

    Function Example

    详情请参考

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html b/docs/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html new file mode 100644 index 00000000..1b66dcff --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html @@ -0,0 +1,39 @@ + + + + + + + + + InjectYukiHookWithXposed - annotation | Yuki Hook API + + + + +

    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.

    InjectYukiHookWithXposed - annotation

    annotation class InjectYukiHookWithXposed(
    +    val sourcePath: String,
    +    val modulePackageName: String,
    +    val entryClassName: String,
    +    val isUsingResourcesHook: Boolean
    +)
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    新增 entryClassName 参数

    v1.0.92 modified

    新增 isUsingResourcesHook 参数

    Function Illustrate

    标识 YukiHookAPI 注入 Xposed 入口的类注解。

    Function Example

    详情请参考 InjectYukiHookWithXposed Annotation

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html new file mode 100644 index 00000000..57e43431 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html @@ -0,0 +1,48 @@ + + + + + + + + + CurrentClass - class | Yuki Hook API + + + + +

    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.

    CurrentClass - class

    class CurrentClass internal constructor(internal val classSet: Class<*>, internal val instance: Any)
    +

    Change Records

    v1.0.70 added

    v1.1.0 modified

    调整了构造方法的参数名称

    Function Illustrate

    当前实例的类操作对象。

    name - field

    val name: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前 classSetClass.getName

    simpleName - field

    val simpleName: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前 classSetClass.getSimpleName

    generic - method

    fun generic(): GenericClass?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前实例中的泛型父类。

    如果当前实例不存在泛型将返回 null

    generic - method

    inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前实例中的泛型父类。

    如果当前实例不存在泛型将返回 null

    superClass - method

    fun superClass(): SuperClass
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    调用父类实例。

    field - method

    inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    调用当前实例中的变量。

    method - method

    inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    调用当前实例中的方法。

    SuperClass - class

    inner class SuperClass internal constructor(internal val superClassSet: Class<*>)
    +

    Change Records

    v1.0.80 added

    v1.1.0 modified

    新增 superClassSet 参数

    Function Illustrate

    当前类的父类实例的类操作对象。

    name - field

    val name: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前 classSet 中父类的 Class.getName

    simpleName - field

    val simpleName: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前 classSet 中父类的 Class.getSimpleName

    generic - method

    fun generic(): GenericClass?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前实例父类中的泛型父类。

    如果当前实例不存在泛型将返回 null

    generic - method

    inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前实例父类中的泛型父类。

    如果当前实例不存在泛型将返回 null

    field - method

    inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    调用父类实例中的变量。

    method - method

    inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    调用父类实例中的方法。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html new file mode 100644 index 00000000..df1da879 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html @@ -0,0 +1,35 @@ + + + + + + + + + GenericClass - class | Yuki Hook API + + + + +

    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.

    GenericClass - class

    class GenericClass internal constructor(private val type: ParameterizedType)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    当前 Class 的泛型父类操作对象。

    argument - method

    fun argument(index: Int): Class<*>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得泛型参数数组下标的 Class 实例。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html new file mode 100644 index 00000000..335ae9a9 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html @@ -0,0 +1,34 @@ + + + + + + + + + HookClass - class | Yuki Hook API + + + + +

    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.

    HookClass - class

    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 相关功能不再对外开放

    Function Illustrate

    创建一个当前 Hook 的 Class 接管类。

    instance 为实例,name 为实例完整包名,throwable 为找不到实例的时候抛出的异常。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html new file mode 100644 index 00000000..d6756cb1 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html @@ -0,0 +1,34 @@ + + + + + + + + + HookResources - class | Yuki Hook API + + + + +

    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.

    HookResources - class

    class HookResources internal constructor(var instance: YukiResources?)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    创建一个当前 Hook 的 YukiResources 接管类。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html new file mode 100644 index 00000000..d3912c53 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html @@ -0,0 +1,36 @@ + + + + + + + + + VariousClass - class | Yuki Hook API + + + + +

    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.

    VariousClass - class

    class VariousClass(vararg var name: String)
    +

    Change Records

    v1.0 first

    Function Illustrate

    这是一个不确定性 Class 类名装载器,通过 name 装载 Class 名称数组。

    get - method

    fun get(loader: ClassLoader? = null): Class<*>
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    获取匹配的实体类。

    使用当前 loader 装载目标 Class

    getOrNull - method

    fun getOrNull(loader: ClassLoader? = null): Class<*>?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获取匹配的实体类。

    使用当前 loader 装载目标 Class

    匹配不到 Class 会返回 null,不会抛出异常。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html new file mode 100644 index 00000000..ee89dfdc --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html @@ -0,0 +1,153 @@ + + + + + + + + + YukiMemberHookCreator - class | Yuki Hook API + + + + +

    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.

    YukiMemberHookCreator - class

    class YukiMemberHookCreator(internal val packageParam: PackageParam, internal val hookClass: HookClass)
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    hookClass 进行 inline 处理

    v1.1.0 modified

    修正拼写错误的 Creater 命名到 Creator

    Function Illustrate

    YukiHookAPIMember 核心 Hook 实现类。

    PRIORITY_DEFAULT - field

    val PRIORITY_DEFAULT: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    默认 Hook 回调优先级。

    PRIORITY_LOWEST - field

    val PRIORITY_LOWEST: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    延迟回调 Hook 方法结果。

    PRIORITY_HIGHEST - field

    val PRIORITY_HIGHEST: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    更快回调 Hook 方法结果。

    instanceClass - field

    val instanceClass: Class<*>
    +

    Change Records

    v1.0 first

    v1.0.2 modified

    thisClass 更名为 instanceClass

    Function Illustrate

    得到当前被 Hook 的 Class

    Pay Attention

    不推荐直接使用,万一得不到 Class 对象则会无法处理异常导致崩溃。

    injectMember - method

    inline fun injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    增加 priority Hook 优先级

    Function Illustrate

    注入要 Hook 的 MethodConstructor

    Function Example

    你可以注入任意 MethodConstructor,使用 injectMember 即可创建一个 Hook 对象。

    The following example

    injectMember {
    +    // Your code here.
    +}
    +

    你还可以自定义 tag,方便你在调试的时候能够区分你的 Hook 对象。

    The following example

    injectMember(tag = "KuriharaYuki") {
    +    // Your code here.
    +}
    +

    你还可以自定义 priority,以控制当前 Hook 对象并列执行的优先级速度。

    The following example

    injectMember(priority = PRIORITY_HIGHEST) {
    +    // Your code here.
    +}
    +

    useDangerousOperation - method

    fun useDangerousOperation(option: String)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    允许 Hook 过程中的所有危险行为。

    请在 option 中键入 Yes do as I say! 代表你同意允许所有危险行为。

    你还需要在整个调用域中声明注解 CauseProblemsApi 以消除警告。

    若你只需要 Hook ClassLoaderloadClass 方法,请参考 ClassLoader.onLoadClass

    Pay Attention

    若你不知道允许此功能会带来何种后果,请勿使用。

    MemberHookCreator - class

    inner class MemberHookCreator internal constructor(private val priority: Int, internal val tag: String)
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    增加 priority Hook 优先级

    v1.0.81 modified

    增加 packageName 当前 Hook 的 APP 包名

    v1.1.0 modified

    移除 packageName

    修正拼写错误的 Creater 命名到 Creator

    Function Illustrate

    Hook 核心功能实现类,查找和处理需要 Hook 的 MethodConstructor

    member - field

    Change Records

    v1.0 first

    v1.1.0 removed

    请转移到 members

    members - method

    fun members(vararg member: Member?)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    手动指定要 Hook 的 MethodConstructor

    Notice

    不建议使用此方法设置目标需要 Hook 的 Member 对象,你可以使用 methodconstructor 方法。

    Function Example

    你可以调用 instanceClass 来手动查找要 Hook 的 MethodConstructor

    The following example

    injectMember {
    +    members(instanceClass.getDeclaredMethod("test", StringType))
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    同样地,你也可以传入一组 Member 同时进行 Hook。

    The following example

    injectMember {
    +    members(
    +        instanceClass.getDeclaredMethod("test1", StringType),
    +        instanceClass.getDeclaredMethod("test2", StringType),
    +        instanceClass.getDeclaredMethod("test3", StringType)
    +    )
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    allMethods - method

    Change Records

    v1.0 first

    v1.1.0 deprecated

    请使用 method { name = /** name */ }.all() 来取代它

    allConstructors - method

    Change Records

    v1.0 first

    v1.1.0 deprecated

    请使用 allMembers(MembersType.CONSTRUCTOR) 来取代它

    allMembers - method

    fun allMembers(type: MembersType)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    查找并 Hook hookClass 中的全部 MethodConstructor

    Notice

    无法准确处理每个 Member 的返回值和 param,建议使用 method or constructor 对每个 Member 单独 Hook。

    method - method

    inline fun method(initiate: MethodConditions): MethodFinder.Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    查找当前 Class 需要 Hook 的 Method

    Function Example

    你可参考 MethodFinder 查看详细用法。

    The following example

    injectMember {
    +    method {
    +        name = "test"
    +        param(StringType)
    +        returnType = UnitType
    +    }
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    若想 Hook 当前查找 method { ... } 条件的全部结果,你只需要在最后加入 all 即可。

    The following example

    injectMember {
    +    method {
    +        name = "test"
    +        paramCount(1..5)
    +    }.all()
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    此时 beforeHookafterHook 会在每个查找到的结果中多次回调 Hook 方法体。

    Notice

    若没有 all,默认只会 Hook 当前条件查找到的数组下标结果第一位。

    constructor - method

    inline fun constructor(initiate: ConstructorConditions): ConstructorFinder.Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    查找当前 Class 需要 Hook 的 Constructor

    Function Example

    你可参考 ConstructorFinder 查看详细用法。

    The following example

    injectMember {
    +    constructor { param(StringType) }
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    若想 Hook 当前查找 constructor { ... } 条件的全部结果,你只需要在最后加入 all 即可。

    The following example

    injectMember {
    +    constructor { paramCount(1..5) }.all()
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    此时 beforeHookafterHook 会在每个查找到的结果中多次回调 Hook 方法体。

    Notice

    若没有 all,默认只会 Hook 当前条件查找到的数组下标结果第一位。

    HookParam.field - i-ext-method

    inline fun HookParam.field(initiate: FieldConditions): FieldFinder.Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    使用当前 hookClass 查找并得到 Field

    Function Example

    你可参考 FieldFinder 查看详细用法。

    The following example

    injectMember {
    +    method {
    +        name = "test"
    +        param(StringType)
    +        returnType = UnitType
    +    }
    +    afterHook {
    +        // 这里不需要再调用 instanceClass.field 进行查找
    +        field {
    +            name = "isSweet"
    +            type = BooleanType
    +        }.get(instance).setTrue()
    +    }
    +}
    +

    HookParam.method - i-ext-method

    inline fun HookParam.method(initiate: MethodConditions): MethodFinder.Result
    +

    Change Records

    v1.0.2 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    使用当前 hookClass 查找并得到 Method

    HookParam.constructor - i-ext-method

    inline fun HookParam.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
    +

    Change Records

    v1.0.2 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    使用当前 hookClass 查找并得到 Constructor

    HookParam.injectMember - i-ext-method

    inline fun HookParam.injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    注入要 Hook 的 MethodConstructor (嵌套 Hook)。

    beforeHook - method

    fun beforeHook(initiate: HookParam.() -> Unit): HookCallback
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    新增 HookCallback 返回类型

    Function Illustrate

    Member 执行完成前 Hook。

    afterHook - method

    fun afterHook(initiate: HookParam.() -> Unit): HookCallback
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    新增 HookCallback 返回类型

    Function Illustrate

    Member 执行完成后 Hook。

    replaceAny - method

    fun replaceAny(initiate: HookParam.() -> Any?)
    +

    Change Records

    v1.0 first

    Function Illustrate

    拦截并替换此 Member 内容,给出返回值。

    replaceUnit - method

    fun replaceUnit(initiate: HookParam.() -> Unit)
    +

    Change Records

    v1.0 first

    Function Illustrate

    拦截并替换此 Member 内容,没有返回值,可以称为 Void

    replaceTo - method

    fun replaceTo(any: Any?)
    +

    Change Records

    v1.0 first

    Function Illustrate

    拦截并替 Member 返回值。

    replaceToTrue - method

    fun replaceToTrue()
    +

    Change Records

    v1.0 first

    Function Illustrate

    拦截并替换 Member 返回值为 true

    Pay Attention

    确保替换 Member 的返回对象为 Boolean

    replaceToFalse - method

    fun replaceToFalse()
    +

    Change Records

    v1.0 first

    Function Illustrate

    拦截并替换 Member 返回值为 false

    Pay Attention

    确保替换 Member 的返回对象为 Boolean

    intercept - method

    fun intercept()
    +

    Change Records

    v1.0 first

    Function Illustrate

    拦截此 Member

    这将会禁止此 Member 执行并返回 null

    Pay Attention

    例如 IntLongBoolean 常量返回值的 Member 一旦被设置为 null 可能会造成 Hook APP 抛出异常。

    removeSelf - method

    fun removeSelf(result: (Boolean) -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    移除当前注入的 Hook MethodConstructor (解除 Hook)。

    Pay Attention

    你只能在 Hook 回调方法中使用此功能。

    HookCallback - class

    inner class HookCallback internal constructor()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Hook 方法体回调实现类。

    onFailureThrowToApp - method

    fun onFailureThrowToApp()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    当回调方法体内发生异常时将异常抛出给当前 Hook APP。

    Result - class

    inner class Result internal constructor()
    +

    Change Records

    v1.0 first

    Function Illustrate

    监听 Hook 结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.5 modified

    failures 修改为 result

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建监听失败事件方法体。

    Function Example

    你可以使用此方法为 Result 类创建 lambda 方法体。

    The following example

    injectMember {
    +    // Your code here.
    +}.result {
    +    onHooked {}
    +    onAlreadyHooked {}
    +    ignoredConductFailure()
    +    onHookingFailure {}
    +    // ...
    +}
    +

    by - method

    inline fun by(condition: () -> Boolean): Result
    +

    Change Records

    v1.0.5 added

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。

    onHooked - method

    fun onHooked(result: (Member) -> Unit): Result
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    监听 members Hook 成功的回调方法。

    在首次 Hook 成功后回调。

    在重复 Hook 时会回调 onAlreadyHooked

    onAlreadyHooked - method

    fun onAlreadyHooked(result: (Member) -> Unit): Result
    +

    Change Records

    v1.0.89 added

    Function Illustrate

    监听 members 重复 Hook 的回调方法。

    Notice

    同一个 hookClass 中的同一个 members 不会被 API 重复 Hook,若由于各种原因重复 Hook 会回调此方法。

    onNoSuchMemberFailure - method

    fun onNoSuchMemberFailure(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.0.5 added

    Function Illustrate

    监听 members 不存在发生错误的回调方法。

    onConductFailure - method

    fun onConductFailure(result: (HookParam, Throwable) -> Unit): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    监听 Hook 进行过程中发生错误的回调方法。

    onHookingFailure - method

    fun onHookingFailure(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    监听 Hook 开始时发生的错误的回调方法。

    onAllFailure - method

    fun onAllFailure(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    监听全部 Hook 过程发生错误的回调方法。

    ignoredNoSuchMemberFailure - method

    fun ignoredNoSuchMemberFailure(): Result
    +

    Change Records

    v1.0.5 added

    Function Illustrate

    忽略 members 不存在发生的错误。

    ignoredConductFailure - method

    fun ignoredConductFailure(): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    忽略 Hook 进行过程中发生的错误。

    ignoredHookingFailure - method

    fun ignoredHookingFailure(): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    忽略 Hook 开始时发生的错误。

    ignoredAllFailure - method

    fun ignoredAllFailure(): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    忽略全部 Hook 过程发生的错误。

    remove - method

    fun remove(result: (Boolean) -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    移除当前注入的 Hook MethodConstructor (解除 Hook)。

    Notice

    你只能在 Hook 成功后才能解除 Hook,可监听 onHooked 事件。

    Result - class

    inner class Result internal constructor()
    +

    Change Records

    v1.0.3 added

    Function Illustrate

    监听全部 Hook 结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.0.3 added

    v1.0.5 modified

    failures 修改为 result

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建监听事件方法体。

    by - method

    inline fun by(condition: () -> Boolean): Result
    +

    Change Records

    v1.0.5 added

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。

    onPrepareHook - method

    fun onPrepareHook(callback: () -> Unit): Result
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    监听 hookClass 存在时准备开始 Hook 的操作。

    onHookClassNotFoundFailure - method

    fun onHookClassNotFoundFailure(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.0.3 added

    Function Illustrate

    监听 hookClass 找不到时发生错误的回调方法。

    ignoredHookClassNotFoundFailure - method

    fun ignoredHookClassNotFoundFailure(): Result
    +

    Change Records

    v1.0.3 added

    Function Illustrate

    忽略 hookClass 找不到时出现的错误。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html new file mode 100644 index 00000000..c6c1615e --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html @@ -0,0 +1,127 @@ + + + + + + + + + YukiResourcesHookCreator - class | Yuki Hook API + + + + +

    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.

    YukiResourcesHookCreator - class

    class YukiResourcesHookCreator(internal val packageParam: PackageParam, internal val hookResources: HookResources)
    +

    Change Records

    v1.0.80 added

    v1.1.0 modified

    修正拼写错误的 Creater 命名到 Creator

    Function Illustrate

    YukiHookAPIResources 核心 Hook 实现类。

    injectResource - method

    inline fun injectResource(tag: String, initiate: ResourceHookCreator.() -> Unit): ResourceHookCreator.Result
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    注入要 Hook 的 Resources。

    Function Example

    你可以注入任意 Resources,使用 injectResource 即可创建一个 Hook 对象。

    The following example

    injectResource {
    +    // Your code here.
    +}
    +

    你还可以自定义 tag,方便你在调试的时候能够区分你的 Hook 对象。

    The following example

    injectResource(tag = "KuriharaYuki") {
    +    // Your code here.
    +}
    +

    ResourcesHookCreator - class

    inner class ResourcesHookCreator internal constructor(private val tag: String)
    +

    Change Records

    v1.0.80 added

    v1.1.0 modified

    移除 packageName

    修正拼写错误的 Creater 命名到 Creator

    Function Illustrate

    Hook 核心功能实现类。

    查找和处理需要 Hook 的 Resources。

    resourceId - field

    var resourceId: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    直接设置需要替换的 Resources Id。

    Notice

    不建议使用此方法设置目标需要 Hook 的 Resources Id,你可以使用 conditions 方法。

    Function Example

    你可以直接设置并指定目标 Hook APP 的 Resources Id。

    The following example

    injectResource {
    +    resourceId = 0x7f060001.toInt()
    +    replaceTo(...)
    +}
    +

    conditions - method

    inline fun conditions(initiate: ConditionFinder.() -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 查找条件。

    若你设置了 resourceId 则此方法将不会被使用。

    Function Example

    你可参考 ConditionFinder 查看详细用法。

    The following example

    injectResource {
    +    conditions {
    +        name = "test_string"
    +        string()
    +    }
    +    replaceTo(...)
    +}
    +

    replaceTo - method

    fun replaceTo(any: Any)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    替换指定 Resources 为指定的值。

    Function Example

    你可以替换找到的 Resources 为你想要的值,可以是 StringDrawable 等。

    比如我们要替换一个找到的字符串 Resources。

    The following example

    injectResource {
    +    conditions {
    +        name = "test_string"
    +        string()
    +    }
    +    replaceTo("replace string")
    +}
    +

    或是替换为一个 Drawable,你无需对目标 Resources 实现 fwd 方法或 DrawableLoader

    The following example

    injectResource {
    +    conditions {
    +        name = "test_drawable"
    +        drawable()
    +    }
    +    replaceTo(ColorDrawable(Color.RED))
    +}
    +

    replaceToTrue - method

    fun replaceToTrue()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    替换指定 Resources 为 true

    Pay Attention

    确保目标替换 Resources 的类型为 Boolean

    replaceToFalse - method

    fun replaceToFalse()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    替换指定 Resources 为 false

    Pay Attention

    确保目标替换 Resources 的类型为 Boolean

    replaceToModuleResource - method

    fun replaceToModuleResource(resId: Int)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    替换为当前 Xposed 模块的 Resources。

    你可以直接使用模块的 R.string.xxxR.mipmap.xxxR.drawable.xxx 替换 Hook APP 的 Resources。

    Function Example

    使用此方法可非常方便地使用当前模块的 Resources 去替换目标 Hook APP 的 Resources。

    这个过程你无需对目标 Resources 实现 fwd 方法。

    比如我们要替换一个字符串。

    The following example

    injectResource {
    +    conditions {
    +        name = "test_string"
    +        string()
    +    }
    +    replaceToModuleResource(R.string.module_string)
    +}
    +

    还可以替换一些复杂的 Resources,比如 xml 创建的 drawable

    The following example

    injectResource {
    +    conditions {
    +        name = "test_drawable"
    +        drawable()
    +    }
    +    replaceToModuleResource(R.drawable.module_drawable)
    +}
    +

    injectAsLayout - method

    fun injectAsLayout(initiate: YukiResources.LayoutInflatedParam.() -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    作为装载的布局注入。

    Function Example

    你可以直接注入一个布局监听并修改它的内部 View

    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"
    +    }
    +}
    +

    你还可以通过 currentView 拿到 Context

    The following example

    injectResource {
    +    conditions {
    +        name = "activity_main"
    +        layout()
    +    }
    +    injectAsLayout {
    +        Toast.makeText(currentView.context, "Hook this", Toast.LENGTH_SHORT).show()
    +    }
    +}
    +

    ConditionFinder - class

    inner class ConditionFinder internal constructor()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    Resources 查找条件实现类。

    name - field

    var name: String
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 名称。

    anim - method

    fun anim()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为动画。

    animator - method

    fun animator()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为属性动画。

    bool - method

    fun bool()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为布朗(Boolean)。

    color - method

    fun color()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为颜色(Color)。

    dimen - method

    fun dimen()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为尺寸(Dimention)。

    drawable - method

    fun drawable()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为 Drawable。

    integer - method

    fun integer()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为整型(Integer)。

    layout - method

    fun layout()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为布局(Layout)。

    plurals - method

    fun plurals()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为 Plurals。

    string - method

    fun string()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为字符串(String)。

    xml - method

    fun xml()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为 Xml。

    mipmap - method

    fun mipmap()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 Resources 类型为位图(Mipmap)。

    array - method

    fun array()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Resources 类型为数组(Array)。

    Result - class

    inner class Result internal constructor()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    监听全部 Hook 结果实现类,可在这里处理失败事件监听。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    创建监听事件方法体。

    by - method

    inline fun by(condition: () -> Boolean): Result
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。

    onHookingFailure - method

    fun onHookingFailure(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    监听 Hook 过程发生错误的回调方法。

    ignoredHookingFailure - method

    fun ignoredHookingFailure(): Result
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    忽略 Hook 过程出现的错误。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html new file mode 100644 index 00000000..ee7cf8e2 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html @@ -0,0 +1,41 @@ + + + + + + + + + BaseFinder - class | Yuki Hook API + + + + +

    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.

    BaseFinder - class

    abstract class BaseFinder
    +

    Change Records

    v1.0.70 added

    v1.1.0 modified

    分离原始命名 BaseFinder 中的部分方法与参数到 MemberBaseFinder

    Function Illustrate

    这是 ClassMember 查找类功能的基本类实现。

    BaseFinder.IndexTypeCondition - class

    inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    字节码下标筛选实现类。

    index - method

    fun index(num: Int)
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置下标。

    index 小于零则为倒序,此时可以使用 IndexTypeConditionSort.reverse 方法实现。

    可使用 IndexTypeConditionSort.firstIndexTypeConditionSort.last 设置首位和末位筛选条件。

    index - method

    fun index(): IndexTypeConditionSort
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    得到下标。

    IndexTypeConditionSort - class

    inner class IndexTypeConditionSort internal constructor()
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    字节码下标排序实现类。

    first - method

    fun first()
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置满足条件的第一个。

    last - method

    fun last()
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置满足条件的最后一个。

    reverse - method

    fun reverse(num: Int)
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置倒序下标。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html new file mode 100644 index 00000000..897edcf6 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html @@ -0,0 +1,38 @@ + + + + + + + + + CountRules - class | Yuki Hook API + + + + +

    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.

    CountRules - class

    class CountRules private constructor()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    这是一个模糊 ClassMember 数组 (下标) 个数条件实现类。

    可对 R8 混淆后的 ClassMember 进行更加详细的定位。

    Int.isZero - i-ext-method

    fun Int.isZero(): Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    是否为 0。

    Int.moreThan - i-ext-method

    fun Int.moreThan(count: Int): Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    大于 count

    Int.lessThan - i-ext-method

    fun Int.lessThan(count: Int): Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    小于 count

    Int.inInterval - i-ext-method

    fun Int.inInterval(countRange: IntRange): Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    countRange 区间 A ≤ this ≤ B。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html new file mode 100644 index 00000000..3b71e2f0 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html @@ -0,0 +1,46 @@ + + + + + + + + + ModifierRules - class | Yuki Hook API + + + + +

    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.

    ModifierRules - class

    class ModifierRules private constructor()
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    新增 Class 的描述符判断

    作为 lambda 整体判断条件使用

    移动到 base 包名

    私有化构造方法

    Function Illustrate

    这是一个 ClassMember 描述符条件实现类。

    可对 R8 混淆后的 ClassMember 进行更加详细的定位。

    isPublic - i-ext-field

    val isPublic: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    ClassMember 类型是否包含 public

    isPrivate - i-ext-field

    val isPrivate: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    ClassMember 类型是否包含 private

    isProtected - i-ext-field

    val isProtected: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    ClassMember 类型是否包含 protected

    isStatic - i-ext-field

    val isStatic: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    ClassMember 类型是否包含 static

    对于任意的静态 ClassMember 可添加此描述进行确定。

    Notice

    Kotlin → Jvm 后的 object 类中的方法并不是静态的。

    isFinal - i-ext-field

    val isFinal: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    ClassMember 类型是否包含 final

    Notice

    Kotlin → Jvm 后没有 open 符号标识的 ClassMember 和没有任何关联的 ClassMember 都将为 final

    isSynchronized - i-ext-field

    val isSynchronized: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    ClassMember 类型是否包含 synchronized

    isVolatile - i-ext-field

    val isVolatile: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    Field 类型是否包含 volatile

    isTransient - i-ext-field

    val isTransient: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    Field 类型是否包含 transient

    isNative - i-ext-field

    val isNative: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    Method 类型是否包含 native

    对于任意 JNI 对接的 Method 可添加此描述进行确定。

    isInterface - i-ext-field

    val isInterface: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    Class 类型是否包含 interface

    isAbstract - i-ext-field

    val isAbstract: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    ClassMember 类型是否包含 abstract

    对于任意的抽象 ClassMember 可添加此描述进行确定。

    isStrict - i-ext-field

    val isStrict: Boolean
    +

    Change Records

    v1.0.67 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    ClassMember 类型是否包含 strictfp

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html new file mode 100644 index 00000000..9eaf198f --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html @@ -0,0 +1,41 @@ + + + + + + + + + NameRules - class | Yuki Hook API + + + + +

    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.

    NameRules - class

    class NameRules private constructor()
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    NameConditions 更名为 NameRules

    作为 lambda 整体判断条件使用

    移动到 base 包名

    私有化构造方法

    Function Illustrate

    这是一个模糊 ClassMember 名称条件实现类。

    可对 R8 混淆后的 ClassMember 进行更加详细的定位。

    String.isSynthetic - i-ext-method

    fun String.isSynthetic(index: Int): Boolean
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    是否为匿名类的主类调用对象。

    String.isOnlySymbols - i-ext-method

    fun String.isOnlySymbols(): Boolean
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    是否只有符号。

    String.isOnlyLetters - i-ext-method

    fun String.isOnlyLetters(): Boolean
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    是否只有字母。

    String.isOnlyNumbers - i-ext-method

    fun String.isOnlyNumbers(): Boolean
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    是否只有数字。

    String.isOnlyLettersNumbers - i-ext-method

    fun String.isOnlyLettersNumbers(): Boolean
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    是否只有字母或数字。

    String.isOnlyLowercase - i-ext-method

    fun String.isOnlyLowercase(): Boolean
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    是否只有小写字母。

    在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。

    String.isOnlyUppercase - i-ext-method

    fun String.isOnlyUppercase(): Boolean
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    统一合并到扩展方法并改名

    Function Illustrate

    是否只有大写字母。

    在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html new file mode 100644 index 00000000..c8272d08 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html @@ -0,0 +1,77 @@ + + + + + + + + + DexClassFinder - class | Yuki Hook API + + + + +

    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.

    DexClassFinder - class

    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 查找类。

    可使用 BaseDexClassLoader 通过指定条件查找指定 Class 或一组 Class

    Notice

    此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。

    companion object - object

    Change Records

    v1.1.0 added

    clearCache - method

    fun clearCache(context: Context?, versionName: String?, versionCode: Long?)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    清除当前 DexClassFinderClass 缓存。

    适用于全部通过 ClassLoader.searchClassPackageParam.searchClass 获取的 DexClassFinder

    fullName - field

    var fullName: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 完整名称。

    只会查找匹配到的 Class.getName

    例如 com.demo.Test 需要填写 com.demo.Test

    simpleName - field

    var simpleName: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 简单名称。

    只会查找匹配到的 Class.getSimpleName

    例如 com.demo.Test 只需要填写 Test

    对于匿名类例如 com.demo.Test$InnerTest 会为空,此时你可以使用 singleName

    singleName - field

    var singleName: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 独立名称。

    设置后将首先使用 Class.getSimpleName,若为空则会使用 Class.getName 进行处理。

    例如 com.demo.Test 只需要填写 Test

    对于匿名类例如 com.demo.Test$InnerTest 只需要填写 Test$InnerTest

    from - method

    fun from(vararg name: String): FromPackageRules
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置在指定包名范围查找当前 Class

    设置后仅会在当前 name 开头匹配的包名路径下进行查找,可提升查找速度。

    例如 ↓

    com.demo.test

    com.demo.test.demo

    Notice

    建议设置此参数指定查找范围,否则 Class 过多时将会非常慢。

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 标识符筛选条件。

    可不设置筛选条件。

    fullName - method

    fun fullName(value: String): ClassNameRules
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 完整名称。

    只会查找匹配到的 Class.getName

    例如 com.demo.Test 需要填写 com.demo.Test

    simpleName - method

    fun simpleName(value: String): ClassNameRules
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 简单名称。

    只会查找匹配到的 Class.getSimpleName

    例如 com.demo.Test 只需要填写 Test

    对于匿名类例如 com.demo.Test$InnerTest 会为空,此时你可以使用 singleName

    singleName - method

    fun singleName(value: String): ClassNameRules
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 独立名称。

    设置后将首先使用 Class.getSimpleName,若为空则会使用 Class.getName 进行处理。

    例如 com.demo.Test 只需要填写 Test

    对于匿名类例如 com.demo.Test$InnerTest 只需要填写 Test$InnerTest

    fullName - method

    fun fullName(conditions: NameConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 完整名称条件。

    只会查找匹配到的 Class.getName

    simpleName - method

    fun simpleName(conditions: NameConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 简单名称条件。

    只会查找匹配到的 Class.getSimpleName

    singleName - method

    fun singleName(conditions: NameConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 独立名称条件。

    设置后将首先使用 Class.getSimpleName,若为空则会使用 Class.getName 进行处理。

    extends - method

    inline fun <reified T> extends()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 继承的父类。

    extends - method

    fun extends(vararg name: String)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 继承的父类。

    会同时查找 name 中所有匹配的父类。

    implements - method

    inline fun <reified T> implements()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 实现的接口类。

    implements - method

    fun implements(vararg name: String)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 实现的接口类。

    会同时查找 name 中所有匹配的接口类。

    anonymous - method

    fun anonymous()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    标识 Class 为匿名类。

    例如 com.demo.Test$1com.demo.Test$InnerTest

    标识后你可以使用 enclosing 来进一步指定匿名类的 (封闭类) 主类。

    noExtends - method

    fun noExtends()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 没有任何继承。

    此时 Class 只应该继承于 Any

    Notice

    设置此条件后 extends 将失效。

    noImplements - method

    fun noImplements()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 没有任何接口。

    Notice

    设置此条件后 implements 将失效。

    noSuper - method

    fun noSuper()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 没有任何继承与接口。

    此时 Class 只应该继承于 Any

    Notice

    设置此条件后 extendsimplements 将失效。

    enclosing - method

    inline fun <reified T> enclosing()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 匿名类的 (封闭类) 主类。

    enclosing - method

    fun enclosing(vararg name: String)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 匿名类的 (封闭类) 主类。

    会同时查找 name 中所有匹配的 (封闭类) 主类。

    FromPackageRules - class

    inner class FromPackageRules internal constructor(private val packages: ArrayList<ClassRulesData.PackageRulesData>)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    包名范围名称过滤匹配条件实现类。

    absolute - method

    fun absolute()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置包名绝对匹配。

    例如有如下包名 ↓

    com.demo.test.a

    com.demo.test.a.b

    com.demo.test.active

    若包名条件为 com.demo.test.a 则绝对匹配仅能匹配到第一个。

    相反地,不设置以上示例会全部匹配。

    ClassNameRules - class

    inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    类名匹配条件实现类。

    optional - method

    fun optional()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置类名可选。

    例如有如下类名 ↓

    com.demo.Test fullName / Test simpleName

    defpackage.a fullName / a simpleName

    这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。

    此时可设置类名为 com.demo.Test fullName / Test simpleName

    这样就可在完全匹配类名情况下使用类名而忽略其它查找条件,否则忽略此条件继续使用其它查找条件。

    member - method

    inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 满足的 Member 条件。

    field - method

    inline fun field(initiate: FieldRules.() -> Unit): MemberRulesResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 满足的 Field 条件。

    method - method

    inline fun method(initiate: MethodRules.() -> Unit): MemberRulesResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 满足的 Method 条件。

    constructor - method

    inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Class 满足的 Constructor 条件。

    Result - class

    inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Class 查找结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    创建监听结果事件方法体。

    get - method

    fun get(): Class<*>?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到 Class 本身。

    若有多个 Class 结果只会返回第一个。

    在查找条件找不到任何结果的时候将返回 null

    若你设置了 async 请使用 wait 方法。

    all - method

    fun all(): HashSet<Class<*>>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到 Class 本身数组。

    返回全部查找条件匹配的多个 Class 实例。

    在查找条件找不到任何结果的时候将返回空的 HashSet

    若你设置了 async 请使用 waitAll 方法。

    all - method

    fun all(result: (Class<*>) -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到 Class 本身数组 (依次遍历)。

    回调全部查找条件匹配的多个 Class 实例。

    在查找条件找不到任何结果的时候将不会执行。

    若你设置了 async 请使用 waitAll 方法。

    wait - method

    fun wait(result: (Class<*>?) -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到 Class 本身 (异步)。

    若有多个 Class 结果只会回调第一个。

    在查找条件找不到任何结果的时候将回调 null。

    你需要设置 async 后此方法才会被回调,否则请使用 get 方法。

    waitAll - method

    fun waitAll(result: (HashSet<Class<*>>) -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到 Class 本身数组 (异步)。

    回调全部查找条件匹配的多个 Class 实例。

    在查找条件找不到任何结果的时候将回调空的 HashSet

    你需要设置 async 后此方法才会被回调,否则请使用 all 方法。

    onNoClassDefFoundError - method

    fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    监听找不到 Class 时。

    ignored - method

    fun ignored(): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    忽略异常并停止打印任何错误日志。

    此时若要监听异常结果,你需要手动实现 onNoClassDefFoundError 方法。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html new file mode 100644 index 00000000..7866dd59 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html @@ -0,0 +1,40 @@ + + + + + + + + + ConstructorRules - class | Yuki Hook API + + + + +

    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.

    ConstructorRules - class

    class ConstructorRules internal constructor(internal val rulesData: ConstructorRulesData) : BaseRules
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Constructor 查找条件实现类。

    paramCount - field

    var paramCount: Int
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Constructor 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此变量指定参数个数。

    若参数个数小于零则忽略并使用 param

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Constructor 标识符筛选条件。

    可不设置筛选条件。

    emptyParam - method

    fun emptyParam()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Constructor 空参数、无参数。

    param - method

    fun param(vararg paramType: Any)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Constructor 参数。

    如果同时使用了 paramCountparamType 的数量必须与 paramCount 完全匹配。

    如果 Constructor 中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。

    Pay Attention

    无参 Constructor 请使用 emptyParam 设置查找条件。

    有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。

    paramCount - method

    fun paramCount(numRange: IntRange)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Constructor 参数个数范围。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数范围。

    paramCount - method

    fun paramCount(conditions: CountConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Constructor 参数个数条件。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数条件。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html new file mode 100644 index 00000000..3052cfaa --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html @@ -0,0 +1,38 @@ + + + + + + + + + FieldRules - class | Yuki Hook API + + + + +

    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.

    FieldRules - class

    class FieldRules internal constructor(internal val rulesData: FieldRulesData) : BaseRules
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Field 查找条件实现类。

    name - field

    var name: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Field 名称。

    type - field

    var type: Any?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Field 类型。

    可不填写类型。

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Field 标识符筛选条件。

    可不设置筛选条件。

    name - method

    fun name(conditions: NameConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Field 名称条件。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html new file mode 100644 index 00000000..83ce7103 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html @@ -0,0 +1,35 @@ + + + + + + + + + MemberRules - class | Yuki Hook API + + + + +

    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.

    MemberRules - class

    class MemberRules internal constructor(internal val rulesData: MemberRulesData) : BaseRules
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Member 查找条件实现类。

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Member 标识符筛选条件。

    可不设置筛选条件。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html new file mode 100644 index 00000000..f65e279f --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html @@ -0,0 +1,43 @@ + + + + + + + + + MethodRules - class | Yuki Hook API + + + + +

    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.

    MethodRules - class

    class MethodRules internal constructor(internal val rulesData: MethodRulesData) : BaseRules
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Method 查找条件实现类。

    name - field

    var name: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 名称。

    paramCount - field

    var paramCount: Int
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此变量指定参数个数。

    若参数个数小于零则忽略并使用 param

    returnType - field

    var returnType: Any?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 返回值。

    可不填写返回值。

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 标识符筛选条件。

    可不设置筛选条件。

    emptyParam - method

    fun emptyParam()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 空参数、无参数。

    param - method

    fun param(vararg paramType: Any)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 参数。

    如果同时使用了 paramCountparamType 的数量必须与 paramCount 完全匹配。

    如果 Method 中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。

    Pay Attention

    无参 Method 请使用 emptyParam 设置查找条件。

    有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。

    name - method

    fun name(conditions: NameConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 名称条件。

    paramCount - method

    fun paramCount(numRange: IntRange)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 参数个数范围。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数范围。

    paramCount - method

    fun paramCount(conditions: CountConditions)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 参数个数条件。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数条件。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html new file mode 100644 index 00000000..6a4e5efc --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html @@ -0,0 +1,38 @@ + + + + + + + + + MemberRulesResult - class | Yuki Hook API + + + + +

    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.

    MemberRulesResult - class

    class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    当前 Member 查找条件结果实现类。

    none - method

    fun none(): MemberRulesResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置当前 Member 在查找条件中个数为 0

    count - method

    fun count(num: Int): MemberRulesResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置当前 Member 在查找条件中需要全部匹配的个数。

    count - method

    fun count(numRange: IntRange): MemberRulesResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置当前 Member 在查找条件中需要全部匹配的个数范围。

    count - method

    fun count(conditions: CountConditions): MemberRulesResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置当前 Member 在查找条件中需要全部匹配的个数条件。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html new file mode 100644 index 00000000..6c06ab20 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html @@ -0,0 +1,119 @@ + + + + + + + + + ConstructorFinder - class | Yuki Hook API + + + + +

    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.

    ConstructorFinder - class

    class ConstructorFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
    +

    Change Records

    v1.0 first

    v1.0.2 modified

    合并到 BaseFinder

    v1.1.0 modified

    合并到 MemberBaseFinder

    Function Illustrate

    Constructor 查找类。

    可通过指定类型查找指定 Constructor 或一组 Constructor

    paramCount - field

    var paramCount: Int
    +

    Change Records

    v1.0.67 added

    Function Illustrate

    设置 Constructor 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此变量指定参数个数。

    若参数个数小于零则忽略并使用 param

    modifiers - method

    fun modifiers(conditions: ModifierConditions): IndexTypeCondition
    +

    Change Records

    v1.0.67 added

    v1.0.80 modified

    将方法体进行 inline

    v1.1.0 modified

    合并到 ModifierConditions

    Function Illustrate

    设置 Constructor 标识符筛选条件。

    可不设置筛选条件,默认模糊查找并取第一个匹配的 Constructor

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    emptyParam - method

    fun emptyParam(): IndexTypeCondition
    +

    Change Records

    v1.0.75 added

    Function Illustrate

    设置 Constructor 空参数、无参数。

    param - method

    fun param(vararg paramType: Any): IndexTypeCondition
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置 Constructor 参数。

    如果同时使用了 paramCountparamType 的数量必须与 paramCount 完全匹配。

    如果 Constructor 中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。

    Pay Attention

    无参 Constructor 请使用 emptyParam 设置查找条件。

    有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(num: Int): IndexTypeCondition
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置 Constructor 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数。

    若参数个数小于零则忽略并使用 param

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(numRange: IntRange): IndexTypeCondition
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Constructor 参数个数范围。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数范围。

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(conditions: CountConditions): IndexTypeCondition
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Constructor 参数个数条件。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数条件。

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    superClass - method

    fun superClass(isOnlySuperClass: Boolean)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置在 classSet 的所有父类中查找当前 Constructor

    Notice

    若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。

    RemedyPlan - class

    inner class RemedyPlan internal constructor()
    +

    Change Records

    v1.0 first

    Function Illustrate

    Constructor 重查找实现类,可累计失败次数直到查找成功。

    constructor - method

    inline fun constructor(initiate: ConstructorConditions)
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建需要重新查找的 Constructor

    你可以添加多个备选 Constructor,直到成功为止,若最后依然失败,将停止查找并输出错误日志。

    Result - class

    inner class Result internal constructor()
    +

    Change Records

    v1.0.1 added

    Function Illustrate

    RemedyPlan 结果实现类。

    onFind - method

    fun onFind(initiate: HashSet<Constructor<*>>.() -> Unit)
    +

    Change Records

    v1.0.1 added

    v1.1.0 modified

    initiate 参数 Constructor 变为 HashSet<Constructor>

    Function Illustrate

    当在 RemedyPlan 中找到结果时。

    Function Example

    你可以方便地对重查找的 Constructor 实现 onFind 方法。

    The following example

    constructor {
    +    // Your code here.
    +}.onFind {
    +    // Your code here.
    +}
    +

    Process - class

    inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Constructor 查找结果处理类,为 hookInstance 提供。

    result - method

    inline fun result(initiate: Process.() -> Unit): Process
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    创建监听结果事件方法体。

    Function Example

    你可以使用 lambda 形式创建 Result 类。

    The following example

    constructor {
    +    // Your code here.
    +}.result {
    +    all()
    +    remedys {}
    +    onNoSuchConstructor {}
    +}
    +

    all - method

    fun all(): Process
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置全部查找条件匹配的多个 Constructor 实例结果到 hookInstance

    remedys - method

    inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    创建 Constructor 重查找功能。

    Function Example

    当你遇到一种 Constructor 可能存在不同形式的存在时,可以使用 RemedyPlan 重新查找它,而没有必要使用 onNoSuchConstructor 捕获异常二次查找 Constructor

    若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。

    The following example

    constructor {
    +    // Your code here.
    +}.remedys {
    +    constructor {
    +        // Your code here.
    +    }
    +    constructor {
    +        // Your code here.
    +    }
    +}
    +

    onNoSuchConstructor - method

    inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    监听找不到 Constructor 时。

    只会返回第一次的错误信息,不会返回 RemedyPlan 的错误信息。

    Result - class

    inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    继承到接口 BaseResult

    Function Illustrate

    Constructor 查找结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建监听结果事件方法体。

    Function Example

    你可以使用 lambda 形式创建 Result 类。

    The following example

    constructor {
    +    // Your code here.
    +}.result {
    +    get().call()
    +    all()
    +    remedys {}
    +    onNoSuchConstructor {}
    +}
    +

    get - method

    fun get(): Instance
    +

    Change Records

    v1.0.2 added

    Function Illustrate

    获得 Constructor 实例处理类。

    若有多个 Constructor 结果只会返回第一个。

    Pay Attention

    若你设置了 remedys 请使用 wait 回调结果方法。

    Function Example

    你可以通过获得方法所在实例来执行构造方法创建新的实例对象。

    The following example

    constructor {
    +    // Your code here.
    +}.get().call()
    +

    你可以 cast 构造方法为指定类型的实例对象。

    The following example

    constructor {
    +    // Your code here.
    +}.get().newInstance<TestClass>()
    +

    Pay Attention

    若构造方法含有参数则后方参数必填。

    The following example

    constructor {
    +    // Your code here.
    +}.get().newInstance<TestClass>("param1", "param2")
    +

    all - method

    fun all(): ArrayList<Instance>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得 Constructor 实例处理类数组。

    返回全部查找条件匹配的多个 Constructor 实例结果。

    Function Example

    你可以通过此方法来获得当前条件结果中匹配的全部 Constructor

    The following example

    constructor {
    +    // Your code here.
    +}.all().forEach { instance ->
    +    instance.call(...)
    +}
    +

    give - method

    fun give(): Constructor<*>?
    +

    Change Records

    v1.0.67 added

    Function Illustrate

    得到 Constructor 本身。

    若有多个 Constructor 结果只会返回第一个。

    在查找条件找不到任何结果的时候将返回 null

    giveAll - method

    fun giveAll(): HashSet<Constructor<*>>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到 Constructor 本身数组。

    返回全部查找条件匹配的多个 Constructor 实例。

    在查找条件找不到任何结果的时候将返回空的 HashSet

    wait - method

    fun wait(initiate: Instance.() -> Unit)
    +

    Change Records

    v1.0.2 added

    Function Illustrate

    获得 Constructor 实例处理类,配合 RemedyPlan 使用。

    若有多个 Constructor 结果只会返回第一个。

    Pay Attention

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    waitAll - method

    fun waitAll(initiate: ArrayList<Instance>.() -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得 Constructor 实例处理类数组,配合 RemedyPlan 使用。

    返回全部查找条件匹配的多个 Constructor 实例结果。

    Pay Attention

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    remedys - method

    inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建 Constructor 重查找功能。

    Function Example

    当你遇到一种 Constructor 可能存在不同形式的存在时,可以使用 RemedyPlan 重新查找它,而没有必要使用 onNoSuchConstructor 捕获异常二次查找 Constructor

    若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。

    The following example

    constructor {
    +    // Your code here.
    +}.remedys {
    +    constructor {
    +        // Your code here.
    +    }
    +    constructor {
    +        // Your code here.
    +    }
    +}
    +

    onNoSuchConstructor - method

    inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    监听找不到 Constructor 时。

    只会返回第一次的错误信息,不会返回 RemedyPlan 的错误信息。

    ignored - method

    fun ignored(): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    忽略异常并停止打印任何错误日志。

    isNotIgnoredHookingFailurefalse 则自动忽略。

    Notice

    此时若要监听异常结果,你需要手动实现 onNoSuchConstructor 方法。

    ignoredError - method

    Change Records

    v1.0.3 added

    v1.1.0 deprecated

    请转移到新方法 ignored()

    Instance - class

    inner class Instance internal constructor(private val constructor: Constructor<*>?)
    +

    Change Records

    v1.0.2 added

    v1.1.0 modified

    新增 constructor 参数

    Function Illustrate

    Constructor 实例处理类。

    call - method

    fun call(vararg param: Any?): Any?
    +

    Change Records

    v1.0.2 added

    Function Illustrate

    执行 Constructor 创建目标实例,不指定目标实例类型。

    newInstance - method

    fun <T> newInstance(vararg param: Any?): T?
    +

    Change Records

    v1.0.2 added

    Function Illustrate

    执行 Constructor 创建目标实例 ,指定 T 目标实例类型。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html new file mode 100644 index 00000000..3d131c99 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html @@ -0,0 +1,115 @@ + + + + + + + + + FieldFinder - class | Yuki Hook API + + + + +

    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.

    FieldFinder - class

    class FieldFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>?) : MemberBaseFinder
    +

    Change Records

    v1.0 first

    v1.0.2 modified

    合并到 BaseFinder

    v1.1.0 modified

    合并到 MemberBaseFinder

    Function Illustrate

    Field 查找类。

    可通过指定类型查找指定 Field 或一组 Field

    classSet - field

    Change Records

    v1.0 first

    v1.0.2 removed

    name - field

    var name: String
    +

    Change Records

    v1.0 first

    v1.0.70 modified

    允许不填写名称

    Function Illustrate

    设置 Field 名称。

    Pay Attention

    若不填写名称则必须存在一个其它条件。

    type - field

    var type: Any?
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置 Field 类型。

    可不填写类型。

    modifiers - method

    fun modifiers(conditions: ModifierConditions): IndexTypeCondition
    +

    Change Records

    v1.0.67 added

    v1.0.80 modified

    将方法体进行 inline

    v1.1.0 modified

    合并到 ModifierConditions

    Function Illustrate

    设置 Field 标识符筛选条件。

    可不设置筛选条件。

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    order - method

    fun order(): IndexTypeCondition
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    顺序筛选字节码的下标。

    name - method

    fun name(value: String): IndexTypeCondition
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置 Field 名称。

    Pay Attention

    若不填写名称则必须存在一个其它条件。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    name - method

    fun name(conditions: NameConditions): IndexTypeCondition
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    合并到 NameConditions

    Function Illustrate

    设置 Field 名称条件。

    Pay Attention

    若不填写名称则必须存在一个其它条件。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    type - method

    fun type(value: Any): IndexTypeCondition
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置 Field 类型。

    Pay Attention

    可不填写类型。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    superClass - method

    fun superClass(isOnlySuperClass: Boolean)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置在 classSet 的所有父类中查找当前 Field

    Notice

    若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。

    RemedyPlan - class

    inner class RemedyPlan internal constructor()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Field 重查找实现类,可累计失败次数直到查找成功。

    field - method

    inline fun field(initiate: FieldConditions): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    创建需要重新查找的 Field

    你可以添加多个备选 Field,直到成功为止,若最后依然失败,将停止查找并输出错误日志。

    Result - class

    inner class Result internal constructor()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    RemedyPlan 结果实现类。

    onFind - method

    fun onFind(initiate: HashSet<Field>.() -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    当在 RemedyPlan 中找到结果时。

    Function Example

    你可以方便地对重查找的 Field 实现 onFind 方法。

    The following example

    field {
    +    // Your code here.
    +}.onFind {
    +    // Your code here.
    +}
    +

    Result - class

    inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    继承到接口 BaseResult

    Function Illustrate

    Field 查找结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建监听结果事件方法体。

    Function Example

    你可以使用 lambda 形式创建 Result 类。

    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 {}
    +}
    +

    get - method

    fun get(instance: Any?): Instance
    +

    Change Records

    v1.0 first

    Function Illustrate

    获得 Field 实例处理类。

    若有多个 Field 结果只会返回第一个。

    Function Example

    你可以轻松地得到 Field 的实例以及使用它进行设置实例。

    The following example

    field {
    +    // Your code here.
    +}.get(instance).set("something")
    +

    如果你取到的是静态 Field,可以不需要设置实例。

    The following example

    field {
    +    // Your code here.
    +}.get().set("something")
    +

    all - method

    fun all(instance: Any?): ArrayList<Instance>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得 Field 实例处理类数组。

    返回全部查找条件匹配的多个 Field 实例结果。

    Function Example

    你可以通过此方法来获得当前条件结果中匹配的全部 Field,其 Field 所在实例用法与 get 相同。

    The following example

    field {
    +    // Your code here.
    +}.all(instance).forEach { instance ->
    +    instance.self
    +}
    +

    give - method

    fun give(): Field?
    +

    Change Records

    v1.0 first

    Function Illustrate

    得到 Field 本身。

    若有多个 Field 结果只会返回第一个。

    在查找条件找不到任何结果的时候将返回 null

    giveAll - method

    fun giveAll(): HashSet<Field>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到 Field 本身数组。

    返回全部查找条件匹配的多个 Field 实例。

    在查找条件找不到任何结果的时候将返回空的 HashSet

    wait - method

    fun wait(instance: Any?, initiate: Instance.() -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得 Field 实例处理类,配合 RemedyPlan 使用。

    若有多个 Field 结果只会返回第一个。

    Pay Attention

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    waitAll - method

    fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得 Field 实例处理类数组,配合 RemedyPlan 使用。

    返回全部查找条件匹配的多个 Field 实例结果。

    Pay Attention

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    remedys - method

    inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    创建 Field 重查找功能。

    Function Example

    当你遇到一种 Field 可能存在不同形式的存在时,可以使用 RemedyPlan 重新查找它,而没有必要使用 onNoSuchField 捕获异常二次查找 Field

    若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。

    The following example

    field {
    +    // Your code here.
    +}.remedys {
    +    field {
    +        // Your code here.
    +    }
    +    field {
    +        // Your code here.
    +    }
    +}
    +

    onNoSuchField - method

    fun onNoSuchField(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.0 first

    Function Illustrate

    监听找不到 Field 时。

    ignored - method

    fun ignored(): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    忽略异常并停止打印任何错误日志。

    isNotIgnoredHookingFailurefalse 则自动忽略。

    Notice

    此时若要监听异常结果,你需要手动实现 onNoSuchField 方法。

    ignoredError - method

    Change Records

    v1.0.3 added

    v1.1.0 deprecated

    请转移到新方法 ignored()

    Instance - class

    inner class Instance internal constructor(private val instance: Any?, private val field: Field?)
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    新增 field 参数

    不再对外公开 self 参数

    Function Illustrate

    Field 实例变量处理类。

    self - field

    Change Records

    v1.0 first

    v1.1.0 removed

    请直接使用 any 方法得到 Field 自身的实例化对象

    current - method

    fun current(ignored: Boolean): CurrentClass?
    +
    inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前 Field 自身 self 实例的类操作对象 CurrentClass

    cast - method

    fun <T> cast(): T?
    +

    Change Records

    v1.0 first

    v1.0.68 modified

    修改 ofcast

    移动方法到 Instance

    Function Illustrate

    得到当前 Field 实例。

    byte - method

    fun byte(): Byte?
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    得到当前 Field Byte 实例。

    int - method

    fun int(): Int
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 ofIntint

    移动方法到 Instance

    Function Illustrate

    得到当前 Field Int 实例。

    long - method

    fun long(): Long
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 ofLonglong

    移动方法到 Instance

    Function Illustrate

    得到当前 Field Long 实例。

    short - method

    fun short(): Short
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 ofShortshort

    移动方法到 Instance

    Function Illustrate

    得到当前 Field Short 实例。

    double - method

    fun double(): Double
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 ofDoubledouble

    移动方法到 Instance

    Function Illustrate

    得到当前 Field Double 实例。

    float - method

    fun float(): Float
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 ofFloatfloat

    移动方法到 Instance

    Function Illustrate

    得到当前 Field Float 实例。

    string - method

    fun string(): String
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 ofStringstring

    移动方法到 Instance

    Function Illustrate

    得到当前 Field String 实例。

    char - method

    fun char(): Char
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    得到当前 Field Char 实例。

    boolean - method

    fun boolean(): Boolean
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 ofBooleanboolean

    移动方法到 Instance

    Function Illustrate

    得到当前 Field Boolean 实例。

    any - method

    fun any(): Any?
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 ofAnyany

    移动方法到 Instance

    Function Illustrate

    得到当前 Field Any 实例。

    array - method

    inline fun <reified T> array(): Array<T>
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    得到当前 Field Array 实例。

    list - method

    inline fun <reified T> list(): List<T>
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    得到当前 Field List 实例。

    set - method

    fun set(any: Any?)
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置当前 Field 实例。

    setTrue - method

    fun setTrue()
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置当前 Field 实例为 true

    Pay Attention

    请确保实例对象类型为 Boolean

    setFalse - method

    fun setFalse()
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置当前 Field 实例为 false

    Pay Attention

    请确保实例对象类型为 Boolean

    setNull - method

    fun setNull()
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置当前 Field 实例为 null

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html new file mode 100644 index 00000000..ee057d9a --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html @@ -0,0 +1,134 @@ + + + + + + + + + MethodFinder - class | Yuki Hook API + + + + +

    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.

    MethodFinder - class

    class MethodFinder internal constructor(override val hookInstance: YukiMemberHookCreator.MemberHookCreator?, override val classSet: Class<*>) : MemberBaseFinder
    +

    Change Records

    v1.0 first

    v1.0.2 modified

    合并到 BaseFinder

    v1.1.0 modified

    合并到 MemberBaseFinder

    Function Illustrate

    Method 查找类。

    可通过指定类型查找指定 Method 或一组 Method

    name - field

    var name: String
    +

    Change Records

    v1.0 first

    v1.0.70 modified

    允许不填写名称

    Function Illustrate

    设置 Method 名称。

    Pay Attention

    若不填写名称则必须存在一个其它条件。

    paramCount - field

    var paramCount: Int
    +

    Change Records

    v1.0.67 added

    Function Illustrate

    设置 Method 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此变量指定参数个数。

    若参数个数小于零则忽略并使用 param

    returnType - field

    var returnType: Any?
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置 Method 返回值,可不填写返回值。

    modifiers - method

    fun modifiers(conditions: ModifierConditions): IndexTypeCondition
    +

    Change Records

    v1.0.67 added

    v1.0.80 modified

    将方法体进行 inline

    v1.1.0 modified

    合并到 ModifierConditions

    Function Illustrate

    设置 Method 标识符筛选条件。

    可不设置筛选条件。

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    emptyParam - method

    fun emptyParam(): IndexTypeCondition
    +

    Change Records

    v1.0.75 added

    Function Illustrate

    设置 Method 空参数、无参数。

    param - method

    fun param(vararg paramType: Any): IndexTypeCondition
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置 Method 参数。

    如果同时使用了 paramCountparamType 的数量必须与 paramCount 完全匹配。

    如果 Method 中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。

    Pay Attention

    无参 Method 请使用 emptyParam 设置查找条件。

    有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    order - method

    fun order(): IndexTypeCondition
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    顺序筛选字节码的下标。

    name - method

    fun name(value: String): IndexTypeCondition
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置 Method 名称。

    Pay Attention

    若不填写名称则必须存在一个其它条件。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    name - method

    fun name(conditions: NameConditions): IndexTypeCondition
    +

    Change Records

    v1.0.88 added

    v1.1.0 modified

    合并到 NameConditions

    Function Illustrate

    设置 Method 名称条件。

    Pay Attention

    若不填写名称则必须存在一个其它条件。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(num: Int): IndexTypeCondition
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置 Method 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数。

    若参数个数小于零则忽略并使用 param

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(numRange: IntRange): IndexTypeCondition
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 参数个数范围。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数范围。

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(conditions: CountConditions): IndexTypeCondition
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置 Method 参数个数条件。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数条件。

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    returnType - method

    fun returnType(value: Any): IndexTypeCondition
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    设置 Method 返回值。

    可不填写返回值。

    Pay Attention

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    superClass - method

    fun superClass(isOnlySuperClass: Boolean)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置在 classSet 的所有父类中查找当前 Method

    Notice

    若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。

    RemedyPlan - class

    inner class RemedyPlan internal constructor()
    +

    Change Records

    v1.0 first

    Function Illustrate

    Method 重查找实现类,可累计失败次数直到查找成功。

    method - method

    inline fun method(initiate: MethodConditions): Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建需要重新查找的 Method

    你可以添加多个备选 Method,直到成功为止,若最后依然失败,将停止查找并输出错误日志。

    Result - class

    inner class Result internal constructor()
    +

    Change Records

    v1.0.1 added

    Function Illustrate

    RemedyPlan 结果实现类。

    onFind - method

    fun onFind(initiate: HashSet<Method>.() -> Unit)
    +

    Change Records

    v1.0.1 added

    v1.1.0 modified

    initiate 参数 Method 变为 HashSet<Method>

    Function Illustrate

    当在 RemedyPlan 中找到结果时。

    Function Example

    你可以方便地对重查找的 Method 实现 onFind 方法。

    The following example

    method {
    +    // Your code here.
    +}.onFind {
    +    // Your code here.
    +}
    +

    Process - class

    inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    Method 查找结果处理类,为 hookInstance 提供。

    result - method

    inline fun result(initiate: Process.() -> Unit): Process
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    创建监听结果事件方法体。

    Function Example

    你可以使用 lambda 形式创建 Result 类。

    The following example

    method {
    +    // Your code here.
    +}.result {
    +    all()
    +    remedys {}
    +    onNoSuchMethod {}
    +}
    +

    all - method

    fun all(): Process
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置全部查找条件匹配的多个 Method 实例结果到 hookInstance

    remedys - method

    inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    创建 Method 重查找功能。

    Function Example

    当你遇到一种 Method 可能存在不同形式的存在时,可以使用 RemedyPlan 重新查找它,而没有必要使用 onNoSuchMethod 捕获异常二次查找 Method

    若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。

    The following example

    method {
    +    // Your code here.
    +}.remedys {
    +    method {
    +        // Your code here.
    +    }
    +    method {
    +        // Your code here.
    +    }
    +}
    +

    onNoSuchMethod - method

    inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    监听找不到 Method 时。

    只会返回第一次的错误信息,不会返回 RemedyPlan 的错误信息。

    Result - class

    inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    继承到接口 BaseResult

    Function Illustrate

    Method 查找结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建监听结果事件方法体。

    Function Example

    你可以使用 lambda 形式创建 Result 类。

    The following example

    method {
    +    // Your code here.
    +}.result {
    +    get(instance).call()
    +    all(instance)
    +    remedys {}
    +    onNoSuchMethod {}
    +}
    +

    get - method

    fun get(instance: Any?): Instance
    +

    Change Records

    v1.0.2 added

    Function Illustrate

    获得 Method 实例处理类。

    若有多个 Method 结果只会返回第一个。

    Pay Attention

    若你设置了 remedys 请使用 wait 回调结果方法。

    Function Example

    你可以通过获得方法所在实例来执行 Method

    The following example

    method {
    +    // Your code here.
    +}.get(instance).call()
    +

    若当前为静态方法,你可以不设置实例。

    The following example

    method {
    +    // Your code here.
    +}.get().call()
    +

    all - method

    fun all(instance: Any?): ArrayList<Instance>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得 Method 实例处理类数组。

    返回全部查找条件匹配的多个 Method 实例结果。

    Function Example

    你可以通过此方法来获得当前条件结果中匹配的全部 Method,其方法所在实例用法与 get 相同。

    The following example

    method {
    +    // Your code here.
    +}.all(instance).forEach { instance ->
    +    instance.call(...)
    +}
    +

    give - method

    fun give(): Method?
    +

    Change Records

    v1.0.67 added

    Function Illustrate

    得到 Method 本身。

    若有多个 Method 结果只会返回第一个。

    在查找条件找不到任何结果的时候将返回 null

    giveAll - method

    fun giveAll(): HashSet<Method>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到 Method 本身数组。

    返回全部查找条件匹配的多个 Method 实例。

    在查找条件找不到任何结果的时候将返回空的 HashSet

    wait - method

    fun wait(instance: Any?, initiate: Instance.() -> Unit)
    +

    Change Records

    v1.0.2 added

    Function Illustrate

    获得 Method 实例处理类,配合 RemedyPlan 使用。

    若有多个 Method 结果只会返回第一个。

    Pay Attention

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    waitAll - method

    fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得 Method 实例处理类数组,配合 RemedyPlan 使用。

    返回全部查找条件匹配的多个 Method 实例结果。

    Pay Attention

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    remedys - method

    inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    创建 Method 重查找功能。

    Function Example

    当你遇到一种 Method 可能存在不同形式的存在时,可以使用 RemedyPlan 重新查找它,而没有必要使用 onNoSuchMethod 捕获异常二次查找 Method

    若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。

    The following example

    method {
    +    // Your code here.
    +}.remedys {
    +    method {
    +        // Your code here.
    +    }
    +    method {
    +        // Your code here.
    +    }
    +}
    +

    onNoSuchMethod - method

    inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    监听找不到 Method 时。

    只会返回第一次的错误信息,不会返回 RemedyPlan 的错误信息。

    ignored - method

    fun ignored(): Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    忽略异常并停止打印任何错误日志。

    isNotIgnoredHookingFailurefalse 则自动忽略。

    Notice

    此时若要监听异常结果,你需要手动实现 onNoSuchMethod 方法。

    ignoredError - method

    Change Records

    v1.0.3 added

    v1.1.0 deprecated

    请转移到新方法 ignored()

    Instance - class

    inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
    +

    Change Records

    v1.0.2 added

    v1.1.0 modified

    新增 method 参数

    Function Illustrate

    Method 实例处理类。

    original - method

    fun original(): Instance
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    标识需要调用当前 Method 未经 Hook 的原始方法。

    若当前 Method 并未 Hook 则会使用原始的 Method.invoke 方法调用。

    Pay Attention

    你只能在 (Xposed) 宿主环境中使用此功能。

    call - method

    fun call(vararg param: Any?): Any?
    +

    Change Records

    v1.0.2 added

    Function Illustrate

    执行 Method,不指定返回值类型。

    invoke - method

    fun <T> invoke(vararg param: Any?): T?
    +

    Change Records

    v1.0.2 added

    Function Illustrate

    执行 Method,指定 T 返回值类型。

    byte - method

    fun byte(vararg param: Any?): Byte?
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    执行 Method,指定 Byte 返回值类型。

    int - method

    fun int(vararg param: Any?): Int
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 callIntint

    Function Illustrate

    执行 Method,指定 Int 返回值类型。

    long - method

    fun long(vararg param: Any?): Long
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 callLonglong

    Function Illustrate

    执行 Method,指定 Long 返回值类型。

    short - method

    fun short(vararg param: Any?): Short
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 callShortshort

    Function Illustrate

    执行 Method,指定 Short 返回值类型。

    double - method

    fun double(vararg param: Any?): Double
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 callDoubledouble

    Function Illustrate

    执行 Method,指定 Double 返回值类型。

    float - method

    fun float(vararg param: Any?): Float
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 callFloatfloat

    Function Illustrate

    执行 Method,指定 Float 返回值类型。

    string - method

    fun string(vararg param: Any?): String
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 callStringstring

    Function Illustrate

    执行 Method,指定 String 返回值类型。

    char - method

    fun char(vararg param: Any?): Char
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    执行 Method,指定 Char 返回值类型。

    boolean - method

    fun boolean(vararg param: Any?): Boolean
    +

    Change Records

    v1.0.65 added

    v1.0.68 modified

    修改 callBooleanboolean

    Function Illustrate

    执行 Method,指定 Boolean 返回值类型。

    array - method

    inline fun <reified T> array(vararg param: Any?): Array<T>
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    执行 Method,指定 Array 返回值类型。

    list - method

    inline fun <reified T> list(vararg param: Any?): List<T>
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    执行 Method,指定 List 返回值类型。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html new file mode 100644 index 00000000..c8411f0e --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html @@ -0,0 +1,35 @@ + + + + + + + + + YukiBaseHooker - class | Yuki Hook API + + + + +

    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.

    YukiBaseHooker - class

    abstract class YukiBaseHooker : PackageParam()
    +

    Change Records

    v1.0 first

    Function Illustrate

    YukiHookAPI 的子类 Hooker 实现。

    onHook - method

    fun onHook()
    +

    Change Records

    v1.0 first

    Function Illustrate

    子类 Hook 开始。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html new file mode 100644 index 00000000..d1bf77a2 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html @@ -0,0 +1,91 @@ + + + + + + + + + ReflectionFactory - kt | Yuki Hook API + + + + +

    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.

    ReflectionFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    这是自定义 MemberClass 相关功能的查找匹配以及 invoke 的封装类。

    MembersType - class

    enum class MembersType
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    定义一个 Class 中的 Member 类型

    ALL - enum

    ALL
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    全部 MethodConstructor

    METHOD - enum

    METHOD
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    全部 Method

    CONSTRUCTOR - enum

    CONSTRUCTOR
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    全部 Constructor

    ClassLoader.searchClass - ext-method

    inline fun ClassLoader.searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    通过当前 ClassLoader 按指定条件查找并得到 Dex 中的 Class

    Pay Attention

    此方法在 Class 数量过多及查找条件复杂时会非常耗时。

    建议启用 async 或设置 name 参数,name 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。

    此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。

    ClassLoader.onLoadClass - ext-method

    fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    监听当前 ClassLoaderClassLoader.loadClass 方法装载。

    Pay Attention

    只有当前 ClassLoader 有主动使用 ClassLoader.loadClass 事件时才能被捕获。

    这是一个实验性功能,一般情况下不会用到此方法,不保证不会发生错误。

    只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。

    Function Example

    针对一些使用特定 ClassLoader 装载 Class 的宿主应用,你可以使用此方法来监听 Class 加载情况。

    Notice

    为了防止发生问题,你需要得到一个存在的 ClassLoader 实例来使用此功能。

    比如我们在 PackageParam 中使用 appClassLoader

    The following example

    appClassLoader.onLoadClass { clazz ->
    +    // 得到 clazz 即加载对象
    +    clazz... // 这里进行你需要的操作
    +}
    +

    或使用你得到的存在的 ClassLoader 实例,可以通过 Hook 获取。

    The following example

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +customClassLoader?.onLoadClass { clazz ->
    +    // ...
    +}
    +

    在判断到这个 Class 被装载成功时,开始执行你的 Hook 功能。

    The following example

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +customClassLoader?.onLoadClass { clazz ->
    +    if(clazz.name == /** 你需要的 Class 名称 */) {
    +        clazz.hook {
    +            // ...
    +        }
    +    }
    +}
    +

    hookClass - field

    Change Records

    v1.0 first

    v1.1.0 removed

    HookClass 相关功能不再对外开放

    normalClass - field

    Change Records

    v1.0 first

    v1.1.0 removed

    HookClass 相关功能不再对外开放

    hasClass - field

    Change Records

    v1.0 first

    v1.1.0 removed

    请直接使用 hasClass() 无参方法

    Class.hasExtends - ext-field

    val Class<*>.hasExtends: Boolean
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    当前 Class 是否有继承关系,父类是 Any 将被认为没有继承关系。

    classOf - method

    Change Records

    v1.0 first

    v1.1.0 deprecated

    请转到 toClass(...) 方法

    String.toClass - ext-method

    fun String.toClass(loader: ClassLoader?): Class<*>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    通过字符串类名转换为 loader 中的实体类。

    Function Example

    你可以直接填写你要查找的目标 Class,必须在默认 ClassLoader 下存在。

    The following example

    "com.example.demo.DemoClass".toClass()
    +

    你还可以自定义 Class 所在的 ClassLoader

    The following example

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +"com.example.demo.DemoClass".toClass(customClassLoader)
    +

    String.toClassOrNull - ext-method

    fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    通过字符串类名转换为 loader 中的实体类。

    找不到 Class 会返回 null,不会抛出异常。

    Function Example

    用法请参考 String.toClass 方法。

    classOf - method

    inline fun <reified T> classOf(loader: ClassLoader?): Class<*>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    通过 T 得到其 Class 实例并转换为实体类。

    Function Example

    我们要获取一个 ClassKotlin 下不通过反射时应该这样做。

    The following example

    DemoClass::class.java
    +

    现在,你可以直接 cast 一个实例并获取它的 Class 对象,必须在当前 ClassLoader 下存在。

    The following example

    classOf<DemoClass>()
    +

    若目标存在的 Classstub,通过这种方式,你还可以自定义 Class 所在的 ClassLoader

    The following example

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +classOf<DemoClass>(customClassLoader)
    +

    String.hasClass - ext-method

    fun String.hasClass(loader: ClassLoader?): Boolean
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    支持直接使用空参数方法使用默认 ClassLoader 进行判断

    Function Illustrate

    通过字符串类名使用指定的 ClassLoader 查找是否存在。

    Function Example

    你可以轻松的使用此方法判断字符串中的类是否存在,效果等同于直接使用 Class.forName

    The following example

    if("com.example.demo.DemoClass".hasClass()) {
    +    // Your code here.
    +}
    +

    填入方法中的 loader 参数可判断指定的 ClassLoader 中的 Class 是否存在。

    The following example

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
    +    // Your code here.
    +}
    +

    Class.hasField - ext-method

    inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
    +

    Change Records

    v1.0.4 added

    v1.0.67 modified

    合并到 FieldFinder

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    查找变量是否存在。

    Class.hasMethod - ext-method

    inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
    +

    Change Records

    v1.0 first

    v1.0.1 modified

    新增 returnType 参数

    v1.0.67 modified

    合并到 MethodFinder

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    查找方法是否存在。

    Class.hasConstructor - ext-method

    inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
    +

    Change Records

    v1.0.2 added

    v1.0.67 modified

    合并到 ConstructorFinder

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    查找构造方法是否存在。

    Member.hasModifiers - ext-method

    inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
    +

    Change Records

    v1.0.67 added

    v1.0.80 modified

    将方法体进行 inline

    v1.1.0 modified

    合并到 ModifierConditions

    Function Illustrate

    查找 Member 中匹配的描述符。

    Class.hasModifiers - ext-method

    inline fun Class<*>.hasModifiers(conditions: ModifierConditions): Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    查找 Class 中匹配的描述符。

    obtainStaticFieldAny - method

    Change Records

    v1.0 first

    v1.0.1 removed

    obtainFieldAny - method

    Change Records

    v1.0 first

    v1.0.1 removed

    modifyStaticField - method

    Change Records

    v1.0 first

    v1.0.1 removed

    modifyField - method

    Change Records

    v1.0 first

    v1.0.1 removed

    Class.field - ext-method

    inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
    +

    Change Records

    v1.0.2 added

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    查找并得到变量。

    Class.method - ext-method

    inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
    +

    Change Records

    v1.0 first

    v1.0.1 modified

    obtainMethod 更名为 method

    新增 returnType 参数

    v1.0.2 modified

    合并到 MethodFinder 方法体

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    查找并得到方法。

    Class.constructor - ext-method

    inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
    +

    Change Records

    v1.0 first

    v1.0.1 modified

    obtainConstructor 更名为 constructor

    v1.0.2 modified

    合并到 ConstructorFinder 方法体

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    查找并得到构造方法。

    callStatic - method

    Change Records

    v1.0 first

    v1.0.1 modified

    invokeStatic 更名为 callStatic

    v1.0.2 removed

    call - method

    Change Records

    v1.0 first

    v1.0.1 modified

    invokeAny 更名为 call

    v1.0.2 removed

    Class.generic - ext-method

    fun Class<*>.generic(): GenericClass?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前 Class 的泛型父类。

    如果当前实例不存在泛型将返回 null

    Class.generic - ext-method

    inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获得当前 Class 的泛型父类。

    如果当前实例不存在泛型将返回 null

    Any.current - ext-method

    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

    新增 ignored 参数,可以忽略在 CurrentClass 中出现的异常

    新增不使用 current { ... } 调用域直接使用 current() 得到实例的类操作对象

    Function Illustrate

    获得当前实例的类操作对象。

    Class.buildOfAny - ext-method

    Change Records

    v1.0.70 added

    v1.0.80 modified

    将方法体进行 inline

    v1.1.0 deprecated

    请转移到 buildOf 方法

    Class.buildOf - ext-method

    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

    将方法体进行 inline

    v1.1.0 modified

    加入无泛型方法 buildOf

    Function Illustrate

    通过构造方法创建新实例,指定类型 T 或任意类型 Any

    Class.allMethods - ext-method

    inline fun Class<*>.allMethods(result: (index: Int, method: Method) -> Unit)
    +

    Change Records

    v1.0.70 added

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    遍历当前类中的所有方法。

    Class.allConstructors - ext-method

    inline fun Class<*>.allConstructors(result: (index: Int, constructor: Constructor<*>) -> Unit)
    +

    Change Records

    v1.0.70 added

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    遍历当前类中的所有构造方法。

    Class.allFields - ext-method

    inline fun Class<*>.allFields(result: (index: Int, field: Field) -> Unit)
    +

    Change Records

    v1.0.70 added

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    遍历当前类中的所有变量。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html new file mode 100644 index 00000000..f7708b2b --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html @@ -0,0 +1,44 @@ + + + + + + + + + YukiHookFactory - kt | Yuki Hook API + + + + +

    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.

    YukiHookFactory - kt

    Change Records

    v1.0 first

    v1.0.80 modified

    合并到 IYukiHookXposedInit,将方法体进行 inline

    Function Illustrate

    这是 YukiHookAPI 相关 lambda 方法的封装类以及部分 API 用法。

    IYukiHookXposedInit.configs - ext-method

    inline fun IYukiHookXposedInit.configs(initiate: YukiHookAPI.Configs.() -> Unit)
    +

    Change Records

    v1.0.1 added

    v1.0.80 modified

    合并到 IYukiHookXposedInit

    Function Illustrate

    IYukiHookXposedInit 中配置 Configs

    IYukiHookXposedInit.encase - ext-method

    fun IYukiHookXposedInit.encase(initiate: PackageParam.() -> Unit)
    +
    fun IYukiHookXposedInit.encase(vararg hooker: YukiBaseHooker)
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    合并到 IYukiHookXposedInit

    Function Illustrate

    IYukiHookXposedInit 中调用 YukiHookAPI

    Context.modulePrefs - ext-field

    val Context.modulePrefs: YukiHookModulePrefs
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取模块的存取对象。

    Context.modulePrefs - ext-method

    fun Context.modulePrefs(name: String): YukiHookModulePrefs
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取模块的存取对象,可设置 name 为自定义 Sp 存储名称。

    Context.dataChannel - ext-method

    fun Context.dataChannel(packageName: String): YukiHookDataChannel.NameSpace
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    获取模块的数据通讯桥命名空间对象。

    Pay Attention

    只能在模块环境使用此功能,其它环境下使用将不起作用。

    Context.processName - ext-field

    val Context.processName: String
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前进程名称。

    Context+Resources.injectModuleAppResources - ext-method

    fun Context.injectModuleAppResources()
    +
    fun Resources.injectModuleAppResources()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    向 Hook APP (宿主) ContextResources 注入当前 Xposed 模块的资源。

    注入成功后,你就可以直接使用例如 ImageView.setImageResourceResources.getString 装载当前 Xposed 模块的资源 ID。

    注入的资源作用域仅限当前 ContextResources,你需要在每个用到宿主 ContextResources 的地方重复调用此方法进行注入才能使用。

    Pay Attention

    只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。

    Context.registerModuleAppActivities - ext-method

    fun Context.registerModuleAppActivities(proxy: Any?)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    向 Hook APP (宿主) 注册当前 Xposed 模块的 Activity

    注册成功后,你就可以直接使用 Context.startActivity 来启动未在宿主中注册的 Activity

    使用此方法会在未注册的 Activity 在 Hook APP (宿主) 中启动时自动调用 injectModuleAppResources 注入当前 Xposed 模块的资源。

    你要将需要在宿主启动的 Activity 继承于 ModuleAppActivityModuleAppCompatActivity

    Pay Attention

    只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。

    Context.applyModuleTheme - ext-method

    fun Context.applyModuleTheme(theme: Int, configuration: Configuration?): ModuleContextThemeWrapper
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    生成一个 ContextThemeWrapper 代理以应用当前 Xposed 模块的主题资源。

    在 Hook APP (宿主) 中使用此方法会自动调用 injectModuleAppResources 注入当前 Xposed 模块的资源。

    如果在 Hook APP (宿主) 中使用此方法发生 ClassCastException,请手动设置 configuration

    isSupportResourcesHook - field

    Change Records

    v1.0.80 added

    v1.0.91 removed

    请转移到 YukiHookAPI.Status.isSupportResourcesHook

    isModuleActive - field

    Change Records

    v1.0.6 added

    v1.0.91 removed

    请转移到 YukiHookAPI.Status.isModuleActive

    isXposedModuleActive - field

    Change Records

    v1.0.6 added

    v1.0.91 removed

    请转移到 YukiHookAPI.Status.isXposedModuleActive

    isTaiChiModuleActive - field

    Change Records

    v1.0 first

    v1.0.91 removed

    请转移到 YukiHookAPI.Status.isTaiChiModuleActive

    YukiHookModuleStatus - class

    Change Records

    v1.0 first

    v1.0.91 deprecated

    请转移到 YukiHookAPI.Status

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html new file mode 100644 index 00000000..565bd9be --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html @@ -0,0 +1,59 @@ + + + + + + + + + LoggerFactory - kt | Yuki Hook API + + + + +

    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.

    LoggerFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    这是 YukiHookAPI 的日志封装类,可实现同时向 LogcatXposedBridge.log 打印日志的功能。

    LoggerType - class

    enum class LoggerType
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    需要打印的日志类型。

    决定于模块与 (Xposed) 宿主环境使用的打印方式。

    LOGD - enum

    LOGD
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    仅使用 android.util.Log

    XPOSEDBRIDGE - enum

    XPOSEDBRIDGE
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    仅使用 XposedBridge.log

    Pay Attention

    只能在 (Xposed) 宿主环境中使用,模块环境将不生效。

    SCOPE - enum

    SCOPE
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    分区使用。

    (Xposed) 宿主环境仅使用 XPOSEDBRIDGE

    模块环境仅使用 LOGD

    BOTH - enum

    BOTH
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    同时使用。

    (Xposed) 宿主环境使用 LOGDXPOSEDBRIDGE

    模块环境仅使用 LOGD

    YukiHookLogger - object

    object YukiHookLogger
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    调试日志实现类。

    contents - field

    val contents: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获取当前日志文件内容。

    如果当前没有已记录的日志会返回空字符串。

    clear - method

    fun clear()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    清除全部已记录的日志。

    saveToFile - method

    fun saveToFile(fileName: String)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    保存当前日志到文件。

    若当前未开启 Configs.isRecord 或记录为空则不会进行任何操作。

    日志文件会追加到 fileName 的文件结尾,若文件不存在会自动创建。

    Pay Attention

    文件读写权限取决于当前宿主已获取的权限。

    Configs - object

    object Configs
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    配置 YukiHookLogger

    TAG - field

    const val TAG: Int
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    标签。

    PRIORITY - field

    const val PRIORITY: Int
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    优先级。

    PACKAGE_NAME - field

    const val PACKAGE_NAME: Int
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    当前宿主的包名。

    USER_ID - field

    const val USER_ID: Int
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    当前宿主的用户 ID (主用户不显示)。

    isEnable - field

    var isEnable: Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    是否启用调试日志的输出功能。

    关闭后将会停用 YukiHookAPI 对全部日志的输出。

    但是不影响当你手动调用下面这些方法输出日志。

    loggerDloggerIloggerWloggerE

    isEnable 关闭后 YukiHookAPI.Configs.isDebug 也将同时关闭。

    isRecord - field

    var isRecord: Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    是否启用调试日志的记录功能。

    开启后将会在内存中记录全部可用的日志和异常堆栈。

    需要同时启用 isEnable 才能有效。

    Pay Attention

    过量的日志可能会导致宿主运行缓慢或造成频繁 GC。

    开启后你可以调用 YukiHookLogger.saveToFile 实时保存日志到文件或使用 YukiHookLogger.contents 获取实时日志文件。

    tag - field

    var tag: String
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    这是一个调试日志的全局标识。

    默认文案为 YukiHookAPI

    你可以修改为你自己的文案。

    elements - method

    fun elements(vararg item: Int)
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    自定义调试日志对外显示的元素。

    只对日志记录和 XposedBridge.log 生效。

    日志元素的排列将按照你在 item 中设置的顺序进行显示。

    你还可以留空 item 以不显示除日志内容外的全部元素。

    可用的元素有:TAGPRIORITYPACKAGE_NAMEUSER_ID

    Function Example

    打印的日志样式将按照你设置的排列顺序和元素内容进行。

    The following example

    elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
    +

    以上内容定义的日志将显示为如下样式。

    The following example

    [YukiHookAPI][D][com.demo.test][999]--> This is a log
    +

    如果我们调整元素顺序以及减少个数,那么结果又会不一样。

    The following example

    elements(PACKAGE_NAME, USER_ID, PRIORITY)
    +

    以上内容定义的日志将显示为如下样式。

    The following example

    [com.demo.test][999][D]--> This is a log
    +

    loggerD - method

    fun loggerD(tag: String, msg: String, type: LoggerType)
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    新增 type 参数

    Function Illustrate

    LogcatXposedBridge 打印日志,级别 D

    tag 的默认参数为 YukiHookAPI.Configs.debugTag,你可以进行自定义。

    loggerI - method

    fun loggerI(tag: String, msg: String, type: LoggerType)
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    新增 type 参数

    Function Illustrate

    LogcatXposedBridge 打印日志,级别 I

    tag 的默认参数为 YukiHookAPI.Configs.debugTag,你可以进行自定义。

    loggerW - method

    fun loggerW(tag: String, msg: String, type: LoggerType)
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    新增 type 参数

    Function Illustrate

    LogcatXposedBridge 打印日志,级别 W

    tag 的默认参数为 YukiHookAPI.Configs.debugTag,你可以进行自定义。

    loggerE - method

    fun loggerE(tag: String, msg: String, e: Throwable?, type: LoggerType)
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    新增 type 参数

    Function Illustrate

    LogcatXposedBridge 打印日志,级别 E,可携带 e 异常信息,将打印异常堆栈。

    tag 的默认参数为 YukiHookAPI.Configs.debugTag,你可以进行自定义。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html new file mode 100644 index 00000000..a18bef0f --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html @@ -0,0 +1,118 @@ + + + + + + + + + HookParam - class | Yuki Hook API + + + + +

    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.

    HookParam - class

    class HookParam internal constructor(private val creatorInstance: YukiMemberHookCreator, private var param: YukiHookCallback.Param?)
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    移动 HookParamWrapperYukiHookCallback.Param

    修正拼写错误的 creater 命名到 creator

    Function Illustrate

    Hook 方法、构造方法的目标对象实现类。

    args - field

    val args: Array<Any?>
    +

    Change Records

    v1.0 添加

    Function Illustrate

    获取当前 Hook 对象 memberconstructor 的参数对象数组。

    这里的数组每项类型默认为 Any,你可以使用 args 方法来实现 ArgsModifyer.cast 功能。

    firstArgs - field

    Change Records

    v1.0 first

    v1.0.75 removed

    请使用 args(index = 0)args().first()

    lastArgs - field

    Change Records

    v1.0 first

    v1.0.75 removed

    请使用 args().last()

    instance - field

    val instance: Any
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook 实例的对象。

    Pay Attention

    如果你当前 Hook 的对象是一个静态,那么它将不存在实例的对象。

    instanceClass - field

    val instanceClass: Class<*>
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook 实例的类对象。

    member - field

    val member: Member
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获取当前 Hook 对象的 Member

    在不确定 Member 类型为 MethodConstructor 时可以使用此方法。

    method - field

    val method: Method
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook 对象的方法。

    constructor - field

    val constructor: Constructor
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook 对象的构造方法。

    result - field

    var result: Any?
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取、设置当前 Hook 对象的 methodconstructor 的返回值。

    hasThrowable - field

    val hasThrowable: Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    判断是否存在设置过的方法调用抛出异常。

    throwable - field

    val throwable: Throwable?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获取设置的方法调用抛出异常。

    Throwable.throwToApp - i-ext-method

    fun Throwable.throwToApp()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    向 Hook APP 抛出异常。

    使用 hasThrowable 判断当前是否存在被抛出的异常。

    使用 throwable 获取当前设置的方法调用抛出异常。

    仅会在回调方法的 MemberHookCreator.beforeHookMemberHookCreator.afterHook 中生效。

    Pay Attention

    设置后会同时执行 resultNull 方法并将异常抛出给当前 Hook APP。

    Function Example

    Hook 过程中的异常仅会作用于 (Xposed) 宿主环境,目标 Hook APP 不会受到影响。

    若想将异常抛给 Hook APP,可以直接使用如下方法。

    The following example

    injectMember {
    +    method {
    +        // ...
    +    }
    +    beforeHook {
    +        RuntimeException("Test Exception").throwToApp()
    +    }
    +}
    +

    Pay Attention

    向 Hook APP 抛出异常会对其暴露被 Hook 的事实,是不安全的,容易被检测,请按实际场景合理使用。

    result - method

    inline fun <reified T> result(): T?
    +

    Change Records

    v1.0.75 added

    Function Illustrate

    获取当前 Hook 对象的 methodconstructor 的返回值 T

    firstArg - method

    Change Records

    v1.0.66 added

    v1.0.75 removed

    lastArgs - method

    Change Records

    v1.0.66 added

    v1.0.75 removed

    instance - method

    inline fun <reified T> instance(): T
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook 实例的对象 T

    Function Example

    你可以通过 instance 方法轻松使用泛型 cast 为目标对象的类型。

    The following example

    instance<Activity>().finish()
    +

    args - method

    fun args(): ArgsIndexCondition
    +

    Change Records

    v1.0.75 added

    Function Illustrate

    获取当前 Hook 对象的 methodconstructor 的参数数组下标实例化类。

    args - method

    fun args(index: Int): ArgsModifyer
    +

    Change Records

    v1.0 first

    v1.0.75 modified

    默认值 index = 0 移动到新的使用方法 args().first()

    Function Illustrate

    获取当前 Hook 对象的 methodconstructor 的参数实例化对象类。

    Function Example

    你可以通过 args 方法修改当前 Hook 实例的方法、构造方法的参数内容。

    你可以直接使用 set 方法设置 param 为你的目标实例,接受 Any 类型。

    Pay Attention

    请确保 param 类型为你的目标实例类型。

    The following example

    args(index = 0).set("modify the value")
    +

    你可以这样直接设置第一位 param 的值。

    The following example

    args().first().set("modify the value")
    +

    你还可以直接设置最后一位 param 的值。

    The following example

    args().last().set("modify the value")
    +

    你还可以使用 setNull 方法设置 param 为空。

    The following example

    args(index = 1).setNull()
    +

    你还可以使用 setTrue 方法设置 paramtrue

    Pay Attention

    请确保 param 类型为 Boolean

    The following example

    args(index = 1).setTrue()
    +

    你还可以使用 setFalse 方法设置 paramfalse

    Pay Attention

    请确保 param 类型为 Boolean

    The following example

    args(index = 1).setFalse()
    +

    callOriginal - method

    fun callOriginal(): Any?
    +
    fun <T> callOriginal(): T?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    执行原始 Member

    调用自身未进行 Hook 的原始 Member 并调用原始参数执行。

    功能实例

    此方法可以 invoke 原始未经 Hook 的 Member 对象,取决于原始 Member 的参数。

    调用自身原始的方法不会再经过当前 beforeHookafterHook 以及 replaceUnitreplaceAny

    比如我们 Hook 的这个方法被这样调用 test("test value"),使用此方法会调用其中的 "test value" 作为参数。

    The following example

    injectMember {
    +    method {
    +        name = "test"
    +        param(StringType)
    +        returnType = StringType
    +    }
    +    afterHook {
    +        // <方案1> 不使用泛型,不获取方法执行结果,调用将使用原方法传入的 args 自动传参
    +        callOriginal()
    +        // <方案2> 使用泛型,已知方法执行结果参数类型进行 cast
    +        // 假设返回值为 String,失败会返回 null,调用将使用原方法传入的 args 自动传参
    +        val value = callOriginal<String>()
    +    }
    +}
    +

    invokeOriginal - method

    fun invokeOriginal(vararg args: Any?): Any?
    +
    fun <T> invokeOriginal(vararg args: Any?): T?
    +

    Change Records

    v1.0 first

    v1.1.0 modified

    不再需要使用 member.invokeOriginal 进行调用

    Function Illustrate

    执行原始 Member

    调用自身未进行 Hook 的原始 Member 并自定义 args 执行。

    功能实例

    此方法可以 invoke 原始未经 Hook 的 Member 对象,可自定义需要调用的参数内容。

    调用自身原始的方法不会再经过当前 beforeHookafterHook 以及 replaceUnitreplaceAny

    比如我们 Hook 的这个方法被这样调用 test("test value"),使用此方法可自定义其中的 args 作为参数。

    The following example

    injectMember {
    +    method {
    +        name = "test"
    +        param(StringType)
    +        returnType = StringType
    +    }
    +    afterHook {
    +        // <方案1> 不使用泛型,不获取方法执行结果
    +        invokeOriginal("test value")
    +        // <方案2> 使用泛型,已知方法执行结果参数类型进行 cast,假设返回值为 String,失败会返回 null
    +        val value = invokeOriginal<String>("test value")
    +    }
    +}
    +

    resultTrue - method

    fun resultTrue()
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置当前 Hook 对象方法的 result 返回值为 true

    Pay Attention

    请确保 result 类型为 Boolean

    resultFalse - method

    fun resultFalse()
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置当前 Hook 对象方法的 result 返回值为 false

    Pay Attention

    请确保 result 类型为 Boolean

    resultNull - method

    fun resultNull()
    +

    Change Records

    v1.0 first

    Function Illustrate

    Notice

    此方法将强制设置 Hook 对象方法的 resultnull

    ArgsIndexCondition - class

    inner class ArgsIndexCondition internal constructor()
    +

    Change Records

    v1.0.75 added

    Function Illustrate

    对方法参数的数组下标进行实例化类。

    first - method

    fun first(): ArgsModifyer
    +

    Change Records

    v1.0.75 added

    Function Illustrate

    获取当前 Hook 对象的 methodconstructor 的参数数组第一位。

    last - method

    fun last(): ArgsModifyer
    +

    Change Records

    v1.0.75 added

    Function Illustrate

    获取当前 Hook 对象的 methodconstructor 的参数数组最后一位。

    ArgsModifyer - class

    inner class ArgsModifyer internal constructor(private val index: Int)
    +

    Change Records

    v1.0 first

    Function Illustrate

    对方法参数的修改进行实例化类。

    cast - method

    fun <T> cast(): T?
    +

    Change Records

    v1.0.66 added

    v1.0.68 modified

    修改 ofcast

    Function Illustrate

    得到方法参数的实例对象 T

    byte - method

    fun byte(): Byte?
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    得到方法参数的实例对象 Byte。

    int - method

    fun int(): Int
    +

    Change Records

    v1.0.66 added

    v1.0.68 modified

    修改 ofIntint

    Function Illustrate

    得到方法参数的实例对象 Int。

    long - method

    fun long(): Long
    +

    Change Records

    v1.0.66 added

    v1.0.68 modified

    修改 ofLonglong

    Function Illustrate

    得到方法参数的实例对象 Long。

    short - method

    fun short(): Short
    +

    Change Records

    v1.0.66 added

    v1.0.68 modified

    修改 ofShortshort

    Function Illustrate

    得到方法参数的实例对象 Short。

    double - method

    fun double(): Double
    +

    Change Records

    v1.0.66 added

    v1.0.68 modified

    修改 ofDoubledouble

    Function Illustrate

    得到方法参数的实例对象 Double。

    float - method

    fun float(): Float
    +

    Change Records

    v1.0.66 added

    v1.0.68 modified

    修改 ofFloatfloat

    Function Illustrate

    得到方法参数的实例对象 Float。

    string - method

    fun string(): String
    +

    Change Records

    v1.0.66 added

    v1.0.68 modified

    修改 ofStringstring

    Function Illustrate

    得到方法参数的实例对象 String。

    char - method

    fun char(): Char
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    得到方法参数的实例对象 Char。

    boolean - method

    fun boolean(): Boolean
    +

    Change Records

    v1.0.66 added

    v1.0.68 modified

    修改 ofBooleanboolean

    Function Illustrate

    得到方法参数的实例对象 Boolean。

    any - method

    fun any(): Any?
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    得到方法参数的实例对象 Any。

    array - method

    inline fun <reified T> array(): Array<T>
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    得到方法参数的实例对象 Array。

    list - method

    inline fun <reified T> list(): List<T>
    +

    Change Records

    v1.0.68 added

    Function Illustrate

    得到方法参数的实例对象 List。

    set - method

    fun <T> set(any: T?)
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置方法参数的实例对象。

    setNull - method

    fun setNull()
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置方法参数的实例对象为 null

    setTrue - method

    fun setTrue()
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置方法参数的实例对象为 true

    Pay Attention

    请确保目标对象的类型是 Boolean

    setFalse - method

    fun setFalse()
    +

    Change Records

    v1.0 first

    Function Illustrate

    设置方法参数的实例对象为 false

    Pay Attention

    请确保目标对象的类型是 Boolean

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html new file mode 100644 index 00000000..d92fa64a --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html @@ -0,0 +1,136 @@ + + + + + + + + + PackageParam - class | Yuki Hook API + + + + +

    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.

    PackageParam - class

    open class PackageParam internal constructor(internal var wrapper: PackageParamWrapper?)
    +

    Change Records

    v1.0 first

    Function Illustrate

    装载 Hook 的目标 APP 入口对象实现类。

    appClassLoader - field

    val appClassLoader:ClassLoader
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook APP 的 ClassLoader

    appInfo - field

    val appInfo: ApplicationInfo
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook APP 的 ApplicationInfo

    appUserId - field

    val appUserId: Int
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获取当前 Hook APP 的用户 ID。

    机主为 0,应用双开 (分身) 或工作资料因系统环境不同 ID 也各不相同。

    appContext - field

    val appContext: Application?
    +

    Change Records

    v1.0.72 added

    v1.1.0 modified

    加入可空类型 (空安全)

    Function Illustrate

    获取当前 Hook APP 的 Application

    Pay Attention

    首次装载可能是空的,请延迟一段时间再获取或使用 onAppLifecycle 监听来完成。

    appResources - field

    val appResources:Resources?
    +

    Change Records

    v1.0.80 added

    v1.1.0 modified

    加入可空类型 (空安全)

    Function Illustrate

    获取当前 Hook APP 的 Resources。

    Pay Attention

    你只能在 HookResources.hook 方法体内或 appContext 装载完毕时进行调用。

    systemContext - field

    val systemContext: Context
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    获取当前系统框架的 Context

    processName - field

    val processName: String
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook APP 的进程名称。

    packageName - field

    val packageName: String
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook APP 的包名。

    isFirstApplication - field

    val isFirstApplication: Boolean
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取当前 Hook APP 是否为第一个 Application

    mainProcessName - field

    val mainProcessName: String
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    获取当前 Hook APP 的主进程名称。

    其对应的就是 packageName

    moduleAppFilePath - field

    val moduleAppFilePath: String
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    获取当前 Xposed 模块自身 APK 文件路径。

    Pay Attention

    作为 Hook API 装载时无法使用,会获取到空字符串。

    moduleAppResources - field

    val moduleAppResources: YukiModuleResources
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    获取当前 Xposed 模块自身 Resources

    Pay Attention

    作为 Hook API 或不支持的 Hook Framework 装载时无法使用,会抛出异常。

    prefs - field

    val prefs: YukiHookModulePrefs
    +

    Change Records

    v1.0 first

    Function Illustrate

    获得当前使用的存取数据对象缓存实例。

    Pay Attention

    作为 Hook API 装载时无法使用,会抛出异常。

    prefs - method

    fun prefs(name: String): YukiHookModulePrefs
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    获得当前使用的存取数据对象缓存实例。

    你可以通过 name 来自定义 Sp 存储的名称。

    Pay Attention

    作为 Hook API 装载时无法使用,会抛出异常。

    dataChannel - field

    val dataChannel: YukiHookDataChannel.NameSpace
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    获得当前使用的数据通讯桥命名空间对象。

    Pay Attention

    作为 Hook API 装载时无法使用,会抛出异常。

    resources - method

    fun resources(): HookResources
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    获得当前 Hook APP 的 YukiResources 对象。

    请调用 HookResources.hook 方法开始 Hook。

    refreshModuleAppResources - method

    fun refreshModuleAppResources()
    +

    Change Records

    v1.0.87 added

    Function Illustrate

    刷新当前 Xposed 模块自身 Resources

    onAppLifecycle - method

    inline fun onAppLifecycle(initiate: AppLifecycle.() -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    监听当前 Hook APP 生命周期装载事件。

    Notice

    loadZygote 中不会被装载,仅会在 loadSystemloadApp 中装载。

    作为 Hook API 装载时请使用原生的 Application 实现生命周期监听。

    loadApp - method

    inline fun loadApp(name: String, initiate: PackageParam.() -> Unit)
    +
    fun loadApp(name: String, hooker: YukiBaseHooker)
    +

    Change Records

    v1.0 first

    v1.0.80 modified

    将方法体进行 inline

    Function Illustrate

    装载并 Hook 指定包名的 APP。

    name 为 APP 的包名,后方的两个参数一个可作为 lambda 方法体使用,一个可以直接装载子 Hooker。

    装载并 Hook 指定、全部包名的 APP。

    若要装载 APP Zygote 事件,请使用 loadZygote

    若要 Hook 系统框架,请使用 loadSystem

    Function Example

    你可以使用 loadApplambda 方法体形式或直接装载一个 Hooker。

    The following example

    // 使用 lambda
    +loadApp(name = "com.example.test") {
    +    // Your code here.
    +}
    +// 使用 Hooker
    +loadApp(name = "com.example.test", CustomHooker)
    +

    若不指定 name 参数,则此方法体默认会过滤当前系统中全部可被 Hook 的 APP。

    The following example

    // 使用 lambda
    +loadApp {
    +    // Your code here.
    +}
    +// 使用 Hooker
    +loadApp(hooker = CustomHooker)
    +

    loadZygote - method

    inline fun loadZygote(initiate: PackageParam.() -> Unit)
    +
    fun loadZygote(hooker: YukiBaseHooker)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    装载 APP Zygote 事件。

    方法中的两个参数一个可作为 lambda 方法体使用,一个可以直接装载子 Hooker。

    loadSystem - method

    inline fun loadSystem(initiate: PackageParam.() -> Unit)
    +
    fun loadSystem(hooker: YukiBaseHooker)
    +

    Change Records

    v1.0.82 added

    Function Illustrate

    装载并 Hook 系统框架。

    方法中的两个参数一个可作为 lambda 方法体使用,一个可以直接装载子 Hooker。

    withProcess - method

    inline fun withProcess(name: String, initiate: PackageParam.() -> Unit)
    +
    fun withProcess(name: String, hooker: YukiBaseHooker)
    +

    Change Records

    v1.0.70 added

    Function Illustrate

    装载并 Hook APP 的指定进程。

    name 为 APP 的进程名称,后方的两个参数一个可作为 lambda 方法体使用,一个可以直接装载子 Hooker。

    loadHooker - method

    fun loadHooker(hooker: YukiBaseHooker)
    +

    Change Records

    v1.0 first

    Function Illustrate

    装载 Hook 子类。

    你可以填入 hooker 在 Hooker 中继续装载 Hooker。

    searchClass - method

    inline fun searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    通过 appClassLoader 按指定条件查找并得到当前 Hook APP Dex 中的 Class

    Pay Attention

    此方法在 Class 数量过多及查找条件复杂时会非常耗时。

    建议启用 async 或设置 name 参数,name 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。

    此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。

    String+VariousClass.clazz - i-ext-field

    Change Records

    v1.0 first

    v1.1.0 deprecated

    请转移到 toClass(...) 方法

    String.hasClass - i-ext-field

    Change Records

    v1.0 first

    v1.1.0 deprecated

    请转移到 hasClass(...) 方法

    String+VariousClass.toClass - i-ext-method

    fun String.toClass(loader: ClassLoader?): Class<*>
    +
    fun VariousClass.toClass(loader: ClassLoader?): Class<*>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    通过字符串类名、VariousClass 转换为 loader 中的实体类。

    默认使用当前 appClassLoader 装载目标 Class

    Function Example

    你可以轻松地将 String 类型的 Class 包名转为 Class 实例。

    The following example

    "com.example.demo.DemoClass".toClass()
    +

    你还可以向 loader 参数传入你自定义的 ClassLoader

    The following example

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +"com.example.demo.DemoClass".toClass(customClassLoader)
    +

    你还可以创建一个 VariousClass,并转换为实体类。

    VariousClass 会枚举所有设置的 Class 并最终获得第一个存在的 Class

    The following example

    VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass()
    +

    同样地,你还可以向 loader 参数传入你自定义的 ClassLoader

    The following example

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").toClass(customClassLoader)
    +

    String+VariousClass.toClassOrNull - i-ext-method

    fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
    +
    fun VariousClass.toClassOrNull(loader: ClassLoader?): Class<*>?
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    通过字符串类名、VariousClass 转换为 loader 中的实体类。

    默认使用当前 appClassLoader 装载目标 Class

    找不到 Class 会返回 null,不会抛出异常。

    Function Example

    用法请参考 String+VariousClass.toClass 方法。

    String.hasClass - i-ext-method

    fun String.hasClass(loader: ClassLoader?): Boolean
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    通过字符串类名查找是否存在。

    默认使用当前 appClassLoader 装载目标 Class

    Function Example

    你可以轻松的使用此方法判断字符串中的类是否存在。

    The following example

    if("com.example.demo.DemoClass".hasClass()) {
    +    // Your code here.
    +}
    +

    你还可以自定义其中的 loader 参数,默认为 appClassLoader

    The following example

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +if("com.example.demo.DemoClass".hasClass(customClassLoader)) {
    +    // Your code here.
    +}
    +

    findClass - method

    fun findClass(name: String, loader: ClassLoader?): HookClass
    +
    fun findClass(vararg name: String, loader: ClassLoader?): VariousClass
    +

    Change Records

    v1.0 first

    v1.0.1 modified

    移除了 findClass(various: VariousClass) 方法

    v1.1.0 modified

    新增 loader 参数

    Function Illustrate

    通过完整包名+名称查找需要被 Hook 的 Class

    Notice

    使用此方法会得到一个 HookClass 仅用于 Hook,若想查找 Class 请使用 toClass 功能。

    Function Example

    你可以使用三种方式查找你需要 Hook 的目标 Class

    你可以直接将被查找的 Class 完整包名+名称填入 name 中。

    The following example

    findClass(name = "com.example.demo.DemoClass")
    +

    若你不确定多个版本的 Class 以及不同名称,你可以将多个完整包名+名称填入 name 中。

    The following example

    findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
    +

    你还可以创建一个 VariousClass,将 Class 的完整包名+名称填入 VariousClassname 中并填入 various 参数中。

    The following example

    val variousClass = VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2", "com.example.demo.DemoClass3")
    +

    若你当前需要查找的 Class 不属于 appClassLoader,你可以使用 loader 参数指定你要装载的 ClassLoader

    The following example

    val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
    +findClass(name = "com.example.demo.OutsideClass", loader = outsideLoader)
    +

    同样地,在不确定多个版本的 Class 以及不同名称时,也可以使用 loader 参数指定你要装载的 ClassLoader

    The following example

    val outsideLoader: ClassLoader? = ... // 假设这就是你的 ClassLoader
    +findClass("com.example.demo.OutsideClass1", "com.example.demo.OutsideClass2", "com.example.demo.OutsideClass3", loader = outsideLoader)
    +

    String+Class+VariousClass+HookClass.hook - i-ext-method

    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

    新增 VariousClass 的直接调用 hook 方法

    v1.0.2 modified

    新增 String 的直接调用 hook 方法

    v1.0.3 modified

    新增 YukiMemberHookCreator.Result 返回值

    v1.0.70 modified

    新增 isUseAppClassLoader 参数

    v1.0.80 modified

    将方法体进行 inline

    v1.1.0 modified

    移除了 isUseAppClassLoader 参数

    添加了 isForceUseAbsolute 参数到 Class.hook 方法

    Function Illustrate

    这是一切 Hook 的入口创建方法,Hook 方法、构造方法。

    Function Example

    如你所见,Hook 方法体的创建可使用 4 种方式。

    通过字符串类名得到 HookClass 实例进行创建。

    The following example

    "com.example.demo.DemoClass".hook {
    +    // Your code here.
    +}
    +
    +

    通过 findClass 得到 HookClass 实例进行创建。

    The following example

    findClass(name = "com.example.demo.DemoClass").hook {
    +    // Your code here.
    +}
    +

    使用 stub 或直接拿到 Class 实例进行创建。

    默认情况下 API 会将 Class 实例转换为类名并绑定到 appClassLoader,若失败,则会使用原始 Class 实例直接进行 Hook。

    The following example

    Stub::class.java.hook {
    +    // Your code here.
    +}
    +

    若当前 Class 不在 appClassLoader 且自动匹配无法找到该 Class,请启用 isForceUseAbsolute

    The following example

    YourClass::class.java.hook(isForceUseAbsolute = true) {
    +    // Your code here.
    +}
    +

    使用 VariousClass 实例进行创建。

    The following example

    VariousClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
    +    // Your code here.
    +}
    +

    或者直接使用可变字符串数组进行创建。

    The following example

    findClass("com.example.demo.DemoClass1", "com.example.demo.DemoClass2").hook {
    +    // Your code here.
    +}
    +

    HookResources.hook - i-ext-method

    inline fun HookResources.hook(initiate: YukiResourcesHookCreator.() -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    Hook APP 的 Resources。

    Pay Attention

    请注意你需要确保当前 Hook Framework 支持且 InjectYukiHookWithXposed.isUsingResourcesHook 已启用。

    Function Example

    Resources Hook 为固定用法,获取 resources 对象,然后调用 hook 方法开始 Hook。

    The following example

    resources().hook {
    +    // Your code here.
    +}
    +

    Pay Attention

    这是固定用法,为了防止发生问题,你不可手动实现任何 HookResources 实例执行 hook 调用。

    将 Resources 的 Hook 设置为这样是为了与 findClass(...).hook 做到统一,使得调用起来逻辑不会混乱。

    AppLifecycle - class

    inner class AppLifecycle internal constructor()
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    当前 Hook APP 的生命周期实例处理类。

    attachBaseContext - method

    fun attachBaseContext(result: (baseContext: Context, hasCalledSuper: Boolean) -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    监听当前 Hook APP 装载 Application.attachBaseContext

    onCreate - method

    fun onCreate(initiate: Application.() -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    监听当前 Hook APP 装载 Application.onCreate

    onTerminate - method

    fun onTerminate(initiate: Application.() -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    监听当前 Hook APP 装载 Application.onTerminate

    onLowMemory - method

    fun onLowMemory(initiate: Application.() -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    监听当前 Hook APP 装载 Application.onLowMemory

    onTrimMemory - method

    fun onTrimMemory(result: (self: Application, level: Int) -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    监听当前 Hook APP 装载 Application.onTrimMemory

    onConfigurationChanged - method

    fun onConfigurationChanged(result: (self: Application, config: Configuration) -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    监听当前 Hook APP 装载 Application.onConfigurationChanged

    registerReceiver - method

    fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    注册系统广播监听。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html new file mode 100644 index 00000000..7e148c35 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html @@ -0,0 +1,33 @@ + + + + + + + + + ComponentTypeFactory - kt | Yuki Hook API + + + + +

    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.

    ComponentTypeFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    这是一个预置 Hook 类型的常量类,主要为 Android 相关组件的 Class 内容,跟随版本更新会逐一进行增加。

    详情可 点击这里open in new window 进行查看。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html new file mode 100644 index 00000000..49680be4 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html @@ -0,0 +1,33 @@ + + + + + + + + + GraphicsTypeFactory - kt | Yuki Hook API + + + + +

    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.

    GraphicsTypeFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    这是一个预置 Hook 类型的常量类,主要为 Android 相关 GraphicsClass 内容,跟随版本更新会逐一进行增加。

    详情可 点击这里open in new window 进行查看。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html new file mode 100644 index 00000000..e5c82151 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html @@ -0,0 +1,33 @@ + + + + + + + + + ViewTypeFactory - kt | Yuki Hook API + + + + +

    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.

    ViewTypeFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    这是一个预置 Hook 类型的常量类,主要为 Android 相关 WidgetClass 内容,跟随版本更新会逐一进行增加。

    详情可 点击这里open in new window 进行查看。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html new file mode 100644 index 00000000..f6590c07 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html @@ -0,0 +1,34 @@ + + + + + + + + + DefinedTypeFactory - kt | Yuki Hook API + + + + +

    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.

    DefinedTypeFactory - kt

    Change Records

    v1.1.0 added

    Function Illustrate

    这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。

    VagueType - field

    val VagueType: Class<*>
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    得到模糊类型。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html new file mode 100644 index 00000000..6d41f266 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html @@ -0,0 +1,33 @@ + + + + + + + + + VariableTypeFactory - kt | Yuki Hook API + + + + +

    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.

    VariableTypeFactory - kt

    Change Records

    v1.0 first

    Function Illustrate

    这是一个预置 Hook 类型的常量类,主要为 Java 相关基本变量类型的 Class 内容,跟随版本更新会逐一进行增加。

    详情可 点击这里open in new window 进行查看。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html new file mode 100644 index 00000000..82760cd9 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html @@ -0,0 +1,49 @@ + + + + + + + + + ModuleApplication - class | Yuki Hook API + + + + +

    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.

    ModuleApplication - class

    open class ModuleApplication: Application()
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    这是对使用 YukiHookAPI Xposed 模块实现中的一个扩展功能。

    在你的 Xposed 模块的 Application 中继承此类。

    或在 AndroidManifest.xmlapplication 标签中指定此类。

    目前可实现功能如下

    • 全局共享模块中静态的 appContext

    • 在模块与宿主中装载 YukiHookAPI.Config 以确保 YukiHookAPI.Configs.debugTag 不需要重复定义

    • 在模块与宿主中使用 YukiHookDataChannel 进行通讯

    • 在模块中使用系统隐藏 API,核心技术引用了开源项目 FreeReflectionopen in new window

    • 在模块中使用 YukiHookAPI.Status.isTaiChiModuleActive 判断太极、无极激活状态

    Function Example

    将此类继承到你的自定义 Application 上。

    The following example

    package com.demo
    +
    +class MyApplication: ModuleApplication() {
    +
    +    override fun onCreate() {
    +        super.onCreate()
    +    }
    +}
    +

    AndroidManifest.xmlapplication 标签中指定自定义的 Application

    The following example

    <application
    +    android:name="com.demo.MyApplication"
    +    ...>
    +

    如果你不需要自定义 Application 可以直接将 ModuleApplication 设置到 AndroidManifest.xmlapplication 标签中。

    The following example

    <application
    +    android:name="com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication"
    +    ...>
    +

    appContext - field

    val appContext: ModuleApplication
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    获取全局静态 Application 实例。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html new file mode 100644 index 00000000..ff195102 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html @@ -0,0 +1,35 @@ + + + + + + + + + YukiModuleResources - class | Yuki Hook API + + + + +

    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.

    YukiModuleResources - class

    class YukiModuleResources private constructor(private val baseInstance: XModuleResources) : Resources
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    对接 XModuleResources 的中间层实例。

    fwd - method

    fun fwd(resId: Int): YukiResForwarder
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    对接 XModuleResources.fwd 方法。

    创建 YukiResForwarderXResForwarder 实例。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html new file mode 100644 index 00000000..b5324717 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html @@ -0,0 +1,36 @@ + + + + + + + + + YukiResForwarder - class | Yuki Hook API + + + + +

    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.

    YukiResForwarder - class

    class YukiResForwarder private constructor(private val baseInstance: XResForwarder)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    对接 XResForwarder 的中间层实例。

    instance - field

    Change Records

    v1.0.80 added

    v1.1.0 deprecated

    不再对外公开 instance 参数

    id - field

    val id: Int
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    获得当前 APP 的 Resources Id。

    resources - field

    val resources: Resources
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    获得当前 APP 的 Resources。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html new file mode 100644 index 00000000..e7c76ea3 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html @@ -0,0 +1,39 @@ + + + + + + + + + YukiResources - class | Yuki Hook API + + + + +

    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.

    YukiResources - class

    class YukiResources private constructor(private val baseInstance: XResources) : Resources
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    对接 XResources 的中间层实例。

    LayoutInflatedParam - class

    class LayoutInflatedParam(internal val baseParam: XC_LayoutInflated.LayoutInflatedParam)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    装载 Hook APP 的目标布局 Resources 实现类。

    variantName - field

    val variantName: String
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    获取当前被 Hook 的布局装载目录名称。

    例如:layoutlayout-landlayout-sw600dp

    currentView - field

    val currentView: View
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    获取当前被 Hook 的布局实例。

    findViewByIdentifier - method

    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

    使用 Identifier 查找 Hook APP 指定 Id 的 View

    扩展方法可以使用 Identifier 查找 Hook APP 当前装载布局中指定 Id 的 View

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html new file mode 100644 index 00000000..be8247e5 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html @@ -0,0 +1,38 @@ + + + + + + + + + YukiXposedEvent - object | Yuki Hook API + + + + +

    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.

    YukiXposedEvent - object

    object YukiXposedEvent
    +

    Change Records

    v1.0.80 first

    Function Illustrate

    实现对原生 Xposed API 的装载事件监听。

    events - method

    inline fun events(initiate: YukiXposedEvent.() -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    YukiXposedEvent 创建一个方法体。

    onInitZygote - method

    fun onInitZygote(result: (StartupParam) -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 initZygote 事件监听。

    onHandleLoadPackage - method

    fun onHandleLoadPackage(result: (LoadPackageParam) -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 handleLoadPackage 事件监听。

    onHandleInitPackageResources - method

    fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    设置 handleInitPackageResources 事件监听。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html new file mode 100644 index 00000000..f5204562 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html @@ -0,0 +1,44 @@ + + + + + + + + + YukiHookDataChannel - class | Yuki Hook API + + + + +

    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.

    YukiHookDataChannel - class

    class YukiHookDataChannel private constructor()
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    实现 Xposed 模块的数据通讯桥。

    通过模块与宿主相互注册 BroadcastReceiver 来实现数据的交互。

    模块需要将 Application 继承于 ModuleApplication 来实现此功能。

    Pay Attention

    模块与宿主需要保持存活状态,否则无法建立通讯。

    NameSpace - class

    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

    新增 isSecure 参数

    Function Illustrate

    YukiHookDataChannel 命名空间。

    with - method

    inline fun with(initiate: NameSpace.() -> Unit): NameSpace
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    创建一个调用空间。

    put - method

    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

    发送键值数据。

    put - method

    fun put(key: String)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    仅发送键值监听,使用默认值 VALUE_WAIT_FOR_LISTENER 发送键值数据。

    wait - method

    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

    移除默认值 value

    Function Illustrate

    获取键值数据。

    wait - method

    fun wait(key: String, callback: () -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    仅获取监听结果,不获取键值数据。

    Pay Attention

    仅限使用 VALUE_WAIT_FOR_LISTENER 发送的监听才能被接收。

    checkingVersionEquals - method

    fun checkingVersionEquals(result: (Boolean) -> Unit)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    获取模块与宿主的版本是否匹配。

    通过此方法可原生判断 Xposed 模块更新后宿主并未重新装载造成两者不匹配的情况。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html new file mode 100644 index 00000000..e5d6d5e3 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html @@ -0,0 +1,55 @@ + + + + + + + + + ChannelData - class | Yuki Hook API + + + + +

    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.

    ChannelData - class

    data class ChannelData<T>(var key: String, var value: T?)
    +

    Change Records

    v1.0.88 added

    Function Illustrate

    数据通讯桥键值构造类。

    这个类是对 YukiHookDataChannel 的一个扩展用法。

    Function Example

    建立一个模板类定义模块与宿主需要发送的键值数据。

    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)
    +}
    +

    键值数据定义后,你就可以方便地在模块和宿主中调用所需要发送的数据。

    模块示例如下

    // 从指定包名的宿主获取
    +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")
    +

    你依然可以不使用模板定义的默认值,随时修改你的默认值。

    The following example

    // 获取 - 此时 value 取到的默认值将会是 2 - 并不是模板提供的 0
    +dataChannel.wait(DataConst.TEST_KV_DATA_2, value = 2) { value ->
    +    // Your code here.
    +}
    +
    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html new file mode 100644 index 00000000..4cacf1f4 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html @@ -0,0 +1,34 @@ + + + + + + + + + ModuleAppActivity - class | Yuki Hook API + + + + +

    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.

    ModuleAppActivity - class

    open class ModuleAppActivity : Activity()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    代理 Activity

    继承于此类的 Activity 可以同时在宿主与模块中启动。

    在 (Xposed) 宿主环境需要在宿主启动时调用 Context.registerModuleAppActivities 进行注册。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html new file mode 100644 index 00000000..11580598 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html @@ -0,0 +1,35 @@ + + + + + + + + + ModuleAppCompatActivity - class | Yuki Hook API + + + + +

    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.

    ModuleAppCompatActivity - class

    open class ModuleAppCompatActivity : AppCompatActivity()
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    代理 AppCompatActivity

    继承于此类的 Activity 可以同时在宿主与模块中启动。

    在 (Xposed) 宿主环境需要在宿主启动时调用 Context.registerModuleAppActivities 进行注册。

    在 (Xposed) 宿主环境需要重写 moduleTheme 设置 AppCompat 主题,否则会无法启动。

    moduleTheme - field

    open val moduleTheme: Int
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置当前代理的 Activity 主题。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html new file mode 100644 index 00000000..faff7bc4 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html @@ -0,0 +1,35 @@ + + + + + + + + + ModuleContextThemeWrapper - class | Yuki Hook API + + + + +

    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.

    ModuleContextThemeWrapper - class

    class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) : ContextThemeWrapper
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    代理 ContextThemeWrapper

    通过包装,你可以轻松在 (Xposed) 宿主环境使用来自模块的主题资源。

    applyConfiguration - method

    fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
    +

    Change Records

    v1.1.0 added

    Function Illustrate

    设置当前 ModuleContextThemeWrapperConfiguration

    设置后会自动调用 Resources.updateConfiguration

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html new file mode 100644 index 00000000..939bfc46 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html @@ -0,0 +1,62 @@ + + + + + + + + + YukiHookModulePrefs - class | Yuki Hook API + + + + +

    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.

    YukiHookModulePrefs - class

    class YukiHookModulePrefs private constructor(private var context: Context?)
    +

    Change Records

    v1.0 first

    Function Illustrate

    实现 Xposed 模块的数据存取,对接 SharedPreferencesXSharedPreferences

    在不同环境智能选择存取使用的对象。

    Pay Attention

    此功能为实验性功能,仅在 LSPosed 环境测试通过,EdXposed 理论也可以使用但不再推荐。

    使用 LSPosed 环境请在 AndroidManifests.xml 中将 xposedminversion 最低设置为 93

    详见 New XSharedPreferencesopen in new window

    若你在按照规定配置后依然无法使用或出现文件权限错误问题,可以参考 isEnableHookSharedPreferences

    未使用 LSPosed 环境请将你的模块 API 降至 26 以下,YukiHookAPI 将会尝试使用 makeWorldReadable 但仍有可能不成功。

    太极请参阅 文件权限/配置/XSharedPreferenceopen in new window

    Pay Attention

    当你在 Xposed 模块中存取数据的时候 context 必须不能是空的。

    若你正在使用 PreferenceFragmentCompat,请迁移到 ModulePreferenceFragment 以适配上述功能特性。

    可选配置

    若你不想将你的模块的 xposedminversion 最低设置为 93,你可以在 AndroidManifest.xml 中添加 xposedsharedprefs 来实现支持。

    详见 New XSharedPreferencesopen in new window

    The following example

    <meta-data
    +    android:name="xposedsharedprefs"
    +    android:value="true"/>
    +

    isXSharePrefsReadable - field

    val isXSharePrefsReadable: Boolean
    +

    Change Records

    v1.0.90 added

    Function Illustrate

    获取 XSharedPreferences 是否可读。

    Pay Attention

    只能在 (Xposed) 宿主环境中使用,模块环境中始终返回 false。

    isRunInNewXShareMode - field

    val isRunInNewXShareMode: Boolean
    +

    Change Records

    v1.0.78 added

    Function Illustrate

    获取 YukiHookModulePrefs 是否正处于 EdXposed/LSPosed 的最高权限运行。

    前提条件为当前 Xposed 模块已被激活。

    Pay Attention

    只能在模块环境中使用,(Xposed) 宿主环境中始终返回 false。

    name - method

    fun name(name: String): YukiHookModulePrefs
    +

    Change Records

    v1.0 first

    Function Illustrate

    自定义 Sp 存储名称。

    Function Example

    Activity 中的使用方法。

    The following example

    modulePrefs("custom_name").getString("custom_key")
    +

    在 (Xposed) 宿主环境 PackageParam 中的使用方法。

    The following example

    prefs("custom_name").getString("custom_key")
    +

    direct - method

    fun direct(): YukiHookModulePrefs
    +

    Change Records

    v1.0.5 added

    Function Illustrate

    忽略缓存直接读取键值。

    无论是否开启 YukiHookAPI.Configs.isEnableModulePrefsCache

    仅在 XSharedPreferences 下生效。

    getString - method

    fun getString(key: String, value: String): String
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取 String 键值。

    getStringSet - method

    fun getStringSet(key: String, value: Set<String>): Set<String>
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    获取 Set<String> 键值。

    getBoolean - method

    fun getBoolean(key: String, value: Boolean): Boolean
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取 Boolean 键值。

    getInt - method

    fun getInt(key: String, value: Int): Int
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取 Int 键值。

    getLong - method

    fun getLong(key: String, value: Long): Long
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取 Long 键值。

    getFloat - method

    fun getFloat(key: String, value: Float): Float
    +

    Change Records

    v1.0 first

    Function Illustrate

    获取 Float 键值。

    all - method

    fun all(): HashMap<String, Any?>
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    获取全部存储的键值数据。

    智能识别对应环境读取键值数据。

    Pay Attention

    每次调用都会获取实时的数据,不受缓存控制,请勿在高并发场景中使用。

    remove - method

    fun remove(key: String)
    +

    Change Records

    v1.0 first

    Function Illustrate

    移除全部包含 key 的存储数据。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    remove - method

    inline fun <reified T> remove(prefs: PrefsData<T>)
    +

    Change Records

    v1.0.67 added

    Function Illustrate

    移除 PrefsData.key 的存储数据。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    clear - method

    fun clear()
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    移除全部存储数据。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    putString - method

    fun putString(key: String, value: String)
    +

    Change Records

    v1.0 first

    Function Illustrate

    存储 String 键值。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    putStringSet - method

    fun putStringSet(key: String, value: Set<String>)
    +

    Change Records

    v1.0.77 added

    Function Illustrate

    存储 Set<String> 键值。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    putBoolean - method

    fun putBoolean(key: String, value: Boolean)
    +

    Change Records

    v1.0 first

    Function Illustrate

    存储 Boolean 键值。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    putInt - method

    fun putInt(key: String, value: Int)
    +

    Change Records

    v1.0 first

    Function Illustrate

    存储 Int 键值。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    putLong - method

    fun putLong(key: String, value: Long)
    +

    Change Records

    v1.0 first

    Function Illustrate

    存储 Long 键值。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    putFloat - method

    fun putFloat(key: String, value: Float)
    +

    Change Records

    v1.0 first

    Function Illustrate

    存储 Float 键值。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    get - method

    inline fun <reified T> get(prefs: PrefsData<T>, value: T): T
    +

    Change Records

    v1.0.67 added

    Function Illustrate

    智能获取指定类型的键值。

    put - method

    inline fun <reified T> put(prefs: PrefsData<T>, value: T)
    +

    Change Records

    v1.0.67 added

    Function Illustrate

    智能存储指定类型的键值。

    Notice

    在 (Xposed) 宿主环境下只读,无法使用。

    clearCache - method

    fun clearCache()
    +

    Change Records

    v1.0.5 added

    Function Illustrate

    清除 XSharedPreferences 中缓存的键值数据。

    无论是否开启 YukiHookAPI.Configs.isEnableModulePrefsCache

    调用此方法将清除当前存储的全部键值缓存。

    下次将从 XSharedPreferences 重新读取。

    在 (Xposed) 宿主环境中使用。

    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html new file mode 100644 index 00000000..6e2bb98d --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html @@ -0,0 +1,50 @@ + + + + + + + + + PrefsData - class | Yuki Hook API + + + + +

    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.

    PrefsData - class

    data class PrefsData<T>(var key: String, var value: T)
    +

    Change Records

    v1.0.67 added

    Function Illustrate

    键值对存储构造类。

    这个类是对 YukiHookModulePrefs 的一个扩展用法。

    Function Example

    建立一个模板类定义模块与宿主需要使用的键值数据。

    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)
    +}
    +

    键值数据定义后,你就可以方便地在模块和宿主中调用所需要的数据。

    模块示例如下

    // 读取
    +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)
    +

    你依然可以不使用模板定义的默认值,随时修改你的默认值。

    The following example

    // 读取 - 此时 data 取到的默认值将会是 2 - 并不是模板提供的 0
    +val data = prefs.get(DataConst.TEST_KV_DATA_3, 2)
    +
    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html new file mode 100644 index 00000000..94666b10 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html @@ -0,0 +1,54 @@ + + + + + + + + + ModulePreferenceFragment - class | Yuki Hook API + + + + +

    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.

    ModulePreferenceFragment - class

    abstract class ModulePreferenceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener
    +

    Change Records

    v1.0.78 added

    Function Illustrate

    这是对使用 YukiHookAPI Xposed 模块实现中的一个扩展功能。

    此类接管了 PreferenceFragmentCompat 并对其实现了 Sp 存储在 Xposed 模块中的全局可读可写。

    在你使用 PreferenceFragmentCompat 的实例中,将继承对象换成此类。

    然后请将重写方法由 onCreatePreferences 替换为 onCreatePreferencesInModuleApp 即可。

    Function Example

    使用 ModulePreferenceFragment 创建一个 PreferenceFragmentCompat 对象。

    The following example

    class SettingsFragment : ModulePreferenceFragment() {
    +
    +    override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
    +        setPreferencesFromResource(R.xml.settings_preferences, rootKey)
    +        // Your code here.
    +    }
    +}
    +

    其余用法与 PreferenceFragmentCompat 保持一致。

    onCreatePreferencesInModuleApp - method

    abstract fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?)
    +

    Change Records

    v1.0.78 added

    Function Illustrate

    对接原始方法 onCreatePreferences

    onSharedPreferenceChanged - method

    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?)
    +

    Change Records

    v1.0.78 added

    Function Illustrate

    实现了 SharedPreferences.OnSharedPreferenceChangeListener 的原生监听功能。

    Function Example

    Notice

    在使用 onSharedPreferenceChanged 时请保留 super 方法。

    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.
    +    }
    +}
    +
    + + + diff --git a/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html new file mode 100644 index 00000000..baf6ca04 --- /dev/null +++ b/docs/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html @@ -0,0 +1,37 @@ + + + + + + + + + IYukiHookXposedInit - interface | Yuki Hook API + + + + +

    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.

    IYukiHookXposedInit - interface

    interface IYukiHookXposedInit
    +

    Change Records

    v1.0 first

    v1.0.80 modified deprecated

    作废了 YukiHookXposedInitProxy 名称但保留接口

    转移到 IYukiHookXposedInit 新名称

    Function Illustrate

    YukiHookAPI 的 Xposed 装载 API 调用接口。

    onInit - method

    fun onInit()
    +

    Change Records

    v1.0.5 added

    Function Illustrate

    配置 YukiHookAPI.Configs 的初始化方法。

    Pay Attention

    在这里只能进行初始化配置,不能进行 Hook 操作。

    此方法可选,你也可以选择不对 YukiHookAPI.Configs 进行配置。

    onHook - method

    fun onHook()
    +

    Change Records

    v1.0 first

    Function Illustrate

    Xposed API 的模块装载调用入口方法。

    onXposedEvent - method

    fun onXposedEvent()
    +

    Change Records

    v1.0.80 added

    Function Illustrate

    监听 Xposed 原生装载事件。

    若你的 Hook 事件中存在需要兼容的原生 Xposed 功能,可在这里实现。

    请在这里使用 YukiXposedEvent 创建回调事件监听。

    可监听的事件如下:

    YukiXposedEvent.onInitZygote

    YukiXposedEvent.onHandleLoadPackage

    YukiXposedEvent.onHandleInitPackageResources

    Pay Attention

    此接口仅供监听和实现原生 Xposed API 的功能,请不要在这里操作 YukiHookAPI

    YukiHookXposedInitProxy - interface

    Change Records

    v1.0 first

    v1.0.80 deprecated

    请转移到 IYukiHookXposedInit

    + + + diff --git a/docs/en/api/special-features/host-inject.html b/docs/en/api/special-features/host-inject.html new file mode 100644 index 00000000..63f54298 --- /dev/null +++ b/docs/en/api/special-features/host-inject.html @@ -0,0 +1,154 @@ + + + + + + + + + Host Resource Injection Extension | Yuki Hook API + + + + +

    Host Resource Injection Extension

    This is an extension that injects Module App's Resources, Activity components, and Context topics into the Host App.

    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 build.gradle of the current Xposed Module project.

    • Kotlin Gradle DSL
    android {
    +    androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
    +}
    +
    • Groovy
    android {
    +    aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
    +}
    +

    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.

    Inject Module App's Resources

    After the Host App is hooked, we can directly inject the Context obtained in the Hooker into the current Module App's Resources.

    The following example

    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)
    +        }
    +    }
    +}
    +

    You can also inject current Module App's Resources directly in AppLifecycle.

    The following example

    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)
    +    }
    +}
    +

    Tips

    For more functions, please refer to the Context+Resources.injectModuleAppResources method.

    Register Module App's Activity

    When the Activity of all applications in the Android system starts, it needs to be registered in AndroidManifest.xml.

    During the Hook process, if we want to directly start the unregistered Activity in the Module App through the Host App, what should we do?

    After the Host App is hooked, we can directly register the Activity proxy of the current Module App in the Context obtained in the Hooker.

    The following example

    injectMember {
    +    method {
    +        name = "onCreate"
    +        param(BundleClass)
    +    }
    +    afterHook {
    +        instance<Activity>().registerModuleAppActivities()
    +    }
    +}
    +

    You can also register the current Module App's Activity proxy directly in AppLifecycle.

    The following example

    onAppLifecycle {
    +    onCreate {
    +        registerModuleAppActivities()
    +    }
    +}
    +

    If the 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.

    Usually, it works, but the above situation will fail in some apps, for example, some Activity will add launching parameters to the registration list, so we need to use another solution.

    If the unregistered 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.

    You need to choose an unneeded Activity that may not be used by the current Host App as a "puppet" to proxy it, which usually works.

    For example, we have found a suitable Activity that can be proxied.

    The following example

    <activity
    +    android:name="com.demo.test.activity.TestActivity"
    +    ...>
    +

    According to the name, we only need to add this parameter to the method for registration.

    The following example

    registerModuleAppActivities(proxy = "com.demo.test.activity.TestActivity")
    +

    Alternatively, if you write a stub for the Host App's class, you can register it directly through the Class object.

    The following example

    registerModuleAppActivities(TestActivity::class.java)
    +

    After the registration is complete, extends the Activity in the Module App you need to use the Host App to start by ModuleAppActivity or ModuleAppCompatActivity.

    These Activity now live seamlessly in the Host App without registration.

    The following example

    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)
    +    }
    +}
    +

    If you need to extends ModuleAppCompatActivity, you need to set the AppCompat theme manually.

    The following example

    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)
    +    }
    +}
    +

    After all the above steps are completed, you can happily call startActivity anywhere in the (Xposed) Host environment where a Context exists.

    The following example

    val context: Context = ... // Assume this is your Context
    +context.startActivity(context, HostTestActivity::class.java)
    +

    Tips

    For more functions, please refer to the Context.registerModuleAppActivities method.

    Create ContextThemeWrapper Proxy

    Sometimes, we need to use MaterialAlertDialogBuilder to beautify our own dialogs in the Host App, but we can't create them without the AppCompat theme.

    • Will got the following exception
    The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
    +

    At this time, we want to use MaterialAlertDialogBuilder to create a dialog in the current Activity of the Host App being hooked, you can have the following methods.

    The following example

    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()
    +    }
    +}
    +

    You can also set the system (native) night mode and day mode on the current Context through uiMode.

    Which requires at least Android 10 and above system version support and the current theme contains night mode related elements.

    The following example

    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()
    +    }
    +}
    +

    This way, we can create dialogs in the Host App very simply using MaterialAlertDialogBuilder.

    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 codeopen in new window 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.

    + + + diff --git a/docs/en/api/special-features/host-lifecycle.html b/docs/en/api/special-features/host-lifecycle.html new file mode 100644 index 00000000..a01ce24c --- /dev/null +++ b/docs/en/api/special-features/host-lifecycle.html @@ -0,0 +1,79 @@ + + + + + + + + + Host Lifecycle Extension | Yuki Hook API + + + + +

    Host Lifecycle Extension

    This is an extension of the lifecycle of an automatic hooking Host App.

    Monitor Lifecycle

    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 Application, just use the following methods.

    The following example

    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 ->
    +            // ...
    +        }
    +    }
    +}
    +

    Tips

    For more functions, please refer to AppLifecycle.

    Register System Broadcast

    Register system broadcast through the Application.onCreate method to monitor system broadcast.

    We can also register system broadcast in the Host App's Application.

    The following example

    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 ->
    +            // ...
    +        }
    +    }
    +}
    +

    Tips

    For more functions, please refer to AppLifecycle.

    + + + diff --git a/docs/en/api/special-features/logger.html b/docs/en/api/special-features/logger.html new file mode 100644 index 00000000..8f9d4a65 --- /dev/null +++ b/docs/en/api/special-features/logger.html @@ -0,0 +1,65 @@ + + + + + + + + + Debug Logs | Yuki Hook API + + + + +

    Debug Logs

    Log is the most important part of the debugging process, YukiHookAPI encapsulates a set of stable and efficient debugging log functions for developers.

    Normal Logs

    You can call loggerD, loggerI, loggerW to print normal logs to the console.

    The usage method is as follows.

    The following example

    loggerD(msg = "This is a log")
    +

    At this point, YukiHookAPI will call android.util.Log and XposedBridge.log to print this log at the same time.

    The default TAG of the log is the value you set in YukiHookLogger.Configs.tag.

    You can also customize this value dynamically, but it is not recommended to modify TAG easily to prevent logs from being filtered.

    The following example

    loggerD(tag = "YukiHookAPI", msg = "This is a log")
    +

    The printed result is as shown below.

    The following example

    [YukiHookAPI][D][host package name]--> This is a log
    +

    You can also use LoggerType to customize the type of log printing.

    You can choose to use android.util.Log or XposedBridge.log to print logs.

    The default type is LoggerType.BOTH, which means that both methods are used to print logs.

    For example we only use android.util.Log to print logs.

    The following example

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.LOGD)
    +

    Or just use XposedBridge.log to print the log, this method can only be used in the (Xposed) Host environment.

    The following example

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.XPOSEDBRIDGE)
    +

    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

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
    +

    In this way, the API will intelligently select the specified method type to print this log in different environments.

    Tips

    For more functions, please refer to loggerD, loggerI and loggerW methods.

    Error Logs

    You can call loggerE to print E level logs to the console.

    The usage method is as follows.

    The following example

    loggerE(msg = "This is an error")
    +

    The error log is the highest level, regardless of whether you have filtered only E level logs.

    For error-level logging, you can also append an exception stack.

    // Assume this is the exception that was thrown
    +val throwable = Throwable(...)
    +// Print log
    +loggerE(msg = "This is an error", e = throwable)
    +

    The printed result is as shown below.

    The following example

    [YukiHookAPI][E][host package name]--> This is an error
    +

    At the same time, the log will help you print the entire exception stack.

    The following example

    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
    +

    In the error log, you can also use LoggerType to specify the method type currently used to print the log.

    Tips

    For more functions, please refer to the loggerE method.

    Save Logs and Custom Elements

    You can save all currently printed logs directly to a file using the YukiHookLogger.saveToFile method.

    The following example

    // 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")
    +

    You can also use YukiHookLogger.contents to get all the log file contents that have been printed so far.

    The following example

    // Get the contents of all log files that have been printed so far
    +val fileContent = YukiHookLogger.contents
    +

    The above features require YukiHookLogger.Configs.isRecord to be enabled.

    You can also use YukiHookLogger.Configs.elements to customize the elements that debug logs display externally.

    This function requires YukiHookAPI.Configs to be configured in onInit of the Hook entry class.

    The following example

    override fun onInit() = configs {
    +    debugLog {
    +        // ...
    +        elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
    +    }
    +    // ...
    +}
    +

    Tips

    For more functions, please refer to YukiHookLogger.contents, YukiHookLogger.saveToFile methods and YukiHookLogger.Configs.

    + + + diff --git a/docs/en/api/special-features/reflection.html b/docs/en/api/special-features/reflection.html new file mode 100644 index 00000000..9dfb0ee3 --- /dev/null +++ b/docs/en/api/special-features/reflection.html @@ -0,0 +1,870 @@ + + + + + + + + + Reflection Extensions | 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

    Here are the extension functions related to the Class object itself.

    Object Conversion

    Suppose we want to get a Class that cannot be called directly.

    Normally, we can use the standard reflection API to find this Class.

    The following example

    // 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")
    +

    This is probably not very friendly, and YukiHookAPI provides you with a syntactic sugar that can be used anywhere.

    The above writing can be written as YukiHookAPI as follows.

    The following example

    // 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)
    +

    If the current Class does not exist, using the above method will throw an exception.

    If you are not sure whether the Class exists, you can refer to the following solutions.

    The following example

    // 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)
    +

    We can also get an existing Class object by mapping.

    The following example

    // 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

    Suppose we want to determine whether a Class exists.

    Usually, we can use the standard reflection API to find this Class to determine whether it exists by exception.

    The following example

    // 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
    +}
    +

    This is probably not very friendly, and YukiHookAPI provides you with a syntactic sugar that can be used anywhere.

    The above writing can be written as YukiHookAPI as follows.

    The following example

    // 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)
    +

    Tips

    For more functions, please refer to String.hasClass, PackageParam → String.hasClass methods.

    The Class name in the Host App's Dex after being obfuscated by tools such as R8 will be difficult to distinguish.

    Its correct position is uncertain, and cannot be obtained directly through Object Conversion.

    At this point, there is DexClassFinder, its role is to determine the instance of this Class by the bytecode features in the Class that need to be searched.

    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.

    Get Started

    Below is a simple usage example.

    Suppose the following Class is what we want, the names are obfuscated and may be different in each version.

    The following example

    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) {
    +        // ...
    +    }
    +}
    +

    At this point, we want to get this Class, you can use the ClassLoader.searchClass method directly.

    In PackageParam you can use the searchClass method directly and it will automatically specify the appClassLoader.

    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

    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
    +

    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, DexClassFinder will use synchronous mode to search Class, which will block the current thread until it finds or finds an exception.

    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 async = true, which will not require you to start a thread again, the API has already handled the related problems for you.

    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

    searchClass(async = true) {
    +    // ...
    +}.wait { class1 ->
    +    // Get asynchronous result
    +}
    +searchClass(async = true) {
    +    // ...
    +}.wait { class2 ->
    +    // Get asynchronous result
    +}
    +

    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.

    Local Cache

    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 name parameter.

    Next time, the found class name will be directly read from the local cache.

    The local cache uses 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.

    After enabling the local cache, async = true will be set at the same time, you don't need to set it manually.

    The following example

    searchClass(name = "com.demo.class1") {
    +    // ...
    +}.wait { class1 ->
    +    // Get asynchronous result
    +}
    +searchClass(name = "com.demo.class2") {
    +    // ...
    +}.wait { class2 ->
    +    // Get asynchronous result
    +}
    +

    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

    // 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)
    +    }
    +}
    +

    You can also clear the Host App's cache for a specific version.

    The following example

    // 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)
    +    }
    +}
    +

    If you need to search a set of 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
    +    }
    +}
    +

    Tips

    For more functions, please refer to ClassLoader.searchClass, PackageParam.searchClass methods.

    Member Extensions

    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 Class.

    The following example

    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

    Suppose we want to get the doTask method of Test and execute it.

    Normally, we can use the standard reflection API to find this method.

    The following example

    // 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")
    +

    This is probably not very friendly, and YukiHookAPI provides you with a syntactic sugar that can be used anywhere.

    The above writing can be written as YukiHookAPI as follows.

    The following example

    // 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")
    +

    Tips

    For more features, please refer to MethodFinder.

    Similarly, we need to get the isTaskRunning field can also be written as follows.

    The following example

    // 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
    +

    Tips

    For more features, please refer to FieldFinder.

    Maybe you also want to get the current Class constructor, the same can be achieved.

    The following example

    Test::class.java.constructor {
    +    param(BooleanType)
    +}.get().call(true) // Can create a new instance
    +

    If you want to get the no-argument constructor of Class, you can write it as follows.

    The following example

    Test::class.java.constructor().get().call() // Create a new instance
    +

    Tips

    For more features, please refer to ConstructorFinder.

    Optional Find Conditions

    Suppose we want to get the getName method in Class, which can be implemented as follows.

    The following example

    // 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
    +

    Through observation, it is found that there is only one method named getName in this Class, so can we make it simpler?

    The following example

    // 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
    +

    Yes, you can refine your find criteria for methods that do not change exactly.

    When using only get or wait methods to get results, YukiHookAPI will match the first found result in bytecode order by default.

    The problem comes again, this Class has a release method, but its method parameters are very long, and some types may not be directly available.

    Normally we would use param(...) to find this method, but is there an easier way.

    At this point, after determining the uniqueness of the method, you can use paramCount to find the method.

    The following example

    // 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
    +

    Although the above example can be successfully matched, it is not accurate.

    At this time, you can also use VagueType to fill in the method parameter type that you do not want to fill in.

    The following example

    // 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

    You will notice that 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?

    Referring to the above find conditions, we only need to add a superClass to the find conditions to achieve this function.

    The following example

    // 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")
    +

    At this time, we can get this method in the super class.

    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.

    Since we now know that the doBaseTask method only exists in the super class, this condition can be added to save finding time.

    The following example

    // 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")
    +

    At this time, we can also get this method in the super class.

    Once 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).

    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.

    Vague Find

    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 doTask method in Class, which can be implemented as follows.

    The following example

    // 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")
    +

    Knowing that there is currently only one doTask method in Class, we can also judge that the method name contains only the characters specified in it.

    The following example

    // 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")
    +

    We can also judge based on the first and last strings.

    The following example

    // 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")
    +

    By observing that this method name contains only letters, we can add a precise search condition.

    The following example

    // 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")
    +

    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.

    Multiple Find

    Sometimes, we may need to find a set of methods, constructors, and fields with the same characteristics in a Class.

    At this time, we can use relative condition matching to complete.

    Based on the result of the find condition, we only need to replace get with all to get all the bytecodes that match the condition.

    Suppose this time we want to get all methods in Class with the number of method parameters in the range 1..3, you can use the following implementation.

    The following example

    // 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(...)
    +}
    +

    The above example can be perfectly matched to the following 3 methods.

    private void doTask(String taskName)

    private void release(String taskName, Function<boolean, String> task, boolean isFinish)

    private void b(String a)

    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

    // 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(...)
    +}
    +

    The above example can be perfectly matched to the following 6 methods.

    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)

    By observing that there are two methods named b in Class, you can use the following implementation.

    The following example

    // 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(...)
    +}
    +

    The above example can be perfectly matched to the following 2 methods.

    private void b()

    private void b(String a)

    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.

    Static Bytecode

    Some methods and fields are statically implemented in Class, at this time, we can call them without passing in an instance.

    Suppose we want to get the contents of the static field TAG this time.

    The following example

    Test::class.java.field {
    +    name = "TAG"
    +    type = StringType
    +}.get().string() // The type of Field is string and can be cast directly
    +

    Assuming that there is a non-static TAG field with the same name in Class, what should I do at this time?

    Just add a filter.

    The following example

    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
    +

    We can also call a static method called init.

    The following example

    Test::class.java.method {
    +    name = "init"
    +    emptyParam()
    +}.get().call()
    +

    Likewise, you can identify it as a static.

    The following example

    Test::class.java.method {
    +    name = "init"
    +    emptyParam()
    +    // This method of identity find needs to be static
    +    modifiers { isStatic }
    +}.get().call()
    +

    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.

    Obfuscated Bytecode

    You may have noticed that the example Class given here has two obfuscated field names, both of which are a, how do we get them at this time?

    There are two options.

    The first option is to determine the name and type of the field.

    The following example

    // 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
    +

    The second option is to determine where the type of the field is located.

    The following example

    // 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
    +

    In the above two cases, the corresponding field private boolean a can be obtained.

    Likewise, there are two obfuscated method names in this Class, both of which are b.

    You can also have two options to get them.

    The first option is to determine the method name and method parameters.

    The following example

    // 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]
    +

    The second option is to determine where the parameters of the method are located.

    The following example

    // 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]
    +

    Since it is observed that this method is last in Class, then we have an alternative.

    The following example

    // 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
    +

    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.

    Directly Called

    The methods of calling bytecode described above all need to use get(instance) to call the corresponding method.

    Is there a simpler way?

    At this point, you can use the current method on any instance to create a call space.

    The following example

    // 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()
    +}
    +

    We can also use superClass to call methods of the current Class super class.

    The following example

    // 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")
    +}
    +

    If you don't like to use a lambda to create the namespace of the current instance, you can use the current() method directly.

    The following example

    // 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()
    +

    Likewise, consecutive calls can be made between them, but inline calls are not allowed.

    The following example

    // 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()
    +

    For Field instances, there is also a convenience method that can directly get the object of the instance where Field is located.

    The following example

    // 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")
    +}
    +

    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

    Test(true).doTask("task_name")
    +

    Usually, we can use the standard reflection API to call.

    The following example

    "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")
    +    }
    +

    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 buildOf method to create an instance.

    The following example

    "com.demo.Test".toClass().buildOf(true) { param(BooleanType) }?.current {
    +    method {
    +        name = "doTask"
    +        param(StringType)
    +    }.call("task_name")
    +}
    +

    If you want the 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.

    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

    // Assume this Class can be obtained directly
    +val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
    +test.doTask("task_name")
    +

    Tips

    For more functions, please refer to CurrentClass and Class.buildOf method.

    Original Called

    If you are using reflection to call a method that has been hooked, how do we call its original method?

    The native XposedBridge provides us with a XposedBridge.invokeOriginalMethod function.

    Now, in YukiHookAPI you can use the following method to implement this function conveniently.

    Suppose below is the Class we want to demonstrate.

    The following example

    public class Test {
    +
    +    public static String getString() {
    +        return "Original";
    +    }
    +}
    +

    Here's how the getString method in this Class Hooks.

    The following example

    Test::class.java.hook {
    +    injectMember {
    +        method {
    +            name = "getString"
    +            emptyParam()
    +            returnType = StringType
    +        }
    +        replaceTo("Hooked")
    +    }
    +}
    +

    At this point, we use reflection to call this method, and we will get the result of Hook "Hooked".

    The following example

    // Result will be "Hooked"
    +val result = Test::class.java.method {
    +    name = "getString"
    +    emptyParam()
    +    returnType = StringType
    +}.get().string()
    +

    If we want to get the original method and result of this method without hooking, we just need to add original to the result.

    The following example

    // Result will be "Original"
    +val result = Test::class.java.method {
    +    name = "getString"
    +    emptyParam()
    +    returnType = StringType
    +}.get().original().string()
    +

    Tips

    For more functions, please refer to the MethodFinder.Result.original method.

    Find Again

    Suppose there are three different versions of Class, all of which are the same Class for different versions of this Host App.

    There is also a method doTask in it, assuming they function the same.

    The following example of version A

    public class Test {
    +
    +    public void doTask() {
    +        // ...
    +    }
    +}
    +

    The following example of version B

    public class Test {
    +
    +    public void doTask(String taskName) {
    +        // ...
    +    }
    +}
    +

    The following example of version C

    public class Test {
    +
    +    public void doTask(String taskName, int type) {
    +        // ...
    +    }
    +}
    +

    We need to get this same functionality of the doTask method in a different version, how do we do it?

    At this point, you can use RemedyPlan to complete your needs.

    The following example

    // 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
    +}
    +

    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 RemedyPlan while using Multiple Find.

    The following example

    // 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
    +}
    +

    Take the current Class as an example, if Multiple Find is used in conjunction with RemedyPlan when creating a Hook, you need to change the usage slightly.

    The following example

    injectMember {
    +    method {
    +        name = "doTask"
    +        emptyParam()
    +    }.remedys {
    +        method {
    +            name = "doTask"
    +            paramCount(0..1)
    +        }
    +        method {
    +            name = "doTask"
    +            paramCount(1..2)
    +        }
    +    }.all()
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    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 .

    Relative Matching

    Suppose there is a Class with the same function in different versions of the Host App but only the name of the Class is different.

    The following example of version A

    public class ATest {
    +
    +    public static void doTask() {
    +        // ...
    +    }
    +}
    +

    The following example of version B

    public class BTest {
    +
    +    public static void doTask() {
    +        // ...
    +    }
    +}
    +

    At this time, what should we do if we want to call the doTask method in this Class in each version?

    The usual practice is to check if Class exists.

    The following example

    // 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()
    +

    I feel that this solution is very inelegant and cumbersome, then YukiHookAPI provides you with a very convenient VariousClass to solve this problem.

    Now, you can get this Class directly using the following methods.

    The following example

    VariousClass("com.demo.ATest", "com.demo.BTest").get().method {
    +    name = "doTask"
    +    emptyParam()
    +}.get().call()
    +

    If the current Class exists in the specified ClassLoader, you can fill in your ClassLoader in get.

    The following example

    val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
    +VariousClass("com.demo.ATest", "com.demo.BTest").get(customClassLoader).method {
    +    name = "doTask"
    +    emptyParam()
    +}.get().call()
    +

    If you are not sure that all Class will be matched, you can use the getOrNull method.

    The following example

    val customClassLoader: ClassLoader? = ... // Assume this is your ClassLoader
    +VariousClass("com.demo.ATest", "com.demo.BTest").getOrNull(customClassLoader)?.method {
    +     name = "doTask"
    +     emptyParam()
    +}?.get()?.call()
    +

    If you are using the Class of the (Xposed) Host environment in PackageParam, you can use toClass() to set it directly.

    The following example

    VariousClass("com.demo.ATest", "com.demo.BTest").toClass().method {
    +    name = "doTask"
    +    emptyParam()
    +}.get().call()
    +

    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 Class cannot be found.

    The following example

    findClass("com.demo.ATest", "com.demo.BTest").hook {
    +    // Your code here.
    +}
    +

    You can also define this Class as a constant type to use.

    The following example

    // Define constant type
    +val ABTestClass = VariousClass("com.demo.ATest", "com.demo.BTest")
    +// Use directly
    +ABTestClass.hook {
    +    // Your code here.
    +}
    +

    Tips

    For more functions, please refer to the PackageParam.findClass method.

    Calling Generics

    In the process of reflection, we may encounter generic problems.

    In the reflection processing of generics, YukiHookAPI also provides a syntactic sugar that can be used anywhere.

    For example we have the following generic class.

    The following example

    class TestGeneric<T, R> (t: T, r: R) {
    +
    +    fun foo() {
    +        // ...
    +    }
    +}
    +

    When we want to get a Class instance of the generic T or R in the current Class, only the following implementation is required.

    The following example

    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)
    +        }
    +    }
    +}
    +

    When we want to call this Class externally, it can be implemented as follows.

    The following example

    // 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>()
    +

    Tips

    For more functions, please refer to CurrentClass.generic, Class.generic methods and GenericClass.

    Pay Attention of Trap

    Here are some misunderstandings that may be encountered during use for reference.

    Restrictive Find Conditions

    Pay Attention

    In find conditions you can only use index function once except order.

    The following example

    method {
    +    name = "test"
    +    param(BooleanType).index(num = 2)
    +    // ❗ Wrong usage, please keep only one index method
    +    returnType(StringType).index(num = 1)
    +}
    +

    The following find conditions can be used without any problems.

    The following example

    method {
    +    name = "test"
    +    param(BooleanType).index(num = 2)
    +    order().index(num = 1)
    +}
    +

    Necessary Find Conditions

    Pay Attention

    In common method find conditions, even methods without parameters need to set find conditions.

    Suppose we have the following Class.

    The following example

    public class TestFoo {
    +
    +    public void foo(String string) {
    +        // ...
    +    }
    +
    +    public void foo() {
    +        // ...
    +    }
    +}
    +

    We want to get the public void foo() method, which can be written as follows.

    The following example

    TestFoo::class.java.method {
    +    name = "foo"
    +}
    +

    However, the above example is wrong.

    You will find two foo methods in this Class, one of which takes a method parameter.

    Since the above example does not set the find conditions for 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.

    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

    TestFoo::class.java.method {
    +    name = "foo"
    +    // ✅ Correct usage, add detailed filter conditions
    +    emptyParam()
    +}
    +

    At this point, the above example will perfectly match the public void foo() method.

    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.

    Abbreviated Find Conditions

    In the construction method find conditions, constructors without parameters do not need to fill in the find conditions.

    Suppose we have the following Class.

    The following example

    public class TestFoo {
    +
    +    public TestFoo() {
    +        // ...
    +    }
    +}
    +

    We want to get the public TestFoo() constructor, which can be written as follows.

    The following example

    TestFoo::class.java.constructor { emptyParam() }
    +

    The above example can successfully obtain the public TestFoo() constructor, but it feels a bit cumbersome.

    Unlike normal methods, since the constructor does not need to consider the name, when the constructor has no parameters, we can omit the emptyParam parameter.

    The following example

    TestFoo::class.java.constructor()
    +

    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.

    Bytecode Type

    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 Boolean and cast it to String.

    The following is the wrong way to use it.

    The following example

    field {
    +    name = "test"
    +    type = BooleanType
    +}.get().string() // ❗ Wrong usage, must be cast to the bytecode target type
    +

    The following is the correct way to use it.

    The following example

    field {
    +    name = "test"
    +    type = BooleanType
    +}.get().boolean().toString() // ✅ The correct way to use, get the type and then convert
    +

    Common Type Extensions

    When find methods and fields, we usually need to specify the type in find conditions.

    The following example

    field {
    +    name = "test"
    +    type = Boolean::class.java
    +}
    +

    Expressing the type Boolean::class.java in Kotlin is very long and not convenient.

    Therefore, YukiHookAPI encapsulates common type calls for developers, including Android's basic types and Java's basic types.

    At this time, the above type can be written in the following form.

    The following example

    field {
    +    name = "test"
    +    type = BooleanType
    +}
    +

    Common basic types in Java have been encapsulated as Name + Type, such as IntType, FloatType.

    Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type String[].

    You need to write java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass to get this type.

    Does it feel very troublesome? At this time, we can use the extension method ArrayClass(StringType) to get this type.

    At the same time, since String is a common type, you can also directly use StringArrayClass to get this type.

    Some common methods found in Hook have their corresponding encapsulation types for use, in the format Name + Class.

    For example, the Hook onCreate method needs to find the Bundle::class.java type.

    The following example

    method {
    +    name = "onCreate"
    +    param(BundleClass)
    +}
    +

    At the same time, you are welcome to contribute more commonly used types.

    + + + diff --git a/docs/en/api/special-features/xposed-channel.html b/docs/en/api/special-features/xposed-channel.html new file mode 100644 index 00000000..a09dbde0 --- /dev/null +++ b/docs/en/api/special-features/xposed-channel.html @@ -0,0 +1,94 @@ + + + + + + + + + Xposed Module and Host Channel | Yuki Hook API + + + + +

    Xposed Module and Host Channel

    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.

    Basic Usage

    The basic usage of the wait and put methods is described here.

    By using 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.

    The Module App example is as follows

    // 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")
    +

    The Host App example is as follows

    // 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")
    +

    You can leave the value of dataChannel unset to only notify the Module App or Host App to call back the wait method.

    The Module App example is as follows

    // 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")
    +

    The Host App example is as follows

    // 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")
    +

    Pay Attention

    The receiver needs to stay alive to receive the communication data.

    Tips

    For more functions, please refer to YukiHookDataChannel.

    Determine Module App and Host App Version Match

    Through the communication bridge function, 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.

    We only need to call the checkingVersionEquals method to achieve this function.

    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

    // Get from the Host App of the specified package name
    +dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
    +    // Your code here.
    +}
    +

    You can also determine in the Host App whether it matches the current Module App version.

    The following example

    // Get from the Module App
    +dataChannel.checkingVersionEquals { isEquals ->
    +    // Your code here.
    +}
    +

    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.

    Rules for Callback Event Response

    Only examples used in Module App are listed here, the same key in the Host App is always not allowed to be created repeatedly.

    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

    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.
    +        }
    +    }
    +}
    +

    In the above example, the callback event A will be replaced by the callback event B, the 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.

    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(...).

    Security Instructions

    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.

    + + + diff --git a/docs/en/api/special-features/xposed-storage.html b/docs/en/api/special-features/xposed-storage.html new file mode 100644 index 00000000..0324c6dd --- /dev/null +++ b/docs/en/api/special-features/xposed-storage.html @@ -0,0 +1,44 @@ + + + + + + + + + Xposed Module Data Storage | Yuki Hook API + + + + +

    Xposed Module Data Storage

    This is an efficient Module App data storage solution that automatically connects SharedPreferences and XSharedPreferences.

    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 Sp storage.

    The native Xposed provides us with a XSharedPreferences for reading the Sp data of the Module App.

    Use in Activity

    Loading YukiHookModulePrefs in Activity is described here.

    Usually we can initialize it in Host App like this.

    The following example

    XSharedPreferences(BuildConfig.APPLICATION_ID)
    +

    Is there a convenient and quick solution?

    At this point, you can use the extension capability of YukiHookAPI to quickly implement this function.

    When you store data in a Module App, you can use the following methods if you are currently in an Activity.

    The following example

    modulePrefs.putString("test_name", "saved_value")
    +

    When you read data in a Host App, you can use the following methods.

    The following example

    val testName = prefs.getString("test_name", "default_value")
    +

    You don't need to consider the module package name and a series of complicated permission configurations, everything is handled by YukiHookModulePrefs.

    To achieve localization of storage, you can specify the name of each prefs file.

    This is used in the Activity of the Module App.

    The following example

    // 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")
    +

    Read like this in Host App.

    The following example

    // 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")
    +

    If your project has a lot of fixed data that needs to be stored and read, it is recommended to use PrefsData to create templates.

    Tips

    For more functions, please refer to YukiHookModulePrefs, PrefsData.

    Use in PreferenceFragment

    Loading YukiHookModulePrefs in PreferenceFragment is described here.

    If your Module App uses PreferenceFragmentCompat, you can now start migrating its extends ModulePreferenceFragment.

    Pay Attention

    You must extends ModulePreferenceFragment to implement the module storage function of YukiHookModulePrefs.

    Tips

    For more functions, please refer to ModulePreferenceFragment.

    + + + diff --git a/docs/en/config/api-example.html b/docs/en/config/api-example.html new file mode 100644 index 00000000..51f1d75e --- /dev/null +++ b/docs/en/config/api-example.html @@ -0,0 +1,214 @@ + + + + + + + + + API Basic Configs | Yuki Hook API + + + + +

    API Basic Configs

    The basic configuration method of YukiHookAPI is introduced here.

    Function Configs

    Either Use as Xposed Module Configs or Use as Hook API Configs, you can specify YukiHookAPI for configuration.

    configs Method

    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.

    Hooker Configs

    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.

    Created by lambda

    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.

    encase Method

    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.

    Created by Custom Hooker

    This scheme is more suitable for large-scale projects, such as the need to classify Hooker or classify the role of Hook.

    encase Method

    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 Usage

    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 ...)
    +}
    +

    Expansion Features

    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.
    +        }
    +    }
    +}
    +

    Precautions

    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 initZygoteencase

    • load handleLoadPackageencase

    • load handleInitPackageResourcesencase

    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 {
    +    // ❗ Wrong usage, can't start Hook directly
    +    findClass(name = "com.example.demo.DemoClass").hook {
    +        // ...
    +    }
    +    // ❗ 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() {
    +        // ❗ 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 {
    +    // ✅ 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 {
    +            // ...
    +        }
    +    }
    +}
    +

    Sample Code 2

    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

    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.

    + + + diff --git a/docs/en/config/api-exception.html b/docs/en/config/api-exception.html new file mode 100644 index 00000000..b026fc78 --- /dev/null +++ b/docs/en/config/api-exception.html @@ -0,0 +1,391 @@ + + + + + + + + + API Exception Handling | Yuki Hook API + + + + +

    API Exception Handling

    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.

    Non-Blocking Exceptions

    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.

    exception

    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.

    exception

    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() {
    +        // ❗ Wrong usage
    +        YukiHookAPI.encase {
    +            // Your code here.
    +        }
    +    }
    +
    +    override fun onXposedEvent() {
    +        // ❗ 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() {
    +        // ✅ Correct usage
    +        YukiHookAPI.encase {
    +            // Your code here.
    +        }
    +    }
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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 {
    +    // ✅ Examples of correct usage
    +    method {
    +        // Your code here.
    +    }
    +    afterHook {
    +        // ...
    +    }
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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 {
    +    // ❗ Invalid type example is set
    +    param(false, 1, 0)
    +    // ❗ Invalid type example is set
    +    returnType = false
    +}
    +
    +// Find a variable
    +field {
    +    // ❗ 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 {
    +    // ✅ Examples of correct usage
    +    param(BooleanType, IntType, IntType)
    +    // ✅ Examples of correct usage
    +    returnType = BooleanType
    +    // ✅ The following scheme is also correct
    +    returnType = "java.lang.Boolean"
    +}
    +
    +// Find a variable
    +field {
    +    // ✅ Examples of correct usage
    +    type = BooleanType
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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

    // ❗ 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.

    exception

    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.

    exception

    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.

    Blocking Exceptions

    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".

    exception

    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 {
    +    // ...
    +    // ❗ The method execution is not called
    +    // The actual method is called here is the MethodFinder.Result object
    +}.get(instance).current()
    +YourClass.method {
    +    // ...
    +    // ✅ 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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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) {
    +            // ❗ 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.

    exception

    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.

    exception

    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) {
    +            // ❗ 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.

    exception

    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.

    exception

    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.

    exception

    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)
    +        // ❗ 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)
    +        // ✅ Correct usage
    +        modulePrefs.getBoolean("test_data")
    +    }
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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.

    exception

    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
    +}
    +
    exception

    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.

    exception

    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.

    exception

    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.

    + + + diff --git a/docs/en/config/api-using.html b/docs/en/config/api-using.html new file mode 100644 index 00000000..edd48dc1 --- /dev/null +++ b/docs/en/config/api-using.html @@ -0,0 +1,82 @@ + + + + + + + + + Use as Hook API Configs | Yuki Hook API + + + + +

    Use as Hook API Configs

    As a Hook API, it is usually used for Hook operations for hot updates or functional needs of its own app and product testing.

    Dependency Configs

    You just need to integrate the com.highcapable.yukihookapi:api dependency.

    Then please integrate the Hook Framework dependencies used by your target.

    Entry Configs

    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.

    Hook Framework

    Here are some related ways of how to connect the Hook Framework with the YukiHookAPI, which is widely used.

    Pineopen in new window

    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)
    +}
    +

    SandHookopen in new window

    Required Xposed API dependencies com.swift.sandhook:xposedcompat or com.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)
    +}
    +

    Whaleopen in new window

    Required Xposed API dependencies com.wind.xposed:xposed-on-whale

    Please refer to xposed-hook-based-on-whaleopen in new window.

    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)
    +}
    +
    + + + diff --git a/docs/en/config/r8-proguard.html b/docs/en/config/r8-proguard.html new file mode 100644 index 00000000..2b714b06 --- /dev/null +++ b/docs/en/config/r8-proguard.html @@ -0,0 +1,34 @@ + + + + + + + + + R8 & Proguard Obfuscate | Yuki Hook API + + + + +

    R8 & Proguard Obfuscate

    In most scenarios, the Xposed Module can be compressed by native obfuscation.

    Here is the configuration method of obfuscation.

    R8

    If you are using 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.

    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 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
    +
    + + + diff --git a/docs/en/config/xposed-using.html b/docs/en/config/xposed-using.html new file mode 100644 index 00000000..fe6ed432 --- /dev/null +++ b/docs/en/config/xposed-using.html @@ -0,0 +1,109 @@ + + + + + + + + + Use as Xposed Module Configs | Yuki Hook API + + + + +

    Use as Xposed Module Configs

    Here are the related configuration methods used by YukiHookAPI as an Xposed Module.

    Dependency Configs

    As an Xposed Module, YukiHookAPI provides an automatic builder.

    You need to integrate the latest version of the com.highcapable.yukihookapi:ksp-xposed dependency in your build.gradle.

    Custom Automatic Builder

    You can configure how 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
    +)
    +

    The @InjectYukiHookWithXposed annotation is an important annotation to mark the entry point of a Module App's Hook.

    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.

    sourcePath Parameter

    The sourcePath parameter determines the important identifier for the automatic builder to automatically find and match your current project path.

    The content of this parameter is a relative path match, and the default parameter is src/main.

    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

    @InjectYukiHookWithXposed(sourcePath = "src/custom")
    +

    The file path separator used by 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).

    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 com.example.demo, any one of the following definitions.

    The following definitions are for reference only, usually as long as your project can generate the 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 example

    android {
    +    namespace 'com.example.demo'
    +}
    +

    build.gradle.kts example

    android {
    +    namespace = "com.example.demo"
    +}
    +

    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 modulePackageName parameter.

    The following example

    @InjectYukiHookWithXposed(modulePackageName = "com.example.demo")
    +

    As long as you customize the modulePackageName parameter, you will get a warning at compile time.

    The following example

    You set the customize module package name to "com.example.demo", please check for yourself if it is correct
    +

    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.

    entryClassName Parameter

    entryClassName determines how the automatic builder generates the entry class name in xposed_init.

    By default, it will use your entry class package name to insert the _YukiHookXposedInit suffix for generation.

    Suppose this is your entry class.

    The following example

    @InjectYukiHookWithXposed
    +class HookEntry: IYukiHookXposedInit
    +

    The Xposed entry class is handled as follows.

    The following example

    class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
    +

    The compiled class name structure is as follows.

    The following example

    ...hook.HookEntry ← Your entry class
    +...hook.HookEntry_Impl ← Auto-generated Impl class
    +...hook.HookEntry_YukiHookXposedInit ← Automatically generated Xposed entry class
    +

    We now define the entry class name as HookXposedEntry.

    The following example

    @InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
    +class HookEntry: IYukiHookXposedInit
    +

    The Xposed entry class is handled as follows.

    The following example

    class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
    +

    The compiled class name structure is as follows.

    The following example

    ...hook.HookEntry ← Your entry class
    +...hook.HookEntry_Impl ← Auto-generated Impl class
    +...hook.HookXposedEntry ← Automatically generated Xposed entry class
    +

    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.

    isUsingResourcesHook Parameter

    isUsingResourcesHook determines whether the automatic builder generates relevant code for the Resources Hook, this feature is enabled by default.

    The generated entry class after enabling it will look like the following.

    The following example

    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?) {
    +        // ...
    +    }
    +}
    +

    If your current project does not need to use Reources Hook, you can set isUsingResourcesHook = false to disable automatic generation.

    The following example

    @InjectYukiHookWithXposed(isUsingResourcesHook = false)
    +

    The resulting entry class after closing will look like the following.

    The following example

    class _YukiHookXposedInit : IXposedHookZygoteInit, IXposedHookLoadPackage {
    +
    +    override fun initZygote(sparam: IXposedHookZygoteInit.StartupParam?) {
    +        // ...
    +    }
    +
    +    override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
    +        // ...
    +    }
    +}
    +

    IYukiHookXposedInit Interface

    The IYukiHookXposedInit interface that your HookEntryClass must implements it, which is the entry point for your Module App to start hooking.

    Tips

    For more functions, please refer to IYukiHookXposedInit.

    When your Module App is loaded by Xposed, the onHook method will be called back, you need to start using YukiHookAPI in this method.

    The basic calling process is _YukiHookXposedInitIYukiHookXposedInit.onXposedEventIYukiHookXposedInit.onInitIYukiHookXposedInit.onHook

    For details, please refer to API Basic Configs.

    Native Xposed API Events

    If your current Xposed Module uses third-party resources, but may not be able to transfer them in a short time, you can use onXposedEvent to monitor all loading events of the native Xposed API.

    The following example

    @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.

    Tips

    For more functions, please refer to the IYukiHookXposedInit.onXposedEvent method.

    + + + diff --git a/docs/en/guide/example.html b/docs/en/guide/example.html new file mode 100644 index 00000000..9273f75b --- /dev/null +++ b/docs/en/guide/example.html @@ -0,0 +1,318 @@ + + + + + + + + + Usage Example | Yuki Hook API + + + + +

    Usage Example

    Here is an introduction to the basic working method of YukiHookAPI and a list of simple Hook examples and common functions.

    Structure Diagram

    The structure below describes the basic working and principle of YukiHookAPI.

    Host Environment
    +└── YukiMemberHookCreator
    +    └── Class
    +        └── MemberHookCreator
    +            └── Member
    +                ├── Before
    +                └── After
    +            MemberHookCreator
    +            └── Member
    +                ├── Before
    +                └── After
    +            ...
    +    YukiResourcesHookCreator
    +    └── Resources
    +        └── ResourcesHookCreator
    +            └── Drawable
    +                └── Replace
    +            ResourcesHookCreator
    +            └── Layout
    +                └── Inject
    +            ...
    +

    The above structure can be written in the following form in code.

    TargetClass.hook {
    +    injectMember {
    +        method {
    +            // Your code here.
    +        }
    +        beforeHook {
    +            // Your code here.
    +        }
    +        afterHook {
    +            // Your code here.
    +        }
    +    }
    +}
    +resources().hook {
    +    injectResource {
    +        conditions {
    +            // Your code here.
    +        }
    +        replaceTo(...)
    +    }
    +}
    +

    Demo

    You can find the demo provided by the API below to learn how to use YukiHookAPI.

    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.

    A Simple Hook Example

    Here are examples of Hook App, Hook System Framework and Hook Resources for reference.

    Hook App

    Suppose, we want to hook the onCreate method in com.android.browser and show a dialog.

    Add code in the body of the encase method.

    The following example

    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()
    +            }
    +        }
    +    }
    +}
    +

    At this point, the onCreate method will be successfully hooked and this dialog will show when every Activity in com.android.browser starts.

    So, what should I do if I want to continue the Hook onStart method?

    In the code just now, continue to insert an injectMember method body.

    The following example

    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.
    +            }
    +        }
    +    }
    +}
    +

    For the 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.

    For example, I want to get com.example.demo.TestClass.

    The following example

    findClass(name = "com.example.demo.TestClass").hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    If com.example.demo is the app you want to hook, then the writing method can be simpler.

    The following example

    findClass(name = "$packageName.TestClass").hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    Some people may have started to say that findClass is a bit cumbersome in some scenarios.

    Because some people may have the following needs.

    The following example

    const val TestClass = "com.example.demo.TestClass"
    +
    +TestClass.hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    That's okay, you can also create a Hook directly using the string class name.

    The following example

    "$packageName.TestClass".hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    Tips

    For more functions, please refer to MemberHookCreator.

    Hook Zygote

    The first event initZygote after the new process is forked when the app starts.

    Suppose we want to globally Hook the onCreate event of an app Activity

    Add code in the body of the encase method.

    The following example

    loadZygote {
    +    ActivityClass.hook {
    +        injectMember {
    +            method {
    +                name = "onCreate"
    +                param(BundleClass)
    +                returnType = UnitType
    +            }
    +            afterHook {
    +                // Your code here.
    +            }
    +        }
    +    }
    +}
    +

    Notice

    The functionality performed in loadZygote is very limited, and the loadZygote method is rarely needed.

    Hook System Framework

    In YukiHookAPI, the implementation of the Hook System Framework is very simple.

    Suppose, you want to get ApplicationInfo and PackageInfo and do something with them.

    Add code in the body of the encase method.

    The following example

    loadSystem {
    +    ApplicationInfoClass.hook {
    +        // Your code here.
    +    }
    +    PackageInfoClass.hook {
    +        // Your code here.
    +    }
    +}
    +

    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.

    Hook Resources

    Suppose, we want to replace the content of app_name of type string in Hook com.android.browser with 123.

    Add code in the body of the encase method.

    The following example

    loadApp(name = "com.android.browser") {
    +    resources().hook {
    +        injectResource {
    +            conditions {
    +                name = "app_name"
    +                string()
    +            }
    +            replaceTo("123")
    +        }
    +    }
    +}
    +

    If the current app has a title bar text set with app_name, it will become our 123.

    You can also replace the Hook App's Resources with the current Xposed Module's Resources.

    Suppose, we want to continue to hook ic_launcher of type mipmap in com.android.browser.

    The following example

    loadApp(name = "com.android.browser") {
    +    resources().hook {
    +        injectResource {
    +            conditions {
    +                name = "ic_launcher"
    +                mipmap()
    +            }
    +            replaceToModuleResource(R.mipmap.ic_launcher)
    +        }
    +    }
    +}
    +

    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 loadApp with loadZygote.

    The following example

    loadZygote {
    +    resources().hook {
    +        // Your code here.
    +    }
    +}
    +

    Tips

    For more functions, please refer to ResourcesHookCreator.

    Remove Hook

    The native Xposed provides us with a XC_MethodHook.Unhook function, which can remove the current Hook from the Hook queue, and YukiHookAPI can also implement this function.

    The first way, save the Result instance of the current injected object, and call remove at the appropriate time and place to remove the injected object.

    The following example

    // 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()
    +

    The second method, call removeSelf in the Hook callback method to remove itself.

    The following example

    injectMember {
    +    method {
    +        name = "test"
    +        returnType = UnitType
    +    }
    +    afterHook {
    +        // Just call the following method directly
    +        removeSelf()
    +    }
    +}
    +

    Tips

    For more functions, please refer to MemberHookCreator.

    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

    You can handle exceptions that occur during the Hook method.

    The following example

    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 {}
    +    // ...
    +}
    +

    This method also works in the Resources Hook.

    The following example

    injectResource {
    +    // Your code here.
    +}.result {
    +    // Handle arbitrary exceptions when hooking
    +    onHookingFailure {}
    +    // ...
    +}
    +

    You can also handle exceptions that occur when the Hook's Class does not exist.

    The following example

    TargetClass.hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}.onHookClassNotFoundFailure {
    +    // Your code here.
    +}
    +

    You can also handle exceptions when looking up methods.

    The following example

    method {
    +    // Your code here.
    +}.onNoSuchMethod {
    +    // Your code here.
    +}
    +

    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.

    Throw an Exception

    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 hook method body will be taken over by the YukiHookAPI to avoid interrupting the next Hook process and causing the Hook process to "die".

    Here's how these exceptions work when YukiHookAPI takes over.

    The following example

    // <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 -> }
    +}
    +

    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 param.throwable method, and YukiHookAPI can also implement this function.

    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

    injectMember {
    +    method {
    +        // ...
    +    }
    +    afterHook {
    +        RuntimeException("Exception Test").throwToApp()
    +    }
    +}
    +

    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

    injectMember {
    +    method {
    +        // ...
    +    }
    +    afterHook {
    +        throw RuntimeException("Exception Test")
    +    }.onFailureThrowToApp()
    +}
    +

    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.

    Status Monitor

    People who use XposedHelpers often print Unhook after the Hook to determine whether the Hook is successful.

    In YukiHookAPI, you can easily reimplement this functionality with the following methods.

    First we can monitor that the Hook is ready to start.

    The following example

    YourClass.hook {
    +    // Your code here.
    +}.onPrepareHook {
    +    loggerD(msg = "$instanceClass hook start")
    +}
    +

    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

    injectMember {
    +    // Your code here.
    +}.onHooked { member ->
    +    loggerD(msg = "$member has hooked")
    +}
    +

    Expansion Usage

    You can use the following methods to easily implement various judgments and functions in the Hook process.

    Multiple Hosts

    If your Module App needs to handle Hook events of multiple apps at the same time, you can use the loadApp method body to distinguish the app you want to hook.

    The following example

    loadApp(name = "com.android.browser") {
    +    // Your code here.
    +}
    +loadApp(name = "com.android.phone") {
    +    // Your code here.
    +}
    +

    Tips

    For more functions, please refer to PackageParam.loadApp.

    Multiple Processes

    If your Hook's Host App has multiple processes, you can use the withProcess method body to hook them separately.

    The following example

    withProcess(mainProcessName) {
    +    // Your code here.
    +}
    +withProcess(name = "$packageName:tool") {
    +    // Your code here.
    +}
    +

    Tips

    For more functions, please refer to PackageParam.withProcess.

    Writing Optimization

    To make the code more concise, you can omit the name of YukiHookAPI and write your onHook entry as lambda.

    The following example

    override fun onHook() = encase {
    +    // Your code here.
    +}
    +

    Xposed Module own Active State

    Usually, we choose to write a method that return false, and then Hook this method to return true to prove that the Hook has taken effect.

    In YukiHookAPI, you don't need to do this at all. YukiHookAPI has already encapsulated this operation for you, and you can use it directly.

    Now, you can use YukiHookAPI.Status.isXposedModuleActive directly in the Module App to determine whether it is active.

    The following example

    if(YukiHookAPI.Status.isXposedModuleActive) {
    +    // Your code here.
    +}
    +

    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 YukiHookAPI.Status.isTaiChiModuleActive to determine whether it is activated.

    The following example

    if(YukiHookAPI.Status.isTaiChiModuleActive) {
    +    // Your code here.
    +}
    +

    If you want to use both judgment schemes, YukiHookAPI also encapsulates a convenient way for you.

    At this point, you can use YukiHookAPI.Status.isModuleActive to determine whether you are activated in Xposed or TaiChi and Promise.

    The following example

    if(YukiHookAPI.Status.isModuleActive) {
    +    // Your code here.
    +}
    +

    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.

    + + + diff --git a/docs/en/guide/home.html b/docs/en/guide/home.html new file mode 100644 index 00000000..5d947782 --- /dev/null +++ b/docs/en/guide/home.html @@ -0,0 +1,139 @@ + + + + + + + + + Introduce | Yuki Hook API + + + + +

    Introduce

    This is a Hook API Framework, it does not provide any Hook function itself, it needs the support of basic Xposed API.

    Background

    This is an efficient Xposed Hook API rebuilt in Kotlin.

    The name is taken from "ももくり" heroine Yuki Kuriharaopen in new window.

    Formerly the Innocent Xposed API used in Development Learning Projectopen in new window, now renamed and open sourced.

    Usage

    YukiHookAPI is built entirely with Kotlin lambda syntax.

    Abandoning the original less friendly XposedHelpers, you can use it to easily create Xposed Modules and easily implement custom Hook API.

    Language Requirement

    Please use 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.

    All demo code in this document will be described using Kotlin, if you don't know how to use Kotlin then you may not be able to use YukiHookAPI.

    Part of the Java Demo code can be found hereopen in new window, but not recommended.

    Source of Inspiration

    Previously, when we built an Xposed Module, we first needed to create an xposed_init file under assets.

    Then, manually fill in your own entry class name into the file and use XposedHelpers to implement our Hook logic.

    Since Kotlin is the main Android development language, this API is really not very elegant to use.

    Is there any easy to use, light, elegant solution?

    With this idea, YukiHookAPI was born.

    Now, we only need to write a small amount of code, and all the time and expense are handed over to automation.

    With Kotlin's elegant lambda writing and YukiHookAPI, you can make your Hook logic more beautiful and clear.

    The following example

    @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)
    +            )
    +    }
    +}
    +

    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 YukiHookAPI, you can implement a very simple Xposed Module.

    Suppored Hook Framework

    The following are the Hook Framework and Xposed framework supported by YukiHookAPI.

    Hook FrameworkSTDescription
    LSPosedopen in new windowStable use in multiple scenarios
    LSPatchopen in new windowWIP after this project is improved
    EdXposedopen in new windowMaintenance has stopped, no longer recommended
    Pineopen in new windowOnly available
    SandHookopen in new windowOnly available
    Whaleopen in new windowNeed xposed-hook-based-on-whaleopen in new window
    YAHFAopen in new windowNeed to implement the Xposed API yourself
    FastHookopen in new windowNeed to implement the Xposed API yourself
    Epicopen in new windowNeed Dexposedopen in new window by yourself
    TaiChiopen in new windowOnly available for Xposed Module
    Xposedopen in new windowNot test, no longer recommended
    + + + diff --git a/docs/en/guide/knowledge.html b/docs/en/guide/knowledge.html new file mode 100644 index 00000000..49c3c038 --- /dev/null +++ b/docs/en/guide/knowledge.html @@ -0,0 +1,45 @@ + + + + + + + + + Basic Knowledge | Yuki Hook API + + + + +

    Basic Knowledge

    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.

    What is Xposed

    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.

    What can Xposed do

    The structure below describes the basic workings and principles of Xposed.

    Xposed Framework
    +└── App's Environment
    +    └── Hooker (Hooked)
    +        ...
    +    App's Environment
    +    └── Hooker (Hooked)
    +        ...
    +    ...
    +

    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 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

    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)

    Derivatives

    The structure below describes how and how the Xposed-like Hook Framework works.

    App's Environment
    +└── Hook Framework
    +    └── Hooker (Hooked)
    +        ...
    +

    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.

    What YukiHookAPI does

    Since Xposed appeared until now, apart from XposedHelpers, which is well known to developers, there is still no set of syntactic sugar for Kotlin and API with complete usage encapsulation.

    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, 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

    Before starting, you need to have the following basics to better use YukiHookAPI.

    • 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 Jadxopen in new window and ApkToolopen in new window

    • 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 APIopen in new window 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

    + + + diff --git a/docs/en/guide/move-to-new-api.html b/docs/en/guide/move-to-new-api.html new file mode 100644 index 00000000..5c824cf5 --- /dev/null +++ b/docs/en/guide/move-to-new-api.html @@ -0,0 +1,216 @@ + + + + + + + + + Migrate from Xposed API | Yuki Hook API + + + + +

    Migrate from Xposed API

    If you are familiar with Xposed API, you can refer to the same point below to quickly migrate your API to YukiHookAPI.

    Migrate Hook Entry Point

    Migrated from 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.

    The API function differences are compared as follows

    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

    Migrated from 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.

    The API function differences are compared as follows

    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

    The replaceHook method is special, and the YukiHookAPI makes a variety of forms for it to choose from.

    The API function differences are compared as follows

    /// 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.

    + + + diff --git a/docs/en/guide/quick-start.html b/docs/en/guide/quick-start.html new file mode 100644 index 00000000..1aaf9e4d --- /dev/null +++ b/docs/en/guide/quick-start.html @@ -0,0 +1,102 @@ + + + + + + + + + Quick Start | Yuki Hook API + + + + +

    Quick Start

    Integrate YukiHookAPI into your project.

    Environment Requirements

    • 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 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.

    You can click here to check it out.

    Manually Configure Project

    If you don't want to use automated build tools, you can still manually configure project dependencies as follows.

    Create Project

    Use 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

    Add dependencies to your project build.gradle.

    The following example

    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" }
    +}
    +

    Add plugin to your app build.gradle.

    The following example

    plugins {
    +    // ❗Be sure to add it as an Xposed Module, optional in other cases
    +    id 'com.google.devtools.ksp' version '<ksp-version>'
    +}
    +

    Add dependencies to your app build.gradle.

    The following example

    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>'
    +}
    +

    Please modify <ksp-version> to the latest version from hereopen in new window (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 Kotlin to 11 and above in your app build.gradle.

    The following example

    android {
    +    compileOptions {
    +        sourceCompatibility JavaVersion.VERSION_11
    +        targetCompatibility JavaVersion.VERSION_11
    +    }
    +    kotlinOptions {
    +        jvmTarget = '11'
    +    }
    +}
    +

    Notice

    Since API 1.0.80 version, the default JVM version is 11, and 1.8 and below are no longer supported.

    Use as Xposed Module

    Add the base code to your AndroidManifest.xml.

    The following example

    <!-- 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"/>
    +

    Create a Hook entry class in your project, implements IYukiHookXposedInit and add the annotation @InjectYukiHookWithXposed.

    The following example

    @InjectYukiHookWithXposed
    +class HookEntry : IYukiHookXposedInit {
    +
    +    override fun onHook() = YukiHookAPI.encase {
    +        // Your code here.
    +    }
    +}
    +

    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.

    Use as Hook API

    Integration

    Create your custom Application.

    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 YukiHookAPI.encase method to attachBaseContext.

    The following example

    override fun attachBaseContext(base: Context?) {
    +    // Load Hook Framework
    +    //
    +    // Your code here.
    +    //
    +    // Load YukiHookAPI
    +    YukiHookAPI.encase(base) {
    +        // Your code here.
    +    }
    +    super.attachBaseContext(base)
    +}
    +

    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.

    + + + diff --git a/docs/en/index.html b/docs/en/index.html new file mode 100644 index 00000000..6746fdd7 --- /dev/null +++ b/docs/en/index.html @@ -0,0 +1,58 @@ + + + + + + + + + Home | Yuki Hook API + + + + +
    Yuki Hook API

    Yuki Hook API

    An efficient Kotlin version of the Xposed Hook API

    Get Started Changelog

    Xposed Module Develop

    The automatic builder can help you quickly create an Xposed Module, automatic configure the entry class and xposed_init file.

    Light and Elegant

    A powerful, elegant, beautiful API built with Kotlin lambda can help you quickly implement members search and methods hooks.

    Debugging Efficient

    A rich debug log function, detailing the name of each hooked method, time-consuming to find the class can quickly debug and find errors.

    Easy to transplant

    Native support for Xposed API usage, in any case, the supported Hook Framework with Xposed API can be quickly spliced with it.

    Obfuscate Support

    The built Xposed Module simply supports R8, obfuscate will not destroy the hook entry point, and no other configuration is required under R8.

    Quickly Started

    Simple and easy to use it now! Do not need complex configuration and full development experience, Integrate dependencies and enjoy yourself.

    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)
    +        }
    +    }
    +}
    +
    + + + diff --git a/docs/en/tools/yukihookapi-projectbuilder.html b/docs/en/tools/yukihookapi-projectbuilder.html new file mode 100644 index 00000000..f1c9a2a3 --- /dev/null +++ b/docs/en/tools/yukihookapi-projectbuilder.html @@ -0,0 +1,33 @@ + + + + + + + + + YukiHookAPI Project Builder | Yuki Hook API + + + + +

    YukiHookAPI Project Builder

    This is an automatic building tool for Xposed Modules using YukiHookAPI as the core.

    Implementing automated search relies on quickly building an Android project template that includes a Xposed Module environment.

    Get Project

    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-ProjectBuilderopen in new window

    If you want to download directly, you can click hereopen in new window to go to the Release address.

    Usage

    Here contains the basic usage and function explanation.

    Basic Usage

    • 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

    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.

    Multilingual Support

    The software language follows the current system, and you can manually select the software interface language in the Language column of the menu bar.

    + + + diff --git a/docs/images/logo.png b/docs/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7576340dc8d4839aefac808e9e68a48598e08414 GIT binary patch literal 24264 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�b4p_-MUjvfC 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 z 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%0DA> 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­Wx(fh_K$o)0UplHYafPj9iR0Iq8YXpk}hPpzy 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 z z$*Wh-gfu4jEjdqNd)|VY^y=1cTiUfrj0eR-!{ai-X0Uk<@7?#+^D-xFDG>fYCVyKZ zhfv7evNh6qO@Of{77Ky&fX-5OV z?$FBswj3%v0IJo4l9lNWS~TuVM1|eNfU)nxl?;5n@55&c)0v|J>Dnn9?1BXx}#O!S;kp02BP_`_`<9)cF3&gR%xc`t2pS8l>+(Y z69ATMf0vY(`_XKg>BO#7W3+Fv{eVN(2u$9w`2Gjyi&wQW!WE~Q!~FNql*NDsZM#O< ziWaA)uAuSVZPM2LZ_*gNE5fjXTfOH-vGz?ZFGNr9Ec8 zUdJ(dDW}|2^`;cVx0QqAza2?>7V{@Z=dr=O`z3GSL>>$nv7MhkNBUvlnA-ihSjif% zQ%ZV!(94&cKbD4q&BIh)%GwWmXXB}vTdNw$odyxudZ#3B{C-HDk{|ozCer$W(0E(3 zcZjmmIG-rpA3w%(19iWCzNeCn##23k8txTtPm-xLLa7nL>--eQJ}qAd7lPiW$NOm( z0ch;shtn1RS7I_)*D;Xx{w{p^HI zp5WE{ZDsE549SDzpxZDX^lgwGqUbx!5Hn<;CUMUok5=Pq@sw59FY&ZUtkJ)8g#d1{ zh%Tkb%}@*T6JF%Dxau$haG#k?=Ts_tZBRkYk9jvh3RF>}A1YZodCl$CJs-t#Mv8}X@l=T&7~l#Xd}nve&@Y;OyfA28`5EwO zTbqvu6Eo> zD2sbCB50{@NNi7Z^8@C3TZaZ^m0zT86p{ZpZ~%8q_pZ((f|%T`3bT_M*YE{K@V@7;fOi6F4jq@2d`Y#CgxXa_#14hmF9RnB6+CD>gh4@kZrchn?vy` zipxAZ+@h<&^Sx6+0ma#Qpf)JCShOX9RfTC)TwlA5U-q%F=lV*~U1CtUm~6N7NnuV} znM{e;$N^;|D3DMc+Y2yXvh@k-We6v7WO&6q>UT2lmIMhM#rB?xYEIVGEpi>(&I~}G z-VVehTM>g?&k3zAeqpAaDF`1r*0(s&D{nh+cbAqZ=flxV97>rokeg#h#9L(FuXt&x z9^YN{?kT6(nR=mJWVSH$3yx+f`{7=1@{!pjJ}xS=a#WK)QMRCfhvC^ z8q$R)XJ{lgH}0R3U97AV$*Z}ShXrgZh8J~T4B?fZ^>FB^SwT!0wcDcYy5qfKyDKSL z?cr!p*az@AG0g@pC$A&Ez~wnwZM5s(Tpf*6@$u~QAg?cvB+rPPi3KFIWhYcJGXbbC z;Kefhj-r`mi>El;5v|urLcMu^eUndF?~~oHmYq^vN^QSf<5OLX68lVM;X_dn2#QXQ zF_Vmpe4zfNqV&)*cXFO#Wl~(+0-3D)wTc+Dv4yb43(j^V2JP}%Qt;EsaUEG8>*n5X zn!K{wQ{rqDCymr@W6ZEozw1tR&af_;1%pGLAv&!1e6fD&)hjPUU-EySLl9=$EtZ}Y zyyE6P?=qd=z)Jc;j*GMD&oK_l&`33VeKj=R&IxAm+|=_qA7+qSTO;qC%->vc3dY0C zt5;UTeO>qv6HOedlwtx>MK;SC#b6L4Ni8&e4dIeh>MclArbfbOJsol3mvHBWiK9Fk zPtyu^6Sm$9qgtQb_T0^vBym#marmO2G(+^kn^woxig0bQG*iW4{y~07dhZ$r$}B{iq^y5!i|(wTbWZ~#Q8CjW1P^~T6vaf z7yev44)p!J?|)DL{3kj(ra7ZfSaU?O|h;_D+YRqnr7lP{0gH!-OykF{tPdKRkQljBLfLYM`wic@eiwo=N9 zuppAx8;cgIY1%=Pk}3=4_~=2hf`2dPG1VbQ2TLtlXz-(l)EpjKvZVPEgztb-w_hhG zM+ORwUhDI9NnWhKUuk&Lzh!*wBhQKpvSATJ>PTcL)^{rm$1|U**=u8u}(l zY{#y`!5D$e??t{9C1%+9gpucZmTV4zoa~9W<`g$N)H=Mp`e9Dx0@b(joZAM7()Alf z@~UoTbS7FucY-h*c5}4PW*VprLU;+>E6u$hZr7T&e5;G+rCQ6T^S&{YF$I}7 z#u6wMm?OP?+Y>xL!+|Yn`Vcm{DM7 zt0K+{I%ZfCPJvTU)x;nQl3UTWlbc8E@#MJ|J=v;K!^QTOGr|(*K{wT8R?tbt#{6K2 z5ULI^e{6?MYG6bBdf^342$iXye9mfxXFOgmeE(Flscd3S=dg!2y!D@tR8Qi;y8ENmzM$$ z7h-s**VWYzu%aMOLche4#-$y?1UxWUNE^IJrE2PACstaPHTR@bHk z@o}mcxiH~1*(Ib#r;@9gp&DNgN{QA_F1AM{OfFPY0+*q(!SQKxo^zx~dRlZzM}*og zREmnYdIi!h?)Otb2MIDWizgGXh+AwI1C+GOz6H6_ z(`kT@OCB^HFx=1F4m!q%8scY>lc!`yby*TN4~_dOCNZ|tu;`$DYQO{|o3@Or93@k) zhQ9k~qrNuu#VzD*Y?0+T=YD25-u?~H@rd3jByH)wJuK3mjQ-sS{rJVL{@`QVv8LsQ4dy`9Umme6hL!)x;1#E;*Aqd!bIU&|#R&`H_qbRCRNwbd6 z)M{~$Muy&L-`@#c?^`4EYO2`%l9WGzRigIZ4!UdHYhcxC%Gw`?e*9gV&x`Ct$9N2!&g5~2Tc}q?7 zP7OAH$9)S+Wk_%`H#Xl|`(=F=?M!ote|bAirlczO%c%R8rpIV0p7 z%P2UjFW>5DhMw%9B3gJsw2|kFi3YY>37h_F4NAT*8>2$eY};FkpjL+H#vWq9*6bqE z5lYl{u4K)4*?@(G1@acZgd?5h-Zi#W9Qp@c@j6l5peB1s;gG1or;sq-^Rp^?)?_bN zidDo;GSO7Y%a_u@heCYnLMb6A32a?%LEl%ac*CywfBfhos+aF~)=&{?NQw8PEM5iQ zJ7KP4j%I0xqAP?c#qcRt4n!baRH)}d;L~{89xwM(9Nb)Y^)=1mG9(r8kQ%rGZfisw zfJP1l2RxHrcl_09GUAe-o#lAFpfBZjEl>P|p>S``WHQtqURTE|Fsyz{^7GJ_IEA7| zE%aKG!EyiYRE@dhRx_I4bD#4ZC>lo73DkUY08_ocMj5YL;}d-;OFS8M)pV97H7|A; zJ0S591VN_)*rw6)+b749WJ6b!JtZE`Yk>n*2T6h8aPW>(!g$@5KG$BP|BlVW%8pU+ z2qpBXoQa7bD$50Ev)>2Gkcqx<%OEqCprh$wmla*JXAnC-oJIAwRUqAB`uAT>ln$au ziDj{Xo`91A)4_aGgSXU?o^(lkz!8aWgk-8x)BCjodw2lb-{nIsIVq_V%6IS4SqXaRuUQYJovpD%w?{OKOP*0RqL7HXvqMve z!~6w-zZZJaJ0A8GS}>n3cOfojW$9O@pCMO_4YjZ-T146nuMXt#!>X9DeGK^}^OiZp z4ARU!zkyZ!GxBQrTb(Q;BZr(N>I{ zm_U!5jjlpbeiVdAf9gbJoe_zZw$`q(|5AIgf_kwFwK8#{xd?}ztKB925@`O*#I6Ng zyqxV-INiD4^Hy4&;My{bGVD7~cTcDIcbBZvG)AE=Rvji3HLH*MHE56`v7S?=cUNCE zda!JWXf^SaNDIZdS9X3lxz~wpia!_wGz7R_zA8za3-~uMpd18Wu}k$bHqBO-_5A$t zt6|=(QmOCWHCbX%E(xQuK~H5qI+N{HNkXiorAl!y9nnxIpu;q+dm8Zg`)Gx<>MHDh zsAvSmbz$%|ltXF0R%Y0;%Bn@5O@qDhdKh)xc0lrbhcNDcarNHuRQ~bbcuFBci-RdzVFBVdpyqH zb#Ptp_v`hXHwRt~W}pA=0}=a>Wm*UUIEqUSv-W}>JJ6DIo7xn<<|-SA?+^pF{7)V>=WgvsoP0aS%=mez#DRWqwJ=Ehe_>gLD2+> zJ_J;dpZ~^X=+(*Kz)_dZVs|8*zl6scm1m#2bSnuQY?l~1A}+OlRJjr$SY@UFCUk7N z-(Qi%`a3agOJ{Ee9q}IhdA%|2_6csCW+R8gxYvELC)Wn=#Y+u6R+pfK39BF0B7x2D z&4QQKU;PQzII9jI)G5(ggmJ{QyHB#UXKJm{b037${&}Nhci!u4ccZ4llJU!P(Jrm0 zWsa2K{K@^`@=Wt0+4Rb7`HI)BpXoi^k;Ti6SN(+t(X?|@Odlj|hpv9P?F7yY2`uSk zHO`;&NFvH#7Sz_@vd2+07zsHH-);2zDF}Ka7Yu$^JK^q9pW5l~Za6`lZxOWR&=mji zOO=#~Eu!FDXS6kOd*+JN>{qdU45jyJ!`;Q(V47`VmY`Szo_xMkr54!N-{ttON}{uW zSB!Q3PlLh#OH5UB;JPRo(Z~?$0S>9ca@mCqRAs;jpCvAYiVF=sSf9)@=#IT^)T3PX zSG3B7?#bD^A_4*QaTirpbsDh(zJqG~>7l-ZOxam+N7F-Wt?cce{7rri48Iy>-cFv? zyJV}E2b-C3*E!FaE}C1Ijiny=rg<%Xu9E8p^V(P9+cflV-w#bkZTO2+Y4>qQ3Jj1< zgaZA?hK6n}tH{TPSx<6i@!mhVWun?LpW9z@+hAoobwbwEq(D|$%%OMRSI6YK&U+n;;L+4dW|1H5Kf%`m-Zo8r_Uv-;4)_GSs;i4j+?-$BOboag{C>ct- zdC!o{gzE{g1;L`#ELfnDy&luXH1!qXPrFgP_ zo0a(SXjyp~nD0`mB8#PN=|VIrU#9^l1EXH?$hB8+9emnl!Ys`Ya)16e%p6 zSl(y;Ku3oaY(IDN;X~@NV%WyuEwKp|o*UCU)_rLiX%Jbv8g7k;U+oDC3c4(O zG8pI|Q}ed9U4GP~vdbTL*^DgQzKvgcxB=fG=&E`!`g*jASROfENa&&@xJ+lE=Q= z$@Iy?R|xKe8d3ii4OlQx` zMuqDbQWJUmF12t}?PfU-GLImp-d+iZPcKGy(O6K+Kg$OTDW}1Y`oBIp3JUBLFV`hr zo_9#6se5S<%}Yv^fK0u@_(_KM;Z>+NK$XOBq6Q)yD>NoBg$bQYeM{1@_g8aq5kReG z3b?s@lv`2@SmdAk3xMBs+vkg2JwF9SO(ecDgM9cMYfbd#&J$hTq4uR)nTYiNPI}id z)492M)Ff!AYcnl~KR-b=d?0%r6~e=dzN=3T)pZ%X)Jt2ju~C(InkT&2(v4gfOwTFj z%$yY#7GBxV&q#!%s9W!0wRFOdIc|tRV14w|jH^Rs1WL}&&rhduwA094-78yLo`dG4 zv-Ta4-58Lf4d)9UHjEIo2~=yl!D`NZ(k z;ZyV!Qvb2m5hRnn@5XI!Zy&b%i=(BQU#?UU0XY)|GmSjXBzN}XrusV?%lvqFI+m=! zKi<~XQ6qcOC7$-yq1=xw&1PFleM7-k=ZuJ%(1RE;fgw+d%9L{x^N-%=WU zFGpXQQC0fx!>v2;+c_vA;?#L~j}jiE=yZy+3>$xIFEUv$pmS{oD6r+SNn7jAH!j1w zti;I*swMM}3>)Zj@|WD={MT^?1XL^kXL#Y+~9xH-ZN zmlpc2?yizj5mC{M+>&jiJ?vTk@2S=?Z5%Pm@N61Tdtk_zj%GiXpcYVPtP$;`*ctjg zNbsYsMFwJs`_G=bz-WU1e4rjz%8i*2R*+|Ro_0UROs=}#*JM}hdbKke{)Yvqa<`we8LPN@C&c9Bi!kYWB3cF zKU=50+{v7+{y8$K(DN_a&I@!nn>ISgao|)N@dT%B5Qp^#eA&=zECGUs2dj6*8@4HI zdMyAZ?BKv|2j}`;Dn>>iV`;yKKDRDaT!UI=eE-*n5*LZsk6V-sl1S~|R~A5hlP>TW zk(5HIhO#QEo;X1QN)dh&-eZi4@kmlc;MhC&!eWMZV3VxR*yzo z5@UHdrS01gj5RdepYgCKv}EbVD2YEg$MWWXwQG!)y$COWXp}>6F7O6rLQT=oeX%zk zot-nK4XR99T3WW;_jAS2q2;hD4a!}OS%YO|W!u`@YE`(S;jyY7JIwe0;J4l#-`j-5 z#Wx+=v45(huU!*0>%O~-PEAd9^Kjz{;t>&16Z;>7H3@n4?O|+kTx+tfS<1|OeL(>;7KibC$2bg`m zG*PiNR)0v@B{i5jHy_`6Lmr$MSsKTtH+}$;ad3H5>B)#}h)P74V28Nqcu%~zUyao2 z(UOvusoTJ2pekWr^4SZJnB_+d$M0xm7`RP`kJj~eMWs#{md^g=rC~u6=WyFAa$lOH zoFe3DEn_BcD=s50o>nn5pX)o3ASHFXjwC55$-h3`0acGk4Z(r8R9&CM6(EI#LMn!& zG9N`xy>hf^KV#b=CMxOr-k;5piqJX?CDzb5Y~c_I_)nFGv5E2Cm1+U8+o?lCda&Y;HdLiqo<6zLqB1u5sUub}YGmQBK-! zlxXnODC6wghzK_!t(0GD7%YqQI@0;=&-Qke1LPec^3uXm+~?2AN>;}djVr1ugGsi5 z>quSLPO+c9YyVRK8<@!Yr~1=93okkxqGze7Rv8L>25059t!`5D`NO(HZjh3}JvEtQ zy33F3nTDozKysaGN!GjiW^MG^qF&JJRRz{XsiiFmoX&qQPpssv7$&seHh_YVuv(cz zr*_WRvG^x!9k`vvgx@@i0)LRkjSKAeNC(*dfxnq|k8Iw*x%WlVQ$f_gyc-mkscL8q zntlo!nR7o3c#9Ab11aAf<$%uNz*3Z_yywK~>g#Ja$L(r2s?ggsR$u3bRFkQ{v)PRx z4$I;Vm4TJ}YhxpK&~tFVy}8God2TC-iuT=6Ydq|6%I81c08_V?s?dKu^vF1$tw{>W z0PAsxBF=IUK|%+lm;kGFE~PHW5fB1~JegmssuI*aV?LPBqG(E=&TD`Bg0S_v#-bm5 znVormV~kV%1sm#BquU|uM-?_Z~E${v%F z0(#EPSJO%Xp;F~Ad7@>pOhe-7oDN?n+Iz!qh$1Vw6qEABSCiy-lRIXB3qnLwAMjOB zTmSA}+(7JLJ?kj!JP&K&v%xT8AIYw-&zRC}5fuz=H$9MN0v26uJ_%&B7RKp69-FmS z8AVx<6*p~K$FY?~k#C`<1s##kx32j=e#{$rTBU@2&&~7fsS}mhC~e5z^tyGLm(ZHI zk&3VBb=SpTStTWGy!6c$Z}GLY6_r&y4&h~Gw`}w63>%)`G_oo;rE+a>HPrbZq2dviD6ndb$;{J)t+E7kb|74dtxVZJ8Q$Rz+@cv3|Xfag4ll__uF-BeaDV z3+sPNxtL6eX$QI18z*xy1y5;C%pK34UrB^PhC&ko{+sf*dINI$PPhP~$**PK!6Sdc z_HsX(nvS@*lxFN>N0SV7V`I(!vo=V~H&Kn%jb+!3iAiD`hz^7NsD4E1F{O3PEd*)( zUe&~cM#!>f3NT<{rvf_F?iLhEocO~xJ_Pp<;2-Fg3l?c zl;ook?=?OO5m=urPh8CYPv%|Fkm|{k%p%vWUVcg*92`70$|!Qj)a3N*{@is5wm0(T zoj#$zkjy^Il(p>*>?|t>6s+>F67Hu+h>J%VmA@?YBYPZKUFCfB%AN=GziL7ffRAxG zR1Q9SQSzl`8)YpZ?AZELEoacUjm215*5kv;@A3_lfpDI9S~sS_)S*-U4vlpO>I}EP zWI-)h%PW#ET$d1VUHT;`CV$%gm6Oxb0tf0LV+p${b%xb0`C-2kwrAfdX~)UQ&T8$C z*w7zD^T2AW-wi=okjs*IOUU8Zd)f#N*#v<9J8w$(Y^iYr&sGK`MSe(J`~$bFp(=K8 zl|G3k`$xd7Wmt9H^%0qK0GhU_y>%)URNcp+(S2*lCOJNK3=jb%?|F=R~Us3yM8$Kd15NsZo1`kz`ak1#YFXf`jQv5~AeT z8+mSKlT~BUegkTdHeHP3x3o4E)qoN`mERsL&abbfzD!WHWIVt;%(spjeLJ{)7m3cM zlTZ`okeDw1B+dsRTjdk72}v9c!@q7ISh>?k@*RnkYW7Y*xd-hKJT^wMjW> z->|&FY)OYzJ@xGP-;=}b-w$Y~VoW_&vP?aGzIc4djaIo`D7{A@W~$i%o_PUfwg8FfjExEFq0xtGIc2Zt?~I(Lr=B)EaU+Kka1mfS|^t6;6Z< zO&>!{gAk#!avtmSOu%G;e1rS6Wrd$@2QQ;NPQjm=jH<^A3JWK5I@ZhtiNkS;nAwUu z<_eYs#IP)V&0d+tXGv@6-sgroIuic_^#UW}1rTjHYh%D8aL{qG`Lk0B2#n z=Zr)fy2~po2MY($&IX{Ky1w84!_w35q0~e8l_VYb@MG@bt44EBvB47|A&_9A5J+@H zr##-x`J^rPlB$4VeLfEwsyCv4$1dO}&^O?-8FQZQ9&@axYDlU0i?`-so>w-GF2Zwn z>GHBhY*eC%7$BLkBMNxnqOM7A**^)ysncvm!g({H|pQ8)s0&t+;Z*E z1Z()4-Ja?@1I|HdQ{3j>GlD>b*B(ERr}va=AbRnMjgWAb^L|*ln!2X`A$Ncild6su ztLTGQc6P0K5R(fY3_-OE=$NEw{oF(5#oCUTuM+Pb*@WMqhT5_43le?J2L^N}Z(S~e z5BB%^$MQC(|GTg4*gFvhk@q*Vd|}!TB4QD0wum{+DgDT`CdAbsMag5o=5ad~OM-6D~_*%>|TCz`#M&`aDU zp!CxK8~iWoh!=HffF`1)%@VR5Jm8?w`HFD_v?<8kB$3p6z8@HfLQuKsJ9q!aMxQ@gRq&j6Zv!Gd>B-q{E1HWDlzXXPi zbBUT!tB~2GS)oyRNN;a18!Bi7**>v7eqwcP?K2WmFps{SOKBycPl>@hJFly@MvJ4* z&PQ~={Q23sPEPRDAKbvWrjJQ|0YB2|-p$gR^BnU}%$}ZBlt;+R%RA^%S!24yGfJ>8 zyiBQ7Kk7#sM}NAro63?-%AEiQld5MLxlVUlPTia%l90k`@W?-mXI?`DuWqs$x7V|& z81(Mb;4_VxDqMc4-k6(A=t(c)u&UcY12tX2fSAy(6t^*8Hw9q)0^ zaF=@xuH`OH;dhrQnQhNAPwO&zr&#a5Y8+Wx2(6w{*HypFTG)sNr;ban?9!>EaWMAmLyLO$1gDF@`ic>D_J?6v;QqQOz2k##+ z!U%g9*uE77dAP`PB)AAk!iyNu{?CEvL=;A#sP05s(-C0$J@?P}J2QtEEORuk= zSdfvr^1#AUgJ5bK-T9h~Q&x`CGgkbnI(vthF}Q^%Ig{boYD>t=)VGtyIJ4ujA$<#) z*cSsuFUz>~_f{$R#5MSCqFj}e)kKto?PJc{_-qR5U8EeXtG9PH#kJ3CiJ~LHbCs$c zmT`a$3saXt)OyW*2!G;f&T;7eBrtEKJ@5WqT&fwoHw$X8M-LsN?0@6bN2`k(}b}Y@wbA0b4 zU}=r!G(6GDHh?YMwO2lRK0f|Ee(RF;^~{`{p-N)n=zw99K8@s%|8Mcj;C-1)|Zd=k{koevZB6&gl z`OdsrrvdH#BP!w<^oc>_QC~Cn5bZ6GFD*T%AbG0Mu?LY&vm+OTTcjAyv>_f?t1zT) zq&iYPiMr~yZr!>=E?f|YMv5m_9gTQ@04_k;`ub%TnjkN4!2JBV#FM|r#x7-}qOQ^0 zJv>*=J*7CkvgNxizrj@m6%`dR4sp$t;!87Z;Y=}?MMSV*RPq*qlq6}*k}Ts$|FyLC zg>rOuZqCNeX{jlI zT2Woa8#F)Nd=mV2lcfE|zwUGvL8r=~7wvRYzPqQZBW`uP1j)p&8@T&QNTQ-FwWQsh zj^%Lk#+ zXBxKpJFR8`dW~noXFX}kSc1TTXVFR`ti~m?0|1+PuY}|;@J_8g?#=#+wW2S9Rguws zfyzV0<6R6@0rL{|7-@-7rGh&~KtN#DKALZ@6kv7YND33htXs3r1<}h zl6}U+D&@FV;G=haRWJR4KPl$dPOuYc0si`!M)cEy;+)*vW%>blbGy&D(bR8%0>a?U zeH=2pStJ#;PS`X?R$+rcrbV8bW$J_5Li%y)a#aq3ne@8414Eo93z6(ZkUHN$S|#yP zESeUZ0$#s+U^4k4_dK(RUhOd}$Qlc}L(#c$=pO!Bn&&YQGT^vCq{^lB(f%F5#ZMBQ(` zo4=z&`a^G9-QB@(r$T^xd$kkM@kw`VX;3*0=!O(cO^;%Vea;K)5!~z`Ht>Wd=VfID zT}X*ag>uV`#nRSxFa-sIw*_StVIV(JNyps`v{)Gs9Bo$KVZ)7Y$%W>#@&--!jK~a54*vvGL`aeY2ug)7$rL2c+`ObT ztFvEo#QZs-2CaY(9*3>9~~c%lzO5+cXGba3@HfgqevBb#nE5vpPzCT9-X&|la&d%TMlphnf=7XH8UAKvZVF?bug~3CfIuD3!N1{2O@hRaJeDNC%DxclYzjG7cShxME1JSHbQ$cQl7j649C=P*3lQGlAp$g<4W)WOv6B zVdj9$L}JJ-lGpV2Z@x;ED5GSw<2u09`sa!V88zqHk$0?>jEKUWT7^z83JVB4jE8)z zg;(-ya_s-V!OKK(`uxmCeMY};dd^IYd306Wnaj8!ZPmNSBvVCFnwjrp*jo3uc{IMh z`z}c4Yz_yuurMMN;r-r%=b|l#6u?nFf%hMbUQc9hzSO*I$PHS>_}?R&fl5RKoD^Ma z#qDc^{HP(dTo?)XuY7&}?XzdkxZGuspPY15II$~%o$Z=A{POYR$7YbkOJ@)fbLPYJ z2Z$P8NAgZBnFaRsRMNFqhW`6T&m%5n?1ggPXUvSRkdi5NoGefe7c7yLCPRyZGWfQ$ zux{T>Y%EMZ?5iQhh9^mRmDz#${e&a=r;eKn>zT7>4@okO#SZSV3Gjy>D*0;XA9>RK zcr^0L&G%8_$f%(%Tb<8?9DczE&=IJq56kVNDRXuks17gE(+ARVQ^^@`MMJwWH7TOS zHAm_0k(P06M?pf8^3Qk?{?)_>azk(LeEvhi)a;xrZkRo35IxjM!S(rf^!e{YM+$Mo z%U~Va3>p-}QNe~? zN?%z&w@}Wq@a%9?s)mK)Om)lGK)4btuc{p z4}G?Sc#k_dJa*4?>xyTjp1F!cY3n{aYIUpQ3ET{WLnlq&Q}W&0PaL(MXiSx_KggvpC*8KX3t9jSI5zGakN5&_zqxna__dIW z$?TX(6$cx@u0nfz#e46$me&1-&iPh1JBvQbqy{@e-rnAC=6Xh=jp4P`HGZmuI#u-Q zzy@o}FoKcfMLqq=-{a+l!{diwgj%cYMb%L2@79CiM{azA=|mt2e>9^UYNK>d6Oo#S z)t*%@P*$69O1?saOFW8sa%_swb4_RmA=1OcpNw}BOH}9rlu+-_K6+uDSgVW z;SHbw0zKZ$_w7uWWoUPZrMs@WanR6Iu+L=^m}4NMQg({Xt6IvHrz#a zE@W9pTYDxVnAz)aA@RQYxUq3wabETfY|}7G-+XhYysSJ42v%cu4!pi!H*ZJ+OTker zj`hO&-|yj)7k&ws!7Ietoh9&Ynww#`Q^Vo~I)qDRQ_i=wlm3fq zAKj_c-^SO~)kXKSIZSV?VZ98x9jEV zRdqDv{76`^c?cgt@!`+xpXoiLP&ZN-SoSVY)FG3mecOMzx$OSv8EcNqD*{&^m@$7H za3{%Yw+c*JX-oJU8OgHBQ`jEJUDWsfNU8cG?N3fd?TQ>|yRjl_7calw=_vPIx#erV zrB(oMY-7m8PQbA09;?6Mul4kkiR)(FnmG5HX*%JjiP3MrSG{sWp_a}%Oeh0zC zAou&3u3_^NxI^)!Lc^I=6~t|SUj-C()!>uA$R|A}Q1JekdD$2SMkzxKCuKn7NzGRE z!3^HmQaWtjX|nDUAlAazbWN1F3UsfRj-El26AX+-@x z?>aLWKYPhYww86r;tfLVpc*a`eDY`FWaNU*;h!fiCey1{`co4^cx1zLdFXVaq;5vQUG~avS0Yz`P8a?#4m=*nXe9V7kfAyWw_psmA`B)lodx=ee6x<^}W=E zd+!_7n@ECgs$!eWF2*-CHQj%uQfpO#9op~v$%VK{i}L+oNdQRB!1#c-=6>Igu7|I% z(O2QQY1UGtb}EsTg#NvPXop$2@8qt1f4-CX^NsuzBQ2;!5fJ0-M{U+3Dhxd9{v$Rz@X~fgFA?`=;FpP0BU5gjocs9Dqttj?BhmNs zpA5`-fu?3?^x+h-VJ-}Lj7E2$7-dxidGIu4M{>&QJ>4+Be*3%IF_EhWk*)XAp%g8CP1E;ICLri%#HbW!ByB*0+JVEWpIZ{+K zHSLG?b<`&od|Du6FEKGLPRYYVT4go*ZID_0ehn=#DX9rGgIx5di4{@@k=#W9vlx9i z4w#beuKiNG5pe_Pz+E9Ih~fsGwWVc zcTEv;!OvT6AjRdvOD}x}93o%9V#iB&%g;f8`MoQ*=h_$CUSadZ4CXYY-Mo1-J|UsZ zs*@!sUh1|qiwGn`V|wsJgBdtp+zFkXoi4q#OY8{F=)s{=9PqVkEUU_%;cD$?OB>P{ z$sFg;Ju=s4VO(Vy85kVYdZtJzp)CQf_5AtO+EvR9YwHHlO?2nzr~|9;P6+%}<{lu}bO$ zdG7_}>hyzD{uH~x$s@cUbqSV#mE#A4Q2P44ASC`F&&5;tRDOa$aI2Gp-JA^ePz+5P z(gNUxm67x2n5ecb)hQ7Lgdtk)l{-dDZ=5kxXLKDnCyTbkM}{>FcnRF;METT7H&6F^ zUpN1UhDz7(BLj_VNWlf@jMeH59?vP4M0E{y$J&Jp_qgpIQmZQZ{VwXYBR$CI((O}V zY_z3;kXSyphQmK5l#PCs!|hOoU!s`8g`dLc*M~r(*1M31;$C$P9)q?TZz+JkC*9Az zOM|t$`*Orz)(T3>FO)N>$0IJqH9Pqe>_F3ur2Qd7pft7~_V>qkqXs61xzcf^u(iUj zP2={V#5CS3lz^4@*>@&ycy4#qxr^gOAo_nz5&%m03?BJYYmj`Z*Aq&DJ+ZCo*vWER~19x58KEbn({7e z@q26az$f8=4OVZEj9Z5qPSiS2{iu3%8aMM#z^OL)EC$JfRY zNYvJ5h=c@xBd3>u&UX4N+EBSasAaI1)=xaD=S}iSL|m~2+oOlKk2ik@R@ZuX#yX-1#FXL&mo!K^22s@E+aL-X$oAPb9Whf%~c zt2slLKd(J^?v2~k;QKy~-~H22CjBilDu+V$@nIZ&aNV*t{3B3CfN*J-`5)}P#{L($ z(FbNb*hf^W__@BRDel$PH9d2-a~CeKE5LMJ*0FJMKx(7Nm|K|te0<18$w9*TkQNY- zOWBX|pytwj>&3pcm})qDV-dv}49~&z&zZ8i`K$$l>sZvD0JW^GDAvjTOuQaZUJm3Jw^5jk*cOutq zns>0WRZ$Ce5fO;`j_QH_6@4at2ZJF2_v*X#-$uak@V(_kL zYaeu_xWIiY384)G!V&y$Ofn*?j|Hxw0P*nxeQ}&-2EzO^vq`4ZV}5@B*tgMqDz>un z)85UMPJLK#^qJdkG*6x%>(_s|PO&5)9x*R(-KXT`=P9ZO#Kfef^#WnR^6KhQ zfi=`*laXj|hgC3vJB1{n^m+e{-gw@R1O2*y&zTV4AtI>aG zFJ8P@kvi_Mu~FmK{Q!?C&j_rv`xA7Con9|Dh>4BAqe#Zg>KN$AxK~!**@cfE4^~=7 z-;|DP%M_@qAI^9x%JTG<-)aRr8KJ8Pp%9gX%GNz7YYn<-E+LuSXVDcOn@-Ci)T5&Z zV0BIP%z^?=5#AfWk?WK-XFU9T6TaLygJ$%N?i}#^s*(OKVbeUf;CX7V>hcATl#`Bf z4<_~dEMxA*9?{kyVE5qGGS0G7hUDy_`pgjaQw0cqmWM84`7EfQ)nqVJ?as| zVg80LQ-D|G^Na3;kadim?sJpEs$D)!Y+aY$!sGy&pI|5S4#*KgQtLhV*i1dfUi?Dc zK(Vrgjz|PnCC9#C^1Jz~bOMHf{BIj@c>RT#nD2x?i1Jtce2s)6r~in!1MI=EzrDui z$a36ucAetlb@R`9szbI-z9iSKDj{aAkz^4LGhckn&OiM%L|f_x^!`VUju4nI~h26l$kkBmBMufC`(X~7RJi%8)N~1Cf|8}gEd^sAwN)(!YU^Y zmyoo)yZTkrAQ9Jcq3csyd%H*@*DTxz`+nAtsK1^M2M*%(wfew#(_Cy;Ux`)OVcyxP z-5-xmPxG+Z-Fwpa`|o%}#c@%CVz)KiKvs9lHO=SLt>tAmzwR}{>3ldn!Bzm4`#2l@ ze0G_Lv5riV z$ZBdSMXI(Ci>Xh|frC}~#RBi&5Bw?CBLx6Hn<7tzt7>T+Pmg+iAw6VR;!=W>5qDF^ z>n)*A76F|*%Vh~*R-cVPl1ZefK3Xr)r-WuzhIQ`yNZRTr(kzZdZ$C3i$8SB+K?Xt= zZvj=%D}QjWY4Oo8ugB)-@zHf;4H_&M83~Y<*6s7>KkX3?TxecP{PbHXaP93MdC)UP z8pppH zrp^*kZ>Wh;LR{~nvVo8ph^hLWGe43@ccZSz-fDw+jVS?(*+QLmgl<_SOw}@i3rJ^X zN@xZ?HQExrCjqJq{vdLtA2rd^rzco+pFV8`Fwn;{*;?q1nbt~1o{lwsKoF`^o*G@f zeto_v;FzktE$hf5U0v^AG$)2*#uC+e5*{aL^cX-gR{on%Rf$nX@XO6WH;rb$v_Pe(!h^eYO@3mr$>%kh%>M;``#|uyBn#zBM5^X#X#X z=DwFiEY_;TK*es)y`3NY?4*saJz8j5ydB&Y^iaH!_zW}*{P$A-0>;Td5Y$?B6R;TH zg@Rw7<&#@ln2P_YRXMOk<^4|^?&_cHifg~@_R6zHFIaZ=a{cw|GvhfvIVtbEmW-Rm z^(lle;A{4`RyG#O(PZC;hbZ5btdz?2>%IyS0DxZnnUj_YxLPsjdO-Yz-go3uBD|kk zpIe-#|Au$0)=s#3(w_l$xL7T%-*@VrP0Q0e5M6G!&hefet**GBKkOao zn^q@)&Dxm?fyOGS@BNzE+R`{$Z#Dla&Y6HMDmon?Am?-C{Z#_Ge+BvY|9>ze{=ytb zQ)t!Q9KGk-EE?ah!*#xw_OThgGm=4=v=5D6Ks3u^Jv}$$G2~t3IB`&Glnd&5u;2M- z<-IdG^Z;g}DqKff5|ui!X98l3bN(PWIkrgmot$*u!&L-C2DO#iH;lXm2QQ(%78ON; z;O27s!`Cs>2dugGg2%AWUo**hu0P}(t+r+rjMEsB^k?|=@7N7x9XS$9A{oE#h=c&w zJn`do7wUaRFH)7W>tM_C5R8q5UMtEY#xt0xUhNT@{P#&IDe0Kh+u|)WJky6_*xkcj zd4YpNC%Yu~em5JBK#_x3LzxGcHr11_`_-O|v^0K4Lt>7yzKWQK!CPNyCF%Ukng#?RQsPx(UM9!%_snV0VOtbLKo1rhHHpbm<3WLXB>`~ zF0ZZ3NkE6LhKJ#~y9n+3;1uH{NSMFrV1rrdkKQ9yV*`S~P6Xg$owX60u9&$yq~tHj z53bz?>9Q6*Un;LCm@4s1cdqSnD^WOKP|nBJ)!nV8EpVLU$!f1jG4)kI03NKX>m(?c zBUFuJ$H!YYJ%P-Vo?an3y1du87mN0Z`U<@b3uI7J({hmz7zp8I+g^(oFvl!$*+D>Y zl~ML>AQBqP(NZ$JU@6zZ8VPBWm-dhq5|KkRuuHXnCE784`C>fQ=pYOl*{(EFJ$Ek* zNQ8*M8TeMJ#53B>Z&U+{#f|0FgZ4Z1$}CP$^vDtkg@Q1gcaH^p?LIhs7Bvpzz2&u6 z^Ltjdgm23B4+3LiY!QYXX!;&PeySwa%(Bl=)@{ZfeTkd|)Hc@#5s8-+4~N z2f1RSoSex&db=){QiOHV+CW!9$Pk2zVC^1A6b)%d=h8U1p>Of9g+I^5JB>TY7ykp8 zZiyr4%?T+MEk{2n7~W0Q=ajp5^gdOYA9<*u{qqS&Ow_M;+Ykv&T^kqC zb(HTfUfkQ+4y1o4o#3dKy4GaYsBrh5+|dVWKc6djOse1G#sQ=h+v-`&G}tSD6zYmU zGv#Z?%)ol(N(;1;C;VnPJ(Rcu#xg-`@yK4`HqUN{82_c3Xy4`5LbLjW+H&i-)YP6S zdAU5~Koj7bSqhLBPt`53o-uL$yAN&oOm){Tp_()#?qM*`PaWbSYz7T$cj_`mQL9lO zz0q-!QCNAB3^096Ufi8wg@RC&*(J*Ql+Q=iy1IJeE{gUG*y@(Yp^@GVkT*aThbhcc zt&^UUYQ7C$G>u9u6o3cxI1)bWI~?ot4~Z{vnG-U9Gvn1;KYcV2<&`@y`MNuHyB zVyUpaZ?;QxieXgmO8z`b=iW~+kj{+5;Mr&X-n$PoHUc%aYtOKO+$4`UmhxKP3>$WU zg^#(pds;I23Fc*qN8Qnfp~cVEPaRvk-~(3qU$e^LHQOx*4~ei9C@GnXMsBVqe#ICJ zr+TG`FpUIEhCH7qaqJZIlTa!?4ASqwkq{HO3O!VoU77p8X4$-!k(HH$X95Z=xLQ@y z@AeOKVV{UO)T89+lk~@q9V_&=04|aA3;jB*44wK0wMdtd;P@CHSr{dp1&9yh99td7ITQ;2B~@DMYNzxCDbUV=x;ne1(zzTLSh8 z>e(}^Bw1G>AoBd0g8@U=wUc3CA@MLs*(R{im3VF`fQ2<$4eqB(=)pt8Zti~ga`NTn zl@+FfU1^oeoRcI(FURJ}wMeD&pPpO4P}z<<8)xe8H(&OgvY+E0g7mh#B zaf(j%v2IvBc{hw!xNcuoRt~`K`$uj9%x+;ZCN-|RW?eJQhjtt&Ce^gG7Qj0BDm!9Y zF5^WBKgWOcQqofYS~{YZA*V)yke{C)qs8l==e+Cc;;DrB!V!+vSjoigoo(Q|(vKcol7jYu~ z@s;F!T3-G;NNK-aNDCfEJHtqCaw{9PQwqMy%XaGb2(Irwgfzz_#?PM{p@ACj<}=ct z$Htz&SXx%LM-m8xRiT9HOK`>~=!J4t!9V4IBNcroFUim6zSPs<%`;dtpf&Ad2_&F*+Eu&QAe~7 zJ3B}rzmUpKP^&^z3oWo4X-wuwj8XNqzur?+WT;r?(P_KB=0+_3-!a(T8o6rLTt5+oIQ4Vn3(e z{stfV-ux#yMJiVbWURx%D+V;ABCL_$*%h*@f}-Wz{~yMie%eQj)!bT?b1C6Xztu+zGITL~s_@WC9Wu9MtxeZhmras9X@EzknsS_toM%I8Dj$96Gv|($@A6@Z-^w?XIEG zC5ONy(g)!GQR4W2L65xdZBdxbs0#}W@zhEhC|~?`5bs9lOHv3tXjqb`ka2zQ&aF>W zvz}i#w+4>2?`x2OxtHLU-&VV^nku}PH&}}gS*zXhJO~Iv(q`DFJQqHVo_YRzG3S7$ z$Kdp{b}6M5pk(rGV5iWwAW#o>X9|$t;fHg;7WHt1TueqFg=h%?r-g$=O#~%fW(YU;nI{W!pBu~vDG-7x&r~x?<+ee)-~A> z%GPvqAR}*X0p_14AY!_{k2`J~y!`y7Y8qO=IesC<_y0y$&&>!62@U+23Lu};$|Irq zcL~zHUw0g3&%SfMK8Ko#y6JpKr5-D6gz5Arx0%9DhHHC~RpwYXA-OrUqkOtp$=;~C zV$x*jQs5xiNENx|z)Z?%VDgIcf~h%aPs-TD1gwi!z9H7x4|`jRBxzy2$P47qz3As~ zcDB$6oNBGdI&*dwOolHz_qiD9IlMg&Qh(pmIEEM(bb0sS;qIa9iw6&Jo@_j}#T{CLrnJ6A>053`T_j@jm5lJv@5T zmI}P#8I6r;>xC|vk!qpacnqa)2pI|xeyyj&yhmPlEX02Lq^t~Tz=<*-AxZrEp6;_} zvw$CrTZ6{NJ{QAtq;RgTf}nRTM}feGPSrNQ;A-k!LJ|e}XL9Efpwug2)?su?%KFat z#)}uk%r(s&)5@?`zbvUb6UGsyu#ncZYzzj?C08An6!W9)gL3O1s1tA_qW?5~JeT4W zLV#Q+WEdGrs&o!82 zFftSVp&2{CI9sNR|@K-$xlChx=6RIn!F+^@{R&dJG~%lt8AAD82|lWGH{;(|Eg zs3}^ASE!gf<(5beAvXt;~aj|Apu)W(VOq7LGVppqy;@j8PbciU- zejVk1p?2=I(Qa4wl|1B8RgbN4HGO@dxw1~>VU*Ehc3b%Wq3k{2ss8`|f216#tV$Bc zOm>oN$DV}{%1SEP%FZ}e*^ZG}oCaB0Wv?SM6cX8clfBM<|6e}Wb$$Qe&-c21x9j@e zZt8X#csuXc`!$}=$K(Ep_=q%sB)*f+ojdnEvnt389S-WL9rvLpWT|TCX*pTn)I0S? zEN}Z#z!)(pA9BRL1a_{_{`R%~=Yzl5sf5`ra?ZY+j{Ft>cIuc)L2x{^JuQEG4Xe?W z%)7y7uBOyVPO@JJ*JCQE^6%OPhxnx*2)1>V$G{(Mi%P!6mYToeBkj1~KePFPLijJieJ{fg#P+VmPYy(p|;K(=4&COhR zuvgdJ^^tcSBae*SedGCir2ex@kt5Xno)*Muc%D6AiM!4lkCw7pgLh$8fWjzWe=_3q zp2uO|?@_&b&o6!rLL--#ylq?f6$9Bp*`p-|0^37hAhu?V1gglFi;I`rALkV{e@xMf zoQCGgI}B-cu?nl0Rqg*~Ee_L2yS_R`JW4C9Eb;%~ED>0EWO$@n~V8 zSpDK_Hc-R&+DG~i@>{T-s)RtzxXI+06Mu2IlbkFB&A|ipjoc-YF0;7bhXNUHNKIn3 zt+0pgf5yK=i}|laj{}QzF;r6T!k23OJb&zMUg8(ydAKoDT)(3ON|wjDJ#HPi?f2f& zBVay2xrn;dST?CMJCH&683B72mqjCVqkS5lUMc`@1f!*65t#)8w55{;dFsDF1xNO7 z#y}ezM(43AiE@a4Pp#RF*cbM447$UlAxVDm&9)hLjI3x<5*Q?g+}6#u%SQJfpn6P6 zu3X9|l`%lh7*3zWfS%p~lCY+Q?)bZsh=+q$33a|FZ{0w>MDY#Rd5hUfv?t2kI5xJO z1S4^)AT=~j6cve-S5#;$Z!Z6N2o9oeDx6qpwY7PMtshOzz|o{T+^e(eA5h4P7uhUH zKo6{gIoHmTK)hfr%*=mlemeM=hnJV3xv8d$o~Vjef#VqmX*A-XfvdsMZvJ?U~NPznsgMY&Dso<(vlFM*0q>T8o*p6Aq=`D+gJ zZ|U+$O1?NaI70z$=q>H-hw@fa41v{9c)sV#&V{|)oR0|^iRT-L31OH?JrYk8v_4VA z@@{SlBt=_7-eG1o#NlBxkU?PYVCaprv$JDnV?)Kav>}e`>F8YM6G%VU&=V{?b6eIK z$aCPG&;*^6l7fcvw>nL>${S?J2_R80D>?dQTfbSEQF z`X2iP(y{XL%KrXwHCx*xM+oQ)s>l`P75&2lFedzSzj!S?0dMc(AQJ`Yf>mlyKk;Mx zWlxstA)m@@B@s=H0R#&_=_~<8QES*14KZ{T(_{;Tu7iV;qDTv`^At5TGMD6ij*jMw zKhV0L#2%j|^Ye^ZbHPTHZ#a(w4TAhhx}AxgsYd7ULS%bPIt;ZiiVzWrEibiYoj20Nbv0B@WQG`!+S%(Kld zdA_f=#Xgf*N6G5Z$g;*h_dkT^1dSoG%(itHc7|+iVR#cr%I=pv>}0ZfzRf4hwM`(^ zAB;M_0r94_q|2CiJ3BYm5q#eGN0Q;KRKX3G3efwV?ajS zaR0OhMQTR^=*P#}C{Sqw3zlbD!solso?WwYy*YqQO;7K{j$0^w_SsG+64LEf*q2pd zW*8d<7Hbc2+U=)|coHSz91VT#K62wt4LC+{aXWX+kIG|7l;nM^?S{DI;GJ6bn0`pw zgh0Q9ocXC9Hx8W~4UX7B=|&(4L|X@Fa{aG1e_ih(=hg`-|=ycW)DQ#CHfsQc)^cy3cjY;GnTZtR^!H?E;@ z5zeck;}pQ+Zm%sqWL3q48v1bgoSq5^a#pMbk6f*+oUiZt#ozUNOub}+%)N})Wx>F{ znV6p3R=y%(L7r@Q^c^jQHU+dDGzxK|pkNzn+&PyW(c^tKCT}V~ZF&_mKdTF%9xRx; zO~u+ezv`o@v`P~ymNm1%=de@j-tAr5uVG)9tAN^vtZdhX9C?T(pLZBg3gio$bvq=U zQR}yoYjKIpUhjd9F*BO|BlImnw!i<^6KDH(g>~Hv=$eNs5et~DnB&EPx+e<+g*v}~ zQ#z?^qfDv(Lfx1{mYS-OTmdbJfwmJJ7R&FA4Sp-|3kD>_ z%3~U?K1bD1+!=2JC~4V0;u0j-2>azacYu&YzQv$H4)aSu`d@ri32DvgbG@x93?KSk z(y>W@)%~}y0yzmi2C=z~jaE4#Ts*chvUhgR#r9!Mclq@))Y`rt8&(1V0x~rY(Fc}wUcW|v zH)F@;d+s&Hgb?M=3=SCFzT5fd?iavW@*$9OyQi2o0vUMl)^~2j%36)Rf14L{!8&G< zx!n}U7<{fKJu)tdOm8f+)d}>Z}a}e1$h$Mq?;WPz3_s$E_Y|TP}_g$xqOjAyWqO zsn{(eohrFVgIENU3)wsscqlco0=33Tv zr+3??!Jc<%mywNG)yd*hoUjh`wJVgu$JRglW6rUVKTqezv0pHsV(cXzb4)-6k+Sa` z-?|2w4wZa(_l^-Q_L3MvMQs4qL{(JRAdr=Gbce`H0wKC2_|xC({6KP0%#q) z2iC1Qr|s5jEAY2>5<@~%u6_B;J?fi#soqK~y4T`61|5)+|0`GhJLcfvpymJ-i!$9_ z%5*?_5^PtzoJ+}HfkNxed^_f#=L}I9A^1r7ye z*+(5PK%=-&0X>yJKrJGvRy}l>oSsPgqJNo*%e*f4kzu#(jH~k>rS-1Hjo1MW6 za!8R5&CKcs>tbP*kN&ldUigaBVR+ zpPY{pDw#%N$hRg~!^Hfzqvz-6Pq`xbGPINUcR@~~n*D9b^QE}S!@#Dv^|9N!WopY% z7eqh;7C|Q13YLLJ@f5D7s(QD$jt96zNX3EOw(5FLmp+jE{QR)(QkZjt^3?p#u*vr+*q*7E+&0Q#%%d~>+R01EjTIg zwxBknW_PI$kMxE}<8CddjZI8Kf{M(m$~?Qh!h*zEZL4RagsQRcqthk*D*KrqLm%7Q zVGxLxZG4aG2@bQeVV9yE;7|l0BwEmpS$lpOtj?_+{HGj|9iv<%wJp>lxqQw$+?zkiY6-IHJ>qZXOF5+0c8Dabx2wFp4U zMuufm7ABJ9i{G2VCsH>=;NO zvzU-)cHu3!DawYcyvJkUh%9W{@a+*y-V>_9I}U}*zf&HMj*V&G()L_O*fgu1xnp94 z%swCd_VeeE;$qPh(Yrb-4~PsOz60o;qYcjQ5%QGj80seJ= z>r-yceo0+!I3O6a(DL(>(^A$qm7-c+U$qRp-+faUke=JLbCtcIHz z#y1}r&fdmVzH&0d0D+MgLwrg~PqW1Nnq7TB(@>Di1c$PK*49=HEK<`>j%ojr9coU@ zbqqRDfneNr^?`I_^gZU#U<&W;vHYH)AUD8Y<_uK%BMsiJSCVJ2Em&yJ{?`)+r?-t{ z*l?-)&>7%>jF%AQpNDEm?z2G@3$~;O5UP4ld{RLcq5Kg zV&FLa84P~Q2Aq6v+cCArbaJ{onW*7y@1kuB|*uiFR-p=jVTE6}{F1q4z&b>8a_!116MIMB{iFCY}f08j|H{?UMx z;!Uopsd(}Gz^i|}<6)yai9TGcWv=%&5mT1mDbhCo>Y;yQ+ONXDN)#bm4Tf#}$P9J6|;LoGc-%=;QWDZO@fCN(*Aw@;PcX3T+YKjJdw_9lMVoC{?*DzyW6 z3*Fta*-MMP<`hcpX{Uh5>pPjW0O($H*&nkFtxf4v;*%8O0KX_ujnsqb)b0c>y)hiE zrq8{58DrWUpFnrRZLIKN&ex(?qHzfmnnKXND`$vuD&uZWZ4_xU8?0!jL8=Q>QyhFa{>h8`A5@Z*H2McBV z+D;yMBLE-Kf&d_j)j2uXcldAyy=0H|%@oY(fB=WOx1hoR@fKPqn9teh=hXtr1T@iczi<<;oF)QA&w#_HmCZ`lmn7$Qaa$#K&L?xhKEo6m+8l{-$@QXsAB$1%D4DTU>wyE*d zNlCJ?=BWcH{&WkdWB(XT@)4BlPXV(_a6DMKID`It5@upzUS8R->CI9AeIRzU)lE4o z$TmLE?$PB8sG_Q(f4u+Cv#6*j&U$ie6FfC3RIELE3PCZ-zxX|i-3F34pZT?0tWhmD ztI*!TVHQNJXgD~?g4KD;?EHj+0zen#9ByBNmFIdq!ED5 zbJ%#O;3IDmQIctWPC3Hb%A}a2Zzx-FR@d>&Qk^orW@?wg;_%HMsh0|XOn0yU_L{zq zPXD9xN)+La1p*mYXEGy^momXhlbVXwzv*;JX6_j%+W)?DBN1V{cvDAr|CYGTE5`6>qbY%5xNy}w;lq`la-9O&fJBocj~g)BJKTTz zduO4QpLc6kSB#rseqpJ9WKjJGh(LHQa7CD6y6Nk&4Pxr&r&_?_nv`Ey*nzm(6dX!( zCG*;&hlFsM>33Z^Qskw@MYqND=mf1BF5_C9(=?otlF5kze4>bPa*C!~J1d>zwu(|&8vCei?IC%C$F>zq zsGLLp!p2M^frahr4W3XSP3A52>*ZKwy9iKbpYr?+vSk_5f_@#aN?gUgi zB0qi%tY(^BA~&nk?Z-;L16xmhTL1|7GlhXu5Bwh58A#Gkl2A;YZ&kZDHVU{?&9Uu< zpWS|PGwq2|-=0H9#2~4@g7z!`G0kfMp591}J573eIw16Z1XPX1#mA<|+cRM>h)sYD zHjlH>kv2`6nn0qR2kza74VlFSDf65_zlOXvj?>%&#F6Kz=;UN@)It~h#aUwxMh$qs zJtj?fqZL;0J;g(gdw8Q)_Gxkk^Hq_hLpJ^Rc}d0)G8EW?0B)gEM)W8IjI3=!}a8u1k+I|yqW(rL6h5-54TfL@)`SlPrv$=$k_^#0Sw zh(P(ksf+Ly1j@BWwFl7NEwrJwwwvgkSHlk<*=*J}(fS7L9j`gak zkHtOg-@S9rSVI^VRnT4@(~3e+%DhuZA&t+2k!8Ai}ry?cRMs2wPuiZ1h!PhZkFij9wfx^u|WM zn=3K;Nj@``k{CcZprSG#h3S^MkyY9s$1RN59dI!M>q#AvRpPOMg~iQQ-H@|Py3QtA zKtPZeTEhQU<09nc?X9^rXFGQnSg@&lb~H# zw+ghxnSv7%eRB7oL2bOZYlyAX_H|w4ciT`Z{DjDD?((Djvb>s^GA$^(h7wl z66+&&yw5)b^~8O7?6-xf@$nEf&}&H=9O8%u_P9!CAaZ?HI!gh17gLSUN(=i@*)I7` zcypI^qMYJk-hnsPs$2E;ZALrzs`evT;LzWtK{`Vt0<#i(Zo+GqnzTb``3Isiq3O);uht^f<< z3;~Y_6nXu?GoVIvkBivC%*7yA?CrC2KgODox67U~uoZSuYXe0+AbEbQEI!W*kcU7T zBbWQLf1vr}kJqK8K7a|G21r3*vE}YY2$MZ4y&uqOX=^J}b!uyasruLNNsS(?MHN}< zl0EPs$^){WhPy5u7^m2J#e+YSp-St;shOGQ-XX-qP=Ee7#a+K-v(%Fbz*V3dc=Z!$ zZ4H&TSvroD3t07d{Nqg|!+BR1-)J7qRZDZRyPv613$)2?oCLeakFPzQRXbyHDZ8vJ z0c<)XZ1H<}#FXDAzl$t2^r<~fe!CovhC$q0C>fKRp0qgJe*>;*Q}{ElKI0cM8YmAw9DEo zgzrDrhj*9~dNv<`o%Y%Eo6=o)*A-7vuCV_QgGkXdFg8~6^_3ZR+iD7Y{39!JK^o+E zz;r91jt7tp&TW94Dw0z>qMwQc+_!JL0E32NLh6_QhgYn*>JfvOUacW#j&blH?PR}6 z)mOUMgm*V-c@62`s0L4%M5pVuJ69n#-ei~f7@B5`snnV-Wc?uq0M*#ubm(v;`)cTm z-8MIWZSBsp#dQa=@*JLn*v>o%(}tGzmYu zY^^o?)DVV@0sHW10JS|`hM0MNVg>#k(eKvE?yW;BGa>`y6p|29fo5951%w4JRTAs! z>XtWF+kHh%ADb+e;uTWD`E*mBEhh5$ujpFOe@i$KxH~qrwbg>+bn;Bz*zHy5)kJum zhF!_HO4&@@1P%;7MMaL_7H_^3H|LgW;nBUOq8qoO!qQL zUjSVDQew0ir7wOMPFq<%sArbpb8y!VOo-iUuJy&2QDLKxPMt-_2t;PLW@`}&<1ic0 zn(DC|3KI%~o0>D5qZQo?{QP`h9<<2-);_})ec#{+>qX@7bo6#Ya(dhF_ftn_&y*W4 zFO)nl_6odBS$Ft{YI^@xiRO1C=-YD)lBs4cTF1%&f7_qF?F2FnmH0O(OwTTl8Wj!6xk|5ips$Ic~YOle*OAP8E~u3 z@iN68MZe>ktE&P+Vjn6SMIA^$L-pXuX`OlPg>-}Tq26zVGbR4mF{g2C#_ZhIIh6(b zKJ3&?9kLa~T3EgE+!4+;BImzBl5v0=JUfUIh8+SZZXgYFtt{_NXkI(1^9QTGRUn5I z%1Vdz5m6w`;9KM828sdp;t!Y-bXxUr6+85X7`25%K`O*#uOQXra3A-z^PWHB!m6>- zpylj&2`+GaWyLm4(*69H_eRsEsiJ|AWeX9v8>t%sZ+3NbRi)~T?BwK>kx2)R4p7lx zgtepK`afn`E)^H?ArR<+a^um_(foo>&z5!=67PPo(i z)wLM!Kwytu4hh-{TYi28U`tN+Ulx8yT@e!lrM4NOgvyv6>OKUzdq&{<16rw^*9NDA zyYR@!h$w<#?+d8Qg4N&yyY+UesHH}GTFjgSL?j(^3f%Rqa#?t|bczj$;wRGv%tX4^ zKccN7$Ic^JZ6&IgXQPM9?U{>y{9puh@{X`sTA;K`LJ~=vVV5kQyqcxcttPw5(7g}c zv$K07VS8{BaQ03pfp`d-1NeQz?T2AjMYQ|Kh(6%TsUm*Z*8GgT@{IQ3@V@QLzL=Z^bL$(&nAg{>;6z) z{tEbnZ?9oM7iQ%Uh~vOn0cfXZa*jZx%3wGGsp0t_vA0}^>C*O8pdaBxU=bnTyds=k z?~j0W22JT3sWJmL2g$(R@= z*a$4Tf{H{Q?pAE<^Pr+u3&OTz4bZA6+UtVneX^Dr{lV>IrrZ}yE3d;#nsjD3F0ni~%wfTv$9y54wm$Q$7u^ z_0({53y0R^ozw~RBcHOc03HToQ})HVp`rn_N6UNMYLt*!`4dJAkN|&J_3i=>ca}AA zHC3M2*WwV(`?jIzv@#>p^7;yhrQ4u*ciBX&fq1Ro(9o>*q0HJ)$(%lt%+sAJwh%%m zD!=kCc8GQ{!9MTzh|-K;aqZNQ&QrE5^v(gNLN4=GT~_6F*9pcz2#hCE(!`m zEjuFi3GwktpiT)6vTg?>K#fpXxfr|McGbS0S6Ekp;CEBw1lZ|u?)j)fYxTPN+O}Ym zcV=k7&^x=Q!dzRM)(Wk^V8csrv`xM#@YI=~6`#1g2DSkVd3LbEI^*MpTBgu_0;;?7 zV_sfFlxi~YQr#wTn2=X&`&SAJRbgKp*`(q!P^W=_!v)vD-@2PcCuWQa0swRjI}{y_ z0`5_N>Xp&U##y1H&Cf!j(N`zS@X&C~sp1;EgH)uJ)i+3(tF!Y5my}ev5~r4{wV1+0 z!+q@sKqA`K#>m35w1`7kLvdVWGd0CrlS^!Hd-X^pXQ`I9E+wsHCV-U>Oz-1hC#V2$ z$piP4_NnR~FtpZ~00+w}yhML{d`5c^1dQS6C0UOM z(E9x~@oVm5Qqt@0^k^1F@cvyrGZn)6D>o@K`Nzwl8-2efbZ_FoQQT z>K70Yu>q$z03P`4y=kSBs~1~~)Z)P;eg%jH{H z@+YD2;WX*R9(4D|*w+ksGG)_;g`~h z4K)-#-v&)TJboJ?41K^_J2(ikSom;J zV$eN3dZ6V8fc~xgt#wQO*j3aid#6ieaB&k@mRX=O-|M%(iI$Ds!bt^*+qQ4bp!|8y zT7{8st@Ux-&aAl#*$V37}hH>!R19 zcHpTJac|x{9cGf18(Udf;p0-w3JX)KS9HxIJ$iymeRbC8+M}J@-3U1$AqRrH{KDo| zM+|$nrsB>_9@!i0nb=cF;d8xj6p}zq`lSGO0kk>N&_Qab&Nj2W^6cV1@<{b`7UVg2 zzgk0_almQBUu=-aVkXAmdoxl%OK#>pqnNX$HuesR2shqmo7F zmqvjX4;N1j`n=e6ZNxpM2;BPsf4b6^s1$9_~=+6B`j3Os=@ z{=@UZg9mXV?lR$qkZU?C|BRw@D?XoKqG4&X$=y;k+Uu6Pc$N zo9F>l6__`5ES#K-AwMw9fU4cxoKT6Xk31(YNCg1am)D>l7<`tv(Kz)CC@O7a2*NLL z(9y&Tj^Ty5&`BvAP*Gk4Q!pc%p(9pmeA?=bpX?~o z!QOs(_Nf4nt9aebG16gdmK8*BI^V!FjwrO_tSEea=USw^W4jQ>ciQ@Mbhn@T=fx)7 z3G4;QHx6Ir_patA?1@=a$LGEtJSe2te)<%Yggw<7VY=5vZ)D+i7hf9w23Q-GP!Ao- z{R&TDhvgUq58<4Q`_BhJ?60BY&=tRf77w`S*>geSJLKFkmZKK+j*M&%IS%3jIE~5R z;jQ+Py-nK8ob{{c08mUV9i6BvXz2XWE*?btp4mpSZpZpv>j`rJiig)XTn#%;T}0A% zq>3V+5b3Ir-li;LmCmu#bkymrwvi}Ziph~3G(ZbD{w`M6Iui0SM@5Z0zeA0Y^Pae( z-jnHnBjp#MMYh)?$mzHED}0S<7Z!W6+FG@fR9QULXHY*bb*r;jwz9c4c7kdxF%WS? zTPP_>&CfAPP_ndS@7Xvza(7N?xkHe9FfPb2KBo!}-vV_}M_WKa0x;OPPyjj~N)-BLLjz)8QO)T{hCyWlWLu$I7<5Ku3j+}_^4kMOAW5ZqMTqSs*3>#c5&}+xbVb{j-J9!c zON%7|u>h=U+F^${#K8z9_bQ?^1EH%wZi!I%`!DE#;4N<;mHR0I#l@Xz#4d;#S+YMT z<8GmA1wue{`?G`1DU=#Gi_?F3xN;2y1dhX?!jh6XI7(q-CpRTUV;BlY5V_!lVNFV9 zfK>#Kd2aP?+*s%LE`Zhz=kSk*la@`K?(eR>#SsQduLEthpv&&7@LtRaDyvJ1-9f6cLj3^4ThP)hu>AdlOVuo2N&-bZ1e zP=YDsqD8Fv^SQfv<>PB^Y>$NEwQCZ}LvcWh8wp|+(^H3v7l4*+PxMJK#4^9MyRGjZ zA|#4wo`~AI-=-Xh|K%4y3Yiqw|8~y1eD<6haCq#*y84G^6^pvmZ)*fX1Wk~LjKKZf z`X$gKHqfhv0ohQuN2zR!N{7M=T+z~gZH zG`~>P=0{%M`w40BO=&UWy!^SBOmUbovbW&Yi&tP{mXMWoUYwk)!tngl-H4J!y#eoF zB?>ze&65CJmar{WOD>Ozx%wF|g((f{?-!6A^!`njk(v7jn(>XrDPW6n@G4onsC>_P z6mb^fx^7QG3qmUrcDLQJSAiWDbX(2W@6YVV>0o-79&NvG15UBexc#BXSd`sttF{Xs z2)eX5`6Sa@v(+eoxTx&uHt*%j+{d#&qHH$CYhu{tQb2}{aQAGeX#h;u>{Gy_(^e%Y zP%4bTReiq!CV98K-h(wQ@zW1M_5I0#_*>B&z-9PvQI3!61LzP*kl1f%^i&UC1f4r~zJF*eS|pVE*o{C8 zdcKtx1SNvw%tcySZN0~Oua7G5$WQ*>nsoO!>T%dNme2K=Nk{NJCP47#b{b3RuLM*d zrinV{FfA&Z4<$~ex zs+Z)Z#;C&Hze;)Kwq7B$jjiV|A~VMV^8RDR0v2`5Zl&9*!$W{5LHu!n%E?dLZxpAO*(Hf4(u5|KUNcOZqw(JMZ1MR6z=X(iDGR-7J3AVG0 z`3M~x%dIQ3xTP$_V-f;8bLfkm(Nt=xbT-%4(z;YZf(Pum0#Z7(Ho6(ID>j{q!7r2& z;pAx=;9YGIh3L=_6&h+@8sDvQnP|Ra8lbh!$axky2~rI#sw05tFS)TTIFc(iLq?OPqb+aApXY{v4mUICynKU5A#P?B3%Xx5@ka z6&8Dw(aRevUi;`8A8{Zd{fNP!js#MkYvzpmo8Yv@Ot*+;dhnk#`eGJNC-zISD16+L=3We84fz3_r0wCIif&$}%yCGn5ypxH@ zBO^%PC4kkz--0~#YpCPXT?qzQqu1_G^~_7Q@FHZd{O+lvR39Z3kl=zOwxG=_R*#Zp zc!KCH_qiGg4d$Sz#hQX7ogUil5^_{M7+OFA65nn@A)@)cdUV;RzNZ|kr^8wB_3!!m)xxOE)Fi?yYLG|6Pj85(xU@^q;J5f%dwh z75iM)<`&R#=zWeVnS#GSGqCmUOO1cS*1uuafg)Q0|CmoyG;o0UcHl5#HCefP=goDz zvpqA6n$lBqd3(z_yC=ffb}*@)cpB;9k3=FWMHo4vtA~ee7j@0AO~aLRJZXxC=41q| zMJ}D;48{(dDV-`rJfX2@d_)^oO8#)Lx%y{5k{|7c+iX}?00$L#6^TF~00t2SB{(AO z$@d{EiE^^C+ilo50rKg^!@WIjgSt0iyCB(ZWo^awrbfH?7@(+4gG|1OV;Zx%`5eg9 z_zOr2vRI~_2Bu|SUuWP0o$wlB7MW{)BsD;okh3!DMk)hnV6VTIrN8ke`^wJzQpFt6 z*V^e%IID3oyb@*D6IGvKyT7u@H=J_sm!`^-K`U-Xvt|vQfR}2qG0u?}uSZ9e4~Xpc zi0s&e=raY5G+yKI-?DL%V|bYqie2^%(+UJ0;r%5;a#5XcZq$QV}TCoKI*;Ju(jpUO%Z;I^xNs=2kr0VF&9iG zVS^w-0gTKiRs`}zL0!TRF;=zdv3VuViX8GjL?sJ3Q)Al?KXn3hFKR&Jm@8q)v%j7Q-)HLC@M7Uba= z@#|8Oj${K;62JapupVaCLE+2MNH} z%`08lQxG}jVGV??@p6!e%X*nbUse>_+}N}QgeuONLhFWf{lFcK6GIp!&L;M%sjsUv zaJO}2N2d4Fg>$B*?n`<{wVx;?y#qJa^B;84CZLvQ^91d1v*_b+sV&IF-M{y_xf?dkn&U9;rTQn6*wef*yN zkvsk2!-sFm|K%JpYii6f`;{h86Ny2@=nrgf8U&W7_7w~WDJo_G;cf66Vm-4V7+4^C zi`@Ag@Vjl-M=L0>{^Cb*aM{_s=o@%&7(F_Vs*%A(`0nmYm5L}oP?2Y`a^os1+s=&* z1d&3_$*wZ|x`$$Ub}B2>VR{-t@z+|JZm8thQrkppx}1=_V`o(jKR%4d2}F4rZnLpn zJhJt}M#)>~ms<%BU`U;(M+5Op$vJm05O3oEzExw(ug*_;?a#tEz@Y3c*Y&&zD=ewW zKq?&Yf<&HUyg)#3lx*RKlNxv9L6O$b#BF+vCPnmlF_W?L>N6~7=iQe;V)_vH)xqxl z^yoGCb*;uHQFi0PJ`EKmN8mi;YTN)<_QUqQm5zrHn)Juc!`s^t3f+XJ{T{Bg?ap93 zJ3EQfG>C{&NZ$q0P9yCnWI%r;dff)^nA$hKmSkc|JW`KhyRFG8R%EPAH`EWdA#F?6 zi}ky`;C9+*;Xv+PxF57>wNbr(!_(8}EJ;R2hPcv;oK8a5C#?L+)hq&C^eu&>UO(U) zWzqje$HzB`fc1@r!|caRl7GQhvXpnvrNHN#4dZ^B4cG_%s(;YwGAUDt9T=RjtjSaP zPDKkeA8Wi8Iu-+HY#`uG05>^3m} z??mcblw@@l;C{Aa@I1rZF^ltRFBNHNGvMg>CNQfvVe7Z~KY>97_^ZUEbcCqgCD0Q% z)&yU+8>=kJP5#e+VUC5vPWX~yr98Yx7e6g@M@C1>Iq!jCjLrkFH5FvC(!GUN_S3rhhm=0vb4um3(MTy*MBegjTa+?qAiH3ehSvlMG*p0?xof?%YfT*A#~fODFapjG+jiNu z=AgByH4uO_zFf_4FoljFLyDyI-s!SW%(CPQ|CA8OrU)8u&!E-8Q&^gpGj#&t(yG{Z z+ot|1@)!0bpHDzFxO>z z9nE$6YKV$U3ozmz?nTwR>C@QD@h+iyYRcnPa-z<{x^L%y5#R$c zhc`kP_|I9x9*NmUGguc)Ioa?$T)vcjU&mg2sMsQMXikoA4-F$$R^9+P-~i17`xnaA#*Xe8D^=e3LZo2WpNeMZ8oh!ndCnn4IJ=&&9o5b?IGY68K`FPpOK0HaZFisOS_1}Joof;j9;!^8@T9DsUh<}usNaSm=zF;S8vc|e z2Myao^Ei+;RdKomRH=~0q)c{8`K{?=E+oSEl49>til!D`GFIrr@`3+|UPE$kFQLnVTEnR2IX3O{!O8}L zp=gN8fJ_^|Ay}70`A&l8xQb3T-<^+pkt)@`Es2Q+{W=K)m_me#-OVMFyqLN*ES276 zGJs2euJU`L}ajL;viB9Ji5moJ%d2YUYE;xXM_fPe|qX-9m9Bl+T64BX~! z3>@7J#CN_B0ihHlc3@cr{T4B=UTuL>3&b}~Huxorp%=-AE?WdV0R+0AP-z-!#7nwh z=VJ#vVD5#%xr#n4Bny5*aiGqM|ThKxRE(rEOn|MR2YEBgpQr7e8_5!UgXJKn}!X z$9Q&g7InkvIV1HWmR_>CJoI;&)INHj|J#SYxFQoHj2d7ta-Q+t=C9#>Q?)8giVmUm zjBD0eGO#$_qp*+vu={NC-VBvK6B%@XYc{Je%Cf0fW17T3J7S?iXn*ic?#sXyL<80w zbaD&mEnmd1?!-6v9RdT39vg}OBBrPzGYAP5CP`&tM%F>)zPFc0!mBsWRDkZ{pRe}AE=Z58hQ1DB31Fhp9Y{|gR%5AM2E4P- z-~V%{{qui64Gqlr$)8UV$vo$+%PzEM$0ey#0ArJM_<=@L#WU&rDT13zukSUdfR)C@Mb&*1513YMj)o$jo?Is!T@Da}+k|DR?;L zuu6_lrvFGv*DDS+^e6xL1b>pCfWXgQ`NOP!{AtKzCOo8P<-gx^6lg0NM=v)HUs!^* zrDo_yz*$&2P7h5f0d%;L#(zxK|2)Biwfv%gcIz(i$2_CMKWu=(x0&!tVSNVt=m*OQ z+{Em720s0lCY$Q>zRfaQywg?X6+6FQyS`*f=rL~-6A-Xj@LcWLHM)(NL0kEkbf~tc zi3?j+#(>7Vgg03}jNz}X>pxN6!Hxs2fRGf4jby(3IbiGtRev1Ol1e3>0p1I)vI$Gv z&VBPAE63kI2_cE)W;nIV=b695DQTt?aC6yhg(@e|!Vi0B1E`#mKt+B%wP#ypsr5(v z)xUr0(Iy9c5RHOBf=Y@*wMVepYSv>8A;ll9W2J}Bht3GR>qa&L>V)y!; zuS16O#<}=#FYU|N4P^21?E}Glw(-nd_?d7neTuc9%X>;#7u#K;vsf zYR|a%ccI}|P6v1upZTAE&j0a;_isT~VVO$hIds|cXGAaL(rkS9x2SQ5e+! z*$?{NFw>ul;$=`cw2i!fGQz*zywduAE-r*%4hT!d++{9iBouftefOI29YGm}4=$FeCR2i%e+%pcKn z@x2=i|XMGoc;H~?lK0Ziob<;UhEdR@r+yCWy|M7pog{yH>1qXTbnp)@6Z#-R< zqttqb&}N`=GAAX&lB;uiqkU+{`M=QRXv?}r$WQ*y1Lz-L?r$%kiD{ZpCdN}Ia@1;R zwFgjI@fkc}eRP}GVuU0Om(10=>yyNTW7U>FX$9ovu!dy<+Q)w%YyYpmfumOvAeR=`+;&^0H0-@l&U|Hrug z&!_tz|4Q_JA;y=|G51u_K10VKz&L-D>fsfsjqYbgXM_6CeAoU+2RCVOhMl-~1E#%P zKxy-Dy)VT(4M)!=fzRyZTZ7dGtNhfwBoU`R=w!Zoi9`&qM=30L(3Q#)-Qa;?Cng&H zZ7co1Jx!QGf3BQYU+*)7;gu<=RSL{!RkftNgYJE;;?)w8=jZgeA#6~HZI&4_q+knk zKdyxB{o5jE{b9k}GZsZNp=Sj@teOQ6 z&}aqs)c4^S|GoPvYfVi>*)Nq#_Z)&;^KX8+j-b+} zlz;Eba#+KHw+P4ZdY+zcu>47FE2T+I)SHOBl@&emV0F-Ru6o-Z~gqY?#0CH*tNV$H%+); zjB>W`pjT8}$6-Gb^*;Z5Z`v7an6B7c zUCNXg>7E~K7dNv1IPr*a|9aGCy4uj!uY%6x;XZZ$-x~U&J2@iznJX$Ui&_hRi8Nao z=1qBWH*-m2R_Oal9i4dt&`YGD*qC_8zrLIQ^5*{SkL0@VsfG{krWgoqyEF?v%4aqj zVb&6QMai!!>pbARq4&7&?m3u9YiDkbyMS?4=GlKH*8FWc{BJiJ{Oi;m5CN+`Tq%;{ zyas=PS6@DCma*V;idUhi>`H4o9{yQiLf;0ljG^MEJHKin(A58W;BOcAzdo?$#QS~i zpPlocs*oImn+&J4PyfaxP%$`oPM)cwnFNzetfG#@@!{1k9?b6LT46otSO4yW(7khC z2BULWazZO$t$~<8h60a4e)BA6YZ_6cJVZg>L z_4r~dbN6SuThqyv$ISM1t}TfvoRXJlnZn|)h~S+>RPy})y`4rOF$fU>I$Gd>-k*Z! z)#c;P)*I=sYS2}h_#~=YqkgZaO2w|ngn|)&f@?tAP}X|&Cd{ybOJu#DZSCls%;BN*Kk62p)_qO>IjQBZ65*jqbwYcD7*fd3jWeDWTpM(+}L~P5tm6$jw&TAEbFt~)|TDa zP2=7kp^b_Qnyes$g^n%3>_Yo_`z_n(`{=MQl(V6Xs#_+15}((V|F2*0=zGF-rVayI z4?naYuB(Z2K43YfeDwmOoYE$zZF4mPjD|3Q)}W{KKO9ziosi>( zn=8R|%1uA=+@O|wU9Emg8hODXh;Wc|;VDad-9pT3>zmEo|FAjQCk=_JC4MmF7(2_vP{o9k#^n_q^)kkkSF( zFWR-tt9Mr*i8qXi=ku5U|NRYKcX%676Ccb?wqO#okmab1-&a&^fmvlyH9DAFoxL}< zJq=IGFv-G*=*_uH(sd2@|M#K$zt>N_@mrAXE)wb7w6JbMxOpYR-;hphBblBX?@t~T zsc`9&O2KnAA#M3n6Is$2sc$dCB4L)yj2E;yB|XWehf3=F9pOR1UD*Ex^zwP z1}QVjFgcA54v#*~+kdw7b#lN7Fi0mCf9vcEIjfWtN}ez+(`eU1@r`6|jcCd9PM<7f zwHkP%YuD8EE^VZ5|Iw48Zuwc`MdNSbJD*luBM-h=VSQ_SdA6BV_r$eH`;f>~LoPo? z?qfdc5obI`0>Ax1WGked*-NZr25`GwLuufbH8-WZ&PA-gq#4@D`A?qo))74y<*)|4 zYwm<|ewDM$useUY_?0NRHqER%Tq=!6f?>Woe$i}M3~S72y9TeV_`oVz)uJpC&&Ab; z4aZn|=^{{n_@LWj%;x_7CxTq)RZ<(hxG1C=7#E{vlc=VH9!YVKuF{%h(Zcj>>11?j zBeS%Z>sG{{?WgC+mDSa$YxRM0p>Bb`j<}+o7Q|CLvrLGmd}!Bum#cHNFGIYqsp4b) z?BlK?HStY0(VRS(x@=o%x?`fYq`XJQzX8d)bJFznqeJvo0CJUWSW5mfdU(SdfSPmC8Y z1b5+%lC#$5XmP0-OwMCV!4^#=dXuM*5FCO;c>gSJYNEGdYA=~Z*ITKXo`1`gbk3tj zQuD}}w~OX)@fjkw=fO~o4LsmB%bzVe!rz)LeJQfm+3$9d)L2!MgIDmD6+I(;b%`8L zd-dS@GDiPw#E{#aS24=xHU99uWF#eplF-i4o3)Wv*%7|djcdUq3r#v4)45QWi+a51 zSE)0!;~LDu9uLK4BBgHq*{3GMV-CE~&Zi{^NKVE+wB6~oIk_VdLTSYLf*>Ndrr)G# z?+N_6Jue^MFDowo47oo%I(up|!Tfp(v&dsG&)>D!VD8s%ndZc-mbls4s`lwxsxb$+-9#MT0-v zLZ1Wt&60iy9s1~P#hCmkeHq~@?z>Uq$$*U-*1z~Dn!ip``U>s{kMA+=+ShW8snX0W z^8fcm_8;#K+-qVYdwX|6-aWwx}~mNnxotIoZ3a=3z)8h^9C$Uf)F8X7nA zoj)n-&(2VPoTjQOj%2X6RySuJ<(gCsovJP3j(ln95YL3DU?%8X5fo8}$uT;&N`J4^ z{gbq{koIxcAE)hyc;<&QIKd$5A;-lS!d=X;%W>&kG;5Gc5svzFm#e`OW#$BHv8+0B z^FP-4fB(q&T?V}=I8XMt?$Y5KLKhvG>~NO(tK|`5FReuSXJK` zA^857>>ShP(RowW_p-)~B3f2mp^Z_kH+dHSG|RGXkVmt;avusAWDHjMA=nry2jkBb ztZuj1e5y@PdDPuD zO@2hAwO?t4X-6&T6>2D3J`vG)^k-4{iJu{(46K;bR`v+fyo=yF=jI#HXB5ZbNe*1Z zH%rneV#}5lU5M)@Sz3C&iPiMaPI(f#5uC-nbEea18)WFt7?DwS&ioV?J+2bPZpBKR ze9ppohGOGUto&|spR(zF*gF%KPAw{XjrRv7US_yV|Fs)Fav9cQv;RBf#4 z+GsvIzj5JD@6N#9bh__k`Fu~D1LHFGHh zW@X3zhbh)wL`Reea3^3=Wi{?p_Y~V>sx1oV+(61n`|!(#VY_)k)-N}j+c`IR3aUqQ z|JmX{qhZ#1mj#X%^IjB*C{Af<{~>#|A$G=>DViV762aQcpz=zlu_XPd-|HE+KvMYs znY@wrVw}Gf=89iXUNCw0ALR!P)fp$E3C1f4wW`HM+%lQ6!X9{G4Ymm8h|rr6*mxg5 zlT4Af_;;*7K8jvXt&VoEdfK%m{`2RrYs0wRVOwE;%AE@52?Gq;pZFds`O;OjiT3@Tlk?Rx zL;YAX}~t-f2wpobJdO&b{KZJfJ@U zh3&0=&nW;yw>yC=(3ceRIcmq|01@AeSB*=dZE>onsYQv!UghE3%y5Dd)N047TzT^! zl~c3`2=MhosL{gwT$_PUt!2)mgn#>LAj~?Lu89bTNZQ9ooM*m?#ZewDB8xnPP9_8Y zktK>YL`@mLs zp_L!`IVUGUI<1CcG!ES+9xn7>Y01&8(6iivAu~bFT=dq~&$I9&m#RjYg5T+Ju?EXo z6()IV%ufV1NQ-G*^W!flzC#j8Zv=n>3LnsTu$O0E`hI-8MhkeNv#%ak?Ehk4$%q2l zL?=$FvVr`5%j1R2FPbdQ6A>z&!S30n}hpo5lMdsP&xT zq&Lapq=9dJKrv)XG`>pS!D=?j90{^*JUukMLW(@`DpoTl|lLpQ^j#r4w$ZQHG zLM!)kx2WLfGI1HD%?v_}vvKirak}-1N(mLoC6p*?52H>?(M1FPIn=;1Z}6*R(>(00 zvk~oIv7QE1;BxJpRYPM0M@oT{^P_SH_kJ2H5O-Kn$Yp`I8FxvYVKEd?jjk$U<2QRz ztnyTC5mo+MQW!;%yH*9JhnGk4RY(>Q&)dx~C9bCujS1=$p!JpxRAR#R3m=xoqEw+H zOc|>MwLt}DHET*JS6t5h2S)RPmfDuwGOCa&;$R@|M{loF32ij*VV7GUqOy;|;ue`} zFZN<{Ah}DrmXh%d1^@QF;A7iQtUBIs7h~3{GG=C~_vqOxDGQl^`|b*cYWpWlDjn## zh5gs$0!Uf#fs&h1{sa`_ks+8h?dZ60_NHhgS|%warTVCz7+~F|AJkk;xR(HqEy|lZ zQQii2mPB|$w?nxTYgZ}m1 zfhz;@qV=SSwrNA^F?7rVklnS}nrl@hPr9+G&oKkB2hJR7B|jgS zXuxFG)V!BAtC6o7GFg zbkdl)<83i2mKg#1j#5ZzGXX7iiw2Q|RPpuE!h-KsV!n_^XaR+U=CMH5-Thf{Uma^bpkc~{=M!x(csBIa00izdw?36k z`#b;k(t?1_tkwWwU7vhyNjeQ%WXS+b`Ye9TGzK|!$%#0%83?H)d`KAl0iOJ8Ma?;n zCPg_Mh!s-Jo;xn=BaqLIxc^{HC-g`N}2nMK~P5bOf(HS7-*-G4=8{=E~>kd{V!T9J)Hf1XpE^kxGYc}^!0{1|Rt~Z6) zDpxTOx95G0%ynuB>ztiXjWg(O5T{pX^ZJQ0awOOI_a`9v8nMg z3!~+vrI@o^SzdOKEL216>WmXWync<|)XF$Iv2`@Arsn+hq@0zNez1B8nkC!MpTi=b ztz3I{Dm!pcBh3 zW@wx`<@L=dK6*R~ae#oseo{05dBoX_m-uK+e4%?5)m5N1pe)rp~m z!vi9~y!;y}WLtjak=qrX}~!G|M$(a4)iJ(ajmMw`>X19@h(nD#%(cvO8YHcF;0 zLQQc`WFyqkq|AcraNaBUD63UKNc)!*(@skU4*LU=VW@p!b(n$KRqhRZ4QZ3Mr}p!o zVSE&l68+&rT|d7PPGz&Md9qKP)&9IX^!YQhU51;Y)T8p5dY#R!-O%jnU!QcZ)Iqa! zzkV$|-_cj9J$`9zygtg^eslo%@Lnz3J4i z9TL@R+g;0}l{j-S+#*gtL#_zcjuYZ^2rIQg-StPujGL|7MMYcvsFGVzCtG(pv%>?j4bl$((Y@Rq7)|S*$dk;p2228<-<~>uzq)<@P6rr; z_5ucj)r%|kU~KM533QAqvm#CR;!G>@nr1!gmsTyqU*Xo*dc~6cmqk_!G zhB{TWqkEWw%s>yJaa2|X;(u;6oCi+nP6BhMLa|QW@E8~0;IG5J~9L=O`zSuC|zGF_$ZZ6n}oqX%#9Sl>$Uoq#2j7AH|l^{S|>?vz5uLqHk>-!xIRYd6zuhIR~uw_BX_F zt-Ot}D&Tca!oVST8?zyT$`&pZ0DF4sH_ILZ$lkpvG>&CHEl+_lvBNBso*=VmMBJVr z5%blrcJ|l@#CphY4?2GYE$R2Y=IgDDa1m&hk{<@!Pg%{V0(wAuoF!COYN1<-^jQgs zd+_{h3p4uQj}}utG$1Qh;x)iiK$%Ydd{&8^v5ETr^gB?!ziVcupGu*~LZ}g3l`BK# zw2xrKtP+OG4$OUY@Dt_sx~{HrLgVg5)J@C>2zXH|FMTNW-ifL70@h*5bttHC;NZUt zOw_7B94~^oZ}0PBQ&@#|`N|L%ZMvL3GBp^EdJ;royksHJ&bS|!|K{8dT>1G4Qj>2Y&PKoSky4&}PP{G4K5N)#56|#-P{6N{04g|D8putK}Vz4s*H1EmaL+FU5G=IuK`$dY?nNttn znS#MAuemdA+0M9t)80ShyE70OU~>B1Y5_)i4b{dh?)&!-=VZfLj`gRb73}Nd6!5Yj!l|7mMV6NtC6$mEV`DD!XyvB7uKm-$KU{n0~p|#rw z%Jd05+o3It=VXBIG74%F1jOM5f{N1({I$%y&(VTTbwNPq)dftiv@2cDIzasXl^Ch1 zde!syb@%%UoRd&^(V!K&2i|w6h1*vCBu`o^?o_LS5z_bCIs}{tgMxr6T}sl=pR#Y? zNIiPKZ)0@HvPmA)WB3F6!mX)IbG`%d1#vwuk0VDufBm|hrYrrlgvRL(kslp6-JK~k zt^gic*U3kl%_+g|tJpfrL~^JrnxeEV(Tzf_;sU4^i%k1a?FzzpI%4)PpZ4zAX$b!Y zw^<#@SEcR_fxYwI5Rs;%rFAvMpI8g+P-Vo_(!j7n=&R1Zx1YN~Hn_J}aE1;jKQPem zY&F_z^=Pq@Ifd-Jgqo{L^q%igdRT9(ko%zEvtfohWU~6-SOyfc7gM`j;Y-~3;5zco z=_~d|M7_B5UuP7HsBNjvck1kWr~Sv`;J*xq_I)?Jj0lO)w*j%I!#PI*@7y)Y7bXWJ zGA@B=Lq#@IRdX>gicdy3jU+qQ zY)HcyMrev&_G_s`c|3T44LH2PfowzF{>TIf*0O*?Tt#uTq3suz$aEm&0RxMFV9eLR&&szAz8={Z%eSSgfAPrPHZDsOM^I7Hi7k{q z1mu^KlOubi5OW~#<;$07gtclusMi4g#IhgGInO~_f74*VB4B~oLp4>o!ZN)^r9mdY zi)Ff=iLQw4NR+U4&SuJLk3J)zBA9slUVpXQ62mj-5D;ptIl=`~c=kAp5(oEHEw%OU z951)`Mveay26tmq^Vy}7tE0^6{$pe$*07L*)G{~dRVO3;{gcvEJQGqAwVypJWmrLh zoCr+U_kX&{`u@vV_-!aRFYoi`&!LlRrw1=x;`j!o82tm%hrgrV zxQ>AV$J6iMd+jpzB}h)a#x#6KyL{D5Qxu_w=D*v~Zb_#>9@3-*-2q8d`rzG1Wls$L ze!fkg4-I^C%v!6e3l5iQ`D-QvODpQ5Sg#}DF(m-%7#th~H;D4Lbwh`es@TWW&$mKj zg;bs&Do$Xt;^ch^dSCV4H5FMlFOOx}B~trf%|KN*a%6O<#6~w-g1jebitFm=I3p%S z4XnTn9Gt(Y;@Mx~E!>lEkK+m1j-u~jVEI{t?CnqN1LU!UP^P`mz~q?vV~@r4E-yxd72ct2A28jB z6Yi|@-g$f3Rn-4rmo^?i`~I)18Yhh)2nKAu6#fAJroUhHU0mGvykw8qEca4M@*5s4 z!6l>7pV-_h*S$CQiOP9!t2K)(*AAn9{*m<`zpRvz=GGj>?tm?#m+Sw2Z;7E7h0hFv zg>s8&^_OPXhnQUSUE{adyJPOVu8?pqQJI`q+C*Uw0|B;eK^RBVIJKC$f(zX<%sMc9 z#&-r|lN(A%Arac!1Wc82IX1d=7IbR8oEqF~JuUgz&7x-GYOAA6&A^B9_dwP$ahoq? z&ju2|#h1^sjWZ!1 z+wU?zKn5OluO;pk{w5Ip5xem-?Tx{M4n1w;J9@B&k_BYgLJvgQ2|eiR?*43+>hbvV zmr{q;p?4Q(R!|B&YZ%oyS|Jt;6-r>3!$G92QHF5SA!jFV6;s7`I z%fUflK_Pr&LNQ;CeH-d+<-d3Dp1l%Bx|!wB(9mJQ)A6IbtlTqj4+jpObPb+TL}Qor zKX^gz_LqA;s3Q@d{!S;VuFm*Q0WD??Lj^jZj7M&SbBKR`_&keX_=*`otO`m~FLV@j!*82~j(R|}Yl(o~N(ih+uwYL-@v!%qm$4t(e5Vn&hK-=2i8Ygqm0 zvhM|IjP1qk!cqK@mpf6jO)u+q2X!6BN{%vkF;DrvnBVRy%mm;<%mE6B0fXH8gxgX8 zAFWNRmP4p&rBkw*;>c0bx7Wu}IiX#-F$G3o!A0;JIN*7oRfxL$2m-cg`^zDmbRUfh z)AJscpEJEFP=I3P^J~ln)jhBTcH!q8Li_s~sI6btiW3-q3`xq!%zw|$nA`Er2wz14 z88I;UFWG!W+=&XDh&{cio8 zl7D&6?^)r^dUGdC7Dflv`(;Uh*S<_cSq0Y5k$cXtJ*<-zar{APY1sbBi-?$E=Ejk#@jK(`zaW1rwL1$_`@ z$}T_VTC`>BtCMvqPkFTAYDw`~+GmbbS9|+ywFb+g0$0WbY=1 z&y4`!1BZ2I(gi=-zTKqPJn=WSm;pe95^7S(tkQL_OI{rhV~0O98h<)JR-JX|%|0kE-*HPqe*my{jN&P_^4)V343wReISjTLZu_Ss&JV zxPM?ZtMQm!&I&t6Dpx44qqPa%GNmGDq87166eePW(tvQ?>$(%Gf=;fWzrk=^Mr ziYNc(A_$2#t8b)CDQQu>+sLvfa=@U=0t*F$o{s8dn7ZNZauzwAhx<-V-2x2FN41Z26jJm3yNbMl1f|{y zlTF47hq2BnPv~kMlnMFH&1$d8!TyqzOf`j8S68{<&vNaX_xcho9Cb-oj)vCMJQ5Bd zSw6@!jW41lze(EaZHde?FMnm?RDDwBLJ4j?j%7p%POj9TD)n{ER}EwV=#9;``)%WW zBQv2<6ni0hTVPYqFZ&LZszj6rh)YM|Mor?#e*O(;IK|v{?z89I2x@hG`eFBcoLcXQ z6mlyq3X|AR8_G7Af5*Z*SAihlVp5er>w^ezDI=FAtSijA@CRQ5?68yB&KtRky7rTE zwRk!%Y@h5tAPaOD=lJP)2@t!WVwF3dpY8M&I>d_7BPc|%u&|J`5>iko_d23buE0Vq ztf+`R20vf`mO>@S&T5*GnOUpd&LWV%vI-!SW()!47yM3kMFk(%@#Dv<78Xsu6?`{% z0DAad$U5v@atdd`}Emwg8-Zq`>S3z!A|S8K{3DcC^Z7eorDY;910yR~0#Djm6gGxFe zt^(2Vxt&&^!^mCOK`=Dz%S2+(ECK#y=>QH-O!)A3yFr?9kws9g2^foys4p}}wd>fXe29&aG8prtAdWGv~5PlxgPU^tqB*fo~tAJy-vq!aEYig-$PPEwh+`81|(Xl zbG<$eU9Y@WMEeN+x@Wiz;1UzW&m)~h_U+PwQD>wt!F-#xEJAH0-^g3Hv5l8Gbye}U zjcHi*E%IleK-*dUy6poWt}m?rOlA_NcjAaKL51jXJs+Q|tQcd>N&T_l*IQ~vv5jw@ zN=D?o7Z{Wul+^+@;?kw+Y00;ttoGCG1KL7qGpOBx@TBB7m;6X_Nl9y#``ZgIR!3s? zjvl4#$;9DTakQ|qpFbG@$sobZl4e%>!fjt^ik6)rmkx^V()^;=qvpOL7Ns5lFCY5q zXfK<9rJWl9!QCFFN@7k(5baJ=375$55is-vtv}@h;%1zLuvgRgussmnL0EA45LY_f zN6oYWj&k9`R5KzSItFq<+mXDn(;iq$(CIrKXx3W$_VSh)TR&9Pe5fw?WaumV>PX(g z7^<$}AlO~chiIl1eR_Sv$HExn%FC(h1s6H({xjaxyEXao(qhqGt`ud{BMTHD~AF(qTG@=faF&836~sKRoZe06^B#=L>%Wl~v5$`(`#fN-;am#t;*8LBSIo zT1c&iXyMp+RsAi2{zja7%^j*C*+M|nrG;DjHShFa2v@2}y$3rWh@82$Je>S4|-a1HbT3>o;duvNIIZ?-{7Qv+cN$_ozAn zLs^g^tUQssg|8m5pxQs9a#nD+F|?ow)T#iMh@F@%@9jv5hoHy*z2p0&%lsZ_sxr=# z0ayyMMZfs__7CKI2^Y0u1qgRc`2jHEJs(q91!ygFmZJq`K!TFHF$-rI?z+EFv6*jH`-VT= zH@#eNWM{*7Q|{T%C*$R%o;}7@F7$xoF)}qZXAHDK?p_*{Cq3U!siUo|p2$PC1L5%- zP&0X`#(h<50yiHA@5B0!WBVg{=?;fNMj)y&+N9?JO3^_14Lht zzJ7sbiLSug$PM%>ivw=Z14))+!LtB!RWPf0LC-Q?0gAsYfWfLat=uPQW`bVSd+Ts` z2xwW4rReVOWYF|%Y}kQt$$8?muZ&Jl!q(ZUBOQFkX7`%QjgVcLjSLrnRcOfXp?4tB z1UI0c>W;O6+Wyb}V-cDOhg(cg$szOGlkD|-$oanirkX$|bM5QU#alS`V#5F91j?PiTw&NWp!MWqn}rr36qbVXnwJ8(s`eUb z^mTG_2he>zZGJ}Gar`o9+Z-oC{zhgZK>s%!*iF-4zwdq$M*21X4rG|3sti*;V;S0) z7|GD}2OfO<=6-T-&$lseqRG+=HVXwVc>Sc3?N_0uYqadw@$Uczd2V50;pfOmJm{(6 z2%MCrCLs@ztKF#0J&fe(6F5(@VX9&bxWVY={*ICCoe3c5cme4mo>*vp0t1K#yQ>pQ zA0a6uIvDil5A)fU9S0hy4ugJ{T^9CTlLPlvlkpK~2>~hl64pL`%KJbIIVR^ht$N6l z$kKw3euIt;@HtHw%o3jZuA_z!A7bBH#5}=sF~=eZ_aP0kQaNpSc;w}J2C%~k7!Y{i z6+)p07<&(}P7z#yBOz@L!M``v>z60Lu%c!B01!7BKwj6+LtQ5dt6A-%?)@j;EqZqL zIERPZ`X#0TmcL~j;d1d z&1=%qi&6WmSA0mae|x0hX-O9XEdhzl)NA&oB_w#+i>q?dN8WSNqc$HmlUm^a6Xi!9 z9UYb5XyG*`R=QtA7Dqcy9DfR055|!FD1Xt@W?L?p3c>5yvuDk;(*^8SZ%Mr>%&(IZ zdjNatR{(MHbz&Ot$W%^p#m3=&2KM!!kpu$g(H7ZlY`m%0z|q;`m%aK$oa*=aoG_~# z6HuA}<>@lG=K>rO&jd_9d{RuQbQo*OF0~c)`rtEu;gI;};n8PJ`JTPi(QSw=@n$_V zyAackVaqM;Sm)#tv4!tt01RvypgZB+-E4RuF`3Q~I$iGrP<*>ED#`+Cj1~rFHn@!L zY(Ucq1`=(BH-&-TGzaybf$}@T`nY9FdV@>HmlPMzexjlS`1U*^m=h&1aTd$iVtJr5 z7ZStLoJk)7v|wjJ|KmoWOp5du{Q&#aI2l+_qQTYp%>ZIaC}nkJwTTALK>0zn0AfC+ z{OohB4`Z7!>a=^gLb1C`hiDj^`lo>dXQbjZ?Px&1n4;74kKp|bF;P>G){{WsnW@sg zrGcJd|F=>5N!<>zo45C>fS10YR^O+v4t{<_#hJ6;C=!R|-=6a-i2 zj76n(BHlV;_9vc;#-C+kKMgwo=8;)mM#Yln_(B@FR7SRda@pN142pziK&E$U|17hP_Pi8uLmTZ@8u z#uYpaejsmpY-1zuGIK3>zHk5_0-|{)rEfsT7|^Hsmip`lnqE=@`WyT!P~jXxSBR5t zsogk|x-)v~Tw6$KpXxE0x$1pW4j|TQR@)Yfc%KKg5S(+M`~SQN;l6t}74U-jMlku3 z4Cv5yovpp6f%H`JP$d!`?OYhEbmZm4ad55;oAzX+q++5lZfB5yZPA-n8-Xfw7)uDC z9t>ug5M8L`MTdW9+)M?WP0-{SX=rY?aDl2{Hj)CW#7;&3nz-HC7>Wupv(l7BYpA-C zYm0FM$AjghjqiY9xw}4--k+t-31VCqsJdEt4b?lu;#9ALYdwUS{{u>0Ti9K5IaSt) zeCUwoMNac#=3uz+$#mUO z6lDm`yN#>1=TE*rY%#N7WUj>p5RR}Z7`C)&XQHf)v~lg!Egk(V_f^G@@Y9s`QB-@Z z&~NN_G1BYw^p&qn7;9T<<#a$Iz)-bf4uMd|=7VEZfG!MRV^m`}+`pxvF$8wW>j!-~ zMELYcwqQ3pnp%Nck~RbUzO1h~0*p+jr!#Jy9ehlVnvX6%hGnN7`Y}xI^v%-)F?K8b z>qgR@jD@Zg1{VO6=p09%X3;X;x-#EgYFtbqf}Y2{s`A&pW>*2EqM{PT4DX|a3aj}h z#HYt{FAvvp0uyCfV)gabBa31Od9CN)JyGGxk{YNLou@nU5)P8#KghQPnzF~ z;*(kihP(p}Fw4d6ce@)ysXvqcQRVj8``wdhs1{>^xqN~V7q_>SXrMk;kPQ+I=jFjK ztl1d>S8F{^PSD^>A+kQ*u9m)Me>oFMsP6j{?y|*D3<#e5=_p|ahw-|1jUizojsARQ z)OK9KDRadjdEgkF$|KLh8}=~#a=U-3k*SQuO6ggR@- z_wT!KYzELHzFX&Ol$e3Ye^kN9W>U!q7J{t&x72T9J|)G7{&jr1K{K@w6%J2&%%;By zUE#fv7(n7`eCtp4ICbVqAb~54Q?Lzh*(|HEetdSz`8EWYIE( zvasVL`A5ad>~XPWWiJK?<$rW`f2yi_Tl45BF|dNTGBjv zO1`Y`k(wiPoi^8<1J%UEE!aRSOCy|_j4V@swyKh#d9OV~&F6(3enyOE1tVfF1eyUl zUX<#rC&vH<=ukBr1fsP{8s@^kmCOEn>^gH}!D~$wWiti%MvYrV^D==|N9py}7>BB^ z`^%;aQk5(iS%?i&P9<^{n`dn}k7$B!N+6|B5!L$h`#t6LvU_6{!{$2JTq7CK@aU0% zqpkyzB$619fnuWVhCXbH#_mKB*DCg_Pyz>v)0z;znLMB>qhxH-(6FXl+T5+;zNSZx zU2n*b7G?7Lc(ZFU;@VT4Q}T%Yx5{pdMV3QaF8jolp>Vf8weSFca*4f>>yWzdcND=K zYGl$li}hmOK|s+uyb{3@Kt%6h1?`MOVO`y#srv%a>z8vJ{ui%dKQZW-PTwt@GkJ5o zn3rpN$0RtOS^)_<*BR)$yJKma1_5z*va|;P_{y-1I!glM#V1W)(R z{rf@Opj_fvgyWzZkKa58FK@nlu`vipDBGvhU%1j8>k&~NCe*=J^ z?{{lofXAAsbj}7YR2vR{scwLiVrIZT0XKoHz>S24=wl{utSe1xN>FgHy9P4_IHx$4 z(Nf;574NMzZp>K$D8t`k0#1ydNWuVSL%*Sc4wG0OuBvhIX($ngiu(=M(_KbsG4C8+ z3tDX8G(2AJxAarols|;}>%84gUHZj*z`5M_x-kUMgKd@tnJZC%`Ce{cMhls3VwH9% zqKb7R@}N*k>Nlu}8baY6MFf`p{O79sT6bHIAofm~d|s&qnYZjNK;S1(WE;nR+V#e9 zce)oV*!ZNRq;q6sobc4c`e)@Tr^Exuc1;B5DyoidSCPUm^6UXXUv?I~1B)EH9_Y>Z z_ozevBDGSTQ^0zp8P6!ma0Wi9hab?X2iLC*3!x6$%pF$=P?Joc=KEcL#Bt`;(UZ4L z?#*wXuy0w1@+FOd9;((AWv{jI>L|SKc}tmn>m5$Mll-Zv5U3O$ufEA|iPg@_NKET_ zXP5p`#3RGCa1Xx29=2Qd0wnd%*zgTh&Jz124rvSp*u}avGytU0GBBa!?)zFCZ5m0A zx>oDqc*?UWl4W1F`M|Rs0<8D$;G;X%^-FZ)7%xvbI7$^ru$soI(5}4lT%Y@%o&NP} zO&Cz976(lEP>Q7FU&fWTLjIhqH%e_Uuuz?Mm*WBUDH83n^7A`L$AjJal*2&>eejbF zkl{8v0t45+MoUzYb$hHaE!{CSlbQ-L8%d)QkG)3+oT?u{fKXh4JWiREGPa}Gw~@8B z?2-@iJ{$F!gX_UJV-HifR|vRn(H6&c*jcE3aa!wW|K@o(|7M9z*9A!_!)4S&RK)~k zYHO*Y$+3>SaW;%yNSGrNCHTKeLk|pE`tO9smfq*B(;gS9c7^88v{j7~G8=?pRajMg z^qKSH!cAjocjT(NmXFTYK4y%@iUgB~1uk3mfdUCKzjVxMsc0>+LdiauMe(^ z?9#jq<~Y=rY%M!? z&j_h~|9(sl&MeqI@KsJ{f1wh9pX-Maq8>Nq1p%3-sTp-3CfWq(7CN~P@~s5JtKP<* zlKT*+PK!9%WwgC0=={9H6H^Ki_~|l0YJ@c;I~!wyJaPV+qkL#ul@V_se#VZRyl~2}yylR~62l?q?p`KCZ?!-&#YRI(5ntlANyYs!&o_ zqRlW}^<3}%MV!vg`y48RHvTVaN_VK;smo8e03@iOJXQ_kJkDAfwudyWOPrfC(=WrU z-}v%H92S%?csKan-NC!WX()PW+y=Lb^dpn+s9f=yd@Bd&eZK#U{w%Vf@v{l}Tn3#X zmL0fjUcJBfPtr%Yrm1n6)Nbje()YXamo8mL0h}uE_T7?+;cB7VC!5VjQK<-h0w!z~ z)h*$1?v(x##yhcItsZ7v|IFQi+U)=6IN`)J8XDET@&p-}47D&oMTf z>OF2d*TBW^z(U5=lpl>myHcALkPjZMOz)6rMCZ@CqrH0R6!kCSHWy9tN0Apz8$#{U zZDulqOx=1Ee$~i89(`|Cc1sqjAU@R(5M;2Y6*>`k@nuwG2BPQv zmzIN!2^uQx-@{D?CbtR(zhS6{XbIh`v5i;vcEP*!?cI7uRbjG&=*6gel! z^u$e*zeDwv5ExnF%5=-_?azd6#*~Yi-^D^!?eM0R;auZ-+xzo0cnYEbg{>%~0g-5| zc~uPXp*ZwIHBj3FT#N<({~$rbITK`^^vt5!kN2flM+Y*hxsg*803PuyxTAkP$T-Fsv zt2~PKLb`C5??cy(Ig{_-S0&AaSj>F;c;l3Bld(x`{9D6|KnVW%sY9S85r7b2@ND^K z@sRoiVDUU4F@rv@=Bl6QVXG!?MB96Jt6h%d#S9Q?eLq!erhD0jmh0mRe)w6owiuz> zQ9#ez0^|lfH@JKn__v?$Od6WOa-QWx#MHDMAib-p`IqS*l{?w2viZta4jHP1+%r^8 zF1H^o@oPPfev1iY2Lotc1ENmVziolb54oeW$w$$k(`;W*vzQZlz$x4~#IZgRzK;7v2(LQek5sS=IY3rhi8I~ErHq`- z{v0Ut__JLob@Qu15m&RP;eeW2mwf*NK~q|pCnNo6my4+~x!+poKv1o?7+1BI z`FkB@1(hz8KZ`eP9Nz;M(0VzPvR3Tr|6~+xT}2y{EHb49;WTM-7q)h?^YTuFXirc^ zBDT;T|K2+6!_Sr#=tGzW0Sjp5nf=)9BJRL+f1ig%jYLj$ zk#sjfQhS_G`%Dl+a{ynX9;N&f_Q7~tFgMLy!RD`i*H8v7vIp;5Yj?oA{&H!U6RF~gCMNLd>1aqIM`>Q|Db%$l{@5Qbj* z+;ptU3&-0~%f7r_&tvU7+@M+nH{$(`ivlJF-4flHdrPs=LcXeSKRo?r-44fL_Ct1n zMnFyZ2=KG9rG=?aAkd?U>q%7-6^%x$U%u+T(c-<7(LUL?c<0gGrcf3`xyN`BUvha7 zRc9Ghtdx&5F=<}ZPvx>krE@Tpr4-?{izFRiJx4`KN9>8ZoXIQ(pLhjZHI3i5|uU#2q-&3JzW z-F{uq3hL`~{@vT80g)mIs7Mn5l@b*N8=|5j(m_E$x>BSB=|~k&I*1JwqzKX>)X=0Ty@np?HK8SW z&&>YLUVH8TKi?T^3>^a<8eZP^%xBK~zV0l8Lf=SB@1Jl)G^fY>Cng4Pry$e0XDc1j zqcp&Q(%pz7b${xh3YT_G7CqU&9WclY4J`Bb#D;E6@hWSvGMiiMn>XV-&lYEW`nK)W zf3$DJq03wr?h7-2&ieWR7I3$5g|CPMS)TYZ(90fuy_hVgwF!L{v#GE98EZasiq?__ z3v6NFJzdgjHJH9&6-LR=di1WlqxZI}B8S8tJ@VX|ItgvI z8<}su)e!9As;QPfvo9bIm%GdFe>62&*!bRdPSKRyU=Q_+key0m8)j^qArM}biuOah zcYRy+i%Git7%^$8TR=}xdJ7HpIqsLauo4K*j)*DPbRj+av-Z$|6K5|dkj{605K=kP zSW=DG2Dzn(+JbTc#3Qc#*dqN!mBDyLK!DAbhfCb9sKkM=m5j)u28leDs;Z29wU4ERZ{*A)L?x961L=#iKA*_R zrTgR2kHA<>E*L7lM|bYr^Xq%@M7R*)Tl`sKz(qtoS|UX1-+K!|#nGx_1y4rIa(2*Q zuBLr4Tz2gO=JR8QSHbv*^ZZ39#>N*#sLB-WU6>Feu3$!zru6B|V>JEo#T|yQR&-<3 z;c{j7lb0?j->-PSA5{0BvMVEkCDvz#lZdv1P-EN!!^{l8ccRJdHAk_O%YaPvvOVwJ(_%8|7)Fc`q=Qg3U z4H?UaA3d51<}H1?a3RQLL9g%$U+}-CsrVkaUo*dbyCh5190#k7v^TYVxLc_l@eG2M zuGFkpMxovH&SYNG6*Z&A$364587Q=Y4ZPu>fsfZt;Ora!F6SCt+^N*QeY>u9gB8o` zIy6=}DZ!h-qa3`%cD3fbQbTcqFKVo|80|m$@HS65Ew|C|{@tR~mlF!=LDUW!iDVN{ z4t!ZG42D>$ri1x7F?fSV#%MmmW6$`i)kygz-z9!?%;R(S3*49>T?|Y2`}b|mIAmuD z1CQh}QOyX@cG@vI%m{UGhONGz9;nG=(s z78{Ebm3}5GB#B1wUVpB!?Olj6o5S(? z%Iuk#Lr(;K_<9elv%6JI&Lj5h**vEAt3z z5vr~iZGbSZLS4mUHvdfu6Y=+Qt3^h7jwtf#rd2UgCL@HOP#Qt{p-s#CXDBb9 zU&THdT?;DJt%ix6W}%5&#owZoaGo&}4T9_(g6KVt+m+Sacx6kpcRc3B<5SJoWGXMZ z+&chyHq%BM$UvbLYZXj48Hp&}totzc@UCN3GSE&cwB;UvHYz>A{zy-@hYj+>W`QZa z!h;wgX&8*6T)Sb1{qssRLDBZ$8ooV4duasJ(9z%;eJ$U9+RsrU!W@?0pYd|Fsg1U8 zKb0o#2)g;aTwT3SVGJe@W?HhJbzOWCd4{!od5BrK1{=;l;aPKj2}~oOw$pHL5%*KG zNc`s2f=4|)z4>k{W|afw|7vzV3MDrc0Qbh)`s+-08IRZVjr42ywoR-h_^VB*)dy_i zw+GJ3f}`()IB-w2rY9m%Az~sIw6wHhwy52Fkj=av8Zz+MkM=veDQ^3>Ay;=%drZwG z7MBb~#qJka=_6+CANKQ{Hp9zS4~@TLj{d&1V|uhwO7uTIOgs5^A65`c_&RWq3T=@t{UZW$M{}*07dhyl{j|0{m$L>; zlADGLc1@31GzHv`h-ySUJcrQont)2Oe6=}~CKAZZn=#tO;mKo(Hralh9pMb76`;Mh4M&Ghe)K-_>&aB@t$@72`SZ2v{;E31i{`kJNVmw zz};i#!lt0mT~1nU0YC{aN1G}>IhPW|a>h5(;^$jnMeqQL2Ak$`kh+5}C{KpwcmM&H zZ<*sD>IIYQRggE_F31mNfSbl9yX?(9sRy_9^;^DAwQSBA3#ONTjpj#h(natoCJzlg zxp8*p2-S4MAmn*DbXw~4N?puyw937l2d%a2sN@cc8ObXfZMwstt5-})Qn0}?!M!=I z98)~9n861SkTzxRGmye*1+SGP zCHrYuQq19_g?+8M5cn0TvU<7n*^&krqy}X!@}4m}@+$adfwP2t#fmu9BLOF7Y{X*; zWcY_Vh?X$=G4cPJXk7@Isk5Mf+ZetwHsC~1=#B0bkztXQk%?THXpndOeZ-Y_Zlpus`zGxU2Q2B zPFFpVHSqjZud=?Zo~2h7VJWUsThC*7{i^j|kTp$$wT-nGlddTg&RG<5IPXXKFQSqi z8Cu*-q#(iP!4NhszD<}5#k-$)P#)iq=EkK0&eQg)YP#CntAho3zAJjU%gm)N3or5R zixu%Qjsz48!Qp?jtWLGKlYVJlvFZtXAE9>e{QZ18DR$I4hlzbBdXiH!kSz0uYs~nd zH>H@M$+eSaV!u%A)P0pDDlH9n8p&zGr~RAqge^lMIp%RRJs zq%hWb8jZ&+*Dyor)kzU_^&`2?_qBb!D|z(3ZWS;bqLN~2iM9cE?&(ISzG?fUmGt?` z7i{RogGC61RMCx*%iFf^p#0i?K8+@xVSKvK6TYcgJAp~B4g3YOi0!f^k>;z-@L$qD z6oj2ur;kZUXbRNg?}t)aK-uNU8HLv`SNF;S^q{OGTT5T@NgvhN2LcW{aK~x*u%k9P zb}N>a#l8-rTclTh>^ZuCdy2^C$(&C5gJzwRszfS?&62x|PBpf*jxE=+z1Phd0fFXg z$lBpB%r&Vb^X+1X*M84KB=hSRdO4`}k8G~s(82hCbhmR}wze@_miWm&@g*vYPfIK02Lw6=jkQqJV#g?E9xdb-kMiE0r!4BDme zS!0#Rw{l27k>>?%5W7j!Z?T^#3PI4g(0YvULBoL1d>87RUJ8rv)-|&p1CKUSdW3*jd z6hA%^Go@stsHNsfgfV+KB9tKKpUYzqy`01+uVxllcCg}8>DeJgcK)-m=lvK0o}oZz zbmO$?iOviyOVHYqCN)vw%F0RKf1lLvW%Q$G9S^QnuOU*^V4&h{Bnn(AU!Apq-&mq(9m+@Uppj*|#O1`MLQ=)Z*u6a97tUm_62#f>;HbVc=H_#}a(_kn>MD z>Peo_$&mLNczRps_V7txMrtR1@i@AM1WHCz%J^zrG0B`@k09g<4Eq{;?|C6<%)FBb zmm~T9Wo@lTFkwHTR~{c?kE#7ogrkl^S1KfPtUHkLK`yFq&3j`9cgvtW35C?#HR!cz9OrPo8*AGCHpd{-+W=Sl zxxKE#!Rt7m*T(Y7B!s+OZRbj&`NaA8^XG@t8S>}fng_8JlEhavgIh`*DPTY;+^m>K zgZ`smzr4(qx;BC^%bym?VYYM74{dDBb-m1dOITIv+bj0)In=>$5w-cDycp;QQ}tz_ zk;lUy{Z@aUq)BxfcP#rL$ATgPh(fR?j87;JLgWKk4*o3tVbj#qCXTs#P2c4`F~~MR zKS9o1BUxxeHg8*#<&v_CFxMdRq>s{~n*}tDz~rGrFpoBqcWDrMMj$YGTWEY5M2aF8 zE)CK?9#LV}R*5(>&HL#_Li0~;3m82~pRc1PxJRYDp0XA&@*pehWo9_xnvGc(_3f090o_T%`L!(3))Ysh-VJ6{%gTlZOr zRh?-7^+it}d&u<=*s_2T<_AOZ;cZP{V?DjFV4OC>R;F#AvJhItn$a@!h-oCF61)f+;GHU4Rna_qQHhrqEi9nL4e% z=zQT3c1}NgF28;AVhiIVEci%|U`ttzWk*z(pv81$v}=*WF7q7v&}#;OwC_^N>%3H> z3Ek2(&y#*I2cx44J17Ss-o-w#lMeyL$+lR6w^Ku&(DEw{*YJV#FHbZgT`yWSwB%W4 z4|TK2!h1T3bZ;v?a;-Nf}EkrWgA2)hqIof~Qaft+E7&O}?Zihxu+a(QHDDbLxG zvlr(kdaS95X^USj_H|rCb|A~D>%B3e$cX1!Ye!C2wuWr^7M7paTz1!`!O(-cYO;>M z2Y;r@CxJXByKMTPxOPI#>V8S8t*>OXhWXE6nM_HmbBJ4EL=G5yjvqe`Yrjy7L^g%| zxQp%jQUucux68?u(XP`}XNg#CSlxER9hHjjy z9)xKjneua{V=h;(U8{Ec@F~LyJCotO%{Ngy5@65XXJ5Rc0dR=sp9wq_xa4 zbp3?33KpF8f!>)tThtA&it?CVp*?PT)(SV5w%hU^Q?LZnR*}_kAgvvZ^JL>KSS4P_ zjBVrH^M0EbEfp=Ge_hHe9lUq{vXvE+FYw3q!k&!YG7MF53u(7WZ5ZAdsyB~Rt@f3v ztfKRzs%hYxY=AnBZ*P$;yY>L%0K$OUq}4_dPNm7j3vELSB-yk1%ly&fW}kL;-4Z4a zC)&npMBYeIcEFK0RzR61ztgF`0(OlzyK2Vhww;LymYtcA0!M~>iPWX)Vh6H2vbUrOAnTPrJ+>+9unaVcc}6?@+#G2u9DmwWm zyr1Q4n@>UKTK$<8t9lTt=EcNDA>AeAc$F>k=<>YJEUpk0J^)n~iea>Gtig8>e?zPN z+{HelJ9SXFJ{~UpvF4W+>r2=(r&sK7_}r$)f_fl}=|I7;Slw9edI{gY%#DeiG{*%Y zSJHkWD$b@$X^eu-F{-H9j_m1O`a$802R{TrD*81kfyTq`k!AWRhgA}kvdaU>OHk*r zk(W1R?8up!nG+yIfr{5ZHg=yz#M#1INamL>V_;D>_c`D$b;Y_TOgs{KJm1^XGhXJj zOK9H2J@@f4_^{8ZsC&KJ8OfekeTytN z1R-%<%%Y97&nGMEP}^y96^Ss_7Z%4_iL=_zUAbf`H$`Y_BhSE#r}E`wY;46e=J79{ ze~n4s>KA1XxeP9VV0aC56yMid#O~)bL1S@iUVcncV{O!=NIWOZ!GBE?Y&vxrOcPWH#t3xW&OHX zfl&Vnlo-%80h10f3GHPl1uEhun^&3^&!>Bx$eCZW-+lfZT(JIhb#?XfOSc`u-0bWV zBlnVr78U|g#yWS^e?`Ez_zi-q60-0P&#F?TDX;=JD=X9k@b1VR3KFpmYUK2+g5-N! zQh@E~&oS09)PjZR`$_pmM;KdpUvl45_A=C}^V5%tiZRR=a&MMlt)c7io+^OjDuXub z93Ui>3zvkIWa40(;5BWmtJ@A9i&NLGege53Ocs<)gv|T$oEf^iyQveMg7tN@4U+RE zdz=A>(02dm9&#KMSf3r9L;a>8SIK|j>2QLWPlXW>sjYOU_YR0`bUQ)N%yQG{UbDUT zj(#1Fr(F28xMH4_$`^x6#o=LL*BM*D$=R*oiT}MMJGxBk(F$#Vr4OZ_0>PLXkUW3F z!jmMYGm`YX5wnwO9Fv^f)u@DB1~MNw$s{^UoOxi65Ck}&TDb<6iJ$UqLpJ30RKhVR z17Qqt(z5Lkja|i*1rQWLKUw}R*%-HG^L%5b1!AfXEh25nTTK1^XP*A)NIf9+Kv55& zn#iujNwJdCka_&#qEpBM#=84>>hoyXfuhvtaSwC+#_Fl_6{0^~axxxM3Tvr=Cmz&3qEM>CbbPfDbeWOAJ*83@k(*j&xgZ{hbO|Ou5 zA>?p0S6&4N*^?Yz23McDUl&|W;Zio)y#nz-!fzI2f$ z-@&i$Z*PF%$wOow6a>%DpMYK5A!r4M4gXecYj0|qg7b&3bCg&iF}LSgcU!BaA&@E^ zJ_yhV`f});8NmMLgogz|ZB^*xW5%KpCrQj!t37Z}R9h1j==?2?HD&4L(@&^dKiF%T z=Ec@@%^mOr zt%+i5wL+9AZf%v2c03w89iG&epW**~^|rOm+~;qZd+0ts`Ut$Rn|BQ-gy*2ltg_W0 z;wY9W&%^>=U^PDZBIQT$-H9xwx;h~Q=I3|Q*H7%HLj?gB60b2 z4q4=P>$v*eyL)0JwCUyGHJLP@b$zdko#pSkE2d;2u*@>DZeu#B%?Y@zt-mAnvuU!3 zEFYb`W!q$ht3-fgE$D_7e*A!425lg~D1t$5++Q9xs_E79O`m7>*s)__2UQbqz1IjJ zqYMxOO7(^eSaMA(_}!E~9LaFn91HT}gd(k~<9*P{jr{h$LNEP3gyq6L3wr2DV_&I9 z9C<@Q7XLPfG$wDZX!>28dr!Y2hc!&VTkPV#cpz5bY~EW^vHR{Lii!5S!^&7=O_nbW zRetf2jIYHKo3!)~OiGDgM4T{ALTL++DzunjSdMr%2rKbwI68Y+cfU+;#} zt=iap?Js{OsmGTvi7!%{B-_KNZvKQc2&zT^r6ih~{?l`)f29xf_4}6jzei@mb3O?a9Kx zvvuY9Tz^s~v@XAX6?tH+ncubV`^oRi<(Fe9y2iHVYtvfm^W8BAS{DrWy3F^T*VE&B zb=jXNa5idkk%o%b&^|RQ(S^?c!07AwUlP7q?i(?srDx4eH)Mr(iQB!(<;`>R6OlC= zx&rlgHSfIMr|Lu4R_;Lcnl=AXkZ+R_E9%IfdfK73FaXzW80r}bGnwN|_lJ?RScGBD zv8I$x!<~gYMZIc6K*g`By8)WrcC^PWPH0^6h<*H+j2>~P>MV>0xBnv3L$CecouL2u z3c=t#MBKPgZqjC&i*mxLhIgvi>EyC$b}9`!=p%h3u=@}B{41!f%;w~$^Bu5gQIs0& zQ*bZ!?JHi-CqIFrU{hx2O4Bj8IPacidPWa_TgJ3)QU6)1_6<9YxqDlaMb?kd`m6j= zNRO00;9?(9o3qmimfqjy{*QzC+aJkDs=e%GFRu!wxFY+0o-t3NDs5P?F8#%-4afHc zGiF!aY6&&}<=Y;AOX9#C!W4Xnh2beQD9Ha4Gk_4Nb>scYCuacXL%K&jW&c@s|LZI7 zPVZCJQIAhqvxuK)G?6f?It`xPsy#QuLB;a`7;I#MYIwy+~^Q>XObdRbi~?74m-ad|92Y_IU*kLtQs2}U*F zU^-QyIu2!MY*yKFMGrp7r3a99%XH`)5D=VM0Bx`MY07gHuds&xchUQPT+gMeDK~CvQ@|dHI|H zuVCLTPo_776Qh2+Eotgd|Lj0Hwm5g^RI0r^SL~D0YNEpE?P^ZW9gf~&+~OZ* z5lwj*)lulrYE;Ry?Oo_|s-9Z%CI519L>gMP{fg$D&&!(XiQBQ!dK8|E3i;oj?EiY? zg+y?$C?`l`jq(Jg_g!ba%B?)SU*rYHb!VCDo7xIcZl>gDJ@!!S+y6R{|LqwM>e9Y?^@1l( z3A-_TF;AyXHO|E4yr-;)k3Ajth0_Nbh zg`(+cBaWBMB0f@lfgvlk8IG6uW!V~hXgU2_>!lW=IruaF*)4RN>g1V>P+lr-*~Cgs z_Ft$gj#hQ;FQc8WpA|nKg=HSu&y#FV8&csHY}gn-s>S2)pYXq3?*BS&2w3Bc+TQ+L z&AZIPtAw>PxM^l4KVZ5kYruV7N%0WwfNhJ*8vRP~o*K>NF6QQcn4bAZQ$#S;-ZSI5 zi;-ha{psdDB+RfcxUNRF@Uowf{_dS4$*degVZ6RYW^rAEAOG3Pc5}OONwiW(0iuCl z(sGvZGWu2r_t8FQ;N!*yoIBmOL^<`GakLC0t;8}eYw+TqzL9uv8{sQn%7=?5E6&qk z>#jn?Sf}hmrgzuk9~vATHNO}o{+(s*9|j6edQ{3mU}oR03pd|YoD|4A+}B?xWnHsX zdy{UcNTxoxOm;-da)@Ncb>JVK#s!b`X%p^pE@&j1pIkI{e00q(enM!xpAS}?mmh6t zJlX5$rMO=H*9HC0J^0^Wp)ZqydCt$y&Mqvy!AM}DBO*5!oRjZpZ5$~F<^2LFT1#`L_AL9FsmileXY}23-?)J9Uob{ zH1rL>C#*V{bvI5p^%h#j`+W7;Pd8GoUV0?f5YAT{by&UfF4Tkn`P~2IE5y}P{eLou zh4Vt_^>g*3Huroq<=n-nVc>|pp@cPJjdXKSn@~6!wA?Vvc@txW2E7}Vc0J!;k@WKA zUdV{hu(m!J8Rg6Xu?2kGn>9)P8+tuZ*DyRg7{0Bc`=*ySXW;S%0geB!; z=97nVY{{AE(aIGsr5sPmwf~e(C=ML=;Va{~eTR#m2&_EeGg}T9-VCNSA1YWDT*IpE zUmp6MdU{0Kr==xT#)Q#0lv$_Celo`>{|zWALYFk<7)K}gOn=vf(1Za zR7@KiJ-|+At5HRde5V|QD|Xhm;#Lup?Wb^oo8MOZod%&olg)@3hJXRbvfwtbYfqcd zm`5l_fS%LKd{D?dey3jr=D>lp(x;a^Pv+-WDv*uI=(MF?&4g1{T)`a~_Cf&N>i%G? zuhUw0CFY#T`sZ5(*00k>(aXPr0L%gdVM#CqcvVqK6>O*?mSbPOu%Ik9X{Rt21nYnG z(_5r5$wy>XQTl&H>rl|`IGx+gbs(?%7jxBsOHFY5N6ur(^x0`$0C7V9R zwgf9IecVsjY=}oxP4EKTJgU!$4@ol_F-bAxZ=Vsr6-%$Pp_0-V7P|8F)oV{@e$S*4 zH|CF}fBwwDy?NPJsL;5NlD7&ffol-&w0~*}Ood(&^AhKdaHT_E+@lq}ka+jWNWqp5 z*=qxH5hWoJ1e%jo+yF%$MUI7*g-?Cx0odfKL7jL#;p~3T&W99JG6NaaCM0Ke1T+jx z6ktm(zZW7ivH$|{rOU$L%9f?`nb|+-ZXzBF=)t1>PD6bYfF2oJC>nXEgKvWt*eC5I z?4vkiS~ItWAH9D%@+Qz95KXUIh}(f?e>bWdIarAH_Ewt!0Wm*@g5*==xy6@PC39p= zYj!`t7j5@U{pZ<13s+W0T^v%s?r^2t$39p2BNjOAY{}vLzX|7ev-oZXjvja8-uJjF zf-vZG$=9TQ&$*$WvkVjvlf^Ip-0g{aDJ3A=qbLIKE+*QDGcI*XClPc#H0r0m-USt> z-xr;X?@wpq!uXZmXbNuei^x7|-Wft8exrQg1<-K0!A3P{0HjwHwKIcE%-UpAg=?{> zv3~rf$-t@Q(N1m4S8v`F_L5KtNuEON#rRon*2DW}NzIEg1KW6;lDX`%zI(+fN=9fu z7shZR@pPkPn^$dmuf1P}qtyR0x2GNTV~_wEULbbgN?y^@^v`gMKka6JqXsIzZP zd9|}9DCytiZAhA!28Z`%(GLVCtcq%`qhb}{Mur=(avd&E5AOkijG>HqiEgjJ)Nq4Sd*h?GXq zh!_33(DJwDe{YCDEqjjixC?q%;X16o)%1HHL{T(2cu-HljqMb+Z^Ka(F*1|Q3p&5N zEGNxN%YyCma}XWVpH)VWy$iTV{v0m$_$JfA-xQSN?~5!T?&ri6li0B`$BsR!4J2e4 z7QF!~oIC)8_7?GoZ&LM9+Eoh=ru9!maQMFY?haP<&iK3Fb&H?U) zy)h?JBSG0x(XAr~XIjwK4((cKS+bB#HCe@;bfHBM&|$oWkUhqZkNP}?wvrzlY)o@s z2e0i>iF_ZS;`{EM0BJ%DfZ$wz%n=U2?Zn!1xgc5pEt3fiEoZt&xm zdeAGwCm7~Ct58wf8?_Xn9qi0t=YOL3s&~MIdBNTNlG}C8q+x%@5Z>k7b~+KyIwI=e zBI57O@rC~gyBE=$q<_x{8+&ZYdC?v3^?nX9@d}ANPq~D;-qgy0NF46%D{w2z$~xga zQ#>Q?$oZn6pulT-DXDK)gOKYXEP>73q}q22+P5!WOkfYibs(@#U?bj%usDG8I#`}% zxgNiEOiG3s4>3|m*-|AxTPoetg#o^5Xn~@U+65>2W=YUY8q?6Tp~@j2jQ@V=(=VZ# zveH{sa0%2!^ZrV72N_Z2N2z5g=-93@hf$O}0TY*dMPc|jPklGdotJ(%eQ zZc@Arz4|D8d^1Q1MW~nId}DL-_Y~!M`fReF-p82*ZD5ZYAUpV8Dw*yUG_TLW%Gg(F z&HzbDymVKtaKc*PT(!l+v-Ix!*XF{H5&%_MjIu|!sjOY6)>B_MtJ>RjmFXvCdkZf%4yrB&)-1a-3imAo?!C38V1ftU`qZ5w7Vq&?}9HRINGgrKAp_vrmss+&HA^l>hKt@R3VHv|rPu4}P>AEL0(P$$KIU zxC|JB?ODS+&o*T&H{vK*u%~S#A&K3YpcdP0GQZNWq=Wz>Lv#1Z-<>nAn`2{%&vOaJ z4<0m=VNzkQYw8aWS%(?1xKlF>gzvz-Nqs&&Ba0Rlq+;BO=eo9C?wq2w_FwnLI&+(fQe&quLp+6JH~4*EiId4k>0#^JmT8kkzlu`#8gUQH+@aw z2p3_oup1BE!(3zU^zPT$1}3mKFax6T{vSV67?m*wYO9fB9Vf72S!k;01ljo&NnGHc z69Vf==#`&a2Yvuo^ndDF^fIONnazT;k}+u|qq<=&d5Pb{;IP)_?j0eIl?mcCE>a(t z);2V?StHSvUkC`&Up9AI@~fiH1jcglH|uZVidb4+UjM5{eSKciMjwAU94~zI{?V5r z@63EmcA32^@L@b~Ir!-{{9<&O^9ZUfp=863V^(rkyJu|0M%&LVwe~ZX(``dvL;eFH?L^9nwxA{w9D@b4_A;5{OL}*`dTtztM|-% zHbCqH)wfjY$u)&VhGTSYDik+uAb|xrp0|9BvfJ7Cncwzs=yVyo?J_6lY_EM|7$2?^ zTt*|$=N5{$F=K&qd}p5={bAE>O4?*{r0n4_sDmUG0}5$jI}L?a17Zr>9MbvA{4_W& znFRHGGGCl=wg}p?A1r)rR{t_a$=JxEJ;8i}jyOMjZKT}YFll@>a$CH$JKhI>$<2J3 zzf0w#_?0V72Cjz6-YKd{Pni1U*D=u_ubzC={Lrp~a1Rv6Y`_yNloIk})csL18@08h zt$Hp>E8E}%Z(KIKOL2HgxNvK zj6LQ&Cpkr4&5yC^TF=r}-OL%;^4w{?zgRja?M;59*mUgJ)A_C!mZ{!vK##Qgb_;<_ zgLJfa#hPE;$yW4M^ZqPj3=?O%QN{K}u5!#BgyHsvGo02}$={VbN%EWb5xlYYSgX>= zcS(-xo@6>lzg4c6TV%D;iOD5U|k(d@- z-ZX=%(t0@l4I;X6_&$>8Kn{I@LJS(3?@HF>jJ^fTj_x-DQ!VYGNX)M(`>E#rru`2<34HI?$B*i0s^SdAeEq~Qj zOss4<61UAT*8a@qm~Qr=Af?OqD;5TRd^9X8tUh3M)A83fyJpqrTM)>N2;w8t(4_(s#zcDM$u{Av(7`R9jj?RS-vi|C9`9|H+v?iW^~#rR0uCfPQ< zsR7K0$!H5*34X-m0;&+1`k9afDG5O@_e=f)tW{M9AR3z##3iH>ja@oO3-!Ack@+)D z6m%RWR{>dEVrQ^IYVT7j(}*dmZfpiX$KQ9{AXv?7rvs8|WD%HnuT*Oa37kY;0o34HmI8F>w~15F947!{X51YwXp!zLX(9*PsXfBuOa!$(ml|zvOb6i1Et#%MjmG zC|hPZezQ8>#I>)1=kSo66Iz&f;0c#kq?Ca{@?xKAYG3|))%L~5{Gu0SzM%5RP^!v5 z{ZlsC5|;+f{Dcbudqu~8721NN0(eytr)5QFJj=|zp5W0RD3Cf=3p?-nFACPTziB+< z;?4wl-Om;}dK1}G_P=}&RJYljMR_QC^n_HKFO5{B8^62Aq!H$pCaC&c)@kx`*b8u| z#QXa*Lgqo+NrX?{g62Z1iu-4;=Tf>Z(_8QZZMcn_bF?XAQYG2#9!vg=ITpcwc9HG!BQIy7bZ4|4b7^8P{ zD$3qF9-(p^vk&##lDR2I0)m&jbi5)viGQ_4B8Ob3N_rD)5r4H8_Cr^EU4jQGT=;#`c{0TKi71XOl|7f%m(QU66Dt6*E^kpNlj7cb@eTe zt)MH978yFpt1a#Oj^8<&+{L(rb)K{;(u@OT|6R2MUTj>g*74iG`Qb zWTinW{Aw~IA)n@RbbMpDp?z43@lfQmU0M2=H&8i*f`IfFMAH?MG=X10y+SwNn%wWN zyr{3V83XRZKp@)D)cnvju8mR(l67BwxUGtdEL$q!*DgOXhd_`*Ew4J6carx)foUI!Ir6Hp&>Cl9EoTuaidqsuUoa-Pw~_# zyW+9uG;NT(C2ijg`EUGmjG&wtAM1BMU2*T*i8b8!XOit39@tCA?&RDHXA?L}5hX9B zeFh7Kn{#6l@#=GPG-BPGEd^?7wHKJbFk)VW_ujrdhYuIOz5{IlVHa~8kL$-2AEw&e z_IpZ-5A-AQiZ7oEyea1rYe~22GdhbIZSWYfl=zAPi{*%y>(NSkD3Fywy-!c>opbGsV1blJ+5-^xPdO&M0+bAEw5{uF(1T{LQIys+FV z8aa637^6D}5;hBK!Q{>xzzGR}Y!A(m#+zqfKHtaz!qcCDAZCE-C_Y^b$d8X=Eu zySDU5ozTxaBzvm#&xISuA9O|U0%S41!c?8M7=msdI}`4jyhAPjj6W0lO~2?i#@lPL zY)K98%)3>#NjCgA#`;%JlgrI!>hT-;8#r7 zpSP2yw?nKOOjNMBop(X(>Ko}xU!uk2D%;cMde`9GLg(i;hzBM~e~3AKyP_O+HiRn= zAq4we2}_*g&bOWh|E)ohA>%UICdk?0Q?gSr`D|Er0H3DYPIQ=QK&NcfauUKyMkkLVri85G$ zeLOLT`P7$(2u~AU5@Lqs`{i4N$}vL}kB#}U7Yu@o^-u@}`uqEDl3vMTnGYJ#@K$b) zhsM+W5oEZ{z6{w$Iv8(Nr>Vw((Xi{Ju7a+PwIhj|2!&j-v*_VQCR7(*<8|)XUV>z? z5~nF@mfu8He!Elm>t_`GBD;KoWT1h&(;701m>mJRn<;if&iV4E1?~CG^@XLLtD2=G z+ri3|jX*YapLg{ye|^5i?a*S3%Sdx#=&;p`M2&>XrG>*gT9=;1Bu+V$-;(6H zQQC_tru|J#SNOcz)ryKO!Velaj9r2!n*H|{6qTkdL5;?jRih4Uui=rlu9?oNi)%pY z2uYE%NW1yu=Xf5xK8i_msa^*Zw7;~G_F&}yynb<{R6mL?*=5^m==n7zBQIN7o8GJ` z07Fj)^4rr)IM0Clx3eAfg1ud(JFZXi;y^)3bWSBDny(XMN!nZ?k=AmO^)lMfg=Bf~ zxfr((yAHR`8>6d*CtG6TsH^mk+3sXH3)vx35w_& z^h5|0)yhP{Ap`Z9L38pP7We5=T0Oe8S(*hC6{N=m(|Hu^;|xawV>GHV_;ugoes%FOvv2pn2AF2zejpx(e?VK z8Q=ntqoRJbrzpwj8oG;hf4%EE5f*-#<@ND<@0>oq?8-4t!+9sw#>=JUK_oGUy4&mg zJog4{{70Dv4>JGW{U;hj0qL{v`$U$|4>?)uNeSrRve638Q#fq1t+{oPge~c12SlDs zT!KY#JfprN+g4eZhZr+xhhcqkuuFw-$2&=NCwHx(+sZ-P_vb9KCR53nHshU3Lh-L1 zOF8R$-Ul*xe|^8(qCUOk?lNR-i{xOvTLD=}b9$jmr#NfskxN@K$U6}gD0tj)_m8F)B|Wz;Mug&$Nndo+>1 z%tcK9!tUI;w6Ax$N}$E-M!4$%)(y;dw2)=%WL7EuVI#UWFnrzpt9>7x7nEGlqLt)ZJo|}zAUUsU9I33CEj+s zPtP^x-+X2y3a%B(?z~qfUQo(QDy$UUJ#@**PF;6sYa%fI+G4;cU3Ibp1q|i9uoJhk za=~8>%PTrApX=PQ=z;%r1~BTm%;Lf#>mKQ8 z;kO{5Cvcy%f&b%xzJODYkp=ytlh3wKC1Kpg*e_}L16(ZtM3^gs_Re2!y+3Qq3SZnm^lZFp0?_FcjoT#yKHMXh-_-{0yO0BhSkh*~tPt zq?0iaGAV%Z93oV=r{GC<;+t>M402$R+bf&wJ@Dnumj?@@Tl_fh7fE4TMRxr!q1_oU zC!UmQS|v%xx4GJ~S;a2zEo_->VApxxtz1`oL}=y3w;%uY{1Vs;$)Xnm$?eT|xgd90 zs$^}_CC_3Z%_#H0e#v{&WX@W>5~oYWh`Cot6Ry1r#W{;y_9_ba^GS{dT}G}w93K#0 z?f+i(g~yStvegA*#=~V4WmMDyf9kL}x>u;F4}m7-!9c=9q&$e(8AKdW+`G*@DZE_Y z@uT3iQW@Vy;}?o*zvtMx3Zz~RBxzkY~XtJ+|fD4r~K^avC~N3n8=P2Dvv8 zZ8EA62^;uPGS^ndmPz*eZMza!ox^Ui_DKtb!B!M|R(HvtMbtby6#D@3DoAjw`$bM* z8fx`EyLgyT+F``I9VOIBS%$JLfcdHgrIdg^xm9+I3dSlZxMSUw)$}DJMFYr)AxAE< zl~DQ%y_8XHiA}#BwdfVOuuANgyfJn4_2;`~iV|^B9v!448DF2Y!3ErU_;VB)XBMi=E0`vywu)!5N(0i;eqJ5E~8Rkrg!+hQ z=T@~Zm(FK>2iSC8sb!W9o?a3^u2Xn|{V7`b1ne2mCrEzKn>DdNNZXl#ZV$7PKgZJj z_1;9dl2K8+l)SLw!f7-ZpRcDVvN|qlm2O8~wA-1KTom)xo`C@58CW>4a};4dz_Z$=6^F%V#@ud8&$X zha)ZdjPr|gkVfRT^)b%9d}9Ja3>thITw^{tSmj%&Kt{o-#~q_G8wmWnm3jI0-_WdL zw4Tfh5}NR1*BmWrV1vcP_;&Q|n(ZZWUCch|n~cHj=#3FoNO|I+n{1DRtV|mRc+tQl zC(mK*0`$kPCY*fq`BsHEta@UaZHI#HBA~W@gx!$8pYNi;uW0w~`poY;nGeE`hum#U zLm{Rz2u6mK0yOqq3&Mljowtwa7oM7Gex2d+ZQ!Dry}4Ty5tr-8oo~_hknpv86FZ`j zZQcDfR(b2;k;7wAgf!4Yk6*eL|Nl_+-QiTm|KCKYlvNR-vMO0Al5x^jNt?1s$Q~IP zCn_VPD0@_jMD||C-Xmm>V~>o3W1V&1&-*;r^ZWk3&mXR?D_vcj`@TQ-`~8}VSRqIT z_-;~np>c5-Q?fJIO}Ve0TCVd85lFpPe4{9)Wb(ao5%GQLX??Jo zyWYI4hnNr*8yd;~;mc57PxgRwi9fZjVhk(FHpkqTRs5G`I}#(UhVm!t5Sbj;js)4h zZ7N3xMtT8d^V;RfUWLr!ZLwblenfT^Y6(jhZ*wcyjMf53)B?5wOMHbYq;v~0K|T*1 z?HQO&ET$@@Qyo}Ixr0aRl|-N|doPC>eE|O54V~p!mNYe;3aqPRs|Mw%FJAtx`Gp;78K_3;{?ikp41 zjsDhRNw6E18T23>&Ln)PoeVulA#had!>72zZD+*^rO*mU$Bn*89B4a(9#(R4^om?K zBx}ULQd3&v*EL-)@IG+kKTeTM1Rc_{ABuis?(ScA)46`^5`{~g+9#Bi*L~TwAPKAY zWjSAShobNiklclo-sZ%vhSkBveZv37{6g(t9F2`>vA;OHDie3R&{pw&meJ9&fCg|k z+1~2Bw^K?F{@e7_vb6b$|_*}Vu2!H>Z zjvV`k4^kKLYFZAPkIkJ>uPq<8p#tk^KWOBv4w9Y#BJ2Cbx_8(UDD(gY71(4>131Ir zWB3fMhBe+{C1uLx)xUtn!ESC!2EJjah zQP;3hE%;6YCujPHH9TgP1nA-KDXvKHW zal@|{=Xe_v6C)z?$3OuTh)3UzppDfMKVv3~kkCd6(V8$Ma8pL_r))~RH@{i)r)S+W zZ4c5Oh4}8=%>c+3<85WygOd+4_%=A?QQ4_m1z0W%r=Eupc_ZTXEjm`r3+beVa*2#` z5ba#`OMlumI#ZN?o(TTx9DVwl9t!zXyScwuWPgKtBg^Pnna%>suJ4xTI((Q?8AQdF zzG-xe8>4va*oAYdJNELQF=}|fWQ-VMX%C~YzX$V=Kg{{G_a4LK-L&3$hb0tX@UR|x zIH?35p*J;ent>^qIe(=m(r}!jHsOvYA_TvAyjDu*72W}Nc}q0-Qi+^8+zuGe+5me* zz^+KHWtsqDPZ%o=c4@88bxz79YsT|mU0HPMxH`0BZX~Tx5`xp5XfL0fv1^BP(eQ_F}Hw8S6i?wj?cLH?-MF!z)fg-A|5q4bQ>1avEqx^O;uR#&8M4WD=m^ zXW98=8D1U2v>E|m1O;Ri91i(UEG5T$s4ylFT3zk4CJm3(+F;E~Q2#$aJFlFv?V5^e zMhV+|t~<}aQuegF#{as!sw|0WpC>sS@oZ7ddh@g^``Ea^rJ_}S&qeOt;j2|{EFEs0 zqFM|Xw;A^*&!6;G=-}g3s@mzBeSTjtq!l#^3w=^jAfggfC_~G2YckPxv;U*rpXbh# zi;WKn{d!}%dGplrTo>oQ3WB`%uv@TsW2Cb1Y@aeFSdx8^Z;NxM@~?i4y6VD1M2SmC z?G(mkQRiT*;VXv7{IcNO_VdIKB#NbX(Vwd-GA(56zxk98Mwj!hvi&;WI1h{3Ea;UO zd@>YAufr@RXR;Eox^t5-q}7oCS)CG_HRuzHjBZ6-g%{=Yi+_1pG*uBOrFgr{;Vcm* zbu7Cyc;UN^lv;y&LZ-?wkM-q(f*uiaPvi4mAbOfJm6?~%rmWQ)q@O#M8siy~Q ziYD^Peaj zHjcEteLPf!0}BF1^Ep5CJeKmuzl~LF$mgNs>zJyQ`6#WCLl$cA&OZxjPe-n`$7Rrx zkn*k3OCWEW=)=evR@bhhkACZB8&&N9{vRgX(}K#*Y(s>!Y{T3a#7CTo01Us~FeFf4 z+D3O2QGwrTY3C4qdNV*5sn!4LEc*YSDA*c_QN<(k1(-TEpcKAe-H36ZFWgbG-aE2u zzFi5@DYK9ZiBb60bVc(bu07g(g(!pTPqQ@L#BwZ|52NP|{^7T?+=g1O}*yWjgf4pYctw*0;fmNnhQW-TgNvP;C3l$4ZxCSM97&g&6QDAQH+1{it(V7 zL2WR>y!LaVH^mjSQ4EU%g?()h*DS-q$C-%R6=uJ)7-3~G9n0;&9Z@?M!HIsVcx6{l5jry0U;(i*eW1DpbhspR2 zNzcCO?X5($z0AucMCsDRS8pg72PJ{)w{8Vnp`Xf6P>W|eME;>xBR#|F2$1dBV_Q4p zT$(MZ-84+tSY4gK{Rg*bu|+R~g%mozA=4`~FV@X9s8RPr4n!92n_h3hR;akUlL7Z# ztrn*H4Y2`J?$jG`iGzGj6k1VW+gE(No(-aI| z&Wk~Xx-!E-B>MyFGNJuTAB$NGw&&L>&1}>T=g{sxi=-{!lFE_)XWO7n_Sg*}DatJq-MsbrA@epQT#}K37Z0+XrI>9gk@is(3d~Q{dpg4~d zH%H*|Tt9WVDYW41;(^S~Tdan+*2fwgmSqge0^rhw#muA-Lx|+;t4CVN4p3{JU&Hei*weW`YA?r{Zu4$fB^tzj8fp5J`M}4AiM3?< z+a~C?VT9nZ?Rt zOPS_fj&=V&x10B5D^!{8+p!noa-7=L8hTSXomTGlgRoG_;0NHd(^O*QYRSF5J(nUbvJ zDfe(1vMGGcch5zl`{!NLTDD`pGJe3wy`d``qJhe6^1gQG`-(=M#VC~1oePgIbvf-Y zAqpWm?DY*i?_vhr4( z$}X-bd5?V@F9=Wta0!k`gF(0x7Vf57-1SE0B@EoMaZ9smD)uN1 zaEtj*nRle2%|~FlV!`&HG*Tmd?Lw(l=H#~^>FS%%e>@5qX@pR|OE;Qrg}fH;R*+@{ zj(xnY1AEot%=;k%8*ZK550-_yIBzEI9P`PP$Cx!B4stwPZQw0vzZ6Q4GEzaq9eq1>ZJ(jb5+Mjd9e9x2%=yLs)xr8w;KHhy|l zt~%??*4sS;aB_>ii=0|bP=$)^P5<2B7CgMmDlY_v)!8T~>mt=+6MT=+|8Nv2R`|3n zmIZT)S&i+$$w#%d+czUmnN=6EC$J^e6Tf?42P5h?efvBZpaZ+E*@@D-)jAXOgG23 zmR`a)WzjH%Li`*ay;93Yj}_Uu`vChd4mrQ;1&a@UKRWvw_jL7`uODftuy|W=-ze&h zda3In;o@4~=j$|+mau#z8H2oYYFMMezm{KBOhPshZI6) zuDKIf*c0sW|I<#6EhC2rC|>0hzZLbN9kY#Sk10O?8x_Q_SbaE&gg(R*xrZ4+eAf~2 z^iocD{U_$Di`NUa4lFB|rtY*a%~wy4viDY$?q5Anm~>zkOJna&+_Vc^=q`Y-m3^rN8_v6!vhE80f5~6FdmhkTcje%rU9# zhCoQ%Mvv##i0j|;H0K-pW$FN=HiEHG&w2dqxk3 zcyw#6%@wuU+%1gVKC0+aeuDiOQbsDH z^_Gs4Q!K;9RZuwPn&Vr&iV>q#rjT$t}pL4w_9g4M6Hheo?8WSN#)*mI(HG=fagw z9aN5w`p_JOqgm7ZHjJQ1Q7hlOguKeLW!PUDItR=;7}jXhZAQ5-@utPU7&R?xne^R(#?M_OOL z<``iJ7a9_q<0@?80Wmopd%9?LlCoFdRZ~1X>m@kbiXuwPL z@*f^knzo_G*;Bs(!_^x|)|_J{_5HdZL?M(X&KkN2iL4Bc^;zJ*dg+Y*dze;Dw(BaA z`}pQf5t%jgnvi$E$3#zGhNjXmokCkdvm23Zc}UvB%=YTHd(;D@og~J#{s%Y_&h$@}WsV9hQ~A_u4bX$k zcE%WX(YU{2yT@*x>7N`h%yW|??DOKqw5j$Dre;?Js`4DG&kT#Y4wX3?0iuU>=uzz^{2v%^~R^;#(k{fPwuPhUS7aF3s|))r70Ygd2+c(m%kf% zOzLzASt7D-i6ztUpmYA0Xvpz;r8Zpa&QGkmZSlsV=FgJmUi(H+UneJ3CNr1K__dTraW?C8D|fy2XWDDw3d)?tIAdWEaz#N9HtI6~m~=8zpd zG#dh%GmotNOJgd|w(67J>P+C=cac1-%C3Vd%-pPvSgxXCL(LG0_J z%?~>*{I9$)al^C_a|shQ2#@~fcR)0w^2b%<6o4o#!SvP9|ML7rbUTBNcEh+RGZcQL z#!)^KZFspJTrY6{wk(Kv!;MMOi?_CLIp!@aht>+aGoBRlzp6d?@SDcbQ@SN@MoL{9 zNUPB`;6O>elWmgh{Z}=PT-Y7wP=5$ABqHHz83i+PxxUtLuraF+*WFq4?^jwBLR+`! z!Y0uaZ3Y)-d_YxeHh{41J3N+_iEICWLSQcA0+!gOxc`LSxxs=91=a&a>s>b|sV}Vh z>U&@WNtvX8{Y~&Ly2rn!6}uc)Y%H*`&=*P}U|-Dxy*|(-_TZP^wA}`Z$gHQp=3=aW zqt){b!4wU7|FI}RNSUV2;*)RHd+*!jKz0(i*kT;;o=p9^_&(LNWn(Fn*U)hnU}}u_ zlW(cNl1TJCHgzNN#HGI25h! z|HJKsn&S-uZH3EUoTC^50i5iRB!0MkHPZAbDzXtGC+e2aFPS8ETxVi8Q}$Q4`sILH zX0ZZmPMMgGmoMeV7F5}?yP15`X1tn|n<(gygaJ4E4=fA;e7^T3L|>A=E-)9gR?-g= zD09)c-snOf8^{@zU*amaH2L@NB2{^o-9^-Qz56Af#GU*s>A!({+GO&)PmPJoBTLqD z%a-{olw&>krL%gZ0u+}lPYP`3*N8O%re3mB&Cxusc28^VYruOi{Px@&nEfQ_>gY$k zf4{q$%6)8?OI4dFO0OC9o+O|09KLac?EVM3rTaN`U-OA{nyVcCh8&H-{l-e}^p0ZX zCWp2AU)n--@C^02lIat5LB!VFj;q@5{Cm&720Wf6<*M>>?90&5u4yHe&Ds% z=AsfqDK+y+z8`=zoYc4%uoBwi+|3$s4oO$b&Q3{r8m;Dtjq{GpNa&k$LWIFTrE7t#=XA0k|wp!+Qn z8~o>YY;@swe&~1MfYfz47iFb5$^Mr-6|~LRFS0_A5)C1Mmh69MKFcb71f@zLHtX)0ckDxn zKEkD_znsGohwtiGh$5b0(T<1Z=Yv#kBd9q^Rpz{QE0ud@?;ZFAp8x&navi<1Av~23 zGn4zYiCZ!Lg9EDQR`1a|n}Pn;D_#?}L{&>&{cZNv8>l8+p@2*=R>3ACSW~42ijA~O zna0=lA2F<;T8~tywkP6@)b%t4-ashz;B1`mGc-Kv+^yDy^fj#wj+Lb%JI2OX8DT}& z(zm1KiAPSH2;9O@1B60Vukx)M&cP};Ao;I*3j-3f(W6HPk$Garwq@4xJCcga>DLQd zhla4V0b7^Q-g$;`+5^J*96g_P6LzTVTCZb(q-A$NA4+ z43lN%4h|LA?lsrEal^#C>-O&b#~JGFK@@b_dF~FwOnaDahF6%H+%ZGmo(WS7V@GII{ z2PwT@!*FAc9`#|)(w1e3O`i}bd?96P*r%F1v|M)uzsJ^8_S{S1{Zhux;{C=h(J}p% z!^gE2JE#qynOHUP+b3}2NsJxFF@<{7%b}u3>6^Dn&q;{u{CK_KO%~H(D-t^7y;VIXP@`7FJL>rU5UFp%bu*6SPzvZhi!_$ zDYkFI)O99eHv+%^3u;?Ut4Dp`ObB=*c#;7#Q=2!qEg4n<-=pA3wi z!NN|HZ8a;cY&jeg48hm5EHtR;J57G;HAz+L++^^1^g1eXm`K<}g`Xjne+kJxmot5J zicJnAzCTp+83J?f-~)thu-XMhce*I~R(f@e^` zlI0h%W4SLkPQE)Rz2g|H?vGD?k^zZ?q#TQo_uNr6WaW~y)j$~Z7=u;ffQlBKT2*qK z37{m)ix>SqHogWR@kvB)%RG4rXF9tt7E`_aegD0%`;9RFE`YVvmXxNyur!3?t*=B8N?dEr+95 z`qqRLHjiK_lV3v?jc8i8@@VBno1ycw^L-d`Q-qa*WV_}l{eNe|?9h@{C9C>{E{cNR z#)9IV)O&S*Wb}WX2|6hAjvQ@`{d7{FKX6siZZysei6+@o`_Qk{PgA1wZW)FQNJ_qq zDL+_sXSVgc^S{4=0I4}nhUgbV=fH^vMJrr|7?bUd6vJ&=D2Bnq_ou|2pLdQza?3uJ zinVtwQAJcQ6RlsI!5^_lu)5v2wrEY@FS`QgN9)dNtUL9+Sp12*i&C}-9F#9r$d`zR zl-b6Q;UM$rQN4XK28AHRC95xR)IaTrP+jLbe&-0*kA_BLsGJ2@u+9Mdp@a{n)eBv~ z_#*z2r%TX}FA$6;$^?)8wL<-#>>10hPsDZ%;lq+}SzEM-#Fg9UPh6tJ{yoFO;oVlp(U(_# zz6Ec1S{H%;^b%!r>5!V|xhhkxc9n%&paVSFg5Vr#$QI~XzxH_LYm*!=Uj&aIlmPKw zn)dybPxocn=-JH>jyDYw?Y#?Vk2dS-zc1=WZ$NhZYGJT2Z$91&jMV1xKCq$DSYjZqFd)s+Oft9tV4 ztQ7BUeDqDuh-xI!D>SiDE8$uHxytr)sZq5@2kU&GDu#hg>+rb*D%i&5*UP_t7rY)s z=H5^WFwB2)3{ZT)a{YEXji@!#hDt@f=j7lc>5zTWtJLxtGd%_pi-x)WLwMq71d@yqL6iC|+GX`qsv zqBm+zMM&v4n}%+D!J@nqYg(#f85a~eSGj#R07UZUr>=KvG3-C-$n8Z@J4Bvez;;cY z7+%Z(03wy=MTe4roP!ki%yC<@N!Fz(X|!H5re9nE+CChX5<5c+TwX=htWD0yVN=lJ z<|#Y@1@ZFC$7@0%#Mjek;Apw!9h{m(yz{-@ijNi)j{;xzXbQaVgCBj8NH;7@c>XXA z>X>`a;oJgEjM0u$D09=*=p3`hQ09Cj{Yid|{PUh&M66RICj^p8LPs&fSf7#;9AVbM zT!7wQgyy-Tyt*HBsD61W%L2vcxH}D#2?(XMp%6z=9E8FR!$L&sm-r*&w!!@E3jJi_ zRMVyRdc_~p2Ze`_HQpfWA@7! z93JogZ~T%KPg@ydtcV;fl&4gZH>^e&ofi!4$KReJo8JAaRY+S1Y`DT}z(>y=Y}XtU zVwhfYjg>z{z0N!<+^~V=6lRBtLm8{yj4RAw53PczPd$enYU}?t&H+LtcEXYu0FGyW zf8KrCl3;&%Db(jJ_7pQ0G-6$zKKZbEsRLl~k3y;*IWJnog}m}uVR&=#+09+5O6Hgr zwnihQA4b5lR5B52jXKR`xjrs@79TQg_ZM6H;=<%F4|oJ07tn=8!%KrlT_{+v44$!a z*~NgNt}ww4BwB-H25w1cCIrh}1lG%`?m#4Q>@~;geAHcf>hNRoA+q6}hx414a+6hKp;`sbe^Tpp+sQ3h^ATE}hpK zLe7J4!2zWbL)j0VW@b85x^4moU`EYzw4bbnNAMj{?Irn}t31DT^OK(j-aGUUz0-nT z;!vwy;S#B?7IvSytD=?Dilw|4ti5K8?Gg)?vi&aA`xy3{U0$3*FXzO~Afy z3Kwr!7p?&=HyTJK#ofU|O79|mKM~ABQ-rRE%q&yT;{QG=$RYfSEQ_D#{N@nt$*Uoj ze}6g*6FM495&uaKgEuR4dRftyvvL7;oLs)TCyySvySMh*Wj2NO>i9?_ZxLo~h8vuI zjFY>ndVczNsgOXi?W%E8zWq9Z$=lxL^)7)%qn|N4pZ5tWb87@t%Eh4Q5PhlFfn@GI zs7@m+Q0Aj$BnT_vR19z^AG!1GvPO)8O*7m`jnOaK8Mt=yssw^%G}n2a8$i?xK09{m z;HpMtQE10+gH)=n(nQJD+colXa=;;!eHpXRVm950$TY4QIM$BEgw>5M=aD zF=s4W#oDBI5w$k%UjkOlTkOUxTI?-V>N->gVhz{+jnFag!1D@2D1nT+AWWQ)m_4CL6(ve&2|>+h6`Qi_62lvqRvUg}chAV| ze-{4`ad(_{G*qZkCs+VT{@HXrMa11}#fWa>`t<43ANm+?ha(<@uYJ6Fe_rt#%xNK1 z(j~gKqGSXA^&h@YD$B0JR(7-Zg*yEgy!8GjZ8~cR3%yp5Oy9teN9gzQbYJ_P26buR zY6Dqk(R{KkP!+1l21%i3qm*5xgLtKOFhv#?`vzR@dU5^S(t7tdDaR}%QiGzMsu#Fj zb;OO`bNVwo2~}{FE*x){Zo_R)HxpWRAH-zmRDPH#$E!l94>qV=mDdf%R zr9wQ*7p=sKPg1%HFBwMq9h)OmqoE4L0alFDn+uu$SJ+I;S6t+{;@^X~c*dq>eACG` z8TO_u9a;m)2j|;82flfd*5pW~F6`AW?BE*NMw|@%43p4k!EFsp{}R5aL89(23ao6F zOWXO`SezaTA6&>g76?<`<{iWo?DIvvT$YCGHf@Ibb8IBdS`u!-49;nK{r2q{Fo&>= zb={10XsU}`fk$7?W^fCtSm68b1QUc)gj7%{uNW0n_%zm64{u@4+LTAXyOlQn-j7za z6M}H!KY|x9UDRA#lpe?ftLm%lXG05vbv?M+@2gr;SnwcASACxBbDiITH70RjQHM(( z`%BfHP7LwPCH-DSSZm}e%9W!6*W^}rv%HqLINkj4Iu0FzkD2~3K(jX=m{92F2xD+HM59{tv_OzYfOTK9%? zyXf1-fiq=a7$5!;JvNbHapWHitDnH@6&4m(4fw%D6kIJ5=Iwd~t*@tK{2PT`84jPG zF)X@nOlOA&UFTl$QHD$CJ$ztEp|h*^Yy{tVv6L`p*KX65q(<~(BvfrvCpffx+Rx)m z?O^@_TSAiJRNGO{RTA&3kzITK84gqCelg$pbgIgxaC9^AIf`4JjKBmT0tjIbb~Z$D zl#Q5q?*}&>dWZZVxbA1ztHC6y37B8;Ty;>+3W)QsO$S$K+{~2-4|rtgru?1TFPpJ4Oqg~Z{TXI z&`1LzPBOUuobskMok=o}()j?gP+)Nb;vV#uLY^x}5uLn%FtH%;5Ony-nUzol(^0bt z^B&Y?xxdL3@5NdP*3%$6Pw%+1;fi>-*9(LBNk&x{8>aqCuj%UPFzttt<1^W`SzKxO zc7+P~YMeKD{wu!7!SuFT@!|W)o(+R9tODIG&Ucv=!E~Rhlg*tyglUPCHuo>}?c)m^ zLN+evtZTg?ceFy#17G>ejUDi4$xK80brx6gn#mT%u4MjMMWWnmt{Q*hrmo%noXZ+7 zx4b80!GNMu>?^J*^9(|ZJuzM-v3^A~0!Rr46^})+Q*cGEU885w(LY-jf3g_iNyAtm z>TO!lDsQ0+0@F>yzA0L=vmYAFaP$pl58gW^Q;1^&L$1s)>p+q5r8B7W62@`;c(Nw# zJ&*voSP0lz9%&i%qUaPpv$?|$!cGQuaQv(1`}pvZRXg;zMnmMP!KGg_oehxe-=B}e zfg#UwS$a}&NIBwt{CPnaG)T~w+I_Ek<=Dp}Dl5m!kndBX7odRR;jnxj1W7bQdubEs zBAQ_Ctpr|>61ssZ;`vP?UwmnMXj45+$8`K2rfCzwP=8tZqWF?w)&<6s+8J>_a5k`l z?G<3@rn`o5Y14%C6-i+U;YzKHdWMw0^HKjaMo4dh!PLTL$+3DfLjd zO#x_WGzs<^`ME33h$K9$C>mhCCr5s$%eS*{xkkYd{e=w*Hj^?t=Aa%FsZg(4XDJ&% zr0_Q$B}&9#qNhW3$E-`uBT%K;gqjWgk`)k0euxXJ{!oaY821<2@#Zg$b$HzmAnj*Q z&^-rRIsPvy0aGg1G2c)vd-0GrP;izF`dB-cmAC7~3=loBShSDumSBaFO((^j#_lYaHtr+e=d%zLs=`Rk1ku5+( zUyi!b_WG4?3GqRwzhtzm@!_S6(tW{qvM=tWOvadN2|*3OF~^zqrNNUGXmP@PMcTK? z8=p@eAfGs)(5nK*-cF?U6nd=}c?e))GweT}Hx=PWsE6zk8-%+J3+Ux3{er*e*(#pu zA>g<0WqaBZ@mly1*2z(7okPPufp=vV?P zTUAf)g<)j&i+bkTf(&l0p&CCwR44<())ZJc!ljOmXHgTeoS@hp}W()Sunm2R)VR5`=BVdoD%II|V`pj&T>5Z*JNSGI<5Fio_^DssF6hQ4@8 zz5xA(L5#*K)jQde>WVUqtC?0i@xqHmhl`yc03Sj=`kA&~JWuoqu!p9V(?*pHpeENm z@AA*hjizN{pG|wV6mu4KiW8v+FEV8b`Di*Jk|~Wy)(?WcHr3pcwYdJXfQR(N598%;dL$ z|8bKyr`UW@n6yUd+FSBun{sJ}r2R`z$+kHDwB_kG-7^^Anc@u1iA@cOV?kP9ec#R@ zW3L@H52)ndbgWK{V6VozV`O$tp=1CuOcJ)qXR)TN5sffZk zyqJhlEeqFh<|tcd61Cwc&SI6@Z=c{h!oCENH`=?N%?z<{%lg$m4|KM`Cs==Ej%>(| zL~-+m?hgg{&lUhenAr}I`t$;pJ%o4R^UjWi|VD`-7FhRn3-E;_>Y`SpIo?Y!qN z+~d$C#Yv?UTm9Ypn}s8B4tsvD+6O)HM3ymI=NG7i;#nbat%O#{No!Db9T8-%8Krqx zGuDe}zmH?~sqe*#hFvHJ&(S}8{A@7S_C}=PKzvx(QItRB@AvCpt8ImN?-x;r4g-qG z!ZwgIeSsZK-9)V_Y$pG}Pm3-q6SCYoC$ebD&K6p~pQM=9j_xR@FmbF6=XUtA>K0g! z|3GBAl4d6ld6s4r5JCilBHv=%n`?_UwC2Nps58q6fzZLIihwg^uJ@*$olP{9X`$kf znY1i4Q0_sdfmAD+UzPdsQyx#Sy=Bl$+>@lMdWcw1GOR8MK#2M??u z+o!ZUqfhEH&}XewpFJ`~D*^v-Pv^tN*JcmZ090!+T6P6ozJHLz?vz4Hr?bMr+ph%d z%Bo10JDxfrAjp_l_E>(gaJcVa=M_o4j@QO*F+I+U!%font7Z)r*H~XHB(wqBn%jsc zFDTj?{rRHK?q$a}RA^mw1Ug4VTEY4*eIV z7K3?Ba)pp(|Nj!F(Y?aTGAclyvOHW*3&S*2urxT(uzA==m@5<%HcVG#?U1rt zYaPQK*670aFZ3t&$OZ$4>N+RjpUnLlS3{_8j$L_IOS)dEQG|Y!(6&{hIiK0fuV6&1 z*MyzsVT6os`^q>0$Z+IR9MHQvI+r?Dfa9XP{+#x@bxrH`jopQTg?4y9 zhYqLqbi_*$V)YUl6ela%98pF7WKL_Wh(cCNOrcS;>wOymq-_&}mO0fh&0&#Zg_cds zLaRI!0Vx$b&K|>#dIF~#Ib7`cQNqp^DqyvIsH7&~9Cq%WN-_HCyZ`u|57lqq-T8Te zQM9T)$E(3*6dm*8^yu@szR6t6NADeGVdtw%e=HxZ@PZ#+ednH{BHLUw(-`csN{oT$ zE}%Z1*0&Oh$x~L9ZtGwxbTu-hH*cjn%^WhO@pmM|jU;Od(1QRWB}pFOo-{ z*n9n`hQ!#d*d>~FYK+CCBLXI&oJAB2F&qnp5DL`&8>{t+@L$ z+rn2>`U_)QHAhPBW>^oflZ3BtxG(io8KcUR>GCHYrMvMpLzi5A&X1ecm=Rp){pWFE zmb65@&8aN(H@-+M9R=-xqa$f8U9Wft*Vm44FC}!C*z{2neqRhM08n9~8n5h9@8o*( z#D`1%Y~RKTda;^63%4$1{t?=cBYKO7AoN z_m^;PvNdL!-07lhe%Bl4}K@OaSBV@jl_V)qoo(a zVu~$4=7Q#43l(CA-1<30rk!_R37QW?6mQP>_iuIbBgo!=pq91k&-$2(_u`$MtY;;a z3JzP;6dSh`*mM>l&nSILlc(M&%JF$et2UgD&clW$Ytj#pg}%&`nG-2=%2dH_@bbNT zr$0+RJm&7ojrW#+e@3|dregY9Qci%1YWCCpCAD7OM6Ve#M$b_rHw*2{1Sb3m zj6jDVLd~ra;axvy3c3;T(-tdfqDwbe-W+Io z#N15I*cJ7dGsTcM)M&VjvTiOfSX#vv554qBABFE8G4#noLgdQ&(JPAaHYkWt zY{ciuC^*pj^DIq^TK}f%D?f>s82pbO3&giXo?~3xo~EG{{{G#*xmdYnY|zk*IlI$?`lo-NP*c|CA zWAm&1^^l&OWN@)o(*sx!{F;6~YsJ&`LhHe5)vaL=8On2Mzb8;54TTy(+t01B!e9(B z0pGv(n}7VRTPoe|s-A61*+yC}oT(gddueAFvDQ~=v!~UnxQS%cm z_t;z`3uMZJf-$n_Pp-LEbA)uwoYu9;;?Ip=|6vyjejo9Jn5px#Iu___%GFk5@YZ?a zw^e#4JBv06l*__vGaU<$%6b7D^a0a~{gv3Xi|AK>p^28viX+!HPh5^qEwn4CvhkfEwq(F%*wS0@Ni17XDG<%!feRA)~2fq%J;bKq0 z=wQ+|c-9y#g=E?Z>dU?SS=RISDrK$bWMR&w>5Vyje^ z%V&iW+{uUFteCDCX9o`8t0B%?!JCkoj}77PsiE#wr|=Zqq>(pBYiTk8`pD}D^y%N@ zqwW-&QY3U9mC`MMWgl@m0yNcBOpS*#+^R#z0b35?b z!D_X2@uQh~#izSdw0?Mdd5Dp#-{S5QKgFn^)q92=C`;progPI1JYO6n;%q}eQJUJf zu$Fgm15QP6mJrwNsAI1wwAZ(YhWRfaS|oTnT2j`IY;a_Gl1_uatV-R#=<1PSG{@%Y zq(T&~2kBIJW$2AWgZux^*Nbm&4dEaq3AD97wuQs3aJ@7`p7+RA)`tj?R+2*LWvi+B zDF-!UsjZ&~;_{IAtOleDIj#$W_YbWPS{YLcEjm>eu}V(UWABxh$H4JM=dh{N7OiE` zg>;JHwmgd;R6{Dvy-``WcU>+;)q3r8uEi>7`z^WF>{Yx|XghL?g8k8azCotJ8(L3pfT zr9@)zQ%G+Oral#g4B@>jQ5e*I)=Bks*QkV@jfTy%5#;5~MYL0p=QfAxiBH9fSA+o6^{!r0e6yj*QB612Zjr z3dJpi@+-XqmFC+ee4Yl6v}1=d*rhDiXo9$A%%4059>{p>fOv-}xk=Un z+mQ)!qH5NnJGW3{hIXb<{`2^D@P#vp1k=b?&)VYZ+-DR0XWhZ#6%Vr_lC&hVBP@fq zXMd}f&koXLA6f}=ad$|;;5wo`s^YnVQ1r004eOzt&oXM1cX~=r-D$3wb55Ij*2mr; z6p_){Qp;}H`r3R{tS!a?64@P>m1d7{$ym>Z#42<`0J^N7fvRxI<<*JhXFGa}O4=U6 zRf^ul(?D$aRtJIef%NntAK#s!q>cZi&4Ql5g(5FyOR1?nKH(B9D$As2M9P^?*C~h_ zli0OGI9rBurX#V1Rk$+WW{8{1Ls7Vc$5nZ2D_Rlj?YETp(++dqU;#_YF&lnKS-QoC z5ppPoAg)gUU`K!ycjJq<>`8gty|*VlF*J`S1=dXxPVG~Ma=~i3WR3zHR30>HD!vFI*3bwR zItu8VZf)g)U0KuGffiX~8+2n6Q{HPSDlVS$bk&4?Wgc>_ppO07AOdp0E3e)i_;n}Q zIXWv25(ypJm1Y@aXZw_>FktDu=s6oKte8-UcaJnEPkc%(#ILl-U;t?Q3o2P$MV*)-+TM+cZ(fE_gmT?+j-B8)o+_E8$rIW{%*{ z)i<@Zm!T{1!o`c#aBaayed z05yt_%st7gmJ0a-w$pup*g<^#RpJYhHe?4X`jrL3LiG>rI@l&xZx7==v&LzcMMY1j zEG`mG46dC1t=pNRmB>!wmAUH+1BqjcRAG)$mFJ2v+!d{HN|LRT3g|UZ9^|&GNM1tV z&;lq-C74fc2cwHbN`G3frnTS@RmP?_I3X1CUPBwrELVuqEg7kf!_OFT7T69o!%D_A ztDX9!M=fadHx|835x^vuyp|bsrpatvIN70!4|N@VIn;w24;pvv8CFmt z1-2Zj94KABVNqni%%fBHad7s~L-E$8+S`7##dgnqyBg<#xKFizmQ2oG{HyG;3>^}; zt^2bWMee|ZZrPWipWI@In@voDPw|va)~lU+yi;z@wzD5vJ9y>YL8bctp0K8G9`x4n ztKGK$L&LLIun}k5CNDABWLgFJkJ#q3b`IqrZ+ZLS>8qkm<{==4s;ym}tkHn|vdt=! zBY93k!fc84p%WVp#%KWZIfmhr^xUpu8cbl@1x7K>vYr^$8wTp)v&6?dfJGh!(1)ME}KUMB@0i zpA8qDGR!^|M<5iSA^N3Vpqza*4)GCVqm<>gJE(GjooV+o4`21^<^!N~89HQJDs_p%ds6R>x6FDHSOTL| z%@yF&`=Om_5M6+M^5kR(=u35+AZ+dF-=Cdvj)Nx_`zyi^O36(6ACk9@fOK^VAsp=eUn@6E$X?n@he7S4A?I4!!9_u^1Q8IlxL77@&LNEJPDYW$2>qIb;mz`zH;@4W>8 zK9DZW0X7cYq#|&3UjdCm7sMZdJNy(DpvoA4n;A-+ixa3MqVQeHHIQkAsUA(&WqNwE z@mY)VWyGC0J3Xy!0Cp{@c?d707i(1Q5~{mDVdk$?k zUwGCYH-G!N!+~RW@+{x=A{1+=JR@(zWpS?2#F9%+2P-|+r&&XvWy1|tN02qMGj&bJMPto{PMcGuUIpZ4wR zwSuTD4wY>Ncj6Qilf(h3=9*BI=KES3JAE?rOC3SoCU3HBUuo|$;I5hrXcRD5{VrzBk~ zmGntM=xG9b`|w5`YKjxK+Uij_FVp^951Euiml)dJql5ZYMOOF_`hX>K@B|^5Fhrb3aAKDS%nzM@8bF)`D$K6pE8eMN zwNoOo_BY+5t_fP9`GMRN8e`>C1C$;bV40HG+^wYwyNve{ch?(vOFJQ$sBUkcVMiUW zVQ`W8`;-pcgQl=Dw2A^S?Ex5>;8xl5ZG+H@gwJ+o(^m8H{ckk<_W3{<)FNCLf`aERTv~K(U)BD;KWL0LPbqk@&94(tK*_t_r2*xQb9mK zL_$D78ibLOZY4xoN*a`q7*c6OxlTrC_vSp?C*iv znM>byoiYHX2C)7I2iN+p@9m@Yi`4Bv8WA_PSN^*w{vD#3@uKk@ve$YY!{{q0KZkQC zl2XLB)Sn#8V_Lb{>E9oieYp;*8P9+~p5CdW*BCV6ZrXKzD^l<<%=T=GoLVDP;$PMYSq(DGI+E&Rb`pxq0p92>$5gv1+*b-%@DLb(7_hg=vPhRqZ(VHcdO+$9OF^BAWit-WCrxT z^cuae0Uw>kt?+3q=i^Y2`q2-;*8RgkuoOlb_;Pcs)M}8NV0l1pB1Wx}bvr&);ASDXB*Edk!+DuS$J0c~`vJWEQJ(6a ziAiEMO-EY~={o4=LlqFP9ah%cKrh;YLn!!G;F5Ph)SLN$y8U{J=s>(nMDY*|}d+lRG0&FAfMVM4-nbAT&1}5uf~E?-Ly zggxCrTcGWfn6?_IjG{}*Sb3kUsH!GF)T%D}n?TRkjWN;ByLgJ)ew5@AcuTsLxRRF!4u7 zFtaVX-raWER_N`X3wmw*HG>-hjwo61uk--h(`NKbmOFeg77#1zf85_I`vhzNV%I8~ z1DdHv9gbtJ_UHhNt&d_nn?iI9Xi4dTWK-v^=l38$qd(KFw7m`@RseN=7t5)ax;5cK zuZ{e*nW1+6>X*EdlG*p}$AG>P0TMXPFYfrERATsZSmt0a1w4Td;OxE+$n0MX8-5((t7*~8A%UZ(V$Zaek&C-O+R^vm&} zTi97r?V;facm9U-_4aWPU$*VddbYanHkbh3a&n>2%iFxXWNq1CaFpB{_j-_S#wc`9 zbqfa3G*0_4C}gI4?p$|X?e+e)QsfxTR4?Quyj^J11JdV<9wgAgSSzgCT^!YSXg^>= zZTyxhq7KX+qT`TopDsy}%HegMm7Kv!8WWp3Ph2}ZV0~tRC9ERQlkZ~)9y6Sdt0_rp z%IlqG=axP35l4_?G_^pWbS9b+aAw+hz4hi1qq&-kk*o*ujunCC+bW*4PU_p!wFSdo9;Ey%ULlG5Yv917^DME|-JUXo@#r`Ds6k`1L?=q>93ncrfSB5j@RwE&e1YilvZ}Vfi70%f1EyQUK^R-vTGyu<3 zdIVOWrQi6A0l=w!jH-i2Fwfw_UVE9g8>Oj+n=iT(xKSDQ!2E-670US&n#zEt!O$Jc zB|UM^92F0I8mz%a@T+Qn0FZqIo{!++dybAquQ0%w9({Ql9qJ?75*U?Cq^B zS_4~VutzqYe~Ubt{|t(Oo?C<-chXZ4XPWsKR zN<00gro@3x9v_6e1%jt_)^L~fgmqVSb;fO$SP6E1I8_5A8A-XFbx#u5H2gJgb%F%a z4SxP}*G|I7r@c>T&Q`7CnB?c5?-4b3bg15M&epvh1Jj5}Lh|CnaHKeg=G=Kc%|uc*Jt) z2=>D=7qE$__neiH;DpoU9}j>owDB6gn!`Hp`3{YFsPcZ8PVx+tn$v(5WQt0PAkg`g zULUC;1p6cL6r@^d?6Ho4xf&0T<&438txn%AC39 z$J7X9hTN-dgcXQh`%-VkjF%K!x&;=jbfktmtgb)V%=!TBrT4m3zlPgz8=r`2A5Y=u-Hv+a9`BO zRc7xOt-A||P9hT^vg1dI!1^q99AJY#_Iudh!kTWLvuovEFg?*`X_546=`Q`eb4a;G zVA~l+cIzS9p$N#iu8CXhXYj2F71n+tZq_(}T)WHku1_rY2g)6Ov_03!E}(`^LhqF+ zCiG&vyH>!arg$)j|D#ccO_5y>HWfd!e&yDiZJ?o+pph-dyBFsN(DQLea}3RTmTBJO zCu%985w!O8=~U^^bP&ay=OBg={1?q9fJveNB9BUn33m@NzWlb3;Bt|4?I6{rw1=AF zsr?jBJ)ip-;P=HF^YGK!ixabZzcy1nST3xhstW;^8;I?-_NUdM0m}|FK#NA``v5hg zD|F*(hqfYL(^!ur&qqf1foxQ;3^@o%Q208ijBq;HDVrkfOrW5poFSNoflU~A3R0!6 z7$I)Z6~1o@{naf%$zd3tD&lh&*iN|6 z#cV^roB?IJTp*f44Vbj`7sVFM9K{Tt-^9TghJ*=Vk*(!9H7W4QGTdjAAKc9`9ErUBTK^i;%o1u^9#B^3zr<_+$Z z3;-X2G6N-8XT;j(pLr+>bq1CrkQ#mh&|Lul&a6rD0Vn3h3zUxU-pP1}%JuWKrOd_z zbL3kNox8xNOck6~(}xJS0qO^XzEA6G;w0F-8&bFWEnv?AtrvxUiO)OuF|gClTqtNn z6kGJspw0Sha^1D@n81(wv%64)TsTh0!zVw>!aFQ=GjqZWE*ao&b<^ptb6P|*Yq?=I z(6=43G?Vk|F1P>Z)qtbLmRPf|or#H|YP)CDAYi1}_yz)r38qei3qMIDY$G5FO(LDF z3K>no_U8fx_lUBCI3O`DEZwjcfCzgQcRUFp1qIhY;Dbjzyp3(DRGYK`9}ZOBLQHoX zU-*9q!;a*R#$)i=1C{v0l`aW2;7}qSo^mMj70lydhskpGgVljGK)}hHxJ{Me`1`_% zbl{PH{`?dES`|Z0lWkYCB?dKaFgn?u_t_X@Fz;cpkM5K5kv&aMCwwgK;0&bhUILd< zM@kXQL`mTKdE1?mf%_2TKX!DKIP_puCH(rqbqslCsf5kC`J1fDf7)hVsLg_^d#67N zAY?Vy!ueFk!EA9wfaB507$pI8D?FuE|5OP23>Efyk}NqiG!)((h<$xap6F2736p72 zm05_l(CI^%{yjnoJmumsiz)T+lo1yk-bcT~}O-WG?5Wp1lpAJEabD5@s1376#$tBJCmDu7?7qgYpXqI*^b1>= zKiP4wg&dpoXx7*?mja7Hvdu4@#56cvfbkEb#eY7%fAHxJN%|-iHwPuYVp`a%HHtL0N%^F(#w6PG7DEwQo<~`#mN|4lF%mC z#Ut88-+V+w%`HeyO7$A|kgXBx;MKJ~Nq;^xQ{2nlyP^+PvyzI6G-GPBss#@{7KsrR zroXSeZeVZ({@g>F`9o?6>Jq<6YwRT!9)Ci^r}r;8*qMZpkw`e_-4CB_O zMjvQfdgf=a7V25(qK@rXjcG_pyt4n8tpD?Kl^dWUt9Jxa?`{3ujEBKq$5~h_A)d5c zbiCAv#FkcGL2X{aki-+x%RkFbU)E-MZoG$II9L=<4xgV`$-6!!Endr|xF24!v}C+w zd<5eayy*sF(cfmuKZB`%`2_jY=r9!g6KK>>HGjYf7bYS#dr)u1$Sa9YN;g>5HSRCY zY&Os09w4^pfXT-jb2-=h!F_RV(+s~zvc2#CDKSwa$CEl^hRM4-sKgD0qiAm~JQmKL zHszbf1K05GY5cia|I5gJ|M5I~nRc$4W4L{sW3)BNpG?x)w6ji%nbhBDCjuXZk0G!# zH}2-T7od2_)wo4#ws&7`+IuO$->$3UszobBI2AD?-q*N@XzKnr`zYj;jK8orRnB-~ z0Qt!81Nl#@5%uvDxCaIAo^>2I(z3gTSC5e^-wh^th_z>DEQKf6%D+&TNVZc%8aQvV zCV-JX?ti(fTAf&1OQi48c7~jfVK$d#T*s|*4@WbN>ObQhYdXVYlCZyHNpO7FfKN#1 z%o`jwKz+H(emqU5lGN1Fnkheg@1}F*7>BGm*f)fJjsz#bNp5!uLeeqGh_Eu2v`<%2 zW?uaW4mO6@C_vd~eeu_w8VQ|({TiK8T}ONe#@U~)a;Sk%zdx>XR3jjO)ljgY0_CL~ zKi;@sZyYXe%56&0c-EMvXR9m8L*BArn-ziAF^)Ekdt68qj$X1rgLS!?d)oMqtv@7# zLb6zH%|I7@t7D;~LoOm^0QWu-4jE=6V|v(d^}7i40UU<_ipyQ|c_W-SIvtptnR^Ai zK}%0lAPV;8#yO+s=DdeD>E4{TNDw7qEPjkt;%BP7mqjS$|K*bNcjFdge!ex1SreZz zRsiFURb3jdJ3DZI6KHlfYlYhlR@w^Lkw&H5r1MWORFC{`SKNQMMgRGC46+b%_@392 z*!QyGP*3g-jSi&cwD~5}AWt~g(7c>wb0Z!rW*hFU*YmgVJEv;?@?!quJhnP*+`ZM9 zVc|6wNr}niDoBbIKvsgge&d-kH5JA}v(FK0E2Hl&vUZv$xYZFm^l}4zY~(d3)N!;O zJpbZ_b3sXzI4 z+(s~Qvnq?dHias~Ynu5+Z;pr4L2!GCrCcfsp|H!1&TfuS05@em%{^G2I>reV%Ar5h zPA3*@$+~wtkt4YfeNUW}wp^a=a$BDU{FWh>h$G{7391=mZj-1Qllp4CHf%{{6MuBF zHu)E+SPCJ8oNrai)feZc_9HGgLV-CnL*~T^_8asqSe@I%52v#{&~EL_HyEedNK)W% zP=o8H^SA>O!Rhk<`84|DTPVLbk$Z=bWQo0(dh!EDT#s9cJUC0HFXeW4$IsdcgBh6w zukliwwG>BSp%ZqvMY;=GU2gd#H{t| zDRUc$m{>7NKDpdDUwEluaSNL=C>vuDbu0+pn|u9+TKcCIRJ~MkS}wf~F+C=3sn9*J97x{{Qn>^@mwWGb{x1&w zzc}>&;?Vz#L;wHd&}PDp%y@VcJ{w#|6*k1*k6CBt|)X45awOs6HiF!3Zmk+WQT z>g;gI(0*Hv$?zYMX0h@T<1J$^26Q(@L;upJx`X@SXLN69%-*8O?HOFB#x&&#=K61y z%K!P`h^lqiYoib74rnbFnZ=Vo2F8n`V=8tbd zs*sNhQZBE0OYS9Fp%_a-vL(gCY4cs2Vye$6R^`;($B&*mHexfM;xoCjnE8_!kdj*z zUg8jHJe3=kdjPx-i8_2Oo2t#WIeAZ=y(Izet{6uCHSafQ(B?2pB*OyVU+x^g3R#qW3vi;_E`!8}qhV9NmQzl8e#VL6>=Z-kKoXq_Cl{uf%J;8y>ebgT;;M>Rp=eGXCOxD*pGoH?{(ldKNB#VbcsJuA0a-1C(7Xu=aSpW)W&FkNmY4IX+!h$pHX zGD2jSvcky3@~ZP&c}z{iJ-B&y!|_a?O7h;q4&cQ|H=Z^>GI_^)6#IM4;6Fay^Xx_1 z0ICofe>c@K?8&OiM@CID+4#8JoEm6OyTmLOqLO=LGIZ-FjIY=AFfUo``>wXf^c6rv zh}^Fg$9iu^j?ixP(o0lB+pE_NnyBAXC{b1}VR@!C;6qd()VD74jy^*ldGmH8mY4IB zinU<)Q+q0S#S&#>ZjpHn_`*$Zp*xwl8%HfF@f2C2GcXHdGP+*!Tw9hStp_bMtd{Fr z&v2F`_x4`$GU5dX$_9@o?%91nw~tx~Afx@5rp;rIajP1*HAoRqWGxS&pNTuJ?%xCTdBn) zt_WUnMbVm3IJRU)b9tytvORXRVuDJuI!|UtR=mWxR<=F?=2{6LLtnEc)R8sm2hKVtMS@n#AXKlE=Z%lBY0SV;io5l&Z z9yU=7L6umEU3ap~IED|o=9bbiL|&AWH+q)rH~B3+STNZqzzvQ{8al?C|TTT^uj z*8%4D_U#}*2fi`(>$m6w8M2v|lM_9E#&YEv2@kzQM?3|^+XjCF9-MFnW|KX#`*7Ze zPoMd+&eM_xcsthNU%e%W$GExZ zkhbbU4-_Li+@Ecr_BRKZS$8dfkRZSPG&NCg1|(w(e}c`ZhJ2#zcCqIGy>^kIT)t)w zx@zL--=_V?Cj|s(fbwB{klRPeWw;f54gdzlfEM)Ni`olP%*M5D-tl{OzCfZDc&``c zyy~Mtb)6d3m}28(yq67q#|=fA6`s58PPBGE{`}P_Q(gT@Dh!AYjuz@EC1$ zA`%4Jq3XHH8_*BPn0GNJ2Llm6n&XKjX>#7H`}?c3}6Iw!KW#`Jzm&oex@y0I2X7kdC@Qbin1Q%B5>Dj>a1*fpzp$U_j> zzfgc19Y9jR?a(K(HX@!oX%v3*izA$j_ly1!D-fz9?wP1@VGUl0OTZ-$(e(fve>|Se zH%XibGn3;o8NePzMm3yW34iZSD~wEQpp*~r{rTSi=X+!H4N_4&w#T&?hqInXd8WI; z{swQE7$1lFK0w=OpxOvb$6{ul@IWQbG}OKDdW@B>^=^85$7|KY!eaMu)inyJc&EQa zNMw-2s=RtdLs0$ROXSCQn?zAqU$B(asA5A&$as*Whbf5XWT%+hCD7rV9|ApKLQMLz&GMyvr zT9VB`%_Y46X1A%`5q=|L6y#lMn!pM(*8io=7_WIZC7Pkn%2g@vn;!dG!^6N87#*!| zX;EFTt;qKc!>jQWF`a9M2#1FAc)o?g<{`ZfnEjII1?nU`G#BXCSz$xBrb94*q?LlM zyTmks#flNpHgLNEzCC~b0p&fOs@#6I{FNc~>H~Jix#2;>2xEZ21m+O;*N^$;gJZx< z(Q0@Vq1>oHlqp%|Vm(osn~qMg!QJqaz*1B7VEtCqtIlCRWLpMw^=J+%1mB!qfT8Eq&h>e}l23kTTXI9^a9xDpJ@qu{wmZuU@@UKg*`f zx9rbskshRJX+3ZfUEx=>9vU8+sgSR#NQf#6nX^3cf9eZ-2+PcSt^pK(J5VUe*Up*5 z7DBfD`8L{N^y znnmz+*uN=;aQmct=O{z_COU z1`v1I2(&6kX>}xOSgkl=7R^O#zrQy8qT2|2+c&H z*ZfNzQI_ysIi3WG-mQR@`xaufmfP9#*a?Bp)h0F zG{}qDjSBB)nV1B=4s`cHdXZgFyMXJ4`9_9$Aay@2a_Nz_bwnk<)z#&I#jo&e z&O}I5_%38?qK=B6-+ufp;^giJIP0I=0ynaK%S;k)GD%Bk@(}@{xfnJZCiT!G4NQy2 zmV$F4bR{Z-Y-m&Yso270=c zGO{uO1>=B}fqR7>jgmD+?OkeWc-L$EAIgdZo<}$K7CXDto;d8F-FUDbViv-DO`boIqAcj%o011ZAu`2Wjx5>+sDW6%ew^;McS?xWMB%a` zTNS@`f1rII4W1k?0O%g>&J6&U1FPu|3Y8}ij~{Bt`!7Ss{e$*SzC2wN>O?)^P^E*Y z$|pvB{JIYPa;}z!h>4A*G&M6rX`YRJG{lSm{F&&PIwa%0JFk20!YIp`jNBz85bM&8 zKZ3QrL=Z|x2c(AWKpmrdC`XCib0cTkv6VQTf&N;5UxPhPfilq!F73T?SjT;zt#yrD z)w3Y41(O$z`C(MhOp;_oG?~RFq19hj6a4h11jEhBE6ATEnyyWsCMB;vu~E;AJHwd5 z?wcc6iM7XCnWHfeu(Rg0%SFaIYmZFUL>(`#O&rCq%`d(1LbK(2z-dX!&cD+s&o3$m z1(tG%Mt5GT3kMJm?E+I&y14CJW5magY&86~zMedhuT5HCFLd`iec+p~Ur1v|hQzQq zFUpXkEtuS_4(dx4!TbiyW?!}mgdHr-Roma70HPB>a(%GzoEUv2$q0~(R);95tj>Nr zj4rkYqdke`lVc%{xrP(i5N9@t;sk7p{12AR82V^<*c-0grf~Q;EAV(dG<*T?r|b zGelx$>RdGnr&j>zWLTjF0BFTC7v3=?xEHJn;?k7g^IqOtXblWJ^`D%hTFkcS`<&V_ z;_e`Ls?YQBoFeLm*^hGT52>nI5Bq4?z-*xPqv*iq`^$;<(R->AA0MtaUir{wyI1Uv zC7+vxVUmKEo92+D6Sd{-qXf6%ev+V*2fof6MUpmze096p4=>I*{`_%EJNp>qUmI{oGR=eQ-M{;wWKM$^!UZo77edf90G-vk?qenZK}L4Rjc;9iJv5PfE zWx^w5E^KtyGMu63y~a{UIMRtZB!pGC8Vb3s7`taW1w5w#tAiLlAD0-qHQ5e0O!BZs z@BF6~&x@nlKZL{}IK+@4ORUroAB@hZjLestf`&-7yi`ec6~MREYe2ny=Zu5>AukWN z0tHl7j?E{_GnY_&d0M*Vdv0K=5wZ1uNEO^%D*>7`rC7ulQqyg16m67j^S@wBvSIt* zT1l`im_D8lfV1^rKqA5JY^?$%_fXbDBmI7o@}p-Xvb=wJh1K5WENxRVnAcVrd-MI# zD<IjnAjD4nDD-s8qu+7)pOjf zm*{>!I->&_h(XYPZE?LM+t35(CtznPWIv<~58)-5@)N^1M;h4v?JbfWPaaZ17iHd0 zeD!8T>-%v`VVBL-Ik0d{MGSJfRe;ZJ=Xh+R9=ev{nLcc(xjqL2!nfE6Ct;gN+9L{J zwIi6JwzjpXBhqH{!Oha)` zjO;@L$|bcwQi6XRLejR|!Tn*+qrTC^>hq$AU@gkkDbk@$wWk5iI91OTMXvG&iL6*@ zB_1ew!3X-^H0@4z4~kHWtlkZTU@ldM)d{*JeAH~JwA;l;v18e8&r25 zef|8#x%)d?EWuvdF$sf2??x=;r$>b?zsAN^dWstPAESSIT+sdLF^Bc|M~!$8jxWM8 zr~dVTY&q1h@Mzd9T6-ONgYOt!X#1#PNp1R7wS?Yjq2!fD-m)kokR_|f&yDF{K9Uoo>vhDGjyl&UuL5%m*3+{5*eBLXk zDnU?QTEb)bsjgKT)2dTvc|uJ|ZLL!S@?QNyqDYCr=-q_QL?^>K2P;yEyDs*gxgsdz zyB%&#n0e(D3KZ3c0-=sq2{r?XP@aINF(!)P-SEee@Hat0BD*2hkn&WyPrk?dz!b zCf#>is=`~?cV5wj`80$uK;9XgF^IT^1H!*XmKQdV#Zm0zuz8p4{Q5edrSrr}0+TsUcC*RX&-iHu=l3~=H?V|PNI~%ua{paB{>_T zBqQm>6+5PaME_-1%viZ4Gu8cB`P*kZ3z-fIlXCVbAXbZ9dODJ zZpZF)$eyV6rqzfh%k*D@crEjwRVt{{FOFGF?ZZOiR1iCQYngcXgt8p+iuWb=^Pk0P z+m2U92S~qu7Hs6%iRz4`cVZe_J$^EgYpS;lb1zx^qF)txOYREpvXO_+=(gGeR~7K4 zUSZ`>-d2k1X7Sl>-+jc@d6*$;PCy_V@S6C-KOx@#@Wy1B^&SggWnTd*Ef_@&hslG} z1lC7yn8d}!r;h8~HdT-4XT(upVVnJkWxt@ETBxL)o+WBM$$xiSx5gR!!i*2ZfRg9C zQa7N#6%~x8eUj521`k-8*tir2;p9vQaG{he3iwx3#?cGZ;~!e1@?08{MR8>b{4x0i z_U{<82UVi8$~%;RXtZ5N^+e>@svb_hWp?F@UFyr1g&=|PF@wKv&zvt+;$ExUZ8UGK z{WbnzMKLbl+s@9?yZwU#h0_~@c}Z5EmR$}zmVr1e*)?8YV%jl2`)Oez;Z%)H;uk@t z2diAR6ZP$3b0=OzneM;hbk3a&tp0Yk`JDkFNLg#PM{M!SAD$Wd{CbQ!ydH@vt+SqQ zr%Govaz`p7OKx?lD~eH+N;WUhL+=o0KRgc}Lf;iI-#eg#uo#v}9>N*KeJF*#U<_ib z6I@{swT(o@vGBsNLRcd$X;EDO-jjg@ZX)01WoBEu?ARdf%KQ}TaOLfy z`r~tR7S`LC{kOlD1v5D4r`eo2OqE0cSp)T>(^?rh*_0!QI^|t2e3fK@9Mc>EgrHmD zflqLV(NwZZiV(Vbjq?g4Oa^Y+|GefG#LkC9Obf-W_n!Gl>!{sSam9Aq3zMk7mavR$ zRDvrj%A#FL>yD(xKVP?6p@;Ylt=^<0a9cD;c^Q{fAe3UIJh7VDp-qsJCQUabtjJD! zQO4rR*hh@;u?GePS%O?sJYckg1g>Y{*;!@BBbTM!l-V_DRB6i&HgY)PI$vL2Lu>1S zMw!J+AS|(cLSWu_)*D`yd0e5HXlBmm&e!4aV|Rp57QT4fYPvcfzvE0~fOhEZ}6(XQXVxG} zdjb~c>Yxm?LUtcO>F(#w_hES2y_bfk87(#a=JCKKQ^Cc;Td~{vaC?UKEsD_XFR5Sj z8G%&q#2OBIQwRIEnkY{z%vIk`?`d!RUCKfyi(h?rt|ek(@eAj5rTnl`H_mFPw&Q9% z_BaTmWM5oQ&X$YRte5HHJP!=Ox9~+9)WGh2R;uq11TXLZ&aL?Yj{uK^B=70TK1iNI zK`mIT(pJwaex=P}^g9hO0=`B8YYEe}Zr>|Y=n4RUPB+b+I5n0NM1u)DVojbqHtR+<`s+PKm(tgajD60=b_RI_T>q=+dV038Wgu zcrDo!oXamuQ-xOFsin6;32mV(%X6sRcTzzjP6#Yub^G-uve!p@+XyK9OG!)De2^yt zbtbbHYkf_6uzm|5s+}~6Y71Fn%Neit;G6S0PqV%Sjn{b4aQchgsL?CFQBTWq3U!NV zUn}4AwxHc?OXUqQHiOz;Y{-lIwb$x0_y4#31Ez5r~EF;F~iDU}Tvj8uvXO9v)Uul~7Pt4quvj^yyJoSPx<$>YH|9hBTu4 z#8dU11PcUT6twI3BL( zJG>#LjC{GX4K**AjIDcrUvYCD!7*OvMnXGU;P&YguLDQz$(z{N;V)CgSN1|(Scb1& z5W}B$hc`a-!x;XQdy(NucPBl1|Nd6Kler3bmA%Q2KU+_Kj2=T-phUx3b-WslP^z8{BxAz$*$2njLB7DC%qw^tZI2wI0MYz(m@>x z4XASjh$+Y3`}KGdqX$y#yzkxplu6Bx3e|jmrUwphI6SO+r`E=L42e@Lso%}untKdC z6KUIBVSR(Z)TNo;jjl`lTU|}+h>H7ZAWq>&T{6eJ!pAz1s8~=6e+%Q&Tlt{i#tE{Z$T~huIB? zDx0bFA{a9CmRuD4`(DxdPyt^FHlY)XKpgN~<~41@)70$$mMwQd6pp8YOqw3V_l2KW za{_auEcs|Ay8G^L85&XjpN#@eiIpuXa@|Wz6U&ZGI*Q7y)QcocOtL^@Gz>^P-qk|T zxFnqcwl3PW*4N&Wz!#leqZF$X)L4L=BM`}Mpz^feX1E@m@i7=7c~X^%aN8IPa^0TF z=3f;jE=W8+7yv?NexPCr#)BpZWNP!=LlzT-(68zyfBpKE&O2xo2$b3C!Xgczh~~pI zu@m5wb}@^^U%kk4&bfoOHCvV-UU#ToYis>&ud~qLqHJ)X+n2bG0aZdl#{Qa?3=da` zU>b;h^60X?gPn+pQJ}6U!r=8?_sY5tth6KPq{^RT31&@sO>iGhBP6~y`=+%l)M$wzT(5(~%FfHV2Zj^j>Pk;#^tYq;BNE6` zg65P28u5=YIX`walkTqUUC0CCL$!3#u6mDy2ONrVchi>Oc`f-i*Wh^{K3HhH*;;Z_ z9mg?l3B(72lFjv!D=V$_PT#>8fg$cYcGTlfkATxjEvI39Fj%+n)6Ia8$Z)2UXQev! zz`p6Dc10~aM=Kn)f4fJw@`ax9<3R%85vRNW_H_7IzSf(GvNce{NfrUS@lH{hQxvMg z^@oiKOKzIJvLE%6D*L{2Yc0@Sq26skNf1OhPwF0woo3Y4P64;JHC86rN#s%a2tNz* zel#(yAlikcSm~=@&w*-NOK|k9jo~_~s~nGr4$<|eF0ut6WbC}Wt^sCvZ*D}&w)r}Qs$CvBVL#S(jhBQ%bP2qcR^~DYZB1Trb{zYND?xjQW;dO%JFeyGN`pwP%bm~s-6GXI6i^HAZG&t> z@ZNXUdZ?PEN$$%aTCgvw8qBxT_%jlx*s@=l<}70^LY8y^;D-mToE< zQdoYS^EBN737hf`XS?he^0%=6qL54Vi2>$FmU-bS1!U(QOcC^mAjQ0d{TSpT1RJ}% zk1`%R{aoj5qGRPiAY0sBTs^@~{P9tV=@qz`tVtw9t3Q=RK;UWycPt1>icQX6sfU6Z zgNTFT3LVT15wTCNWA*-4b}-kYV1RVctaIfuB{XM4X-5OYds9WT#R_RGdf#d zIMugOl0EF}M?8>5x3z`Dfb(8B-UG9x=fV~;BqYS5J2s!0HRC5@vf??#4T`?$nuGpY zlwXYK?y*sHdLbx`^6^>p8V{s51ipDQSOkTFP$LJ(W{gi-OpX{)3)+HO@z{HX><+;6 z@3lcKe~797bvTvi#!!Ah0U}bZ+86Ah32d@mqVJIJEUC4Z6?C#Y`|B=YEK|_3G6->V;k&iV1hHAMAIK=*SUb)hczi0Oh?P*5qlfS!`afsb^S^-S$m2@Wik zQTWoML2=|$QrKIgToo68_?gaAjhkw4sylQ&K%{eZq+KODKLMyiXLut&KmM#(@%*v8 zg33x;35ATDTr|YU2Z}&P+7uDHMpg)X|D=;=)=4Yuyv!z%Aq%w0RFGxC7YaM~f9^@A z-uHM1YS!w-#*+JTGMT;rCg8rU_WH2M;Ou!J(3dmoRCQ$Gijyh{0;PFg`)S<=TIE(` z6bkfb8T$28$TEw5Q!w+HSy{6*V%ZG+ea=tG^?61OQgS0`DfAiR*@tsWy(Sd3IgJ#6 zhdpqC5xK1t&&a}(3@SII(GXY?Gq*-6C?2UZ=4Qq~tAgN2=L4h62a-T0sRtN`QlAa0 zsiL$-YAPeE+E4EP9#m4z{gNbGJUCG{*@=#J)*hYo;I%d52uf-mbH^3MO2yc%Zxc)i zycfiAG>;u*_am}EAl}^Y*rs4FLlZ1-=nM(TfLsXq?FLzBo>9^4FMj*Uz~Z;X%0BM$ zY(R^v*_-Dp>o=h}JW{5$EA^>S&D zA>La0TFLrmMG}RJGFF9rH>_}H%C#56pc-eO-7#M7aVyA_P$R45s>rDVE4hgKIvRi> z<*H|m6EgYyHBk40FDO5!kt1OR7Om_9YGc-I+`+6yjgEy4tCROnF7^~4%C&mBS;We3 z{7&DdePb93uu;d*d&q;qxiU*C2JfF_R-R<7e-6FM4jOEgrB z=S;IiEoVSWZPplMsDj@=>e8eWbEV`5ouJsYV~Ut}<1hz?xI2$e^_L(o_bJavw$}E0 zdQ9|wytn^7r{GpLvMzY}>Xj&4SrZyTj=&S_cZS<&d|?jOy$MxIMzSK`i zMcwLOpYDHM6~cYKE#_M4b1quBJKZ%q-Ma!(~C^tl_hgZ?&`+(duJj%X%lamAl^_Ro9#`=<;sBle&b zyKFmkzbOuN3;S75^_ms-wL+L<>_anL${jA=moF{OFsr1kFDB7%kL&N3`mb-Hs^0v% z-3C@QaT*#=b)|u`5OL4{|8y``1&9m7A~KacQsc#I@|0d!&r}<<5T^+F$;=weBj; zjFT%b$}yD0-ddhjxu`*Pgy%YT5QMrJL?lVDs|4F|IhdpB#u8lf51B4^$**ITuKmh7 zlc^;;cFT7im9#8sw1Sm)mNRnAAUybXP@asraYK_^+c5`F279Q|8lQe3v{8d%%>_xE4Mix zS%f$vwRe6Hmz9`0asI{I)--_cF9tH4l7^8XDf^)En{-+n|rJ=xe0 zjJLCSqqUlcP0({c_r`dBl(z4^vIEy9kv&0z9NW|iIxRoD9h)K^p=%M&Kk@|r!+rnt zQG@B!vu{$PRB<$gUheXv?jCmbgA)ODLB*t(lr#ltztCb`S>OVhj?#|}jd$3OX#V{o z`)#Bbs|hmJIAB?$wQX$TVg4LLbdRz1V8Agly9G3S1-rep11mz8QameXuFM- zr7Zp*ukrgAsMJ#cbvjP>MAlH17oN8kk?ye%OYgR5fWq*205cZ5#WGlh|DT}P3%-9JcN`eUOZsl)cZ$}Lq z)aO+W#bEblD2>HnY2)A6a9i2c|NRF4FV6)j@(UCTo=jEh&8P3DXJI@!QyT3qQ0}-$NS5zeF}hw1W|+as^{SUW9&Plno8Gy5k*H7u%JjEbx@ijU1<>o8zm?z z0zyWSCQX`j0-~ZQqJne?ML?w~U0MJsQbQA@cR~*#KoUr@@54F&d+#~tuDjOxfL~nB zK-l|zpXXND?k(FXO!{C_grTfa59`A2N~fmY|Lz5C^X0mu zfwSy!d&EQF(>fA@{*h;l_16`E${ z51!Hs^x^QzZZ{V$Ff_8B776`sUe2Coa4n`(JhZ1jv*@v+e;;4 zR5>`LZ`u^x{#&BJwZDSzL6zcE9d&cpLGClF`Gl)zv^A96M4U35P6_#!W99$%RwJ0T z!ul1u?~?jud5+k!^qZ!E>%H}5#^x_M4ch!dx$mHpzg`!g3W(&oHi2{p96$x(Ahx(Y z8Rxn(DWQ*Jh08qWvFKe==hI{S7oQ$d^nXVA?MIpzi!I%DE%k?$&Z0g%en`4`Bou2o z72GQK>>R<|C(NqcHoHv_JHNgN8QSe?v?9ZjkzL}ZMbaKa?nXtdWG?b?%@N5PwHdH#S!l!$_9PetJn>_rgprX zs!NODmb@j=CWz3!SpYo58|rc(CLxzm*~87wai8ac+_iz2-lr zrF{ddMUFTok)0z&rk`O=%r!21uI{tGPvr15){7VTNhc`4*^NS4nm%NHzLU(Jd~XbE z$1qISzxSK(M>GgX0C+q0*I$$IQ&=Y8y0Ho`xdeL*vrTSEZME ze5cgwk!xWE$aB58E4sQL4ead`Cs0hHgnx`|kb`N_zJq1~pJqPUGcN`oI0C>0=me9r zUXIslX(NktkBN~AA0Bnb${308jM04F51BU`6frb#+y`d zN$S~Sse6H&Q}fqUwI!!cMi}Y{whN@`DLU|YNO4}1D9C?u`)`dsqdPO&P?$Kq4^3^# zp)=H0xnjNil`tWdT5BASn8Z2$XFGK`Xz8~lBr^Cl?2kZcT4f0ZSB;bNk}J&pq7Cto zHiHHHC*O!}>abG8@bWh8f9~WGs(L@AgRIl|>SZRgq1(H)co?9)#jJ5OTF1Jn`?GG0 zT1;d3NqNhr2Pe=8Et4<9W7KR9Y?V26PBucz)H9%s)FT{DkA&3UuLwTV{g~#w%q^VP~@!h+L6Ua<> zn7EK>G_L*)6I+beM_X^UCA=0yCHj!Q$3b!2jfzW(-fpD8gvdl9gAl7840T>0h~ftI zx!PqcQ51W|rrlw$fWixau(YM>zWmDk{>|{RRa@d(@j3#!HCew6H-DkE<4{Y7G&2eM z=!}OSzA%=VRK8Z)KOY8Y;zE|0JXs@Ow+TKg>Z0GP{R0@IcbRyXDalK(j|A$YFG~U8 zvHiF|jaB{%!L7QNh88In_1FwN*3f-uVPTQc_j`7B#x2fm;6$s^{6{;%?5+x)#PoT$ z1viRkY4$gV&};{LYrk*=vHH)G1>rzxNf_>W#!+-h!f=0q>8Ec6uWYRCGHM*f3T{v9 zdS!6_7RZ*avQI5wpL%Bf@Lo`!LXifKUmm6PGi!!T^w4N{Bl@gcbTW=h?3}EG;E3%V zE-cF{7IY@^P}|)UA>m4%9wB=y4r}L{SLnS73>8!YatQ68cqZ`c@^b#lhfut`g1G8$ zQeWyWD3GWV)DBe6_FTi}b|(Me3b^`4R>b`ZvK!$cpCsd@pIhdWI7uRE~fqYCGU?@3lv$28psl;&{R1#B1 z5H_}pH>CWYKRi}f(!iOd^GBTW}TljD2YB)CO2ps7idTj=ahc$NAJH+dpY zo3_=^p0T_+1|xItw4o;&I=<^fsZC+VG(L4qyT0fv!Y5dzMwq6D!S(;heX*adB}O&s z8JRq-OU5T7xpyl&Up1DMFJfk}ulSHQU|MH-b47I`rN@RmMzqbU{s#nOAVru86E5g( z49M=_Fki$W?`F9-i#xVGk%n6 zy54|YazRG6nM&yDibtL@Yx-bhM#uf{G?qQJ2r!PM5idp7vTU>sH~?)>=5@D zzZ+BkIQPObakgu(pwjEW?K=%hbz@#hA=~`tVs1KC(yhR2$yQQ6IJKo+i2-#Sbc`(b zwI>^IK;Y^$w0Is@of50n?oJP29zVv=tin#Am3imCRA$b-la?m)H zqzIDK1BdvxRaH<2F9M?a$(Yh4%_N{in?jY{t!6vL{yHhvRpM-M>9vq%?`bniHw$d` z=2`pS(Vb6fAdM^!VAkJ06z_t}cI-$Ab z_3Wnkz@@}N{y(;xI{&z_WUa3SGC#;PE`fR z&KI&4{>M(|^chd#O@2L8TW!BszS&mxmzWr+N(7(p<*$KI*z*#J{&N!G-VE9qdD?95 zrU_+5C--lBiIN&p0MW zFmHmbx{%IA1!Aj(t60+gx>w|}U80XjepD!b(taWO>do%Tw03@~v7Oc40nbCu-^A->BYX``x%c6W9yS5A9L&>9cb4V9t>5x98>yG$HKN*bkb{5s=>t%sV#Z7 zh<5r)8uke3jhy~HX0bI1gZ&lnH0)JHUw+zmy1h3&KVBoDhVMt^-&IwC5vR=7Q=0Je zsLernX_lWXr*_%;;t^FVX>}j!{e@`Ry@DF?&CO90FB@<_Cr>6`c~JXvzj(Gy_or_o zJVHWEM*{ut-W7`aP|;#+l_M%^wQwgwX@8XTb-XtR zQ{c_AY{I^LFBYS|X|z!!hI$Q@> z;I!bRx$;;;hyo?1E6c}uRGny+>s`=5KG&GxeEH>0$=hF|*M7Usz57L@upaqWtoPfg zZTw8N7KY{{%4|=CAoyn3K!+!rdMWf+k%2VN;ZyYuIDcK2&a1$wHs%vFn!5;UdM{-D zLeqJG;__UM>&`L`XBDqrwyhKP7}WGOQ7ImBR?W9+<%~W{4OUx>vehJKq@{0<1uDyP z-rTjdux|;=K2adBbC1vbwtpHBrpsA8m+U@LqhMa={m!P6bCKD5tV^*@%KVPyA zUwKw~_c`kW;*5mvc6X!(d(9+YrY)5@eV=GkrO|$bRWQn!KkTmMk+8G2MMlC>wY#bk zJce5P3+HJI6vA&%j|c7KelUoh_$qyf7ki=RXcwM+{15+&ak_L5C$L?&xgy)6RV*c; zZ20{4XHZN8)_7>%@`l9NxD1@v76GSXbn<&iBJ$7O7IC5#+L?u3lI@StQr5PGM)GT; zi`|WeiKNI+zDtu{ixedmwkGW5o9V^|+#~^o_L2!Mf5JYDeT2dOw(%EGjfABr;K|G< z8|dunNn)htFCPN;0xfGCJ6gTT&zg!7&)%wV0=l}sC-%E5u^qmH(cbnj_1FxW>f<>r zUk1Cua_t0qxk)PbZufuaSrKJl(~N^pOmlAAWVgnA;m#^>&<`@=PGx?$VN)RQoW<0R zb;S&Y#L*bxBAmq6hR?vx8tNLeL216sLDzR^@4qDRY+$EkyHUT75O2d9A?9{T8n#lohx-;JUkf(mE$E7oA0uiMi?)}KmCs=JE~dKzt-OF3`K*|ITD=WMwRh& zgQwh%U?22~QQn2;5C@gr#hbbXd|0aEP>hPh7ykC|wOjH+4MDl5!6M$#7oLG~q4&4% z=9=S4jF(2}{4-~f$EBg075gI7fK~qs$3=ggSmB*_Z(^s$#`19y@6kYMCddpZ zQ_J@vKpklAN#;<1nUZHEl!y3yU3v013v^61!ha;wYo4qi=v6%Ab9;vq#c8Zfk{4-+ z`r;JtX6_mSb)%GqoP;Du_>aAreOJ*C8DTa!lCE*Gk@t+-_LMY^D6s~W)7sBix7|(j zTk880HLG>NFhgHk>JKu#1o|+@67FsFh+rEwD-rxiv%!D|w#_S$?%cpaNN;wDnVJ|w>j zKQ4HYnAGz>nq}}UIfiQ@y}xAaU5w zTXi5N;C9a4*7@8DZW9aDMofXtJ3i!AVNR1fa_|Up%gDSAq%Jc(sjBknXySt#2dJn= zs8@$ikH_U!j)D47OH1nj{~=AS2RrufzYcEB1N-?kD|W73)z?kY4BB9v9lxBxWNv0H zFruT`TN3021CHXj$3lB|9o)}9wu%pUT$F&ypT$bpT9=a#-+$&w*iEXWo^FnmvFPhe z13)0=D2{8aO_kKbiyxplB63dmkqRa{^=!EJ32_#b$}hvOv%seBfWqqHK$x(qhr!qL zE!q^uKQVL`wmIx&$g#f^p2}O_$Unzwor&Xox>55YOIbRms2Gz!}JMC*z}SJ4$ccG)Fx6@}P%H zd^ah2GNJi9W`>UW{!q+sV{L5}3@F!2436?nzi);g zBLjp7TQe#I#M~&=<)6b~{Z5Q{k?KjiYCi_e;m)xx2J^T!XBT_g;h8gwtg+TnX!+{CujowQZq)&}P)KVv#hZMkau@P=_AB2Ul=x9@=EvP4LQMio3KET>4&jAD)Rsuvc4Hp`*A-m_`j3SBikcnt!SS;8Z}<1JZu z$03zU)`nevg6rqa@>-<10OPrw91POmd`ii95YI5Nt!(N3?0YeABGn!;irBSht3&~q zcN6cmB@XdvhEg!#QY%&4d6v5k(fdt7ueE`JnLQc?g;*trYvJ{ww%sMN<@UpmvQ4rj z&C1+%dk!1H%vB3-rd5Bl*XcM_qVizlpsFK&s5wUYa76mGG|6&S{k(C#C}@-j2Twer znt8}#tJ&+B3fvs43%{gnkc^7M$9`TmEfKY9YNqYky?ZQhm+0hJu;|Xe88qkBxnEMB zkTC~z5tGz{lQ37MU+`=5-go$Leea0x#lkPsWlh*4^q`pYJU_9z)$DuS@yBYV!~!0V z>*?!{!+x`}j)J@NK6HADk8YH%&49j9mnmZbnw#7?nQn4iy<#ei`LN+C!!)x}Kc7q4 zu*)^$B_RJqS&?EWA&HcSNz8sgX-d2}{`|<}r83KynzoM#W8iW72tGyV75xRcCb1s} z&sTqu9Z`J)Zoqc%f)ER9N9GX)|9B#Fj|o2wewIAASWs5$x3&we{_);E*Jb+6MBgVX z9{!X64k6>b#x7knS zF3_hod!6O^XX12vC9>FB&5TlEO}RJIo-Cy5Jm`bP?D9WwY!Bv~Mj&|?O(Fw%@cZk% zt-d?nkW+4&L~LvSF9o~)ZdFrig~tf7)Gn8-DiFde(KLDW;O85K0&Fm@Tf!p~fgk5Y z*sgCo)Et48ADbS^dx2ELRxy|4Im+_+3|b5UPv%;0jGE;&xTvP;8ybAHmFzm=m)p-c z(N(O+R}C((gZon}nP$1+2HJgV$xP-4$NrDIZJ>MlnBV3q<^DB29ScBJ6l~f981$M7 zwn8cahse*eNXLvcrlt^RrW#}ITC$$8zS#QF^7JCIAWzs28rjm`-iiMCoaRDin27q^ z6sm?kyoUXPq@}0J+0!27iYyVpH65>6JhGm44qIYLz!*(9Es;Q_C%{}OAy3^0s7q4776LrmL zBu5>#X^qGxHP+yWeqn_y`Z+u+5G`rVZg$RTd72mLFU<5@AfJQ+?ouOjT{qs;hSy@J zPrn(%_%}KP?c9GzxD{>D&h1iR*3hxj65Uv=3+4L-ID8w7iWKEM&S`J?Rg}w75w+P8zOg>LSohFhJXeTX^ruGR)(yQ>w$!BP z&+d=oq5nHlE#r%^3$-+E!tht!=8O+*#WdY)ljE@d62YF$o^Bd}|FU#1!t}b1t<#~Y z+##Ylm#x5^E5>T)SSfR4Dv+7&=PZ}X#GIKscjXR$kOWCpi z3M?*H+)fannyb}}I+&1#Nxm<(b^ZkasnTEM&n4bR0We-;n>O|Is}YdI~#zCZNdxV5pEHTmV&5+Of z0|+YWgnCTM3MSu5Prff_xyShXeK9nOsX$Ppyryj0`m^ZP2xnD;D0cE!*|iUnca6)G zpr$?LN=J(MCgxVAlKVUcCxJk%*fb%c%Y0KR?WgEFM0#KZ!>5dR@nbnS>sLUK%^vGT znb>MjG#@KrDqEuze1f1MCZP$uJau+2r;3O2vb+N=zkHC*_HMKlBy?SDd`$9E|6v+4Y}d%h=! ziKRmX+XM3W$hMN4Husy4H9m<5;Rjf(0q7oTXiHF~>_ZXtSpUYAGG6`Q*}ePdjtJMH z#6GRQehIVWLjf_hhD%dDgPWYzE8I{)jLfN)A4?;Q>q-27K}&CHFp?FyEqaMhq&U-EL-{a@yfSV z+!m^!n)l83n!L77eDVaB8htXne0{@iYd~yMcE1Nn6g!3^^1eo3AMJRPo;8jFUAO55 zl{zlUsyoBU7qZ5H*3^z9O+Ul1D#^YO5Z`%5k^I*Ch(AU71E;bmfIM$;a5F!}6aA+p z&hI~PIOH~K-DA(q^9|g}XYMgPrwN;_dp#T~1%-LHS^e2u)duzOrG|FLwt>N!sxLpPK6FnJMfy-+P zL$O}4S2CwncjDcrjMtFkm*2?wv`Mpm(|28dBa#e7csFzI#(;9xFzI~tpIB&{6;k!z ztFSPDCp2bT{iqLZNl@j>PQLSU{O0Z#C=LIkpRI3b+CoCHKuSvL6*Sti`ibY2UYj)F zpG?4;2@X%7G|xJZpJkhBib~a;l}q}YS;{4(5)rU-ix2HgyXJaK;vJxgPkORU@uxo_ z2tbp=4{U%&JLk5%Z@^=L&E6M+A43JK;*cM~2k#U+R`l|&33i{X<%`WAqgFOW%gMbd zw{$`d%iQ1aJ-mqgoCuTm>eNEBR+?ob%*(ajFlA&mad5NkH3?h^yiv{a81Zkg%f;8H z>%|Q%J*(G^N3C^t0jPNHCw3zyL&B_d@AjR8oPZS%H-pmLixfoNy@yK-<9TFjC){Ez zjm-U@@t`*L1=LRd#iDK?G#Ic_t*LQd7RzxE&+&TuCQo~jnJJX&{dlqeIBZcZc?jm# zrlf%K!-YDYSlGT+C^WLo=<>VcTN{yh(v^;5S$DoY*@yWTl{+Q`Vg*rj|w|FQZ3-1bGieB4A9Jx9h$lSbB=zXi5)i8in zF|F0Qb5Oh1Wy=APB3hHzNkPyyxp^N|iEK3>hU(;526tVUW_ zhLh+DG3;j#W@GclwMa>Ab1Dk5mr~JqjbT=X9nn$2wsS9+8tb=3OYFH)L}3qrmaq8wsu`KNAA-kx2U>&4d;Q%z>qYEl ztFk!*#@&{2T3i5)Jbu}3seJx)x_;uq2b?8ic-^xB-#3Mwc)lhLA!n@Lg?q9Ue`WS2 zT?(CpK4xyr3(^yZf0r2`BWqoqoqv3**nZg3-z1>uYeLBPusF`Zn$IsBIJbp{*4$89 z^4OcYO()QhpVUur^lb9gVEZFFR}JMGA<;;)vJm_#Ej%hkIb9JtVpP4=HFv)H5+g@#9&q$#!$U$`S=t+~lHUOU_g9kShqeVftVReYCR;X1=W{tolKd?;l#K z?rR5j3aboOby_w@%lfHMhy?5A=~k^v+MYjJgl{H>p@YIIWnvr=zjh&d(C|J zXL&_C^Q#cA*xFvK0E}KL1kbUWX(|J;FXz?44OT6s>($IVP~=3t?>3QZlI?B4fXn>Y zEWz-Ed~A{iv*wk|jrlLJUJs$yuqej=<2~4S_m;RW+u0EhLCBSEOXf-3QU%+!_x6(7Q-_ux%0A4Sh)8 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%0ADlo#Jls3l6I)ibX# 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 z%0A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 z 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 G!T$gZ6SbHC literal 0 HcmV?d00001 diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 00000000..2d9c9336 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,33 @@ + + + + + + + + + Yuki Hook API + + + + +

    Select a language

    English 简体中文

    + + + diff --git a/docs/zh-cn/about/about.html b/docs/zh-cn/about/about.html new file mode 100644 index 00000000..331ed347 --- /dev/null +++ b/docs/zh-cn/about/about.html @@ -0,0 +1,54 @@ + + + + + + + + + 关于此文档 | Yuki Hook API + + + + +

    关于此文档

    此文档由 VuePress在新窗口中打开 强力驱动。

    License

    The MIT License (MIT)在新窗口中打开

    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.
    +

    版权所有 © 2019-2022 HighCapable

    + + + diff --git a/docs/zh-cn/about/changelog.html b/docs/zh-cn/about/changelog.html new file mode 100644 index 00000000..37b548b0 --- /dev/null +++ b/docs/zh-cn/about/changelog.html @@ -0,0 +1,33 @@ + + + + + + + + + 更新日志 | Yuki Hook API + + + + +

    更新日志

    这里记录了 YukiHookAPI 的版本更新历史。

    特别注意

    我们只会对最新的 API 版本进行维护,若你正在使用过时的 API 版本则代表你自愿放弃一切维护的可能性。

    1.1.0 | 2022.09.28  最新

    • 这是一次大版本更新,有关更新日志中提到的变化及用法请参考 API 文档 以及 特色功能
    • 更换帮助文档框架到 VuePress在新窗口中打开
    • 统一并规范文档中的术语名词,例如“查询”一律更改为了“查找”,XposedHelper 拼写错误修改为了 XposedHelpers
    • 文档 入门 → 基础知识 页面加入友情链接,仅限简体中文
    • 将 Hook App Demo 的 ClassMethod 转为 Java 以提供更好的演示效果
    • 修正了 Hook Module Demo 中的代码注释命名
    • 重构了大量底层 Hook 逻辑及 Xposed API 的对接方式
    • 移除了 HookParamWrapper,现已将其直接与 YukiBridgeFactory 对接
    • 移动部分 YukiHookBridge 中的方法到 AppParasitics
    • 移除了 HookParam.args 与底层的直接对接方法 setArgs,直接获取并设置当前数组的对象
    • 优化自动处理程序,将引用的 jar 合并到 stub 项目
    • 修复多项目打包时模块包名无法正确匹配的问题以及修改自动处理程序的模块包名匹配逻辑,感谢 5ec1cff在新窗口中打开 的反馈及提供的解决方案
    • 对 API 私有工具类的方法进行了 internal 闭包处理,避免污染顶级命名空间
    • 修正了所有反射和 Hook 类的 Creater 命名到 Creator
    • 新增 YukiHookAPI.Status.compiledTimestamp 功能,可以在作为 Xposed 模块使用时获取编译完成的时间戳
    • 新增 YukiHookAPI.Status.isXposedEnvironment 功能,可以判断当前为 (Xposed) 宿主环境还是模块环境
    • 调试日志功能进行了大改版,现已将 YukiHookAPI.Configs.debugTag 等功能合并到 YukiHookLogger.Configs
    • 调试日志新增可指定打印使用的方法为 XposedBridge.logLogd
    • 调试日志中默认加入当前宿主的包名以及当前用户 ID,以供调试,你可以在 debugLog 配置中自行更改
    • 新增 generic 功能,可对泛型进行反射和调用,你可以在 ClassCurrentClass 中使用它
    • 作废 buildOfAny 方法,现在请直接使用 buildOf 方法 (不带泛型) 来使用构造方法创建新对象并得到结果 Any
    • 修复 hasExtends 使用过程发生空指针异常的问题
    • CurrentClass 新增非 lambda 方式的调用方法
    • CurrentClass 新增 namesimpleName 功能
    • 完全重写 ReflectionTool 的核心方法,将不同的查找条件进行了整理分类
    • 修复 ReflectionTool 中可能的直接调用 declared 获取的 Member 抛出异常的问题
    • 修复 ReflectionToolUndefinedType 未在 MethodConstructor 条件中正确判断的问题
    • 新增反射查找结果发生异常时的友好提示方式,可具体定位到指定条件找不到 Member 的问题
    • 反射查找 MethodConstructor 中新增 VagueType 条件,可使用在 param 条件中用于忽略你不想填写的参数
    • 反射查找 MethodConstructor 中新增 paramCount { ... } 条件,现在你可以直接拿到其中的 it 来自定义你的判断条件
    • FieldFinder 结果中新增 current 方法,可直接对结果实例创建调用空间
    • 修改了反射查找功能中的 modifiers 条件以及 name 条件,现在你需要对此方法体结尾返回一个 Boolean 以使条件成立
    • ModifierRules 中的 as* 功能改名为 is*,感谢 Kitsune在新窗口中打开 的建议
    • FieldFinder 中新增 RemedyPlan 功能
    • 新增 Dex 中的 Class 模糊查找功能 (Beta),你现在可以直接使用 searchClass 功能来使用指定条件模糊查找 Class
    • 新增反射查找中的多重查找功能,可使用相对查找条件同时获取多个查找结果,感谢 AA 以及 Kitsune在新窗口中打开 的建议
    • 修复 appClassLoader 获取到的对象在某些系统中的系统应用中不正确的问题,感谢 Luckyzyx在新窗口中打开 的反馈
    • 修改了 XposedBridge.invokeOriginalMethod 的调用方式并在 MethodFinder.Result.Instance 中增加 original 功能
    • 修复 YukiHookModulePrefsgetStringSet 方法取值错误的问题并优化代码风格,感谢 Teddy_Zhu在新窗口中打开PR在新窗口中打开
    • 修改 YukiHookModulePrefs,拦截 XSharePreference 可能不存在的异常
    • 修复 YukiHookDataChannel 在某些第三方 ROM 系统框架中无法注册成功的问题
    • 安全化 YukiHookDataChannel,现在它只能在来自指定包名的模块与宿主之间通信
    • 新增自动 Hook SharedPreferences 以修复部分系统中文件权限不是 0664 的问题,感谢 5ec1cff在新窗口中打开 的反馈及提供的实现代码
    • 新增 YukiHookAPI.Configs.isEnableHookSharedPreferences 功能,默认关闭,若 SharedPreferences 的权限错误可进行启用
    • 修复查找 Constructor 时无参构造方法在不填写查找条件时无法找到的 BUG,感谢 B5 KAKA 的反馈
    • 分离位于 injectMembermethodconstructorResult 实例到 Process
    • 在 Hook 过程中新增 useDangerousOperation 方法,未进行声明时在 Hook 危险列表中的功能后会自动停止 Hook 并打印错误
    • 新增模块资源注入与 Activity 代理功能,你可以调用 injectModuleAppResourcesregisterModuleAppActivities 来使用
    • 新增 ModuleContextThemeWrapper 功能,你可以调用 applyModuleTheme 在任意 Activity 中创建模块的 Context
    • 新增 ClassLoader.onLoadClass 功能,可用于监听 ClassLoaderloadClass 方法被调用的事件
    • 作废了 classOfclazz 扩展方法,新增 toClass 以及 toClassOrNull 用法,请现在转移到新的方法
    • VariousClass 新增 getOrNull 方法,可在匹配不到 Class 的时候不抛出异常而是返回 null
    • PackageParam.hook 中移除了 isUseAppClassLoader 参数,修改为 isForceUseAbsolute 并自动匹配目标 Class
    • PackageParam 新增 systemContext 功能,你可以在任意时间调用此功能获取一个持久化的 Context
    • 不再对外开放 HookClass 中的任何方法
    • HookParam 中新增 throwToApp 功能,可将异常直接抛给宿主
    • Hook 回调中新增 onFailureThrowToApp 功能,可在发生异常时直接抛给宿主
    • 修改了调试日志的打印逻辑,反射查找功能中的耗时记录仅会在 Hook 过程中进行打印
    • Hook 过程中新增解除 Hook 功能,可使用 removeremoveSelf 方法解除 Hook
    • 修复在 ReplaceHook 失败的时候导致宿主抛出异常的问题,现修改为调用原始方法保证宿主功能正常运行
    • 新增 Hook 过程中对方法返回值的检查功能,在返回值不匹配的情况下会根据情景自动抛出异常或打印错误
    • Resources Hook 中新增 array 类型,感谢 GSWXXN在新窗口中打开PR在新窗口中打开
    • 移动 me.weishu.reflectionthirdparty 防止同时引入的同名依赖冲突
    • 移除 Hook 方法体为空时抛出的异常,修改为打印警告日志
    • 修改 AppLifecycle 的异常处理逻辑,当其发生异常时直接抛给宿主
    • 更新 Demo 的 API 版本到 33

    1.0.92 | 2022.05.31  过旧

    • 修正了大量方法中 callback 的命名方法
    • 更换方案再次修复 YukiHookDataChannel 在低于 Android 12 的设备上不能回调当前 Activity 广播的问题
    • InjectYukiHookWithXposed 注解新增 isUsingResourcesHook 功能,现在你可以选择性关闭自动生成 IXposedHookInitPackageResources 的依赖接口了

    1.0.91 | 2022.05.29  过期

    • 修复部分设备的定制系统在 LSPosed 环境下开机启动获取的 ClassLoader 错误的问题,感谢 Luckyzyx在新窗口中打开 的反馈
    • 修复 YukiHookDataChannelZUI 以及低于 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 方法,可判断当前方法是否被重复 Hook
    • 修改部分重复添加 HashMap 的逻辑,移除 putIfAbsent 方法,允许覆盖添加
    • 修复了几处可能的 BUG

    1.0.88 | 2022.05.25  过期

    • 对 Xposed API 完全解耦合
    • 增加了 type 中的 android 类型
    • YukiHookModuleStatus 从自动生成代码中分离,并加入 isEnableHookModuleStatus 的开关,由你决定是否启用
    • 对 API 大量类的构造方法进行了 internal 闭包处理
    • YukiHookModulePrefs 设置为单例运行,防止重复创建浪费系统资源
    • 修复自 1.0.80 版本后无法嵌套 Hook 的 BUG,并优化嵌套 Hook 相关功能
    • 修改 Hooker 存储方案由 HashSet 到 HashMap,防止重复添加 Hooker 的问题
    • 修改 Hook 核心实现方法,加入查重,避免重复 Hook 多次回调 HookParam 方法
    • MethodFinderFieldFinder 加入查找模糊方法、变量名称功能,可调用 name { ... } 来设置查找条件,支持正则
    • 优化并修改 appContext 的获取方式,降低会取到空的问题的可能性
    • 修改自动生成的代码中 logger 的打印 TAG 默认为你自定义的名称,方便进行调试
    • 优化 YukiHookBridgeHooker 实现方式,提升 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  过期

    • 修复不支持 Resources Hook(资源钩子) 的情况下在 initZygote 时持续报错的问题,复现在 ZUI/LSPosed CI(1.8.3-6550)
    • 优化并对 Resources Hook 进行异常处理,只有被使用后不支持才会打印错误和警告

    1.0.85 | 2022.05.04  过期

    • 修复无法 Hook 系统框架的严重问题,从 1.0.80 开始出现
    • 调试日志中新增区分 initZygote 装载的包名为 android-zygotepackageName 保持 android 不变

    1.0.83 | 2022.05.04  过期

    • 修复 YukiHookModuleStatusloadSystem 后大量报错的问题
    • 新增 type 中的 android 类型
    • 更新帮助文档的示例说明

    1.0.82 | 2022.05.04  过期

    • 修复了一处概念混淆错误,区分 initZygote 与系统框架的关系,之前的注释和文档有问题,非常抱歉
    • PackageParam 新增 loadSystem 方法,不需要再写 loadApp(name = "android") 即可 Hook 系统框架

    1.0.81 | 2022.05.04  过期

    • 修复使用 by 方法设置条件后 Hook 方法体内查找不到的方法、构造方法依然输出错误日志的问题
    • 在执行 Hook 过程中加入全局日志显示当前 Hook APP 的包名,并修复一处错误日志打印样式的问题

    1.0.80 | 2022.05.01  过期

    • InjectYukiHookWithXposed 注解新增 entryClassName 功能,可自定义生成的 xposed_init 入口类名
    • YukiHookXposedInitProxy 更名为 IYukiHookXposedInit,原接口名称已作废,将在后续版本中直接被删除
    • 新增 initZygote 与 Resources Hook 功能,支持 Hook Layout
    • 新增 onXposedEvent 方法,可监听原生 Xposed API 的全部事件
    • 对 Hook 功能的 lambda 进行 inline 处理,避免生成过碎的匿名类,提升编译后的运行性能
    • 修复 PrefsData 编译后的方法体复制过大的问题
    • 增加 XSharePreference 可读性测试,失败后会自动打印警告日志
    • PackageParam 新增 appResourcesmoduleAppResourcesmoduleAppFilePath 功能
    • PackageParamloadApp 新增不写 name 功能,默认筛选全部 APP
    • PackageParam 新增 loadZygote 方法,可直接 Hook 系统框架
    • PackageParam 新增 resources().hook 功能
    • 优化方法、构造方法、变量查找功能,找不到的错误日志将优先显示已设置的查找条件
    • 增加 hasExtends 扩展方法,可判断当前 Class 是否有继承关系
    • 增加 isSupportResourcesHook 功能,判断当前是否支持资源钩子(Resources Hook)
    • current 功能新增 superClass 方法调用父类
    • 查找方法、构造方法、变量新增 superClass 查找条件,可继续在父类中查找
    • YukiHookAPI 大量方法与 Xposed API 解耦合
    • 新增 Xposed API 的原生 Hook 优先级功能
    • 修复 isFirstApplication 可能判断不准确的问题
    • 屏蔽 MIUI 系统上 MiuiCatcherPatch 重复调用 Hook 入口方法的问题
    • 优化 Hook 入口调用方法,避免因为 Hook Framework 问题导致多次调用
    • 修复 Hook ClassLoader 导致 Hook 卡死的问题,感谢 WankkoRee在新窗口中打开 的反馈
    • 提升 XC_Callback 接口对接后的性能
    • Java type 新增 ClassLoader 类型
    • 优化 API 帮助文档,修复可能持续缓存页面的问题

    1.0.78 | 2022.04.18  过期

    • YukiHookModulePrefs 新增 isRunInNewXShareMode 方法,可用于判断模块当前是否处于 New XSharePreference 模式
    • 修复 YukiHookModulePrefsNew XSharePreference 模式下工作的部分问题
    • 新增 ModulePreferenceFragment,现在,你可以完全替换掉 PreferenceFragmentCompat 并开始使用新的功能
    • 适配 PreferenceFragmentCompat 的 Sp 数据存储解决方案,感谢 mahoshojoHCG在新窗口中打开 的反馈
    • 更新自动处理程序以及 Kotlin 依赖到最新版本
    • 修正部分文档和代码注释中的错误

    1.0.77 | 2022.04.15  过期

    • YukiHookModulePrefs 新增 clear 方法,感谢 WankkoRee在新窗口中打开 的建议
    • YukiHookModulePrefs 新增 getStringSetputStringSetall 方法
    • HookParamargs 增加 any 方法
    • 新增 ModuleApplication,可在模块中继承此类实现更多功能
    • 对接全部的 findClass 功能到 Xposed API,在非宿主环境继续使用原生 ClassLoader
    • 修复了一些可能存在的 BUG

    1.0.75 | 2022.04.13  过期

    • 更正了自动处理程序的逻辑识别部分,感谢 ApeaSuperz在新窗口中打开 的贡献
    • 修正一处文档注释的引用未更改的问题
    • HookParam 中删除了 firstArgslastArgs 方法,现在你可以使用 args().first()args().last() 来取代它
    • HookParam 中删除了 args() 中的默认参数 index = 0,现在你可以使用 args().first()args(index = 0) 来取代它
    • HookParamresult 功能增加了泛型匹配,现在你可以使用 result<T> 来匹配你的目标方法已知返回值类型了
    • 方法、构造方法查找功能新增 emptyParam 条件,并完善了文档相关需要注意的查找条件误区
    • 增加了 type 中的 android 类型

    1.0.73 | 2022.04.10

    1.0.72 | 2022.04.09  过期

    • 更新 API 文档到新的地址
    • PackageParam 中加入 appContext 功能
    • 修复一些已知的 BUG,提升 Hook 稳定性

    1.0.71 | 2022.04.04  过期

    • 修复 VariousClass 无法匹配时会停止 Hook 抛出异常的严重问题

    1.0.70 | 2022.04.04  过期

    • 修复 instanceClass 在静态实例中调用后报错问题
    • 在 Hook 过程中加入 isUseAppClassLoader 功能,感谢 WankkoRee在新窗口中打开 的反馈
    • 加入 withProcess 功能,可根据 APP 当前指定进程进行 Hook
    • 修复查找方法、构造类和变量的严重逻辑错误问题
    • 修复 Hook 目标类不存在的时候无法忽略异常输出的问题
    • 修复部分情况下 APP 启动方法装载过快导致 Hook 不能生效的问题
    • 修复 allMethods 未 Hook 到方法时不会抛出异常的问题,感谢 WankkoRee在新窗口中打开 的反馈
    • 加入 Hook 状态监听功能,感谢 WankkoRee在新窗口中打开 的建议
    • 修改 Xposed 入口注入类的方式,重新声明 API 的定义域
    • 加入混淆的方法以及变量的查找功能,可使用不同类型筛选 index 定位指定的方法和变量,感谢 WankkoRee在新窗口中打开 提供的思路
    • 查找方法、变量时允许传入多种类型,例如 String 声明的类名和 VariousClass
    • 加入全新的 current 功能,可对任意的类构建一个反射方法操作空间,方便地调用和修改其中的方法和变量
    • 修复了 Hook 过程中的大量 BUG,感谢 WankkoRee在新窗口中打开 对此项目所做出的贡献

    1.0.69 | 2022.03.30  过期

    • 添加并改进一些方法功能的注释
    • 增加 Demo 中的更多示例 Hook 内容
    • 修复在一个 Hook 实例中,allMethods 多次使用时只有最后一个生效的问题,感谢 WankkoRee在新窗口中打开 的反馈

    1.0.68 | 2022.03.29  过期

    • 增加 Demo 中的新用例和 LSPosed 作用域
    • 增加 Member 查找缓存和查找缓存配置开关
    • 移除和修改 MethodFinderFieldFinder 以及 HookParam 相关方法的调用
    • 增加更多 Finder 中的 cast 类型并支持 cast 为数组
    • 整体的性能和稳定性提升
    • 修复上一个版本可能存在的 BUG

    1.0.67 | 2022.03.27  过期

    • 增加三个 Finder 中的 modifiers 功能,可筛选 staticnativepublicabstract 等诸多描述类型
    • 增加方法和构造方法查找时可模糊方法参数类型为指定个数进行查找
    • 增加 MemberhasModifiers 扩展功能
    • 增加 MethodFinderConstructorFinder 中的 give 方法,可获得原始类型
    • 增加 YukiHookModulePrefs 中的 PrefsData 模板功能
    • 彻底对方法、构造方法及变量的查找方案进行重构
    • 优化代码注释,修复了可能产生的 BUG

    1.0.66 | 2022.03.25  过期

    • 修复 MethodFinder 中的一个严重问题
    • 增加 hookParam 中的 args 调用方法
    • 修复其它可能存在的问题以及修复部分类的注释问题

    1.0.65 | 2022.03.25  过期

    • 重新发布版本修复 Maven 仓库因为缓存问题新版本不正确的情况
    • 增加 MethodFinderFieldFinder 新的返回值调用方法
    • 修复可能存在的问题,并修复太极使用过程中可能存在的问题
    • 修复自动生成 Xposed 入口类可能发生的问题
    • 增加了 type 中的 android 类型以及 java 类型

    1.0.6 | 2022.03.20  过期

    • 修复 YukiHookModulePrefs 在使用一次 direct 忽略缓存后每次都忽略的 BUG
    • 增加新的 API,作废了 isActive 判断模块激活的传统用法
    • 修复非 Xposed 环境使用 API 时打印调试日志的问题
    • 修复查找 Field 时的日志输出问题和未拦截的异常问题
    • 解耦合 ReflectionUtils 中的 Xposed API
    • 增加 YukiHookModuleStatus 方法名称的混淆,以精简模块生成的体积
    • 装载模块自身 Hook 时将不再打印欢迎信息
    • 修复上一个版本仍然存在的某些 BUG

    1.0.55 | 2022.03.18  过期

    • 修正一处注释错误
    • 临时修复一个 BUG
    • 增加了 type 中的大量 android 类型以及少量 java 类型
    • 修复新版与旧版 Kotlin APIs 的兼容性问题

    1.0.5 | 2022.03.18  过期

    • 修复旧版本 LSPosed 框架情况下欢迎信息多次打印的问题
    • 添加 onInit 方法来配置 YukiHookAPI
    • 新增 executorNameexecutorVersion 来获取当前 Hook 框架的名称和版本号
    • 新增 by 方法来设置 Hook 的时机和条件
    • YukiHookModulePrefs 新增可控制的键值缓存,可在宿主运行时模块动态更新数据
    • 修复了一些可能存在的 BUG

    1.0.4 | 2022.03.06  过期

    • 修复 LSPosed 在最新版本中启用“只有模块classloader可以使用Xposed API”选项后找不到 XposedBridge 的问题
    • 添加 YukiHookAPI 的常量版本名称和版本号
    • 新增 hasField 方法以及 isAllowPrintingLogs 配置参数
    • 新增 isDebug 开启的情况下 API 将自动打印欢迎信息测试模块是否生效

    1.0.3 | 2022.03.02  过期

    • 修复一个潜在性的异常未拦截 BUG
    • 增加 ignoredError 功能
    • 增加了 type 中的 android 类型
    • 增加监听 hook 后的 ClassNotFound 功能

    1.0.2 | 2022.02.18  过期

    • 修复 Windows 下无法找到项目路径的问题
    • 移除部分反射 API,合并至 BaseFinder 进行整合
    • 增加直接使用字符串创建 Hook 的方法

    1.0.1 | 2022.02.15  过期

    • RemedyPlan 增加 onFind 功能
    • 整合并修改了部分反射 API 代码
    • 增加了 type 中的 java 类型
    • 修复忽略错误在控制台仍然输出的问题

    1.0 | 2022.02.14  过期

    • 首个版本提交至 Maven
    + + + diff --git a/docs/zh-cn/about/contacts.html b/docs/zh-cn/about/contacts.html new file mode 100644 index 00000000..fb7a80af --- /dev/null +++ b/docs/zh-cn/about/contacts.html @@ -0,0 +1,33 @@ + + + + + + + + + 联系我们 | Yuki Hook API + + + + +

    联系我们

    如在使用中有任何问题,或有任何建设性的建议,都可以联系我们。

    加入我们 点击加入 Telegram 群组在新窗口中打开

    酷安 找到我 @星夜不荟在新窗口中打开

    助力维护

    感谢您选择并使用 YukiHookAPI,如有代码相关的建议和请求,可在 Github 提交 Pull Request。

    + + + diff --git a/docs/zh-cn/about/future.html b/docs/zh-cn/about/future.html new file mode 100644 index 00000000..879dc77d --- /dev/null +++ b/docs/zh-cn/about/future.html @@ -0,0 +1,33 @@ + + + + + + + + + 展望未来 | Yuki Hook API + + + + +

    展望未来

    未来是美好的,也是不确定的,让我们共同期待 YukiHookAPI 在未来的发展空间。

    未解决的问题

    这里收录了 YukiHookAPI 尚未解决的问题。

    YukiHookModulePrefs

    目前仅限完美支持 LSPosed,其它 Xposed 框架需要降级模块 API。

    可能完全不支持太极,太极在高版本系统上需要更低的 API 才能适配。

    部分 Xposed 模块开发者目前选择 Hook 目标 APP 内置 Sp 存储方案解决模块设置共享问题。

    后期 Android 系统的权限将越来越严格,selinux 就是目前面临的一个大问题,有待讨论和研究。

    未来的计划

    这里收录了 YukiHookAPI 可能会在后期添加的功能。

    支持独立使用的 Lite 版本

    待讨论

    目前 API 只支持通过自动处理程序绑定到 xposed_init,若您不喜欢自动处理程序,一定要自己实现模块装载入口,未来会按照需求人数推出仅有 API 功能的 Lite 版本,你可向我们提出 issues

    API 已经提供了 Xposed 原生 API 监听接口,你可以 在这里 找到或查看 Demo 的实现方法。

    支持更多 Hook Framework

    作为 API 来讲,目前仅仅对接 XposedBridge 作为兼容层,还是有一定的局限性。

    大部分 inline hook 没有 Java 兼容层,后期可能会考虑 native hookJava 兼容层适配。

    + + + diff --git a/docs/zh-cn/api/home.html b/docs/zh-cn/api/home.html new file mode 100644 index 00000000..c9fa4520 --- /dev/null +++ b/docs/zh-cn/api/home.html @@ -0,0 +1,33 @@ + + + + + + + + + 文档介绍 | Yuki Hook API + + + + +

    文档介绍

    这里的文档将同步最新 API 版本的相关用法,请保持 YukiHookAPI 为最新版本以使用最新版本的功能。

    功能描述说明

    功能描述主要介绍当前 API 的相关用法和用途。

    功能示例说明

    功能示例主要展示了当前 API 的基本用法示例,可供参考。

    变更记录说明

    首个版本的功能将标记为 v<version> 添加

    后期新增加的功能将标记为 v<version> 新增

    后期修改的功能将被追加为 v<version> 修改

    后期被作废的功能将标记为 v<version> 作废 并会标注删除线;

    后期被删除的功能将标记为 v<version> 移除 并会标注删除线。

    相关符号说明

    • kt  Kotlin Static File

    • annotation  注解

    • interface  接口

    • object  类 (单例)

    • class  类

    • field  变量或 getset 方法或只读的 get 方法

    • method  方法

    • enum  Enum 常量

    • ext-field  扩展的变量 (全局)

    • ext-method  扩展的方法 (全局)

    • i-ext-field  扩展的变量 (调用域限制)

    • i-ext-method  扩展的方法 (调用域限制)

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.html new file mode 100644 index 00000000..d26633a2 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.html @@ -0,0 +1,130 @@ + + + + + + + + + YukiHookAPI - object | Yuki Hook API + + + + +

    YukiHookAPI - object

    object YukiHookAPI
    +

    变更记录

    v1.0 添加

    功能描述

    这是 YukiHookAPI 的 API 调用总类,Hook 相关功能的开始、Hook 相关功能的配置都在这里。

    API_VERSION_NAME - field

    const val API_VERSION_NAME: String
    +

    变更记录

    v1.0.4 新增

    功能描述

    获取当前 YukiHookAPI 的版本。

    API_VERSION_CODE - field

    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

    Status - object

    object Status
    +

    变更记录

    v1.0.91 新增

    功能描述

    当前 YukiHookAPI 的状态。

    compiledTimestamp - field

    val compiledTimestamp: Long
    +

    变更记录

    v1.1.0 新增

    功能描述

    获取项目编译完成的时间戳 (当前本地时间)。

    isXposedEnvironment - field

    val isXposedEnvironment: Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    获取当前是否为 (Xposed) 宿主环境。

    executorName - field

    val executorName: String
    +

    变更记录

    v1.0.91 新增

    功能描述

    获取当前 Hook 框架的名称。

    无法获取会返回 unknownXposedBridge 不存在会返回 invalid

    注意

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    executorVersion - field

    val executorVersion: Int
    +

    变更记录

    v1.0.91 新增

    功能描述

    获取当前 Hook 框架的版本。

    无法获取会返回 -1

    注意

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    isModuleActive - field

    val isModuleActive: Boolean
    +

    变更记录

    v1.0.91 新增

    功能描述

    判断模块是否在 Xposed 或太极、无极中激活。

    注意

    在模块环境中你需要将 Application 继承于 ModuleApplication

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    在 (Xposed) 宿主环境中仅返回非 isTaiChiModuleActive 的激活状态。

    isXposedModuleActive - field

    val isXposedModuleActive: Boolean
    +

    变更记录

    v1.0.91 新增

    功能描述

    仅判断模块是否在 Xposed 中激活。

    注意

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    在 (Xposed) 宿主环境中始终返回 true。

    isTaiChiModuleActive - field

    val isTaiChiModuleActive: Boolean
    +

    变更记录

    v1.0.91 新增

    功能描述

    仅判断模块是否在太极、无极中激活。

    注意

    在模块环境中你需要将 Application 继承于 ModuleApplication

    在 (Xposed) 宿主环境中始终返回 false。

    isSupportResourcesHook - field

    val isSupportResourcesHook: Boolean
    +

    变更记录

    v1.0.91 新增

    功能描述

    判断当前 Hook Framework 是否支持资源钩子(Resources Hook)。

    注意

    在模块环境中需要启用 Configs.isEnableHookModuleStatus

    在 (Xposed) 宿主环境中可能会延迟等待事件回调后才会返回 true。

    请注意你需要确保 InjectYukiHookWithXposed.isUsingResourcesHook 已启用,否则始终返回 false。

    Configs - object

    object Configs
    +

    变更记录

    v1.0 添加

    功能描述

    对 API 相关功能的配置类。

    debugLog - method

    inline fun debugLog(initiate: YukiHookLogger.Configs.() -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    配置 YukiHookLogger.Configs 相关参数。

    debugTag - field

    变更记录

    v1.0 添加

    v1.1.0 作废

    请转移到 YukiHookLogger.Configs.tag

    isDebug - field

    var isDebug: Boolean
    +

    变更记录

    v1.0 添加

    功能描述

    是否启用 DEBUG 模式。

    默认为开启状态,开启后模块将会向 LogcatXposedBridge.log 打印详细的 Hook 日志,关闭后仅会打印 E 级别的日志。

    isAllowPrintingLogs - field

    变更记录

    v1.0.4 新增

    v1.1.0 作废

    请转移到 YukiHookLogger.Configs.isEnable

    isEnableModulePrefsCache - field

    var isEnableModulePrefsCache: Boolean
    +

    变更记录

    v1.0.5 新增

    功能描述

    是否启用 YukiHookModulePrefs 的键值缓存功能。

    为防止内存复用过高问题,此功能默认启用。

    你可以手动在 YukiHookModulePrefs 中自由开启和关闭缓存功能以及清除缓存。

    isEnableModuleAppResourcesCache - field

    var isEnableModuleAppResourcesCache: Boolean
    +

    变更记录

    v1.0.87 新增

    功能描述

    是否启用当前 Xposed 模块自身 Resources 缓存功能。

    为防止内存复用过高问题,此功能默认启用。

    你可以手动调用 PackageParam.refreshModuleAppResources 来刷新缓存。

    注意

    关闭后每次使用 PackageParam.moduleAppResources 都会重新创建,可能会造成运行缓慢。

    isEnableHookModuleStatus - field

    var isEnableHookModuleStatus: Boolean
    +

    变更记录

    v1.0.88 新增

    功能描述

    是否启用 Hook Xposed 模块激活等状态功能.

    为原生支持 Xposed 模块激活状态检测,此功能默认启用。

    注意

    关闭后你将不能再在模块环境中使用 YukiHookAPI.Status 中的激活状态判断功能。

    isEnableHookSharedPreferences - field

    var isEnableHookSharedPreferences: Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    是否启用 Hook SharedPreferences

    启用后将在模块启动时强制将 SharedPreferences 文件权限调整为 Context.MODE_WORLD_READABLE (0664)。

    注意

    这是一个可选的实验性功能,此功能默认不启用。

    仅用于修复某些系统可能会出现在启用了 New XSharedPreferences 后依然出现文件权限错误问题,若你能正常使用 YukiHookModulePrefs 就不建议启用此功能。

    isEnableDataChannel - field

    var isEnableDataChannel: Boolean
    +

    变更记录

    v1.0.88 新增

    功能描述

    是否启用当前 Xposed 模块与宿主交互的 YukiHookDataChannel 功能。

    请确保 Xposed 模块的 Application 继承于 ModuleApplication 才能有效。

    此功能默认启用,关闭后将不会在功能初始化的时候装载 YukiHookDataChannel

    isEnableMemberCache - field

    var isEnableMemberCache: Boolean
    +

    变更记录

    v1.0.68 新增

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    是否启用 Member 缓存功能。

    为防止 Member 复用过高造成的系统 GC 问题,此功能默认启用。

    启用后会缓存已经找到的 MethodConstructorField

    缓存的 Member 都将处于 MemberCacheStore 的全局静态实例中。

    推荐使用 MethodFinderConstructorFinderFieldFinder 来获取 Member

    除非缓存的 Member 发生了混淆的问题,例如使用 R8 混淆后的 APP 的目标 Member,否则建议启用。

    configs - method

    inline fun configs(initiate: Configs.() -> Unit)
    +

    变更记录

    v1.0 添加

    功能描述

    Configs 类实现了一个 lambda 方法体。

    你可以轻松的调用它进行配置。

    功能示例

    你可以在 HookEntryClassonInit 方法中调用 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.
    +    }
    +}
    +

    你也可以不通过 configsdebugLog 方法,直接进行配置。

    示例如下

    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.
    +    }
    +}
    +

    encase - method

    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 添加

    功能描述

    装载 Hook 入口的核心方法。

    功能示例

    详情请参考

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html new file mode 100644 index 00000000..77bad3d4 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html @@ -0,0 +1,39 @@ + + + + + + + + + InjectYukiHookWithXposed - annotation | Yuki Hook API + + + + +

    InjectYukiHookWithXposed - annotation

    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 入口的类注解。

    功能示例

    详情请参考 InjectYukiHookWithXposed 注解

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html new file mode 100644 index 00000000..3297d1a8 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html @@ -0,0 +1,48 @@ + + + + + + + + + CurrentClass - class | Yuki Hook API + + + + +

    CurrentClass - class

    class CurrentClass internal constructor(internal val classSet: Class<*>, internal val instance: Any)
    +

    变更记录

    v1.0.70 新增

    v1.1.0 修改

    调整了构造方法的参数名称

    功能描述

    当前实例的类操作对象。

    name - field

    val name: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前 classSetClass.getName

    simpleName - field

    val simpleName: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前 classSetClass.getSimpleName

    generic - method

    fun generic(): GenericClass?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前实例中的泛型父类。

    如果当前实例不存在泛型将返回 null

    generic - method

    inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前实例中的泛型父类。

    如果当前实例不存在泛型将返回 null

    superClass - method

    fun superClass(): SuperClass
    +

    变更记录

    v1.0.80 新增

    功能描述

    调用父类实例。

    field - method

    inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
    +

    变更记录

    v1.0.70 新增

    功能描述

    调用当前实例中的变量。

    method - method

    inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
    +

    变更记录

    v1.0.70 新增

    功能描述

    调用当前实例中的方法。

    SuperClass - class

    inner class SuperClass internal constructor(internal val superClassSet: Class<*>)
    +

    变更记录

    v1.0.80 新增

    v1.1.0 修改

    新增 superClassSet 参数

    功能描述

    当前类的父类实例的类操作对象。

    name - field

    val name: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前 classSet 中父类的 Class.getName

    simpleName - field

    val simpleName: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前 classSet 中父类的 Class.getSimpleName

    generic - method

    fun generic(): GenericClass?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前实例父类中的泛型父类。

    如果当前实例不存在泛型将返回 null

    generic - method

    inline fun generic(initiate: GenericClass.() -> Unit): GenericClass?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前实例父类中的泛型父类。

    如果当前实例不存在泛型将返回 null

    field - method

    inline fun field(initiate: FieldConditions): FieldFinder.Result.Instance
    +

    变更记录

    v1.0.80 新增

    功能描述

    调用父类实例中的变量。

    method - method

    inline fun method(initiate: MethodConditions): MethodFinder.Result.Instance
    +

    变更记录

    v1.0.80 新增

    功能描述

    调用父类实例中的方法。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html new file mode 100644 index 00000000..7e3e3818 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html @@ -0,0 +1,35 @@ + + + + + + + + + GenericClass - class | Yuki Hook API + + + + +

    GenericClass - class

    class GenericClass internal constructor(private val type: ParameterizedType)
    +

    变更记录

    v1.1.0 新增

    功能描述

    当前 Class 的泛型父类操作对象。

    argument - method

    fun argument(index: Int): Class<*>
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得泛型参数数组下标的 Class 实例。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html new file mode 100644 index 00000000..9e1c9769 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html @@ -0,0 +1,34 @@ + + + + + + + + + HookClass - class | Yuki Hook API + + + + +

    HookClass - class

    class HookClass internal constructor(internal var instance: Class<*>?, internal var name: String, internal var throwable: Throwable?)
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    HookClass 相关功能不再对外开放

    功能描述

    创建一个当前 Hook 的 Class 接管类。

    instance 为实例,name 为实例完整包名,throwable 为找不到实例的时候抛出的异常。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html new file mode 100644 index 00000000..1b7c61f9 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html @@ -0,0 +1,34 @@ + + + + + + + + + HookResources - class | Yuki Hook API + + + + +

    HookResources - class

    class HookResources internal constructor(var instance: YukiResources?)
    +

    变更记录

    v1.0.80 新增

    功能描述

    创建一个当前 Hook 的 YukiResources 接管类。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html new file mode 100644 index 00000000..99653a3d --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html @@ -0,0 +1,36 @@ + + + + + + + + + VariousClass - class | Yuki Hook API + + + + +

    VariousClass - class

    class VariousClass(vararg var name: String)
    +

    变更记录

    v1.0 添加

    功能描述

    这是一个不确定性 Class 类名装载器,通过 name 装载 Class 名称数组。

    get - method

    fun get(loader: ClassLoader? = null): Class<*>
    +

    变更记录

    v1.0.70 新增

    功能描述

    获取匹配的实体类。

    使用当前 loader 装载目标 Class

    getOrNull - method

    fun getOrNull(loader: ClassLoader? = null): Class<*>?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获取匹配的实体类。

    使用当前 loader 装载目标 Class

    匹配不到 Class 会返回 null,不会抛出异常。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html new file mode 100644 index 00000000..f3a3c362 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html @@ -0,0 +1,153 @@ + + + + + + + + + YukiMemberHookCreator - class | Yuki Hook API + + + + +

    YukiMemberHookCreator - class

    class YukiMemberHookCreator(internal val packageParam: PackageParam, internal val hookClass: HookClass)
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    hookClass 进行 inline 处理

    v1.1.0 修改

    修正拼写错误的 Creater 命名到 Creator

    功能描述

    YukiHookAPIMember 核心 Hook 实现类。

    PRIORITY_DEFAULT - field

    val PRIORITY_DEFAULT: Int
    +

    变更记录

    v1.0.80 新增

    功能描述

    默认 Hook 回调优先级。

    PRIORITY_LOWEST - field

    val PRIORITY_LOWEST: Int
    +

    变更记录

    v1.0.80 新增

    功能描述

    延迟回调 Hook 方法结果。

    PRIORITY_HIGHEST - field

    val PRIORITY_HIGHEST: Int
    +

    变更记录

    v1.0.80 新增

    功能描述

    更快回调 Hook 方法结果。

    instanceClass - field

    val instanceClass: Class<*>
    +

    变更记录

    v1.0 添加

    v1.0.2 修改

    thisClass 更名为 instanceClass

    功能描述

    得到当前被 Hook 的 Class

    特别注意

    不推荐直接使用,万一得不到 Class 对象则会无法处理异常导致崩溃。

    injectMember - method

    inline fun injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    增加 priority Hook 优先级

    功能描述

    注入要 Hook 的 MethodConstructor

    功能示例

    你可以注入任意 MethodConstructor,使用 injectMember 即可创建一个 Hook 对象。

    示例如下

    injectMember {
    +    // Your code here.
    +}
    +

    你还可以自定义 tag,方便你在调试的时候能够区分你的 Hook 对象。

    示例如下

    injectMember(tag = "KuriharaYuki") {
    +    // Your code here.
    +}
    +

    你还可以自定义 priority,以控制当前 Hook 对象并列执行的优先级速度。

    示例如下

    injectMember(priority = PRIORITY_HIGHEST) {
    +    // Your code here.
    +}
    +

    useDangerousOperation - method

    fun useDangerousOperation(option: String)
    +

    变更记录

    v1.1.0 新增

    功能描述

    允许 Hook 过程中的所有危险行为。

    请在 option 中键入 Yes do as I say! 代表你同意允许所有危险行为。

    你还需要在整个调用域中声明注解 CauseProblemsApi 以消除警告。

    若你只需要 Hook ClassLoaderloadClass 方法,请参考 ClassLoader.onLoadClass

    特别注意

    若你不知道允许此功能会带来何种后果,请勿使用。

    MemberHookCreator - class

    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

    修正拼写错误的 Creater 命名到 Creator

    功能描述

    Hook 核心功能实现类,查找和处理需要 Hook 的 MethodConstructor

    member - field

    变更记录

    v1.0 添加

    v1.1.0 移除

    请转移到 members

    members - method

    fun members(vararg member: Member?)
    +

    变更记录

    v1.1.0 新增

    功能描述

    手动指定要 Hook 的 MethodConstructor

    注意

    不建议使用此方法设置目标需要 Hook 的 Member 对象,你可以使用 methodconstructor 方法。

    功能示例

    你可以调用 instanceClass 来手动查找要 Hook 的 MethodConstructor

    示例如下

    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) 来取代它

    allMembers - method

    fun allMembers(type: MembersType)
    +

    变更记录

    v1.1.0 新增

    功能描述

    查找并 Hook hookClass 中的全部 MethodConstructor

    注意

    无法准确处理每个 Member 的返回值和 param,建议使用 method or constructor 对每个 Member 单独 Hook。

    method - method

    inline fun method(initiate: MethodConditions): MethodFinder.Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    查找当前 Class 需要 Hook 的 Method

    功能示例

    你可参考 MethodFinder 查看详细用法。

    示例如下

    injectMember {
    +    method {
    +        name = "test"
    +        param(StringType)
    +        returnType = UnitType
    +    }
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    若想 Hook 当前查找 method { ... } 条件的全部结果,你只需要在最后加入 all 即可。

    示例如下

    injectMember {
    +    method {
    +        name = "test"
    +        paramCount(1..5)
    +    }.all()
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    此时 beforeHookafterHook 会在每个查找到的结果中多次回调 Hook 方法体。

    注意

    若没有 all,默认只会 Hook 当前条件查找到的数组下标结果第一位。

    constructor - method

    inline fun constructor(initiate: ConstructorConditions): ConstructorFinder.Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    查找当前 Class 需要 Hook 的 Constructor

    功能示例

    你可参考 ConstructorFinder 查看详细用法。

    示例如下

    injectMember {
    +    constructor { param(StringType) }
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    若想 Hook 当前查找 constructor { ... } 条件的全部结果,你只需要在最后加入 all 即可。

    示例如下

    injectMember {
    +    constructor { paramCount(1..5) }.all()
    +    beforeHook {}
    +    afterHook {}
    +}
    +

    此时 beforeHookafterHook 会在每个查找到的结果中多次回调 Hook 方法体。

    注意

    若没有 all,默认只会 Hook 当前条件查找到的数组下标结果第一位。

    HookParam.field - i-ext-method

    inline fun HookParam.field(initiate: FieldConditions): FieldFinder.Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    使用当前 hookClass 查找并得到 Field

    功能示例

    你可参考 FieldFinder 查看详细用法。

    示例如下

    injectMember {
    +    method {
    +        name = "test"
    +        param(StringType)
    +        returnType = UnitType
    +    }
    +    afterHook {
    +        // 这里不需要再调用 instanceClass.field 进行查找
    +        field {
    +            name = "isSweet"
    +            type = BooleanType
    +        }.get(instance).setTrue()
    +    }
    +}
    +

    HookParam.method - i-ext-method

    inline fun HookParam.method(initiate: MethodConditions): MethodFinder.Result
    +

    变更记录

    v1.0.2 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    使用当前 hookClass 查找并得到 Method

    HookParam.constructor - i-ext-method

    inline fun HookParam.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
    +

    变更记录

    v1.0.2 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    使用当前 hookClass 查找并得到 Constructor

    HookParam.injectMember - i-ext-method

    inline fun HookParam.injectMember(priority: Int, tag: String, initiate: MemberHookCreator.() -> Unit): MemberHookCreator.Result
    +

    变更记录

    v1.0.88 新增

    功能描述

    注入要 Hook 的 MethodConstructor (嵌套 Hook)。

    beforeHook - method

    fun beforeHook(initiate: HookParam.() -> Unit): HookCallback
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    新增 HookCallback 返回类型

    功能描述

    Member 执行完成前 Hook。

    afterHook - method

    fun afterHook(initiate: HookParam.() -> Unit): HookCallback
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    新增 HookCallback 返回类型

    功能描述

    Member 执行完成后 Hook。

    replaceAny - method

    fun replaceAny(initiate: HookParam.() -> Any?)
    +

    变更记录

    v1.0 添加

    功能描述

    拦截并替换此 Member 内容,给出返回值。

    replaceUnit - method

    fun replaceUnit(initiate: HookParam.() -> Unit)
    +

    变更记录

    v1.0 添加

    功能描述

    拦截并替换此 Member 内容,没有返回值,可以称为 Void

    replaceTo - method

    fun replaceTo(any: Any?)
    +

    变更记录

    v1.0 添加

    功能描述

    拦截并替 Member 返回值。

    replaceToTrue - method

    fun replaceToTrue()
    +

    变更记录

    v1.0 添加

    功能描述

    拦截并替换 Member 返回值为 true

    特别注意

    确保替换 Member 的返回对象为 Boolean

    replaceToFalse - method

    fun replaceToFalse()
    +

    变更记录

    v1.0 添加

    功能描述

    拦截并替换 Member 返回值为 false

    特别注意

    确保替换 Member 的返回对象为 Boolean

    intercept - method

    fun intercept()
    +

    变更记录

    v1.0 添加

    功能描述

    拦截此 Member

    这将会禁止此 Member 执行并返回 null

    特别注意

    例如 IntLongBoolean 常量返回值的 Member 一旦被设置为 null 可能会造成 Hook APP 抛出异常。

    removeSelf - method

    fun removeSelf(result: (Boolean) -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    移除当前注入的 Hook MethodConstructor (解除 Hook)。

    特别注意

    你只能在 Hook 回调方法中使用此功能。

    HookCallback - class

    inner class HookCallback internal constructor()
    +

    变更记录

    v1.1.0 新增

    功能描述

    Hook 方法体回调实现类。

    onFailureThrowToApp - method

    fun onFailureThrowToApp()
    +

    变更记录

    v1.1.0 新增

    功能描述

    当回调方法体内发生异常时将异常抛出给当前 Hook APP。

    Result - class

    inner class Result internal constructor()
    +

    变更记录

    v1.0 添加

    功能描述

    监听 Hook 结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    变更记录

    v1.0 添加

    v1.0.5 修改

    failures 修改为 result

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建监听失败事件方法体。

    功能示例

    你可以使用此方法为 Result 类创建 lambda 方法体。

    示例如下

    injectMember {
    +    // Your code here.
    +}.result {
    +    onHooked {}
    +    onAlreadyHooked {}
    +    ignoredConductFailure()
    +    onHookingFailure {}
    +    // ...
    +}
    +

    by - method

    inline fun by(condition: () -> Boolean): Result
    +

    变更记录

    v1.0.5 新增

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。

    onHooked - method

    fun onHooked(result: (Member) -> Unit): Result
    +

    变更记录

    v1.0.70 新增

    功能描述

    监听 members Hook 成功的回调方法。

    在首次 Hook 成功后回调。

    在重复 Hook 时会回调 onAlreadyHooked

    onAlreadyHooked - method

    fun onAlreadyHooked(result: (Member) -> Unit): Result
    +

    变更记录

    v1.0.89 新增

    功能描述

    监听 members 重复 Hook 的回调方法。

    注意

    同一个 hookClass 中的同一个 members 不会被 API 重复 Hook,若由于各种原因重复 Hook 会回调此方法。

    onNoSuchMemberFailure - method

    fun onNoSuchMemberFailure(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.0.5 新增

    功能描述

    监听 members 不存在发生错误的回调方法。

    onConductFailure - method

    fun onConductFailure(result: (HookParam, Throwable) -> Unit): Result
    +

    变更记录

    v1.0 添加

    功能描述

    监听 Hook 进行过程中发生错误的回调方法。

    onHookingFailure - method

    fun onHookingFailure(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.0 添加

    功能描述

    监听 Hook 开始时发生的错误的回调方法。

    onAllFailure - method

    fun onAllFailure(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.0 添加

    功能描述

    监听全部 Hook 过程发生错误的回调方法。

    ignoredNoSuchMemberFailure - method

    fun ignoredNoSuchMemberFailure(): Result
    +

    变更记录

    v1.0.5 新增

    功能描述

    忽略 members 不存在发生的错误。

    ignoredConductFailure - method

    fun ignoredConductFailure(): Result
    +

    变更记录

    v1.0 添加

    功能描述

    忽略 Hook 进行过程中发生的错误。

    ignoredHookingFailure - method

    fun ignoredHookingFailure(): Result
    +

    变更记录

    v1.0 添加

    功能描述

    忽略 Hook 开始时发生的错误。

    ignoredAllFailure - method

    fun ignoredAllFailure(): Result
    +

    变更记录

    v1.0 添加

    功能描述

    忽略全部 Hook 过程发生的错误。

    remove - method

    fun remove(result: (Boolean) -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    移除当前注入的 Hook MethodConstructor (解除 Hook)。

    注意

    你只能在 Hook 成功后才能解除 Hook,可监听 onHooked 事件。

    Result - class

    inner class Result internal constructor()
    +

    变更记录

    v1.0.3 新增

    功能描述

    监听全部 Hook 结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    变更记录

    v1.0.3 新增

    v1.0.5 修改

    failures 修改为 result

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建监听事件方法体。

    by - method

    inline fun by(condition: () -> Boolean): Result
    +

    变更记录

    v1.0.5 新增

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。

    onPrepareHook - method

    fun onPrepareHook(callback: () -> Unit): Result
    +

    变更记录

    v1.0.70 新增

    功能描述

    监听 hookClass 存在时准备开始 Hook 的操作。

    onHookClassNotFoundFailure - method

    fun onHookClassNotFoundFailure(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.0.3 新增

    功能描述

    监听 hookClass 找不到时发生错误的回调方法。

    ignoredHookClassNotFoundFailure - method

    fun ignoredHookClassNotFoundFailure(): Result
    +

    变更记录

    v1.0.3 新增

    功能描述

    忽略 hookClass 找不到时出现的错误。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html new file mode 100644 index 00000000..56b0e078 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html @@ -0,0 +1,127 @@ + + + + + + + + + YukiResourcesHookCreator - class | Yuki Hook API + + + + +

    YukiResourcesHookCreator - class

    class YukiResourcesHookCreator(internal val packageParam: PackageParam, internal val hookResources: HookResources)
    +

    变更记录

    v1.0.80 新增

    v1.1.0 修改

    修正拼写错误的 Creater 命名到 Creator

    功能描述

    YukiHookAPIResources 核心 Hook 实现类。

    injectResource - method

    inline fun injectResource(tag: String, initiate: ResourceHookCreator.() -> Unit): ResourceHookCreator.Result
    +

    变更记录

    v1.0.80 新增

    功能描述

    注入要 Hook 的 Resources。

    功能示例

    你可以注入任意 Resources,使用 injectResource 即可创建一个 Hook 对象。

    示例如下

    injectResource {
    +    // Your code here.
    +}
    +

    你还可以自定义 tag,方便你在调试的时候能够区分你的 Hook 对象。

    示例如下

    injectResource(tag = "KuriharaYuki") {
    +    // Your code here.
    +}
    +

    ResourcesHookCreator - class

    inner class ResourcesHookCreator internal constructor(private val tag: String)
    +

    变更记录

    v1.0.80 新增

    v1.1.0 修改

    移除 packageName

    修正拼写错误的 Creater 命名到 Creator

    功能描述

    Hook 核心功能实现类。

    查找和处理需要 Hook 的 Resources。

    resourceId - field

    var resourceId: Int
    +

    变更记录

    v1.0.80 新增

    功能描述

    直接设置需要替换的 Resources Id。

    注意

    不建议使用此方法设置目标需要 Hook 的 Resources Id,你可以使用 conditions 方法。

    功能示例

    你可以直接设置并指定目标 Hook APP 的 Resources Id。

    示例如下

    injectResource {
    +    resourceId = 0x7f060001.toInt()
    +    replaceTo(...)
    +}
    +

    conditions - method

    inline fun conditions(initiate: ConditionFinder.() -> Unit)
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 查找条件。

    若你设置了 resourceId 则此方法将不会被使用。

    功能示例

    你可参考 ConditionFinder 查看详细用法。

    示例如下

    injectResource {
    +    conditions {
    +        name = "test_string"
    +        string()
    +    }
    +    replaceTo(...)
    +}
    +

    replaceTo - method

    fun replaceTo(any: Any)
    +

    变更记录

    v1.0.80 新增

    功能描述

    替换指定 Resources 为指定的值。

    功能示例

    你可以替换找到的 Resources 为你想要的值,可以是 StringDrawable 等。

    比如我们要替换一个找到的字符串 Resources。

    示例如下

    injectResource {
    +    conditions {
    +        name = "test_string"
    +        string()
    +    }
    +    replaceTo("replace string")
    +}
    +

    或是替换为一个 Drawable,你无需对目标 Resources 实现 fwd 方法或 DrawableLoader

    示例如下

    injectResource {
    +    conditions {
    +        name = "test_drawable"
    +        drawable()
    +    }
    +    replaceTo(ColorDrawable(Color.RED))
    +}
    +

    replaceToTrue - method

    fun replaceToTrue()
    +

    变更记录

    v1.0.80 新增

    功能描述

    替换指定 Resources 为 true

    特别注意

    确保目标替换 Resources 的类型为 Boolean

    replaceToFalse - method

    fun replaceToFalse()
    +

    变更记录

    v1.0.80 新增

    功能描述

    替换指定 Resources 为 false

    特别注意

    确保目标替换 Resources 的类型为 Boolean

    replaceToModuleResource - method

    fun replaceToModuleResource(resId: Int)
    +

    变更记录

    v1.0.80 新增

    功能描述

    替换为当前 Xposed 模块的 Resources。

    你可以直接使用模块的 R.string.xxxR.mipmap.xxxR.drawable.xxx 替换 Hook APP 的 Resources。

    功能示例

    使用此方法可非常方便地使用当前模块的 Resources 去替换目标 Hook APP 的 Resources。

    这个过程你无需对目标 Resources 实现 fwd 方法。

    比如我们要替换一个字符串。

    示例如下

    injectResource {
    +    conditions {
    +        name = "test_string"
    +        string()
    +    }
    +    replaceToModuleResource(R.string.module_string)
    +}
    +

    还可以替换一些复杂的 Resources,比如 xml 创建的 drawable

    示例如下

    injectResource {
    +    conditions {
    +        name = "test_drawable"
    +        drawable()
    +    }
    +    replaceToModuleResource(R.drawable.module_drawable)
    +}
    +

    injectAsLayout - method

    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()
    +    }
    +}
    +

    ConditionFinder - class

    inner class ConditionFinder internal constructor()
    +

    变更记录

    v1.0.80 新增

    功能描述

    Resources 查找条件实现类。

    name - field

    var name: String
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 名称。

    anim - method

    fun anim()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为动画。

    animator - method

    fun animator()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为属性动画。

    bool - method

    fun bool()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为布朗(Boolean)。

    color - method

    fun color()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为颜色(Color)。

    dimen - method

    fun dimen()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为尺寸(Dimention)。

    drawable - method

    fun drawable()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为 Drawable。

    integer - method

    fun integer()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为整型(Integer)。

    layout - method

    fun layout()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为布局(Layout)。

    plurals - method

    fun plurals()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为 Plurals。

    string - method

    fun string()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为字符串(String)。

    xml - method

    fun xml()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为 Xml。

    mipmap - method

    fun mipmap()
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 Resources 类型为位图(Mipmap)。

    array - method

    fun array()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Resources 类型为数组(Array)。

    Result - class

    inner class Result internal constructor()
    +

    变更记录

    v1.0.80 新增

    功能描述

    监听全部 Hook 结果实现类,可在这里处理失败事件监听。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    变更记录

    v1.0.80 新增

    功能描述

    创建监听事件方法体。

    by - method

    inline fun by(condition: () -> Boolean): Result
    +

    变更记录

    v1.0.80 新增

    功能描述

    添加执行 Hook 需要满足的条件,不满足条件将直接停止 Hook。

    onHookingFailure - method

    fun onHookingFailure(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.0.80 新增

    功能描述

    监听 Hook 过程发生错误的回调方法。

    ignoredHookingFailure - method

    fun ignoredHookingFailure(): Result
    +

    变更记录

    v1.0.80 新增

    功能描述

    忽略 Hook 过程出现的错误。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html new file mode 100644 index 00000000..99454ef8 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html @@ -0,0 +1,41 @@ + + + + + + + + + BaseFinder - class | Yuki Hook API + + + + +

    BaseFinder - class

    abstract class BaseFinder
    +

    变更记录

    v1.0.70 新增

    v1.1.0 修改

    分离原始命名 BaseFinder 中的部分方法与参数到 MemberBaseFinder

    功能描述

    这是 ClassMember 查找类功能的基本类实现。

    BaseFinder.IndexTypeCondition - class

    inner class IndexTypeCondition internal constructor(private val type: IndexConfigType)
    +

    变更记录

    v1.0.70 新增

    功能描述

    字节码下标筛选实现类。

    index - method

    fun index(num: Int)
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置下标。

    index 小于零则为倒序,此时可以使用 IndexTypeConditionSort.reverse 方法实现。

    可使用 IndexTypeConditionSort.firstIndexTypeConditionSort.last 设置首位和末位筛选条件。

    index - method

    fun index(): IndexTypeConditionSort
    +

    变更记录

    v1.0.70 新增

    功能描述

    得到下标。

    IndexTypeConditionSort - class

    inner class IndexTypeConditionSort internal constructor()
    +

    变更记录

    v1.0.70 新增

    功能描述

    字节码下标排序实现类。

    first - method

    fun first()
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置满足条件的第一个。

    last - method

    fun last()
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置满足条件的最后一个。

    reverse - method

    fun reverse(num: Int)
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置倒序下标。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html new file mode 100644 index 00000000..ab081de6 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html @@ -0,0 +1,38 @@ + + + + + + + + + CountRules - class | Yuki Hook API + + + + +

    CountRules - class

    class CountRules private constructor()
    +

    变更记录

    v1.1.0 新增

    功能描述

    这是一个模糊 ClassMember 数组 (下标) 个数条件实现类。

    可对 R8 混淆后的 ClassMember 进行更加详细的定位。

    Int.isZero - i-ext-method

    fun Int.isZero(): Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    是否为 0。

    Int.moreThan - i-ext-method

    fun Int.moreThan(count: Int): Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    大于 count

    Int.lessThan - i-ext-method

    fun Int.lessThan(count: Int): Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    小于 count

    Int.inInterval - i-ext-method

    fun Int.inInterval(countRange: IntRange): Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    countRange 区间 A ≤ this ≤ B。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html new file mode 100644 index 00000000..ff688535 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html @@ -0,0 +1,46 @@ + + + + + + + + + ModifierRules - class | Yuki Hook API + + + + +

    ModifierRules - class

    class ModifierRules private constructor()
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    新增 Class 的描述符判断

    作为 lambda 整体判断条件使用

    移动到 base 包名

    私有化构造方法

    功能描述

    这是一个 ClassMember 描述符条件实现类。

    可对 R8 混淆后的 ClassMember 进行更加详细的定位。

    isPublic - i-ext-field

    val isPublic: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    ClassMember 类型是否包含 public

    isPrivate - i-ext-field

    val isPrivate: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    ClassMember 类型是否包含 private

    isProtected - i-ext-field

    val isProtected: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    ClassMember 类型是否包含 protected

    isStatic - i-ext-field

    val isStatic: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    ClassMember 类型是否包含 static

    对于任意的静态 ClassMember 可添加此描述进行确定。

    注意

    Kotlin → Jvm 后的 object 类中的方法并不是静态的。

    isFinal - i-ext-field

    val isFinal: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    ClassMember 类型是否包含 final

    注意

    Kotlin → Jvm 后没有 open 符号标识的 ClassMember 和没有任何关联的 ClassMember 都将为 final

    isSynchronized - i-ext-field

    val isSynchronized: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    ClassMember 类型是否包含 synchronized

    isVolatile - i-ext-field

    val isVolatile: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    Field 类型是否包含 volatile

    isTransient - i-ext-field

    val isTransient: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    Field 类型是否包含 transient

    isNative - i-ext-field

    val isNative: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    Method 类型是否包含 native

    对于任意 JNI 对接的 Method 可添加此描述进行确定。

    isInterface - i-ext-field

    val isInterface: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    Class 类型是否包含 interface

    isAbstract - i-ext-field

    val isAbstract: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    ClassMember 类型是否包含 abstract

    对于任意的抽象 ClassMember 可添加此描述进行确定。

    isStrict - i-ext-field

    val isStrict: Boolean
    +

    变更记录

    v1.0.67 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    ClassMember 类型是否包含 strictfp

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html new file mode 100644 index 00000000..9b69b569 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html @@ -0,0 +1,41 @@ + + + + + + + + + NameRules - class | Yuki Hook API + + + + +

    NameRules - class

    class NameRules private constructor()
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    NameConditions 更名为 NameRules

    作为 lambda 整体判断条件使用

    移动到 base 包名

    私有化构造方法

    功能描述

    这是一个模糊 ClassMember 名称条件实现类。

    可对 R8 混淆后的 ClassMember 进行更加详细的定位。

    String.isSynthetic - i-ext-method

    fun String.isSynthetic(index: Int): Boolean
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    是否为匿名类的主类调用对象。

    String.isOnlySymbols - i-ext-method

    fun String.isOnlySymbols(): Boolean
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    是否只有符号。

    String.isOnlyLetters - i-ext-method

    fun String.isOnlyLetters(): Boolean
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    是否只有字母。

    String.isOnlyNumbers - i-ext-method

    fun String.isOnlyNumbers(): Boolean
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    是否只有数字。

    String.isOnlyLettersNumbers - i-ext-method

    fun String.isOnlyLettersNumbers(): Boolean
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    是否只有字母或数字。

    String.isOnlyLowercase - i-ext-method

    fun String.isOnlyLowercase(): Boolean
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    是否只有小写字母。

    在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。

    String.isOnlyUppercase - i-ext-method

    fun String.isOnlyUppercase(): Boolean
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    统一合并到扩展方法并改名

    功能描述

    是否只有大写字母。

    在没有其它条件的情况下设置此条件允许判断对象存在字母以外的字符。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html new file mode 100644 index 00000000..d16c8f68 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html @@ -0,0 +1,77 @@ + + + + + + + + + DexClassFinder - class | Yuki Hook API + + + + +

    DexClassFinder - class

    class DexClassFinder internal constructor(
    +    internal var name: String,
    +    internal var async: Boolean,
    +    override val loaderSet: ClassLoader?
    +) : ClassBaseFinder
    +

    变更记录

    v1.1.0 新增

    功能描述

    Class 查找类。

    可使用 BaseDexClassLoader 通过指定条件查找指定 Class 或一组 Class

    注意

    此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。

    companion object - object

    变更记录

    v1.1.0 新增

    clearCache - method

    fun clearCache(context: Context?, versionName: String?, versionCode: Long?)
    +

    变更记录

    v1.1.0 新增

    功能描述

    清除当前 DexClassFinderClass 缓存。

    适用于全部通过 ClassLoader.searchClassPackageParam.searchClass 获取的 DexClassFinder

    fullName - field

    var fullName: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 完整名称。

    只会查找匹配到的 Class.getName

    例如 com.demo.Test 需要填写 com.demo.Test

    simpleName - field

    var simpleName: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 简单名称。

    只会查找匹配到的 Class.getSimpleName

    例如 com.demo.Test 只需要填写 Test

    对于匿名类例如 com.demo.Test$InnerTest 会为空,此时你可以使用 singleName

    singleName - field

    var singleName: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 独立名称。

    设置后将首先使用 Class.getSimpleName,若为空则会使用 Class.getName 进行处理。

    例如 com.demo.Test 只需要填写 Test

    对于匿名类例如 com.demo.Test$InnerTest 只需要填写 Test$InnerTest

    from - method

    fun from(vararg name: String): FromPackageRules
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置在指定包名范围查找当前 Class

    设置后仅会在当前 name 开头匹配的包名路径下进行查找,可提升查找速度。

    例如 ↓

    com.demo.test

    com.demo.test.demo

    注意

    建议设置此参数指定查找范围,否则 Class 过多时将会非常慢。

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 标识符筛选条件。

    可不设置筛选条件。

    fullName - method

    fun fullName(value: String): ClassNameRules
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 完整名称。

    只会查找匹配到的 Class.getName

    例如 com.demo.Test 需要填写 com.demo.Test

    simpleName - method

    fun simpleName(value: String): ClassNameRules
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 简单名称。

    只会查找匹配到的 Class.getSimpleName

    例如 com.demo.Test 只需要填写 Test

    对于匿名类例如 com.demo.Test$InnerTest 会为空,此时你可以使用 singleName

    singleName - method

    fun singleName(value: String): ClassNameRules
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 独立名称。

    设置后将首先使用 Class.getSimpleName,若为空则会使用 Class.getName 进行处理。

    例如 com.demo.Test 只需要填写 Test

    对于匿名类例如 com.demo.Test$InnerTest 只需要填写 Test$InnerTest

    fullName - method

    fun fullName(conditions: NameConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 完整名称条件。

    只会查找匹配到的 Class.getName

    simpleName - method

    fun simpleName(conditions: NameConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 简单名称条件。

    只会查找匹配到的 Class.getSimpleName

    singleName - method

    fun singleName(conditions: NameConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 独立名称条件。

    设置后将首先使用 Class.getSimpleName,若为空则会使用 Class.getName 进行处理。

    extends - method

    inline fun <reified T> extends()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 继承的父类。

    extends - method

    fun extends(vararg name: String)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 继承的父类。

    会同时查找 name 中所有匹配的父类。

    implements - method

    inline fun <reified T> implements()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 实现的接口类。

    implements - method

    fun implements(vararg name: String)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 实现的接口类。

    会同时查找 name 中所有匹配的接口类。

    anonymous - method

    fun anonymous()
    +

    变更记录

    v1.1.0 新增

    功能描述

    标识 Class 为匿名类。

    例如 com.demo.Test$1com.demo.Test$InnerTest

    标识后你可以使用 enclosing 来进一步指定匿名类的 (封闭类) 主类。

    noExtends - method

    fun noExtends()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 没有任何继承。

    此时 Class 只应该继承于 Any

    注意

    设置此条件后 extends 将失效。

    noImplements - method

    fun noImplements()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 没有任何接口。

    注意

    设置此条件后 implements 将失效。

    noSuper - method

    fun noSuper()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 没有任何继承与接口。

    此时 Class 只应该继承于 Any

    注意

    设置此条件后 extendsimplements 将失效。

    enclosing - method

    inline fun <reified T> enclosing()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 匿名类的 (封闭类) 主类。

    enclosing - method

    fun enclosing(vararg name: String)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 匿名类的 (封闭类) 主类。

    会同时查找 name 中所有匹配的 (封闭类) 主类。

    FromPackageRules - class

    inner class FromPackageRules internal constructor(private val packages: ArrayList<ClassRulesData.PackageRulesData>)
    +

    变更记录

    v1.1.0 新增

    功能描述

    包名范围名称过滤匹配条件实现类。

    absolute - method

    fun absolute()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置包名绝对匹配。

    例如有如下包名 ↓

    com.demo.test.a

    com.demo.test.a.b

    com.demo.test.active

    若包名条件为 com.demo.test.a 则绝对匹配仅能匹配到第一个。

    相反地,不设置以上示例会全部匹配。

    ClassNameRules - class

    inner class ClassNameRules internal constructor(private val name: ClassRulesData.NameRulesData)
    +

    变更记录

    v1.1.0 新增

    功能描述

    类名匹配条件实现类。

    optional - method

    fun optional()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置类名可选。

    例如有如下类名 ↓

    com.demo.Test fullName / Test simpleName

    defpackage.a fullName / a simpleName

    这两个类名都是同一个类,但是在有些版本中被混淆有些版本没有。

    此时可设置类名为 com.demo.Test fullName / Test simpleName

    这样就可在完全匹配类名情况下使用类名而忽略其它查找条件,否则忽略此条件继续使用其它查找条件。

    member - method

    inline fun member(initiate: MemberRules.() -> Unit): MemberRulesResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 满足的 Member 条件。

    field - method

    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 条件。

    constructor - method

    inline fun constructor(initiate: ConstructorRules.() -> Unit): MemberRulesResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Class 满足的 Constructor 条件。

    Result - class

    inner class Result internal constructor(internal var isNotFound: Boolean, internal var throwable: Throwable?) : BaseResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    Class 查找结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    创建监听结果事件方法体。

    get - method

    fun get(): Class<*>?
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到 Class 本身。

    若有多个 Class 结果只会返回第一个。

    在查找条件找不到任何结果的时候将返回 null

    若你设置了 async 请使用 wait 方法。

    all - method

    fun all(): HashSet<Class<*>>
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到 Class 本身数组。

    返回全部查找条件匹配的多个 Class 实例。

    在查找条件找不到任何结果的时候将返回空的 HashSet

    若你设置了 async 请使用 waitAll 方法。

    all - method

    fun all(result: (Class<*>) -> Unit): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到 Class 本身数组 (依次遍历)。

    回调全部查找条件匹配的多个 Class 实例。

    在查找条件找不到任何结果的时候将不会执行。

    若你设置了 async 请使用 waitAll 方法。

    wait - method

    fun wait(result: (Class<*>?) -> Unit): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到 Class 本身 (异步)。

    若有多个 Class 结果只会回调第一个。

    在查找条件找不到任何结果的时候将回调 null。

    你需要设置 async 后此方法才会被回调,否则请使用 get 方法。

    waitAll - method

    fun waitAll(result: (HashSet<Class<*>>) -> Unit): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到 Class 本身数组 (异步)。

    回调全部查找条件匹配的多个 Class 实例。

    在查找条件找不到任何结果的时候将回调空的 HashSet

    你需要设置 async 后此方法才会被回调,否则请使用 all 方法。

    onNoClassDefFoundError - method

    fun onNoClassDefFoundError(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    监听找不到 Class 时。

    ignored - method

    fun ignored(): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    忽略异常并停止打印任何错误日志。

    此时若要监听异常结果,你需要手动实现 onNoClassDefFoundError 方法。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html new file mode 100644 index 00000000..b3255f91 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html @@ -0,0 +1,40 @@ + + + + + + + + + ConstructorRules - class | Yuki Hook API + + + + +

    ConstructorRules - class

    class ConstructorRules internal constructor(internal val rulesData: ConstructorRulesData) : BaseRules
    +

    变更记录

    v1.1.0 新增

    功能描述

    Constructor 查找条件实现类。

    paramCount - field

    var paramCount: Int
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Constructor 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此变量指定参数个数。

    若参数个数小于零则忽略并使用 param

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Constructor 标识符筛选条件。

    可不设置筛选条件。

    emptyParam - method

    fun emptyParam()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Constructor 空参数、无参数。

    param - method

    fun param(vararg paramType: Any)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Constructor 参数。

    如果同时使用了 paramCountparamType 的数量必须与 paramCount 完全匹配。

    如果 Constructor 中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。

    特别注意

    无参 Constructor 请使用 emptyParam 设置查找条件。

    有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。

    paramCount - method

    fun paramCount(numRange: IntRange)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Constructor 参数个数范围。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数范围。

    paramCount - method

    fun paramCount(conditions: CountConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Constructor 参数个数条件。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数条件。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html new file mode 100644 index 00000000..65b9bd88 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html @@ -0,0 +1,38 @@ + + + + + + + + + FieldRules - class | Yuki Hook API + + + + +

    FieldRules - class

    class FieldRules internal constructor(internal val rulesData: FieldRulesData) : BaseRules
    +

    变更记录

    v1.1.0 新增

    功能描述

    Field 查找条件实现类。

    name - field

    var name: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Field 名称。

    type - field

    var type: Any?
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Field 类型。

    可不填写类型。

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Field 标识符筛选条件。

    可不设置筛选条件。

    name - method

    fun name(conditions: NameConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Field 名称条件。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html new file mode 100644 index 00000000..7813efd6 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html @@ -0,0 +1,35 @@ + + + + + + + + + MemberRules - class | Yuki Hook API + + + + +

    MemberRules - class

    class MemberRules internal constructor(internal val rulesData: MemberRulesData) : BaseRules
    +

    变更记录

    v1.1.0 新增

    功能描述

    Member 查找条件实现类。

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Member 标识符筛选条件。

    可不设置筛选条件。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html new file mode 100644 index 00000000..d32283e9 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html @@ -0,0 +1,43 @@ + + + + + + + + + MethodRules - class | Yuki Hook API + + + + +

    MethodRules - class

    class MethodRules internal constructor(internal val rulesData: MethodRulesData) : BaseRules
    +

    变更记录

    v1.1.0 新增

    功能描述

    Method 查找条件实现类。

    name - field

    var name: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 名称。

    paramCount - field

    var paramCount: Int
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此变量指定参数个数。

    若参数个数小于零则忽略并使用 param

    returnType - field

    var returnType: Any?
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 返回值。

    可不填写返回值。

    modifiers - method

    fun modifiers(conditions: ModifierConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 标识符筛选条件。

    可不设置筛选条件。

    emptyParam - method

    fun emptyParam()
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 空参数、无参数。

    param - method

    fun param(vararg paramType: Any)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 参数。

    如果同时使用了 paramCountparamType 的数量必须与 paramCount 完全匹配。

    如果 Method 中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。

    特别注意

    无参 Method 请使用 emptyParam 设置查找条件。

    有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。

    name - method

    fun name(conditions: NameConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 名称条件。

    paramCount - method

    fun paramCount(numRange: IntRange)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 参数个数范围。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数范围。

    paramCount - method

    fun paramCount(conditions: CountConditions)
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 参数个数条件。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数条件。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html new file mode 100644 index 00000000..30511f5b --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html @@ -0,0 +1,38 @@ + + + + + + + + + MemberRulesResult - class | Yuki Hook API + + + + +

    MemberRulesResult - class

    class MemberRulesResult internal constructor(private val rulesData: MemberRulesData)
    +

    变更记录

    v1.1.0 新增

    功能描述

    当前 Member 查找条件结果实现类。

    none - method

    fun none(): MemberRulesResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置当前 Member 在查找条件中个数为 0

    count - method

    fun count(num: Int): MemberRulesResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置当前 Member 在查找条件中需要全部匹配的个数。

    count - method

    fun count(numRange: IntRange): MemberRulesResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置当前 Member 在查找条件中需要全部匹配的个数范围。

    count - method

    fun count(conditions: CountConditions): MemberRulesResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置当前 Member 在查找条件中需要全部匹配的个数条件。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html new file mode 100644 index 00000000..69caf1a5 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html @@ -0,0 +1,119 @@ + + + + + + + + + ConstructorFinder - class | Yuki Hook API + + + + +

    ConstructorFinder - class

    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

    paramCount - field

    var paramCount: Int
    +

    变更记录

    v1.0.67 新增

    功能描述

    设置 Constructor 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此变量指定参数个数。

    若参数个数小于零则忽略并使用 param

    modifiers - method

    fun modifiers(conditions: ModifierConditions): IndexTypeCondition
    +

    变更记录

    v1.0.67 新增

    v1.0.80 修改

    将方法体进行 inline

    v1.1.0 修改

    合并到 ModifierConditions

    功能描述

    设置 Constructor 标识符筛选条件。

    可不设置筛选条件,默认模糊查找并取第一个匹配的 Constructor

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    emptyParam - method

    fun emptyParam(): IndexTypeCondition
    +

    变更记录

    v1.0.75 新增

    功能描述

    设置 Constructor 空参数、无参数。

    param - method

    fun param(vararg paramType: Any): IndexTypeCondition
    +

    变更记录

    v1.0 添加

    功能描述

    设置 Constructor 参数。

    如果同时使用了 paramCountparamType 的数量必须与 paramCount 完全匹配。

    如果 Constructor 中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。

    特别注意

    无参 Constructor 请使用 emptyParam 设置查找条件。

    有参 Constructor 必须使用此方法设定参数或使用 paramCount 指定个数。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(num: Int): IndexTypeCondition
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置 Constructor 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数。

    若参数个数小于零则忽略并使用 param

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(numRange: IntRange): IndexTypeCondition
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Constructor 参数个数范围。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数范围。

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(conditions: CountConditions): IndexTypeCondition
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Constructor 参数个数条件。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数条件。

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    superClass - method

    fun superClass(isOnlySuperClass: Boolean)
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置在 classSet 的所有父类中查找当前 Constructor

    注意

    若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。

    RemedyPlan - class

    inner class RemedyPlan internal constructor()
    +

    变更记录

    v1.0 添加

    功能描述

    Constructor 重查找实现类,可累计失败次数直到查找成功。

    constructor - method

    inline fun constructor(initiate: ConstructorConditions)
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建需要重新查找的 Constructor

    你可以添加多个备选 Constructor,直到成功为止,若最后依然失败,将停止查找并输出错误日志。

    Result - class

    inner class Result internal constructor()
    +

    变更记录

    v1.0.1 新增

    功能描述

    RemedyPlan 结果实现类。

    onFind - method

    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.
    +}
    +

    Process - class

    inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    Constructor 查找结果处理类,为 hookInstance 提供。

    result - method

    inline fun result(initiate: Process.() -> Unit): Process
    +

    变更记录

    v1.1.0 新增

    功能描述

    创建监听结果事件方法体。

    功能示例

    你可以使用 lambda 形式创建 Result 类。

    示例如下

    constructor {
    +    // Your code here.
    +}.result {
    +    all()
    +    remedys {}
    +    onNoSuchConstructor {}
    +}
    +

    all - method

    fun all(): Process
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置全部查找条件匹配的多个 Constructor 实例结果到 hookInstance

    remedys - method

    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.
    +    }
    +}
    +

    onNoSuchConstructor - method

    inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    监听找不到 Constructor 时。

    只会返回第一次的错误信息,不会返回 RemedyPlan 的错误信息。

    Result - class

    inner class Result internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    继承到接口 BaseResult

    功能描述

    Constructor 查找结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建监听结果事件方法体。

    功能示例

    你可以使用 lambda 形式创建 Result 类。

    示例如下

    constructor {
    +    // Your code here.
    +}.result {
    +    get().call()
    +    all()
    +    remedys {}
    +    onNoSuchConstructor {}
    +}
    +

    get - method

    fun get(): Instance
    +

    变更记录

    v1.0.2 新增

    功能描述

    获得 Constructor 实例处理类。

    若有多个 Constructor 结果只会返回第一个。

    特别注意

    若你设置了 remedys 请使用 wait 回调结果方法。

    功能示例

    你可以通过获得方法所在实例来执行构造方法创建新的实例对象。

    示例如下

    constructor {
    +    // Your code here.
    +}.get().call()
    +

    你可以 cast 构造方法为指定类型的实例对象。

    示例如下

    constructor {
    +    // Your code here.
    +}.get().newInstance<TestClass>()
    +

    特别注意

    若构造方法含有参数则后方参数必填。

    示例如下

    constructor {
    +    // Your code here.
    +}.get().newInstance<TestClass>("param1", "param2")
    +

    all - method

    fun all(): ArrayList<Instance>
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得 Constructor 实例处理类数组。

    返回全部查找条件匹配的多个 Constructor 实例结果。

    功能示例

    你可以通过此方法来获得当前条件结果中匹配的全部 Constructor

    示例如下

    constructor {
    +    // Your code here.
    +}.all().forEach { instance ->
    +    instance.call(...)
    +}
    +

    give - method

    fun give(): Constructor<*>?
    +

    变更记录

    v1.0.67 新增

    功能描述

    得到 Constructor 本身。

    若有多个 Constructor 结果只会返回第一个。

    在查找条件找不到任何结果的时候将返回 null

    giveAll - method

    fun giveAll(): HashSet<Constructor<*>>
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到 Constructor 本身数组。

    返回全部查找条件匹配的多个 Constructor 实例。

    在查找条件找不到任何结果的时候将返回空的 HashSet

    wait - method

    fun wait(initiate: Instance.() -> Unit)
    +

    变更记录

    v1.0.2 新增

    功能描述

    获得 Constructor 实例处理类,配合 RemedyPlan 使用。

    若有多个 Constructor 结果只会返回第一个。

    特别注意

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    waitAll - method

    fun waitAll(initiate: ArrayList<Instance>.() -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得 Constructor 实例处理类数组,配合 RemedyPlan 使用。

    返回全部查找条件匹配的多个 Constructor 实例结果。

    特别注意

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    remedys - method

    inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建 Constructor 重查找功能。

    功能示例

    当你遇到一种 Constructor 可能存在不同形式的存在时,可以使用 RemedyPlan 重新查找它,而没有必要使用 onNoSuchConstructor 捕获异常二次查找 Constructor

    若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。

    示例如下

    constructor {
    +    // Your code here.
    +}.remedys {
    +    constructor {
    +        // Your code here.
    +    }
    +    constructor {
    +        // Your code here.
    +    }
    +}
    +

    onNoSuchConstructor - method

    inline fun onNoSuchConstructor(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    监听找不到 Constructor 时。

    只会返回第一次的错误信息,不会返回 RemedyPlan 的错误信息。

    ignored - method

    fun ignored(): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    忽略异常并停止打印任何错误日志。

    isNotIgnoredHookingFailurefalse 则自动忽略。

    注意

    此时若要监听异常结果,你需要手动实现 onNoSuchConstructor 方法。

    ignoredError - method

    变更记录

    v1.0.3 新增

    v1.1.0 作废

    请转移到新方法 ignored()

    Instance - class

    inner class Instance internal constructor(private val constructor: Constructor<*>?)
    +

    变更记录

    v1.0.2 新增

    v1.1.0 修改

    新增 constructor 参数

    功能描述

    Constructor 实例处理类。

    call - method

    fun call(vararg param: Any?): Any?
    +

    变更记录

    v1.0.2 新增

    功能描述

    执行 Constructor 创建目标实例,不指定目标实例类型。

    newInstance - method

    fun <T> newInstance(vararg param: Any?): T?
    +

    变更记录

    v1.0.2 新增

    功能描述

    执行 Constructor 创建目标实例 ,指定 T 目标实例类型。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html new file mode 100644 index 00000000..00e68930 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html @@ -0,0 +1,115 @@ + + + + + + + + + FieldFinder - class | Yuki Hook API + + + + +

    FieldFinder - class

    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 移除

    name - field

    var name: String
    +

    变更记录

    v1.0 添加

    v1.0.70 修改

    允许不填写名称

    功能描述

    设置 Field 名称。

    特别注意

    若不填写名称则必须存在一个其它条件。

    type - field

    var type: Any?
    +

    变更记录

    v1.0 添加

    功能描述

    设置 Field 类型。

    可不填写类型。

    modifiers - method

    fun modifiers(conditions: ModifierConditions): IndexTypeCondition
    +

    变更记录

    v1.0.67 新增

    v1.0.80 修改

    将方法体进行 inline

    v1.1.0 修改

    合并到 ModifierConditions

    功能描述

    设置 Field 标识符筛选条件。

    可不设置筛选条件。

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    order - method

    fun order(): IndexTypeCondition
    +

    变更记录

    v1.0.70 新增

    功能描述

    顺序筛选字节码的下标。

    name - method

    fun name(value: String): IndexTypeCondition
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置 Field 名称。

    特别注意

    若不填写名称则必须存在一个其它条件。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    name - method

    fun name(conditions: NameConditions): IndexTypeCondition
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    合并到 NameConditions

    功能描述

    设置 Field 名称条件。

    特别注意

    若不填写名称则必须存在一个其它条件。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    type - method

    fun type(value: Any): IndexTypeCondition
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置 Field 类型。

    特别注意

    可不填写类型。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    superClass - method

    fun superClass(isOnlySuperClass: Boolean)
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置在 classSet 的所有父类中查找当前 Field

    注意

    若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。

    RemedyPlan - class

    inner class RemedyPlan internal constructor()
    +

    变更记录

    v1.1.0 新增

    功能描述

    Field 重查找实现类,可累计失败次数直到查找成功。

    field - method

    inline fun field(initiate: FieldConditions): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    创建需要重新查找的 Field

    你可以添加多个备选 Field,直到成功为止,若最后依然失败,将停止查找并输出错误日志。

    Result - class

    inner class Result internal constructor()
    +

    变更记录

    v1.1.0 新增

    功能描述

    RemedyPlan 结果实现类。

    onFind - method

    fun onFind(initiate: HashSet<Field>.() -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    当在 RemedyPlan 中找到结果时。

    功能示例

    你可以方便地对重查找的 Field 实现 onFind 方法。

    示例如下

    field {
    +    // Your code here.
    +}.onFind {
    +    // Your code here.
    +}
    +

    Result - class

    inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    继承到接口 BaseResult

    功能描述

    Field 查找结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建监听结果事件方法体。

    功能示例

    你可以使用 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 {}
    +}
    +

    get - method

    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")
    +

    all - method

    fun all(instance: Any?): ArrayList<Instance>
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得 Field 实例处理类数组。

    返回全部查找条件匹配的多个 Field 实例结果。

    功能示例

    你可以通过此方法来获得当前条件结果中匹配的全部 Field,其 Field 所在实例用法与 get 相同。

    示例如下

    field {
    +    // Your code here.
    +}.all(instance).forEach { instance ->
    +    instance.self
    +}
    +

    give - method

    fun give(): Field?
    +

    变更记录

    v1.0 添加

    功能描述

    得到 Field 本身。

    若有多个 Field 结果只会返回第一个。

    在查找条件找不到任何结果的时候将返回 null

    giveAll - method

    fun giveAll(): HashSet<Field>
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到 Field 本身数组。

    返回全部查找条件匹配的多个 Field 实例。

    在查找条件找不到任何结果的时候将返回空的 HashSet

    wait - method

    fun wait(instance: Any?, initiate: Instance.() -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得 Field 实例处理类,配合 RemedyPlan 使用。

    若有多个 Field 结果只会返回第一个。

    特别注意

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    waitAll - method

    fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得 Field 实例处理类数组,配合 RemedyPlan 使用。

    返回全部查找条件匹配的多个 Field 实例结果。

    特别注意

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    remedys - method

    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.
    +    }
    +}
    +

    onNoSuchField - method

    fun onNoSuchField(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.0 添加

    功能描述

    监听找不到 Field 时。

    ignored - method

    fun ignored(): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    忽略异常并停止打印任何错误日志。

    isNotIgnoredHookingFailurefalse 则自动忽略。

    注意

    此时若要监听异常结果,你需要手动实现 onNoSuchField 方法。

    ignoredError - method

    变更记录

    v1.0.3 新增

    v1.1.0 作废

    请转移到新方法 ignored()

    Instance - class

    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 自身的实例化对象

    current - method

    fun current(ignored: Boolean): CurrentClass?
    +
    inline fun current(ignored: Boolean, initiate: CurrentClass.() -> Unit): Any?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前 Field 自身 self 实例的类操作对象 CurrentClass

    cast - method

    fun <T> cast(): T?
    +

    变更记录

    v1.0 添加

    v1.0.68 修改

    修改 ofcast

    移动方法到 Instance

    功能描述

    得到当前 Field 实例。

    byte - method

    fun byte(): Byte?
    +

    变更记录

    v1.0.68 新增

    功能描述

    得到当前 Field Byte 实例。

    int - method

    fun int(): Int
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 ofIntint

    移动方法到 Instance

    功能描述

    得到当前 Field Int 实例。

    long - method

    fun long(): Long
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 ofLonglong

    移动方法到 Instance

    功能描述

    得到当前 Field Long 实例。

    short - method

    fun short(): Short
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 ofShortshort

    移动方法到 Instance

    功能描述

    得到当前 Field Short 实例。

    double - method

    fun double(): Double
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 ofDoubledouble

    移动方法到 Instance

    功能描述

    得到当前 Field Double 实例。

    float - method

    fun float(): Float
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 ofFloatfloat

    移动方法到 Instance

    功能描述

    得到当前 Field Float 实例。

    string - method

    fun string(): String
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 ofStringstring

    移动方法到 Instance

    功能描述

    得到当前 Field String 实例。

    char - method

    fun char(): Char
    +

    变更记录

    v1.0.68 新增

    功能描述

    得到当前 Field Char 实例。

    boolean - method

    fun boolean(): Boolean
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 ofBooleanboolean

    移动方法到 Instance

    功能描述

    得到当前 Field Boolean 实例。

    any - method

    fun any(): Any?
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 ofAnyany

    移动方法到 Instance

    功能描述

    得到当前 Field Any 实例。

    array - method

    inline fun <reified T> array(): Array<T>
    +

    变更记录

    v1.0.68 新增

    功能描述

    得到当前 Field Array 实例。

    list - method

    inline fun <reified T> list(): List<T>
    +

    变更记录

    v1.0.68 新增

    功能描述

    得到当前 Field List 实例。

    set - method

    fun set(any: Any?)
    +

    变更记录

    v1.0 添加

    功能描述

    设置当前 Field 实例。

    setTrue - method

    fun setTrue()
    +

    变更记录

    v1.0 添加

    功能描述

    设置当前 Field 实例为 true

    特别注意

    请确保实例对象类型为 Boolean

    setFalse - method

    fun setFalse()
    +

    变更记录

    v1.0 添加

    功能描述

    设置当前 Field 实例为 false

    特别注意

    请确保实例对象类型为 Boolean

    setNull - method

    fun setNull()
    +

    变更记录

    v1.0 添加

    功能描述

    设置当前 Field 实例为 null

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html new file mode 100644 index 00000000..66fa2e39 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html @@ -0,0 +1,134 @@ + + + + + + + + + MethodFinder - class | Yuki Hook API + + + + +

    MethodFinder - class

    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

    name - field

    var name: String
    +

    变更记录

    v1.0 添加

    v1.0.70 修改

    允许不填写名称

    功能描述

    设置 Method 名称。

    特别注意

    若不填写名称则必须存在一个其它条件。

    paramCount - field

    var paramCount: Int
    +

    变更记录

    v1.0.67 新增

    功能描述

    设置 Method 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此变量指定参数个数。

    若参数个数小于零则忽略并使用 param

    returnType - field

    var returnType: Any?
    +

    变更记录

    v1.0 添加

    功能描述

    设置 Method 返回值,可不填写返回值。

    modifiers - method

    fun modifiers(conditions: ModifierConditions): IndexTypeCondition
    +

    变更记录

    v1.0.67 新增

    v1.0.80 修改

    将方法体进行 inline

    v1.1.0 修改

    合并到 ModifierConditions

    功能描述

    设置 Method 标识符筛选条件。

    可不设置筛选条件。

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    emptyParam - method

    fun emptyParam(): IndexTypeCondition
    +

    变更记录

    v1.0.75 新增

    功能描述

    设置 Method 空参数、无参数。

    param - method

    fun param(vararg paramType: Any): IndexTypeCondition
    +

    变更记录

    v1.0 添加

    功能描述

    设置 Method 参数。

    如果同时使用了 paramCountparamType 的数量必须与 paramCount 完全匹配。

    如果 Method 中存在一些无意义又很长的类型,你可以使用 VagueType 来替代它。

    特别注意

    无参 Method 请使用 emptyParam 设置查找条件。

    有参 Method 必须使用此方法设定参数或使用 paramCount 指定个数。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    order - method

    fun order(): IndexTypeCondition
    +

    变更记录

    v1.0.70 新增

    功能描述

    顺序筛选字节码的下标。

    name - method

    fun name(value: String): IndexTypeCondition
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置 Method 名称。

    特别注意

    若不填写名称则必须存在一个其它条件。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    name - method

    fun name(conditions: NameConditions): IndexTypeCondition
    +

    变更记录

    v1.0.88 新增

    v1.1.0 修改

    合并到 NameConditions

    功能描述

    设置 Method 名称条件。

    特别注意

    若不填写名称则必须存在一个其它条件。

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(num: Int): IndexTypeCondition
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置 Method 参数个数。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数。

    若参数个数小于零则忽略并使用 param

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(numRange: IntRange): IndexTypeCondition
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 参数个数范围。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数范围。

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    paramCount - method

    fun paramCount(conditions: CountConditions): IndexTypeCondition
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置 Method 参数个数条件。

    你可以不使用 param 指定参数类型而是仅使用此方法指定参数个数条件。

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    returnType - method

    fun returnType(value: Any): IndexTypeCondition
    +

    变更记录

    v1.0.70 新增

    功能描述

    设置 Method 返回值。

    可不填写返回值。

    特别注意

    存在多个 IndexTypeCondition 时除了 order 只会生效最后一个。

    superClass - method

    fun superClass(isOnlySuperClass: Boolean)
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置在 classSet 的所有父类中查找当前 Method

    注意

    若当前 classSet 的父类较多可能会耗时,API 会自动循环到父类继承是 Any 前的最后一个类。

    RemedyPlan - class

    inner class RemedyPlan internal constructor()
    +

    变更记录

    v1.0 添加

    功能描述

    Method 重查找实现类,可累计失败次数直到查找成功。

    method - method

    inline fun method(initiate: MethodConditions): Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建需要重新查找的 Method

    你可以添加多个备选 Method,直到成功为止,若最后依然失败,将停止查找并输出错误日志。

    Result - class

    inner class Result internal constructor()
    +

    变更记录

    v1.0.1 新增

    功能描述

    RemedyPlan 结果实现类。

    onFind - method

    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.
    +}
    +

    Process - class

    inner class Process internal constructor(internal val isNoSuch: Boolean, internal val throwable: Throwable?) : BaseResult
    +

    变更记录

    v1.1.0 新增

    功能描述

    Method 查找结果处理类,为 hookInstance 提供。

    result - method

    inline fun result(initiate: Process.() -> Unit): Process
    +

    变更记录

    v1.1.0 新增

    功能描述

    创建监听结果事件方法体。

    功能示例

    你可以使用 lambda 形式创建 Result 类。

    示例如下

    method {
    +    // Your code here.
    +}.result {
    +    all()
    +    remedys {}
    +    onNoSuchMethod {}
    +}
    +

    all - method

    fun all(): Process
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置全部查找条件匹配的多个 Method 实例结果到 hookInstance

    remedys - method

    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.
    +    }
    +}
    +

    onNoSuchMethod - method

    inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    监听找不到 Method 时。

    只会返回第一次的错误信息,不会返回 RemedyPlan 的错误信息。

    Result - class

    inner class Result internal constructor(internal val isNoSuch: Boolean, private val throwable: Throwable?) : BaseResult
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    继承到接口 BaseResult

    功能描述

    Method 查找结果实现类。

    result - method

    inline fun result(initiate: Result.() -> Unit): Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建监听结果事件方法体。

    功能示例

    你可以使用 lambda 形式创建 Result 类。

    示例如下

    method {
    +    // Your code here.
    +}.result {
    +    get(instance).call()
    +    all(instance)
    +    remedys {}
    +    onNoSuchMethod {}
    +}
    +

    get - method

    fun get(instance: Any?): Instance
    +

    变更记录

    v1.0.2 新增

    功能描述

    获得 Method 实例处理类。

    若有多个 Method 结果只会返回第一个。

    特别注意

    若你设置了 remedys 请使用 wait 回调结果方法。

    功能示例

    你可以通过获得方法所在实例来执行 Method

    示例如下

    method {
    +    // Your code here.
    +}.get(instance).call()
    +

    若当前为静态方法,你可以不设置实例。

    示例如下

    method {
    +    // Your code here.
    +}.get().call()
    +

    all - method

    fun all(instance: Any?): ArrayList<Instance>
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得 Method 实例处理类数组。

    返回全部查找条件匹配的多个 Method 实例结果。

    功能示例

    你可以通过此方法来获得当前条件结果中匹配的全部 Method,其方法所在实例用法与 get 相同。

    示例如下

    method {
    +    // Your code here.
    +}.all(instance).forEach { instance ->
    +    instance.call(...)
    +}
    +

    give - method

    fun give(): Method?
    +

    变更记录

    v1.0.67 新增

    功能描述

    得到 Method 本身。

    若有多个 Method 结果只会返回第一个。

    在查找条件找不到任何结果的时候将返回 null

    giveAll - method

    fun giveAll(): HashSet<Method>
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到 Method 本身数组。

    返回全部查找条件匹配的多个 Method 实例。

    在查找条件找不到任何结果的时候将返回空的 HashSet

    wait - method

    fun wait(instance: Any?, initiate: Instance.() -> Unit)
    +

    变更记录

    v1.0.2 新增

    功能描述

    获得 Method 实例处理类,配合 RemedyPlan 使用。

    若有多个 Method 结果只会返回第一个。

    特别注意

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    waitAll - method

    fun waitAll(instance: Any?, initiate: ArrayList<Instance>.() -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得 Method 实例处理类数组,配合 RemedyPlan 使用。

    返回全部查找条件匹配的多个 Method 实例结果。

    特别注意

    若你设置了 remedys 必须使用此方法才能获得结果。

    若你没有设置 remedys 此方法将不会被回调。

    remedys - method

    inline fun remedys(initiate: RemedyPlan.() -> Unit): Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    创建 Method 重查找功能。

    功能示例

    当你遇到一种 Method 可能存在不同形式的存在时,可以使用 RemedyPlan 重新查找它,而没有必要使用 onNoSuchMethod 捕获异常二次查找 Method

    若第一次查找失败了,你还可以在这里继续添加此方法体直到成功为止。

    示例如下

    method {
    +    // Your code here.
    +}.remedys {
    +    method {
    +        // Your code here.
    +    }
    +    method {
    +        // Your code here.
    +    }
    +}
    +

    onNoSuchMethod - method

    inline fun onNoSuchMethod(result: (Throwable) -> Unit): Result
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    监听找不到 Method 时。

    只会返回第一次的错误信息,不会返回 RemedyPlan 的错误信息。

    ignored - method

    fun ignored(): Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    忽略异常并停止打印任何错误日志。

    isNotIgnoredHookingFailurefalse 则自动忽略。

    注意

    此时若要监听异常结果,你需要手动实现 onNoSuchMethod 方法。

    ignoredError - method

    变更记录

    v1.0.3 新增

    v1.1.0 作废

    请转移到新方法 ignored()

    Instance - class

    inner class Instance internal constructor(private val instance: Any?, private val method: Method?)
    +

    变更记录

    v1.0.2 新增

    v1.1.0 修改

    新增 method 参数

    功能描述

    Method 实例处理类。

    original - method

    fun original(): Instance
    +

    变更记录

    v1.1.0 新增

    功能描述

    标识需要调用当前 Method 未经 Hook 的原始方法。

    若当前 Method 并未 Hook 则会使用原始的 Method.invoke 方法调用。

    特别注意

    你只能在 (Xposed) 宿主环境中使用此功能。

    call - method

    fun call(vararg param: Any?): Any?
    +

    变更记录

    v1.0.2 新增

    功能描述

    执行 Method,不指定返回值类型。

    invoke - method

    fun <T> invoke(vararg param: Any?): T?
    +

    变更记录

    v1.0.2 新增

    功能描述

    执行 Method,指定 T 返回值类型。

    byte - method

    fun byte(vararg param: Any?): Byte?
    +

    变更记录

    v1.0.68 新增

    功能描述

    执行 Method,指定 Byte 返回值类型。

    int - method

    fun int(vararg param: Any?): Int
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 callIntint

    功能描述

    执行 Method,指定 Int 返回值类型。

    long - method

    fun long(vararg param: Any?): Long
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 callLonglong

    功能描述

    执行 Method,指定 Long 返回值类型。

    short - method

    fun short(vararg param: Any?): Short
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 callShortshort

    功能描述

    执行 Method,指定 Short 返回值类型。

    double - method

    fun double(vararg param: Any?): Double
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 callDoubledouble

    功能描述

    执行 Method,指定 Double 返回值类型。

    float - method

    fun float(vararg param: Any?): Float
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 callFloatfloat

    功能描述

    执行 Method,指定 Float 返回值类型。

    string - method

    fun string(vararg param: Any?): String
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 callStringstring

    功能描述

    执行 Method,指定 String 返回值类型。

    char - method

    fun char(vararg param: Any?): Char
    +

    变更记录

    v1.0.68 新增

    功能描述

    执行 Method,指定 Char 返回值类型。

    boolean - method

    fun boolean(vararg param: Any?): Boolean
    +

    变更记录

    v1.0.65 新增

    v1.0.68 修改

    修改 callBooleanboolean

    功能描述

    执行 Method,指定 Boolean 返回值类型。

    array - method

    inline fun <reified T> array(vararg param: Any?): Array<T>
    +

    变更记录

    v1.0.68 新增

    功能描述

    执行 Method,指定 Array 返回值类型。

    list - method

    inline fun <reified T> list(vararg param: Any?): List<T>
    +

    变更记录

    v1.0.68 新增

    功能描述

    执行 Method,指定 List 返回值类型。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html new file mode 100644 index 00000000..736be33c --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html @@ -0,0 +1,35 @@ + + + + + + + + + YukiBaseHooker - class | Yuki Hook API + + + + +

    YukiBaseHooker - class

    abstract class YukiBaseHooker : PackageParam()
    +

    变更记录

    v1.0 添加

    功能描述

    YukiHookAPI 的子类 Hooker 实现。

    onHook - method

    fun onHook()
    +

    变更记录

    v1.0 添加

    功能描述

    子类 Hook 开始。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html new file mode 100644 index 00000000..889aeda5 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html @@ -0,0 +1,91 @@ + + + + + + + + + ReflectionFactory - kt | Yuki Hook API + + + + +

    ReflectionFactory - kt

    变更记录

    v1.0 添加

    功能描述

    这是自定义 MemberClass 相关功能的查找匹配以及 invoke 的封装类。

    MembersType - class

    enum class MembersType
    +

    变更记录

    v1.1.0 新增

    功能描述

    定义一个 Class 中的 Member 类型

    ALL - enum

    ALL
    +

    变更记录

    v1.1.0 新增

    功能描述

    全部 MethodConstructor

    METHOD - enum

    METHOD
    +

    变更记录

    v1.1.0 新增

    功能描述

    全部 Method

    CONSTRUCTOR - enum

    CONSTRUCTOR
    +

    变更记录

    v1.1.0 新增

    功能描述

    全部 Constructor

    ClassLoader.searchClass - ext-method

    inline fun ClassLoader.searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    通过当前 ClassLoader 按指定条件查找并得到 Dex 中的 Class

    特别注意

    此方法在 Class 数量过多及查找条件复杂时会非常耗时。

    建议启用 async 或设置 name 参数,name 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。

    此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。

    ClassLoader.onLoadClass - ext-method

    fun ClassLoader.onLoadClass(result: (Class<*>) -> Unit)
    +

    变更记录

    v1.1.0 新增

    功能描述

    监听当前 ClassLoaderClassLoader.loadClass 方法装载。

    特别注意

    只有当前 ClassLoader 有主动使用 ClassLoader.loadClass 事件时才能被捕获。

    这是一个实验性功能,一般情况下不会用到此方法,不保证不会发生错误。

    只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。

    功能示例

    针对一些使用特定 ClassLoader 装载 Class 的宿主应用,你可以使用此方法来监听 Class 加载情况。

    注意

    为了防止发生问题,你需要得到一个存在的 ClassLoader 实例来使用此功能。

    比如我们在 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() 无参方法

    Class.hasExtends - ext-field

    val Class<*>.hasExtends: Boolean
    +

    变更记录

    v1.0.80 新增

    功能描述

    当前 Class 是否有继承关系,父类是 Any 将被认为没有继承关系。

    classOf - method

    变更记录

    v1.0 添加

    v1.1.0 作废

    请转到 toClass(...) 方法

    String.toClass - ext-method

    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)
    +

    String.toClassOrNull - ext-method

    fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
    +

    变更记录

    v1.1.0 新增

    功能描述

    通过字符串类名转换为 loader 中的实体类。

    找不到 Class 会返回 null,不会抛出异常。

    功能示例

    用法请参考 String.toClass 方法。

    classOf - method

    inline fun <reified T> classOf(loader: ClassLoader?): Class<*>
    +

    变更记录

    v1.1.0 新增

    功能描述

    通过 T 得到其 Class 实例并转换为实体类。

    功能示例

    我们要获取一个 ClassKotlin 下不通过反射时应该这样做。

    示例如下

    DemoClass::class.java
    +

    现在,你可以直接 cast 一个实例并获取它的 Class 对象,必须在当前 ClassLoader 下存在。

    示例如下

    classOf<DemoClass>()
    +

    若目标存在的 Classstub,通过这种方式,你还可以自定义 Class 所在的 ClassLoader

    示例如下

    val customClassLoader: ClassLoader? = ... // 假设这个就是你的 ClassLoader
    +classOf<DemoClass>(customClassLoader)
    +

    String.hasClass - ext-method

    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.
    +}
    +

    Class.hasField - ext-method

    inline fun Class<*>.hasField(initiate: FieldConditions): Boolean
    +

    变更记录

    v1.0.4 新增

    v1.0.67 修改

    合并到 FieldFinder

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    查找变量是否存在。

    Class.hasMethod - ext-method

    inline fun Class<*>.hasMethod(initiate: MethodConditions): Boolean
    +

    变更记录

    v1.0 添加

    v1.0.1 修改

    新增 returnType 参数

    v1.0.67 修改

    合并到 MethodFinder

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    查找方法是否存在。

    Class.hasConstructor - ext-method

    inline fun Class<*>.hasConstructor(initiate: ConstructorConditions): Boolean
    +

    变更记录

    v1.0.2 新增

    v1.0.67 修改

    合并到 ConstructorFinder

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    查找构造方法是否存在。

    Member.hasModifiers - ext-method

    inline fun Member.hasModifiers(conditions: ModifierConditions): Boolean
    +

    变更记录

    v1.0.67 新增

    v1.0.80 修改

    将方法体进行 inline

    v1.1.0 修改

    合并到 ModifierConditions

    功能描述

    查找 Member 中匹配的描述符。

    Class.hasModifiers - ext-method

    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 移除

    Class.field - ext-method

    inline fun Class<*>.field(initiate: FieldConditions): FieldFinder.Result
    +

    变更记录

    v1.0.2 新增

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    查找并得到变量。

    Class.method - ext-method

    inline fun Class<*>.method(initiate: MethodConditions): MethodFinder.Result
    +

    变更记录

    v1.0 添加

    v1.0.1 修改

    obtainMethod 更名为 method

    新增 returnType 参数

    v1.0.2 修改

    合并到 MethodFinder 方法体

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    查找并得到方法。

    Class.constructor - ext-method

    inline fun Class<*>.constructor(initiate: ConstructorConditions): ConstructorFinder.Result
    +

    变更记录

    v1.0 添加

    v1.0.1 修改

    obtainConstructor 更名为 constructor

    v1.0.2 修改

    合并到 ConstructorFinder 方法体

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    查找并得到构造方法。

    callStatic - method

    变更记录

    v1.0 添加

    v1.0.1 修改

    invokeStatic 更名为 callStatic

    v1.0.2 移除

    call - method

    变更记录

    v1.0 添加

    v1.0.1 修改

    invokeAny 更名为 call

    v1.0.2 移除

    Class.generic - ext-method

    fun Class<*>.generic(): GenericClass?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前 Class 的泛型父类。

    如果当前实例不存在泛型将返回 null

    Class.generic - ext-method

    inline fun Class<*>.generic(initiate: GenericClass.() -> Unit): GenericClass?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获得当前 Class 的泛型父类。

    如果当前实例不存在泛型将返回 null

    Any.current - ext-method

    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 修改

    将方法体进行 inline

    v1.1.0 作废

    请转移到 buildOf 方法

    Class.buildOf - ext-method

    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 修改

    将方法体进行 inline

    v1.1.0 修改

    加入无泛型方法 buildOf

    功能描述

    通过构造方法创建新实例,指定类型 T 或任意类型 Any

    Class.allMethods - ext-method

    inline fun Class<*>.allMethods(result: (index: Int, method: Method) -> Unit)
    +

    变更记录

    v1.0.70 新增

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    遍历当前类中的所有方法。

    Class.allConstructors - ext-method

    inline fun Class<*>.allConstructors(result: (index: Int, constructor: Constructor<*>) -> Unit)
    +

    变更记录

    v1.0.70 新增

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    遍历当前类中的所有构造方法。

    Class.allFields - ext-method

    inline fun Class<*>.allFields(result: (index: Int, field: Field) -> Unit)
    +

    变更记录

    v1.0.70 新增

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    遍历当前类中的所有变量。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html new file mode 100644 index 00000000..34ad3ab8 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html @@ -0,0 +1,44 @@ + + + + + + + + + YukiHookFactory - kt | Yuki Hook API + + + + +

    YukiHookFactory - kt

    变更记录

    v1.0 添加

    v1.0.80 修改

    合并到 IYukiHookXposedInit,将方法体进行 inline

    功能描述

    这是 YukiHookAPI 相关 lambda 方法的封装类以及部分 API 用法。

    IYukiHookXposedInit.configs - ext-method

    inline fun IYukiHookXposedInit.configs(initiate: YukiHookAPI.Configs.() -> Unit)
    +

    变更记录

    v1.0.1 新增

    v1.0.80 修改

    合并到 IYukiHookXposedInit

    功能描述

    IYukiHookXposedInit 中配置 Configs

    IYukiHookXposedInit.encase - ext-method

    fun IYukiHookXposedInit.encase(initiate: PackageParam.() -> Unit)
    +
    fun IYukiHookXposedInit.encase(vararg hooker: YukiBaseHooker)
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    合并到 IYukiHookXposedInit

    功能描述

    IYukiHookXposedInit 中调用 YukiHookAPI

    Context.modulePrefs - ext-field

    val Context.modulePrefs: YukiHookModulePrefs
    +

    变更记录

    v1.0 添加

    功能描述

    获取模块的存取对象。

    Context.modulePrefs - ext-method

    fun Context.modulePrefs(name: String): YukiHookModulePrefs
    +

    变更记录

    v1.0 添加

    功能描述

    获取模块的存取对象,可设置 name 为自定义 Sp 存储名称。

    Context.dataChannel - ext-method

    fun Context.dataChannel(packageName: String): YukiHookDataChannel.NameSpace
    +

    变更记录

    v1.0.88 新增

    功能描述

    获取模块的数据通讯桥命名空间对象。

    特别注意

    只能在模块环境使用此功能,其它环境下使用将不起作用。

    Context.processName - ext-field

    val Context.processName: String
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前进程名称。

    Context+Resources.injectModuleAppResources - ext-method

    fun Context.injectModuleAppResources()
    +
    fun Resources.injectModuleAppResources()
    +

    变更记录

    v1.1.0 新增

    功能描述

    向 Hook APP (宿主) ContextResources 注入当前 Xposed 模块的资源。

    注入成功后,你就可以直接使用例如 ImageView.setImageResourceResources.getString 装载当前 Xposed 模块的资源 ID。

    注入的资源作用域仅限当前 ContextResources,你需要在每个用到宿主 ContextResources 的地方重复调用此方法进行注入才能使用。

    特别注意

    只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。

    Context.registerModuleAppActivities - ext-method

    fun Context.registerModuleAppActivities(proxy: Any?)
    +

    变更记录

    v1.1.0 新增

    功能描述

    向 Hook APP (宿主) 注册当前 Xposed 模块的 Activity

    注册成功后,你就可以直接使用 Context.startActivity 来启动未在宿主中注册的 Activity

    使用此方法会在未注册的 Activity 在 Hook APP (宿主) 中启动时自动调用 injectModuleAppResources 注入当前 Xposed 模块的资源。

    你要将需要在宿主启动的 Activity 继承于 ModuleAppActivityModuleAppCompatActivity

    特别注意

    只能在 (Xposed) 宿主环境使用此功能,其它环境下使用将不生效且会打印警告信息。

    Context.applyModuleTheme - ext-method

    fun Context.applyModuleTheme(theme: Int, configuration: Configuration?): ModuleContextThemeWrapper
    +

    变更记录

    v1.1.0 新增

    功能描述

    生成一个 ContextThemeWrapper 代理以应用当前 Xposed 模块的主题资源。

    在 Hook APP (宿主) 中使用此方法会自动调用 injectModuleAppResources 注入当前 Xposed 模块的资源。

    如果在 Hook APP (宿主) 中使用此方法发生 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

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html new file mode 100644 index 00000000..89dceb7f --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html @@ -0,0 +1,59 @@ + + + + + + + + + LoggerFactory - kt | Yuki Hook API + + + + +

    LoggerFactory - kt

    变更记录

    v1.0 添加

    功能描述

    这是 YukiHookAPI 的日志封装类,可实现同时向 LogcatXposedBridge.log 打印日志的功能。

    LoggerType - class

    enum class LoggerType
    +

    变更记录

    v1.1.0 新增

    功能描述

    需要打印的日志类型。

    决定于模块与 (Xposed) 宿主环境使用的打印方式。

    LOGD - enum

    LOGD
    +

    变更记录

    v1.1.0 新增

    功能描述

    仅使用 android.util.Log

    XPOSEDBRIDGE - enum

    XPOSEDBRIDGE
    +

    变更记录

    v1.1.0 新增

    功能描述

    仅使用 XposedBridge.log

    特别注意

    只能在 (Xposed) 宿主环境中使用,模块环境将不生效。

    SCOPE - enum

    SCOPE
    +

    变更记录

    v1.1.0 新增

    功能描述

    分区使用。

    (Xposed) 宿主环境仅使用 XPOSEDBRIDGE

    模块环境仅使用 LOGD

    BOTH - enum

    BOTH
    +

    变更记录

    v1.1.0 新增

    功能描述

    同时使用。

    (Xposed) 宿主环境使用 LOGDXPOSEDBRIDGE

    模块环境仅使用 LOGD

    YukiHookLogger - object

    object YukiHookLogger
    +

    变更记录

    v1.1.0 新增

    功能描述

    调试日志实现类。

    contents - field

    val contents: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    获取当前日志文件内容。

    如果当前没有已记录的日志会返回空字符串。

    clear - method

    fun clear()
    +

    变更记录

    v1.1.0 新增

    功能描述

    清除全部已记录的日志。

    saveToFile - method

    fun saveToFile(fileName: String)
    +

    变更记录

    v1.1.0 新增

    功能描述

    保存当前日志到文件。

    若当前未开启 Configs.isRecord 或记录为空则不会进行任何操作。

    日志文件会追加到 fileName 的文件结尾,若文件不存在会自动创建。

    特别注意

    文件读写权限取决于当前宿主已获取的权限。

    Configs - object

    object Configs
    +

    变更记录

    v1.1.0 新增

    功能描述

    配置 YukiHookLogger

    TAG - field

    const val TAG: Int
    +

    变更记录

    v1.1.0 新增

    功能描述

    标签。

    PRIORITY - field

    const val PRIORITY: Int
    +

    变更记录

    v1.1.0 新增

    功能描述

    优先级。

    PACKAGE_NAME - field

    const val PACKAGE_NAME: Int
    +

    变更记录

    v1.1.0 新增

    功能描述

    当前宿主的包名。

    USER_ID - field

    const val USER_ID: Int
    +

    变更记录

    v1.1.0 新增

    功能描述

    当前宿主的用户 ID (主用户不显示)。

    isEnable - field

    var isEnable: Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    是否启用调试日志的输出功能。

    关闭后将会停用 YukiHookAPI 对全部日志的输出。

    但是不影响当你手动调用下面这些方法输出日志。

    loggerDloggerIloggerWloggerE

    isEnable 关闭后 YukiHookAPI.Configs.isDebug 也将同时关闭。

    isRecord - field

    var isRecord: Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    是否启用调试日志的记录功能。

    开启后将会在内存中记录全部可用的日志和异常堆栈。

    需要同时启用 isEnable 才能有效。

    特别注意

    过量的日志可能会导致宿主运行缓慢或造成频繁 GC。

    开启后你可以调用 YukiHookLogger.saveToFile 实时保存日志到文件或使用 YukiHookLogger.contents 获取实时日志文件。

    tag - field

    var tag: String
    +

    变更记录

    v1.1.0 新增

    功能描述

    这是一个调试日志的全局标识。

    默认文案为 YukiHookAPI

    你可以修改为你自己的文案。

    elements - method

    fun elements(vararg item: Int)
    +

    变更记录

    v1.1.0 新增

    功能描述

    自定义调试日志对外显示的元素。

    只对日志记录和 XposedBridge.log 生效。

    日志元素的排列将按照你在 item 中设置的顺序进行显示。

    你还可以留空 item 以不显示除日志内容外的全部元素。

    可用的元素有:TAGPRIORITYPACKAGE_NAMEUSER_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
    +

    loggerD - method

    fun loggerD(tag: String, msg: String, type: LoggerType)
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    新增 type 参数

    功能描述

    LogcatXposedBridge 打印日志,级别 D

    tag 的默认参数为 YukiHookAPI.Configs.debugTag,你可以进行自定义。

    loggerI - method

    fun loggerI(tag: String, msg: String, type: LoggerType)
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    新增 type 参数

    功能描述

    LogcatXposedBridge 打印日志,级别 I

    tag 的默认参数为 YukiHookAPI.Configs.debugTag,你可以进行自定义。

    loggerW - method

    fun loggerW(tag: String, msg: String, type: LoggerType)
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    新增 type 参数

    功能描述

    LogcatXposedBridge 打印日志,级别 W

    tag 的默认参数为 YukiHookAPI.Configs.debugTag,你可以进行自定义。

    loggerE - method

    fun loggerE(tag: String, msg: String, e: Throwable?, type: LoggerType)
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    新增 type 参数

    功能描述

    LogcatXposedBridge 打印日志,级别 E,可携带 e 异常信息,将打印异常堆栈。

    tag 的默认参数为 YukiHookAPI.Configs.debugTag,你可以进行自定义。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html new file mode 100644 index 00000000..44be42d4 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html @@ -0,0 +1,118 @@ + + + + + + + + + HookParam - class | Yuki Hook API + + + + +

    HookParam - class

    class HookParam internal constructor(private val creatorInstance: YukiMemberHookCreator, private var param: YukiHookCallback.Param?)
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    移动 HookParamWrapperYukiHookCallback.Param

    修正拼写错误的 creater 命名到 creator

    功能描述

    Hook 方法、构造方法的目标对象实现类。

    args - field

    val args: Array<Any?>
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook 对象 memberconstructor 的参数对象数组。

    这里的数组每项类型默认为 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()

    instance - field

    val instance: Any
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook 实例的对象。

    特别注意

    如果你当前 Hook 的对象是一个静态,那么它将不存在实例的对象。

    instanceClass - field

    val instanceClass: Class<*>
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook 实例的类对象。

    member - field

    val member: Member
    +

    变更记录

    v1.1.0 新增

    功能描述

    获取当前 Hook 对象的 Member

    在不确定 Member 类型为 MethodConstructor 时可以使用此方法。

    method - field

    val method: Method
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook 对象的方法。

    constructor - field

    val constructor: Constructor
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook 对象的构造方法。

    result - field

    var result: Any?
    +

    变更记录

    v1.0 添加

    功能描述

    获取、设置当前 Hook 对象的 methodconstructor 的返回值。

    hasThrowable - field

    val hasThrowable: Boolean
    +

    变更记录

    v1.1.0 新增

    功能描述

    判断是否存在设置过的方法调用抛出异常。

    throwable - field

    val throwable: Throwable?
    +

    变更记录

    v1.1.0 新增

    功能描述

    获取设置的方法调用抛出异常。

    Throwable.throwToApp - i-ext-method

    fun Throwable.throwToApp()
    +

    变更记录

    v1.1.0 新增

    功能描述

    向 Hook APP 抛出异常。

    使用 hasThrowable 判断当前是否存在被抛出的异常。

    使用 throwable 获取当前设置的方法调用抛出异常。

    仅会在回调方法的 MemberHookCreator.beforeHookMemberHookCreator.afterHook 中生效。

    特别注意

    设置后会同时执行 resultNull 方法并将异常抛出给当前 Hook APP。

    功能示例

    Hook 过程中的异常仅会作用于 (Xposed) 宿主环境,目标 Hook APP 不会受到影响。

    若想将异常抛给 Hook APP,可以直接使用如下方法。

    示例如下

    injectMember {
    +    method {
    +        // ...
    +    }
    +    beforeHook {
    +        RuntimeException("Test Exception").throwToApp()
    +    }
    +}
    +

    特别注意

    向 Hook APP 抛出异常会对其暴露被 Hook 的事实,是不安全的,容易被检测,请按实际场景合理使用。

    result - method

    inline fun <reified T> result(): T?
    +

    变更记录

    v1.0.75 新增

    功能描述

    获取当前 Hook 对象的 methodconstructor 的返回值 T

    firstArg - method

    变更记录

    v1.0.66 新增

    v1.0.75 移除

    lastArgs - method

    变更记录

    v1.0.66 新增

    v1.0.75 移除

    instance - method

    inline fun <reified T> instance(): T
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook 实例的对象 T

    功能示例

    你可以通过 instance 方法轻松使用泛型 cast 为目标对象的类型。

    示例如下

    instance<Activity>().finish()
    +

    args - method

    fun args(): ArgsIndexCondition
    +

    变更记录

    v1.0.75 新增

    功能描述

    获取当前 Hook 对象的 methodconstructor 的参数数组下标实例化类。

    args - method

    fun args(index: Int): ArgsModifyer
    +

    变更记录

    v1.0 添加

    v1.0.75 修改

    默认值 index = 0 移动到新的使用方法 args().first()

    功能描述

    获取当前 Hook 对象的 methodconstructor 的参数实例化对象类。

    功能示例

    你可以通过 args 方法修改当前 Hook 实例的方法、构造方法的参数内容。

    你可以直接使用 set 方法设置 param 为你的目标实例,接受 Any 类型。

    特别注意

    请确保 param 类型为你的目标实例类型。

    示例如下

    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 方法设置 paramtrue

    特别注意

    请确保 param 类型为 Boolean

    示例如下

    args(index = 1).setTrue()
    +

    你还可以使用 setFalse 方法设置 paramfalse

    特别注意

    请确保 param 类型为 Boolean

    示例如下

    args(index = 1).setFalse()
    +

    callOriginal - method

    fun callOriginal(): Any?
    +
    fun <T> callOriginal(): T?
    +

    变更记录

    v1.1.0 新增

    功能描述

    执行原始 Member

    调用自身未进行 Hook 的原始 Member 并调用原始参数执行。

    功能实例

    此方法可以 invoke 原始未经 Hook 的 Member 对象,取决于原始 Member 的参数。

    调用自身原始的方法不会再经过当前 beforeHookafterHook 以及 replaceUnitreplaceAny

    比如我们 Hook 的这个方法被这样调用 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>()
    +    }
    +}
    +

    invokeOriginal - method

    fun invokeOriginal(vararg args: Any?): Any?
    +
    fun <T> invokeOriginal(vararg args: Any?): T?
    +

    变更记录

    v1.0 添加

    v1.1.0 修改

    不再需要使用 member.invokeOriginal 进行调用

    功能描述

    执行原始 Member

    调用自身未进行 Hook 的原始 Member 并自定义 args 执行。

    功能实例

    此方法可以 invoke 原始未经 Hook 的 Member 对象,可自定义需要调用的参数内容。

    调用自身原始的方法不会再经过当前 beforeHookafterHook 以及 replaceUnitreplaceAny

    比如我们 Hook 的这个方法被这样调用 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")
    +    }
    +}
    +

    resultTrue - method

    fun resultTrue()
    +

    变更记录

    v1.0 添加

    功能描述

    设置当前 Hook 对象方法的 result 返回值为 true

    特别注意

    请确保 result 类型为 Boolean

    resultFalse - method

    fun resultFalse()
    +

    变更记录

    v1.0 添加

    功能描述

    设置当前 Hook 对象方法的 result 返回值为 false

    特别注意

    请确保 result 类型为 Boolean

    resultNull - method

    fun resultNull()
    +

    变更记录

    v1.0 添加

    功能描述

    注意

    此方法将强制设置 Hook 对象方法的 resultnull

    ArgsIndexCondition - class

    inner class ArgsIndexCondition internal constructor()
    +

    变更记录

    v1.0.75 新增

    功能描述

    对方法参数的数组下标进行实例化类。

    first - method

    fun first(): ArgsModifyer
    +

    变更记录

    v1.0.75 新增

    功能描述

    获取当前 Hook 对象的 methodconstructor 的参数数组第一位。

    last - method

    fun last(): ArgsModifyer
    +

    变更记录

    v1.0.75 新增

    功能描述

    获取当前 Hook 对象的 methodconstructor 的参数数组最后一位。

    ArgsModifyer - class

    inner class ArgsModifyer internal constructor(private val index: Int)
    +

    变更记录

    v1.0 添加

    功能描述

    对方法参数的修改进行实例化类。

    cast - method

    fun <T> cast(): T?
    +

    变更记录

    v1.0.66 新增

    v1.0.68 修改

    修改 ofcast

    功能描述

    得到方法参数的实例对象 T

    byte - method

    fun byte(): Byte?
    +

    变更记录

    v1.0.68 新增

    功能描述

    得到方法参数的实例对象 Byte。

    int - method

    fun int(): Int
    +

    变更记录

    v1.0.66 新增

    v1.0.68 修改

    修改 ofIntint

    功能描述

    得到方法参数的实例对象 Int。

    long - method

    fun long(): Long
    +

    变更记录

    v1.0.66 新增

    v1.0.68 修改

    修改 ofLonglong

    功能描述

    得到方法参数的实例对象 Long。

    short - method

    fun short(): Short
    +

    变更记录

    v1.0.66 新增

    v1.0.68 修改

    修改 ofShortshort

    功能描述

    得到方法参数的实例对象 Short。

    double - method

    fun double(): Double
    +

    变更记录

    v1.0.66 新增

    v1.0.68 修改

    修改 ofDoubledouble

    功能描述

    得到方法参数的实例对象 Double。

    float - method

    fun float(): Float
    +

    变更记录

    v1.0.66 新增

    v1.0.68 修改

    修改 ofFloatfloat

    功能描述

    得到方法参数的实例对象 Float。

    string - method

    fun string(): String
    +

    变更记录

    v1.0.66 新增

    v1.0.68 修改

    修改 ofStringstring

    功能描述

    得到方法参数的实例对象 String。

    char - method

    fun char(): Char
    +

    变更记录

    v1.0.68 新增

    功能描述

    得到方法参数的实例对象 Char。

    boolean - method

    fun boolean(): Boolean
    +

    变更记录

    v1.0.66 新增

    v1.0.68 修改

    修改 ofBooleanboolean

    功能描述

    得到方法参数的实例对象 Boolean。

    any - method

    fun any(): Any?
    +

    变更记录

    v1.0.77 新增

    功能描述

    得到方法参数的实例对象 Any。

    array - method

    inline fun <reified T> array(): Array<T>
    +

    变更记录

    v1.0.68 新增

    功能描述

    得到方法参数的实例对象 Array。

    list - method

    inline fun <reified T> list(): List<T>
    +

    变更记录

    v1.0.68 新增

    功能描述

    得到方法参数的实例对象 List。

    set - method

    fun <T> set(any: T?)
    +

    变更记录

    v1.0 添加

    功能描述

    设置方法参数的实例对象。

    setNull - method

    fun setNull()
    +

    变更记录

    v1.0 添加

    功能描述

    设置方法参数的实例对象为 null

    setTrue - method

    fun setTrue()
    +

    变更记录

    v1.0 添加

    功能描述

    设置方法参数的实例对象为 true

    特别注意

    请确保目标对象的类型是 Boolean

    setFalse - method

    fun setFalse()
    +

    变更记录

    v1.0 添加

    功能描述

    设置方法参数的实例对象为 false

    特别注意

    请确保目标对象的类型是 Boolean

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html new file mode 100644 index 00000000..d99b31d0 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html @@ -0,0 +1,136 @@ + + + + + + + + + PackageParam - class | Yuki Hook API + + + + +

    PackageParam - class

    open class PackageParam internal constructor(internal var wrapper: PackageParamWrapper?)
    +

    变更记录

    v1.0 添加

    功能描述

    装载 Hook 的目标 APP 入口对象实现类。

    appClassLoader - field

    val appClassLoader:ClassLoader
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook APP 的 ClassLoader

    appInfo - field

    val appInfo: ApplicationInfo
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook APP 的 ApplicationInfo

    appUserId - field

    val appUserId: Int
    +

    变更记录

    v1.1.0 新增

    功能描述

    获取当前 Hook APP 的用户 ID。

    机主为 0,应用双开 (分身) 或工作资料因系统环境不同 ID 也各不相同。

    appContext - field

    val appContext: Application?
    +

    变更记录

    v1.0.72 新增

    v1.1.0 修改

    加入可空类型 (空安全)

    功能描述

    获取当前 Hook APP 的 Application

    特别注意

    首次装载可能是空的,请延迟一段时间再获取或使用 onAppLifecycle 监听来完成。

    appResources - field

    val appResources:Resources?
    +

    变更记录

    v1.0.80 新增

    v1.1.0 修改

    加入可空类型 (空安全)

    功能描述

    获取当前 Hook APP 的 Resources。

    特别注意

    你只能在 HookResources.hook 方法体内或 appContext 装载完毕时进行调用。

    systemContext - field

    val systemContext: Context
    +

    变更记录

    v1.1.0 新增

    功能描述

    获取当前系统框架的 Context

    processName - field

    val processName: String
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook APP 的进程名称。

    packageName - field

    val packageName: String
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook APP 的包名。

    isFirstApplication - field

    val isFirstApplication: Boolean
    +

    变更记录

    v1.0 添加

    功能描述

    获取当前 Hook APP 是否为第一个 Application

    mainProcessName - field

    val mainProcessName: String
    +

    变更记录

    v1.0.70 新增

    功能描述

    获取当前 Hook APP 的主进程名称。

    其对应的就是 packageName

    moduleAppFilePath - field

    val moduleAppFilePath: String
    +

    变更记录

    v1.0.80 新增

    功能描述

    获取当前 Xposed 模块自身 APK 文件路径。

    特别注意

    作为 Hook API 装载时无法使用,会获取到空字符串。

    moduleAppResources - field

    val moduleAppResources: YukiModuleResources
    +

    变更记录

    v1.0.80 新增

    功能描述

    获取当前 Xposed 模块自身 Resources

    特别注意

    作为 Hook API 或不支持的 Hook Framework 装载时无法使用,会抛出异常。

    prefs - field

    val prefs: YukiHookModulePrefs
    +

    变更记录

    v1.0 添加

    功能描述

    获得当前使用的存取数据对象缓存实例。

    特别注意

    作为 Hook API 装载时无法使用,会抛出异常。

    prefs - method

    fun prefs(name: String): YukiHookModulePrefs
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    获得当前使用的存取数据对象缓存实例。

    你可以通过 name 来自定义 Sp 存储的名称。

    特别注意

    作为 Hook API 装载时无法使用,会抛出异常。

    dataChannel - field

    val dataChannel: YukiHookDataChannel.NameSpace
    +

    变更记录

    v1.0.88 新增

    功能描述

    获得当前使用的数据通讯桥命名空间对象。

    特别注意

    作为 Hook API 装载时无法使用,会抛出异常。

    resources - method

    fun resources(): HookResources
    +

    变更记录

    v1.0.80 新增

    功能描述

    获得当前 Hook APP 的 YukiResources 对象。

    请调用 HookResources.hook 方法开始 Hook。

    refreshModuleAppResources - method

    fun refreshModuleAppResources()
    +

    变更记录

    v1.0.87 新增

    功能描述

    刷新当前 Xposed 模块自身 Resources

    onAppLifecycle - method

    inline fun onAppLifecycle(initiate: AppLifecycle.() -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    监听当前 Hook APP 生命周期装载事件。

    注意

    loadZygote 中不会被装载,仅会在 loadSystemloadApp 中装载。

    作为 Hook API 装载时请使用原生的 Application 实现生命周期监听。

    loadApp - method

    inline fun loadApp(name: String, initiate: PackageParam.() -> Unit)
    +
    fun loadApp(name: String, hooker: YukiBaseHooker)
    +

    变更记录

    v1.0 添加

    v1.0.80 修改

    将方法体进行 inline

    功能描述

    装载并 Hook 指定包名的 APP。

    name 为 APP 的包名,后方的两个参数一个可作为 lambda 方法体使用,一个可以直接装载子 Hooker。

    装载并 Hook 指定、全部包名的 APP。

    若要装载 APP Zygote 事件,请使用 loadZygote

    若要 Hook 系统框架,请使用 loadSystem

    功能示例

    你可以使用 loadApplambda 方法体形式或直接装载一个 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)
    +

    loadZygote - method

    inline fun loadZygote(initiate: PackageParam.() -> Unit)
    +
    fun loadZygote(hooker: YukiBaseHooker)
    +

    变更记录

    v1.0.80 新增

    功能描述

    装载 APP Zygote 事件。

    方法中的两个参数一个可作为 lambda 方法体使用,一个可以直接装载子 Hooker。

    loadSystem - method

    inline fun loadSystem(initiate: PackageParam.() -> Unit)
    +
    fun loadSystem(hooker: YukiBaseHooker)
    +

    变更记录

    v1.0.82 新增

    功能描述

    装载并 Hook 系统框架。

    方法中的两个参数一个可作为 lambda 方法体使用,一个可以直接装载子 Hooker。

    withProcess - method

    inline fun withProcess(name: String, initiate: PackageParam.() -> Unit)
    +
    fun withProcess(name: String, hooker: YukiBaseHooker)
    +

    变更记录

    v1.0.70 新增

    功能描述

    装载并 Hook APP 的指定进程。

    name 为 APP 的进程名称,后方的两个参数一个可作为 lambda 方法体使用,一个可以直接装载子 Hooker。

    loadHooker - method

    fun loadHooker(hooker: YukiBaseHooker)
    +

    变更记录

    v1.0 添加

    功能描述

    装载 Hook 子类。

    你可以填入 hooker 在 Hooker 中继续装载 Hooker。

    searchClass - method

    inline fun searchClass(name: String, async: Boolean, initiate: ClassConditions): DexClassFinder.Result
    +

    变更记录

    v1.1.0 新增

    功能描述

    通过 appClassLoader 按指定条件查找并得到当前 Hook APP Dex 中的 Class

    特别注意

    此方法在 Class 数量过多及查找条件复杂时会非常耗时。

    建议启用 async 或设置 name 参数,name 参数将在 Hook APP (宿主) 不同版本中自动进行本地缓存以提升效率。

    此功能尚在试验阶段,性能与稳定性可能仍然存在问题,使用过程遇到问题请向我们报告并帮助我们改进。

    String+VariousClass.clazz - i-ext-field

    变更记录

    v1.0 添加

    v1.1.0 作废

    请转移到 toClass(...) 方法

    String.hasClass - i-ext-field

    变更记录

    v1.0 添加

    v1.1.0 作废

    请转移到 hasClass(...) 方法

    String+VariousClass.toClass - i-ext-method

    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)
    +

    String+VariousClass.toClassOrNull - i-ext-method

    fun String.toClassOrNull(loader: ClassLoader?): Class<*>?
    +
    fun VariousClass.toClassOrNull(loader: ClassLoader?): Class<*>?
    +

    变更记录

    v1.1.0 新增

    功能描述

    通过字符串类名、VariousClass 转换为 loader 中的实体类。

    默认使用当前 appClassLoader 装载目标 Class

    找不到 Class 会返回 null,不会抛出异常。

    功能示例

    用法请参考 String+VariousClass.toClass 方法。

    String.hasClass - i-ext-method

    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.
    +}
    +

    findClass - method

    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 参数

    功能描述

    通过完整包名+名称查找需要被 Hook 的 Class

    注意

    使用此方法会得到一个 HookClass 仅用于 Hook,若想查找 Class 请使用 toClass 功能。

    功能示例

    你可以使用三种方式查找你需要 Hook 的目标 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 的完整包名+名称填入 VariousClassname 中并填入 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)
    +

    String+Class+VariousClass+HookClass.hook - i-ext-method

    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 修改

    将方法体进行 inline

    v1.1.0 修改

    移除了 isUseAppClassLoader 参数

    添加了 isForceUseAbsolute 参数到 Class.hook 方法

    功能描述

    这是一切 Hook 的入口创建方法,Hook 方法、构造方法。

    功能示例

    如你所见,Hook 方法体的创建可使用 4 种方式。

    通过字符串类名得到 HookClass 实例进行创建。

    示例如下

    "com.example.demo.DemoClass".hook {
    +    // Your code here.
    +}
    +
    +

    通过 findClass 得到 HookClass 实例进行创建。

    示例如下

    findClass(name = "com.example.demo.DemoClass").hook {
    +    // Your code here.
    +}
    +

    使用 stub 或直接拿到 Class 实例进行创建。

    默认情况下 API 会将 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.
    +}
    +

    HookResources.hook - i-ext-method

    inline fun HookResources.hook(initiate: YukiResourcesHookCreator.() -> Unit)
    +

    变更记录

    v1.0.80 新增

    功能描述

    Hook APP 的 Resources。

    特别注意

    请注意你需要确保当前 Hook Framework 支持且 InjectYukiHookWithXposed.isUsingResourcesHook 已启用。

    功能示例

    Resources Hook 为固定用法,获取 resources 对象,然后调用 hook 方法开始 Hook。

    示例如下

    resources().hook {
    +    // Your code here.
    +}
    +

    特别注意

    这是固定用法,为了防止发生问题,你不可手动实现任何 HookResources 实例执行 hook 调用。

    将 Resources 的 Hook 设置为这样是为了与 findClass(...).hook 做到统一,使得调用起来逻辑不会混乱。

    AppLifecycle - class

    inner class AppLifecycle internal constructor()
    +

    变更记录

    v1.0.88 新增

    功能描述

    当前 Hook APP 的生命周期实例处理类。

    attachBaseContext - method

    fun attachBaseContext(result: (baseContext: Context, hasCalledSuper: Boolean) -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    监听当前 Hook APP 装载 Application.attachBaseContext

    onCreate - method

    fun onCreate(initiate: Application.() -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    监听当前 Hook APP 装载 Application.onCreate

    onTerminate - method

    fun onTerminate(initiate: Application.() -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    监听当前 Hook APP 装载 Application.onTerminate

    onLowMemory - method

    fun onLowMemory(initiate: Application.() -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    监听当前 Hook APP 装载 Application.onLowMemory

    onTrimMemory - method

    fun onTrimMemory(result: (self: Application, level: Int) -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    监听当前 Hook APP 装载 Application.onTrimMemory

    onConfigurationChanged - method

    fun onConfigurationChanged(result: (self: Application, config: Configuration) -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    监听当前 Hook APP 装载 Application.onConfigurationChanged

    registerReceiver - method

    fun registerReceiver(vararg action: String, result: (context: Context, intent: Intent) -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    注册系统广播监听。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html new file mode 100644 index 00000000..42257390 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html @@ -0,0 +1,33 @@ + + + + + + + + + ComponentTypeFactory - kt | Yuki Hook API + + + + +

    ComponentTypeFactory - kt

    变更记录

    v1.0 添加

    功能描述

    这是一个预置 Hook 类型的常量类,主要为 Android 相关组件的 Class 内容,跟随版本更新会逐一进行增加。

    详情可 点击这里在新窗口中打开 进行查看。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html new file mode 100644 index 00000000..c0a22ae1 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html @@ -0,0 +1,33 @@ + + + + + + + + + GraphicsTypeFactory - kt | Yuki Hook API + + + + +

    GraphicsTypeFactory - kt

    变更记录

    v1.0 添加

    功能描述

    这是一个预置 Hook 类型的常量类,主要为 Android 相关 GraphicsClass 内容,跟随版本更新会逐一进行增加。

    详情可 点击这里在新窗口中打开 进行查看。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html new file mode 100644 index 00000000..79bc907a --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html @@ -0,0 +1,33 @@ + + + + + + + + + ViewTypeFactory - kt | Yuki Hook API + + + + +

    ViewTypeFactory - kt

    变更记录

    v1.0 添加

    功能描述

    这是一个预置 Hook 类型的常量类,主要为 Android 相关 WidgetClass 内容,跟随版本更新会逐一进行增加。

    详情可 点击这里在新窗口中打开 进行查看。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html new file mode 100644 index 00000000..63e03619 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html @@ -0,0 +1,34 @@ + + + + + + + + + DefinedTypeFactory - kt | Yuki Hook API + + + + +

    DefinedTypeFactory - kt

    变更记录

    v1.1.0 新增

    功能描述

    这是一个内部类型的定义常量类,主要用于反射 API 相关用法的延伸。

    VagueType - field

    val VagueType: Class<*>
    +

    变更记录

    v1.1.0 新增

    功能描述

    得到模糊类型。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html new file mode 100644 index 00000000..1b20205b --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html @@ -0,0 +1,33 @@ + + + + + + + + + VariableTypeFactory - kt | Yuki Hook API + + + + +

    VariableTypeFactory - kt

    变更记录

    v1.0 添加

    功能描述

    这是一个预置 Hook 类型的常量类,主要为 Java 相关基本变量类型的 Class 内容,跟随版本更新会逐一进行增加。

    详情可 点击这里在新窗口中打开 进行查看。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html new file mode 100644 index 00000000..50feb9a2 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html @@ -0,0 +1,49 @@ + + + + + + + + + ModuleApplication - class | Yuki Hook API + + + + +

    ModuleApplication - class

    open class ModuleApplication: Application()
    +

    变更记录

    v1.0.77 新增

    功能描述

    这是对使用 YukiHookAPI Xposed 模块实现中的一个扩展功能。

    在你的 Xposed 模块的 Application 中继承此类。

    或在 AndroidManifest.xmlapplication 标签中指定此类。

    目前可实现功能如下

    • 全局共享模块中静态的 appContext

    • 在模块与宿主中装载 YukiHookAPI.Config 以确保 YukiHookAPI.Configs.debugTag 不需要重复定义

    • 在模块与宿主中使用 YukiHookDataChannel 进行通讯

    • 在模块中使用系统隐藏 API,核心技术引用了开源项目 FreeReflection在新窗口中打开

    • 在模块中使用 YukiHookAPI.Status.isTaiChiModuleActive 判断太极、无极激活状态

    功能示例

    将此类继承到你的自定义 Application 上。

    示例如下

    package com.demo
    +
    +class MyApplication: ModuleApplication() {
    +
    +    override fun onCreate() {
    +        super.onCreate()
    +    }
    +}
    +

    AndroidManifest.xmlapplication 标签中指定自定义的 Application

    示例如下

    <application
    +    android:name="com.demo.MyApplication"
    +    ...>
    +

    如果你不需要自定义 Application 可以直接将 ModuleApplication 设置到 AndroidManifest.xmlapplication 标签中。

    示例如下

    <application
    +    android:name="com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication"
    +    ...>
    +

    appContext - field

    val appContext: ModuleApplication
    +

    变更记录

    v1.0.77 新增

    功能描述

    获取全局静态 Application 实例。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html new file mode 100644 index 00000000..9cd7fb4c --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html @@ -0,0 +1,35 @@ + + + + + + + + + YukiModuleResources - class | Yuki Hook API + + + + +

    YukiModuleResources - class

    class YukiModuleResources private constructor(private val baseInstance: XModuleResources) : Resources
    +

    变更记录

    v1.0.80 新增

    功能描述

    对接 XModuleResources 的中间层实例。

    fwd - method

    fun fwd(resId: Int): YukiResForwarder
    +

    变更记录

    v1.0.80 新增

    功能描述

    对接 XModuleResources.fwd 方法。

    创建 YukiResForwarderXResForwarder 实例。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html new file mode 100644 index 00000000..bf249462 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html @@ -0,0 +1,36 @@ + + + + + + + + + YukiResForwarder - class | Yuki Hook API + + + + +

    YukiResForwarder - class

    class YukiResForwarder private constructor(private val baseInstance: XResForwarder)
    +

    变更记录

    v1.0.80 新增

    功能描述

    对接 XResForwarder 的中间层实例。

    instance - field

    变更记录

    v1.0.80 新增

    v1.1.0 作废

    不再对外公开 instance 参数

    id - field

    val id: Int
    +

    变更记录

    v1.0.80 新增

    功能描述

    获得当前 APP 的 Resources Id。

    resources - field

    val resources: Resources
    +

    变更记录

    v1.0.80 新增

    功能描述

    获得当前 APP 的 Resources。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html new file mode 100644 index 00000000..b430adb9 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html @@ -0,0 +1,39 @@ + + + + + + + + + YukiResources - class | Yuki Hook API + + + + +

    YukiResources - class

    class YukiResources private constructor(private val baseInstance: XResources) : Resources
    +

    变更记录

    v1.0.80 新增

    功能描述

    对接 XResources 的中间层实例。

    LayoutInflatedParam - class

    class LayoutInflatedParam(internal val baseParam: XC_LayoutInflated.LayoutInflatedParam)
    +

    变更记录

    v1.0.80 新增

    功能描述

    装载 Hook APP 的目标布局 Resources 实现类。

    variantName - field

    val variantName: String
    +

    变更记录

    v1.0.80 新增

    功能描述

    获取当前被 Hook 的布局装载目录名称。

    例如:layoutlayout-landlayout-sw600dp

    currentView - field

    val currentView: View
    +

    变更记录

    v1.0.80 新增

    功能描述

    获取当前被 Hook 的布局实例。

    findViewByIdentifier - method

    inline fun <reified T : View> View.findViewByIdentifier(name: String): T?
    +
    inline fun <reified T : View> findViewByIdentifier(name: String): T?
    +

    变更记录

    v1.0.80 新增

    功能描述

    使用 Identifier 查找 Hook APP 指定 Id 的 View

    扩展方法可以使用 Identifier 查找 Hook APP 当前装载布局中指定 Id 的 View

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html new file mode 100644 index 00000000..bebf9639 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html @@ -0,0 +1,38 @@ + + + + + + + + + YukiXposedEvent - object | Yuki Hook API + + + + +

    YukiXposedEvent - object

    object YukiXposedEvent
    +

    变更记录

    v1.0.80 添加

    功能描述

    实现对原生 Xposed API 的装载事件监听。

    events - method

    inline fun events(initiate: YukiXposedEvent.() -> Unit)
    +

    变更记录

    v1.0.80 新增

    功能描述

    YukiXposedEvent 创建一个方法体。

    onInitZygote - method

    fun onInitZygote(result: (StartupParam) -> Unit)
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 initZygote 事件监听。

    onHandleLoadPackage - method

    fun onHandleLoadPackage(result: (LoadPackageParam) -> Unit)
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 handleLoadPackage 事件监听。

    onHandleInitPackageResources - method

    fun onHandleInitPackageResources(result: (InitPackageResourcesParam) -> Unit)
    +

    变更记录

    v1.0.80 新增

    功能描述

    设置 handleInitPackageResources 事件监听。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html new file mode 100644 index 00000000..5a41ce26 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html @@ -0,0 +1,44 @@ + + + + + + + + + YukiHookDataChannel - class | Yuki Hook API + + + + +

    YukiHookDataChannel - class

    class YukiHookDataChannel private constructor()
    +

    变更记录

    v1.0.88 新增

    功能描述

    实现 Xposed 模块的数据通讯桥。

    通过模块与宿主相互注册 BroadcastReceiver 来实现数据的交互。

    模块需要将 Application 继承于 ModuleApplication 来实现此功能。

    特别注意

    模块与宿主需要保持存活状态,否则无法建立通讯。

    NameSpace - class

    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 命名空间。

    with - method

    inline fun with(initiate: NameSpace.() -> Unit): NameSpace
    +

    变更记录

    v1.0.88 新增

    功能描述

    创建一个调用空间。

    put - method

    fun <T> put(key: String, value: T)
    +
    fun <T> put(data: ChannelData<T>, value: T?)
    +
    fun put(vararg data: ChannelData<*>)
    +

    变更记录

    v1.0.88 新增

    功能描述

    发送键值数据。

    put - method

    fun put(key: String)
    +

    变更记录

    v1.0.88 新增

    功能描述

    仅发送键值监听,使用默认值 VALUE_WAIT_FOR_LISTENER 发送键值数据。

    wait - method

    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

    功能描述

    获取键值数据。

    wait - method

    fun wait(key: String, callback: () -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    仅获取监听结果,不获取键值数据。

    特别注意

    仅限使用 VALUE_WAIT_FOR_LISTENER 发送的监听才能被接收。

    checkingVersionEquals - method

    fun checkingVersionEquals(result: (Boolean) -> Unit)
    +

    变更记录

    v1.0.88 新增

    功能描述

    获取模块与宿主的版本是否匹配。

    通过此方法可原生判断 Xposed 模块更新后宿主并未重新装载造成两者不匹配的情况。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html new file mode 100644 index 00000000..39bf403f --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html @@ -0,0 +1,55 @@ + + + + + + + + + ChannelData - class | Yuki Hook API + + + + +

    ChannelData - class

    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.
    +}
    +
    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html new file mode 100644 index 00000000..3bc4b5ae --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html @@ -0,0 +1,34 @@ + + + + + + + + + ModuleAppActivity - class | Yuki Hook API + + + + +

    ModuleAppActivity - class

    open class ModuleAppActivity : Activity()
    +

    变更记录

    v1.1.0 新增

    功能描述

    代理 Activity

    继承于此类的 Activity 可以同时在宿主与模块中启动。

    在 (Xposed) 宿主环境需要在宿主启动时调用 Context.registerModuleAppActivities 进行注册。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html new file mode 100644 index 00000000..a287f5f5 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html @@ -0,0 +1,35 @@ + + + + + + + + + ModuleAppCompatActivity - class | Yuki Hook API + + + + +

    ModuleAppCompatActivity - class

    open class ModuleAppCompatActivity : AppCompatActivity()
    +

    变更记录

    v1.1.0 新增

    功能描述

    代理 AppCompatActivity

    继承于此类的 Activity 可以同时在宿主与模块中启动。

    在 (Xposed) 宿主环境需要在宿主启动时调用 Context.registerModuleAppActivities 进行注册。

    在 (Xposed) 宿主环境需要重写 moduleTheme 设置 AppCompat 主题,否则会无法启动。

    moduleTheme - field

    open val moduleTheme: Int
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置当前代理的 Activity 主题。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html new file mode 100644 index 00000000..9b862dae --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html @@ -0,0 +1,35 @@ + + + + + + + + + ModuleContextThemeWrapper - class | Yuki Hook API + + + + +

    ModuleContextThemeWrapper - class

    class ModuleContextThemeWrapper private constructor(baseContext: Context, theme: Int, configuration: Configuration?) : ContextThemeWrapper
    +

    变更记录

    v1.1.0 新增

    功能描述

    代理 ContextThemeWrapper

    通过包装,你可以轻松在 (Xposed) 宿主环境使用来自模块的主题资源。

    applyConfiguration - method

    fun applyConfiguration(initiate: Configuration.() -> Unit): ModuleContextThemeWrapper
    +

    变更记录

    v1.1.0 新增

    功能描述

    设置当前 ModuleContextThemeWrapperConfiguration

    设置后会自动调用 Resources.updateConfiguration

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html new file mode 100644 index 00000000..b36504cc --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html @@ -0,0 +1,62 @@ + + + + + + + + + YukiHookModulePrefs - class | Yuki Hook API + + + + +

    YukiHookModulePrefs - class

    class YukiHookModulePrefs private constructor(private var context: Context?)
    +

    变更记录

    v1.0 添加

    功能描述

    实现 Xposed 模块的数据存取,对接 SharedPreferencesXSharedPreferences

    在不同环境智能选择存取使用的对象。

    特别注意

    此功能为实验性功能,仅在 LSPosed 环境测试通过,EdXposed 理论也可以使用但不再推荐。

    使用 LSPosed 环境请在 AndroidManifests.xml 中将 xposedminversion 最低设置为 93

    详见 New XSharedPreferences在新窗口中打开

    若你在按照规定配置后依然无法使用或出现文件权限错误问题,可以参考 isEnableHookSharedPreferences

    未使用 LSPosed 环境请将你的模块 API 降至 26 以下,YukiHookAPI 将会尝试使用 makeWorldReadable 但仍有可能不成功。

    太极请参阅 文件权限/配置/XSharedPreference在新窗口中打开

    特别注意

    当你在 Xposed 模块中存取数据的时候 context 必须不能是空的。

    若你正在使用 PreferenceFragmentCompat,请迁移到 ModulePreferenceFragment 以适配上述功能特性。

    可选配置

    若你不想将你的模块的 xposedminversion 最低设置为 93,你可以在 AndroidManifest.xml 中添加 xposedsharedprefs 来实现支持。

    详见 New XSharedPreferences在新窗口中打开

    示例如下

    <meta-data
    +    android:name="xposedsharedprefs"
    +    android:value="true"/>
    +

    isXSharePrefsReadable - field

    val isXSharePrefsReadable: Boolean
    +

    变更记录

    v1.0.90 新增

    功能描述

    获取 XSharedPreferences 是否可读。

    特别注意

    只能在 (Xposed) 宿主环境中使用,模块环境中始终返回 false。

    isRunInNewXShareMode - field

    val isRunInNewXShareMode: Boolean
    +

    变更记录

    v1.0.78 新增

    功能描述

    获取 YukiHookModulePrefs 是否正处于 EdXposed/LSPosed 的最高权限运行。

    前提条件为当前 Xposed 模块已被激活。

    特别注意

    只能在模块环境中使用,(Xposed) 宿主环境中始终返回 false。

    name - method

    fun name(name: String): YukiHookModulePrefs
    +

    变更记录

    v1.0 添加

    功能描述

    自定义 Sp 存储名称。

    功能示例

    Activity 中的使用方法。

    示例如下

    modulePrefs("custom_name").getString("custom_key")
    +

    在 (Xposed) 宿主环境 PackageParam 中的使用方法。

    示例如下

    prefs("custom_name").getString("custom_key")
    +

    direct - method

    fun direct(): YukiHookModulePrefs
    +

    变更记录

    v1.0.5 新增

    功能描述

    忽略缓存直接读取键值。

    无论是否开启 YukiHookAPI.Configs.isEnableModulePrefsCache

    仅在 XSharedPreferences 下生效。

    getString - method

    fun getString(key: String, value: String): String
    +

    变更记录

    v1.0 添加

    功能描述

    获取 String 键值。

    getStringSet - method

    fun getStringSet(key: String, value: Set<String>): Set<String>
    +

    变更记录

    v1.0.77 新增

    功能描述

    获取 Set<String> 键值。

    getBoolean - method

    fun getBoolean(key: String, value: Boolean): Boolean
    +

    变更记录

    v1.0 添加

    功能描述

    获取 Boolean 键值。

    getInt - method

    fun getInt(key: String, value: Int): Int
    +

    变更记录

    v1.0 添加

    功能描述

    获取 Int 键值。

    getLong - method

    fun getLong(key: String, value: Long): Long
    +

    变更记录

    v1.0 添加

    功能描述

    获取 Long 键值。

    getFloat - method

    fun getFloat(key: String, value: Float): Float
    +

    变更记录

    v1.0 添加

    功能描述

    获取 Float 键值。

    all - method

    fun all(): HashMap<String, Any?>
    +

    变更记录

    v1.0.77 新增

    功能描述

    获取全部存储的键值数据。

    智能识别对应环境读取键值数据。

    特别注意

    每次调用都会获取实时的数据,不受缓存控制,请勿在高并发场景中使用。

    remove - method

    fun remove(key: String)
    +

    变更记录

    v1.0 添加

    功能描述

    移除全部包含 key 的存储数据。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    remove - method

    inline fun <reified T> remove(prefs: PrefsData<T>)
    +

    变更记录

    v1.0.67 新增

    功能描述

    移除 PrefsData.key 的存储数据。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    clear - method

    fun clear()
    +

    变更记录

    v1.0.77 新增

    功能描述

    移除全部存储数据。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    putString - method

    fun putString(key: String, value: String)
    +

    变更记录

    v1.0 添加

    功能描述

    存储 String 键值。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    putStringSet - method

    fun putStringSet(key: String, value: Set<String>)
    +

    变更记录

    v1.0.77 新增

    功能描述

    存储 Set<String> 键值。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    putBoolean - method

    fun putBoolean(key: String, value: Boolean)
    +

    变更记录

    v1.0 添加

    功能描述

    存储 Boolean 键值。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    putInt - method

    fun putInt(key: String, value: Int)
    +

    变更记录

    v1.0 添加

    功能描述

    存储 Int 键值。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    putLong - method

    fun putLong(key: String, value: Long)
    +

    变更记录

    v1.0 添加

    功能描述

    存储 Long 键值。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    putFloat - method

    fun putFloat(key: String, value: Float)
    +

    变更记录

    v1.0 添加

    功能描述

    存储 Float 键值。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    get - method

    inline fun <reified T> get(prefs: PrefsData<T>, value: T): T
    +

    变更记录

    v1.0.67 新增

    功能描述

    智能获取指定类型的键值。

    put - method

    inline fun <reified T> put(prefs: PrefsData<T>, value: T)
    +

    变更记录

    v1.0.67 新增

    功能描述

    智能存储指定类型的键值。

    注意

    在 (Xposed) 宿主环境下只读,无法使用。

    clearCache - method

    fun clearCache()
    +

    变更记录

    v1.0.5 新增

    功能描述

    清除 XSharedPreferences 中缓存的键值数据。

    无论是否开启 YukiHookAPI.Configs.isEnableModulePrefsCache

    调用此方法将清除当前存储的全部键值缓存。

    下次将从 XSharedPreferences 重新读取。

    在 (Xposed) 宿主环境中使用。

    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html new file mode 100644 index 00000000..52ca13be --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html @@ -0,0 +1,50 @@ + + + + + + + + + PrefsData - class | Yuki Hook API + + + + +

    PrefsData - class

    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)
    +
    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html new file mode 100644 index 00000000..c4417e27 --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html @@ -0,0 +1,54 @@ + + + + + + + + + ModulePreferenceFragment - class | Yuki Hook API + + + + +

    ModulePreferenceFragment - class

    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 保持一致。

    onCreatePreferencesInModuleApp - method

    abstract fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?)
    +

    变更记录

    v1.0.78 新增

    功能描述

    对接原始方法 onCreatePreferences

    onSharedPreferenceChanged - method

    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?)
    +

    变更记录

    v1.0.78 新增

    功能描述

    实现了 SharedPreferences.OnSharedPreferenceChangeListener 的原生监听功能。

    功能示例

    注意

    在使用 onSharedPreferenceChanged 时请保留 super 方法。

    示例如下

    class SettingsFragment : ModulePreferenceFragment() {
    +
    +    override fun onCreatePreferencesInModuleApp(savedInstanceState: Bundle?, rootKey: String?) {
    +        // ...
    +    }
    +
    +    override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
    +        super.onSharedPreferenceChanged(sharedPreferences, key)
    +        // Your code here.
    +    }
    +}
    +
    + + + diff --git a/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html new file mode 100644 index 00000000..32b23ccf --- /dev/null +++ b/docs/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html @@ -0,0 +1,37 @@ + + + + + + + + + IYukiHookXposedInit - interface | Yuki Hook API + + + + +

    IYukiHookXposedInit - interface

    interface IYukiHookXposedInit
    +

    变更记录

    v1.0 添加

    v1.0.80 修改 作废

    作废了 YukiHookXposedInitProxy 名称但保留接口

    转移到 IYukiHookXposedInit 新名称

    功能描述

    YukiHookAPI 的 Xposed 装载 API 调用接口。

    onInit - method

    fun onInit()
    +

    变更记录

    v1.0.5 新增

    功能描述

    配置 YukiHookAPI.Configs 的初始化方法。

    特别注意

    在这里只能进行初始化配置,不能进行 Hook 操作。

    此方法可选,你也可以选择不对 YukiHookAPI.Configs 进行配置。

    onHook - method

    fun onHook()
    +

    变更记录

    v1.0 添加

    功能描述

    Xposed API 的模块装载调用入口方法。

    onXposedEvent - method

    fun onXposedEvent()
    +

    变更记录

    v1.0.80 新增

    功能描述

    监听 Xposed 原生装载事件。

    若你的 Hook 事件中存在需要兼容的原生 Xposed 功能,可在这里实现。

    请在这里使用 YukiXposedEvent 创建回调事件监听。

    可监听的事件如下:

    YukiXposedEvent.onInitZygote

    YukiXposedEvent.onHandleLoadPackage

    YukiXposedEvent.onHandleInitPackageResources

    特别注意

    此接口仅供监听和实现原生 Xposed API 的功能,请不要在这里操作 YukiHookAPI

    YukiHookXposedInitProxy - interface

    变更记录

    v1.0 添加

    v1.0.80 作废

    请转移到 IYukiHookXposedInit

    + + + diff --git a/docs/zh-cn/api/special-features/host-inject.html b/docs/zh-cn/api/special-features/host-inject.html new file mode 100644 index 00000000..59cd8c2a --- /dev/null +++ b/docs/zh-cn/api/special-features/host-inject.html @@ -0,0 +1,150 @@ + + + + + + + + + 宿主资源注入扩展 | Yuki Hook API + + + + +

    宿主资源注入扩展

    这是一个将模块资源、Activity 组件以及 Context 主题注入到宿主的扩展功能。

    在使用以下功能之前,为防止资源 ID 互相冲突,你需要在当前 Xposed 模块项目的 build.gradle 中修改资源 ID。

    • Kotlin Gradle DSL
    android {
    +    androidResources.additionalParameters("--allow-reserved-package-id", "--package-id", "0x64")
    +}
    +
    • Groovy
    android {
    +    aaptOptions.additionalParameters '--allow-reserved-package-id', '--package-id', '0x64'
    +}
    +

    注意

    提供的示例资源 ID 值仅供参考,不可使用 0x7f,默认为 0x64,为了防止当前宿主存在多个 Xposed 模块,建议自定义你自己的资源 ID。

    注入模块资源 (Resources)

    在 Hook 宿主之后,我们可以直接在 Hooker 中得到的 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)
    +    }
    +}
    +

    小提示

    更多功能请参考 Context+Resources.injectModuleAppResources 方法。

    注册模块 Activity

    在 Android 系统中所有应用的 Activity 启动时,都需要在 AndroidManifest.xml 中进行注册,在 Hook 过程中,如果我们想通过宿主来直接启动模块中未注册的 Activity 要怎么做呢?

    在 Hook 宿主之后,我们可以直接在 Hooker 中得到的 Context 注册当前模块的 Activity 代理。

    示例如下

    injectMember {
    +    method {
    +        name = "onCreate"
    +        param(BundleClass)
    +    }
    +    afterHook {
    +        instance<Activity>().registerModuleAppActivities()
    +    }
    +}
    +

    你还可以直接在 AppLifecycle 中注册当前模块的 Activity 代理。

    示例如下

    onAppLifecycle {
    +    onCreate {
    +        registerModuleAppActivities()
    +    }
    +}
    +

    如果没有填写 proxy 参数,API 将会根据当前 Context 自动获取当前宿主的启动入口 Activity 进行代理。

    通常情况下,它是有效的,但是以上情况在一些 APP 中会失效,例如一些 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 继承于 ModuleAppActivityModuleAppCompatActivity

    这些 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)
    +    }
    +}
    +

    以上步骤全部完成后,你就可以在 (Xposed) 宿主环境任意存在 Context 的地方愉快地调用 startActivity 了。

    示例如下

    val context: Context = ... // 假设这就是你的 Context
    +context.startActivity(context, HostTestActivity::class.java)
    +

    小提示

    更多功能请参考 Context.registerModuleAppActivities 方法。

    创建 ContextThemeWrapper 代理

    有时候,我们需要使用 MaterialAlertDialogBuilder 来美化自己在宿主中的对话框,但是拿不到 AppCompat 主题就无法创建。

    • 会得到如下异常
    The style on this component requires your app theme to be Theme.AppCompat (or a descendant).
    +

    这时,我们想在宿主被 Hook 的当前 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 创建对话框了。

    可能存在的问题

    由于一些 APP 自身使用的 androidx 依赖库或自定义主题可能会对当前 MaterialAlertDialog 实际样式造成干扰,例如对话框的按钮样式,这种情况你可以参考 模块 Demo这里的示例代码在新窗口中打开 来修复这个问题。

    某些 APP 在创建时可能会发生 ClassCastException 异常,请手动指定新的 Configuration 实例来进行修复。

    小提示

    更多功能请参考 Context.applyModuleTheme 方法。

    + + + diff --git a/docs/zh-cn/api/special-features/host-lifecycle.html b/docs/zh-cn/api/special-features/host-lifecycle.html new file mode 100644 index 00000000..c9ec6b23 --- /dev/null +++ b/docs/zh-cn/api/special-features/host-lifecycle.html @@ -0,0 +1,78 @@ + + + + + + + + + 宿主生命周期扩展 | Yuki Hook API + + + + +

    宿主生命周期扩展

    这是一个自动 Hook 宿主 APP 生命周期的扩展功能。

    监听生命周期

    通过自动化 Hook 宿主 APP 的生命周期方法,来实现监听功能。

    我们需要监听宿主 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 ->
    +            // ...
    +        }
    +    }
    +}
    +

    小提示

    更多功能请参考 AppLifecycle

    注册系统广播

    通过 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 ->
    +            // ...
    +        }
    +    }
    +}
    +

    小提示

    更多功能请参考 AppLifecycle

    + + + diff --git a/docs/zh-cn/api/special-features/logger.html b/docs/zh-cn/api/special-features/logger.html new file mode 100644 index 00000000..e45960bc --- /dev/null +++ b/docs/zh-cn/api/special-features/logger.html @@ -0,0 +1,63 @@ + + + + + + + + + 调试日志 | Yuki Hook API + + + + +

    调试日志

    日志是调试过程最重要的一环,YukiHookAPI 为开发者封装了一套稳定高效的调试日志功能。

    普通日志

    你可以调用 loggerDloggerIloggerW 来向控制台打印普通日志。

    使用方法如下所示。

    示例如下

    loggerD(msg = "This is a log")
    +

    此时,YukiHookAPI 会调用 android.util.LogXposedBridge.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)
    +

    若你想智能区分 (Xposed) 宿主环境与模块环境,可以写为如下形式。

    示例如下

    loggerD(tag = "YukiHookAPI", msg = "This is a log", type = LoggerType.SCOPE)
    +

    这样 API 就会在不同环境智能选择指定的方法类型去打印这条日志。

    小提示

    更多功能请参考 loggerDloggerIloggerW 方法。

    错误日志

    你可以调用 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 来指定当前打印日志所用到的方法类型。

    小提示

    更多功能请参考 loggerE 方法。

    保存日志与自定义元素

    你可以使用 YukiHookLogger.saveToFile 方法直接保存当前已打印的全部日志到文件。

    示例如下

    // 请注意保存的文件路径必须拥有读写权限,否则会抛出异常
    +YukiHookLogger.saveToFile("/sdcard/Documents/debug_log.log")
    +

    你还可以使用 YukiHookLogger.contents 获取当前已打印的全部日志文件内容。

    示例如下

    // 获取当前已打印的全部日志文件内容
    +val fileContent = YukiHookLogger.contents
    +

    以上功能需要启用 YukiHookLogger.Configs.isRecord

    你还可以使用 YukiHookLogger.Configs.elements 自定义调试日志对外显示的元素。

    此功能需要在 Hook 入口类的 onInit 中对 YukiHookAPI.Configs 进行配置。

    示例如下

    override fun onInit() = configs {
    +    debugLog {
    +        // ...
    +        elements(TAG, PRIORITY, PACKAGE_NAME, USER_ID)
    +    }
    +    // ...
    +}
    +

    小提示

    更多功能请参考 YukiHookLogger.contentsYukiHookLogger.saveToFile 方法以及 YukiHookLogger.Configs

    + + + diff --git a/docs/zh-cn/api/special-features/reflection.html b/docs/zh-cn/api/special-features/reflection.html new file mode 100644 index 00000000..2514cc31 --- /dev/null +++ b/docs/zh-cn/api/special-features/reflection.html @@ -0,0 +1,844 @@ + + + + + + + + + 字节码与反射扩展 | Yuki Hook API + + + + +

    字节码与反射扩展

    YukiHookAPI 为开发者封装了一套接近零反射写法的反射 API,它几乎可以完全取代原生 Java 的反射 API 相关用法。

    Class 扩展

    这里是 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)
    +

    小提示

    更多功能请参考 String.hasClassPackageParam → String.hasClass 方法。

    模糊查找 Beta

    在 R8 等工具混淆后的宿主 Dex 中的 Class 名称将会难以分辨,且不确定其正确位置,不能直接通过 对象转换 来得到。

    此时就有了 DexClassFinder,它的作用是通过需要查找的 Class 中的字节码特征来确定这个 Class 的实例。

    注意

    目前 DexClassFinder 的功能尚在试验阶段,由于仅通过 Java 层实现查找功能,在宿主 Class 过多时性能可能不能达到最佳水平,如果发生查找不到、定位有误的问题欢迎向我们反馈。

    由于是反射层面的 API,目前它只能通过类与成员的特征来定位指定的 Class,不能通过指定字节码中的字符串和方法内容特征来进行定位。

    查找 Class 的速度取决于当前设备的性能,目前主流的移动端处理器在 10~15w 数量的 Class 中条件不算复杂的情况下大概在 3~10s 区间,条件稍微复杂的情况下最快速度能达到 25s 以内,匹配到的同类型 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
    +

    小提示

    上述用法中对于 FieldMethodConstructor 的条件用法与 Member 扩展 中的相关用法是一致的,仅有小部分区别。

    更多功能请参考 MemberRulesFieldRulesMethodRulesConstructorRules

    异步查找

    默认情况下 DexClassFinder 会使用同步方式查找 Class,会阻塞当前线程直到找到或找不到发生异常为止,若查找消耗的时间过长,可能会导致宿主发生 ANR 问题。

    针对上述问题,我们可以启用异步,只需要加入参数 async = true,这将不需要你再次启动一个线程,API 已帮你处理好相关问题。

    注意

    对于异步情况下你需要使用 wait 方法来得到结果,get 方法将不再起作用。

    示例如下

    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,那么你只需要使用 allwaitAll 方法来得到结果。

    // 同步查找,使用 all 得到条件全部查找到的结果
    +searchClass {
    +    // ...
    +}.all().forEach { clazz ->
    +    // 得到每个结果
    +}
    +// 同步查找,使用 all { ... } 遍历每个结果
    +searchClass {
    +    // ...
    +}.all { clazz ->
    +    // 得到每个结果
    +}
    +// 异步查找,使用 waitAll 得到条件全部查找到的结果
    +searchClass(async = true) {
    +    // ...
    +}.waitAll { classes ->
    +    classes.forEach {
    +        // 得到每个结果
    +    }
    +}
    +

    小提示

    更多功能请参考 ClassLoader.searchClassPackageParam.searchClass 方法。

    Member 扩展

    这里是 Class 字节码成员变量 FieldMethodConstructor 相关的扩展功能。

    小提示

    MemberFieldMethodConstructor 的接口描述对象,它在 Java 反射中为 Class 中字节码成员的总称。

    假设有一个这样的 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")
    +

    小提示

    更多功能请参考 MethodFinder

    同样地,我们需要得到 isTaskRunning 变量也可以写作如下形式。

    示例如下

    // 假设这就是这个 Class 的实例
    +val instance = Test()
    +// 使用 YukiHookAPI 调用并执行
    +Test::class.java.field {
    +    name = "isTaskRunning"
    +    type = BooleanType
    +}.get(instance).any() // any 为 Field 的任意类型实例化对象
    +

    小提示

    更多功能请参考 FieldFinder

    也许你还想得到当前 Class 的构造方法,同样可以实现。

    示例如下

    Test::class.java.constructor {
    +    param(BooleanType)
    +}.get().call(true) // 可创建一个新的实例
    +

    若想得到的是 Class 的无参构造方法,可写作如下形式。

    示例如下

    Test::class.java.constructor().get().call() // 可创建一个新的实例
    +

    小提示

    更多功能请参考 ConstructorFinder

    可选的查找条件

    假设我们要得到 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() // 得到方法的结果
    +

    是的,对于确切不会变化的方法,你可以精简查找条件。

    在只使用 getwait 方法得到结果时 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,现在我们想得到 BaseTestdoBaseTask 方法,在不知道父类名称的情况下,要怎么做呢?

    参照上面的查找条件,我们只需要在查找条件中加入一个 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)为止。

    特别注意

    当前查找的 Method 除非指定 superClass 条件,否则只能查找到当前 ClassMethod,这是 Java 反射 API 的默认行为。

    模糊查找

    如果我们想查找一个方法名称,但是又不确定它在每个版本中是否发生变化,此时我们就可以使用模糊查找功能。

    假设我们要得到 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")
    +

    小提示

    使用 name { ... } 创建一个条件方法体,其中的变量 it 即当前名称的字符串,此时你就可以在 NameRules 的扩展方法中自由使用其中的功能。

    方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。

    更多功能请参考 NameRules

    多重查找

    有些时候,我们可能需要查找一个 Class 中具有相同特征的一组方法、构造方法、变量,此时,我们就可以利用相对条件匹配来完成。

    在查找条件结果的基础上,我们只需要把 get 换为 all 即可得到匹配条件的全部字节码。

    假设这次我们要得到 Class 中方法参数个数范围在 1..3 的全部方法,可以使用如下实现。

    示例如下

    // 假设这就是这个 Class 的实例
    +val instance = Test()
    +// 使用 YukiHookAPI 调用并执行
    +Test::class.java.method {
    +    paramCount(1..3)
    +}.all(instance).forEach { instance ->
    +    // 调用执行每个方法
    +    instance.call(...)
    +}
    +

    上述示例可完美匹配到如下 3 个方法。

    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(...)
    +}
    +

    上述示例可完美匹配到如下 6 个方法。

    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(...)
    +}
    +

    上述示例可完美匹配到如下 2 个方法。

    private void b()

    private void b(String a)

    小提示

    使用 paramCount { ... } 创建一个条件方法体,其中的变量 it 即当前参数个数的整数,此时你就可以在 CountRules 的扩展方法中自由使用其中的功能。

    方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。

    更多功能请参考 CountRules

    静态字节码

    有些方法和变量在 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()
    +

    小提示

    使用 modifiers { ... } 创建一个条件方法体,此时你就可以在 ModifierRules 中自由使用其中的功能。

    方法体末尾条件需要返回一个 Boolean,即最终的条件判断结果。

    更多功能请参考 ModifierRules

    混淆的字节码

    你可能已经注意到了,这里给出的示例 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 的最后一个方法
    +

    注意

    请尽量避免使用 order 来筛选字节码的下标,它们可能是不确定的,除非你确定它在这个 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")
    +}
    +

    注意

    上述 current 方法相当于帮你调用了 CurrentClass 中的 field { ... }.any()?.current() 方法。

    若不存在 CurrentClass 调用域,你需要使用 field { ... }.get(instance).current() 来进行调用。

    问题又来了,我想使用反射的方式创建如下的实例并调用其中的方法,该怎么做呢?

    示例如下

    Test(true).doTask("task_name")
    +

    通常情况下,我们可以使用标准的反射 API 来调用。

    示例如下

    "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 方法返回当前实例的类型,你可以在其中加入类型泛型声明,而无需使用 ascast 目标类型。

    这种情况多用于实例本身的构造方法是私有的,但是里面的方法是公有的,这样我们只需要对其构造方法进行反射创建即可。

    示例如下

    // 假设这个 Class 是能够直接被得到的
    +val test = Test::class.java.buildOf<Test>(true) { param(BooleanType) }
    +test.doTask("task_name")
    +

    小提示

    更多功能请参考 CurrentClass 以及 Class.buildOf 方法。

    原始调用

    若你正在使用反射调用的一个方法是被 Hook 过的,此时我们如何调用其原始方法呢?

    原生的 XposedBridge 为我们提供了一个 XposedBridge.invokeOriginalMethod 功能。

    现在,在 YukiHookAPI 中你可以使用如下方法便捷地实现这个功能。

    假设下面是我们要演示的 Class

    示例如下

    public class Test {
    +
    +    public static String getString() {
    +        return "Original";
    +    }
    +}
    +

    下面是 Hook 这个 ClassgetString 方法的方式。

    示例如下

    Test::class.java.hook {
    +    injectMember {
    +        method {
    +            name = "getString"
    +            emptyParam()
    +            returnType = StringType
    +        }
    +        replaceTo("Hooked")
    +    }
    +}
    +

    此时,我们再使用反射调用这个方法,则会得到 Hook 后的结果 "Hooked"

    示例如下

    // result 的结果会是 "Hooked"
    +val result = Test::class.java.method {
    +    name = "getString"
    +    emptyParam()
    +    returnType = StringType
    +}.get().string()
    +

    如果我们想得到这个方法未经 Hook 的原始方法及结果,只需要在结果中加入 original 即可。

    示例如下

    // result 的结果会是 "Original"
    +val result = Test::class.java.method {
    +    name = "getString"
    +    emptyParam()
    +    returnType = StringType
    +}.get().original().string()
    +

    小提示

    更多功能请参考 MethodFinder.Result.original 方法。

    再次查找

    假设有三个不同版本的 Class,它们都是这个宿主不同版本相同的 Class

    这里面同样都有一个方法 doTask,假设它们的功能是一样的。

    版本 A 示例如下

    public class Test {
    +
    +    public void doTask() {
    +        // ...
    +    }
    +}
    +

    版本 B 示例如下

    public class Test {
    +
    +    public void doTask(String taskName) {
    +        // ...
    +    }
    +}
    +

    版本 C 示例如下

    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 的方法查找结果不能再使用 get 的方式得到方法实例,应当使用 wait 方法。

    另外,你还可以在使用 多重查找 的情况下继续使用 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 {}
    +}
    +

    小提示

    在创建 Hook 的时候使用可参考 MethodFinder.Process.allConstructorFinder.Process.all 方法。

    更多功能请参考 MethodFinder.RemedyPlanConstructorFinder.RemedyPlanFieldFinder.RemedyPlan

    相对匹配

    假设宿主中不同版本中存在功能相同的 Class 但仅有 Class 的名称不一样。

    版本 A 示例如下

    public class ATest {
    +
    +    public static void doTask() {
    +        // ...
    +    }
    +}
    +

    版本 B 示例如下

    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()
    +

    小提示

    更多功能请参考 VariousClass

    若在创建 Hook 的时候使用,可以更加方便,还可以自动拦截找不到 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.
    +}
    +

    小提示

    更多功能请参考 PackageParam.findClass 方法。

    调用泛型

    在反射过程中,我们可能会遇到泛型问题,在泛型的反射处理上,YukiHookAPI 同样提供了一个可在任意地方使用的语法糖。

    例如我们有如下的泛型类。

    示例如下

    class TestGeneric<T, R> (t: T, r: R) {
    +
    +    fun foo() {
    +        // ...
    +    }
    +}
    +

    当我们想在当前 Class 中获得泛型 TRClass 实例,只需要如下实现。

    示例如下

    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>()
    +

    小提示

    更多功能请参考 CurrentClass.genericClass.generic 方法以及 GenericClass

    注意误区

    这里列举了使用时可能会遇到的误区部分,可供参考。

    限制性查找条件

    特别注意

    在查找条件中,除了 order 你只能使用一次 index 功能。

    示例如下

    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() 方法。

    兼容性说明

    在过往历史版本的 API 中是允许匹配不写默认匹配无参方法的做法的,但是最新版本更正了这一问题,请确保你使用的是最新的 API 版本。

    可简写查找条件

    在构造方法查找条件中,无参的构造方法可以不需要填写查找条件

    假设我们有如下的 Class

    示例如下

    public class TestFoo {
    +
    +    public TestFoo() {
    +        // ...
    +    }
    +}
    +

    我们要得到其中的 public TestFoo() 构造方法,可以写作如下形式。

    示例如下

    TestFoo::class.java.constructor { emptyParam() }
    +

    上面的例子可以成功获取到 public TestFoo() 构造方法,但是感觉有一些繁琐。

    与普通方法不同,由于构造方法不需要考虑 name 名称,当构造方法没有参数的时候,我们可以省略 emptyParam 参数。

    示例如下

    TestFoo::class.java.constructor()
    +

    兼容性说明

    在过往历史版本的 API 中构造方法不填写任何查找参数会直接找不到构造方法,这是一个 BUG,最新版本已经进行修复,请确保你使用的是最新的 API 版本。

    字节码类型

    特别注意

    在字节码调用结果中,cast 方法只能指定字节码对应的类型。

    例如我们想得到一个 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
    +}
    +

    在 Java 中常见的基本类型都已被封装为 类型 + Type 的方式,例如 IntTypeFloatType

    相应地,数组类型也有方便的使用方法,假设我们要获得 String[] 类型的数组。

    需要写做 java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass 才能得到这个类型。

    感觉是不是很麻烦,这个时候我们可以使用扩展方法 ArrayClass(StringType) 来得到这个类型。

    同时由于 String 是常见类型,所以还可以直接使用 StringArrayClass 来得到这个类型。

    一些常见的 Hook 中查找的方法,都有其对应的封装类型以供使用,格式为 类型 + Class

    例如 Hook onCreate 方法需要查找 Bundle::class.java 类型。

    示例如下

    method {
    +    name = "onCreate"
    +    param(BundleClass)
    +}
    +

    同时,欢迎你能贡献更多的常用类型。

    + + + diff --git a/docs/zh-cn/api/special-features/xposed-channel.html b/docs/zh-cn/api/special-features/xposed-channel.html new file mode 100644 index 00000000..88af6953 --- /dev/null +++ b/docs/zh-cn/api/special-features/xposed-channel.html @@ -0,0 +1,94 @@ + + + + + + + + + Xposed 模块与宿主通讯桥 | Yuki Hook API + + + + +

    Xposed 模块与宿主通讯桥

    这是一个使用系统无序广播在模块与宿主之间发送和接收数据的解决方案。

    需要满足的条件

    模块与宿主需要保持存活状态,否则无法建立通讯。

    基本用法

    这里描述了 waitput 方法的基本使用方法。

    通过使用 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")
    +

    你可以不设置 dataChannelvalue 来达到仅通知模块或宿主回调 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")
    +

    特别注意

    接收方需要保持存活状态才能收到通讯数据。

    小提示

    更多功能请参考 YukiHookDataChannel

    判断模块与宿主版本是否匹配

    通过通讯桥功能,YukiHookAPI 还为你提供了在用户更新模块后,判断模块是否与宿主版本匹配的解决方案。

    我们只需要调用 checkingVersionEquals 方法,即可实现这个功能。

    在模块与宿主中可进行双向判断。

    你可以在模块中判断指定包名的宿主是否与当前模块的版本匹配。

    示例如下

    // 从指定包名的宿主获取
    +dataChannel(packageName = "com.example.demo").checkingVersionEquals { isEquals ->
    +    // Your code here.
    +}
    +

    你还可以在宿主中判断是否自身与当前模块的版本匹配。

    示例如下

    // 从模块获取
    +dataChannel.checkingVersionEquals { isEquals ->
    +    // Your code here.
    +}
    +

    方法回调的条件

    宿主、模块保持存活状态,并在激活模块后重启了作用域中的 Hook 目标宿主对象。

    小提示

    更多功能请参考 YukiHookDataChannel

    回调事件响应的规则

    这里只列出了在模块中使用的例子,在宿主中相同的 key 始终不允许重复创建。

    特别注意

    在模块和宿主中,每一个 dataChannel 对应的 key 的回调事件都不允许重复创建,若重复,之前的回调事件会被新增加的回调事件替换,若在模块中使用,在同一个 Activity 中不可以重复,不同的 Activity 中相同的 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.
    +        }
    +    }
    +}
    +

    在上述示例中,回调事件 A 会被回调事件 B 替换掉,回调事件 C 的 key 不与其它重复,回调事件 D 在另一个 Activity 中,所以最终回调事件 B、C、D 都可被创建成功。

    特别注意

    一个相同 key 的回调事件只会回调当前模块正在显示的 Activity 中注册的回调事件,例如上述中的 test_key,如果 OtherActivity 正在显示,那么 MainActivity 中的 test_key 就不会被回调。

    相同的 key 在同一个 Activity 不同的 Fragment 中注册 dataChannel,它们依然会在当前 Activity 中同时被回调。

    在模块中,你只能使用 ActivityContext 注册 dataChannel,你不能在 Application 以及 Service 等地方使用 dataChannel

    若要在 Fragment 中使用 dataChannel,请使用 activity?.dataChannel(...)

    安全性说明

    在模块环境中,你只能接收指定包名的宿主发送的通讯数据且只能发送给指定包名的宿主

    特别注意

    为了进一步防止广播滥用,通讯数据中 API 会自动指定宿主和模块的包名,防止其它 APP 监听并利用广播做出超限行为。

    + + + diff --git a/docs/zh-cn/api/special-features/xposed-storage.html b/docs/zh-cn/api/special-features/xposed-storage.html new file mode 100644 index 00000000..3892ea11 --- /dev/null +++ b/docs/zh-cn/api/special-features/xposed-storage.html @@ -0,0 +1,44 @@ + + + + + + + + + Xposed 模块数据存储 | Yuki Hook API + + + + +

    Xposed 模块数据存储

    这是一个自动对接 SharedPreferencesXSharedPreferences 的高效模块数据存储解决方案。

    我们需要存储模块的数据,以供宿主调用,这个时候会遇到原生 Sp 存储的数据互通阻碍。

    原生的 Xposed 给我们提供了一个 XSharedPreferences 用于读取模块的 Sp 数据。

    在 Activity 中使用

    这里描述了在 Activity 中装载 YukiHookModulePrefs 的场景。

    通常情况下我们可以这样在 Hook APP (宿主) 内对其进行初始化。

    示例如下

    XSharedPreferences(BuildConfig.APPLICATION_ID)
    +

    有没有方便快捷的解决方案呢,此时你就可以使用 YukiHookAPI 的扩展能力快速实现这个功能。

    当你在模块中存储数据的时候,若当前处于 Activity 内,可以使用如下方法。

    示例如下

    modulePrefs.putString("test_name", "saved_value")
    +

    当你在 Hook APP (宿主) 中读取数据时,可以使用如下方法。

    示例如下

    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")
    +

    在 Hook APP (宿主) 中这样读取。

    示例如下

    // 推荐用法
    +val testName = prefs("specify_file_name").getString("test_name", "default_value")
    +// 也可以这样用
    +val testName = prefs.name("specify_file_name").getString("test_name", "default_value")
    +

    若你的项目中有大量的固定数据需要存储和读取,推荐使用 PrefsData 来创建模板。

    小提示

    更多功能请参考 YukiHookModulePrefsPrefsData

    在 PreferenceFragment 中使用

    这里描述了在 PreferenceFragment 中装载 YukiHookModulePrefs 的场景。

    若你的模块使用了 PreferenceFragmentCompat,你现在可以将其继承类开始迁移到 ModulePreferenceFragment

    特别注意

    你必须继承 ModulePreferenceFragment 才能实现 YukiHookModulePrefs 的模块存储功能。

    小提示

    更多功能请参考 ModulePreferenceFragment

    + + + diff --git a/docs/zh-cn/config/api-example.html b/docs/zh-cn/config/api-example.html new file mode 100644 index 00000000..79e899aa --- /dev/null +++ b/docs/zh-cn/config/api-example.html @@ -0,0 +1,212 @@ + + + + + + + + + API 基本配置 | Yuki Hook API + + + + +

    API 基本配置

    这里介绍了 YukiHookAPI 的基本配置方法。

    功能配置

    无论是 作为 Xposed 模块使用 还是 作为 Hook API 使用,你都可以在 API 装载之前或装载过程中对 YukiHookAPI 进行配置。

    configs 方法

    fun configs(initiate: Configs.() -> Unit)
    +

    configs 方法对 Configs 类实现了一个 lambda 方法体,你可以轻松地调用它进行配置。

    小提示

    更多功能请参考 YukiHookAPI.configs 方法。

    Hooker 配置

    一个 Xposed 模块或 Hook API 最重要的地方就是 Hooker 的创建与使用,YukiHookAPI 提供了两种使用方法。

    通过 lambda 创建

    这种方案是最简单的,如果你的模块功能不多,代码数量不大,不需要进行分类处理,推荐使用这种方式进行创建。

    encase 方法

    fun encase(initiate: PackageParam.() -> Unit)
    +

    encase 方法是 Hook 一切生命的开始,在一个模块或一个 Hook 过程中,encase 方法只能作用一次,用于创建 Hooker。

    PackageParam 为宿主(目标 APP)的重要实例对象,通过 PackageParam 来实现对当前 Hook 作用对象的全部 Hook 操作。

    小提示

    更多功能请参考 PackageParam

    encase 方法可以在 onHook 方法中使用两种方案创建。

    示例代码 1

    YukiHookAPI.encase {
    +    loadApp(name = "com.example.demo") {
    +        findClass(name = "$packageName.DemoClass").hook { 
    +            // Your code here.
    +        }
    +    }
    +}
    +

    示例代码 2

    encase {
    +    loadApp(name = "com.example.demo") {
    +        findClass(name = "$packageName.DemoClass").hook { 
    +            // Your code here.
    +        }
    +    }
    +}
    +

    encase 方法中进行你的 Hook 操作。

    通过自定义 Hooker 创建

    这种方案更加适用于大型项目,例如需要对 Hooker 进行分类或对 Hook 的作用对象进行分类。

    encase 方法

    fun encase(vararg hooker: YukiBaseHooker)
    +

    同样为 encase 方法,这里的方法可变数组参数 hooker 为创建入口提供了一个对象,你可以将所有继承于 YukiBaseHooker 的 Hooker 一次性进行装载。

    YukiBaseHooker 用法

    YukiBaseHooker 继承于 PackageParam,你需要将你的子 Hooker 继承于 YukiBaseHooker

    小提示

    更多功能请参考 YukiBaseHooker

    示例如下

    object CustomHooker : YukiBaseHooker() {
    +
    +    override fun onHook() {
    +        // Your code here.
    +    }
    +}
    +

    子 Hooker 建议使用单例 object 创建,你也可以使用 class 但不推荐。

    注意

    你无需再在继承于 YukiBaseHookeronHook 方法中重新调用 encase,这是错误的,且不会生效,你应该直接开始编写你的 Hook 代码。

    示例如下

    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.
    +            }
    +        }
    +    }
    +}
    +

    作为子 Hooker 使用,你还可以在外部调用 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)
    +    }
    +}
    +

    搭建完全部 Hooker 后,你就可以在你的 HookEntryClass 入口类中的 onHook 方法中装载你的 Hooker 了。

    示例如下

    class HookEntry : IYukiHookXposedInit {
    +
    +    override fun onHook() = 
    +        YukiHookAPI.encase(FirstHooker, SecondHooker, ThirdHooker ...)
    +}
    +

    当然,我们同样可以对其进行简写。

    示例如下

    class HookEntry : IYukiHookXposedInit {
    +
    +    override fun onHook() = encase(FirstHooker, SecondHooker, ThirdHooker ...)
    +}
    +

    扩展特性

    如果你当前使用的 Hook Framework 支持并启用了资源钩子(Resources Hook)功能,你现在可以直接在 encase 中创建 Resources Hook。

    你完全不需要与之前在使用 Xposed API 那样区分 initZygotehandleLoadPackagehandleInitPackageResources 方法来执行不同的功能。

    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.
    +        }
    +    }
    +}
    +

    注意事项

    直接装载 Hooker 或直接开始 Hook 是错误的,encase 事件在被 Hook Framework 装载后,会经历三次回调。

    • 装载 initZygoteencase

    • 装载 handleLoadPackageencase

    • 装载 handleInitPackageResourcesencase

    在这个过程中,你需要使用 loadApploadSystemloadZygote 来区分每一次装载代码的调用域,否则你的代码就会被多次执行造成错误

    注意

    无论使用 encase 创建 lambda 方法体还是直接使用 Hooker 形式,你都不应该直接在首个 onHook 事件中直接装载 Hooker 或直接开始 Hook。

    下面是两个错误示例。

    示例代码 1

    encase {
    +    // ❗错误的使用方法,不能直接开始 Hook
    +    findClass(name = "com.example.demo.DemoClass").hook {
    +        // ...
    +    }
    +    // ❗错误的使用方法,不能直接开始 Hook
    +    resources().hook {
    +        // ...
    +    }
    +}
    +

    示例代码 2

    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 {
    +            // ...
    +        }
    +    }
    +}
    +

    下面是上述错误示例的正确示例。

    示例代码 1

    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 {
    +            // ...
    +        }
    +    }
    +}
    +

    示例代码 2

    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 使用需要注意的地方

    若你作为 Hook API 使用,那么你只需要在入口处对 encase 方法进行区分。

    注意

    encase 方法对作为 Hook API 使用提供了两个完全一样的方法,但是比前两者仅多出一个参数 baseContext

    方法 1

    fun encase(baseContext: Context?, initiate: PackageParam.() -> Unit)
    +

    方法 2

    fun encase(baseContext: Context?, vararg hooker: YukiBaseHooker)
    +

    此处的 baseContext 只需填入你在 attachBaseContext 处得到的 Context 即可,其它用法与上述内容完全一致。

    特别注意

    切勿以 Xposed 方式使用 encase 方法而漏掉 baseContext 参数,否则你的 Hook 将完全不工作。

    Resources Hook 功能不支持作为 Hook API 使用。

    + + + diff --git a/docs/zh-cn/config/api-exception.html b/docs/zh-cn/config/api-exception.html new file mode 100644 index 00000000..e8f886fc --- /dev/null +++ b/docs/zh-cn/config/api-exception.html @@ -0,0 +1,386 @@ + + + + + + + + + API 异常处理 | Yuki Hook API + + + + +

    API 异常处理

    异常是在开发过程经常遇到的主要问题,这里介绍了 YukiHookAPI 在使用过程中可能遇到的常见异常以及处理方式。

    这里的异常说明只会同步最新的 API 版本,较旧的 API 版本的异常将不会再进行说明,请始终保持 API 版本为最新。

    非阻断异常

    这些异常不会导致 APP 停止运行(FC),但是会在控制台打印 E 级别的日志,也可能会停止继续执行相关功能。

    exception

    loggerE

    Could not found XposedBridge in current space! Aborted

    异常原因

    你的 Hook Framework 未在工作或并未成功装载 XposedBridge

    解决方案

    请确认你在正确的地方装载了 YukiHookAPIencase 方法,详情请参考 作为 Xposed 模块使用的相关配置 以及 作为 Hook API 使用的相关配置

    exception

    loggerE

    You cannot load a hooker in "onInit" or "onXposedEvent" method! Aborted

    异常原因

    你尝试在继承 IYukiHookXposedInit 的 Hook 入口类的 onInitonXposedEvent 方法中装载了 encase 方法。

    示例如下

    class HookEntry : IYukiHookXposedInit {
    +
    +    override fun onInit() {
    +        // ❗错误的使用方法
    +        YukiHookAPI.encase {
    +            // Your code here.
    +        }
    +    }
    +
    +    override fun onXposedEvent() {
    +        // ❗错误的使用方法
    +        YukiHookAPI.encase {
    +            // Your code here.
    +        }
    +    }
    +
    +    override fun onHook() {
    +        // Your code here.
    +    }
    +}
    +

    解决方案

    请在 onHook 方法中装载 encase 方法。

    示例如下

    class HookEntry : IYukiHookXposedInit {
    +
    +    override fun onInit() {
    +        // 这里只能装载 configs 方法
    +        YukiHookAPI.configs {
    +            // Your code here.
    +        }
    +    }
    +
    +    override fun onHook() {
    +        // ✅ 正确的使用方法
    +        YukiHookAPI.encase {
    +            // Your code here.
    +        }
    +    }
    +}
    +
    exception

    loggerE

    Hooking Process exception occurred

    异常原因

    YukiHookAPI 在进行自身初始化 Hook 过程中发生异常。

    解决方案

    通常情况下这种错误不会轻易发生,若一旦发生此错误,可直接提交日志进行反馈。

    exception

    loggerE

    YukiHookAPI try to load HookEntryClass failed

    异常原因

    YukiHookAPI 在尝试装载 Hook 入口类 onInitonHook 方法时发生了不能处理的异常或找不到入口类。

    解决方案

    通常情况下这种错误不会轻易发生,若一旦发生此错误,请自行查看控制台打印的日志定位问题,确定并非自己的代码发生的问题后,可提交日志进行反馈。

    exception

    loggerE

    YukiHookAPI bind initZygote failed

    异常原因

    YukiHookAPI 在尝试装载 Xposed 原生接口 initZygote 方法时发生了不能处理的异常。

    解决方案

    通常情况下这种错误不会轻易发生,若一旦发生此错误,请自行查看控制台打印的日志定位问题,确定并非自己的代码发生的问题后,可提交日志进行反馈。

    exception

    loggerE

    Failed to execute method "NAME", maybe your Hook Framework not support Resources Hook

    异常原因

    YukiHookAPI 在尝试进行 Resources Hook 时发生错误。

    解决方案

    请仔细检查错误日志的详细信息。

    若发生 Resources$NotFoundException 则可能为你查找的 Resources Id 不正确。

    若发生 ClassNotFoundNoClassDefFoundError 可能是 Hook Framework 不支持 Resources Hook(资源钩子)。

    exception

    loggerE

    HookClass [NAME] not found

    异常原因

    当前被 Hook 的 Class 没有被找到。

    解决方案

    请检查目标 Class 是否存在,若想忽略此错误请使用 ignoredHookClassNotFoundFailure 方法。

    exception

    loggerE

    Hook Member [NAME] failed

    异常原因

    Hook 目标方法、构造方法时发生错误。

    解决方案

    此问题通常由 Hook Framework 产生,请检查对应的日志内容,若问题持续出现请携带详细日志进行反馈。

    exception

    loggerE

    Hooked Member with a finding error by CLASS

    异常原因

    在 Hook 执行后被 Hook 的 membernull 且已经设置目标 Hook 方法、构造类。

    解决方案

    请检查此错误发生前的上一个错误日志,或许在查找方法、构造方法的时候发生了找不到方法、构造方法的错误。

    exception

    loggerE

    Hooked Member cannot be non-null by CLASS

    异常原因

    在 Hook 执行后被 Hook 的 membernull 且没有设置目标 Hook 方法、构造类。

    示例如下

    injectMember {
    +    // 这里并没有设置需要 Hook 的方法、构造方法的查找条件
    +    afterHook {
    +        // ...
    +    }
    +}
    +

    解决方案

    请确认你已经在 Hook 之前正确设置了要 Hook 的方法、构造方法的查找方式。

    示例如下

    injectMember {
    +    // ✅ 正确的使用方法举例
    +    method {
    +        // Your code here.
    +    }
    +    afterHook {
    +        // ...
    +    }
    +}
    +
    exception

    loggerE

    Hooked method return type match failed, required [TYPE] but got [TYPE]

    异常原因

    在 Hook 回调方法体中设置了 HookParam.result 或使用了 replaceHook 但是被 Hook 的方法返回值类型与原返回值类型不匹配。

    示例如下

    假设这个是被 Hook 的方法。

    private boolean test()
    +

    下面是一个错误的案列。

    injectMember {
    +    method {
    +        name = "test"
    +        emptyParam()
    +    }
    +    // <情景1> 设置了错误的类型,原类型为 Boolean
    +    beforeHook {
    +        result = 0
    +    }
    +    // <情景2> 返回了错误的类型,原类型为 Boolean
    +    replaceAny {
    +        0
    +    }
    +    // <情景3> 直接使用了错误的类型,原类型为 Boolean
    +    replaceTo(any = 0)
    +}
    +

    注意

    若上述场景在 beforeHookafterHook 中发生,则会造成被 Hook 的 APP (宿主) 由 XposedBridge 抛出异常 (会对其暴露被 Hook 的事实)。

    解决方案

    请确认当前被 Hook 方法的正确返回值类型,修改后再试一次。

    exception

    loggerE

    Hook initialization failed because got an Exception

    异常原因

    在准备 Hook 时发生了任意的异常。

    解决方案

    这是一个准备 Hook 阶段就发生异常的提醒,请仔细查看具体的异常是什么以重新确定问题。

    exception

    loggerE

    Try to hook NAME[NAME] got an Exception

    异常原因

    在 Hook 开始时发生了任意的异常。

    解决方案

    这是一个 Hook 开始就发生异常的提醒,请仔细查看具体的异常是什么以重新确定问题。

    exception

    loggerE

    Method/Constructor/Field match type "TYPE" not allowed

    异常原因

    在查找方法、构造方法以及变量时设置了不允许的参数类型。

    示例如下

    // 查找一个方法
    +method {
    +    // ❗设置了无效的类型举例
    +    param(false, 1, 0)
    +    // ❗设置了无效的类型举例
    +    returnType = false
    +}
    +
    +// 查找一个变量
    +field {
    +    // ❗设置了无效的类型举例
    +    type = false
    +}
    +

    解决方案

    在查找中 paramreturnTypetype 中仅接受 ClassStringVariousClass 类型的传值,不可传入参数实例。

    示例如下

    // 查找一个方法
    +method {
    +    // ✅ 正确的使用方法举例
    +    param(BooleanType, IntType, IntType)
    +    // ✅ 正确的使用方法举例
    +    returnType = BooleanType
    +    // ✅ 以下方案也是正确的
    +    returnType = "java.lang.Boolean"
    +}
    +
    +// 查找一个变量
    +field {
    +    // ✅ 正确的使用方法举例
    +    type = BooleanType
    +}
    +
    exception

    loggerE

    NoSuchMethod/NoSuchConstructor/NoSuchField happend in [NAME]

    异常原因

    在查找方法、构造方法以及变量时并未找到目标方法、构造方法以及变量。

    解决方案

    请确认你的查找条件是否能正确匹配到目标 Class 中的指定方法、构造方法以及变量。

    exception

    loggerE

    Trying COUNT times and all failure by RemedyPlan

    异常原因

    使用 RemedyPlan 重新查找方法、构造方法、变量时依然没有找到方法、构造方法、变量。

    解决方案

    请确认你设置的 RemedyPlan 参数以及宿主内存在的 Class,再试一次。

    exception

    loggerE

    You must set a condition when finding a Method/Constructor/Field

    异常原因

    在查找方法、构造方法以及变量时并未设置任何条件。

    示例如下

    method {
    +    // 这里没有设置任何条件
    +}
    +

    解决方案

    请将查找条件补充完整并再试一次。

    exception

    loggerE

    Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiHookAPI#ReflectionTool

    异常原因

    通过 ClassLoader.searchClassPackageParam.searchClass 找不到需要查找的 Class 对象。

    示例如下

    customClassLoader?.searchClass {
    +    from(...)
    +    // ...
    +}.get()
    +

    解决方案

    这是一个安全异常,请检查你设置的条件,使用相关工具查看所在 Dex 中的 Class 以及字节码对象特征,并再试一次。

    exception

    loggerE

    Can't find this Method/Constructor/Field in [CLASS]: CONTENT Generated by YukiHookAPI#ReflectionTool

    异常原因

    通过指定条件找不到需要查找的方法、构造方法以及变量。

    示例如下

    TargetClass.method {
    +    name = "test"
    +    param(BooleanType)
    +}
    +

    解决方案

    这是一个安全异常,请检查你设置的条件,使用相关工具查看所在 Class 中的字节码对象特征,并再试一次。

    exception

    loggerE

    The number of VagueType must be at least less than the count of paramTypes

    异常原因

    MethodConstructor 查找条件中错误地使用了 VagueType

    示例如下

    TargetClass.method {
    +    name = "test"
    +    // <情景1>
    +    param(VagueType)
    +    // <情景2>
    +    param(VagueType, VagueType ...)
    +}
    +

    解决方案

    VagueType 不能在方法、构造方法参数中完全填充,若存在这样的需求请使用 paramCount

    exception

    loggerE

    Field match type class is not found

    异常原因

    在查找变量时所设置的查找条件中 typeClass 实例未被找到。

    示例如下

    field {
    +    name = "test"
    +    // 假设这里设置的 type 的 Class 并不存在
    +    type = "com.example.TestClass"
    +}
    +

    解决方案

    请检查查找条件中 typeClass 是否存在,然后再试一次。

    exception

    loggerE

    Method match returnType class is not found

    异常原因

    在查找方法时所设置的查找条件中 returnTypeClass 实例未被找到。

    示例如下

    method {
    +    name = "test"
    +    // 假设这里设置的 returnType 的 Class 并不存在
    +    returnType = "com.example.TestClass"
    +}
    +

    解决方案

    请检查查找条件中 returnTypeClass 是否存在,然后再试一次。

    exception

    loggerE

    Method/Constructor match paramType[INDEX] class is not found

    异常原因

    在查找方法、构造方法时所设置的查找条件中 paramindex 号下标的 Class 实例未被找到。

    method {
    +    name = "test"
    +    // 假设这里设置的 1 号下标的 Class 并不存在
    +    param(StringType, "com.example.TestClass", BooleanType)
    +}
    +

    解决方案

    请检查查找条件中 paramindex 号下标的 Class 是否存在,然后再试一次。

    exception

    loggerE

    Resources Hook condition name/type cannot be empty [TAG]

    异常原因

    在查找 Resources 时并未设置任何条件。

    示例如下

    // 情况 1
    +conditions {
    +    // 这里没有设置任何条件
    +}
    +// 情况 2
    +conditions {
    +    name = "test"
    +    // 这里缺少了 type 条件
    +}
    +

    解决方案

    Resources 的 Hook 并非类似方法的 Hook,其必须拥有完整的名称和类型描述才能查找成功,请将查找条件补充完整并再试一次。

    exception

    loggerE

    Resources Hook type is invalid [TAG]

    异常原因

    在 Hook Resources 时发生了类型错误的异常。

    解决方案

    YukiHookAPI 会尝试在 initZygotehandleInitPackageResources 中装载 Resources Hook,若全部装载失败可能会发生此异常,当前 Hook Framework 需要支持并启用资源钩子(Resources Hook)功能,请检查后再试一次。

    exception

    loggerE

    Resources Hook got an Exception [TAG]

    异常原因

    在 Hook Resources 时发生了任意的异常。

    解决方案

    这是一个异常汇总,请自行向下查看日志具体的异常是什么,例如找不到 Resources Id 的问题。

    exception

    loggerE

    Received action "ACTION" failed

    异常原因

    使用 YukiHookDataChannel 时回调广播事件异常。

    解决方案

    一般情况下,此错误基本上不会发生,一旦发生错误,排除自身代码的问题后,请携带详细日志进行反馈。

    exception

    loggerE

    Failed to sendBroadcast like "KEY", because got null context in "PACKAGENAME"

    异常原因

    使用 YukiHookDataChannel 时发送广播取到了空的上下文实例。

    解决方案

    一般情况下,此错误基本上不会发生,在最新版本中已经修复宿主使用时可能发生的问题,若最新版本依然发生错误,排除自身代码的问题后,请携带详细日志进行反馈。

    exception

    loggerE

    Failed to inject module resources into [RESOURCES]

    异常原因

    在 (Xposed) 宿主环境中使用 injectModuleAppResources 注入模块资源时发生异常。

    解决方案

    一般情况下,此错误基本上不会发生,排除自身代码的问题后,请携带详细日志进行反馈。

    exception

    loggerE

    Activity Proxy initialization failed because got an Exception

    异常原因

    在 (Xposed) 宿主环境中使用 registerModuleAppActivities 注入模块 Activity 时发生异常。

    解决方案

    请检查此错误发生后的下一个错误日志,或许在配置参数上可能发生了一些问题,若找不到相关错误日志的说明,排除自身代码的问题后,请携带详细日志进行反馈。

    exception

    loggerE

    Activity Proxy got an Exception in msg.what [WHAT]

    异常原因

    在 (Xposed) 宿主环境中使用 registerModuleAppActivities 注入模块 Activity 时发生异常。

    解决方案

    一般情况下,此错误基本上不会发生,但根据系统版本差异性并未做详细测试,排除自身代码的问题后,请携带详细日志进行反馈。

    exception

    loggerE

    This proxy [TYPE] type is not allowed

    异常原因

    在 (Xposed) 宿主环境中使用 registerModuleAppActivities 注入模块 Activity 时填入了无效的参数。

    示例如下

    // ❗ 这里填入的内容仅为举例,其中 proxy 填入了不能理解的无效参数
    +registerModuleAppActivities(proxy = false)
    +

    解决方案

    方法中的 proxy 参数只接受 StringCharSequenceClass 类型,请查看相关使用方法正确填入方法参数。

    exception

    loggerE

    Cound not got launch intent for package "NAME"

    异常原因

    在 (Xposed) 宿主环境中使用 registerModuleAppActivities 注入模块 Activity 时找不到宿主的启动 Activity

    示例如下

    // 使用了默认参数直接进行注册
    +registerModuleAppActivities()
    +

    解决方案

    默认参数 (无参) 只能用于可被启动的 APP,若 APP 并未声明启动入口 Activity,你就需要手动指定方法的 proxy 参数。

    exception

    loggerE

    Could not found "NAME" or Class is not a type of Activity

    异常原因

    在 (Xposed) 宿主环境中使用 registerModuleAppActivities 注入模块 Activity 时无法找到被填入参数 proxyActivity

    示例如下

    registerModuleAppActivities(proxy = "com.demo.test.TestActivity")
    +

    解决方案

    请确认你填入的 Activity 名称真实有效地存在于宿主中,且目标 Class 继承于 Activity

    阻断异常

    这些异常会直接导致 APP 停止运行(FC),同时会在控制台打印 E 级别的日志,还会造成 Hook 进程“死掉”。

    exception

    RuntimeException

    !!!DO NOT ALLOWED!!! You cannot hook or reflection to call the internal class of the YukiHookAPI itself, The called class is [CLASS]

    异常原因

    你使用 YukiHookAPI 的相关反射或 Hook 功能调用了 API 自身的 Class 对象。

    示例如下

    // <情景1>
    +YukiHookAPI.current()
    +// <情景2>
    +PackageParam::class.java.hook {
    +    // ...
    +}
    +// <情景3>
    +MethodFinder::class.java.method {
    +    name = "name"
    +    param(StringType)
    +}.get().call("name")
    +// ...
    +

    解决方案

    请检查代码部分是否有错误,例如下面的情况。

    示例如下

    YourClass.method {
    +    // ...
    +    // ❗ 没有调用方法执行,这里实际调用的是 MethodFinder.Result 对象
    +}.get(instance).current()
    +YourClass.method {
    +    // ...
    +    // ✅ 正确的使用方法,假设此方法无参
    +}.get(instance).call().current()
    +

    不允许内联、反射、Hook YukiHookAPI 自身的 Class 以及内部功能,防止发生错误。

    exception

    UnsupportedOperationException

    !!!DANGEROUS!!! Hook [CLASS] Class is a dangerous behavior! [CONTENT] [SOLVE]

    异常原因

    你尝试 Hook 了处于危险行为列表中的 Class 对象,例如 ClassClassLoaderMethod

    示例如下

    // <情景1>
    +JavaClassLoader.hook {
    +    // ...
    +}
    +// <情景2>
    +JavaClass.hook {
    +    // ...
    +}
    +// <情景3>
    +JavaMethod.hook {
    +    // ...
    +}
    +// ...
    +

    解决方案

    这些功能是系统内部的,它们不应该被 Hook,在部分 Hook Framework 上可能不被支持,还会引发其它错误,请尝试更换 Hook 点。

    小提示

    若你仍要使用此功能,请参考 YukiMemberHookCreator.useDangerousOperation

    但是强烈建议不要这样做,发生问题请不要反馈,自行承担一切后果

    exception

    NoClassDefFoundError

    Can't find this Class in [CLASSLOADER]: CONTENT Generated by YukiHookAPI#ReflectionTool

    异常原因

    通过 String.toClass(...)classOf<...>() 找不到需要查找的 Class 对象。

    示例如下

    "com.demo.Test".toClass()
    +

    解决方案

    请检查当前字符串或实体匹配到的 Class 是否存在于当前 ClassLoader,并再试一次。

    exception

    IllegalStateException

    ClassLoader [CLASSLOADER] is not a DexClassLoader

    异常原因

    使用 ClassLoader.searchClassPackageParam.searchClass 查找 Class 但是当前 ClassLoader 并不继承于 BaseDexClassLoader

    解决方案

    这种情况基本不存在,除非当前 APP 引用了非 ART 平台的可执行文件 (但是这种情况还是不会存在) 或当前 ClassLoader 为空。

    exception

    IllegalStateException

    Failed to got SystemContext

    异常原因

    在被 Hook 的宿主内调用了 systemContext 但并未成功获取到实例对象。

    示例如下

    encase {
    +    // 调用了此变量
    +    systemContext...
    +}
    +

    解决方案

    这种情况不应该存在,由于 systemContext 通过反射从 ActivityThread 中得到,除非系统进程发生异常,否则获取到的对象不会为空。

    exception

    IllegalStateException

    App is dead, You cannot call to appContext

    异常原因

    第一种情况

    在被 Hook 的宿主内调用了 ModuleApplicationappContext

    示例如下

    encase {
    +    // 调用了此变量
    +    ModuleApplication.appContext...
    +}
    +

    第二种情况

    使用 ModuleApplication 时调用了 appContext 但是 APP 可能已经被销毁或没有正确启动。

    示例如下

    // 调用了此变量但是 APP 可能已被销毁或没有正确启动
    +ModuleApplication.appContext...
    +

    解决方案

    第一种情况

    你只能在模块内使用 ModuleApplicationappContext,在宿主内请使用 PackageParam 中的 appContext,请确认你使用的是否正确。

    第二种情况

    这种情况基本不存在,由于 appContext 是在 onCreate 中被赋值的,除非遇到多进程并发启动或 APP 没有启动完成前被反射调用了父类的 onCreate 方法。

    exception

    IllegalStateException

    YukiHookModulePrefs not allowed in Custom Hook API

    异常原因

    在 Hook 自身 APP(非 Xposed 模块) 中使用了 YukiHookModulePrefs

    示例如下

    class MyApplication : Application() {
    +
    +    override fun attachBaseContext(base: Context?) {
    +        YukiHookAPI.encase(base) {
    +            // ❗不能在这种情况下使用 prefs
    +            prefs.getBoolean("test_data")
    +        }
    +        super.attachBaseContext(base)
    +    }
    +}
    +

    解决方案

    你只能在 作为 Xposed 模块使用 时使用 YukiHookModulePrefs,在 Hook 自身 APP 中请使用原生的 Sp 存储。

    exception

    IllegalStateException

    Cannot load the XSharedPreferences, maybe is your Hook Framework not support it

    异常原因

    在 (Xposed) 宿主环境使用了 YukiHookModulePrefs 但是无法得到 XSharedPreferences 对象。

    示例如下

    encase {
    +    // 调用了此变量
    +    prefs...
    +}
    +

    解决方案

    一般情况下不会发生此问题,若持续无法获取 XSharedPreferences 对象则可能是你使用的 Hook Framework 不支持此功能或自身存在错误。

    exception

    IllegalStateException

    YukiHookDataChannel not allowed in Custom Hook API

    异常原因

    在 Hook 自身 APP(非 Xposed 模块) 中使用了 YukiHookDataChannel

    示例如下

    class MyApplication : Application() {
    +
    +    override fun attachBaseContext(base: Context?) {
    +        YukiHookAPI.encase(base) {
    +            // ❗不能在这种情况下使用 dataChannel
    +            dataChannel.wait(key = "test_data") {
    +                // ...
    +            }
    +        }
    +        super.attachBaseContext(base)
    +    }
    +}
    +

    解决方案

    你只能在 作为 Xposed 模块使用 时使用 YukiHookDataChannel

    exception

    IllegalStateException

    YukiHookDataChannel only support used on an Activity, but this current context is "CLASSNAME"

    异常原因

    在模块的非 Activity 环境中使用了 YukiHookDataChannel

    解决方案

    你只能在 ActivityFragment 中使用 YukiHookDataChannel

    exception

    IllegalStateException

    Xposed modulePackageName load failed, please reset and rebuild it

    异常原因

    在 Hook 过程中使用 YukiHookModulePrefsYukiHookDataChannel 时无法读取装载时的 modulePackageName 导致不能确定自身模块的包名。

    解决方案

    请仔细阅读 这里 的帮助文档,正确配置模块的 Hook 入口类包名。

    exception

    IllegalStateException

    YukiHookModulePrefs missing Context instance

    异常原因

    在模块中使用了 YukiHookModulePrefs 存储数据但并未传入 Context 实例。

    示例如下

    class MainActivity : AppCompatActivity() {
    +
    +    override fun onCreate(savedInstanceState: Bundle?) {
    +        super.onCreate(savedInstanceState)
    +        // ❗错误的使用方法
    +        // 构造方法已在 API 1.0.88 及以后的版本中设置为 private
    +        YukiHookModulePrefs().getBoolean("test_data")
    +    }
    +}
    +

    解决方案

    Activity 中推荐使用 modulePrefs 方法来装载 YukiHookModulePrefs

    示例如下

    class MainActivity : AppCompatActivity() {
    +
    +    override fun onCreate(savedInstanceState: Bundle?) {
    +        super.onCreate(savedInstanceState)
    +        // ✅ 正确的使用方法
    +        modulePrefs.getBoolean("test_data")
    +    }
    +}
    +
    exception

    IllegalStateException

    Key-Value type TYPE is not allowed

    异常原因

    在使用 YukiHookModulePrefsgetput 方法或 YukiHookDataChannelwaitput 方法时传入了不支持的存储类型。

    解决方案

    YukiHookModulePrefs 支持的类型只有 StringSet<String>IntFloatLongBoolean,请传入支持的类型。

    YukiHookDataChannel 支持的类型为 Intent.putExtra 限制的类型,请传入支持的类型。

    exception

    IllegalStateException

    YukiHookDataChannel cannot used in zygote

    异常原因

    loadZygote 中使用了 YukiHookDataChannel

    示例如下

    loadZygote {
    +    // 调用了此变量
    +    dataChannel...
    +}
    +

    解决方案

    YukiHookDataChannel 只能在 loadSystemloadApp 中使用。

    exception

    IllegalStateException

    Custom Hooking Members is empty

    异常原因

    MemberHookCreator 中调用 members() 但是未设置需要 Hook 的 Member 实例。

    示例如下

    injectMember {
    +    // 括号里的方法参数被留空了
    +    members()
    +    afterHook {
    +        // ...
    +    }
    +}
    +

    解决方案

    若要使用 members() 设置自定义 Hook 方法,你必须保证其方法参数里的 Member 数组对象不能为空。

    exception

    IllegalStateException

    HookParam Method args index must be >= 0

    异常原因

    HookParam 中调用 args().last() 但是目标 param 为空或 args 中的 index 设置了小于 0 的数值。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 假设 param 是空的
    +        args().last()...
    +        // 设置了小于 0 的 index
    +        args(index = -5)...
    +    }
    +}
    +

    解决方案

    请确认你 Hook 的目标方法、构造方法的方法参数数量是否不为空,且不能对 args 的下标设置小于 0 的数值。

    exception

    IllegalStateException

    HookParam instance got null! Is this a static member?

    异常原因

    HookParam 中调用 instance 变量或 instance 方法但获取不到当前实例的对象。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 调用了此变量
    +        instance...
    +        // 调用了此方法
    +        instance<Any>()...
    +    }
    +}
    +

    解决方案

    请确认你 Hook 的方法是否为静态类型,静态类型的方法没有实例,不能使用此功能,若非静态方法,请检查实例是否已经销毁。

    exception

    IllegalStateException

    Current hooked Member args is null

    异常原因

    HookParam 中调用 args 变量但获取不到当前实例方法、构造方法的参数数组。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 调用了此变量
    +        args...
    +    }
    +}
    +

    解决方案

    这种问题一般不会发生,真的发生了此问题,请携带详细日志进行反馈。

    exception

    IllegalStateException

    Current hooked Member is null

    异常原因

    HookParam 中调用 member 变量但获取不到当前实例的方法、构造方法实例。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 调用了此变量
    +        member...
    +    }
    +}
    +

    解决方案

    这种问题一般不会发生,真的发生了此问题,请携带详细日志进行反馈。

    exception

    IllegalStateException

    Current hooked Member is not a Method

    异常原因

    HookParam 中调用 method 变量但获取不到当前实例的方法实例。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 调用了此变量
    +        method...
    +    }
    +}
    +

    解决方案

    请确认你 Hook 的方法是构造方法还是普通方法并使用对应类型的方法获取指定的实例,若不知道字节码的类型可以直接使用 member 来获取。

    exception

    IllegalStateException

    Current hooked Member is not a Constructor

    异常原因

    HookParam 中调用 constructor 变量但获取不到当前实例的方法实例。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 调用了此变量
    +        constructor...
    +    }
    +}
    +

    解决方案

    请确认你 Hook 的方法是普通方法还是构造方法并使用对应类型的方法获取指定的实例,若不知道字节码的类型可以直接使用 member 来获取。

    exception

    IllegalStateException

    HookParam instance cannot cast to TYPE

    异常原因

    HookParam 中调用 instance 方法指定了错误的类型。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 类型被 cast 为 Activity 但假设当前实例的类型并非此类型
    +        instance<Activity>()...
    +    }
    +}
    +

    解决方案

    请确认当前 Hook 实例的正确类型并重新填写泛型中的类型,若不能确定请使用 Any 或直接使用 instance 变量。

    exception

    IllegalStateException

    HookParam Method args is empty, mabe not has args

    异常原因

    HookParam 中调用 ArgsModifyer.set 方法但是当前实例的方法参数数组为空。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 调用了此方法
    +        args(...).set(...)
    +    }
    +}
    +

    解决方案

    请确认你 Hook 的目标方法、构造方法的方法参数数量是否不为空,否则你无法使用此功能。

    exception

    IllegalStateException

    HookParam Method args index out of bounds, max is NUMBER

    异常原因

    HookParam 中调用 ArgsModifyer.set 方法指定了超出方法参数下标的数组序号。

    示例如下

    injectMember {
    +    // ...
    +    afterHook {
    +        // 下标从 0 开始,假设原始的参数下标是 5 个,但是这里填写了 6
    +        args(index = 6).set(...)
    +    }
    +}
    +

    解决方案

    请确认你 Hook 的目标方法、构造方法的方法参数个数,并重新设置数组下标。

    exception

    IllegalStateException

    PackageParam got null ClassLoader

    异常原因

    PackageParam 中调用了 appClassLoader 变量但是无法获取到实例对象。

    示例如下

    encase {
    +    // 调用了此变量
    +    appClassLoader...
    +}
    +

    解决方案

    这种情况几乎不存在,除非模块被装载的宿主或目标 Hook Framework 自身存在问题,若真的发生了此问题,请携带详细日志进行反馈。

    exception

    IllegalStateException

    Current Hook Framework not support moduleAppResources

    异常原因

    PackageParam 中调用了 moduleAppResources 变量但是无法获取到实例对象。

    示例如下

    encase {
    +    // 调用了此变量
    +    moduleAppResources...
    +}
    +

    解决方案

    moduleAppResources 需要当前 Hook Framework 支持 initZygote 功能,请检查后再试一次。

    exception

    IllegalStateException

    VariousClass match failed of those CLASSES

    异常原因

    在使用 VariousClass 创建不确定的 Class 对象时全部的 Class 都没有被找到。

    解决方案

    检查当前 Hook 的宿主内是否存在其中能够匹配的 Class 后,再试一次。

    exception

    IllegalStateException

    Cannot get hook class "NAME" cause THROWABLE

    异常原因

    hook 方法体非 onPrepareHook 方法内调用了 instanceClass 变量且当前 Hook 的 Class 不存在。

    示例如下

    TargetClass.hook {
    +    // 可能的情况为在非 onPrepareHook 方法体内调用了 instanceClass 变量用于打印日志
    +    loggerD(msg = "$instanceClass hook start")
    +}
    +

    解决方案

    hook 内直接使用 instanceClass 是很危险的,若 Class 不存在则会直接导致 Hook 进程“死掉”。

    详情请参考 状态监听

    exception

    IllegalStateException

    LayoutInflatedParam View instance got null

    异常原因

    在布局 Hook 回调中调用了 currentView 但没取到实例对象。

    示例如下

    injectResource {
    +    conditions {
    +        name = "activity_main"
    +        layout()
    +    }
    +    injectAsLayout {
    +        // 调用了此变量
    +        currentView...
    +    }
    +}
    +

    解决方案

    这种情况基本上不存在,除非被 Hook 的宿主当前 Activity 已经销毁或 Hook Framework 自身存在问题。

    exception

    IllegalStateException

    XResForwarder is invalid

    异常原因

    YukiResForwarder 中调用了 resources 但没取到实例对象。

    示例如下

    // 调用了此变量
    +moduleAppResources.fwd(...).resources
    +

    解决方案

    这种情况基本上不存在,除非 Hook Framework 自身存在问题。

    exception

    IllegalStateException

    paramTypes is empty, please use emptyParam() instead

    异常原因

    在查找方法、构造方法时保留了空的 param 方法。

    示例如下

    method {
    +    name = "test"
    +    // 括号内没有填写任何参数
    +    param()
    +}
    +

    解决方案

    若要标识此方法、构造方法没有参数,你可以有如下设置方法。

    第一种,设置 emptyParam (推荐)

    示例如下

    method {
    +    name = "test"
    +    emptyParam()
    +}
    +

    第二种,设置 paramCount = 0

    示例如下

    method {
    +    name = "test"
    +    paramCount = 0
    +}
    +
    exception

    IllegalStateException

    Invalid YukiHookCallback type

    异常原因

    YukiHookAPI 的核心 Hook 功能发生故障。

    解决方案

    这种情况基本上不存在,若发生上述问题,确定并非自己的代码发生的问题后,可提交日志进行反馈。

    exception

    IllegalStateException

    ModuleContextThemeWrapper already loaded

    异常原因

    Context 中使用 applyModuleTheme 方法时重复进行调用。

    示例如下

    // 假设这就是当前的 Context 对象
    +context.applyModuleTheme(R.style.Theme_AppCompat).applyModuleTheme(R.style.Theme_AppCompat)
    +

    解决方案

    Context 中只能创建一次 ModuleContextThemeWrapper,请检查代码是否有循环调用问题。

    exception

    IllegalStateException

    Cannot create classes cache for "android", please remove "name" param

    异常原因

    在系统框架 (android) 宿主使用了 DexClassFinder 的缓存功能 searchClass(name = ...)

    示例如下

    loadSystem {
    +    searchClass(name = "test") {
    +        from(...)
    +        // ...
    +    }.get()
    +}
    +

    解决方案

    由于缓存会将找到的 Class 名称存入 SharedPreferences,但是系统框架不存在 data 目录,所以请不要在系统框架中使用此功能。

    + + + diff --git a/docs/zh-cn/config/api-using.html b/docs/zh-cn/config/api-using.html new file mode 100644 index 00000000..1d154776 --- /dev/null +++ b/docs/zh-cn/config/api-using.html @@ -0,0 +1,82 @@ + + + + + + + + + 作为 Hook API 使用的相关配置 | Yuki Hook API + + + + +

    作为 Hook API 使用的相关配置

    作为 Hook API 通常为做自身 APP 热更新或功能需要以及产品测试的 Hook 操作。

    依赖配置

    你只需要集成 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)
    +    }
    +}
    +

    这样,你就完成了 API 的相关配置。

    你可以 点击这里 查看异同点和注意事项。

    注意

    你不能再使用 loadApp 进行包装,可直接开始编写你的 Hook 代码。

    Hook Framework

    这里给出了一些较高使用率的 Hook Framework 如何对接 YukiHookAPI 的相关方式。

    Pine在新窗口中打开

    所需 Xposed API 依赖 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在新窗口中打开

    所需 Xposed API 依赖 com.swift.sandhook:xposedcompatcom.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在新窗口中打开

    所需 Xposed API 依赖 com.wind.xposed:xposed-on-whale

    请参考 xposed-hook-based-on-whale在新窗口中打开

    示例如下

    override fun attachBaseContext(base: Context?) {
    +    // 装载 Whale 不需要任何配置
    +    // 装载 YukiHookAPI
    +    YukiHookAPI.encase(base) {
    +        // Your code here.
    +    }
    +    super.attachBaseContext(base)
    +}
    +
    + + + diff --git a/docs/zh-cn/config/r8-proguard.html b/docs/zh-cn/config/r8-proguard.html new file mode 100644 index 00000000..91024c30 --- /dev/null +++ b/docs/zh-cn/config/r8-proguard.html @@ -0,0 +1,34 @@ + + + + + + + + + R8 与 Proguard 混淆 | Yuki Hook API + + + + +

    R8 与 Proguard 混淆

    大部分场景下 Xposed 模块可通过原生混淆压缩体积,这里介绍了混淆的配置方法。

    R8

    如果你使用的是 R8,那么你无需对 YukiHookAPI 进行任何特殊配置。

    Proguard

    如果你仍然在使用 Proguard,你需要做一些规则配置。

    特别注意

    Proguard 规则已被弃用,请不要再使用,自从 Android Gradle Plugin 4.2 后,拥有 Android Jetpack 套件最新版本的混淆处理程序默认均为 R8,不再需要考虑混淆的问题。

    若要在任何版本下启用 R8,请在 gradle.properties 文件中加入如下规则,Android Gradle Plugin 7.0 及以上版本无需任何配置。

    android.enableR8=true
    +
    + + + diff --git a/docs/zh-cn/config/xposed-using.html b/docs/zh-cn/config/xposed-using.html new file mode 100644 index 00000000..e8aa1d06 --- /dev/null +++ b/docs/zh-cn/config/xposed-using.html @@ -0,0 +1,109 @@ + + + + + + + + + 作为 Xposed 模块使用的相关配置 | Yuki Hook API + + + + +

    作为 Xposed 模块使用的相关配置

    这里介绍了 YukiHookAPI 作为 Xposed 模块使用的相关配置方法。

    依赖配置

    作为 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 入口的重要注解。

    特别注意

    @InjectYukiHookWithXposed 注解的 Class 必须实现 IYukiHookXposedInit 接口。

    在你当前项目中的所有 Class 标记中只能存在一次,若存在多个声明自动处理程序会在编译时抛出异常,你可以自定义其相关参数。

    sourcePath 参数

    sourcePath 参数决定了自动处理程序自动查找并匹配你当前项目路径的重要标识,此参数的内容为相对路径匹配,默认参数为 src/main

    特别注意

    如果你的项目不在 ../src/main.. 或你手动使用 sourceSets 设置了项目路径,你就需要手动设置 sourcePath 参数,否则自动处理程序将无法识别你的项目路径并会在编译时抛出异常

    示例如下

    @InjectYukiHookWithXposed(sourcePath = "src/custom")
    +

    sourcePath 使用的文件路径分隔符写法根据 WindowsUnix 将自动进行识别,使用 /\ 均可。

    modulePackageName 参数

    modulePackageName 是你当前项目的 applicationId,也就是你的模块包名 (最终生成的应用包名),留空或不填时自动处理程序将对当前项目文件进行分析并生成。

    注意

    若你想使用模块包名自动生成,你需要确保你的项目命名空间在 AndroidManifest.xmlbuild.gradlebuild.gradle.kts 中存在如下任意定义方式。

    示例命名空间 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
    +

    Xposed 入口类处理如下。

    示例如下

    class HookEntry_YukiHookXposedInit: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
    +

    编译后的类名结构如下。

    示例如下

    ...hook.HookEntry ← 你的入口类
    +...hook.HookEntry_Impl ← 自动生成的 Impl 类
    +...hook.HookEntry_YukiHookXposedInit ← 自动生成的 Xposed 入口类
    +

    我们现在定义入口类名称为 HookXposedEntry

    示例如下

    @InjectYukiHookWithXposed(entryClassName = "HookXposedEntry")
    +class HookEntry: IYukiHookXposedInit
    +

    Xposed 入口类处理如下。

    示例如下

    class HookXposedEntry: IXposedHookZygoteInit, IXposedHookLoadPackage, ...
    +

    编译后的类名结构如下。

    示例如下

    ...hook.HookEntry ← 你的入口类
    +...hook.HookEntry_Impl ← 自动生成的 Impl 类
    +...hook.HookXposedEntry ← 自动生成的 Xposed 入口类
    +

    特别注意

    你定义的 entryClassName 不可与 xposed_init 中的类名相同,否则自动处理程序会在编译时抛出异常

    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?) {
    +        // ...
    +    }
    +}
    +

    若你当前的项目并不需要用到 Reources Hook,可以设置 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 的起点。

    小提示

    更多功能请参考 IYukiHookXposedInit

    当你的模块被 Xposed 装载后,onHook 方法将会被回调,你需要在此方法中开始使用 YukiHookAPI

    基本的调用流程为 _YukiHookXposedInitIYukiHookXposedInit.onXposedEventIYukiHookXposedInit.onInitIYukiHookXposedInit.onHook

    详情请参考 API 基本配置

    原生 Xposed API 事件

    若你当前的 Xposed 模块使用了第三方的资源,但是短时间内可能无法转移它们,此时,你可以使用 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]
    +            }
    +        }
    +    }
    +}
    +

    onXposedEventonHook 方法完全独立存在,互不影响,你可以继续在 onHook 方法中使用 YukiHookAPI

    小提示

    更多功能请参考 IYukiHookXposedInit.onXposedEvent 方法。

    + + + diff --git a/docs/zh-cn/guide/example.html b/docs/zh-cn/guide/example.html new file mode 100644 index 00000000..2fdbfde8 --- /dev/null +++ b/docs/zh-cn/guide/example.html @@ -0,0 +1,318 @@ + + + + + + + + + 用法示例 | 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

    你可以在下方找到 API 提供的 Demo 来学习 YukiHookAPI 的使用方法。

    同时安装宿主和模块 Demo,通过激活模块来测试宿主中被 Hook 的功能。

    一个简单的 Hook 例子

    这里给出了 Hook APP、Hook 系统框架与 Hook Resources 等例子,可供参考。

    Hook APP

    假设,我们要 Hook 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 启动时弹出此对话框。

    那么,我想继续 Hook 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.
    +    }
    +}
    +

    没关系,你还可以使用字符串类名直接创建一个 Hook。

    示例如下

    "$packageName.TestClass".hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}
    +

    小提示

    更多功能请参考 MemberHookCreator

    Hook Zygote

    在 APP 启动时,新的进程被 fork 后的第一个事件 initZygote

    假设我们要全局 Hook 一个 APP ActivityonCreate 事件

    encase 方法体中添加代码。

    示例如下

    loadZygote {
    +    ActivityClass.hook { 
    +        injectMember { 
    +            method { 
    +                name = "onCreate"
    +                param(BundleClass)
    +                returnType = UnitType
    +            }
    +            afterHook {
    +                // Your code here.
    +            }
    +        }
    +    }
    +}
    +

    注意

    loadZygote 中进行的功能十分有限,几乎很少的情况下需要用到 loadZygote 方法。

    Hook 系统框架

    YukiHookAPI 中,Hook 系统框架的实现非常简单。

    假设,你要得到 ApplicationInfoPackageInfo 并对它们进行一些操作。

    encase 方法体中添加代码。

    示例如下

    loadSystem {
    +    ApplicationInfoClass.hook {
    +        // Your code here.
    +    }
    +    PackageInfoClass.hook {
    +        // Your code here.
    +    }
    +}
    +

    特别注意

    loadZygoteloadSystem 有直接性区别,loadZygote 会在 initZygote 中装载,系统框架被视为 loadApp(name = "android") 而存在,若要 Hook 系统框架,可直接使用 loadSystem

    Hook Resources

    假设,我们要 Hook com.android.browserstring 类型的 app_name 内容替换为 123

    encase 方法体中添加代码。

    示例如下

    loadApp(name = "com.android.browser") {
    +    resources().hook {
    +        injectResource {
    +            conditions {
    +                name = "app_name"
    +                string()
    +            }
    +            replaceTo("123")
    +        }
    +    }
    +}
    +

    若当前 APP 使用 app_name 设置了标题栏文本,则它就会变成我们的 123

    你还可以使用当前 Xposed 模块的 Resources 替换 Hook APP 的 Resources。

    假设,我们要继续 Hook com.android.browsermipmap 类型的 ic_launcher

    示例如下

    loadApp(name = "com.android.browser") {
    +    resources().hook {
    +        injectResource {
    +            conditions {
    +                name = "ic_launcher"
    +                mipmap()
    +            }
    +            replaceToModuleResource(R.mipmap.ic_launcher)
    +        }
    +    }
    +}
    +

    至此目标 APP 的图标将会被替换为我们设置的图标。

    若你想替换系统框架的资源,同样也可以这样实现,只需要把 loadApp 换成 loadZygote 即可。

    示例如下

    loadZygote {
    +    resources().hook {
    +        // Your code here.
    +    }
    +}
    +

    小提示

    更多功能请参考 ResourcesHookCreator

    解除 Hook

    原生的 Xposed 为我们提供了一个 XC_MethodHook.Unhook 功能,可以从 Hook 队列中将当前 Hook 移除,YukiHookAPI 同样可以实现此功能。

    第一种方法,保存当前注入对象的 Result 实例,在适当的时候和地方调用 remove 即可解除该注入对象。

    示例如下

    // 设置一个变量保存当前实例
    +val hookResult = injectMember { 
    +    method { 
    +        name = "test"
    +        returnType = UnitType
    +    }
    +    afterHook {
    +        // ...
    +    }
    +}
    +// 在适当的时候调用如下方法即可
    +hookResult.remove()
    +

    第二种方法,在 Hook 回调方法中调用 removeSelf 移除自身。

    示例如下

    injectMember { 
    +    method { 
    +        name = "test"
    +        returnType = UnitType
    +    }
    +    afterHook {
    +        // 直接调用如下方法即可
    +        removeSelf()
    +    }
    +}
    +

    小提示

    更多功能请参考 MemberHookCreator

    异常处理

    YukiHookAPI 重新设计了对异常的监听,任何异常都不会在 Hook 过程中抛出,避免打断下一个 Hook 流程导致 Hook 进程“死掉”。

    监听异常

    你可以处理 Hook 方法过程发生的异常。

    示例如下

    injectMember {
    +    // Your code here.
    +}.result {
    +    // 处理 Hook 开始时的异常
    +    onHookingFailure {}
    +    // 处理 Hook 过程中的异常
    +    onConductFailure { param, throwable -> }
    +    // 处理全部异常
    +    onAllFailure {}
    +    // ...
    +}
    +

    在 Resources Hook 时此方法同样适用。

    示例如下

    injectResource {
    +    // Your code here.
    +}.result {
    +    // 处理 Hook 时的任意异常
    +    onHookingFailure {}
    +    // ...
    +}
    +

    你还可以处理 Hook 的 Class 不存在时发生的异常。

    示例如下

    TargetClass.hook {
    +    injectMember {
    +        // Your code here.
    +    }
    +}.onHookClassNotFoundFailure {
    +    // Your code here.
    +}
    +

    你还可以处理查找方法时的异常。

    示例如下

    method {
    +    // Your code here.
    +}.onNoSuchMethod {
    +    // Your code here.
    +}
    +

    小提示

    更多功能请参考 MemberHookCreator.ResultResourcesHookCreator.Result

    这里介绍了可能发生的常见异常,若要了解更多请参考 API 异常处理

    抛出异常

    在某些情况下,你可以手动抛出异常来达到提醒某些功能存在问题的目的。

    上面已经介绍过,在 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 -> }
    +}
    +

    以上情景只会在 (Xposed) 宿主环境被处理,不会对宿主自身造成任何影响。

    若我们想将这些异常直接抛给宿主,原生的 Xposed 为我们提供了 param.throwable 方法,YukiHookAPI 同样可以实现此功能。

    若想在 Hook 回调方法体中将一个异常直接抛给宿主,可以有如下实现方法。

    示例如下

    injectMember {
    +    method {
    +        // ...
    +    }
    +    afterHook {
    +        RuntimeException("Exception Test").throwToApp()
    +    }
    +}
    +

    你也可以直接在 Hook 回调方法体中抛出异常,然后标识将异常抛给宿主。

    示例如下

    injectMember {
    +    method {
    +        // ...
    +    }
    +    afterHook {
    +        throw RuntimeException("Exception Test")
    +    }.onFailureThrowToApp()
    +}
    +

    以上两种方法均可在宿主接收到异常从而使宿主进程崩溃。

    注意

    为了保证 Hook 调用域与宿主内调用域相互隔离,异常只有在 beforeHookafterHook 回调方法体中才能抛给宿主。

    状态监听

    在使用 XposedHelpers 的同学往往会在 Hook 后打印 Unhook 的方法确定是否 Hook 成功。

    YukiHookAPI 中,你可以用以下方法方便地重新实现这个功能。

    首先我们可以监听 Hook 已经准备开始。

    示例如下

    YourClass.hook {
    +    // Your code here.
    +}.onPrepareHook {
    +    loggerD(msg = "$instanceClass hook start")
    +}
    +

    特别注意

    instanceClass 建议只在 onPrepareHook 中使用,否则被 Hook 的 Class 不存在会抛出无法拦截的异常导致 Hook 进程“死掉”。

    然后,我们还可以对 Hook 的方法结果进行监听是否成功。

    示例如下

    injectMember {
    +    // Your code here.
    +}.onHooked { member ->
    +    loggerD(msg = "$member has hooked")
    +}
    +

    扩展用法

    你可以在 Hook 过程中使用下面的方法方便地实现各种判断和功能。

    多个宿主

    如果你的模块需要同时处理多个 APP 的 Hook 事件,你可以使用 loadApp 方法体来区分你要 Hook 的 APP。

    示例如下

    loadApp(name = "com.android.browser") {
    +    // Your code here.
    +}
    +loadApp(name = "com.android.phone") {
    +    // Your code here.
    +}
    +

    小提示

    更多功能请参考 PackageParam.loadApp

    多个进程

    如果你 Hook 的宿主 APP 有多个进程,你可以使用 withProcess 方法体来对它们分别进行 Hook。

    示例如下

    withProcess(mainProcessName) {
    +    // Your code here.
    +}
    +withProcess(name = "$packageName:tool") {
    +    // Your code here.
    +}
    +

    小提示

    更多功能请参考 PackageParam.withProcess

    写法优化

    为了使代码更加简洁,你可以删去 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.
    +}
    +

    小提示

    更多功能请参考 YukiHookAPI.Status

    注意

    若模块激活判断中包含太极、无极中的激活状态,就必须将模块的 Application 继承于 ModuleApplication 或直接使用 ModuleApplication

    1.0.91 版本后的 API 修改了激活逻辑判断方式,现在你可以在模块与 Hook APP (宿主) 中同时使用此 API;

    需要确保 YukiHookAPI.Configs.isEnableHookModuleStatus 是启用状态;

    除了提供标准 API 的 Hook 框架之外,其它情况下模块可能都将无法判断自己是否被激活。

    + + + diff --git a/docs/zh-cn/guide/home.html b/docs/zh-cn/guide/home.html new file mode 100644 index 00000000..69222cef --- /dev/null +++ b/docs/zh-cn/guide/home.html @@ -0,0 +1,139 @@ + + + + + + + + + 介绍 | Yuki Hook API + + + + +

    介绍

    这是一个 Hook API 框架,本身不提供任何 Hook 功能,需要 Xposed 基础 API 的支持。

    背景

    这是一个使用 Kotlin 重新构建的高效 Xposed Hook API。

    名称取自 《ももくり》女主 栗原 雪(Yuki)在新窗口中打开

    前身为 开发学习项目在新窗口中打开 中使用的 Innocent Xposed API,现在重新命名并开源。

    用途

    YukiHookAPI 完全采用 Kotlin lambda 语法构建。

    抛弃原始不太友好的 XposedHelpers,你可以使用它来轻松创建 Xposed 模块以及轻松实现自定义 Hook API。

    语言要求

    请使用 Kotlin,框架部分代码构成同样兼容 Java 但基础 Hook 场景的实现可能完全无法使用

    文档全部的 Demo 示例代码都将使用 Kotlin 进行描述,如果你完全不会使用 Kotlin 那你将有可能无法使用 YukiHookAPI

    部分 Java Demo 代码可在 这里在新窗口中打开 找到,但不推荐使用。

    灵感来源

    以前,我们在构建 Xposed 模块的时候,首先需要在 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)
    +            )
    +    }
    +}
    +

    是的,你没有看错,仅仅就需要这些代码,就能完全取代 Xposed API 实现同样的功能。

    现在,借助高效强大的 YukiHookAPI,你就可以实现一个非常简单的 Xposed 模块。

    支持的 Hook 框架

    以下是 YukiHookAPI 支持的 Hook Framework 以及 Xposed 框架。

    Hook FrameworkSTDescription
    LSPosed在新窗口中打开多场景下稳定使用
    LSPatch在新窗口中打开将在此项目完善后逐渐加入 API 支持
    EdXposed在新窗口中打开已停止维护,不再推荐使用
    Pine在新窗口中打开可以使用
    SandHook在新窗口中打开可以使用
    Whale在新窗口中打开需要 xposed-hook-based-on-whale在新窗口中打开
    YAHFA在新窗口中打开需要自行实现 Xposed API
    FastHook在新窗口中打开需要自行实现 Xposed API
    Epic在新窗口中打开需要自行对接 Dexposed在新窗口中打开
    TaiChi在新窗口中打开可以作为模块使用
    Xposed在新窗口中打开未测试,不再推荐使用
    + + + diff --git a/docs/zh-cn/guide/knowledge.html b/docs/zh-cn/guide/knowledge.html new file mode 100644 index 00000000..6a4251ff --- /dev/null +++ b/docs/zh-cn/guide/knowledge.html @@ -0,0 +1,45 @@ + + + + + + + + + 基础知识 | Yuki Hook API + + + + +

    基础知识

    这里收集了 Xposed 相关的介绍以及开启前需要掌握的知识要点,已经了解的同学可以略过。

    基础知识内容并不一定完全准确,请根据自己的见解酌情阅读,若发现内容有错误欢迎指正并帮助我们完善和改进

    相关介绍

    这里介绍了 Xposed 以及 Hook 的工作原理。

    Xposed 是什么

    Xposed 框架(Xposed Framework)是一套开源的、在 Android 高权限模式下运行的框架服务,可以在不修改 APK 文件的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。

    上述内容复制自百度百科。

    Xposed 能做什么

    下方的结构描述了 Xposed 的基本工作方式和原理。

    Xposed Framework
    +└── App's Environment
    +    └── Hooker (Hooked)
    +        ...
    +    App's Environment
    +    └── Hooker (Hooked)
    +        ...
    +    ...
    +

    我们可以在宿主 (APP) 运行时通过注入宿主 (APP) 来达到控制其行为的最终目的。

    Xposed 的这种运行方式被称为寄生,Xposed 模块跟随宿主的生命周期,在宿主的生命周期内完成自己的生命历程。

    我们可以通过反射的方式调用宿主的方法、变量、构造方法,以及使用 XposedBridge 所提供的 Hook 操作动态地在宿主 (APP) 要执行的方法前后插入自己的代码,或完全替换目标,甚至是拦截。

    发展过程

    如今的 Xposed 管理器已完全被其衍生作品替代,而 SuperSU 的时代也已经落幕了,现在,借助 Magisk 使后面的一切又成为了可能。

    其发展史大致可分为 Xposed(Dalvik)Xposed(ART)Xposed(Magisk)EdXposed(Riru)/LSPosed(Riru/Zygisk)

    衍生产品

    下方的结构描述了类似 Xposed 的 Hook Framework 的工作方式和原理。

    App's Environment
    +└── Hook Framework
    +    └── Hooker (Hooked)
    +        ...
    +

    通过 Xposed 的运行原理,从而衍生了很多同类型框架,随着当今时代的移动设备获取 Root 权限甚至刷机越来越困难且不是刚需的时候,一些免 Root 框架也随之产生,例如太极

    这些在 ART 层面上的 Hook 框架同样也可不借助 Xposed API 完成其和 Xposed 原理一样的 Hook 流程,免 Root 的运行原理为修改 APK 并将 Hook 进程注入宿主,通过外部模块对其进行控制。

    另外一种产品就是利用 Android 运行环境现有的功能虚拟出一个完全与当前设备系统一样的环境,并在其中运行 APP,这个就是虚拟 APP 技术 VirtualApp,后来衍生为 VirtualXposed

    上述提到的免 Root 框架分别为太极/无极VirtualXposed/SandVXposed

    YukiHookAPI 做了什么

    自从 Xposed 出现到现在为止,除了开发者人人皆知的 XposedHelpers,依然没有一套针对 Kotlin 打造的语法糖以及用法封装十分完善的 API。

    本 API 框架的诞生就是希望在 Xposed 的如今时代,能让更多有动手能力的 Xposed 模块开发者少走弯路,更容易、更简单地完成整个开发流程。

    未来,YukiHookAPI 将在使用 Xposed API 的目标基础上适配更多第三方 Hook 框架,使得整个生态得到完善,并帮助更多开发者让 Xposed 模块开发变得更加简单和易懂。

    让我们开始吧

    在开始之前,你需要拥有以下基础才能更好地使用 YukiHookAPI

    + + + diff --git a/docs/zh-cn/guide/move-to-new-api.html b/docs/zh-cn/guide/move-to-new-api.html new file mode 100644 index 00000000..53e5c971 --- /dev/null +++ b/docs/zh-cn/guide/move-to-new-api.html @@ -0,0 +1,216 @@ + + + + + + + + + 从 Xposed API 迁移 | Yuki Hook API + + + + +

    从 Xposed API 迁移

    若你熟悉 Xposed API,你可以参考下方的相同点将自己的 API 快速迁移到 YukiHookAPI

    迁移 Hook 入口点

    XC_LoadPackage.LoadPackageParam 迁移至 PackageParam

    YukiHookAPIPackageParam 实现了 lambda 方法体 this 用法,在 encase 方法体内即可全局得到 PackageParam 对象。

    API 功能差异对比如下

    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 用法,在 beforeHookafterHook 等方法体内即可全局得到 HookParam 对象。

    API 功能差异对比如下

    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 为它做出了多种形式以供选择。

    API 功能差异对比如下

    /// 无返回值的方法 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 文档 以及 特色功能 来决定一些功能性的迁移和使用。

    + + + diff --git a/docs/zh-cn/guide/quick-start.html b/docs/zh-cn/guide/quick-start.html new file mode 100644 index 00000000..db4dd9cf --- /dev/null +++ b/docs/zh-cn/guide/quick-start.html @@ -0,0 +1,101 @@ + + + + + + + + + 快速开始 | Yuki Hook API + + + + +

    快速开始

    集成 YukiHookAPI 到你的项目中。

    环境要求

    • 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 1.0.80)

    自动构建项目

    YukiHookAPI 提供了一个自动化构建工具,它可以帮助你快速构建一个拥有 Xposed 模块依赖的 Android 标准项目模板,使用构建好的模板即可直接开始下一步工作。

    你可以 点击这里 进行查看。

    手动配置项目

    若你不想使用自动化构建工具,你依然可以按照以下方式手动配置项目依赖。

    创建项目

    使用 Android StudioIntelliJ 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" }
    +}
    +

    在你的 app build.gradle 中添加 plugin

    示例如下

    plugins {
    +    // ❗作为 Xposed 模块使用务必添加,其它情况可选
    +    id 'com.google.devtools.ksp' version '<ksp-version>'
    +}
    +

    在你的 app 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>'
    +}
    +

    请将 <ksp-version> 修改为 这里在新窗口中打开 的最新版本 (请注意选择你当前对应的 Kotlin 版本)

    请将 <yuki-version> 修改为 这里 的最新版本。

    特别注意

    YukiHookAPIapiksp-xposed 依赖的版本必须一一对应,否则将会造成版本不匹配错误。

    在你的 app build.gradle 中修改 Kotlin 的 Jvm 版本为 11 及以上。

    示例如下

    android {
    +    compileOptions {
    +        sourceCompatibility JavaVersion.VERSION_11
    +        targetCompatibility JavaVersion.VERSION_11
    +    }
    +    kotlinOptions {
    +        jvmTarget = '11'
    +    }
    +}
    +

    注意

    自 API 1.0.80 版本后 Jvm 版本默认为 11,不再支持 1.8 及以下版本。

    作为 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"/>
    +

    在你的项目中创建一个 Hook 入口类,继承于 IYukiHookXposedInit 并加入注解 @InjectYukiHookWithXposed

    示例如下

    @InjectYukiHookWithXposed
    +class HookEntry : IYukiHookXposedInit {
    +
    +    override fun onHook() = YukiHookAPI.encase {
    +        // Your code here.
    +    }
    +}
    +

    建议

    你可以将你的模块 APP 的 Application 继承于 ModuleApplication 以实现完整使用体验。

    更多功能请参考 ModuleApplication

    然后,你就可以开始编写 Hook 代码了。

    有关作为 Xposed 模块使用的相关配置详细内容,你可以 点击这里 继续阅读。

    若你目前正在使用 Xposed API,你可以参考 从 Xposed API 迁移

    作为 Hook API 使用

    集成方式

    创建你的自定义 Application

    特别注意

    无论使用任何 Hook Framework,你都需要加入其对接的 Xposed 依赖支持。

    若目标 Hook Framework 没有集成 Xposed API 你需要自行实现并对接 XposedBridge

    attachBaseContext 中添加 YukiHookAPI.encase 方法。

    示例如下

    override fun attachBaseContext(base: Context?) {
    +    // 装载 Hook Framework
    +    //
    +    // Your code here.
    +    //
    +    // 装载 YukiHookAPI
    +    YukiHookAPI.encase(base) {
    +        // Your code here.
    +    }
    +    super.attachBaseContext(base)
    +}
    +

    然后,你就可以开始编写 Hook 代码了,方式与作为 Xposed 模块使用基本一致。

    有关作为 Hook API 使用的相关配置详细内容,你可以 点击这里 继续阅读。

    注意

    使用自定义的 Hook 框架而并非完整的 Xposed 模块时,YukiHookModuleStatusYukiHookModulePrefsYukiHookDataChannel 以及 Resources Hook 功能将失效。

    + + + diff --git a/docs/zh-cn/index.html b/docs/zh-cn/index.html new file mode 100644 index 00000000..9b94df3b --- /dev/null +++ b/docs/zh-cn/index.html @@ -0,0 +1,58 @@ + + + + + + + + + 首页 | Yuki Hook API + + + + +
    Yuki Hook API

    Yuki Hook API

    一个使用 Kotlin 重构的轻量、高效、稳定的 Xposed Hook API

    快速上手 更新日志

    Xposed 模块开发

    自动构建程序可以帮你快速创建一个 Xposed 模块,完全省去配置入口类和 xposed_init 文件。

    轻量优雅

    拥有一套强大、优雅、人性化、完全使用 Kotlin lambda 打造的 API,可以帮你快速实现字节码的查找以及方法 Hook。

    高效调试

    拥有丰富的调试日志功能,细到每个 Hook 方法的名称、所在类以及查找耗时,可进行快速调试和排错。

    方便移植

    原生支持 Xposed API 用法,并原生对接 Xposed API,拥有 Xposed API 的 Hook 框架都能进行快速对接。

    支持混淆

    构建的 Xposed 模块原生支持 R8 压缩优化混淆,混淆不会破坏 Hook 入口点,R8 下无需任何其它配置。

    快速上手

    简单易用,不需要繁琐的配置,不需要十足的开发经验,搭建环境集成依赖即可立即开始使用。

    所有 Hook 流程一步到位,拒绝繁琐

    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)
    +        }
    +    }
    +}
    +
    + + + diff --git a/docs/zh-cn/tools/yukihookapi-projectbuilder.html b/docs/zh-cn/tools/yukihookapi-projectbuilder.html new file mode 100644 index 00000000..8d46576f --- /dev/null +++ b/docs/zh-cn/tools/yukihookapi-projectbuilder.html @@ -0,0 +1,33 @@ + + + + + + + + + YukiHookAPI 构建工具 | Yuki Hook API + + + + +

    YukiHookAPI 构建工具

    这是一个使用 YukiHookAPI 作为核心的 Xposed 模块自动构建工具。

    实现自动化搜索依赖快速搭建一个包含 Xposed 模块环境的 Android 项目模板。

    获取项目

    本项目完全开源免费,且会根据大家的使用情况持续维护,初代版本可能存在不完善或 BUG,欢迎反馈。

    项目地址 YukiHookAPI-ProjectBuilder在新窗口中打开

    若你想直接下载可以 点击这里在新窗口中打开 前往 Release 发布地址。

    使用方法

    这里包含了基本的使用方法和功能讲解。

    基本用法

    • 软件使用过程需要当前设备已连接互联网,若项目依赖无法搜索请尝试 科学上网

    • 启动软件后,对你期望创建的项目进行简单配置,点击右下角的 按钮 或菜单栏选择 项目 > 开始创建 即可开始任务。

    • 等待依赖自动搜索完成后,你可以对项目依赖进行配置,建议使用最新依赖保证项目的稳定性,构建工具也仅对最新依赖进行支持。

    • 选择你需要创建项目的目录,开始后项目会在你选择的位置中创建,并等待整个过程完成,项目就创建好了。

    配置模板

    配置模板是一个扩展功能,你可以选择菜单栏 项目 > 配置模板 > 新建模板,即可使用当前填写的配置创建一份模板,下次可以从 已保存的模板 中重新载入模板,即可还原当前配置。

    多语言支持

    软件语言跟随当前系统,你可以在菜单栏 语言 (Language) 一栏手动选择软件的界面语言。

    + + +