mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-06 10:45:47 +08:00
853 lines
274 KiB
HTML
853 lines
274 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<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="/YukiHookAPI/images/logo.png"><title>字节码与反射扩展 | Yuki Hook API</title><meta name="description" content="一个使用 Kotlin 构建的高效 Hook API 与 Xposed 模块解决方案">
|
||
<link rel="modulepreload" href="/YukiHookAPI/assets/app.65ee8e4f.js"><link rel="modulepreload" href="/YukiHookAPI/assets/reflection.html.c4c089a0.js"><link rel="modulepreload" href="/YukiHookAPI/assets/reflection.html.eb335976.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.1ad46905.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.58270dd2.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.962e6741.js"><link rel="prefetch" href="/YukiHookAPI/assets/about.html.bac55135.js"><link rel="prefetch" href="/YukiHookAPI/assets/changelog.html.40ff2a93.js"><link rel="prefetch" href="/YukiHookAPI/assets/contacts.html.78c116e0.js"><link rel="prefetch" href="/YukiHookAPI/assets/future.html.290989e8.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.f6b9c2a4.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-example.html.c60371a6.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-exception.html.ba1743d2.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.09de8b71.js"><link rel="prefetch" href="/YukiHookAPI/assets/example.html.bb6da37d.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.ca5e9385.js"><link rel="prefetch" href="/YukiHookAPI/assets/knowledge.html.13983a8b.js"><link rel="prefetch" href="/YukiHookAPI/assets/move-to-new-api.html.f91df01f.js"><link rel="prefetch" href="/YukiHookAPI/assets/quick-start.html.d9d91363.js"><link rel="prefetch" href="/YukiHookAPI/assets/yukihookapi-projectbuilder.html.ed4fa356.js"><link rel="prefetch" href="/YukiHookAPI/assets/about.html.4de66a22.js"><link rel="prefetch" href="/YukiHookAPI/assets/changelog.html.1027a0d9.js"><link rel="prefetch" href="/YukiHookAPI/assets/contacts.html.20aa79de.js"><link rel="prefetch" href="/YukiHookAPI/assets/future.html.3e784ab5.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.cad3998c.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-example.html.29a2e3ae.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-exception.html.b279975a.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.73248b21.js"><link rel="prefetch" href="/YukiHookAPI/assets/example.html.667f5444.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.ced3162e.js"><link rel="prefetch" href="/YukiHookAPI/assets/knowledge.html.830e8c66.js"><link rel="prefetch" href="/YukiHookAPI/assets/move-to-new-api.html.4bf89a9b.js"><link rel="prefetch" href="/YukiHookAPI/assets/quick-start.html.bf02518e.js"><link rel="prefetch" href="/YukiHookAPI/assets/yukihookapi-projectbuilder.html.d499d226.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-inject.html.433c5f35.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-lifecycle.html.7e81cf29.js"><link rel="prefetch" href="/YukiHookAPI/assets/logger.html.a59ab5f0.js"><link rel="prefetch" href="/YukiHookAPI/assets/reflection.html.1e1fd510.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-channel.html.d35b34eb.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-storage.html.bf4a811f.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-inject.html.0f378e76.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-lifecycle.html.136055f0.js"><link rel="prefetch" href="/YukiHookAPI/assets/logger.html.ed51ab5d.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-channel.html.5dd91d68.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-storage.html.909201c9.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookAPI.html.a450e578.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookAPI.html.2007a134.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.f94281cf.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.153f4c39.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiBaseHooker.html.99eec744.js"><link rel="prefetch" href="/YukiHookAPI/assets/ReflectionFactory.html.d2d3ba9a.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookFactory.html.0143ac70.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiMemberHookCreator.html.7e0c1b2e.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResourcesHookCreator.html.2fa2ff0f.js"><link rel="prefetch" href="/YukiHookAPI/assets/LoggerFactory.html.52af0d44.js"><link rel="prefetch" href="/YukiHookAPI/assets/InjectYukiHookWithXposed.html.cf9b500d.js"><link rel="prefetch" href="/YukiHookAPI/assets/CurrentClass.html.641fcd58.js"><link rel="prefetch" href="/YukiHookAPI/assets/GenericClass.html.5d4a2ffe.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.a490557a.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookParam.html.61e05f29.js"><link rel="prefetch" href="/YukiHookAPI/assets/PackageParam.html.cf48302c.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiMemberHookCreator.html.e217488d.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResourcesHookCreator.html.1f540f56.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiBaseHooker.html.b68236f9.js"><link rel="prefetch" href="/YukiHookAPI/assets/ReflectionFactory.html.d78fe330.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookFactory.html.6555413e.js"><link rel="prefetch" href="/YukiHookAPI/assets/LoggerFactory.html.ae54c997.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookParam.html.9db30e67.js"><link rel="prefetch" href="/YukiHookAPI/assets/PackageParam.html.83d09a1a.js"><link rel="prefetch" href="/YukiHookAPI/assets/ComponentTypeFactory.html.91960e5a.js"><link rel="prefetch" href="/YukiHookAPI/assets/GraphicsTypeFactory.html.b9d7edef.js"><link rel="prefetch" href="/YukiHookAPI/assets/ViewTypeFactory.html.2caabca9.js"><link rel="prefetch" href="/YukiHookAPI/assets/DefinedTypeFactory.html.8137c32c.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariableTypeFactory.html.e192299c.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleApplication.html.57573770.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookDataChannel.html.2123b109.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookPrefsBridge.html.f76210ff.js"><link rel="prefetch" href="/YukiHookAPI/assets/IYukiHookXposedInit.html.b37a852b.js"><link rel="prefetch" href="/YukiHookAPI/assets/ComponentTypeFactory.html.9c4ea2f6.js"><link rel="prefetch" href="/YukiHookAPI/assets/GraphicsTypeFactory.html.b556bfd7.js"><link rel="prefetch" href="/YukiHookAPI/assets/ViewTypeFactory.html.2836f840.js"><link rel="prefetch" href="/YukiHookAPI/assets/DefinedTypeFactory.html.ba3bdd0b.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariableTypeFactory.html.1bda3847.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleApplication.html.a386b8db.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookDataChannel.html.c8a74f24.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookPrefsBridge.html.35f775bb.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.282236a6.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldFinder.html.ce7337a4.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodFinder.html.9a97f14f.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiXposedEvent.html.560fa41c.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiModuleResources.html.90f23dcd.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResForwarder.html.65998e9e.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResources.html.cc9ce9fb.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelData.html.1981f416.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleClassLoader.html.2ddf88b6.js"><link rel="prefetch" href="/YukiHookAPI/assets/PrefsData.html.34c51103.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.8e38ad6f.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldFinder.html.30e6d2df.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodFinder.html.9be50874.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiXposedEvent.html.a93ee4ef.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiModuleResources.html.46222277.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResForwarder.html.70fb824b.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResources.html.8714bbf2.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelData.html.5ca343ea.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelPriority.html.7d2ec81d.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelPriority.html.b460c4bc.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleClassLoader.html.0388bffd.js"><link rel="prefetch" href="/YukiHookAPI/assets/PrefsData.html.343169a5.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModulePreferenceFragment.html.0c7dadc7.js"><link rel="prefetch" href="/YukiHookAPI/assets/ExecutorType.html.7e3dd355.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.e986a067.js"><link rel="prefetch" href="/YukiHookAPI/assets/ObjectRules.html.70d91cad.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorRules.html.c7161b83.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldRules.html.c8edc48c.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRules.html.a071b3c6.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodRules.html.6c9a8df6.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppActivity.html.98cb78a4.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppCompatActivity.html.4c0f53a9.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleContextThemeWrapper.html.0879426b.js"><link rel="prefetch" href="/YukiHookAPI/assets/ExecutorType.html.3e98ffe1.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.34ee16d6.js"><link rel="prefetch" href="/YukiHookAPI/assets/ObjectRules.html.4b682129.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorRules.html.f8ba43ee.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldRules.html.a499e892.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRules.html.b3e5d297.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodRules.html.afeaf85e.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppActivity.html.c4a0eeb4.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppCompatActivity.html.e544662e.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleContextThemeWrapper.html.229a46ac.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.54c4ec2b.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.cf0bb6f6.js"><link rel="prefetch" href="/YukiHookAPI/assets/index.html.4e6eef39.js"><link rel="prefetch" href="/YukiHookAPI/assets/about.html.ee644111.js"><link rel="prefetch" href="/YukiHookAPI/assets/changelog.html.86a18ba9.js"><link rel="prefetch" href="/YukiHookAPI/assets/contacts.html.60406153.js"><link rel="prefetch" href="/YukiHookAPI/assets/future.html.fd5c3cea.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.8a9d339c.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-example.html.0aba45cc.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-exception.html.90a25bb3.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-using.html.d47d5f21.js"><link rel="prefetch" href="/YukiHookAPI/assets/r8-proguard.html.3441936b.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-using.html.a67b0b5d.js"><link rel="prefetch" href="/YukiHookAPI/assets/example.html.ae18fbc3.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.8c9a3b82.js"><link rel="prefetch" href="/YukiHookAPI/assets/knowledge.html.2b341c7b.js"><link rel="prefetch" href="/YukiHookAPI/assets/move-to-new-api.html.bb5356f9.js"><link rel="prefetch" href="/YukiHookAPI/assets/quick-start.html.91f8d4fa.js"><link rel="prefetch" href="/YukiHookAPI/assets/yukihookapi-projectbuilder.html.d814fc24.js"><link rel="prefetch" href="/YukiHookAPI/assets/about.html.9a433ddc.js"><link rel="prefetch" href="/YukiHookAPI/assets/changelog.html.7ceceadc.js"><link rel="prefetch" href="/YukiHookAPI/assets/contacts.html.78ccd8c9.js"><link rel="prefetch" href="/YukiHookAPI/assets/future.html.4fc4e7d2.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.63c1018a.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-example.html.ca4ba78b.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-exception.html.bf639ab3.js"><link rel="prefetch" href="/YukiHookAPI/assets/api-using.html.1db6d7df.js"><link rel="prefetch" href="/YukiHookAPI/assets/r8-proguard.html.28972a4d.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-using.html.888e004d.js"><link rel="prefetch" href="/YukiHookAPI/assets/example.html.6748bbc2.js"><link rel="prefetch" href="/YukiHookAPI/assets/home.html.8ebb84ee.js"><link rel="prefetch" href="/YukiHookAPI/assets/knowledge.html.6acb235f.js"><link rel="prefetch" href="/YukiHookAPI/assets/move-to-new-api.html.871a57fc.js"><link rel="prefetch" href="/YukiHookAPI/assets/quick-start.html.c5806d69.js"><link rel="prefetch" href="/YukiHookAPI/assets/yukihookapi-projectbuilder.html.db3ae747.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-inject.html.0504c1fa.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-lifecycle.html.4d83461f.js"><link rel="prefetch" href="/YukiHookAPI/assets/logger.html.094cd601.js"><link rel="prefetch" href="/YukiHookAPI/assets/reflection.html.d2af15d9.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-channel.html.96c8b4ef.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-storage.html.b56b5cc4.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-inject.html.7dee39f4.js"><link rel="prefetch" href="/YukiHookAPI/assets/host-lifecycle.html.2b1f76e4.js"><link rel="prefetch" href="/YukiHookAPI/assets/logger.html.8cd7e1ad.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-channel.html.ec2e4b72.js"><link rel="prefetch" href="/YukiHookAPI/assets/xposed-storage.html.39ab0187.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookAPI.html.27d408ec.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookAPI.html.d7c7e02b.js"><link rel="prefetch" href="/YukiHookAPI/assets/InjectYukiHookWithXposed.html.f85196d9.js"><link rel="prefetch" href="/YukiHookAPI/assets/CurrentClass.html.a1922838.js"><link rel="prefetch" href="/YukiHookAPI/assets/GenericClass.html.03620d16.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookClass.html.4a827bbf.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookResources.html.5814c6c7.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariousClass.html.3ae061a2.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiBaseHooker.html.e82295fd.js"><link rel="prefetch" href="/YukiHookAPI/assets/ReflectionFactory.html.6b0c5537.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookFactory.html.9fb7d4cd.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiMemberHookCreator.html.fff7a5a2.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResourcesHookCreator.html.a290f2c3.js"><link rel="prefetch" href="/YukiHookAPI/assets/LoggerFactory.html.f1d75e09.js"><link rel="prefetch" href="/YukiHookAPI/assets/InjectYukiHookWithXposed.html.64e464e7.js"><link rel="prefetch" href="/YukiHookAPI/assets/CurrentClass.html.3f770770.js"><link rel="prefetch" href="/YukiHookAPI/assets/GenericClass.html.04028bba.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookClass.html.007ce98f.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookResources.html.9c71c9d1.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariousClass.html.df3900d6.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookParam.html.4c6256d6.js"><link rel="prefetch" href="/YukiHookAPI/assets/PackageParam.html.ca84d5c3.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiMemberHookCreator.html.8039ffbb.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResourcesHookCreator.html.aeb10bfd.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiBaseHooker.html.41d12985.js"><link rel="prefetch" href="/YukiHookAPI/assets/ReflectionFactory.html.6a564d50.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookFactory.html.49695848.js"><link rel="prefetch" href="/YukiHookAPI/assets/LoggerFactory.html.2506068c.js"><link rel="prefetch" href="/YukiHookAPI/assets/HookParam.html.b31bbc53.js"><link rel="prefetch" href="/YukiHookAPI/assets/PackageParam.html.7db22fdb.js"><link rel="prefetch" href="/YukiHookAPI/assets/ComponentTypeFactory.html.15eba61d.js"><link rel="prefetch" href="/YukiHookAPI/assets/GraphicsTypeFactory.html.80384642.js"><link rel="prefetch" href="/YukiHookAPI/assets/ViewTypeFactory.html.34b29468.js"><link rel="prefetch" href="/YukiHookAPI/assets/DefinedTypeFactory.html.deaf3356.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariableTypeFactory.html.c3b157db.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleApplication.html.8d8d33dc.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookDataChannel.html.c608f3a0.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookPrefsBridge.html.c7e53204.js"><link rel="prefetch" href="/YukiHookAPI/assets/IYukiHookXposedInit.html.dcfd9541.js"><link rel="prefetch" href="/YukiHookAPI/assets/ComponentTypeFactory.html.dbdda1fe.js"><link rel="prefetch" href="/YukiHookAPI/assets/GraphicsTypeFactory.html.8751ac72.js"><link rel="prefetch" href="/YukiHookAPI/assets/ViewTypeFactory.html.1c0cfeb0.js"><link rel="prefetch" href="/YukiHookAPI/assets/DefinedTypeFactory.html.9b7abe0d.js"><link rel="prefetch" href="/YukiHookAPI/assets/VariableTypeFactory.html.5b6a5486.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleApplication.html.a38e2860.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookDataChannel.html.d9b02f16.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiHookPrefsBridge.html.52a432c5.js"><link rel="prefetch" href="/YukiHookAPI/assets/IYukiHookXposedInit.html.419ecc1e.js"><link rel="prefetch" href="/YukiHookAPI/assets/BaseFinder.html.7c1180be.js"><link rel="prefetch" href="/YukiHookAPI/assets/DexClassFinder.html.339495f0.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorFinder.html.a7f5a328.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldFinder.html.fc247834.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodFinder.html.04f1f553.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiXposedEvent.html.287966a3.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiModuleResources.html.145305d1.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResForwarder.html.abd21aa6.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResources.html.da77100e.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelData.html.c0712c06.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleClassLoader.html.89622882.js"><link rel="prefetch" href="/YukiHookAPI/assets/PrefsData.html.4e42b4a4.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModulePreferenceFragment.html.a3c94fb9.js"><link rel="prefetch" href="/YukiHookAPI/assets/BaseFinder.html.4152f8e6.js"><link rel="prefetch" href="/YukiHookAPI/assets/DexClassFinder.html.da277423.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorFinder.html.eb44fdeb.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldFinder.html.1e62fae2.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodFinder.html.dd5561f6.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiXposedEvent.html.cfa65900.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiModuleResources.html.c97ecc89.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResForwarder.html.d9339c05.js"><link rel="prefetch" href="/YukiHookAPI/assets/YukiResources.html.18e98552.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelData.html.b9ff65a2.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelPriority.html.49d23952.js"><link rel="prefetch" href="/YukiHookAPI/assets/ChannelPriority.html.1fb25099.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleClassLoader.html.debff60b.js"><link rel="prefetch" href="/YukiHookAPI/assets/PrefsData.html.859d4275.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModulePreferenceFragment.html.60d791da.js"><link rel="prefetch" href="/YukiHookAPI/assets/ExecutorType.html.4b76a68d.js"><link rel="prefetch" href="/YukiHookAPI/assets/CountRules.html.2995f7a2.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModifierRules.html.a8103844.js"><link rel="prefetch" href="/YukiHookAPI/assets/NameRules.html.9ef0817d.js"><link rel="prefetch" href="/YukiHookAPI/assets/ObjectRules.html.5776192b.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorRules.html.9776a16c.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldRules.html.b6a79a71.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRules.html.725758ab.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodRules.html.d073f5f0.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppActivity.html.2f977361.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppCompatActivity.html.7c0a7e39.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleContextThemeWrapper.html.28da62f5.js"><link rel="prefetch" href="/YukiHookAPI/assets/ExecutorType.html.22a6ea71.js"><link rel="prefetch" href="/YukiHookAPI/assets/CountRules.html.d3040d8a.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModifierRules.html.10240c63.js"><link rel="prefetch" href="/YukiHookAPI/assets/NameRules.html.417db2b6.js"><link rel="prefetch" href="/YukiHookAPI/assets/ObjectRules.html.2718a513.js"><link rel="prefetch" href="/YukiHookAPI/assets/ConstructorRules.html.a2744ceb.js"><link rel="prefetch" href="/YukiHookAPI/assets/FieldRules.html.bcc048c6.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRules.html.b435504b.js"><link rel="prefetch" href="/YukiHookAPI/assets/MethodRules.html.b9938c0d.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppActivity.html.9f6ba46f.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleAppCompatActivity.html.5ce81f5f.js"><link rel="prefetch" href="/YukiHookAPI/assets/ModuleContextThemeWrapper.html.8814b000.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRulesResult.html.b9014cf5.js"><link rel="prefetch" href="/YukiHookAPI/assets/MemberRulesResult.html.6486b780.js"><link rel="prefetch" href="/YukiHookAPI/assets/404.html.e66bec2f.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/zh-cn/" 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="导航"><span class="title">导航</span><span class="arrow down"></span></button><button class="navbar-dropdown-title-mobile" type="button" aria-label="导航"><span class="title">导航</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>入门</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/home" class="" aria-label="介绍"><!--[--><!--]--> 介绍 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/knowledge" class="" aria-label="基础知识"><!--[--><!--]--> 基础知识 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/quick-start" class="" aria-label="快速开始"><!--[--><!--]--> 快速开始 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/example" class="" aria-label="用法示例"><!--[--><!--]--> 用法示例 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/move-to-new-api" class="" aria-label="从 Xposed API 迁移"><!--[--><!--]--> 从 Xposed API 迁移 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>配置</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/api-example" class="" aria-label="API 基本配置"><!--[--><!--]--> API 基本配置 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/api-exception" class="" aria-label="API 异常处理"><!--[--><!--]--> API 异常处理 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/xposed-using" class="" aria-label="作为 Xposed 模块使用的相关配置"><!--[--><!--]--> 作为 Xposed 模块使用的相关配置 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/api-using" class="" aria-label="作为 Hook API 使用的相关配置"><!--[--><!--]--> 作为 Hook API 使用的相关配置 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/r8-proguard" class="" aria-label="R8 与 Proguard 混淆"><!--[--><!--]--> R8 与 Proguard 混淆 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>工具</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/tools/yukihookapi-projectbuilder" class="" aria-label="YukiHookAPI 构建工具"><!--[--><!--]--> YukiHookAPI 构建工具 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>API 文档</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/api/home" class="" aria-label="文档介绍"><!--[--><!--]--> 文档介绍 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI" class="" aria-label="Public API"><!--[--><!--]--> Public API <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/api/special-features/reflection" class="router-link-active" aria-label="特色功能"><!--[--><!--]--> 特色功能 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>关于</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/about/changelog" class="" aria-label="更新日志"><!--[--><!--]--> 更新日志 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/about/future" class="" aria-label="展望未来"><!--[--><!--]--> 展望未来 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/about/contacts" class="" aria-label="联系我们"><!--[--><!--]--> 联系我们 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/about/about" class="" aria-label="关于此文档"><!--[--><!--]--> 关于此文档 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><!--]--></ul></div></div><div class="navbar-item"><a href="/YukiHookAPI/zh-cn/about/contacts" class="" aria-label="联系我们"><!--[--><!--]--> 联系我们 <!--[--><!--]--></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">简体中文 (CN)</span><span class="arrow down"></span></button><button class="navbar-dropdown-title-mobile" type="button" aria-label="Select language"><span class="title">简体中文 (CN)</span><span class="right arrow"></span></button><ul style="display:none;" class="navbar-dropdown"><!--[--><li class="navbar-dropdown-item"><a href="/YukiHookAPI/en/api/special-features/reflection.html" class="" aria-label="English"><!--[--><!--]--> English <!--[--><!--]--></a></li><li class="navbar-dropdown-item"><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html" class="router-link-active router-link-exact-active router-link-active" 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">在新窗口中打开</span></span><!--[--><!--]--></a></div><!--]--></nav><!--[--><!--]--><button class="toggle-color-mode-button" title="切换颜色模式"><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="搜索" 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="导航"><span class="title">导航</span><span class="arrow down"></span></button><button class="navbar-dropdown-title-mobile" type="button" aria-label="导航"><span class="title">导航</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>入门</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/home" class="" aria-label="介绍"><!--[--><!--]--> 介绍 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/knowledge" class="" aria-label="基础知识"><!--[--><!--]--> 基础知识 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/quick-start" class="" aria-label="快速开始"><!--[--><!--]--> 快速开始 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/example" class="" aria-label="用法示例"><!--[--><!--]--> 用法示例 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/guide/move-to-new-api" class="" aria-label="从 Xposed API 迁移"><!--[--><!--]--> 从 Xposed API 迁移 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>配置</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/api-example" class="" aria-label="API 基本配置"><!--[--><!--]--> API 基本配置 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/api-exception" class="" aria-label="API 异常处理"><!--[--><!--]--> API 异常处理 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/xposed-using" class="" aria-label="作为 Xposed 模块使用的相关配置"><!--[--><!--]--> 作为 Xposed 模块使用的相关配置 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/api-using" class="" aria-label="作为 Hook API 使用的相关配置"><!--[--><!--]--> 作为 Hook API 使用的相关配置 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/config/r8-proguard" class="" aria-label="R8 与 Proguard 混淆"><!--[--><!--]--> R8 与 Proguard 混淆 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>工具</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/tools/yukihookapi-projectbuilder" class="" aria-label="YukiHookAPI 构建工具"><!--[--><!--]--> YukiHookAPI 构建工具 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>API 文档</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/api/home" class="" aria-label="文档介绍"><!--[--><!--]--> 文档介绍 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI" class="" aria-label="Public API"><!--[--><!--]--> Public API <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/api/special-features/reflection" class="router-link-active" aria-label="特色功能"><!--[--><!--]--> 特色功能 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><li class="navbar-dropdown-item"><!--[--><h4 class="navbar-dropdown-subtitle"><span>关于</span></h4><ul class="navbar-dropdown-subitem-wrapper"><!--[--><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/about/changelog" class="" aria-label="更新日志"><!--[--><!--]--> 更新日志 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/about/future" class="" aria-label="展望未来"><!--[--><!--]--> 展望未来 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/about/contacts" class="" aria-label="联系我们"><!--[--><!--]--> 联系我们 <!--[--><!--]--></a></li><li class="navbar-dropdown-subitem"><a href="/YukiHookAPI/zh-cn/about/about" class="" aria-label="关于此文档"><!--[--><!--]--> 关于此文档 <!--[--><!--]--></a></li><!--]--></ul><!--]--></li><!--]--></ul></div></div><div class="navbar-item"><a href="/YukiHookAPI/zh-cn/about/contacts" class="" aria-label="联系我们"><!--[--><!--]--> 联系我们 <!--[--><!--]--></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">简体中文 (CN)</span><span class="arrow down"></span></button><button class="navbar-dropdown-title-mobile" type="button" aria-label="Select language"><span class="title">简体中文 (CN)</span><span class="right arrow"></span></button><ul style="display:none;" class="navbar-dropdown"><!--[--><li class="navbar-dropdown-item"><a href="/YukiHookAPI/en/api/special-features/reflection.html" class="" aria-label="English"><!--[--><!--]--> English <!--[--><!--]--></a></li><li class="navbar-dropdown-item"><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html" class="router-link-active router-link-exact-active router-link-active" 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">在新窗口中打开</span></span><!--[--><!--]--></a></div><!--]--></nav><!--[--><!--]--><ul class="sidebar-items"><!--[--><li><p tabindex="0" class="sidebar-item sidebar-heading collapsible">入门 <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/zh-cn/guide/home.html" class="sidebar-item" aria-label="介绍"><!--[--><!--]--> 介绍 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/guide/knowledge.html" class="sidebar-item" aria-label="基础知识"><!--[--><!--]--> 基础知识 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/guide/quick-start.html" class="sidebar-item" aria-label="快速开始"><!--[--><!--]--> 快速开始 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/guide/example.html" class="sidebar-item" aria-label="用法示例"><!--[--><!--]--> 用法示例 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/guide/move-to-new-api.html" class="sidebar-item" aria-label="从 Xposed API 迁移"><!--[--><!--]--> 从 Xposed API 迁移 <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item sidebar-heading collapsible">配置 <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/zh-cn/config/api-example.html" class="sidebar-item" aria-label="API 基本配置"><!--[--><!--]--> API 基本配置 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/config/api-exception.html" class="sidebar-item" aria-label="API 异常处理"><!--[--><!--]--> API 异常处理 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/config/xposed-using.html" class="sidebar-item" aria-label="作为 Xposed 模块使用的相关配置"><!--[--><!--]--> 作为 Xposed 模块使用的相关配置 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/config/api-using.html" class="sidebar-item" aria-label="作为 Hook API 使用的相关配置"><!--[--><!--]--> 作为 Hook API 使用的相关配置 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/config/r8-proguard.html" class="sidebar-item" aria-label="R8 与 Proguard 混淆"><!--[--><!--]--> R8 与 Proguard 混淆 <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item sidebar-heading collapsible">工具 <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/zh-cn/tools/yukihookapi-projectbuilder.html" class="sidebar-item" aria-label="YukiHookAPI 构建工具"><!--[--><!--]--> YukiHookAPI 构建工具 <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item sidebar-heading active collapsible">API 文档 <span class="down arrow"></span></p><ul style="" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/zh-cn/api/home.html" class="sidebar-item" aria-label="文档介绍"><!--[--><!--]--> 文档介绍 <!--[--><!--]--></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/zh-cn/api/public/com/highcapable/yukihookapi/YukiHookAPI.html" class="sidebar-item" aria-label="YukiHookAPI - object"><!--[--><!--]--> YukiHookAPI - object <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/PackageParam.html" class="sidebar-item" aria-label="PackageParam - class"><!--[--><!--]--> PackageParam - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/param/HookParam.html" class="sidebar-item" aria-label="HookParam - class"><!--[--><!--]--> HookParam - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/annotation/xposed/InjectYukiHookWithXposed.html" class="sidebar-item" aria-label="InjectYukiHookWithXposed - annotation"><!--[--><!--]--> InjectYukiHookWithXposed - annotation <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/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/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/prefs/YukiHookPrefsBridge.html" class="sidebar-item" aria-label="YukiHookPrefsBridge - class"><!--[--><!--]--> YukiHookPrefsBridge - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/channel/priority/ChannelPriority.html" class="sidebar-item" aria-label="ChannelPriority - class"><!--[--><!--]--> ChannelPriority - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/parasitic/reference/ModuleClassLoader.html" class="sidebar-item" aria-label="ModuleClassLoader - class"><!--[--><!--]--> ModuleClassLoader - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/resources/YukiModuleResources.html" class="sidebar-item" aria-label="YukiModuleResources - class"><!--[--><!--]--> YukiModuleResources - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/resources/YukiResources.html" class="sidebar-item" aria-label="YukiResources - class"><!--[--><!--]--> YukiResources - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/xposed/bridge/resources/YukiResForwarder.html" class="sidebar-item" aria-label="YukiResForwarder - class"><!--[--><!--]--> YukiResForwarder - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/api/public/com/highcapable/yukihookapi/hook/log/LoggerFactory.html" class="sidebar-item" aria-label="LoggerFactory - kt"><!--[--><!--]--> LoggerFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory.html" class="sidebar-item" aria-label="ReflectionFactory - kt"><!--[--><!--]--> ReflectionFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/factory/YukiHookFactory.html" class="sidebar-item" aria-label="YukiHookFactory - kt"><!--[--><!--]--> YukiHookFactory - kt <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/entity/YukiBaseHooker.html" class="sidebar-item" aria-label="YukiBaseHooker - class"><!--[--><!--]--> YukiBaseHooker - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/api/compat/type/ExecutorType.html" class="sidebar-item" aria-label="ExecutorType - class"><!--[--><!--]--> ExecutorType - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiMemberHookCreator.html" class="sidebar-item" aria-label="YukiMemberHookCreator - class"><!--[--><!--]--> YukiMemberHookCreator - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/YukiResourcesHookCreator.html" class="sidebar-item" aria-label="YukiResourcesHookCreator - class"><!--[--><!--]--> YukiResourcesHookCreator - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/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/zh-cn/api/public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ObjectRules.html" class="sidebar-item" aria-label="ObjectRules - class"><!--[--><!--]--> ObjectRules - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/HookClass.html" class="sidebar-item" aria-label="HookClass - class"><!--[--><!--]--> HookClass - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/VariousClass.html" class="sidebar-item" aria-label="VariousClass - class"><!--[--><!--]--> VariousClass - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/CurrentClass.html" class="sidebar-item" aria-label="CurrentClass - class"><!--[--><!--]--> CurrentClass - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/public/com/highcapable/yukihookapi/hook/bean/GenericClass.html" class="sidebar-item" aria-label="GenericClass - class"><!--[--><!--]--> GenericClass - class <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/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">特色功能 <span class="down arrow"></span></p><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html" class="router-link-active router-link-exact-active router-link-active sidebar-item active" aria-label="字节码与反射扩展"><!--[--><!--]--> 字节码与反射扩展 <!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#class-扩展" class="router-link-active router-link-exact-active sidebar-item" aria-label="Class 扩展"><!--[--><!--]--> Class 扩展 <!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#对象转换" class="router-link-active router-link-exact-active sidebar-item" aria-label="对象转换"><!--[--><!--]--> 对象转换 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#存在判断" class="router-link-active router-link-exact-active sidebar-item" aria-label="存在判断"><!--[--><!--]--> 存在判断 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#模糊查找" class="router-link-active router-link-exact-active sidebar-item" aria-label="模糊查找"><!--[--><!--]--> 模糊查找 <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#member-扩展" class="router-link-active router-link-exact-active sidebar-item" aria-label="Member 扩展"><!--[--><!--]--> Member 扩展 <!--[--><!--]--></a><ul style="" class="sidebar-item-children"><!--[--><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#查找与反射调用" class="router-link-active router-link-exact-active sidebar-item" aria-label="查找与反射调用"><!--[--><!--]--> 查找与反射调用 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#可选的查找条件" class="router-link-active router-link-exact-active sidebar-item" aria-label="可选的查找条件"><!--[--><!--]--> 可选的查找条件 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#在父类查找" class="router-link-active router-link-exact-active sidebar-item" aria-label="在父类查找"><!--[--><!--]--> 在父类查找 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#模糊查找-1" class="router-link-active router-link-exact-active sidebar-item" aria-label="模糊查找"><!--[--><!--]--> 模糊查找 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#多重查找-1" class="router-link-active router-link-exact-active sidebar-item" aria-label="多重查找"><!--[--><!--]--> 多重查找 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#静态字节码" class="router-link-active router-link-exact-active sidebar-item" aria-label="静态字节码"><!--[--><!--]--> 静态字节码 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#混淆的字节码" class="router-link-active router-link-exact-active sidebar-item" aria-label="混淆的字节码"><!--[--><!--]--> 混淆的字节码 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#直接调用" class="router-link-active router-link-exact-active sidebar-item" aria-label="直接调用"><!--[--><!--]--> 直接调用 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#原始调用" class="router-link-active router-link-exact-active sidebar-item" aria-label="原始调用"><!--[--><!--]--> 原始调用 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#再次查找" class="router-link-active router-link-exact-active sidebar-item" aria-label="再次查找"><!--[--><!--]--> 再次查找 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#相对匹配" class="router-link-active router-link-exact-active sidebar-item" aria-label="相对匹配"><!--[--><!--]--> 相对匹配 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#调用泛型" class="router-link-active router-link-exact-active sidebar-item" aria-label="调用泛型"><!--[--><!--]--> 调用泛型 <!--[--><!--]--></a><!----></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#注意误区" class="router-link-active router-link-exact-active sidebar-item" aria-label="注意误区"><!--[--><!--]--> 注意误区 <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a aria-current="page" href="/YukiHookAPI/zh-cn/api/special-features/reflection.html#常用类型扩展" class="router-link-active router-link-exact-active sidebar-item" aria-label="常用类型扩展"><!--[--><!--]--> 常用类型扩展 <!--[--><!--]--></a><!----></li><!--]--></ul></li><li><a href="/YukiHookAPI/zh-cn/api/special-features/logger.html" class="sidebar-item" aria-label="调试日志"><!--[--><!--]--> 调试日志 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/special-features/xposed-storage.html" class="sidebar-item" aria-label="Xposed 模块数据存储"><!--[--><!--]--> Xposed 模块数据存储 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/special-features/xposed-channel.html" class="sidebar-item" aria-label="Xposed 模块与宿主通讯桥"><!--[--><!--]--> Xposed 模块与宿主通讯桥 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/special-features/host-lifecycle.html" class="sidebar-item" aria-label="宿主生命周期扩展"><!--[--><!--]--> 宿主生命周期扩展 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/api/special-features/host-inject.html" class="sidebar-item" aria-label="宿主资源注入扩展"><!--[--><!--]--> 宿主资源注入扩展 <!--[--><!--]--></a><!----></li><!--]--></ul></li><!--]--></ul></li><li><p tabindex="0" class="sidebar-item sidebar-heading collapsible">关于 <span class="right arrow"></span></p><ul style="display:none;" class="sidebar-item-children"><!--[--><li><a href="/YukiHookAPI/zh-cn/about/changelog.html" class="sidebar-item" aria-label="更新日志"><!--[--><!--]--> 更新日志 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/about/future.html" class="sidebar-item" aria-label="展望未来"><!--[--><!--]--> 展望未来 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/about/contacts.html" class="sidebar-item" aria-label="联系我们"><!--[--><!--]--> 联系我们 <!--[--><!--]--></a><!----></li><li><a href="/YukiHookAPI/zh-cn/about/about.html" class="sidebar-item" aria-label="关于此文档"><!--[--><!--]--> 关于此文档 <!--[--><!--]--></a><!----></li><!--]--></ul></li><!--]--></ul><!--[--><!--]--></aside><!--]--><!--[--><main class="page"><!--[--><!--]--><div class="theme-default-content"><!--[--><!--]--><div><h1 id="字节码与反射扩展" tabindex="-1"><a class="header-anchor" href="#字节码与反射扩展" aria-hidden="true">#</a> 字节码与反射扩展</h1><blockquote><p><code>YukiHookAPI</code> 为开发者封装了一套接近零反射写法的反射 API,它几乎可以完全取代原生 Java 的反射 API 相关用法。</p></blockquote><p>此功能的核心部分已被解耦合为 <a href="https://github.com/fankes/YukiReflection" target="_blank" rel="noopener noreferrer">YukiReflection<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">在新窗口中打开</span></span></a> 项目,它可以独立使用于任何 Android 项目中。</p><p>现在 <code>YukiReflection</code> 作为核心依赖集成于 <code>YukiHookAPI</code>。</p><p><code>YukiHookAPI</code> 在 <code>YukiReflection</code> 的基础上加入了针对 Hook 功能的相关扩展,使用 <code>YukiHookAPI</code> 无需引入此依赖。</p><h2 id="class-扩展" tabindex="-1"><a class="header-anchor" href="#class-扩展" aria-hidden="true">#</a> Class 扩展</h2><blockquote><p>这里是 <strong>Class</strong> 对象自身相关的扩展功能。</p></blockquote><h3 id="对象转换" tabindex="-1"><a class="header-anchor" href="#对象转换" aria-hidden="true">#</a> 对象转换</h3><p>假设我们要得到一个不能直接调用的 <code>Class</code>,通常情况下,我们可以使用标准的反射 API 去查找这个 <code>Class</code>。</p><blockquote><p>示例如下</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;">// 默认 ClassLoader 环境下的 Class</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;">// 指定 ClassLoader 环境下的 Class</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;">// 假设这个就是你的 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>这种写法大概不是很友好,此时 <code>YukiHookAPI</code> 就为你提供了一个可在任意地方使用的语法糖。</p><p>以上写法换做 <code>YukiHookAPI</code> 可写作如下形式。</p><blockquote><p>示例如下</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</span></span>
|
||
<span class="line"><span style="color:#768390;">// 如果当前正处于 PackageParam 环境,那么你可以不需要考虑 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;">// 自定义 Class 所在的 ClassLoader</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;">// 假设这个就是你的 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>如果当前 <code>Class</code> 并不存在,使用上述方法会抛出异常,如果你不确定 <code>Class</code> 是否存在,可以参考下面的解决方案。</p><blockquote><p>示例如下</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</span></span>
|
||
<span class="line"><span style="color:#768390;">// 如果当前正处于 PackageParam 环境,那么你可以不需要考虑 ClassLoader</span></span>
|
||
<span class="line"><span style="color:#768390;">// 得不到时结果会为 null 但不会抛出异常</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;">// 自定义 Class 所在的 ClassLoader</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;">// 假设这个就是你的 ClassLoader</span></span>
|
||
<span class="line"><span style="color:#768390;">// 得不到时结果会为 null 但不会抛出异常</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>我们还可以通过映射来得到一个存在的 <code>Class</code> 对象。</p><blockquote><p>示例如下</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 是能够被直接得到的</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;">// 我们同样可以自定义 Class 所在的 ClassLoader,这对于 stub 来说非常有效</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;">// 假设这个就是你的 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">小提示</p><p>更多功能请参考 <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> 方法。</p></div><h3 id="存在判断" tabindex="-1"><a class="header-anchor" href="#存在判断" aria-hidden="true">#</a> 存在判断</h3><p>假设我们要判断一个 <code>Class</code> 是否存在,通常情况下,我们可以使用标准的反射 API 去查找这个 <code>Class</code> 通过异常来判断是否存在。</p><blockquote><p>示例如下</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;">// 默认 ClassLoader 环境下的 Class</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;">// 指定 ClassLoader 环境下的 Class</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;">// 假设这个就是你的 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>这种写法大概不是很友好,此时 <code>YukiHookAPI</code> 就为你提供了一个可在任意地方使用的语法糖。</p><p>以上写法换做 <code>YukiHookAPI</code> 可写作如下形式。</p><blockquote><p>示例如下</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 是否存在</span></span>
|
||
<span class="line"><span style="color:#768390;">// 如果当前正处于 PackageParam 环境,那么你可以不需要考虑 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;">// 自定义 Class 所在的 ClassLoader</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;">// 假设这个就是你的 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">小提示</p><p>更多功能请参考 <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> 方法。</p></div><h3 id="模糊查找" tabindex="-1"><a class="header-anchor" href="#模糊查找" aria-hidden="true">#</a> 模糊查找 <span class="badge tip" style="vertical-align:middle;"><!--[-->Beta<!--]--></span></h3><p>在 R8 等工具混淆后的宿主 <strong>Dex</strong> 中的 <code>Class</code> 名称将会难以分辨,且不确定其正确位置,不能直接通过 <a href="#%E5%AF%B9%E8%B1%A1%E8%BD%AC%E6%8D%A2">对象转换</a> 来得到。</p><p>此时就有了 <code>DexClassFinder</code>,它的作用是通过需要查找的 <code>Class</code> 中的字节码特征来确定这个 <code>Class</code> 的实例。</p><div class="custom-container warning"><p class="custom-container-title">注意</p><p>目前 <strong>DexClassFinder</strong> 的功能尚在试验阶段,由于仅通过 Java 层实现查找功能,在宿主 <strong>Class</strong> 过多时性能可能不能达到最佳水平,如果发生查找不到、定位有误的问题欢迎向我们反馈。</p><p>由于是反射层面的 API,目前它只能通过<strong>类与成员</strong>的特征来定位指定的 <strong>Class</strong>,不能通过指定字节码中的字符串和方法内容特征来进行定位。</p><p>查找 <strong>Class</strong> 的速度取决于当前设备的性能,目前主流的移动端处理器在 <strong>10~15w</strong> 数量的 <strong>Class</strong> 中条件不算复杂的情况下大概在 <strong>3~10s</strong> 区间,条件稍微复杂的情况下最快速度能达到 <strong>25s</strong> 以内,匹配到的同类型 <strong>Class</strong> 越多速度越慢。</p></div><h4 id="开始使用" tabindex="-1"><a class="header-anchor" href="#开始使用" aria-hidden="true">#</a> 开始使用</h4><p>下面是一个简单的用法示例。</p><p>假设下面这个 <code>Class</code> 是我们想要得到的,其中的名称经过了混淆,在每个版本可能都不一样。</p><blockquote><p>示例如下</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>此时,我们想得到这个 <code>Class</code>,可以直接使用 <code>ClassLoader.searchClass</code> 方法。</p><p>在 <code>PackageParam</code> 中,你可以直接使用 <code>searchClass</code> 方法,它将自动指定 <code>appClassLoader</code>。</p><p>下方演示的条件中每一个都是可选的,条件越复杂定位越精确,同时性能也会越差。</p><blockquote><p>示例如下</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;">// 从指定的包名范围开始查找,实际使用时,你可以同时指定多个包名范围</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;">// 指定当前 Class 的 getSimpleName 的结果,你可以直接对这个字符串进行逻辑判断</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// 这里我们不确定它的名称是不是 a,可以只判断字符串长度</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;">// 指定继承的父类对象,如果是存在的 stub,可以直接用泛型表示</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;">// 指定继承的父类对象,可以直接写为完整类名,你还可以同时指定多个</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;">// 指定实现的接口,如果是存在的 stub,可以直接用泛型表示</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;">// 指定实现的接口,可以直接写为完整类名,你还可以同时指定多个</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;">// 指定构造方法的类型与样式,以及在当前类中存在的个数 count</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;">StringClass</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;">// 指定变量的类型与样式,以及在当前类中存在的个数 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;">StringClass</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;">// 指定变量的类型与样式,以及在当前类中存在的个数 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;">// 直接指定所有变量在当前类中存在的个数 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;">// 如果你认为变量的个数是不确定的,还可以使用如下自定义条件</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;">// 指定方法的类型与样式,以及在当前类中存在的个数 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;">// 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count</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;">StringClass</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;">// 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count</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;">StringClass</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;">StringClass</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;">// 指定方法的类型与样式,同时指定修饰符,以及在当前类中存在的个数 count</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;">// 指定方法的类型与样式,同时指定修饰符和模糊类型 VagueType,以及在当前类中存在的个数 count</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;">StringClass</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;">// 直接指定所有方法在当前类中存在的个数 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;">// 如果你认为方法的个数是不确定的,还可以使用如下自定义条件</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;">// 直接指定所有成员 (Member) 在当前类中存在的个数 count</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// 成员包括: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;">// 所有成员中一定存在一个 static 修饰符,可以这样加入此条件</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;">// 得到这个 Class 本身的实例,找不到会返回 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></div><div class="custom-container tip"><p class="custom-container-title">小提示</p><p>上述用法中对于 <strong>Field</strong>、<strong>Method</strong>、<strong>Constructor</strong> 的条件用法与 <a href="#member-%E6%89%A9%E5%B1%95">Member 扩展</a> 中的相关用法是一致的,仅有小部分区别。</p><p>更多功能请参考 <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="异步查找" tabindex="-1"><a class="header-anchor" href="#异步查找" aria-hidden="true">#</a> 异步查找</h4><p>默认情况下 <code>DexClassFinder</code> 会使用同步方式查找 <code>Class</code>,会阻塞当前线程直到找到或找不到发生异常为止,若查找消耗的时间过长,可能会导致宿主发生 <strong>ANR</strong> 问题。</p><p>针对上述问题,我们可以启用异步,只需要加入参数 <code>async = true</code>,这将不需要你再次启动一个线程,API 已帮你处理好相关问题。</p><div class="custom-container warning"><p class="custom-container-title">注意</p><p>对于异步情况下你需要使用 <strong>wait</strong> 方法来得到结果,<strong>get</strong> 方法将不再起作用。</p></div><blockquote><p>示例如下</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;">// 得到异步结果</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;">// 得到异步结果</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>这样我们的查找过程就是异步运行了,它将不会阻塞主线程,每个查找都将在单独的线程同时进行,可达到并行任务的效果。</p><h4 id="本地缓存" tabindex="-1"><a class="header-anchor" href="#本地缓存" aria-hidden="true">#</a> 本地缓存</h4><p>由于每次重新打开宿主都会重新进行查找,在宿主版本不变的情况下这是一种重复性能浪费。</p><p>此时我们可以通过指定 <code>name</code> 参数来对当前宿主版本的查找结果进行本地缓存,下一次将直接从本地缓存中读取查找到的类名。</p><p>本地缓存使用的是 <code>SharedPreferences</code>,它将被保存到宿主的数据目录中,在宿主版本更新后会重新进行缓存。</p><p>启用本地缓存后,将同时设置 <code>async = true</code>,你可以不需要再手动进行设置。</p><blockquote><p>示例如下</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;">// 得到异步结果</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;">// 得到异步结果</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>如果你想手动清除本地缓存,可以使用如下方法清除当前版本的宿主缓存。</p><blockquote><p>示例如下</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;">// 直接调用,在宿主的 appContext 为空时可能会失败,失败会打印警告信息</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;">// 监听宿主的生命周期后调用</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></div><p>你还可以清除指定版本的宿主缓存。</p><blockquote><p>示例如下</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;">// 直接调用,在宿主的 appContext 为空时可能会失败,失败会打印警告信息</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;">// 监听宿主的生命周期后调用</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></div><h4 id="多重查找" tabindex="-1"><a class="header-anchor" href="#多重查找" aria-hidden="true">#</a> 多重查找</h4><p>如果你需要使用固定的条件同时查找一组 <code>Class</code>,那么你只需要使用 <code>all</code> 或 <code>waitAll</code> 方法来得到结果。</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;">// 同步查找,使用 all 得到条件全部查找到的结果</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;">// 得到每个结果</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"><span style="color:#768390;">// 同步查找,使用 all { ... } 遍历每个结果</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;">// 得到每个结果</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
||
<span class="line"><span style="color:#768390;">// 异步查找,使用 waitAll 得到条件全部查找到的结果</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;">// 得到每个结果</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">小提示</p><p>更多功能请参考 <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> 方法。</p></div><h2 id="member-扩展" tabindex="-1"><a class="header-anchor" href="#member-扩展" aria-hidden="true">#</a> Member 扩展</h2><blockquote><p>这里是 <strong>Class</strong> 字节码成员变量 <strong>Field</strong>、<strong>Method</strong>、<strong>Constructor</strong> 相关的扩展功能。</p></blockquote><div class="custom-container tip"><p class="custom-container-title">小提示</p><p><strong>Member</strong> 是 <strong>Field</strong>、<strong>Method</strong>、<strong>Constructor</strong> 的接口描述对象,它在 Java 反射中为 <strong>Class</strong> 中字节码成员的总称。</p></div><p>假设有一个这样的 <code>Class</code>。</p><blockquote><p>示例如下</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="查找与反射调用" tabindex="-1"><a class="header-anchor" href="#查找与反射调用" aria-hidden="true">#</a> 查找与反射调用</h3><p>假设我们要得到 <code>Test</code>(以下统称“当前 <code>Class</code>”)的 <code>doTask</code> 方法并执行,通常情况下,我们可以使用标准的反射 API 去查找这个方法。</p><blockquote><p>示例如下</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 的实例</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;">// 使用反射 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>这种写法大概不是很友好,此时 <code>YukiHookAPI</code> 就为你提供了一个可在任意地方使用的语法糖。</p><p>以上写法换做 <code>YukiHookAPI</code> 可写作如下形式。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">StringClass</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">小提示</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder">MethodFinder</a>。</p></div><p>同样地,我们需要得到 <code>isTaskRunning</code> 变量也可以写作如下形式。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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 为 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">小提示</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder">FieldFinder</a>。</p></div><p>也许你还想得到当前 <code>Class</code> 的构造方法,同样可以实现。</p><blockquote><p>示例如下</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;">// 可创建一个新的实例</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>若想得到的是 <code>Class</code> 的无参构造方法,可写作如下形式。</p><blockquote><p>示例如下</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;">// 可创建一个新的实例</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">小提示</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder">ConstructorFinder</a>。</p></div><h3 id="可选的查找条件" tabindex="-1"><a class="header-anchor" href="#可选的查找条件" aria-hidden="true">#</a> 可选的查找条件</h3><p>假设我们要得到 <code>Class</code> 中的 <code>getName</code> 方法,可以使用如下实现。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">StringClass</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get(instance).string() </span><span style="color:#768390;">// 得到方法的结果</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>通过观察发现,这个 <code>Class</code> 中只有一个名为 <code>getName</code> 的方法,那我们可不可以再简单一点呢?</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 得到方法的结果</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>是的,对于确切不会变化的方法,你可以精简查找条件。</p><p>在只使用 <code>get</code> 或 <code>wait</code> 方法得到结果时 <code>YukiHookAPI</code> <strong>会默认按照字节码顺序匹配第一个查找到的结果</strong>。</p><p>问题又来了,这个 <code>Class</code> 中有一个 <code>release</code> 方法,但是它的方法参数很长,而且部分类型可能无法直接得到。</p><p>通常情况下我们会使用 <code>param(...)</code> 来查找这个方法,但是有没有更简单的方法呢。</p><p>此时,在确定方法唯一性后,你可以使用 <code>paramCount</code> 来查找到这个方法。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 此时我们不必确定方法参数具体类型,写个数就好</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;">// 得到这个方法</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>上述示例虽然能够匹配成功,但是不精确,此时你还可以使用 <code>VagueType</code> 来填充你不想填写的方法参数类型。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 使用 VagueType 来填充不想填写的类型,同时保证其它类型能够匹配</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringClass</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;">// 得到这个方法</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>如果你并不确定每一个参数的类型,你可以通过 <code>param { ... }</code> 方法来创建一个条件方法体。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 得到 it (Class) 方法参数类型数组实例来仅判断已知的类型和它的位置</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> param { it[</span><span style="color:#6CB6FF;">0</span><span style="color:#ADBAC7;">] </span><span style="color:#F47067;">==</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringClass</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> it[</span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">] </span><span style="color:#F47067;">==</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;">// 得到这个方法</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><div class="custom-container tip"><p class="custom-container-title">小提示</p><p>使用 <strong>param { ... }</strong> 创建一个条件方法体,其中的变量 <strong>it</strong> 即当前方法参数的 <strong>Class</strong> 类型数组实例,此时你就可以自由使用 <strong>Class</strong> 中的所有对象及其方法。</p><p>方法体末尾条件需要返回一个 <strong>Boolean</strong>,即最终的条件判断结果。</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder#type-method-1">FieldFinder.type</a>、<a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#param-method-1">MethodFinder.param</a>、<a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#returntype-method-1">MethodFinder.returnType</a>、<a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#param-method-1">ConstructorFinder.param</a> 方法。</p></div><h3 id="在父类查找" tabindex="-1"><a class="header-anchor" href="#在父类查找" aria-hidden="true">#</a> 在父类查找</h3><p>你会注意到 <code>Test</code> 继承于 <code>BaseTest</code>,现在我们想得到 <code>BaseTest</code> 的 <code>doBaseTask</code> 方法,在不知道父类名称的情况下,要怎么做呢?</p><p>参照上面的查找条件,我们只需要在查找条件中加入一个 <code>superClass</code> 即可实现这个功能。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">StringClass</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;"> 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>这个时候我们就可以在父类中取到这个方法了。</p><p><code>superClass</code> 有一个参数为 <code>isOnlySuperClass</code>,设置为 <code>true</code> 后,可以跳过当前 <code>Class</code> 仅查找当前 <code>Class</code> 的父类。</p><p>由于我们现在已知 <code>doBaseTask</code> 方法只存在于父类,可以加上这个条件节省查找时间。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">StringClass</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;"> 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>这个时候我们同样可以得到父类中的这个方法。</p><p><code>superClass</code> 一旦设置就会自动循环向后查找全部继承的父类中是否有这个方法,直到查找到目标没有父类(继承关系为 <code>java.lang.Object</code>)为止。</p><div class="custom-container tip"><p class="custom-container-title">小提示</p><p>更多功能请参考 <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> 方法。</p></div><div class="custom-container danger"><p class="custom-container-title">特别注意</p><p>当前查找的 <strong>Method</strong> 除非指定 <strong>superClass</strong> 条件,否则只能查找到当前 <strong>Class</strong> 的 <strong>Method</strong>,这是 Java 反射 API 的默认行为。</p></div><h3 id="模糊查找-1" tabindex="-1"><a class="header-anchor" href="#模糊查找-1" aria-hidden="true">#</a> 模糊查找</h3><p>如果我们想查找一个方法名称,但是又不确定它在每个版本中是否发生变化,此时我们就可以使用模糊查找功能。</p><p>假设我们要得到 <code>Class</code> 中的 <code>doTask</code> 方法,可以使用如下实现。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 设置名称不区分大小写</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;">StringClass</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>已知当前 <code>Class</code> 中仅有一个 <code>doTask</code> 方法,我们还可以判断方法名称仅包含其中指定的字符。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 仅包含 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;">StringClass</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>我们还可以根据首尾字符串进行判断。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 开头包含 do,结尾包含 Task</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;">StringClass</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>通过观察发现这个方法名称中只包含字母,我们还可以再增加一个精确的查找条件。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 开头包含 do,结尾包含 Task,仅包含字母</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;">StringClass</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">小提示</p><p>使用 <strong>name { ... }</strong> 创建一个条件方法体,其中的变量 <strong>it</strong> 即当前名称的字符串,此时你就可以在 <strong>NameRules</strong> 的扩展方法中自由使用其中的功能。</p><p>方法体末尾条件需要返回一个 <strong>Boolean</strong>,即最终的条件判断结果。</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder#name-method-1">FieldFinder.name</a>、<a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#name-method-1">MethodFinder.name</a> 方法以及 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules">NameRules</a>。</p></div><h3 id="多重查找-1" tabindex="-1"><a class="header-anchor" href="#多重查找-1" aria-hidden="true">#</a> 多重查找</h3><p>有些时候,我们可能需要查找一个 <code>Class</code> 中具有相同特征的一组方法、构造方法、变量,此时,我们就可以利用相对条件匹配来完成。</p><p>在查找条件结果的基础上,我们只需要把 <code>get</code> 换为 <code>all</code> 即可得到匹配条件的全部字节码。</p><p>假设这次我们要得到 <code>Class</code> 中方法参数个数范围在 <code>1..3</code> 的全部方法,可以使用如下实现。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 调用执行每个方法</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>上述示例可完美匹配到如下 3 个方法。</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>如果你想更加自由地定义参数个数范围的条件,可以使用如下实现。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 调用执行每个方法</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>上述示例可完美匹配到如下 6 个方法。</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>通过观察 <code>Class</code> 中有两个名称为 <code>b</code> 的方法,可以使用如下实现。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">}.all(instance).forEach { instance </span><span style="color:#F47067;">-></span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// 调用执行每个方法</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>上述示例可完美匹配到如下 2 个方法。</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">小提示</p><p>使用 <strong>paramCount { ... }</strong> 创建一个条件方法体,其中的变量 <strong>it</strong> 即当前参数个数的整数,此时你就可以在 <strong>CountRules</strong> 的扩展方法中自由使用其中的功能。</p><p>方法体末尾条件需要返回一个 <strong>Boolean</strong>,即最终的条件判断结果。</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#paramcount-method-2">MethodFinder.paramCount</a>、<a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#paramcount-method-2">ConstructorFinder.paramCount</a> 方法以及 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules">CountRules</a>。</p></div><h3 id="静态字节码" tabindex="-1"><a class="header-anchor" href="#静态字节码" aria-hidden="true">#</a> 静态字节码</h3><p>有些方法和变量在 <code>Class</code> 中是静态的实现,这个时候,我们不需要传入实例就可以调用它们。</p><p>假设我们这次要得到静态变量 <code>TAG</code> 的内容。</p><blockquote><p>示例如下</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;">StringClass</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;">}.get().string() </span><span style="color:#768390;">// Field 的类型是字符串,可直接进行 cast</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>假设 <code>Class</code> 中存在同名的非静态 <code>TAG</code> 变量,这个时候怎么办呢?</p><p>加入一个筛选条件即可。</p><blockquote><p>示例如下</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;">StringClass</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// 标识查找的这个变量需要是静态</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;">// Field 的类型是字符串,可直接进行 cast</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>我们还可以调用名为 <code>init</code> 的静态方法。</p><blockquote><p>示例如下</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>同样地,你可以标识它是一个静态。</p><blockquote><p>示例如下</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;">// 标识查找的这个方法需要是静态</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">小提示</p><p>使用 <strong>modifiers { ... }</strong> 创建一个条件方法体,此时你就可以在 <strong>ModifierRules</strong> 中自由使用其中的功能。</p><p>方法体末尾条件需要返回一个 <strong>Boolean</strong>,即最终的条件判断结果。</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder#modifiers-method">FieldFinder.modifiers</a>、<a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#modifiers-method">MethodFinder.modifiers</a>、<a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#modifiers-method">ConstructorFinder.modifiers</a> 方法以及 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules">ModifierRules</a>。</p></div><h3 id="混淆的字节码" tabindex="-1"><a class="header-anchor" href="#混淆的字节码" aria-hidden="true">#</a> 混淆的字节码</h3><p>你可能已经注意到了,这里给出的示例 <code>Class</code> 中有两个混淆的变量名称,它们都是 <code>a</code>,这个时候我们要怎么得到它们呢?</p><p>有两种方案。</p><p>第一种方案,确定变量的名称和类型。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 得到名称为 a 类型为 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>第二种方案,确定变量的类型所在的位置。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 得到第一个类型为 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>以上两种情况均可得到对应的变量 <code>private boolean a</code>。</p><p>同样地,这个 <code>Class</code> 中也有两个混淆的方法名称,它们都是 <code>b</code>。</p><p>你也可以有两种方案来得到它们。</p><p>第一种方案,确定方法的名称和方法参数。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">StringClass</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;">// 得到名称为 b 方法参数为 [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>第二种方案,确定方法的参数所在的位置。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">StringClass</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;">// 得到第一个方法参数为 [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>由于观察到这个方法在 <code>Class</code> 的最后一个,那我们还有一个备选方案。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 得到当前 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">注意</p><p>请尽量避免使用 <strong>order</strong> 来筛选字节码的下标,它们可能是不确定的,除非你确定它在这个 <strong>Class</strong> 中的位置一定不会变。</p></div><h3 id="直接调用" tabindex="-1"><a class="header-anchor" href="#直接调用" aria-hidden="true">#</a> 直接调用</h3><p>上面介绍的调用字节码的方法都需要使用 <code>get(instance)</code> 才能调用对应的方法,有没有简单一点的办法呢?</p><p>此时,你可以在任意实例上使用 <code>current</code> 方法来创建一个调用空间。</p><blockquote><p>示例如下</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 的实例</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;">// 假设这个 Class 是不能被直接得到的</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;">// 执行 doTask 方法</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;">StringClass</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;">// 执行 stop 方法</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;">// 得到 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>我们还可以用 <code>superClass</code> 调用当前 <code>Class</code> 父类的方法。</p><blockquote><p>示例如下</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 的实例</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;">// 假设这个 Class 是不能被直接得到的</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;">// 执行父类的 doBaseTask 方法</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;">StringClass</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>如果你不喜欢使用一个大括号的调用域来创建当前实例的命名空间,你可以直接使用 <code>current()</code> 方法。</p><blockquote><p>示例如下</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 的实例,这个 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;">// 执行 doTask 方法</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;">StringClass</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;">// 执行 stop 方法</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;">// 得到 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>同样地,它们之间可以连续调用,但<u><strong>不允许内联调用</strong></u>。</p><blockquote><p>示例如下</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 的实例</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;">// 假设这个 Class 是不能被直接得到的</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;">StringClass</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;">// ❗注意,因为 current() 返回的是 CurrentClass 自身对象,所以不能像下面这样调用</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></div><p>针对 <code>Field</code> 实例,还有一个便捷的方法,可以直接获取 <code>Field</code> 所在实例的对象。</p><blockquote><p>示例如下</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 的实例</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;">// 假设这个 Class 是不能被直接得到的</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;">// <方案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;">StringClass</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;">// <方案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;">StringClass</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">注意</p><p>上述 <strong>current</strong> 方法相当于帮你调用了 <strong>CurrentClass</strong> 中的 <strong>field { ... }.any()?.current()</strong> 方法。</p><p>若不存在 <strong>CurrentClass</strong> 调用域,你需要使用 <strong>field { ... }.get(instance).current()</strong> 来进行调用。</p></div><p>问题又来了,我想使用反射的方式创建如下的实例并调用其中的方法,该怎么做呢?</p><blockquote><p>示例如下</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>通常情况下,我们可以使用标准的反射 API 来调用。</p><blockquote><p>示例如下</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>但是感觉这种做法好麻烦,有没有更简洁的调用方法呢?</p><p>这个时候,我们还可以借助 <code>buildOf</code> 方法来创建一个实例。</p><blockquote><p>示例如下</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;">StringClass</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>若你希望 <code>buildOf</code> 方法返回当前实例的类型,你可以在其中加入类型泛型声明,而无需使用 <code>as</code> 来 <code>cast</code> 目标类型。</p><p>这种情况多用于实例本身的构造方法是私有的,但是里面的方法是公有的,这样我们只需要对其构造方法进行反射创建即可。</p><blockquote><p>示例如下</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 是能够直接被得到的</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">小提示</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/bean/CurrentClass">CurrentClass</a> 以及 <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#class-buildof-ext-method">Class.buildOf</a> 方法。</p></div><h3 id="原始调用" tabindex="-1"><a class="header-anchor" href="#原始调用" aria-hidden="true">#</a> 原始调用</h3><p>若你正在使用反射调用的一个方法是被 Hook 过的,此时我们如何调用其原始方法呢?</p><p>原生的 <code>XposedBridge</code> 为我们提供了一个 <code>XposedBridge.invokeOriginalMethod</code> 功能。</p><p>现在,在 <code>YukiHookAPI</code> 中你可以使用如下方法便捷地实现这个功能。</p><p>假设下面是我们要演示的 <code>Class</code>。</p><blockquote><p>示例如下</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>下面是 Hook 这个 <code>Class</code> 中 <code>getString</code> 方法的方式。</p><blockquote><p>示例如下</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;">StringClass</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>此时,我们再使用反射调用这个方法,则会得到 Hook 后的结果 <code>"Hooked"</code>。</p><blockquote><p>示例如下</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 的结果会是 "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;">StringClass</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>如果我们想得到这个方法未经 Hook 的原始方法及结果,只需要在结果中加入 <code>original</code> 即可。</p><blockquote><p>示例如下</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 的结果会是 "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;">StringClass</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">小提示</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#original-method">MethodFinder.Result.original</a> 方法。</p></div><h3 id="再次查找" tabindex="-1"><a class="header-anchor" href="#再次查找" aria-hidden="true">#</a> 再次查找</h3><p>假设有三个不同版本的 <code>Class</code>,它们都是这个宿主不同版本相同的 <code>Class</code>。</p><p>这里面同样都有一个方法 <code>doTask</code>,假设它们的功能是一样的。</p><blockquote><p>版本 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>版本 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>版本 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>我们需要在不同的版本中得到这个相同功能的 <code>doTask</code> 方法,要怎么做呢?</p><p>此时,你可以使用 <code>RemedyPlan</code> 完成你的需求。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">StringClass</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;">// 可在这里实现找到的逻辑</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;">StringClass</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;">// 可在这里实现找到的逻辑</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;">// 得到方法的结果</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">特别注意</p><p>使用了 <strong>RemedyPlan</strong> 的方法查找结果不能再使用 <strong>get</strong> 的方式得到方法实例,应当使用 <strong>wait</strong> 方法。</p></div><p>另外,你还可以在使用 <a href="#%E5%A4%9A%E9%87%8D%E6%9F%A5%E6%89%BE">多重查找</a> 的情况下继续使用 <code>RemedyPlan</code>。</p><blockquote><p>示例如下</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 的实例</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;">// 使用 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;">// 可在这里实现找到的逻辑</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;">// 可在这里实现找到的逻辑</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;">// 得到方法的结果</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>以当前 <code>Class</code> 举例,若 <a href="#%E5%A4%9A%E9%87%8D%E6%9F%A5%E6%89%BE">多重查找</a> 结合 <code>RemedyPlan</code> 在创建 Hook 的时候使用,你需要稍微改变一下用法。</p><blockquote><p>示例如下</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">小提示</p><p>在创建 Hook 的时候使用可参考 <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> 方法。</p><p>更多功能请参考 <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="相对匹配" tabindex="-1"><a class="header-anchor" href="#相对匹配" aria-hidden="true">#</a> 相对匹配</h3><p>假设宿主中不同版本中存在功能相同的 <code>Class</code> 但仅有 <code>Class</code> 的名称不一样。</p><blockquote><p>版本 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>版本 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>这个时候我们想在每个版本都调用这个 <code>Class</code> 里的 <code>doTask</code> 方法该怎么做呢?</p><p>通常做法是判断 <code>Class</code> 是否存在。</p><blockquote><p>示例如下</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</span></span>
|
||
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> currentClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </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;">// 然后再查找这个方法并调用</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>感觉这种方案非常的不优雅且繁琐,那么此时 <code>YukiHookAPI</code> 就为你提供了一个非常方便的 <code>VariousClass</code> 专门来解决这个问题。</p><p>现在,你可以直接使用以下方式获取到这个 <code>Class</code>。</p><blockquote><p>示例如下</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>若当前 <code>Class</code> 在指定的 <code>ClassLoader</code> 中存在,你可以在 <code>get</code> 中填入你的 <code>ClassLoader</code>。</p><blockquote><p>示例如下</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;">// 假设这个就是你的 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>若你不确定所有的 <code>Class</code> 一定会被匹配到,你可以使用 <code>getOrNull</code> 方法。</p><blockquote><p>示例如下</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;">// 假设这个就是你的 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>若你正在 <code>PackageParam</code> 中操作 (Xposed) 宿主环境的 <code>Class</code>,可以直接使用 <code>toClass()</code> 进行设置。</p><blockquote><p>示例如下</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">小提示</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/bean/VariousClass">VariousClass</a>。</p></div><p>若在创建 Hook 的时候使用,可以更加方便,还可以自动拦截找不到 <code>Class</code> 的异常。</p><blockquote><p>示例如下</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>你还可以把这个 <code>Class</code> 定义为一个常量类型来使用。</p><blockquote><p>示例如下</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;">// 定义常量类型</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;">// 直接使用</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">小提示</p><p>更多功能请参考 <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#findclass-method">PackageParam.findClass</a> 方法。</p></div><h3 id="调用泛型" tabindex="-1"><a class="header-anchor" href="#调用泛型" aria-hidden="true">#</a> 调用泛型</h3><p>在反射过程中,我们可能会遇到泛型问题,在泛型的反射处理上,<code>YukiHookAPI</code> 同样提供了一个可在任意地方使用的语法糖。</p><p>例如我们有如下的泛型类。</p><blockquote><p>示例如下</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>当我们想在当前 <code>Class</code> 中获得泛型 <code>T</code> 或 <code>R</code> 的 <code>Class</code> 实例,只需要如下实现。</p><blockquote><p>示例如下</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 style="color:#768390;">// 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写</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;">// 获得 R 的 Class 实例,在参数第 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;">// 你还可以使用如下写法</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;">// 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写</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;">// 获得 R 的 Class 实例,在参数第 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></div><p>当我们想在外部调用这个 <code>Class</code> 时,就可以有如下实现。</p><blockquote><p>示例如下</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;">// 假设这个就是 T 的 Class</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;">// 假设这个就是 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;">// 获得 T 的 Class 实例,在参数第 0 位,默认值可以不写,并获得其中的方法 foo 并调用</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></div><div class="custom-container tip"><p class="custom-container-title">小提示</p><p>更多功能请参考 <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> 方法以及 <a href="../public/com/highcapable/yukihookapi/hook/bean/GenericClass">GenericClass</a>。</p></div><h3 id="注意误区" tabindex="-1"><a class="header-anchor" href="#注意误区" aria-hidden="true">#</a> 注意误区</h3><blockquote><p>这里列举了使用时可能会遇到的误区部分,可供参考。</p></blockquote><h4 id="限制性查找条件" tabindex="-1"><a class="header-anchor" href="#限制性查找条件" aria-hidden="true">#</a> 限制性查找条件</h4><div class="custom-container danger"><p class="custom-container-title">特别注意</p><p>在查找条件中,除了 <strong>order</strong> 你只能使用一次 <strong>index</strong> 功能。</p></div><blockquote><p>示例如下</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;">// ❗错误的使用方法,请仅保留一个 index 方法</span></span>
|
||
<span class="line"><span style="color:#ADBAC7;"> returnType(</span><span style="color:#F69D50;">StringClass</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>以下查找条件的使用是没有任何问题的。</p><blockquote><p>示例如下</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="必要的查找条件" tabindex="-1"><a class="header-anchor" href="#必要的查找条件" aria-hidden="true">#</a> 必要的查找条件</h4><div class="custom-container danger"><p class="custom-container-title">特别注意</p><p>在普通方法查找条件中,<u><strong>即使是无参的方法也需要设置查找条件</strong></u>。</p></div><p>假设我们有如下的 <code>Class</code>。</p><blockquote><p>示例如下</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>我们要得到其中的 <code>public void foo()</code> 方法,可以写作如下形式。</p><blockquote><p>示例如下</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>但是,上面的例子<u><strong>是错误的</strong></u>。</p><p>你会发现这个 <code>Class</code> 中有两个 <code>foo</code> 方法,其中一个带有方法参数。</p><p>由于上述例子没有设置 <code>param</code> 的查找条件,得到的结果将会是匹配名称且匹配字节码顺序的第一个方法 <code>public void foo(String string)</code>,而不是我们需要的最后一个方法。</p><p>这是一个<strong>经常会出现的错误</strong>,<strong>没有方法参数就会丢失方法参数查找条件</strong>的使用问题。</p><p>正确的使用方法如下。</p><blockquote><p>示例如下</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;">// ✅ 正确的使用方法,添加详细的筛选条件</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>至此,上述的示例将可以完美地匹配到 <code>public void foo()</code> 方法。</p><div class="custom-container tip"><p class="custom-container-title">兼容性说明</p><p>在过往历史版本的 API 中是允许匹配不写默认匹配无参方法的做法的,但是最新版本更正了这一问题,请确保你使用的是最新的 API 版本。</p></div><h4 id="可简写查找条件" tabindex="-1"><a class="header-anchor" href="#可简写查找条件" aria-hidden="true">#</a> 可简写查找条件</h4><blockquote><p>在构造方法查找条件中,<u><strong>无参的构造方法可以不需要填写查找条件</strong></u>。</p></blockquote><p>假设我们有如下的 <code>Class</code>。</p><blockquote><p>示例如下</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>我们要得到其中的 <code>public TestFoo()</code> 构造方法,可以写作如下形式。</p><blockquote><p>示例如下</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>上面的例子可以成功获取到 <code>public TestFoo()</code> 构造方法,但是感觉有一些繁琐。</p><p>与普通方法不同,由于构造方法不需要考虑 <code>name</code> 名称,当构造方法没有参数的时候,我们可以省略 <code>emptyParam</code> 参数。</p><blockquote><p>示例如下</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">兼容性说明</p><p>在过往历史版本的 API 中构造方法不填写任何查找参数会直接找不到构造方法,<u><strong>这是一个 BUG,最新版本已经进行修复</strong></u>,请确保你使用的是最新的 API 版本。</p></div><h4 id="字节码类型" tabindex="-1"><a class="header-anchor" href="#字节码类型" aria-hidden="true">#</a> 字节码类型</h4><div class="custom-container danger"><p class="custom-container-title">特别注意</p><p>在字节码调用结果中,<strong>cast</strong> 方法只能指定字节码对应的类型。</p></div><p>例如我们想得到一个 <code>Boolean</code> 类型的变量,把他转换为 <code>String</code>。</p><p>以下是错误的使用方法。</p><blockquote><p>示例如下</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;">// ❗错误的使用方法,必须 cast 为字节码目标类型</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>以下是正确的使用方法。</p><blockquote><p>示例如下</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;">// ✅ 正确的使用方法,得到类型后再进行转换</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="常用类型扩展" tabindex="-1"><a class="header-anchor" href="#常用类型扩展" aria-hidden="true">#</a> 常用类型扩展</h2><p>在查找方法、变量的时候我们通常需要指定所查找的类型。</p><blockquote><p>示例如下</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;">.javaPrimitiveType</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>在 <code>Kotlin</code> 中表达出 <code>Boolean::class.javaPrimitiveType</code> 这个类型的写法很长,感觉并不方便。</p><p>因此,<code>YukiHookAPI</code> 为开发者封装了常见的类型调用,其中包含了 Android 的相关类型和 Java 的常见类型与<strong>原始类型关键字</strong>。</p><p>这个时候上面的类型就可以写作如下形式了。</p><blockquote><p>示例如下</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>在 Java 常见类型中的<strong>原始类型 (或基本类型) 关键字</strong>都已被封装为 <strong>类型 + Type</strong> 的方式,例如 <code>IntType</code>、<code>FloatType</code> (它们的字节码类型为 <code>int</code>、<code>float</code>)。</p><p>相应地,数组类型也有方便的使用方法,假设我们要获得 <code>String[]</code> 类型的数组。</p><p>需要写做 <code>java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass</code> 才能得到这个类型。</p><p>感觉是不是很麻烦,这个时候我们可以使用方法 <code>ArrayClass(StringClass)</code> 来得到这个类型。</p><p>同时由于 <code>String</code> 是常见类型,所以还可以直接使用 <code>StringArrayClass</code> 来得到这个类型。</p><p>一些常见的 Hook 中查找的方法,都有其对应的封装类型以供使用,格式为 <strong>类型 + Class</strong>。</p><p>例如 Hook <code>onCreate</code> 方法需要查找 <code>Bundle::class.java</code> 类型。</p><blockquote><p>示例如下</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><p>以下是 Java 中一些特例类型在 <code>YukiHookAPI</code> 中的封装名称。</p><ul><li><p><code>void</code> → <code>UnitType</code></p></li><li><p><code>java.lang.Void</code> → <code>UnitClass</code></p></li><li><p><code>java.lang.Object</code> → <code>AnyClass</code></p></li><li><p><code>java.lang.Integer</code> → <code>IntClass</code></p></li><li><p><code>java.lang.Character</code> → <code>CharClass</code></p></li></ul><div class="custom-container warning"><p class="custom-container-title">注意</p><p>以 <strong>类型 + Type</strong> 封装类型会且仅会表示为 Java <strong>原始类型关键字</strong>,由于 Kotlin 中不存在<strong>原始类型</strong>这个概念,所以它们都会被定义为 <strong>KClass</strong>。</p><p>Java 中共有 9 个<strong>原始类型关键字</strong>,其中 8 个为<strong>原始类型</strong>,分别为 <strong>boolean</strong>、<strong>char</strong>、<strong>byte</strong>、<strong>short</strong>、<strong>int</strong>、<strong>float</strong>、<strong>long</strong>、<strong>double</strong>,其中 <strong>void</strong> 类型是一个特例。</p><p>同时它们都有 Java 自身对应的封装类型,例如 <strong>java.lang.Boolean</strong>、<strong>java.lang.Integer</strong>,这些类型是<u><strong>不相等的</strong></u>,请注意区分。</p><p>同样地,数组也有对应的封装类型,它们也需要与 Java <strong>原始类型关键字</strong> 进行区分。</p><p>例如 <strong>byte[]</strong> 的封装类型为 <strong>ByteArrayType</strong> 或 <strong>ArrayClass(ByteType)</strong>,而 <strong>Byte[]</strong> 的封装类型为 <strong>ByteArrayClass</strong> 或 <strong>ArrayClass(ByteClass)</strong>,这些类型也是<u><strong>不相等的</strong></u>。</p></div><div class="custom-container tip"><p class="custom-container-title">小提示</p><p>更多类型可查看 <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>同时,欢迎你能贡献更多的常用类型。</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-source/src/zh-cn/api/special-features/reflection.md" 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">在新窗口中打开</span></span><!--[--><!--]--></a></div><div class="meta-item last-updated"><span class="meta-item-label">上次更新: </span><!----></div><div class="meta-item contributors"><span class="meta-item-label">贡献者: </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/zh-cn/api/special-features/logger.html" class="" aria-label="调试日志"><!--[--><!--]--> 调试日志 <!--[--><!--]--></a></span></p></nav><!--[--><!--]--></main><!--]--></div><!----><!--]--></div>
|
||
<script type="module" src="/YukiHookAPI/assets/app.65ee8e4f.js" defer></script>
|
||
</body>
|
||
</html>
|