mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
839 lines
210 KiB
JavaScript
839 lines
210 KiB
JavaScript
import{_ as e,r as l,o,c as p,b as s,d as t,a as n,e as c}from"./app.fb8271cf.js";const i={},r=n(`<h1 id="reflection-extensions" tabindex="-1"><a class="header-anchor" href="#reflection-extensions" aria-hidden="true">#</a> Reflection Extensions</h1><blockquote><p><code>YukiHookAPI</code> encapsulates a set of reflection API with near-zero reflection writing for developers, which can almost completely replace the usage of reflection API in Java.</p></blockquote><h2 id="class-extensions" tabindex="-1"><a class="header-anchor" href="#class-extensions" aria-hidden="true">#</a> Class Extensions</h2><blockquote><p>Here are the extension functions related to the <strong>Class</strong> object itself.</p></blockquote><h3 id="object-conversion" tabindex="-1"><a class="header-anchor" href="#object-conversion" aria-hidden="true">#</a> Object Conversion</h3><p>Suppose we want to get a <code>Class</code> that cannot be called directly.</p><p>Normally, we can use the standard reflection API to find this <code>Class</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Class in the default ClassLoader environment</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Class</span><span style="color:#ADBAC7;">.forName(</span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#768390;">// Specify the Class in the ClassLoader environment</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> custom</span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;">.loadClass(</span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This is probably not very friendly, and <code>YukiHookAPI</code> provides you with a syntactic sugar that can be used anywhere.</p><p>The above writing can be written as <code>YukiHookAPI</code> as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Get this Class directly</span></span>
|
|
<span class="line"><span style="color:#768390;">// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClass()</span></span>
|
|
<span class="line"><span style="color:#768390;">// ClassLoader where the custom Class is located</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClass(customClassLoader)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If the current <code>Class</code> does not exist, using the above method will throw an exception.</p><p>If you are not sure whether the <code>Class</code> exists, you can refer to the following solutions.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Get this Class directly</span></span>
|
|
<span class="line"><span style="color:#768390;">// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader</span></span>
|
|
<span class="line"><span style="color:#768390;">// If not available, the result will be null but no exception will be thrown</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClassOrNull()</span></span>
|
|
<span class="line"><span style="color:#768390;">// ClassLoader where the custom Class is located</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
|
<span class="line"><span style="color:#768390;">// If not available, the result will be null but no exception will be thrown</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClassOrNull(customClassLoader)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We can also get an existing <code>Class</code> object by mapping.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this Class can be obtained directly</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> classOf</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Test</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// We can also customize the ClassLoader where the Class is located, which is very effective for stubs</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> classOf</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Test</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">(customClassLoader)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#classof-method">classOf</a>, <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#string-toclass-ext-method">String.toClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#string-toclassornull-ext-method">String.toClassOrNull</a>, <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#string-variousclass-toclass-i-ext-method">PackageParam \u2192 String+ VariousClass.toClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#string-variousclass-toclassornull-i-ext-method">PackageParam \u2192 String+VariousClass.toClassOrNull</a> methods.</p></div><h3 id="existential-judgment" tabindex="-1"><a class="header-anchor" href="#existential-judgment" aria-hidden="true">#</a> Existential Judgment</h3><p>Suppose we want to determine whether a <code>Class</code> exists.</p><p>Usually, we can use the standard reflection API to find this <code>Class</code> to determine whether it exists by exception.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Class in the default ClassLoader environment</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> isExist </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">try</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Class</span><span style="color:#ADBAC7;">.forName(</span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">} </span><span style="color:#F47067;">catch</span><span style="color:#ADBAC7;"> (_</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Throwable</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">false</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"><span style="color:#768390;">// Specify the Class in the ClassLoader environment</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> isExist </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">try</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> custom</span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;">.loadClass(</span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">} </span><span style="color:#F47067;">catch</span><span style="color:#ADBAC7;"> (_</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Throwable</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">false</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This is probably not very friendly, and <code>YukiHookAPI</code> provides you with a syntactic sugar that can be used anywhere.</p><p>The above writing can be written as <code>YukiHookAPI</code> as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Check if this class exists</span></span>
|
|
<span class="line"><span style="color:#768390;">// If you are currently in the PackageParam environment, then you don't need to consider ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> isExist </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.hasClass()</span></span>
|
|
<span class="line"><span style="color:#768390;">// ClassLoader where the custom Class is located</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> isExist </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.hasClass(customClassLoader)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#string-hasclass-ext-method">String.hasClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#string-hasclass-i-ext-method">PackageParam \u2192 String.hasClass</a> methods.</p></div>`,31),d={id:"vague-search",tabindex:"-1"},y=s("a",{class:"header-anchor",href:"#vague-search","aria-hidden":"true"},"#",-1),A=c(" Vague Search\u2002"),u=n(`<p>The <code>Class</code> name in the Host App's <strong>Dex</strong> after being obfuscated by tools such as R8 will be difficult to distinguish.</p><p>Its correct position is uncertain, and cannot be obtained directly through <a href="#object-conversion">Object Conversion</a>.</p><p>At this point, there is <code>DexClassFinder</code>, its role is to determine the instance of this <code>Class</code> by the bytecode features in the <code>Class</code> that need to be searched.</p><div class="custom-container warning"><p class="custom-container-title">Notice</p><p>At present, the function of <strong>DexClassFinder</strong> is still in the experimental stage.</p><p>Since the search function is only implemented through the Java layer, the performance may not reach the optimal level when there are too many Host App's <strong>Class</strong>.</p><p>If something got wrong welcome to feedback.</p><p>Since it is a reflection-level API, currently it can only locate the specified <strong>Class</strong> through the characteristics of <strong>Class and Member</strong>, and cannot locate it by specifying the string and method content characteristics in the bytecode.</p><p>The speed of searching <strong>Class</strong> depends on the performance of the current device.</p><p>At present, the mainstream mobile processors are in the <strong>3~10s</strong> range when the conditions are not complicated in the <strong>10~15w</strong> number of <strong>Class</strong>, the fastest speed can reach within <strong>25s</strong> under slightly complex conditions.</p><p>Please note that the more the same type <strong>Class</strong> is matched, the slower the speed.</p></div><h4 id="get-started" tabindex="-1"><a class="header-anchor" href="#get-started" aria-hidden="true">#</a> Get Started</h4><p>Below is a simple usage example.</p><p>Suppose the following <code>Class</code> is what we want, the names are obfuscated and may be different in each version.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">package</span><span style="color:#ADBAC7;"> com.demo;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">a</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">extends</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">Activity</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">implements</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">Serializable</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">a;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">b;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">boolean</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">a;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">protected</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(Bundle </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">(</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">, String </span><span style="color:#F69D50;">var2</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">a</span><span style="color:#ADBAC7;">(</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">var1</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">a</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">var2</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">b</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">var3</span><span style="color:#ADBAC7;">, String </span><span style="color:#F69D50;">var4</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><p>At this point, we want to get this <code>Class</code>, you can use the <code>ClassLoader.searchClass</code> method directly.</p><p>In <code>PackageParam</code> you can use the <code>searchClass</code> method directly and it will automatically specify the <code>appClassLoader</code>.</p><p>Each of the conditions demonstrated below is optional, and the more complex the conditions, the more accurate the positioning and the worse the performance.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">searchClass {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Start the search from the specified package name range</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// In actual use, you can specify multiple package name ranges at the same time</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> from(</span><span style="color:#96D0FF;">"com.demo"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the result of getSimpleName of the current Class</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You can directly make logical judgments on this string</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Here we are not sure whether its name is a, we can only judge the length of the string</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> simpleName { it.length </span><span style="color:#F47067;">==</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the inherited parent class object</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// If it is an existing stub, it can be directly represented by generics</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> extends</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Activity</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the inherited parent class object</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Which can be written directly as the full class name</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And you can also specify multiple objects at the same time</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> extends(</span><span style="color:#96D0FF;">"android.app.Activity"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the implemented interface</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// If it exists stub, can be directly represented by generics</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> implements</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Serializable</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the implemented interface</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Which can be written directly as a full class name, or you can specify multiple at the same time</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> implements(</span><span style="color:#96D0FF;">"java.io.Serializable"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the constructor</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number count that exists in the current class</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;"> { param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">) }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the variable</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number that exists in the current class count</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> field { type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the variable</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number that exists in the current class count</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> field { type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Directly specify the number of all variables that exist in the current class count</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> field().count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// If you think the number of variables is indeterminate</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You can also use the following custom conditions</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> field().count(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> field().count { it </span><span style="color:#F47067;">>=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number that exists in the current class count</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"onCreate"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BundleClass</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the modifier, and the number count in the current class</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> modifiers { isStatic </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> isPrivate }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">UnitType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the modifier, and the number count in the current class</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> modifiers { isPrivate </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> isStatic.</span><span style="color:#F47067;">not</span><span style="color:#ADBAC7;">() }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the modifier, and the number count in the current class</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> modifiers { isPrivate </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> isStatic.</span><span style="color:#F47067;">not</span><span style="color:#ADBAC7;">() }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">UnitType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify the type and style of the method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// As well as the modifier and VagueType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// And the number count that exists in the current class</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> modifiers { isPrivate </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> isStatic.</span><span style="color:#F47067;">not</span><span style="color:#ADBAC7;">() }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">VagueType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">VagueType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">UnitType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Directly specify the number of all methods that exist in the current class count</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method().count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">5</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// If you think the number of methods is uncertain, you can also use the following custom conditions</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method().count(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">5</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method().count { it </span><span style="color:#F47067;">>=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">5</span><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Directly specify the number of all members existing in the current class count</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Members include: Field, Method, Constructor</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> member().count(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">9</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// There must be a static modifier in all members, you can add this condition like this</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> member {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> modifiers { isStatic }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get() </span><span style="color:#768390;">// Get the instance of this Class itself, if not found, it will return null</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>The conditional usage of <strong>Field</strong>, <strong>Method</strong>, <strong>Constructor</strong> in the above usage is consistent with the related usage in <a href="#member-extensions">Member Extensions</a>, with only minor differences.</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MemberRules">MemberRules</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/FieldRules">FieldRules</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/MethodRules">MethodRules</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/classes/rules/ConstructorRules">ConstructorRules</a>.</p></div><h4 id="asynchronous-search" tabindex="-1"><a class="header-anchor" href="#asynchronous-search" aria-hidden="true">#</a> Asynchronous Search</h4><p>By default, <code>DexClassFinder</code> will use synchronous mode to search <code>Class</code>, which will block the current thread until it finds or finds an exception.</p><p>If the search takes too long, it may cause <strong>ANR</strong> problems to the Host App.</p><p>In response to the above problems, we can enable asynchronous, just add the parameter <code>async = true</code>, which will not require you to start a thread again, the API has already handled the related problems for you.</p><div class="custom-container warning"><p class="custom-container-title">Notice</p><p>For the asynchronous case you need to use the <strong>wait</strong> method to get the result, the <strong>get</strong> method will no longer work.</p></div><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">searchClass(async </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.wait { class1 </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get asynchronous result</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">searchClass(async </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.wait { class2 </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get asynchronous result</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>In this way, our search process runs asynchronously, it will not block the main thread, and each search will be performed in a separate thread at the same time, which can achieve the effect of parallel tasks.</p><h4 id="local-cache" tabindex="-1"><a class="header-anchor" href="#local-cache" aria-hidden="true">#</a> Local Cache</h4><p>Since the search is performed again every time the Host App is reopened, this is a waste of repetitive performance when the Host App's version is unchanged.</p><p>At this point, we can locally cache the search results of the current Host App's version by specifying the <code>name</code> parameter.</p><p>Next time, the found class name will be directly read from the local cache.</p><p>The local cache uses <code>SharedPreferences</code>, which will be saved to the Host App's data directory and will be re-cached after the Host App's version is updated.</p><p>After enabling the local cache, <code>async = true</code> will be set at the same time, you don't need to set it manually.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">searchClass(name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.class1"</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.wait { class1 </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get asynchronous result</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">searchClass(name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.class2"</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.wait { class2 </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get asynchronous result</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you want to clear the local cache manually, you can use the following method to clear the current version of the Host App's cache.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Call it directly</span></span>
|
|
<span class="line"><span style="color:#768390;">// It may fail when the Host App's appContext is null, and a warning message will be printed on failure</span></span>
|
|
<span class="line"><span style="color:#F69D50;">DexClassFinder</span><span style="color:#ADBAC7;">.clearCache()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Called after listening to the lifecycle of the Host App</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">onAppLifecycle {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> onCreate {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">DexClassFinder</span><span style="color:#ADBAC7;">.clearCache(context </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">this</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>You can also clear the Host App's cache for a specific version.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Call it directly</span></span>
|
|
<span class="line"><span style="color:#768390;">// It may fail when the Host App's appContext is null, and a warning message will be printed on failure</span></span>
|
|
<span class="line"><span style="color:#F69D50;">DexClassFinder</span><span style="color:#ADBAC7;">.clearCache(versionName </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"1.0"</span><span style="color:#ADBAC7;">, versionCode </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#768390;">// Called after listening to the lifecycle of the Host App</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">onAppLifecycle {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> onCreate {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">DexClassFinder</span><span style="color:#ADBAC7;">.clearCache(context </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">this</span><span style="color:#ADBAC7;">, versionName </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"1.0"</span><span style="color:#ADBAC7;">, versionCode </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="multiple-search" tabindex="-1"><a class="header-anchor" href="#multiple-search" aria-hidden="true">#</a> Multiple Search</h4><p>If you need to search a set of <code>Class</code> at the same time using a fixed condition, then you only need to use the <code>all</code> or <code>waitAll</code> method to get the result.</p><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Synchronous search, use all to get all the results found by the conditions</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">searchClass {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.all().forEach { clazz </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get each result</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"><span style="color:#768390;">// Synchronous search, using all { ... } to iterate over each result</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">searchClass {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.all { clazz </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get each result</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"><span style="color:#768390;">// Asynchronous search, use waitAll to get all the results found by the conditions</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">searchClass(async </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.waitAll { classes </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> classes.forEach {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get each result</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#classloader-searchclass-ext-method">ClassLoader.searchClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#searchclass-method">PackageParam.searchClass</a> methods.</p></div><h2 id="member-extensions" tabindex="-1"><a class="header-anchor" href="#member-extensions" aria-hidden="true">#</a> Member Extensions</h2><blockquote><p>Here are the extension functions related to the <strong>Class</strong> bytecode member variables <strong>Field</strong>, <strong>Method</strong>, <strong>Constructor</strong>.</p></blockquote><div class="custom-container tip"><p class="custom-container-title">Tips</p><p><strong>Member</strong> is the interface description object of <strong>Field</strong>, <strong>Method</strong>, <strong>Constructor</strong>, which is the general term for the bytecode members in <strong>Class</strong> in Java reflection.</p></div><p>Suppose there is such a <code>Class</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">package</span><span style="color:#ADBAC7;"> com.demo;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BaseTest</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">BaseTest</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">BaseTest</span><span style="color:#ADBAC7;">(</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">isInit</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doBaseTask</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">package</span><span style="color:#ADBAC7;"> com.demo;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">extends</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">BaseTest</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">Test</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">Test</span><span style="color:#ADBAC7;">(</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">isInit</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> TAG </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"Test"</span><span style="color:#ADBAC7;">;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> BaseTest</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">baseInstance;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">a;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">boolean</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">a;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">boolean</span><span style="color:#F69D50;"> </span><span style="color:#ADBAC7;">isTaskRunning</span><span style="color:#F69D50;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">false</span><span style="color:#ADBAC7;">;</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">init</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">release</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">, Function<</span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;">, </span><span style="color:#F47067;">String</span><span style="color:#ADBAC7;">> </span><span style="color:#F69D50;">task</span><span style="color:#ADBAC7;">, </span><span style="color:#F47067;">boolean</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">isFinish</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">stop</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> String </span><span style="color:#DCBDFB;">getName</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">b</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">private</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">b</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">a</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><h3 id="find-and-reflection" tabindex="-1"><a class="header-anchor" href="#find-and-reflection" aria-hidden="true">#</a> Find and Reflection</h3><p>Suppose we want to get the <code>doTask</code> method of <code>Test</code> and execute it.</p><p>Normally, we can use the standard reflection API to find this method.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using reflection API</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .getDeclaredMethod(</span><span style="color:#96D0FF;">"doTask"</span><span style="color:#ADBAC7;">, String::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#6CB6FF;">apply</span><span style="color:#ADBAC7;"> { isAccessible </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .invoke(instance, </span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This is probably not very friendly, and <code>YukiHookAPI</code> provides you with a syntactic sugar that can be used anywhere.</p><p>The above writing can be written as <code>YukiHookAPI</code> as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more features, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder">MethodFinder</a>.</p></div><p>Similarly, we need to get the <code>isTaskRunning</code> field can also be written as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"isTaskRunning"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).any() </span><span style="color:#768390;">// Any instantiates an object of any type of Field</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more features, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder">FieldFinder</a>.</p></div><p>Maybe you also want to get the current <code>Class</code> constructor, the same can be achieved.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.</span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().call(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) </span><span style="color:#768390;">// Can create a new instance</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you want to get the no-argument constructor of <code>Class</code>, you can write it as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.</span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;">().get().call() </span><span style="color:#768390;">// Create a new instance</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more features, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder">ConstructorFinder</a>.</p></div><h3 id="optional-find-conditions" tabindex="-1"><a class="header-anchor" href="#optional-find-conditions" aria-hidden="true">#</a> Optional Find Conditions</h3><p>Suppose we want to get the <code>getName</code> method in <code>Class</code>, which can be implemented as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getName"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).string() </span><span style="color:#768390;">// Get the result of the method</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Through observation, it is found that there is only one method named <code>getName</code> in this <code>Class</code>, so can we make it simpler?</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getName"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).string() </span><span style="color:#768390;">// Get the result of the method</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Yes, you can refine your find criteria for methods that do not change exactly.</p><p>When using only <code>get</code> or <code>wait</code> methods to get results, <code>YukiHookAPI</code> <strong>will match the first found result in bytecode order</strong> by default.</p><p>The problem comes again, this <code>Class</code> has a <code>release</code> method, but its method parameters are very long, and some types may not be directly available.</p><p>Normally we would use <code>param(...)</code> to find this method, but is there an easier way.</p><p>At this point, after determining the uniqueness of the method, you can use <code>paramCount</code> to find the method.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"release"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// At this point</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// We don't have to determine the specific type of method parameters, just write the number</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> paramCount </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">3</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance) </span><span style="color:#768390;">// Get this method</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Although the above example can be successfully matched, it is not accurate.</p><p>At this time, you can also use <code>VagueType</code> to fill in the method parameter type that you do not want to fill in.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"release"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Use VagueType to fill in the type you don't want to fill in</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// While ensuring that other types can match</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">VagueType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance) </span><span style="color:#768390;">// Get this method</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h3 id="find-in-super-class" tabindex="-1"><a class="header-anchor" href="#find-in-super-class" aria-hidden="true">#</a> Find in Super Class</h3><p>You will notice that <code>Test</code> extends <code>BaseTest</code>, now we want to get the <code>doBaseTask</code> method of <code>BaseTest</code>, how do we do it without knowing the name of the super class?</p><p>Referring to the above find conditions, we only need to add a <code>superClass</code> to the find conditions to achieve this function.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Just add this condition</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> superClass()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>At this time, we can get this method in the super class.</p><p><code>superClass</code> has a parameter <code>isOnlySuperClass</code>, when set to <code>true</code>, you can skip the current <code>Class</code> and only find the super class of the current <code>Class</code>.</p><p>Since we now know that the <code>doBaseTask</code> method only exists in the super class, this condition can be added to save finding time.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Add a find condition</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> superClass(isOnlySuperClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>At this time, we can also get this method in the super class.</p><p>Once <code>superClass</code> is set, it will automatically cycle backward to find out whether this method exists in all extends super classes, until it finds that the target has no super class (the extends is <code>java.lang.Object</code>).</p><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#superclass-method">MethodFinder.superClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#superclass-method">ConstructorFinder.superClass</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder#superclass-method">FieldFinder.superClass</a> methods.</p></div><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>The currently founded <strong>Method</strong> can only find the <strong>Method</strong> of the current <strong>Class</strong> unless the <strong>superClass</strong> condition is specified, which is the default behavior of the Java Reflection API.</p></div><h3 id="vague-find" tabindex="-1"><a class="header-anchor" href="#vague-find" aria-hidden="true">#</a> Vague Find</h3><p>If we want to find a method name, but are not sure if it has changed in each release, we can use vague find.</p><p>Suppose we want to get the <code>doTask</code> method in <code>Class</code>, which can be implemented as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Set name is case insensitive</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> it.equals(</span><span style="color:#96D0FF;">"dotask"</span><span style="color:#ADBAC7;">, isIgnoreCase </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Knowing that there is currently only one <code>doTask</code> method in <code>Class</code>, we can also judge that the method name contains only the characters specified in it.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Only contains oTas</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> it.contains(</span><span style="color:#96D0FF;">"oTas"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We can also judge based on the first and last strings.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Contains do at the beginning and Task at the end</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> it.startsWith(</span><span style="color:#96D0FF;">"do"</span><span style="color:#ADBAC7;">) </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> it.endsWith(</span><span style="color:#96D0FF;">"Task"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>By observing that this method name contains only letters, we can add a precise search condition.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Start with do, end with Task, just letters</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> it.startsWith(</span><span style="color:#96D0FF;">"do"</span><span style="color:#ADBAC7;">) </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> it.endsWith(</span><span style="color:#96D0FF;">"Task"</span><span style="color:#ADBAC7;">) </span><span style="color:#F47067;">&&</span><span style="color:#ADBAC7;"> it.isOnlyLetters()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>Use <strong>name { ... }</strong> to create a conditional method body, where the variable <strong>it</strong> is the string of the current name, and you can freely use it in the extension method of <strong>NameRules</strong> function.</p><p>The condition at the end of the method body needs to return a <strong>Boolean</strong>, which is the final condition judgment result.</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/NameRules">NameRules</a>.</p></div><h3 id="multiple-find" tabindex="-1"><a class="header-anchor" href="#multiple-find" aria-hidden="true">#</a> Multiple Find</h3><p>Sometimes, we may need to find a set of methods, constructors, and fields with the same characteristics in a <code>Class</code>.</p><p>At this time, we can use relative condition matching to complete.</p><p>Based on the result of the find condition, we only need to replace <code>get</code> with <code>all</code> to get all the bytecodes that match the condition.</p><p>Suppose this time we want to get all methods in <code>Class</code> with the number of method parameters in the range <code>1..3</code>, you can use the following implementation.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.all(instance).forEach { instance </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Call and execute each method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> instance.call(...)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The above example can be perfectly matched to the following 3 methods.</p><p><code>private void doTask(String taskName)</code></p><p><code>private void release(String taskName, Function<boolean, String> task, boolean isFinish)</code></p><p><code>private void b(String a)</code></p><p>If you want to define the conditions for the range of the number of parameters more freely, you can use the following implementation.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> paramCount { it </span><span style="color:#F47067;"><</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">3</span><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.all(instance).forEach { instance </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Call and execute each method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> instance.call(...)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The above example can be perfectly matched to the following 6 methods.</p><p><code>private static void init()</code></p><p><code>private void doTask(String taskName)</code></p><p><code>private void stop(String a)</code></p><p><code>private void getName(String a)</code></p><p><code>private void b()</code></p><p><code>private void b(String a)</code></p><p>By observing that there are two methods named <code>b</code> in <code>Class</code>, you can use the following implementation.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHook API</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"b"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.all(instance).forEach { instance </span><span style="color:#F47067;">-></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Call and execute each method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> instance.call(...)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The above example can be perfectly matched to the following 2 methods.</p><p><code>private void b()</code></p><p><code>private void b(String a)</code></p><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>Use <strong>paramCount { ... }</strong> to create a conditional method body, where the variable <strong>it</strong> is the integer of the current number of parameters, and you can use it freely in the extension method of <strong>CountRules</strong> function in it.</p><p>The condition at the end of the method body needs to return a <strong>Boolean</strong>, which is the final condition judgment result.</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/CountRules">CountRules</a>.</p></div><h3 id="static-bytecode" tabindex="-1"><a class="header-anchor" href="#static-bytecode" aria-hidden="true">#</a> Static Bytecode</h3><p>Some methods and fields are statically implemented in <code>Class</code>, at this time, we can call them without passing in an instance.</p><p>Suppose we want to get the contents of the static field <code>TAG</code> this time.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"TAG"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().string() </span><span style="color:#768390;">// The type of Field is string and can be cast directly</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Assuming that there is a non-static <code>TAG</code> field with the same name in <code>Class</code>, what should I do at this time?</p><p>Just add a filter.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"TAG"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// This field to identify the lookup needs to be static</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> modifiers { isStatic }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().string() </span><span style="color:#768390;">// The type of Field is string and can be cast directly</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We can also call a static method called <code>init</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"init"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Likewise, you can identify it as a static.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"init"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// This method of identity find needs to be static</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> modifiers { isStatic }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>Use <strong>modifiers { ... }</strong> to create a conditional method body, at which point you can freely use its functionality in <strong>ModifierRules</strong>.</p><p>The condition at the end of the method body needs to return a <strong>Boolean</strong>, which is the final condition judgment result.</p><p>For more features, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/base/rules/ModifierRules">ModifierRules</a>.</p></div><h3 id="obfuscated-bytecode" tabindex="-1"><a class="header-anchor" href="#obfuscated-bytecode" aria-hidden="true">#</a> Obfuscated Bytecode</h3><p>You may have noticed that the example <code>Class</code> given here has two obfuscated field names, both of which are <code>a</code>, how do we get them at this time?</p><p>There are two options.</p><p>The first option is to determine the name and type of the field.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"a"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).any() </span><span style="color:#768390;">// Get a field named a with type Boolean</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The second option is to determine where the type of the field is located.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">).index().first()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).any() </span><span style="color:#768390;">// Get the first field of type Boolean</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>In the above two cases, the corresponding field <code>private boolean a</code> can be obtained.</p><p>Likewise, there are two obfuscated method names in this <code>Class</code>, both of which are <code>b</code>.</p><p>You can also have two options to get them.</p><p>The first option is to determine the method name and method parameters.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"b"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"test_string"</span><span style="color:#ADBAC7;">) </span><span style="color:#768390;">// Get the method whose name is b and whose parameter is [String]</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The second option is to determine where the parameters of the method are located.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">).index().first()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"test_string"</span><span style="color:#ADBAC7;">) </span><span style="color:#768390;">// Get the method whose first method parameter is [String]</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Since it is observed that this method is last in <code>Class</code>, then we have an alternative.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> order().index().last()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get(instance).call(</span><span style="color:#96D0FF;">"test_string"</span><span style="color:#ADBAC7;">) </span><span style="color:#768390;">// Get the last method of the current Class</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container warning"><p class="custom-container-title">Notice</p><p>Please try to avoid using <strong>order</strong> to filter bytecode subscripts, they may be indeterminate unless you are sure that its position in this <strong>Class</strong> must not change.</p></div><h3 id="directly-called" tabindex="-1"><a class="header-anchor" href="#directly-called" aria-hidden="true">#</a> Directly Called</h3><p>The methods of calling bytecode described above all need to use <code>get(instance)</code> to call the corresponding method.</p><p>Is there a simpler way?</p><p>At this point, you can use the <code>current</code> method on any instance to create a call space.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Assume this Class is not directly available</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">instance.current {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Execute the doTask method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Execute the stop method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"stop"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get name</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> method { name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getName"</span><span style="color:#ADBAC7;"> }.string()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>We can also use <code>superClass</code> to call methods of the current <code>Class</code> super class.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Assume this Class is not directly available</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">instance.current {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Execute the doBaseTask method of the parent class</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> superClass().method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you don't like to use a lambda to create the namespace of the current instance, you can use the <code>current()</code> method directly.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assuming this is an instance of this Class, this Class cannot be obtained directly</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Execute the doTask method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">instance</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .current()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#768390;">// Execute the stop method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">instance</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .current()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"stop"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Get name</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> instance.current().method { name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getName"</span><span style="color:#ADBAC7;"> }.string()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Likewise, consecutive calls can be made between them, but <u><strong>inline calls are not allowed</strong></u>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Assume this Class is not directly available</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">instance.current {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.current()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"stop"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call()</span></span>
|
|
<span class="line"><span style="color:#768390;">// \u2757 Note that because current() returns the CurrentClass object itself</span></span>
|
|
<span class="line"><span style="color:#768390;">// It CANNOT BE CALLED like the following</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">instance.current().current()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>For <code>Field</code> instances, there is also a convenience method that can directly get the object of the instance where <code>Field</code> is located.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Assume this Class is not directly available</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">instance.current {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Plan 1></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"baseInstance"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.current {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Plan 2></span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"baseInstance"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.current()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> ?.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doBaseTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }?.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container warning"><p class="custom-container-title">Notice</p><p>The above <strong>current</strong> method is equivalent to calling the <strong>field { ... }.any()?.current()</strong> method in <strong>CurrentClass</strong> for you.</p><p>If there is no <strong>CurrentClass</strong> calling field, you need to use <strong>field { ... }.get(instance).current()</strong> to call it.</p></div><p>The problem comes again, I want to use reflection to create the following instance and call the method in it, how to do it?</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">).doTask(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>Usually, we can use the standard reflection API to call.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClass()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .getDeclaredConstructor(Boolean::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#6CB6FF;">apply</span><span style="color:#ADBAC7;"> { isAccessible </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .newInstance(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#6CB6FF;">apply</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> javaClass</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .getDeclaredMethod(</span><span style="color:#96D0FF;">"doTask"</span><span style="color:#ADBAC7;">, String::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#6CB6FF;">apply</span><span style="color:#ADBAC7;"> { isAccessible </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .invoke(</span><span style="color:#6CB6FF;">this</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>But I feel that this approach is very troublesome.</p><p>Is there a more concise way to call it?</p><p>At this time, we can also use the <code>buildOf</code> method to create an instance.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#96D0FF;">"com.demo.Test"</span><span style="color:#ADBAC7;">.toClass().buildOf(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) { param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">) }?.current {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.call(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you want the <code>buildOf</code> method to return the type of the current instance, you can include a type-generic declaration in it instead of using <code>as</code> to <code>cast</code> the target type.</p><p>In this case, the constructor of the instance itself is private, but the method inside is public, so we only need to create its constructor by reflection.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this Class can be obtained directly</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> test </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.buildOf</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">Test</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">(</span><span style="color:#6CB6FF;">true</span><span style="color:#ADBAC7;">) { param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">) }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">test.doTask(</span><span style="color:#96D0FF;">"task_name"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/bean/CurrentClass">CurrentClass</a> and <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#class-buildof-ext-method">Class.buildOf</a> method.</p></div><h3 id="original-called" tabindex="-1"><a class="header-anchor" href="#original-called" aria-hidden="true">#</a> Original Called</h3><p>If you are using reflection to call a method that has been hooked, how do we call its original method?</p><p>The native <code>XposedBridge</code> provides us with a <code>XposedBridge.invokeOriginalMethod</code> function.</p><p>Now, in <code>YukiHookAPI</code> you can use the following method to implement this function conveniently.</p><p>Suppose below is the <code>Class</code> we want to demonstrate.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> String </span><span style="color:#DCBDFB;">getString</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">return</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"Original"</span><span style="color:#ADBAC7;">;</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><p>Here's how the <code>getString</code> method in this <code>Class</code> Hooks.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.hook {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> injectMember {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getString"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> replaceTo(</span><span style="color:#96D0FF;">"Hooked"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>At this point, we use reflection to call this method, and we will get the result of Hook <code>"Hooked"</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Result will be "Hooked"</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> result </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getString"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().string()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If we want to get the original method and result of this method without hooking, we just need to add <code>original</code> to the result.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Result will be "Original"</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> result </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"getString"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">StringType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().original().string()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to the <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#original-method">MethodFinder.Result.original</a> method.</p></div><h3 id="find-again" tabindex="-1"><a class="header-anchor" href="#find-again" aria-hidden="true">#</a> Find Again</h3><p>Suppose there are three different versions of <code>Class</code>, all of which are the same <code>Class</code> for different versions of this Host App.</p><p>There is also a method <code>doTask</code> in it, assuming they function the same.</p><blockquote><p>The following example of version A</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><blockquote><p>The following example of version B</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><blockquote><p>The following example of version C</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">taskName</span><span style="color:#ADBAC7;">, </span><span style="color:#F47067;">int</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">type</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><p>We need to get this same functionality of the <code>doTask</code> method in a different version, how do we do it?</p><p>At this point, you can use <code>RemedyPlan</code> to complete your needs.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.remedys {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.onFind {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Found logic can be implemented here</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">IntType</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.onFind {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Found logic can be implemented here</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.wait(instance) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the result of the method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>The method lookup result using <strong>RemedyPlan</strong> can no longer use <strong>get</strong> to get method instance, you should use <strong>wait</strong> method.</p></div><p>Also, you can continue to use <code>RemedyPlan</code> while using <a href="#multiple-find">Multiple Find</a>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is an instance of this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> instance </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Call and execute using YukiHookAPI</span></span>
|
|
<span class="line"><span style="color:#F69D50;">Test</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.remedys {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">0</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.onFind {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Found logic can be implemented here</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.onFind {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Found logic can be implemented here</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.waitAll(instance) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the result of the method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Take the current <code>Class</code> as an example, if <a href="#multiple-find">Multiple Find</a> is used in conjunction with <code>RemedyPlan</code> when creating a Hook, you need to change the usage slightly.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">injectMember {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.remedys {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">0</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> paramCount(</span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">..</span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }.all()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> beforeHook {}</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> afterHook {}</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>When creating a Hook, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#all-method">MethodFinder.Process.all</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#all-method">ConstructorFinder.Process.all</a> methods.</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/MethodFinder#remedyplan-class">MethodFinder.RemedyPlan</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/ConstructorFinder#remedyplan-class">ConstructorFinder.RemedyPlan</a>, <a href="../public/com/highcapable/yukihookapi/hook/core/finder/members/FieldFinder#remedyplan-class">FieldFinder.RemedyPlan</a> .</p></div><h3 id="relative-matching" tabindex="-1"><a class="header-anchor" href="#relative-matching" aria-hidden="true">#</a> Relative Matching</h3><p>Suppose there is a <code>Class</code> with the same function in different versions of the Host App but only the name of the <code>Class</code> is different.</p><blockquote><p>The following example of version A</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ATest</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><blockquote><p>The following example of version B</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BTest</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">static</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">doTask</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><p>At this time, what should we do if we want to call the <code>doTask</code> method in this <code>Class</code> in each version?</p><p>The usual practice is to check if <code>Class</code> exists.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// First find this Class</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> currentClass </span><span style="color:#F47067;">=</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">if</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">.hasClass()) </span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">.toClass() </span><span style="color:#F47067;">else</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">.toClass()</span></span>
|
|
<span class="line"><span style="color:#768390;">// Then look for this method and call</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">currentClass.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>I feel that this solution is very inelegant and cumbersome, then <code>YukiHookAPI</code> provides you with a very convenient <code>VariousClass</code> to solve this problem.</p><p>Now, you can get this <code>Class</code> directly using the following methods.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).get().method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If the current <code>Class</code> exists in the specified <code>ClassLoader</code>, you can fill in your <code>ClassLoader</code> in <code>get</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).get(customClassLoader).method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you are not sure that all <code>Class</code> will be matched, you can use the <code>getOrNull</code> method.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> customClassLoader</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ClassLoader?</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ... </span><span style="color:#768390;">// Assume this is your ClassLoader</span></span>
|
|
<span class="line"><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).getOrNull(customClassLoader)?.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}?.get()?.call()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>If you are using the <code>Class</code> of the (Xposed) Host environment in <code>PackageParam</code>, you can use <code>toClass()</code> to set it directly.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).toClass().method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"doTask"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().call()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/bean/VariousClass">VariousClass</a>.</p></div><p>If it is used when creating a Hook, it can be more convenient, and it can also automatically intercept the exception that <code>Class</code> cannot be found.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">findClass(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">).hook {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Your code here.</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>You can also define this <code>Class</code> as a constant type to use.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Define constant type</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">ABTestClass</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">VariousClass</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"com.demo.ATest"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"com.demo.BTest"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#768390;">// Use directly</span></span>
|
|
<span class="line"><span style="color:#F69D50;">ABTestClass</span><span style="color:#ADBAC7;">.hook {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Your code here.</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to the <a href="../public/com/highcapable/yukihookapi/hook/param/PackageParam#findclass-method">PackageParam.findClass</a> method.</p></div><h3 id="calling-generics" tabindex="-1"><a class="header-anchor" href="#calling-generics" aria-hidden="true">#</a> Calling Generics</h3><p>In the process of reflection, we may encounter generic problems.</p><p>In the reflection processing of generics, <code>YukiHookAPI</code> also provides a syntactic sugar that can be used anywhere.</p><p>For example we have the following generic class.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TestGeneric</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">T</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">R</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;"> (t</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">T</span><span style="color:#ADBAC7;">, r</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">R</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>When we want to get a <code>Class</code> instance of the generic <code>T</code> or <code>R</code> in the current <code>Class</code>, only the following implementation is required.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TestGeneric</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">T</span><span style="color:#ADBAC7;">, </span><span style="color:#F69D50;">R</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;"> (t</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">T</span><span style="color:#ADBAC7;">, r</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">R</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the operation object of the current instance</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the Class instance of T, in the 0th position of the parameter</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// The default value can not be written</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> tClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> current().generic()?.argument()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the Class instance of R, in parameter 1</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> rClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> current().generic()?.argument(index </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You can also use the following syntax</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> current().generic {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the Class instance of T</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// In the 0th position of the parameter, the default value can be left blank</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> tClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> argument()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Get the Class instance of R, in parameter 1</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> rClass </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> argument(index </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>When we want to call this <code>Class</code> externally, it can be implemented as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#768390;">// Assume this is the Class of T</span></span>
|
|
<span class="line"><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TI</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"><span style="color:#768390;">// Assume this is an instance of T</span></span>
|
|
<span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> tInstance</span><span style="color:#F47067;">:</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TI</span><span style="color:#ADBAC7;">? </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> ...</span></span>
|
|
<span class="line"><span style="color:#768390;">// Get the Class instance of T</span></span>
|
|
<span class="line"><span style="color:#768390;">// In the 0th position of the parameter, the default value can be left blank</span></span>
|
|
<span class="line"><span style="color:#768390;">// And get the method foo and call it</span></span>
|
|
<span class="line"><span style="color:#F69D50;">TestGeneric</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.generic()?.argument()?.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"foo"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}?.get(tInstance)?.invoke</span><span style="color:#F47067;"><</span><span style="color:#F69D50;">TI</span><span style="color:#F47067;">></span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more functions, please refer to <a href="../public/com/highcapable/yukihookapi/hook/bean/CurrentClass#generic-method">CurrentClass.generic</a>, <a href="../public/com/highcapable/yukihookapi/hook/factory/ReflectionFactory#class-generic-ext-method">Class.generic</a> methods and <a href="../public/com/highcapable/yukihookapi/hook/bean/GenericClass">GenericClass</a>.</p></div><h3 id="pay-attention-of-trap" tabindex="-1"><a class="header-anchor" href="#pay-attention-of-trap" aria-hidden="true">#</a> Pay Attention of Trap</h3><blockquote><p>Here are some misunderstandings that may be encountered during use for reference.</p></blockquote><h4 id="restrictive-find-conditions" tabindex="-1"><a class="header-anchor" href="#restrictive-find-conditions" aria-hidden="true">#</a> Restrictive Find Conditions</h4><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>In find conditions you can only use <strong>index</strong> function once except <strong>order</strong>.</p></div><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">).index(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// \u2757 Wrong usage, please keep only one index method</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> returnType(</span><span style="color:#F69D50;">StringType</span><span style="color:#ADBAC7;">).index(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The following find conditions can be used without any problems.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BooleanType</span><span style="color:#ADBAC7;">).index(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">2</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> order().index(num </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">1</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h4 id="necessary-find-conditions" tabindex="-1"><a class="header-anchor" href="#necessary-find-conditions" aria-hidden="true">#</a> Necessary Find Conditions</h4><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>In common method find conditions, <u><strong>even methods without parameters need to set find conditions</strong></u>.</p></div><p>Suppose we have the following <code>Class</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">(String </span><span style="color:#F69D50;">string</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">void</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">foo</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><p>We want to get the <code>public void foo()</code> method, which can be written as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"foo"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>However, the above example <u><strong>is wrong</strong></u>.</p><p>You will find two <code>foo</code> methods in this <code>Class</code>, one of which takes a method parameter.</p><p>Since the above example does not set the find conditions for <code>param</code>, the result will be the first method <code>public void foo(String string)</code> that matches the name and matches the bytecode order, not the last method we need.</p><p>This is a <strong>frequent error</strong>, <strong>without method parameters, you will lose the use of method parameter find conditions</strong>.</p><p>The correct usage is as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"foo"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// \u2705 Correct usage, add detailed filter conditions</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> emptyParam()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>At this point, the above example will perfectly match the <code>public void foo()</code> method.</p><div class="custom-container tip"><p class="custom-container-title">Compatibility Notes</p><p>In the past historical versions of the API, it was allowed to match the method without writing the default matching no-parameter method, but the latest version has corrected this problem, please make sure that you are using the latest API version.</p></div><h4 id="abbreviated-find-conditions" tabindex="-1"><a class="header-anchor" href="#abbreviated-find-conditions" aria-hidden="true">#</a> Abbreviated Find Conditions</h4><blockquote><p>In the construction method find conditions, <u><strong>constructors without parameters do not need to fill in the find conditions</strong></u>.</p></blockquote><p>Suppose we have the following <code>Class</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-java ext-java"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">public</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">TestFoo</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// ...</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre></div><p>We want to get the <code>public TestFoo()</code> constructor, which can be written as follows.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.</span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;"> { emptyParam() }</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>The above example can successfully obtain the <code>public TestFoo()</code> constructor, but it feels a bit cumbersome.</p><p>Unlike normal methods, since the constructor does not need to consider the <code>name</code>, when the constructor has no parameters, we can omit the <code>emptyParam</code> parameter.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#F69D50;">TestFoo</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java.</span><span style="color:#DCBDFB;">constructor</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Compatibility Notes</p><p>In the past historical versions of the API, if the constructor does not fill in any find conditions, the constructor will not be found directly.</p><p><u><strong>This is a bug, the latest version has been fixed</strong></u>, please make sure you are using the latest API version.</p></div><h4 id="bytecode-type" tabindex="-1"><a class="header-anchor" href="#bytecode-type" aria-hidden="true">#</a> Bytecode Type</h4><div class="custom-container danger"><p class="custom-container-title">Pay Attention</p><p>In the bytecode call result, the <strong>cast</strong> method can only specify the type corresponding to the bytecode.</p></div><p>For example we want to get a field of type <code>Boolean</code> and cast it to <code>String</code>.</p><p>The following is the wrong way to use it.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().string() </span><span style="color:#768390;">// \u2757 Wrong usage, must be cast to the bytecode target type</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>The following is the correct way to use it.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.get().boolean().toString() </span><span style="color:#768390;">// \u2705 The correct way to use, get the type and then convert</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2 id="common-type-extensions" tabindex="-1"><a class="header-anchor" href="#common-type-extensions" aria-hidden="true">#</a> Common Type Extensions</h2><p>When find methods and fields, we usually need to specify the type in find conditions.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">Boolean</span><span style="color:#ADBAC7;">::</span><span style="color:#6CB6FF;">class</span><span style="color:#ADBAC7;">.java</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Expressing the type <code>Boolean::class.java</code> in <code>Kotlin</code> is very long and not convenient.</p><p>Therefore, <code>YukiHookAPI</code> encapsulates common type calls for developers, including Android's basic types and Java's basic types.</p><p>At this time, the above type can be written in the following form.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">field {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"test"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> type </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BooleanType</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Common basic types in Java have been encapsulated as <strong>Name + Type</strong>, such as <code>IntType</code>, <code>FloatType</code>.</p><p>Correspondingly, array types also have convenient usage methods, assuming we want to get an array of type <code>String[]</code>.</p><p>You need to write <code>java.lang.reflect.Array.newInstance(String::class.java, 0).javaClass</code> to get this type.</p><p>Does it feel very troublesome? At this time, we can use the extension method <code>ArrayClass(StringType)</code> to get this type.</p><p>At the same time, since <code>String</code> is a common type, you can also directly use <code>StringArrayClass</code> to get this type.</p><p>Some common methods found in Hook have their corresponding encapsulation types for use, in the format <strong>Name + Class</strong>.</p><p>For example, the Hook <code>onCreate</code> method needs to find the <code>Bundle::class.java</code> type.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin ext-kt line-numbers-mode"><pre class="shiki" style="background-color:#22272e;"><code><span class="line"><span style="color:#ADBAC7;">method {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> name </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"onCreate"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> param(</span><span style="color:#F69D50;">BundleClass</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><div class="custom-container tip"><p class="custom-container-title">Tips</p><p>For more types, see <a href="../public/com/highcapable/yukihookapi/hook/type/android/ComponentTypeFactory">ComponentTypeFactory</a>, <a href="../public/com/highcapable/yukihookapi/hook/type/android/GraphicsTypeFactory">GraphicsTypeFactory</a>, <a href="../public/com/highcapable/yukihookapi/hook/type/android/ViewTypeFactory">ViewTypeFactory</a>, <a href="../public/com/highcapable/yukihookapi/hook/type/java/VariableTypeFactory">VariableTypeFactory</a>.</p></div><p>At the same time, you are welcome to contribute more commonly used types.</p>`,367);function m(v,h){const a=l("Badge");return o(),p("div",null,[r,s("h3",d,[y,A,t(a,{type:"tip",text:"Beta",vertical:"middle"})]),u])}const D=e(i,[["render",m],["__file","reflection.html.vue"]]);export{D as default};
|