mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-07 03:05:36 +08:00
871 lines
271 KiB
HTML
871 lines
271 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en-US">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<meta name="generator" content="VuePress 2.0.0-beta.51">
|
||
<style>
|
||
:root {
|
||
--c-bg: #fff;
|
||
}
|
||
html.dark {
|
||
--c-bg: #22272e;
|
||
}
|
||
html, body {
|
||
background-color: var(--c-bg);
|
||
}
|
||
</style>
|
||
<script>
|
||
const userMode = localStorage.getItem('vuepress-color-scheme');
|
||
const systemDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||
if (userMode === 'dark' || (userMode !== 'light' && systemDarkMode)) {
|
||
document.documentElement.classList.toggle('dark', true);
|
||
}
|
||
</script>
|
||
<link rel="icon" href="/images/logo.png"><title>Reflection Extensions | Yuki Hook API</title><meta name="description" content="An efficient Kotlin version of the Xposed Hook API">
|
||
<link rel="modulepreload" href="/YukiHookAPI/assets/app.fb8271cf.js"><link rel="modulepreload" href="/YukiHookAPI/assets/reflection.html.37e12a3d.js"><link rel="modulepreload" href="/YukiHookAPI/assets/reflection.html.ff24950f.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.1b76ac9e.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.872aa7a1.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.6cc32291.js"><link rel="prefetch" href="/YukiHookAPI/assets/about.html.7638d3a2.js"><link rel="prefetch" href="/YukiHookAPI/assets/changelog.html.86d916d5.js"><link rel="prefetch" href="/YukiHookAPI/assets/contacts.html.5dc8225c.js"><link rel="prefetch" href="/YukiHookAPI/assets/future.html.94bd226b.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.f6b9c2a4.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-example.html.47c311e0.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-exception.html.72ebad13.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-using.html.c794f69e.js"><link rel="prefetch" href="/YukiHookAPI/assets/r8-proguard.html.15e04e11.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-using.html.cd65195d.js"><link rel="prefetch" href="/YukiHookAPI/assets/example.html.a036bda1.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.f6f658d0.js"><link rel="prefetch" href="/YukiHookAPI/assets/knowledge.html.437816ed.js"><link rel="prefetch" href="/YukiHookAPI/assets/move-to-new-api.html.78f39fa5.js"><link rel="prefetch" href="/YukiHookAPI/assets/quick-start.html.e309979a.js"><link rel="prefetch" href="/YukiHookAPI/assets/yukihookapi-projectbuilder.html.ed4fa356.js"><link rel="prefetch" href="/YukiHookAPI/assets/about.html.c0115524.js"><link rel="prefetch" href="/YukiHookAPI/assets/changelog.html.05a4745e.js"><link rel="prefetch" href="/YukiHookAPI/assets/contacts.html.3df7cacf.js"><link rel="prefetch" href="/YukiHookAPI/assets/future.html.2cf8d6de.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.cad3998c.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-example.html.f5361b1b.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-exception.html.ac2a5859.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-using.html.0a59e2e0.js"><link rel="prefetch" href="/YukiHookAPI/assets/r8-proguard.html.683a5429.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-using.html.557dcdf1.js"><link rel="prefetch" href="/YukiHookAPI/assets/example.html.13ac887a.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.4d8cac8a.js"><link rel="prefetch" href="/YukiHookAPI/assets/knowledge.html.821f04b5.js"><link rel="prefetch" href="/YukiHookAPI/assets/move-to-new-api.html.508c5312.js"><link rel="prefetch" href="/YukiHookAPI/assets/quick-start.html.eacb83f2.js"><link rel="prefetch" href="/YukiHookAPI/assets/yukihookapi-projectbuilder.html.d499d226.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-inject.html.c5fc5faf.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-lifecycle.html.412bbdd6.js"><link rel="prefetch" href="/YukiHookAPI/assets/logger.html.2d57680b.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-channel.html.96712a39.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-storage.html.c35a7041.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-inject.html.83f072dc.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-lifecycle.html.09c0b222.js"><link rel="prefetch" href="/YukiHookAPI/assets/logger.html.e8fab6a3.js"><link rel="prefetch" href="/YukiHookAPI/assets/reflection.html.2e612549.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-channel.html.b798a8f8.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-storage.html.5fd9a913.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookAPI.html.77b2a461.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookAPI.html.476693ca.js"><link rel="prefetch" href="/YukiHookAPI/assets/InjectYukiHookWithXposed.html.56391530.js"><link rel="prefetch" href="/YukiHookAPI/assets/CurrentClass.html.16c29272.js"><link rel="prefetch" href="/YukiHookAPI/assets/GenericClass.html.7b666428.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookClass.html.52e59cf0.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookResources.html.2486cf29.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariousClass.html.bd237fa4.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiMemberHookCreator.html.d3b181da.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResourcesHookCreator.html.8aaa9934.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiBaseHooker.html.99eec744.js"><link rel="prefetch" href="/YukiHookAPI/assets/ReflectionFactory.html.a9e6e2d7.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookFactory.html.61db5860.js"><link rel="prefetch" href="/YukiHookAPI/assets/LoggerFactory.html.914e1c34.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookParam.html.b19d4ad2.js"><link rel="prefetch" href="/YukiHookAPI/assets/PackageParam.html.7a64d58c.js"><link rel="prefetch" href="/YukiHookAPI/assets/CurrentClass.html.641fcd58.js"><link rel="prefetch" href="/YukiHookAPI/assets/GenericClass.html.3a0e1ac6.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookClass.html.486aa6ea.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookResources.html.4f07fd98.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariousClass.html.7c81aa10.js"><link rel="prefetch" href="/YukiHookAPI/assets/InjectYukiHookWithXposed.html.cf9b500d.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiMemberHookCreator.html.37dcaec4.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResourcesHookCreator.html.46168b72.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiBaseHooker.html.b68236f9.js"><link rel="prefetch" href="/YukiHookAPI/assets/ReflectionFactory.html.f7b7c82c.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookFactory.html.64f654a6.js"><link rel="prefetch" href="/YukiHookAPI/assets/LoggerFactory.html.72d1861a.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookParam.html.f98d02d2.js"><link rel="prefetch" href="/YukiHookAPI/assets/PackageParam.html.37aae471.js"><link rel="prefetch" href="/YukiHookAPI/assets/ComponentTypeFactory.html.5af05d7d.js"><link rel="prefetch" href="/YukiHookAPI/assets/GraphicsTypeFactory.html.a3936b7c.js"><link rel="prefetch" href="/YukiHookAPI/assets/ViewTypeFactory.html.7da3eef4.js"><link rel="prefetch" href="/YukiHookAPI/assets/DefinedTypeFactory.html.8137c32c.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariableTypeFactory.html.d4c9dbd1.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleApplication.html.57573770.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookDataChannel.html.75c012dd.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookModulePrefs.html.e0f278fe.js"><link rel="prefetch" href="/YukiHookAPI/assets/IYukiHookXposedInit.html.b37a852b.js"><link rel="prefetch" href="/YukiHookAPI/assets/ComponentTypeFactory.html.0026a7b8.js"><link rel="prefetch" href="/YukiHookAPI/assets/GraphicsTypeFactory.html.bfb4e259.js"><link rel="prefetch" href="/YukiHookAPI/assets/ViewTypeFactory.html.612b6202.js"><link rel="prefetch" href="/YukiHookAPI/assets/DefinedTypeFactory.html.ba3bdd0b.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariableTypeFactory.html.550d3346.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleApplication.html.a386b8db.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookDataChannel.html.74e08a45.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookModulePrefs.html.5eb62ec3.js"><link rel="prefetch" href="/YukiHookAPI/assets/IYukiHookXposedInit.html.78a55860.js"><link rel="prefetch" href="/YukiHookAPI/assets/BaseFinder.html.a5dbb7a7.js"><link rel="prefetch" href="/YukiHookAPI/assets/DexClassFinder.html.5d8e12f0.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorFinder.html.0c13dc47.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldFinder.html.4410e26c.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodFinder.html.97f89f93.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiModuleResources.html.e5c5fb30.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResForwarder.html.4e23df75.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResources.html.afb6fb92.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiXposedEvent.html.560fa41c.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelData.html.f8f818f6.js"><link rel="prefetch" href="/YukiHookAPI/assets/PrefsData.html.dfd7c23c.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModulePreferenceFragment.html.764fecc3.js"><link rel="prefetch" href="/YukiHookAPI/assets/BaseFinder.html.8f275c85.js"><link rel="prefetch" href="/YukiHookAPI/assets/DexClassFinder.html.78c5f805.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorFinder.html.7de4f560.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldFinder.html.25713065.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodFinder.html.03ce70ab.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiModuleResources.html.d8e27a7f.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResForwarder.html.0dadd8db.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResources.html.7b0a4824.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiXposedEvent.html.a93ee4ef.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelData.html.194718a1.js"><link rel="prefetch" href="/YukiHookAPI/assets/PrefsData.html.d3cf97f9.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModulePreferenceFragment.html.0c7dadc7.js"><link rel="prefetch" href="/YukiHookAPI/assets/CountRules.html.2d5ab94d.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModifierRules.html.c36dff17.js"><link rel="prefetch" href="/YukiHookAPI/assets/NameRules.html.00ac96fb.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorRules.html.d62bae6c.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldRules.html.9b04521f.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRules.html.a071b3c6.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodRules.html.c10f9770.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppActivity.html.90d3c4e6.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppCompatActivity.html.a20d9206.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleContextThemeWrapper.html.0879426b.js"><link rel="prefetch" href="/YukiHookAPI/assets/CountRules.html.2639d392.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModifierRules.html.f7582dc2.js"><link rel="prefetch" href="/YukiHookAPI/assets/NameRules.html.47e512e4.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorRules.html.f8d7dd83.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldRules.html.6858f0d6.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRules.html.b3e5d297.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodRules.html.146b27be.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleContextThemeWrapper.html.229a46ac.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppActivity.html.09451ff7.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppCompatActivity.html.dd9e40e9.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRulesResult.html.e79843c3.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRulesResult.html.58e81c94.js"><link rel="prefetch" href="/YukiHookAPI/assets/404.html.c038a05a.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.f53b6095.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.d735d08d.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.f36dcd2e.js"><link rel="prefetch" href="/YukiHookAPI/assets/about.html.7d8b24a5.js"><link rel="prefetch" href="/YukiHookAPI/assets/changelog.html.22a53013.js"><link rel="prefetch" href="/YukiHookAPI/assets/contacts.html.8946c067.js"><link rel="prefetch" href="/YukiHookAPI/assets/future.html.e52259cf.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.fd8a27c6.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-example.html.ffabf490.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-exception.html.5fb01524.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-using.html.1ec848ab.js"><link rel="prefetch" href="/YukiHookAPI/assets/r8-proguard.html.1ec215bf.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-using.html.f07fa93e.js"><link rel="prefetch" href="/YukiHookAPI/assets/example.html.e66bd85b.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.6cc8b4b8.js"><link rel="prefetch" href="/YukiHookAPI/assets/knowledge.html.a4616f5c.js"><link rel="prefetch" href="/YukiHookAPI/assets/move-to-new-api.html.f0cc4092.js"><link rel="prefetch" href="/YukiHookAPI/assets/quick-start.html.749cf17e.js"><link rel="prefetch" href="/YukiHookAPI/assets/yukihookapi-projectbuilder.html.c5d87cd3.js"><link rel="prefetch" href="/YukiHookAPI/assets/about.html.f4c8582a.js"><link rel="prefetch" href="/YukiHookAPI/assets/changelog.html.576ee237.js"><link rel="prefetch" href="/YukiHookAPI/assets/contacts.html.0e0a7262.js"><link rel="prefetch" href="/YukiHookAPI/assets/future.html.4da05d23.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.e164d825.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-example.html.63409bed.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-exception.html.9f654113.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-using.html.37eb156b.js"><link rel="prefetch" href="/YukiHookAPI/assets/r8-proguard.html.44d498ce.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-using.html.701123e9.js"><link rel="prefetch" href="/YukiHookAPI/assets/example.html.be2f529d.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.06a0e41c.js"><link rel="prefetch" href="/YukiHookAPI/assets/knowledge.html.e0a069f9.js"><link rel="prefetch" href="/YukiHookAPI/assets/move-to-new-api.html.2d2ee2a7.js"><link rel="prefetch" href="/YukiHookAPI/assets/quick-start.html.20dd75c7.js"><link rel="prefetch" href="/YukiHookAPI/assets/yukihookapi-projectbuilder.html.ae5d1a49.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-inject.html.e5c6c6ae.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-lifecycle.html.73e3c8fc.js"><link rel="prefetch" href="/YukiHookAPI/assets/logger.html.55af0b09.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-channel.html.ea22e7ce.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-storage.html.cd1e83bb.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-inject.html.acabeb56.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-lifecycle.html.56277eb5.js"><link rel="prefetch" href="/YukiHookAPI/assets/logger.html.fd07b1ad.js"><link rel="prefetch" href="/YukiHookAPI/assets/reflection.html.3174ec77.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-channel.html.18cd2bdb.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-storage.html.6926bcf4.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookAPI.html.1c02f82e.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookAPI.html.18811dc9.js"><link rel="prefetch" href="/YukiHookAPI/assets/InjectYukiHookWithXposed.html.b6100747.js"><link rel="prefetch" href="/YukiHookAPI/assets/CurrentClass.html.072e89c6.js"><link rel="prefetch" href="/YukiHookAPI/assets/GenericClass.html.b1c03ed1.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookClass.html.f01a0415.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookResources.html.b888e8b6.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariousClass.html.3e45065c.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiMemberHookCreator.html.bacce7a8.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResourcesHookCreator.html.d14760e0.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiBaseHooker.html.0fb80f07.js"><link rel="prefetch" href="/YukiHookAPI/assets/ReflectionFactory.html.daab3686.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookFactory.html.61878d38.js"><link rel="prefetch" href="/YukiHookAPI/assets/LoggerFactory.html.84495d50.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookParam.html.918accc4.js"><link rel="prefetch" href="/YukiHookAPI/assets/PackageParam.html.3014d07d.js"><link rel="prefetch" href="/YukiHookAPI/assets/CurrentClass.html.2e606398.js"><link rel="prefetch" href="/YukiHookAPI/assets/GenericClass.html.ca958253.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookClass.html.7354fd95.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookResources.html.70a752b2.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariousClass.html.5a07233f.js"><link rel="prefetch" href="/YukiHookAPI/assets/InjectYukiHookWithXposed.html.ecb261b1.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiMemberHookCreator.html.55afd41d.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResourcesHookCreator.html.ddbc430b.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiBaseHooker.html.6b167698.js"><link rel="prefetch" href="/YukiHookAPI/assets/ReflectionFactory.html.d2629c75.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookFactory.html.122ae5d0.js"><link rel="prefetch" href="/YukiHookAPI/assets/LoggerFactory.html.bb211a96.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookParam.html.30f4fb72.js"><link rel="prefetch" href="/YukiHookAPI/assets/PackageParam.html.4c3306f9.js"><link rel="prefetch" href="/YukiHookAPI/assets/ComponentTypeFactory.html.61d8989e.js"><link rel="prefetch" href="/YukiHookAPI/assets/GraphicsTypeFactory.html.61eca533.js"><link rel="prefetch" href="/YukiHookAPI/assets/ViewTypeFactory.html.e29c5d7e.js"><link rel="prefetch" href="/YukiHookAPI/assets/DefinedTypeFactory.html.bca7fe3f.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariableTypeFactory.html.6d08103b.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleApplication.html.e946b5fe.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookDataChannel.html.f40252bf.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookModulePrefs.html.77ac932a.js"><link rel="prefetch" href="/YukiHookAPI/assets/IYukiHookXposedInit.html.7f3e0a05.js"><link rel="prefetch" href="/YukiHookAPI/assets/ComponentTypeFactory.html.2f6bbc66.js"><link rel="prefetch" href="/YukiHookAPI/assets/GraphicsTypeFactory.html.df9b6853.js"><link rel="prefetch" href="/YukiHookAPI/assets/ViewTypeFactory.html.f12c489b.js"><link rel="prefetch" href="/YukiHookAPI/assets/DefinedTypeFactory.html.1a27d470.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariableTypeFactory.html.c8d4e99d.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleApplication.html.ad43cded.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookDataChannel.html.b01666c1.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookModulePrefs.html.9506520f.js"><link rel="prefetch" href="/YukiHookAPI/assets/IYukiHookXposedInit.html.4813ba4f.js"><link rel="prefetch" href="/YukiHookAPI/assets/BaseFinder.html.8588c8ac.js"><link rel="prefetch" href="/YukiHookAPI/assets/DexClassFinder.html.5e274913.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorFinder.html.022babd4.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldFinder.html.7f3e47fc.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodFinder.html.55746f01.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiModuleResources.html.581abd4c.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResForwarder.html.3fa53afd.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResources.html.b3a31d94.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiXposedEvent.html.ae210e6f.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelData.html.2358cb0e.js"><link rel="prefetch" href="/YukiHookAPI/assets/PrefsData.html.be01fa30.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModulePreferenceFragment.html.40d2af95.js"><link rel="prefetch" href="/YukiHookAPI/assets/BaseFinder.html.1ec4ffab.js"><link rel="prefetch" href="/YukiHookAPI/assets/DexClassFinder.html.92677d64.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorFinder.html.254da89b.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldFinder.html.908d5caa.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodFinder.html.9844b141.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiModuleResources.html.c36ad6ed.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResForwarder.html.ef96ef7b.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResources.html.d71b960b.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiXposedEvent.html.e00ead3e.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelData.html.2404edfd.js"><link rel="prefetch" href="/YukiHookAPI/assets/PrefsData.html.0d8e9948.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModulePreferenceFragment.html.7e33a328.js"><link rel="prefetch" href="/YukiHookAPI/assets/CountRules.html.52ed8a0d.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModifierRules.html.1596e901.js"><link rel="prefetch" href="/YukiHookAPI/assets/NameRules.html.5da95c04.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorRules.html.d56dfdf4.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldRules.html.990238ad.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRules.html.1a50f297.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodRules.html.b1f90f61.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppActivity.html.1aa71ae6.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppCompatActivity.html.2fd9ae3a.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleContextThemeWrapper.html.5787cac6.js"><link rel="prefetch" href="/YukiHookAPI/assets/CountRules.html.5103015c.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModifierRules.html.4767495f.js"><link rel="prefetch" href="/YukiHookAPI/assets/NameRules.html.4729f5e5.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorRules.html.e17434ce.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldRules.html.1fea86e8.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRules.html.fbc5b06f.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodRules.html.9819df7e.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleContextThemeWrapper.html.7262b83c.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppActivity.html.fd7c57b2.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppCompatActivity.html.de402219.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRulesResult.html.2524371e.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRulesResult.html.49b372bb.js"><link rel="prefetch" href="/YukiHookAPI/assets/404.html.d9151b86.js">
|
||
<link rel="stylesheet" href="/YukiHookAPI/assets/style.e115708c.css">
|
||
</head>
|
||
<body>
|
||
<div id="app"><!--[--><div class="theme-container"><!--[--><header class="navbar"><div class="toggle-sidebar-button" title="toggle sidebar" aria-expanded="false" role="button" tabindex="0"><div class="icon" aria-hidden="true"><span></span><span></span><span></span></div></div><span><a href="/YukiHookAPI/en/" class=""><img class="logo" src="/YukiHookAPI/images/logo.png" alt="Yuki Hook API"><span class="site-name can-hide">Yuki Hook API</span></a></span><div class="navbar-items-wrapper" style=""><!--[--><!--]--><nav class="navbar-items can-hide"><!--[--><div class="navbar-item"><div class="navbar-dropdown-wrapper"><button class="navbar-dropdown-title" type="button" aria-label="Navigation"><span class="title">Navigation</span><span class="arrow down"></span></button><button class="navbar-dropdown-title-mobile" type="button" aria-label="Navigation"><span class="title">Navigation</span><span class="right arrow"></span></button><ul style="display:none;" class="navbar-dropdown"><!--[--><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>Get Started</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/home" class="" aria-label="Introduce"><!--[--><!--]--> Introduce <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/knowledge" class="" aria-label="Basic Knowledge"><!--[--><!--]--> Basic Knowledge <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/quick-start" class="" aria-label="Quick Start"><!--[--><!--]--> Quick Start <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/example" class="" aria-label="Usage Example"><!--[--><!--]--> Usage Example <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/move-to-new-api" class="" aria-label="Migrate from Xposed API"><!--[--><!--]--> Migrate from Xposed API <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>Configs</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/api-example" class="" aria-label="API Basic Configs"><!--[--><!--]--> API Basic Configs <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/api-exception" class="" aria-label="API Exception Handling"><!--[--><!--]--> API Exception Handling <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/xposed-using" class="" aria-label="Use as Xposed Module Configs"><!--[--><!--]--> Use as Xposed Module Configs <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/api-using" class="" aria-label="Use as Hook API Configs"><!--[--><!--]--> Use as Hook API Configs <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/r8-proguard" class="" aria-label="R8 & Proguard Obfuscate"><!--[--><!--]--> R8 & Proguard Obfuscate <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>Tools</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/tools/yukihookapi-projectbuilder" class="" aria-label="YukiHookAPI Project Builder"><!--[--><!--]--> YukiHookAPI Project Builder <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>API Document</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/api/home" class="" aria-label="Document Introduction"><!--[--><!--]--> Document Introduction <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/YukiHookAPI" class="" aria-label="Public API"><!--[--><!--]--> Public API <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/api/special-features/reflection" class="router-link-active" aria-label="Special Features"><!--[--><!--]--> Special Features <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>About</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/about/changelog" class="" aria-label="Changelog"><!--[--><!--]--> Changelog <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/about/future" class="" aria-label="Looking for Future"><!--[--><!--]--> Looking for Future <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/about/contacts" class="" aria-label="Contact Us"><!--[--><!--]--> Contact Us <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/about/about" class="" aria-label="About this Document"><!--[--><!--]--> About this Document <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><!--]--></ul></div></div><div class="navbar-item"><a href="/YukiHookAPI/en/about/contacts" class="" aria-label="Contact Us"><!--[--><!--]--> Contact Us <!--[--><!--]--></a></div><div class="navbar-item"><div class="navbar-dropdown-wrapper"><button class="navbar-dropdown-title" type="button" aria-label="Select language"><span class="title">English (US)</span><span class="arrow down"></span></button><button class="navbar-dropdown-title-mobile" type="button" aria-label="Select language"><span class="title">English (US)</span><span class="right arrow"></span></button><ul style="display:none;" class="navbar-dropdown"><!--[--><li class="navbar-dropdown-item"><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html" class="router-link-active router-link-exact-active router-link-active" aria-label="English"><!--[--><!--]--> English <!--[--><!--]--></a></li><li class="navbar-dropdown-item"><a href="/YukiHookAPI/zh-cn/api/special-features/reflection.html" class="" aria-label="简体中文"><!--[--><!--]--> 简体中文 <!--[--><!--]--></a></li><!--]--></ul></div></div><div class="navbar-item"><a class="external-link" href="https://github.com/fankes/YukiHookAPI" rel="noopener noreferrer" target="_blank" aria-label="GitHub"><!--[--><!--]--> GitHub <span><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"><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"></path><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"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!--[--><!--]--></a></div><!--]--></nav><!--[--><!--]--><button class="toggle-color-mode-button" title="toggle color mode"><svg style="" class="icon" focusable="false" viewBox="0 0 32 32"><path d="M16 12.005a4 4 0 1 1-4 4a4.005 4.005 0 0 1 4-4m0-2a6 6 0 1 0 6 6a6 6 0 0 0-6-6z" fill="currentColor"></path><path d="M5.394 6.813l1.414-1.415l3.506 3.506L8.9 10.318z" fill="currentColor"></path><path d="M2 15.005h5v2H2z" fill="currentColor"></path><path d="M5.394 25.197L8.9 21.691l1.414 1.415l-3.506 3.505z" fill="currentColor"></path><path d="M15 25.005h2v5h-2z" fill="currentColor"></path><path d="M21.687 23.106l1.414-1.415l3.506 3.506l-1.414 1.414z" fill="currentColor"></path><path d="M25 15.005h5v2h-5z" fill="currentColor"></path><path d="M21.687 8.904l3.506-3.506l1.414 1.415l-3.506 3.505z" fill="currentColor"></path><path d="M15 2.005h2v5h-2z" fill="currentColor"></path></svg><svg style="display:none;" class="icon" focusable="false" viewBox="0 0 32 32"><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"></path></svg></button><form class="search-box" role="search"><input type="search" placeholder="Search" autocomplete="off" spellcheck="false" value><!----></form></div></header><!--]--><div class="sidebar-mask"></div><!--[--><aside class="sidebar"><nav class="navbar-items"><!--[--><div class="navbar-item"><div class="navbar-dropdown-wrapper"><button class="navbar-dropdown-title" type="button" aria-label="Navigation"><span class="title">Navigation</span><span class="arrow down"></span></button><button class="navbar-dropdown-title-mobile" type="button" aria-label="Navigation"><span class="title">Navigation</span><span class="right arrow"></span></button><ul style="display:none;" class="navbar-dropdown"><!--[--><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>Get Started</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/home" class="" aria-label="Introduce"><!--[--><!--]--> Introduce <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/knowledge" class="" aria-label="Basic Knowledge"><!--[--><!--]--> Basic Knowledge <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/quick-start" class="" aria-label="Quick Start"><!--[--><!--]--> Quick Start <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/example" class="" aria-label="Usage Example"><!--[--><!--]--> Usage Example <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/guide/move-to-new-api" class="" aria-label="Migrate from Xposed API"><!--[--><!--]--> Migrate from Xposed API <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>Configs</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/api-example" class="" aria-label="API Basic Configs"><!--[--><!--]--> API Basic Configs <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/api-exception" class="" aria-label="API Exception Handling"><!--[--><!--]--> API Exception Handling <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/xposed-using" class="" aria-label="Use as Xposed Module Configs"><!--[--><!--]--> Use as Xposed Module Configs <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/api-using" class="" aria-label="Use as Hook API Configs"><!--[--><!--]--> Use as Hook API Configs <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/config/r8-proguard" class="" aria-label="R8 & Proguard Obfuscate"><!--[--><!--]--> R8 & Proguard Obfuscate <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>Tools</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/tools/yukihookapi-projectbuilder" class="" aria-label="YukiHookAPI Project Builder"><!--[--><!--]--> YukiHookAPI Project Builder <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>API Document</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/api/home" class="" aria-label="Document Introduction"><!--[--><!--]--> Document Introduction <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/YukiHookAPI" class="" aria-label="Public API"><!--[--><!--]--> Public API <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/api/special-features/reflection" class="router-link-active" aria-label="Special Features"><!--[--><!--]--> Special Features <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>About</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/about/changelog" class="" aria-label="Changelog"><!--[--><!--]--> Changelog <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/about/future" class="" aria-label="Looking for Future"><!--[--><!--]--> Looking for Future <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/about/contacts" class="" aria-label="Contact Us"><!--[--><!--]--> Contact Us <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/en/about/about" class="" aria-label="About this Document"><!--[--><!--]--> About this Document <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><!--]--></ul></div></div><div class="navbar-item"><a href="/YukiHookAPI/en/about/contacts" class="" aria-label="Contact Us"><!--[--><!--]--> Contact Us <!--[--><!--]--></a></div><div class="navbar-item"><div class="navbar-dropdown-wrapper"><button class="navbar-dropdown-title" type="button" aria-label="Select language"><span class="title">English (US)</span><span class="arrow down"></span></button><button class="navbar-dropdown-title-mobile" type="button" aria-label="Select language"><span class="title">English (US)</span><span class="right arrow"></span></button><ul style="display:none;" class="navbar-dropdown"><!--[--><li class="navbar-dropdown-item"><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html" class="router-link-active router-link-exact-active router-link-active" aria-label="English"><!--[--><!--]--> English <!--[--><!--]--></a></li><li class="navbar-dropdown-item"><a href="/YukiHookAPI/zh-cn/api/special-features/reflection.html" class="" aria-label="简体中文"><!--[--><!--]--> 简体中文 <!--[--><!--]--></a></li><!--]--></ul></div></div><div class="navbar-item"><a class="external-link" href="https://github.com/fankes/YukiHookAPI" rel="noopener noreferrer" target="_blank" aria-label="GitHub"><!--[--><!--]--> GitHub <span><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"><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"></path><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"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!--[--><!--]--></a></div><!--]--></nav><!--[--><!--]--><ul class="sidebar-items"><!--[--><li><p tabindex="0" class="sidebar-item sidebar-heading collapsible">Get Started <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/en/guide/home.html" class="sidebar-item" aria-label="Introduce"><!--[--><!--]--> Introduce <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/guide/knowledge.html" class="sidebar-item" aria-label="Basic Knowledge"><!--[--><!--]--> Basic Knowledge <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/guide/quick-start.html" class="sidebar-item" aria-label="Quick Start"><!--[--><!--]--> Quick Start <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/guide/example.html" class="sidebar-item" aria-label="Usage Example"><!--[--><!--]--> Usage Example <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/guide/move-to-new-api.html" class="sidebar-item" aria-label="Migrate from Xposed API"><!--[--><!--]--> Migrate from Xposed API <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item sidebar-heading collapsible">Configs <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/en/config/api-example.html" class="sidebar-item" aria-label="API Basic Configs"><!--[--><!--]--> API Basic Configs <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/config/api-exception.html" class="sidebar-item" aria-label="API Exception Handling"><!--[--><!--]--> API Exception Handling <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/config/xposed-using.html" class="sidebar-item" aria-label="Use as Xposed Module Configs"><!--[--><!--]--> Use as Xposed Module Configs <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/config/api-using.html" class="sidebar-item" aria-label="Use as Hook API Configs"><!--[--><!--]--> Use as Hook API Configs <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/config/r8-proguard.html" class="sidebar-item" aria-label="R8 & Proguard Obfuscate"><!--[--><!--]--> R8 & Proguard Obfuscate <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item sidebar-heading collapsible">Tools <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/en/tools/yukihookapi-projectbuilder.html" class="sidebar-item" aria-label="YukiHookAPI Project Builder"><!--[--><!--]--> YukiHookAPI Project Builder <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item sidebar-heading active collapsible">API Document <span class="down arrow"></span></p><ul style="" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/en/api/home.html" class="sidebar-item" aria-label="Document Introduce"><!--[--><!--]--> Document Introduce <!--[--><!--]--></a><!----></li><li><p tabindex="0" class="sidebar-item collapsible">Public API <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/YukiHookAPI.html" class="sidebar-item" aria-label="YukiHookAPI - object"><!--[--><!--]--> YukiHookAPI - object <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html" class="sidebar-item" aria-label="PackageParam - class"><!--[--><!--]--> PackageParam - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html" class="sidebar-item" aria-label="HookParam - class"><!--[--><!--]--> HookParam - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html" class="sidebar-item" aria-label="InjectYukiHookWithXposed - annotation"><!--[--><!--]--> InjectYukiHookWithXposed - annotation <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/proxy/IYukiHookXposedInit.html" class="sidebar-item" aria-label="IYukiHookXposedInit - interface"><!--[--><!--]--> IYukiHookXposedInit - interface <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookModulePrefs.html" class="sidebar-item" aria-label="YukiHookModulePrefs - class"><!--[--><!--]--> YukiHookModulePrefs - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/ui/ModulePreferenceFragment.html" class="sidebar-item" aria-label="ModulePreferenceFragment - class"><!--[--><!--]--> ModulePreferenceFragment - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/data/PrefsData.html" class="sidebar-item" aria-label="PrefsData - class"><!--[--><!--]--> PrefsData - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/YukiHookDataChannel.html" class="sidebar-item" aria-label="YukiHookDataChannel - class"><!--[--><!--]--> YukiHookDataChannel - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/channel/data/ChannelData.html" class="sidebar-item" aria-label="ChannelData - class"><!--[--><!--]--> ChannelData - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/application/ModuleApplication.html" class="sidebar-item" aria-label="ModuleApplication - class"><!--[--><!--]--> ModuleApplication - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppActivity.html" class="sidebar-item" aria-label="ModuleAppActivity - class"><!--[--><!--]--> ModuleAppActivity - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/activity/base/ModuleAppCompatActivity.html" class="sidebar-item" aria-label="ModuleAppCompatActivity - class"><!--[--><!--]--> ModuleAppCompatActivity - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/context/wrapper/ModuleContextThemeWrapper.html" class="sidebar-item" aria-label="ModuleContextThemeWrapper - class"><!--[--><!--]--> ModuleContextThemeWrapper - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiModuleResources.html" class="sidebar-item" aria-label="YukiModuleResources - class"><!--[--><!--]--> YukiModuleResources - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResources.html" class="sidebar-item" aria-label="YukiResources - class"><!--[--><!--]--> YukiResources - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/dummy/YukiResForwarder.html" class="sidebar-item" aria-label="YukiResForwarder - class"><!--[--><!--]--> YukiResForwarder - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/event/YukiXposedEvent.html" class="sidebar-item" aria-label="YukiXposedEvent - object"><!--[--><!--]--> YukiXposedEvent - object <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory.html" class="sidebar-item" aria-label="ComponentTypeFactory - kt"><!--[--><!--]--> ComponentTypeFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory.html" class="sidebar-item" aria-label="GraphicsTypeFactory - kt"><!--[--><!--]--> GraphicsTypeFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory.html" class="sidebar-item" aria-label="ViewTypeFactory - kt"><!--[--><!--]--> ViewTypeFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory.html" class="sidebar-item" aria-label="VariableTypeFactory - kt"><!--[--><!--]--> VariableTypeFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/type/defined/DefinedTypeFactory.html" class="sidebar-item" aria-label="DefinedTypeFactory - kt"><!--[--><!--]--> DefinedTypeFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html" class="sidebar-item" aria-label="LoggerFactory - kt"><!--[--><!--]--> LoggerFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html" class="sidebar-item" aria-label="ReflectionFactory - kt"><!--[--><!--]--> ReflectionFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html" class="sidebar-item" aria-label="YukiHookFactory - kt"><!--[--><!--]--> YukiHookFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html" class="sidebar-item" aria-label="YukiBaseHooker - class"><!--[--><!--]--> YukiBaseHooker - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html" class="sidebar-item" aria-label="YukiMemberHookCreator - class"><!--[--><!--]--> YukiMemberHookCreator - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html" class="sidebar-item" aria-label="YukiResourcesHookCreator - class"><!--[--><!--]--> YukiResourcesHookCreator - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder.html" class="sidebar-item" aria-label="MethodFinder - class"><!--[--><!--]--> MethodFinder - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder.html" class="sidebar-item" aria-label="ConstructorFinder - class"><!--[--><!--]--> ConstructorFinder - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder.html" class="sidebar-item" aria-label="FieldFinder - class"><!--[--><!--]--> FieldFinder - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/DexClassFinder.html" class="sidebar-item" aria-label="DexClassFinder - class"><!--[--><!--]--> DexClassFinder - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/result/MemberRulesResult.html" class="sidebar-item" aria-label="MemberRulesResult - class"><!--[--><!--]--> MemberRulesResult - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules.html" class="sidebar-item" aria-label="MemberRules - class"><!--[--><!--]--> MemberRules - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules.html" class="sidebar-item" aria-label="FieldRules - class"><!--[--><!--]--> FieldRules - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules.html" class="sidebar-item" aria-label="MethodRules - class"><!--[--><!--]--> MethodRules - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules.html" class="sidebar-item" aria-label="ConstructorRules - class"><!--[--><!--]--> ConstructorRules - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/BaseFinder.html" class="sidebar-item" aria-label="BaseFinder - class"><!--[--><!--]--> BaseFinder - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules.html" class="sidebar-item" aria-label="CountRules - class"><!--[--><!--]--> CountRules - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules.html" class="sidebar-item" aria-label="ModifierRules - class"><!--[--><!--]--> ModifierRules - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules.html" class="sidebar-item" aria-label="NameRules - class"><!--[--><!--]--> NameRules - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html" class="sidebar-item" aria-label="HookClass - class"><!--[--><!--]--> HookClass - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html" class="sidebar-item" aria-label="VariousClass - class"><!--[--><!--]--> VariousClass - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html" class="sidebar-item" aria-label="CurrentClass - class"><!--[--><!--]--> CurrentClass - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html" class="sidebar-item" aria-label="GenericClass - class"><!--[--><!--]--> GenericClass - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/public/com/highcapable/yukihookapi/hook/bean/HookResources.html" class="sidebar-item" aria-label="HookResources - class"><!--[--><!--]--> HookResources - class <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item active collapsible">Special Features <span class="down arrow"></span></p><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html" class="router-link-active router-link-exact-active router-link-active sidebar-item active" aria-label="Reflection Extensions"><!--[--><!--]--> Reflection Extensions <!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#class-extensions" class="router-link-active router-link-exact-active sidebar-item" aria-label="Class Extensions"><!--[--><!--]--> Class Extensions <!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#object-conversion" class="router-link-active router-link-exact-active sidebar-item" aria-label="Object Conversion"><!--[--><!--]--> Object Conversion <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#existential-judgment" class="router-link-active router-link-exact-active sidebar-item" aria-label="Existential Judgment"><!--[--><!--]--> Existential Judgment <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#vague-search" class="router-link-active router-link-exact-active sidebar-item" aria-label="Vague Search"><!--[--><!--]--> Vague Search <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#member-extensions" class="router-link-active router-link-exact-active sidebar-item" aria-label="Member Extensions"><!--[--><!--]--> Member Extensions <!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#find-and-reflection" class="router-link-active router-link-exact-active sidebar-item" aria-label="Find and Reflection"><!--[--><!--]--> Find and Reflection <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#optional-find-conditions" class="router-link-active router-link-exact-active sidebar-item" aria-label="Optional Find Conditions"><!--[--><!--]--> Optional Find Conditions <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#find-in-super-class" class="router-link-active router-link-exact-active sidebar-item" aria-label="Find in Super Class"><!--[--><!--]--> Find in Super Class <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#vague-find" class="router-link-active router-link-exact-active sidebar-item" aria-label="Vague Find"><!--[--><!--]--> Vague Find <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#multiple-find" class="router-link-active router-link-exact-active sidebar-item" aria-label="Multiple Find"><!--[--><!--]--> Multiple Find <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#static-bytecode" class="router-link-active router-link-exact-active sidebar-item" aria-label="Static Bytecode"><!--[--><!--]--> Static Bytecode <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#obfuscated-bytecode" class="router-link-active router-link-exact-active sidebar-item" aria-label="Obfuscated Bytecode"><!--[--><!--]--> Obfuscated Bytecode <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#directly-called" class="router-link-active router-link-exact-active sidebar-item" aria-label="Directly Called"><!--[--><!--]--> Directly Called <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#original-called" class="router-link-active router-link-exact-active sidebar-item" aria-label="Original Called"><!--[--><!--]--> Original Called <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#find-again" class="router-link-active router-link-exact-active sidebar-item" aria-label="Find Again"><!--[--><!--]--> Find Again <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#relative-matching" class="router-link-active router-link-exact-active sidebar-item" aria-label="Relative Matching"><!--[--><!--]--> Relative Matching <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#calling-generics" class="router-link-active router-link-exact-active sidebar-item" aria-label="Calling Generics"><!--[--><!--]--> Calling Generics <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#pay-attention-of-trap" class="router-link-active router-link-exact-active sidebar-item" aria-label="Pay Attention of Trap"><!--[--><!--]--> Pay Attention of Trap <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a aria-current="page" href="/YukiHookAPI/en/api/special-features/reflection.html#common-type-extensions" class="router-link-active router-link-exact-active sidebar-item" aria-label="Common Type Extensions"><!--[--><!--]--> Common Type Extensions <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a href="/YukiHookAPI/en/api/special-features/logger.html" class="sidebar-item" aria-label="Debug Logs"><!--[--><!--]--> Debug Logs <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/special-features/xposed-storage.html" class="sidebar-item" aria-label="Xposed Module Data Storage"><!--[--><!--]--> Xposed Module Data Storage <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/special-features/xposed-channel.html" class="sidebar-item" aria-label="Xposed Module and Host Channel"><!--[--><!--]--> Xposed Module and Host Channel <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/special-features/host-lifecycle.html" class="sidebar-item" aria-label="Host Lifecycle Extension"><!--[--><!--]--> Host Lifecycle Extension <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/api/special-features/host-inject.html" class="sidebar-item" aria-label="Host Resource Injection Extension"><!--[--><!--]--> Host Resource Injection Extension <!--[--><!--]--></a><!----></li><!--]--></ul></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item sidebar-heading collapsible">About <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/en/about/changelog.html" class="sidebar-item" aria-label="Changelog"><!--[--><!--]--> Changelog <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/about/future.html" class="sidebar-item" aria-label="Looking for Future"><!--[--><!--]--> Looking for Future <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/about/contacts.html" class="sidebar-item" aria-label="Contact Us"><!--[--><!--]--> Contact Us <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/en/about/about.html" class="sidebar-item" aria-label="About this Document"><!--[--><!--]--> About this Document <!--[--><!--]--></a><!----></li><!--]--></ul></li><!--]--></ul><!--[--><!--]--></aside><!--]--><!--[--><main class="page"><!--[--><!--]--><div class="theme-default-content"><!--[--><!--]--><div><h1 id="reflection-extensions" tabindex="-1"><a class="header-anchor" href="#reflection-extensions" aria-hidden="true">#</a> Reflection Extensions</h1><blockquote><p><code>YukiHookAPI</code> 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.</p></blockquote><h2 id="class-extensions" tabindex="-1"><a class="header-anchor" href="#class-extensions" aria-hidden="true">#</a> Class Extensions</h2><blockquote><p>Here are the extension functions related to the <strong>Class</strong> object itself.</p></blockquote><h3 id="object-conversion" tabindex="-1"><a class="header-anchor" href="#object-conversion" aria-hidden="true">#</a> Object Conversion</h3><p>Suppose we want to get a <code>Class</code> that cannot be called directly.</p><p>Normally, we can use the standard reflection API to find this <code>Class</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Class in the default ClassLoader environment</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Class</span><span style="color:#ADBAC7;">.forName(</span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#768390;">// Specify the Class in the ClassLoader environment</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> custom</span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;">.loadClass(</span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This is probably not very friendly, and <code>YukiHookAPI</code> provides you with a syntactic sugar that can be used anywhere.</p><p>The above writing can be written as <code>YukiHookAPI</code> as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Get this Class directly</span></span>
|
||
<span class="line"><span style="color:#768390;">// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClass()</span></span>
|
||
<span class="line"><span style="color:#768390;">// ClassLoader where the custom Class is located</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClass(customClassLoader)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If the current <code>Class</code> does not exist, using the above method will throw an exception.</p><p>If you are not sure whether the <code>Class</code> exists, you can refer to the following solutions.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Get this Class directly</span></span>
|
||
<span class="line"><span style="color:#768390;">// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader</span></span>
|
||
<span class="line"><span style="color:#768390;">// If not available, the result will be null but no exception will be thrown</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClassOrNull()</span></span>
|
||
<span class="line"><span style="color:#768390;">// ClassLoader where the custom Class is located</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
||
<span class="line"><span style="color:#768390;">// If not available, the result will be null but no exception will be thrown</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClassOrNull(customClassLoader)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We can also get an existing <code>Class</code> object by mapping.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this Class can be obtained directly</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> classOf</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Test</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// We can also customize the ClassLoader where the Class is located, which is very effective for stubs</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> classOf</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Test</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">(customClassLoader)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#classof-method">classOf</a>, <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#string-toclass-ext-method">String.toClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#string-toclassornull-ext-method">String.toClassOrNull</a>, <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#string-variousclass-toclass-i-ext-method">PackageParam → String+ VariousClass.toClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#string-variousclass-toclassornull-i-ext-method">PackageParam → String+VariousClass.toClassOrNull</a> methods.</p></div><h3 id="existential-judgment" tabindex="-1"><a class="header-anchor" href="#existential-judgment" aria-hidden="true">#</a> Existential Judgment</h3><p>Suppose we want to determine whether a <code>Class</code> exists.</p><p>Usually, we can use the standard reflection API to find this <code>Class</code> to determine whether it exists by exception.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Class in the default ClassLoader environment</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> isExist </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">try</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Class</span><span style="color:#ADBAC7;">.forName(</span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">} </span><span style="color:#F47067;">catch</span><span style="color:#ADBAC7;"> (_</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Throwable</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">false</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"><span style="color:#768390;">// Specify the Class in the ClassLoader environment</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> isExist </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">try</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> custom</span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;">.loadClass(</span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">} </span><span style="color:#F47067;">catch</span><span style="color:#ADBAC7;"> (_</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Throwable</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">false</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This is probably not very friendly, and <code>YukiHookAPI</code> provides you with a syntactic sugar that can be used anywhere.</p><p>The above writing can be written as <code>YukiHookAPI</code> as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Check if this class exists</span></span>
|
||
<span class="line"><span style="color:#768390;">// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> isExist </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.hasClass()</span></span>
|
||
<span class="line"><span style="color:#768390;">// ClassLoader where the custom Class is located</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> isExist </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.hasClass(customClassLoader)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#string-hasclass-ext-method">String.hasClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#string-hasclass-i-ext-method">PackageParam → String.hasClass</a> methods.</p></div><h3 id="vague-search" tabindex="-1"><a class="header-anchor" href="#vague-search" aria-hidden="true">#</a> Vague Search <span class="badge tip" style="vertical-align:middle;"><!--[-->Beta<!--]--></span></h3><p>The <code>Class</code> name in the Host App's <strong>Dex</strong> after being obfuscated by tools such as R8 will be difficult to distinguish.</p><p>Its correct position is uncertain, and cannot be obtained directly through <a href="#object-conversion">Object Conversion</a>.</p><p>At this point, there is <code>DexClassFinder</code>, its role is to determine the instance of this <code>Class</code> by the bytecode features in the <code>Class</code> that need to be searched.</p><div class="custom-container warning"><p class="custom-container-title">Notice</p><p>At present, the function of <strong>DexClassFinder</strong> is still in the experimental stage.</p><p>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 <strong>Class</strong>.</p><p>If something got wrong welcome to feedback.</p><p>Since it is a reflection-level API, currently it can only locate the specified <strong>Class</strong> through the characteristics of <strong>Class and Member</strong>, and cannot locate it by specifying the string and method content characteristics in the bytecode.</p><p>The speed of searching <strong>Class</strong> depends on the performance of the current device.</p><p>At present, the mainstream mobile processors are in the <strong>3~10s</strong> range when the conditions are not complicated in the <strong>10~15w</strong> number of <strong>Class</strong>, the fastest speed can reach within <strong>25s</strong> under slightly complex conditions.</p><p>Please note that the more the same type <strong>Class</strong> is matched, the slower the speed.</p></div><h4 id="get-started" tabindex="-1"><a class="header-anchor" href="#get-started" aria-hidden="true">#</a> Get Started</h4><p>Below is a simple usage example.</p><p>Suppose the following <code>Class</code> is what we want, the names are obfuscated and may be different in each version.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">package</span><span style="color:#ADBAC7;"> com.demo;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">a</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">extends</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">Activity</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">implements</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">Serializable</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">a;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">b;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">boolean</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">a;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">protected</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(Bundle </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">(</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">, String </span><span style="color:#F69D50;">var2</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">(</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">a</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">var2</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">b</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">var3</span><span style="color:#ADBAC7;">, String </span><span style="color:#F69D50;">var4</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><p>At this point, we want to get this <code>Class</code>, you can use the <code>ClassLoader.searchClass</code> method directly.</p><p>In <code>PackageParam</code> you can use the <code>searchClass</code> method directly and it will automatically specify the <code>appClassLoader</code>.</p><p>Each of the conditions demonstrated below is optional, and the more complex the conditions, the more accurate the positioning and the worse the performance.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">searchClass {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Start the search from the specified package name range</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// In actual use, you can specify multiple package name ranges at the same time</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> from(</span><span style="color:#96D0FF;">"com.demo"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the result of getSimpleName of the current Class</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You can directly make logical judgments on this string</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Here we are not sure whether its name is a, we can only judge the length of the string</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> simpleName { it.length </span><span style="color:#F47067;">==</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the inherited parent class object</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// If it is an existing stub, it can be directly represented by generics</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> extends</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Activity</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the inherited parent class object</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Which can be written directly as the full class name</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And you can also specify multiple objects at the same time</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> extends(</span><span style="color:#96D0FF;">"android.app.Activity"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the implemented interface</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// If it exists stub, can be directly represented by generics</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> implements</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Serializable</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the implemented interface</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Which can be written directly as a full class name, or you can specify multiple at the same time</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> implements(</span><span style="color:#96D0FF;">"java.io.Serializable"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the constructor</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number count that exists in the current class</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;"> { param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">) }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the variable</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number that exists in the current class count</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> field { type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the variable</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number that exists in the current class count</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> field { type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Directly specify the number of all variables that exist in the current class count</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> field().count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// If you think the number of variables is indeterminate</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You can also use the following custom conditions</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> field().count(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> field().count { it </span><span style="color:#F47067;">>=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number that exists in the current class count</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"onCreate"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BundleClass</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the modifier, and the number count in the current class</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> modifiers { isStatic </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> isPrivate }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">UnitType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the modifier, and the number count in the current class</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> modifiers { isPrivate </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> isStatic.</span><span style="color:#F47067;">not</span><span style="color:#ADBAC7;">() }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the modifier, and the number count in the current class</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> modifiers { isPrivate </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> isStatic.</span><span style="color:#F47067;">not</span><span style="color:#ADBAC7;">() }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">UnitType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// As well as the modifier and VagueType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number count that exists in the current class</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> modifiers { isPrivate </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> isStatic.</span><span style="color:#F47067;">not</span><span style="color:#ADBAC7;">() }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">VagueType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">VagueType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">UnitType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Directly specify the number of all methods that exist in the current class count</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method().count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">5</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// If you think the number of methods is uncertain, you can also use the following custom conditions</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method().count(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">5</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method().count { it </span><span style="color:#F47067;">>=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">5</span><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Directly specify the number of all members existing in the current class count</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Members include: Field, Method, Constructor</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> member().count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">9</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// There must be a static modifier in all members, you can add this condition like this</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> member {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> modifiers { isStatic }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get() </span><span style="color:#768390;">// Get the instance of this Class itself, if not found, it will return null</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>The conditional usage of <strong>Field</strong>, <strong>Method</strong>, <strong>Constructor</strong> in the above usage is consistent with the related usage in <a href="#member-extensions">Member Extensions</a>, with only minor differences.</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules">MemberRules</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules">FieldRules</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules">MethodRules</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules">ConstructorRules</a>.</p></div><h4 id="asynchronous-search" tabindex="-1"><a class="header-anchor" href="#asynchronous-search" aria-hidden="true">#</a> Asynchronous Search</h4><p>By default, <code>DexClassFinder</code> will use synchronous mode to search <code>Class</code>, which will block the current thread until it finds or finds an exception.</p><p>If the search takes too long, it may cause <strong>ANR</strong> problems to the Host App.</p><p>In response to the above problems, we can enable asynchronous, just add the parameter <code>async = true</code>, which will not require you to start a thread again, the API has already handled the related problems for you.</p><div class="custom-container warning"><p class="custom-container-title">Notice</p><p>For the asynchronous case you need to use the <strong>wait</strong> method to get the result, the <strong>get</strong> method will no longer work.</p></div><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">searchClass(async </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.wait { class1 </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get asynchronous result</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">searchClass(async </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.wait { class2 </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get asynchronous result</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>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.</p><h4 id="local-cache" tabindex="-1"><a class="header-anchor" href="#local-cache" aria-hidden="true">#</a> Local Cache</h4><p>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.</p><p>At this point, we can locally cache the search results of the current Host App's version by specifying the <code>name</code> parameter.</p><p>Next time, the found class name will be directly read from the local cache.</p><p>The local cache uses <code>SharedPreferences</code>, which will be saved to the Host App's data directory and will be re-cached after the Host App's version is updated.</p><p>After enabling the local cache, <code>async = true</code> will be set at the same time, you don't need to set it manually.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">searchClass(name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.class1"</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.wait { class1 </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get asynchronous result</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">searchClass(name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.class2"</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.wait { class2 </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get asynchronous result</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>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.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Call it directly</span></span>
|
||
<span class="line"><span style="color:#768390;">// It may fail when the Host App's appContext is null, and a warning message will be printed on failure</span></span>
|
||
<span class="line"><span style="color:#F69D50;">DexClassFinder</span><span style="color:#ADBAC7;">.clearCache()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Called after listening to the lifecycle of the Host App</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">onAppLifecycle {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> onCreate {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">DexClassFinder</span><span style="color:#ADBAC7;">.clearCache(context </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">this</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>You can also clear the Host App's cache for a specific version.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Call it directly</span></span>
|
||
<span class="line"><span style="color:#768390;">// It may fail when the Host App's appContext is null, and a warning message will be printed on failure</span></span>
|
||
<span class="line"><span style="color:#F69D50;">DexClassFinder</span><span style="color:#ADBAC7;">.clearCache(versionName </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"1.0"</span><span style="color:#ADBAC7;">, versionCode </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#768390;">// Called after listening to the lifecycle of the Host App</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">onAppLifecycle {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> onCreate {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">DexClassFinder</span><span style="color:#ADBAC7;">.clearCache(context </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">this</span><span style="color:#ADBAC7;">, versionName </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"1.0"</span><span style="color:#ADBAC7;">, versionCode </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="multiple-search" tabindex="-1"><a class="header-anchor" href="#multiple-search" aria-hidden="true">#</a> Multiple Search</h4><p>If you need to search a set of <code>Class</code> at the same time using a fixed condition, then you only need to use the <code>all</code> or <code>waitAll</code> method to get the result.</p><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Synchronous search, use all to get all the results found by the conditions</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">searchClass {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.all().forEach { clazz </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get each result</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"><span style="color:#768390;">// Synchronous search, using all { ... } to iterate over each result</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">searchClass {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.all { clazz </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get each result</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"><span style="color:#768390;">// Asynchronous search, use waitAll to get all the results found by the conditions</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">searchClass(async </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.waitAll { classes </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> classes.forEach {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get each result</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#classloader-searchclass-ext-method">ClassLoader.searchClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#searchclass-method">PackageParam.searchClass</a> methods.</p></div><h2 id="member-extensions" tabindex="-1"><a class="header-anchor" href="#member-extensions" aria-hidden="true">#</a> Member Extensions</h2><blockquote><p>Here are the extension functions related to the <strong>Class</strong> bytecode member variables <strong>Field</strong>, <strong>Method</strong>, <strong>Constructor</strong>.</p></blockquote><div class="custom-container tip"><p class="custom-container-title">Tips</p><p><strong>Member</strong> is the interface description object of <strong>Field</strong>, <strong>Method</strong>, <strong>Constructor</strong>, which is the general term for the bytecode members in <strong>Class</strong> in Java reflection.</p></div><p>Suppose there is such a <code>Class</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">package</span><span style="color:#ADBAC7;"> com.demo;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BaseTest</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">BaseTest</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">BaseTest</span><span style="color:#ADBAC7;">(</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">isInit</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doBaseTask</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">package</span><span style="color:#ADBAC7;"> com.demo;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">extends</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">BaseTest</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">Test</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">Test</span><span style="color:#ADBAC7;">(</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">isInit</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> TAG </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"Test"</span><span style="color:#ADBAC7;">;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> BaseTest</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">baseInstance;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">a;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">boolean</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">a;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">boolean</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">isTaskRunning</span><span style="color:#F69D50;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">false</span><span style="color:#ADBAC7;">;</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">init</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">release</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">, Function<</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;">, </span><span style="color:#F47067;">String</span><span style="color:#ADBAC7;">> </span><span style="color:#F69D50;">task</span><span style="color:#ADBAC7;">, </span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">isFinish</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">stop</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String </span><span style="color:#DCBDFB;">getName</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">b</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">b</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">a</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><h3 id="find-and-reflection" tabindex="-1"><a class="header-anchor" href="#find-and-reflection" aria-hidden="true">#</a> Find and Reflection</h3><p>Suppose we want to get the <code>doTask</code> method of <code>Test</code> and execute it.</p><p>Normally, we can use the standard reflection API to find this method.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using reflection API</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .getDeclaredMethod(</span><span style="color:#96D0FF;">"doTask"</span><span style="color:#ADBAC7;">, String::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#6CB6FF;">apply</span><span style="color:#ADBAC7;"> { isAccessible </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .invoke(instance, </span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This is probably not very friendly, and <code>YukiHookAPI</code> provides you with a syntactic sugar that can be used anywhere.</p><p>The above writing can be written as <code>YukiHookAPI</code> as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more features, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder">MethodFinder</a>.</p></div><p>Similarly, we need to get the <code>isTaskRunning</code> field can also be written as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"isTaskRunning"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).any() </span><span style="color:#768390;">// Any instantiates an object of any type of Field</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more features, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder">FieldFinder</a>.</p></div><p>Maybe you also want to get the current <code>Class</code> constructor, the same can be achieved.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.</span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().call(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) </span><span style="color:#768390;">// Can create a new instance</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you want to get the no-argument constructor of <code>Class</code>, you can write it as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.</span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;">().get().call() </span><span style="color:#768390;">// Create a new instance</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more features, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder">ConstructorFinder</a>.</p></div><h3 id="optional-find-conditions" tabindex="-1"><a class="header-anchor" href="#optional-find-conditions" aria-hidden="true">#</a> Optional Find Conditions</h3><p>Suppose we want to get the <code>getName</code> method in <code>Class</code>, which can be implemented as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getName"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).string() </span><span style="color:#768390;">// Get the result of the method</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Through observation, it is found that there is only one method named <code>getName</code> in this <code>Class</code>, so can we make it simpler?</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getName"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).string() </span><span style="color:#768390;">// Get the result of the method</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Yes, you can refine your find criteria for methods that do not change exactly.</p><p>When using only <code>get</code> or <code>wait</code> methods to get results, <code>YukiHookAPI</code> <strong>will match the first found result in bytecode order</strong> by default.</p><p>The problem comes again, this <code>Class</code> has a <code>release</code> method, but its method parameters are very long, and some types may not be directly available.</p><p>Normally we would use <code>param(...)</code> to find this method, but is there an easier way.</p><p>At this point, after determining the uniqueness of the method, you can use <code>paramCount</code> to find the method.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"release"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// At this point</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// We don't have to determine the specific type of method parameters, just write the number</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> paramCount </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">3</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance) </span><span style="color:#768390;">// Get this method</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Although the above example can be successfully matched, it is not accurate.</p><p>At this time, you can also use <code>VagueType</code> to fill in the method parameter type that you do not want to fill in.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"release"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Use VagueType to fill in the type you don't want to fill in</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// While ensuring that other types can match</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">VagueType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance) </span><span style="color:#768390;">// Get this method</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="find-in-super-class" tabindex="-1"><a class="header-anchor" href="#find-in-super-class" aria-hidden="true">#</a> Find in Super Class</h3><p>You will notice that <code>Test</code> extends <code>BaseTest</code>, now we want to get the <code>doBaseTask</code> method of <code>BaseTest</code>, how do we do it without knowing the name of the super class?</p><p>Referring to the above find conditions, we only need to add a <code>superClass</code> to the find conditions to achieve this function.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Just add this condition</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> superClass()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>At this time, we can get this method in the super class.</p><p><code>superClass</code> has a parameter <code>isOnlySuperClass</code>, when set to <code>true</code>, you can skip the current <code>Class</code> and only find the super class of the current <code>Class</code>.</p><p>Since we now know that the <code>doBaseTask</code> method only exists in the super class, this condition can be added to save finding time.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Add a find condition</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> superClass(isOnlySuperClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>At this time, we can also get this method in the super class.</p><p>Once <code>superClass</code> 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 <code>java.lang.Object</code>).</p><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#superclass-method">MethodFinder.superClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#superclass-method">ConstructorFinder.superClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder#superclass-method">FieldFinder.superClass</a> methods.</p></div><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>The currently founded <strong>Method</strong> can only find the <strong>Method</strong> of the current <strong>Class</strong> unless the <strong>superClass</strong> condition is specified, which is the default behavior of the Java Reflection API.</p></div><h3 id="vague-find" tabindex="-1"><a class="header-anchor" href="#vague-find" aria-hidden="true">#</a> Vague Find</h3><p>If we want to find a method name, but are not sure if it has changed in each release, we can use vague find.</p><p>Suppose we want to get the <code>doTask</code> method in <code>Class</code>, which can be implemented as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Set name is case insensitive</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> it.equals(</span><span style="color:#96D0FF;">"dotask"</span><span style="color:#ADBAC7;">, isIgnoreCase </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Knowing that there is currently only one <code>doTask</code> method in <code>Class</code>, we can also judge that the method name contains only the characters specified in it.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Only contains oTas</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> it.contains(</span><span style="color:#96D0FF;">"oTas"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We can also judge based on the first and last strings.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Contains do at the beginning and Task at the end</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> it.startsWith(</span><span style="color:#96D0FF;">"do"</span><span style="color:#ADBAC7;">) </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> it.endsWith(</span><span style="color:#96D0FF;">"Task"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>By observing that this method name contains only letters, we can add a precise search condition.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Start with do, end with Task, just letters</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> it.startsWith(</span><span style="color:#96D0FF;">"do"</span><span style="color:#ADBAC7;">) </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> it.endsWith(</span><span style="color:#96D0FF;">"Task"</span><span style="color:#ADBAC7;">) </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> it.isOnlyLetters()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>Use <strong>name { ... }</strong> to create a conditional method body, where the variable <strong>it</strong> is the string of the current name, and you can freely use it in the extension method of <strong>NameRules</strong> function.</p><p>The condition at the end of the method body needs to return a <strong>Boolean</strong>, which is the final condition judgment result.</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules">NameRules</a>.</p></div><h3 id="multiple-find" tabindex="-1"><a class="header-anchor" href="#multiple-find" aria-hidden="true">#</a> Multiple Find</h3><p>Sometimes, we may need to find a set of methods, constructors, and fields with the same characteristics in a <code>Class</code>.</p><p>At this time, we can use relative condition matching to complete.</p><p>Based on the result of the find condition, we only need to replace <code>get</code> with <code>all</code> to get all the bytecodes that match the condition.</p><p>Suppose this time we want to get all methods in <code>Class</code> with the number of method parameters in the range <code>1..3</code>, you can use the following implementation.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.all(instance).forEach { instance </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Call and execute each method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> instance.call(...)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The above example can be perfectly matched to the following 3 methods.</p><p><code>private void doTask(String taskName)</code></p><p><code>private void release(String taskName, Function<boolean, String> task, boolean isFinish)</code></p><p><code>private void b(String a)</code></p><p>If you want to define the conditions for the range of the number of parameters more freely, you can use the following implementation.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> paramCount { it </span><span style="color:#F47067;"><</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.all(instance).forEach { instance </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Call and execute each method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> instance.call(...)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The above example can be perfectly matched to the following 6 methods.</p><p><code>private static void init()</code></p><p><code>private void doTask(String taskName)</code></p><p><code>private void stop(String a)</code></p><p><code>private void getName(String a)</code></p><p><code>private void b()</code></p><p><code>private void b(String a)</code></p><p>By observing that there are two methods named <code>b</code> in <code>Class</code>, you can use the following implementation.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHook API</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"b"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.all(instance).forEach { instance </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Call and execute each method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> instance.call(...)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The above example can be perfectly matched to the following 2 methods.</p><p><code>private void b()</code></p><p><code>private void b(String a)</code></p><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>Use <strong>paramCount { ... }</strong> to create a conditional method body, where the variable <strong>it</strong> is the integer of the current number of parameters, and you can use it freely in the extension method of <strong>CountRules</strong> function in it.</p><p>The condition at the end of the method body needs to return a <strong>Boolean</strong>, which is the final condition judgment result.</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules">CountRules</a>.</p></div><h3 id="static-bytecode" tabindex="-1"><a class="header-anchor" href="#static-bytecode" aria-hidden="true">#</a> Static Bytecode</h3><p>Some methods and fields are statically implemented in <code>Class</code>, at this time, we can call them without passing in an instance.</p><p>Suppose we want to get the contents of the static field <code>TAG</code> this time.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"TAG"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().string() </span><span style="color:#768390;">// The type of Field is string and can be cast directly</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Assuming that there is a non-static <code>TAG</code> field with the same name in <code>Class</code>, what should I do at this time?</p><p>Just add a filter.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"TAG"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// This field to identify the lookup needs to be static</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> modifiers { isStatic }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().string() </span><span style="color:#768390;">// The type of Field is string and can be cast directly</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We can also call a static method called <code>init</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"init"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Likewise, you can identify it as a static.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"init"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// This method of identity find needs to be static</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> modifiers { isStatic }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>Use <strong>modifiers { ... }</strong> to create a conditional method body, at which point you can freely use its functionality in <strong>ModifierRules</strong>.</p><p>The condition at the end of the method body needs to return a <strong>Boolean</strong>, which is the final condition judgment result.</p><p>For more features, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules">ModifierRules</a>.</p></div><h3 id="obfuscated-bytecode" tabindex="-1"><a class="header-anchor" href="#obfuscated-bytecode" aria-hidden="true">#</a> Obfuscated Bytecode</h3><p>You may have noticed that the example <code>Class</code> given here has two obfuscated field names, both of which are <code>a</code>, how do we get them at this time?</p><p>There are two options.</p><p>The first option is to determine the name and type of the field.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"a"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).any() </span><span style="color:#768390;">// Get a field named a with type Boolean</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The second option is to determine where the type of the field is located.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">).index().first()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).any() </span><span style="color:#768390;">// Get the first field of type Boolean</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>In the above two cases, the corresponding field <code>private boolean a</code> can be obtained.</p><p>Likewise, there are two obfuscated method names in this <code>Class</code>, both of which are <code>b</code>.</p><p>You can also have two options to get them.</p><p>The first option is to determine the method name and method parameters.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"b"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"test_string"</span><span style="color:#ADBAC7;">) </span><span style="color:#768390;">// Get the method whose name is b and whose parameter is [String]</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The second option is to determine where the parameters of the method are located.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">).index().first()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"test_string"</span><span style="color:#ADBAC7;">) </span><span style="color:#768390;">// Get the method whose first method parameter is [String]</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Since it is observed that this method is last in <code>Class</code>, then we have an alternative.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> order().index().last()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"test_string"</span><span style="color:#ADBAC7;">) </span><span style="color:#768390;">// Get the last method of the current Class</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container warning"><p class="custom-container-title">Notice</p><p>Please try to avoid using <strong>order</strong> to filter bytecode subscripts, they may be indeterminate unless you are sure that its position in this <strong>Class</strong> must not change.</p></div><h3 id="directly-called" tabindex="-1"><a class="header-anchor" href="#directly-called" aria-hidden="true">#</a> Directly Called</h3><p>The methods of calling bytecode described above all need to use <code>get(instance)</code> to call the corresponding method.</p><p>Is there a simpler way?</p><p>At this point, you can use the <code>current</code> method on any instance to create a call space.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Assume this Class is not directly available</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">instance.current {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Execute the doTask method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Execute the stop method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"stop"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get name</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> method { name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getName"</span><span style="color:#ADBAC7;"> }.string()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We can also use <code>superClass</code> to call methods of the current <code>Class</code> super class.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Assume this Class is not directly available</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">instance.current {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Execute the doBaseTask method of the parent class</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> superClass().method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you don't like to use a lambda to create the namespace of the current instance, you can use the <code>current()</code> method directly.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assuming this is an instance of this Class, this Class cannot be obtained directly</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Execute the doTask method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">instance</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .current()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#768390;">// Execute the stop method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">instance</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .current()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"stop"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Get name</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> instance.current().method { name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getName"</span><span style="color:#ADBAC7;"> }.string()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Likewise, consecutive calls can be made between them, but <u><strong>inline calls are not allowed</strong></u>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Assume this Class is not directly available</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">instance.current {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.current()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"stop"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call()</span></span>
|
||
<span class="line"><span style="color:#768390;">// ❗ Note that because current() returns the CurrentClass object itself</span></span>
|
||
<span class="line"><span style="color:#768390;">// It CANNOT BE CALLED like the following</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">instance.current().current()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>For <code>Field</code> instances, there is also a convenience method that can directly get the object of the instance where <code>Field</code> is located.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Assume this Class is not directly available</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">instance.current {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Plan 1></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"baseInstance"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.current {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Plan 2></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"baseInstance"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.current()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> ?.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }?.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container warning"><p class="custom-container-title">Notice</p><p>The above <strong>current</strong> method is equivalent to calling the <strong>field { ... }.any()?.current()</strong> method in <strong>CurrentClass</strong> for you.</p><p>If there is no <strong>CurrentClass</strong> calling field, you need to use <strong>field { ... }.get(instance).current()</strong> to call it.</p></div><p>The problem comes again, I want to use reflection to create the following instance and call the method in it, how to do it?</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">).doTask(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>Usually, we can use the standard reflection API to call.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClass()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .getDeclaredConstructor(Boolean::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#6CB6FF;">apply</span><span style="color:#ADBAC7;"> { isAccessible </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .newInstance(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#6CB6FF;">apply</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> javaClass</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .getDeclaredMethod(</span><span style="color:#96D0FF;">"doTask"</span><span style="color:#ADBAC7;">, String::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#6CB6FF;">apply</span><span style="color:#ADBAC7;"> { isAccessible </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> .invoke(</span><span style="color:#6CB6FF;">this</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>But I feel that this approach is very troublesome.</p><p>Is there a more concise way to call it?</p><p>At this time, we can also use the <code>buildOf</code> method to create an instance.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClass().buildOf(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) { param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">) }?.current {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you want the <code>buildOf</code> method to return the type of the current instance, you can include a type-generic declaration in it instead of using <code>as</code> to <code>cast</code> the target type.</p><p>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.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this Class can be obtained directly</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> test </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.buildOf</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Test</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) { param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">) }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">test.doTask(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/bean/CurrentClass">CurrentClass</a> and <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#class-buildof-ext-method">Class.buildOf</a> method.</p></div><h3 id="original-called" tabindex="-1"><a class="header-anchor" href="#original-called" aria-hidden="true">#</a> Original Called</h3><p>If you are using reflection to call a method that has been hooked, how do we call its original method?</p><p>The native <code>XposedBridge</code> provides us with a <code>XposedBridge.invokeOriginalMethod</code> function.</p><p>Now, in <code>YukiHookAPI</code> you can use the following method to implement this function conveniently.</p><p>Suppose below is the <code>Class</code> we want to demonstrate.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> String </span><span style="color:#DCBDFB;">getString</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">return</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"Original"</span><span style="color:#ADBAC7;">;</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><p>Here's how the <code>getString</code> method in this <code>Class</code> Hooks.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.hook {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> injectMember {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getString"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> replaceTo(</span><span style="color:#96D0FF;">"Hooked"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>At this point, we use reflection to call this method, and we will get the result of Hook <code>"Hooked"</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Result will be "Hooked"</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> result </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getString"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().string()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If we want to get the original method and result of this method without hooking, we just need to add <code>original</code> to the result.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Result will be "Original"</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> result </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getString"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().original().string()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to the <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#original-method">MethodFinder.Result.original</a> method.</p></div><h3 id="find-again" tabindex="-1"><a class="header-anchor" href="#find-again" aria-hidden="true">#</a> Find Again</h3><p>Suppose there are three different versions of <code>Class</code>, all of which are the same <code>Class</code> for different versions of this Host App.</p><p>There is also a method <code>doTask</code> in it, assuming they function the same.</p><blockquote><p>The following example of version A</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><blockquote><p>The following example of version B</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><blockquote><p>The following example of version C</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">, </span><span style="color:#F47067;">int</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">type</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><p>We need to get this same functionality of the <code>doTask</code> method in a different version, how do we do it?</p><p>At this point, you can use <code>RemedyPlan</code> to complete your needs.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.remedys {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.onFind {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Found logic can be implemented here</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">IntType</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.onFind {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Found logic can be implemented here</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.wait(instance) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the result of the method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>The method lookup result using <strong>RemedyPlan</strong> can no longer use <strong>get</strong> to get method instance, you should use <strong>wait</strong> method.</p></div><p>Also, you can continue to use <code>RemedyPlan</code> while using <a href="#multiple-find">Multiple Find</a>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
||
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.remedys {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">0</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.onFind {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Found logic can be implemented here</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.onFind {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Found logic can be implemented here</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.waitAll(instance) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the result of the method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Take the current <code>Class</code> as an example, if <a href="#multiple-find">Multiple Find</a> is used in conjunction with <code>RemedyPlan</code> when creating a Hook, you need to change the usage slightly.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">injectMember {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.remedys {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">0</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }.all()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> beforeHook {}</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> afterHook {}</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>When creating a Hook, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#all-method">MethodFinder.Process.all</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#all-method">ConstructorFinder.Process.all</a> methods.</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#remedyplan-class">MethodFinder.RemedyPlan</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#remedyplan-class">ConstructorFinder.RemedyPlan</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder#remedyplan-class">FieldFinder.RemedyPlan</a> .</p></div><h3 id="relative-matching" tabindex="-1"><a class="header-anchor" href="#relative-matching" aria-hidden="true">#</a> Relative Matching</h3><p>Suppose there is a <code>Class</code> with the same function in different versions of the Host App but only the name of the <code>Class</code> is different.</p><blockquote><p>The following example of version A</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ATest</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><blockquote><p>The following example of version B</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BTest</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><p>At this time, what should we do if we want to call the <code>doTask</code> method in this <code>Class</code> in each version?</p><p>The usual practice is to check if <code>Class</code> exists.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// First find this Class</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> currentClass </span><span style="color:#F47067;">=</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">if</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">.hasClass()) </span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">.toClass() </span><span style="color:#F47067;">else</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">.toClass()</span></span>
|
||
<span class="line"><span style="color:#768390;">// Then look for this method and call</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">currentClass.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>I feel that this solution is very inelegant and cumbersome, then <code>YukiHookAPI</code> provides you with a very convenient <code>VariousClass</code> to solve this problem.</p><p>Now, you can get this <code>Class</code> directly using the following methods.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).get().method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If the current <code>Class</code> exists in the specified <code>ClassLoader</code>, you can fill in your <code>ClassLoader</code> in <code>get</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).get(customClassLoader).method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you are not sure that all <code>Class</code> will be matched, you can use the <code>getOrNull</code> method.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
||
<span class="line"><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).getOrNull(customClassLoader)?.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}?.get()?.call()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you are using the <code>Class</code> of the (Xposed) Host environment in <code>PackageParam</code>, you can use <code>toClass()</code> to set it directly.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).toClass().method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/bean/VariousClass">VariousClass</a>.</p></div><p>If it is used when creating a Hook, it can be more convenient, and it can also automatically intercept the exception that <code>Class</code> cannot be found.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">findClass(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).hook {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Your code here.</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>You can also define this <code>Class</code> as a constant type to use.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Define constant type</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ABTestClass</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#768390;">// Use directly</span></span>
|
||
<span class="line"><span style="color:#F69D50;">ABTestClass</span><span style="color:#ADBAC7;">.hook {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Your code here.</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to the <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#findclass-method">PackageParam.findClass</a> method.</p></div><h3 id="calling-generics" tabindex="-1"><a class="header-anchor" href="#calling-generics" aria-hidden="true">#</a> Calling Generics</h3><p>In the process of reflection, we may encounter generic problems.</p><p>In the reflection processing of generics, <code>YukiHookAPI</code> also provides a syntactic sugar that can be used anywhere.</p><p>For example we have the following generic class.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TestGeneric</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">T</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">R</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;"> (t</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">T</span><span style="color:#ADBAC7;">, r</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">R</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>When we want to get a <code>Class</code> instance of the generic <code>T</code> or <code>R</code> in the current <code>Class</code>, only the following implementation is required.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TestGeneric</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">T</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">R</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;"> (t</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">T</span><span style="color:#ADBAC7;">, r</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">R</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the operation object of the current instance</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the Class instance of T, in the 0th position of the parameter</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// The default value can not be written</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> tClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> current().generic()?.argument()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the Class instance of R, in parameter 1</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> rClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> current().generic()?.argument(index </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You can also use the following syntax</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> current().generic {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the Class instance of T</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// In the 0th position of the parameter, the default value can be left blank</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> tClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> argument()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the Class instance of R, in parameter 1</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> rClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> argument(index </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>When we want to call this <code>Class</code> externally, it can be implemented as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is the Class of T</span></span>
|
||
<span class="line"><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TI</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"><span style="color:#768390;">// Assume this is an instance of T</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> tInstance</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TI</span><span style="color:#ADBAC7;">? </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ...</span></span>
|
||
<span class="line"><span style="color:#768390;">// Get the Class instance of T</span></span>
|
||
<span class="line"><span style="color:#768390;">// In the 0th position of the parameter, the default value can be left blank</span></span>
|
||
<span class="line"><span style="color:#768390;">// And get the method foo and call it</span></span>
|
||
<span class="line"><span style="color:#F69D50;">TestGeneric</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.generic()?.argument()?.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"foo"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}?.get(tInstance)?.invoke</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">TI</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/bean/CurrentClass#generic-method">CurrentClass.generic</a>, <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#class-generic-ext-method">Class.generic</a> methods and <a href="../public/com/highcapable/yukihookapi/hook/bean/GenericClass">GenericClass</a>.</p></div><h3 id="pay-attention-of-trap" tabindex="-1"><a class="header-anchor" href="#pay-attention-of-trap" aria-hidden="true">#</a> Pay Attention of Trap</h3><blockquote><p>Here are some misunderstandings that may be encountered during use for reference.</p></blockquote><h4 id="restrictive-find-conditions" tabindex="-1"><a class="header-anchor" href="#restrictive-find-conditions" aria-hidden="true">#</a> Restrictive Find Conditions</h4><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>In find conditions you can only use <strong>index</strong> function once except <strong>order</strong>.</p></div><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">).index(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ❗ Wrong usage, please keep only one index method</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">).index(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The following find conditions can be used without any problems.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">).index(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> order().index(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="necessary-find-conditions" tabindex="-1"><a class="header-anchor" href="#necessary-find-conditions" aria-hidden="true">#</a> Necessary Find Conditions</h4><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>In common method find conditions, <u><strong>even methods without parameters need to set find conditions</strong></u>.</p></div><p>Suppose we have the following <code>Class</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">string</span><span style="color:#ADBAC7;">) {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><p>We want to get the <code>public void foo()</code> method, which can be written as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"foo"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>However, the above example <u><strong>is wrong</strong></u>.</p><p>You will find two <code>foo</code> methods in this <code>Class</code>, one of which takes a method parameter.</p><p>Since the above example does not set the find conditions for <code>param</code>, the result will be the first method <code>public void foo(String string)</code> that matches the name and matches the bytecode order, not the last method we need.</p><p>This is a <strong>frequent error</strong>, <strong>without method parameters, you will lose the use of method parameter find conditions</strong>.</p><p>The correct usage is as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"foo"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ✅ Correct usage, add detailed filter conditions</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>At this point, the above example will perfectly match the <code>public void foo()</code> method.</p><div class="custom-container tip"><p class="custom-container-title">Compatibility Notes</p><p>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.</p></div><h4 id="abbreviated-find-conditions" tabindex="-1"><a class="header-anchor" href="#abbreviated-find-conditions" aria-hidden="true">#</a> Abbreviated Find Conditions</h4><blockquote><p>In the construction method find conditions, <u><strong>constructors without parameters do not need to fill in the find conditions</strong></u>.</p></blockquote><p>Suppose we have the following <code>Class</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;"> {</span></span>
|
||
<span class="line"></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">TestFoo</span><span style="color:#ADBAC7;">() {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre></div><p>We want to get the <code>public TestFoo()</code> constructor, which can be written as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.</span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;"> { emptyParam() }</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>The above example can successfully obtain the <code>public TestFoo()</code> constructor, but it feels a bit cumbersome.</p><p>Unlike normal methods, since the constructor does not need to consider the <code>name</code>, when the constructor has no parameters, we can omit the <code>emptyParam</code> parameter.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.</span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;">()</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Compatibility Notes</p><p>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.</p><p><u><strong>This is a bug, the latest version has been fixed</strong></u>, please make sure you are using the latest API version.</p></div><h4 id="bytecode-type" tabindex="-1"><a class="header-anchor" href="#bytecode-type" aria-hidden="true">#</a> Bytecode Type</h4><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>In the bytecode call result, the <strong>cast</strong> method can only specify the type corresponding to the bytecode.</p></div><p>For example we want to get a field of type <code>Boolean</code> and cast it to <code>String</code>.</p><p>The following is the wrong way to use it.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().string() </span><span style="color:#768390;">// ❗ Wrong usage, must be cast to the bytecode target type</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The following is the correct way to use it.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().boolean().toString() </span><span style="color:#768390;">// ✅ The correct way to use, get the type and then convert</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="common-type-extensions" tabindex="-1"><a class="header-anchor" href="#common-type-extensions" aria-hidden="true">#</a> Common Type Extensions</h2><p>When find methods and fields, we usually need to specify the type in find conditions.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">Boolean</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Expressing the type <code>Boolean::class.java</code> in <code>Kotlin</code> is very long and not convenient.</p><p>Therefore, <code>YukiHookAPI</code> encapsulates common type calls for developers, including Android's basic types and Java's basic types.</p><p>At this time, the above type can be written in the following form.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">field {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Common basic types in Java have been encapsulated as <strong>Name + Type</strong>, such as <code>IntType</code>, <code>FloatType</code>.</p><p>Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type <code>String[]</code>.</p><p>You need to write <code>java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass</code> to get this type.</p><p>Does it feel very troublesome? At this time, we can use the extension method <code>ArrayClass(StringType)</code> to get this type.</p><p>At the same time, since <code>String</code> is a common type, you can also directly use <code>StringArrayClass</code> to get this type.</p><p>Some common methods found in Hook have their corresponding encapsulation types for use, in the format <strong>Name + Class</strong>.</p><p>For example, the Hook <code>onCreate</code> method needs to find the <code>Bundle::class.java</code> type.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">method {</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"onCreate"</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BundleClass</span><span style="color:#ADBAC7;">)</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more types, see <a href="../public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory">ComponentTypeFactory</a>, <a href="../public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory">GraphicsTypeFactory</a>, <a href="../public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory">ViewTypeFactory</a>, <a href="../public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory">VariableTypeFactory</a>.</p></div><p>At the same time, you are welcome to contribute more commonly used types.</p></div><!--[--><!--]--></div><footer class="page-meta"><div class="meta-item edit-link"><a class="external-link meta-item-label" href="https://github.com/fankes/YukiHookAPI/edit/master/docs/src/en/api/special-features/reflection.md" rel="noopener noreferrer" target="_blank" aria-label="Edit this page on Github"><!--[--><!--]--> Edit this page on Github <span><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"><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"></path><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"></polygon></svg><span class="external-link-icon-sr-only">open in new window</span></span><!--[--><!--]--></a></div><div class="meta-item last-updated"><span class="meta-item-label">Last Updated: </span><!----></div><div class="meta-item contributors"><span class="meta-item-label">Contributors: </span><span class="meta-item-info"><!--[--><!--[--><span class="contributor" title="email: qzmmcn@163.com">fankesyooni</span><!----><!--]--><!--]--></span></div></footer><nav class="page-nav"><p class="inner"><!----><span class="next"><a href="/YukiHookAPI/en/api/special-features/logger.html" class="" aria-label="Debug Logs"><!--[--><!--]--> Debug Logs <!--[--><!--]--></a></span></p></nav><!--[--><!--]--></main><!--]--></div><!----><!--]--></div>
|
||
<script type="module" src="/YukiHookAPI/assets/app.fb8271cf.js" defer></script>
|
||
</body>
|
||
</html>
|