mirror of
https://github.com/HighCapable/YukiHookAPI.git
synced 2025-09-04 09:45:19 +08:00
157 lines
47 KiB
JavaScript
157 lines
47 KiB
JavaScript
import{_ as l,r as o,o as p,c as t,b as s,d as e,e as c,a as n}from"./app-BpUB8-Q8.js";const i={},r=n(`<h1 id="host-resource-injection-extension" tabindex="-1"><a class="header-anchor" href="#host-resource-injection-extension" aria-hidden="true">#</a> Host Resource Injection Extension</h1><blockquote><p>This is an extension that injects Module App's Resources, <code>Activity</code> components, and <code>Context</code> topics into the Host App.</p></blockquote><p>Before using the following functions, in order to prevent Resource Id from conflicting with each other, you need to modify the Resource Id in the <code>build.gradle</code> of the current Xposed Module project.</p><blockquote><p>Kotlin DSL</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">android</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> androidResources.additionalParameters </span><span style="color:#F47067;">+=</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">listOf</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"--allow-reserved-package-id"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"--package-id"</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">"0x64"</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></div><blockquote><p>Groovy DSL</p></blockquote><div class="language-groovy line-numbers-mode" data-ext="groovy"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#ADBAC7;">android {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> androidResources</span><span style="color:#F47067;">.</span><span style="color:#ADBAC7;">additionalParameters </span><span style="color:#F47067;">+=</span><span style="color:#ADBAC7;"> [</span><span style="color:#96D0FF;">'--allow-reserved-package-id'</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">'--package-id'</span><span style="color:#ADBAC7;">, </span><span style="color:#96D0FF;">'0x64'</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></div><div class="custom-container warning"><p class="custom-container-title">Notice</p><p><strong>aaptOptions.additionalParameters</strong> in previous versions has been deprecated, please refer to the above writing method and keep your <strong>Android Gradle Plugin</strong> to the latest version.</p><p>The sample Resource Id value provided is for reference only, <strong>0x7f</strong> cannot be used, the default is <strong>0x64</strong>.</p><p>In order to prevent the existence of multiple Xposed Modules in the current Host App, it is recommended to customize your own Resource Id.</p></div><h2 id="inject-module-app-s-resources" tabindex="-1"><a class="header-anchor" href="#inject-module-app-s-resources" aria-hidden="true">#</a> Inject Module App's Resources</h2><p>After the Host App is hooked, we can directly inject the <code>Context</code> obtained in the Hooker into the current Module App's Resources.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">resolve</span><span style="color:#ADBAC7;">().</span><span style="color:#DCBDFB;">firstMethod</span><span style="color:#ADBAC7;"> {</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;"> </span><span style="color:#DCBDFB;">parameters</span><span style="color:#ADBAC7;">(Bundle::</span><span style="color:#DCBDFB;">class</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.</span><span style="color:#DCBDFB;">hook</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">after</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">instance</span><span style="color:#ADBAC7;"><</span><span style="color:#F69D50;">Activity</span><span style="color:#ADBAC7;">>().</span><span style="color:#DCBDFB;">also</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Scenario 1> Inject Module App's Resources through Context</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> it.</span><span style="color:#DCBDFB;">injectModuleAppResources</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Scenario 2> Get the Host App's Resources directly and inject the Module App's Resources</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> it.resources.</span><span style="color:#DCBDFB;">injectModuleAppResources</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Use the Module App's Resource Id directly</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> it.</span><span style="color:#DCBDFB;">getString</span><span style="color:#ADBAC7;">(R.id.app_name)</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></div><p>You can also inject current Module App's Resources directly in <code>AppLifecycle</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">onAppLifecycle</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Globally inject Module App's Resources, but only in the global lifecycle</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Methods like ImageView.setImageResource need to be injected separately in Activity</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Scenario 1> Inject Module App's Resources through Context</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">injectModuleAppResources</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Scenario 2> Get the Host App's Resources directly and inject the Module App's Resources</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> resources.</span><span style="color:#DCBDFB;">injectModuleAppResources</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Use the Module App's Resource Id directly</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">getString</span><span style="color:#ADBAC7;">(R.id.app_name)</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></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/factory/YukiHookFactory#context-resources-injectmoduleappresources-ext-method">Context+Resources.injectModuleAppResources</a> method.</p></div><h2 id="register-module-app-s-activity" tabindex="-1"><a class="header-anchor" href="#register-module-app-s-activity" aria-hidden="true">#</a> Register Module App's Activity</h2><p>When the <code>Activity</code> of all applications in the Android system starts, it needs to be registered in <code>AndroidManifest.xml</code>.</p><p>During the Hook process, if we want to directly start the unregistered <code>Activity</code> in the Module App through the Host App, what should we do?</p><p>After the Host App is hooked, we can directly register the <code>Activity</code> proxy of the current Module App in the <code>Context</code> obtained in the Hooker.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">resolve</span><span style="color:#ADBAC7;">().</span><span style="color:#DCBDFB;">firstMethod</span><span style="color:#ADBAC7;"> {</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;"> </span><span style="color:#DCBDFB;">parameters</span><span style="color:#ADBAC7;">(Bundle::</span><span style="color:#DCBDFB;">class</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.</span><span style="color:#DCBDFB;">hook</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">after</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">instance</span><span style="color:#ADBAC7;"><</span><span style="color:#F69D50;">Activity</span><span style="color:#ADBAC7;">>().</span><span style="color:#DCBDFB;">registerModuleAppActivities</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>You can also register the current Module App's <code>Activity</code> proxy directly in <code>AppLifecycle</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">onAppLifecycle</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">registerModuleAppActivities</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></div><p>If the <code>proxy</code> parameter is not filled in, the API will automatically obtain the current Host App's launching entry <code>Activity</code> for proxying according to the current <code>Context</code>.</p><p>Usually, it works, but the above situation will fail in some apps, for example, some <code>Activity</code> will add launching parameters to the registration list, so we need to use another solution.</p><p>If the unregistered <code>Activity</code> cannot be launched correctly, we can manually get the Host App's <code>AndroidManifest.xml</code> for analysis to get a registered <code>Activity</code> tag and get the <code>name</code>.</p><p>You need to choose an unneeded <code>Activity</code> that may not be used by the current Host App as a "puppet" to proxy it, which usually works.</p><p>For example, we have found a suitable <code>Activity</code> that can be proxied.</p><blockquote><p>The following example</p></blockquote><div class="language-xml line-numbers-mode" data-ext="xml"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#ADBAC7;"><</span><span style="color:#8DDB8C;">activity</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">android:name</span><span style="color:#ADBAC7;">=</span><span style="color:#96D0FF;">"com.demo.test.activity.TestActivity"</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>According to the <code>name</code>, we only need to add this parameter to the method for registration.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">registerModuleAppActivities</span><span style="color:#ADBAC7;">(proxy </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.test.activity.TestActivity"</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>Alternatively, if you write a <code>stub</code> for the Host App's class, you can register it directly through the <code>Class</code> object.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">registerModuleAppActivities</span><span style="color:#ADBAC7;">(TestActivity::</span><span style="color:#DCBDFB;">class</span><span style="color:#ADBAC7;">.java)</span></span>
|
|
<span class="line"></span></code></pre><div class="line-numbers" aria-hidden="true"><div class="line-number"></div></div></div><p>After registration is completed, please implement the <code>ModuleActivity</code> interface using the <code>Activity</code> module in the host-started module.</p><p>These <code>Activity</code> (ies) now live seamlessly in the host without registration.</p><p>We recommend that you create <code>BaseActivity</code> as the base class for all modules <code>Activity</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#F47067;">abstract</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">BaseActivity</span><span style="color:#ADBAC7;"> : </span><span style="color:#F69D50;">AppCompatActivity</span><span style="color:#ADBAC7;">(), </span><span style="color:#DCBDFB;">ModuleActivity</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Set up AppCompat Theme (if currently is [AppCompatActivity])</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">override</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> moduleTheme </span><span style="color:#F47067;">get</span><span style="color:#ADBAC7;">() </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> R.style.YourAppTheme</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">override</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">getClassLoader</span><span style="color:#ADBAC7;">() </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> delegate.</span><span style="color:#DCBDFB;">getClassLoader</span><span style="color:#ADBAC7;">()</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">override</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(savedInstanceState: </span><span style="color:#F69D50;">Bundle</span><span style="color:#ADBAC7;">?) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> delegate.</span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(savedInstanceState)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">super</span><span style="color:#ADBAC7;">.</span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(savedInstanceState)</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;">override</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onConfigurationChanged</span><span style="color:#ADBAC7;">(newConfig: </span><span style="color:#F69D50;">Configuration</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> delegate.</span><span style="color:#DCBDFB;">onConfigurationChanged</span><span style="color:#ADBAC7;">(newConfig)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">super</span><span style="color:#ADBAC7;">.</span><span style="color:#DCBDFB;">onConfigurationChanged</span><span style="color:#ADBAC7;">(newConfig)</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;">override</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onRestoreInstanceState</span><span style="color:#ADBAC7;">(savedInstanceState: </span><span style="color:#F69D50;">Bundle</span><span style="color:#ADBAC7;">) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> delegate.</span><span style="color:#DCBDFB;">onRestoreInstanceState</span><span style="color:#ADBAC7;">(savedInstanceState)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">super</span><span style="color:#ADBAC7;">.</span><span style="color:#DCBDFB;">onRestoreInstanceState</span><span style="color:#ADBAC7;">(savedInstanceState)</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 class="line-number"></div><div class="line-number"></div></div></div><p>Then inherit the <code>Activity</code> you want to implement in <code>BaseActivity</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">HostTestActivity</span><span style="color:#ADBAC7;"> : </span><span style="color:#F69D50;">BaseActivity</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">override</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(savedInstanceState: </span><span style="color:#F69D50;">Bundle</span><span style="color:#ADBAC7;">?) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">super</span><span style="color:#ADBAC7;">.</span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(savedInstanceState)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Module App's Resources have been injected automatically</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You can directly use xml to load the layout</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">setContentView</span><span style="color:#ADBAC7;">(R.layout.activity_main)</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>After all the above steps are completed, you can happily call <code>startActivity</code> anywhere in the (Xposed) Host environment where a <code>Context</code> exists.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> context: </span><span style="color:#F69D50;">Context</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">..</span><span style="color:#ADBAC7;">. </span><span style="color:#768390;">// Assume this is your Context</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">context.</span><span style="color:#DCBDFB;">startActivity</span><span style="color:#ADBAC7;">(context, HostTestActivity::</span><span style="color:#DCBDFB;">class</span><span style="color:#ADBAC7;">.java)</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></div><p>The <code>proxy</code> parameter we set in the <code>registerModuleAppActivities</code> method above is the default global proxy <code>Activity</code>.</p><p>If you need to specify a delegated <code>Activity</code> to use another Host App's <code>Activity</code> as a proxy, you can refer to the following method.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#F47067;">class</span><span style="color:#ADBAC7;"> </span><span style="color:#F69D50;">HostTestActivity</span><span style="color:#ADBAC7;"> : </span><span style="color:#F69D50;">BaseActivity</span><span style="color:#ADBAC7;">() {</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Specify an additional proxy Activity class name</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Which must also exist in the Host App's AndroidManifest</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">override</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> proxyClassName </span><span style="color:#F47067;">get</span><span style="color:#ADBAC7;">() </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.test.activity.OtherActivity"</span></span>
|
|
<span class="line"></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">override</span><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">fun</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(savedInstanceState: </span><span style="color:#F69D50;">Bundle</span><span style="color:#ADBAC7;">?) {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#6CB6FF;">super</span><span style="color:#ADBAC7;">.</span><span style="color:#DCBDFB;">onCreate</span><span style="color:#ADBAC7;">(savedInstanceState)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Module App's Resources have been injected automatically</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You can directly use xml to load the layout</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">setContentView</span><span style="color:#ADBAC7;">(R.layout.activity_main)</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></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/factory/YukiHookFactory#context-registermoduleappactivities-ext-method">Context.registerModuleAppActivities</a> method.</p></div><h2 id="create-contextthemewrapper-proxy" tabindex="-1"><a class="header-anchor" href="#create-contextthemewrapper-proxy" aria-hidden="true">#</a> Create ContextThemeWrapper Proxy</h2><p>Sometimes, we need to use <code>MaterialAlertDialogBuilder</code> to beautify our own dialogs in the Host App, but we can't create them without the AppCompat theme.</p><ul><li>Will got the following exception</li></ul><div class="language-text" data-ext="text"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#adbac7;">The style on this component requires your app theme to be Theme.AppCompat (or a descendant).</span></span>
|
|
<span class="line"><span style="color:#adbac7;"></span></span></code></pre></div><p>At this time, we want to use <code>MaterialAlertDialogBuilder</code> to create a dialog in the current <code>Activity</code> of the Host App being hooked, you can have the following methods.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">resolve</span><span style="color:#ADBAC7;">().</span><span style="color:#DCBDFB;">firstMethod</span><span style="color:#ADBAC7;"> {</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;"> </span><span style="color:#DCBDFB;">parameters</span><span style="color:#ADBAC7;">(Bundle::</span><span style="color:#DCBDFB;">class</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.</span><span style="color:#DCBDFB;">hook</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">after</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Use applyModuleTheme to create a theme resource in the current Module App</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">val</span><span style="color:#ADBAC7;"> appCompatContext </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">instance</span><span style="color:#ADBAC7;"><</span><span style="color:#F69D50;">Activity</span><span style="color:#ADBAC7;">>().</span><span style="color:#DCBDFB;">applyModuleTheme</span><span style="color:#ADBAC7;">(R.style.Theme_AppCompat)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Directly use this Context that wraps the Module App's theme to create a dialog</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">MaterialAlertDialogBuilder</span><span style="color:#ADBAC7;">(appCompatContext)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">setTitle</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"AppCompat Theme Dialog"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">setMessage</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"I am an AppCompat theme dialog displayed in the Host App."</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">setPositiveButton</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"OK"</span><span style="color:#ADBAC7;">, </span><span style="color:#6CB6FF;">null</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">show</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 class="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 set the system (native) night mode and day mode on the current <code>Context</code> through <code>uiMode</code>.</p><p>Which requires at least Android 10 and above system version support and the current theme contains night mode related elements.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#DCBDFB;">resolve</span><span style="color:#ADBAC7;">().</span><span style="color:#DCBDFB;">firstMethod</span><span style="color:#ADBAC7;"> {</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;"> </span><span style="color:#DCBDFB;">parameters</span><span style="color:#ADBAC7;">(Bundle::</span><span style="color:#DCBDFB;">class</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">}.</span><span style="color:#DCBDFB;">hook</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">after</span><span style="color:#ADBAC7;"> {</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Define the theme resource in the current Module App</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#F47067;">var</span><span style="color:#ADBAC7;"> appCompatContext: </span><span style="color:#F69D50;">ModuleContextThemeWrapper</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Scenario 1> Get the Configuration object directly to set</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> appCompatContext </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">instance</span><span style="color:#ADBAC7;"><</span><span style="color:#F69D50;">Activity</span><span style="color:#ADBAC7;">>()</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">applyModuleTheme</span><span style="color:#ADBAC7;">(R.style.Theme_AppCompat)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">applyConfiguration</span><span style="color:#ADBAC7;"> { uiMode </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> Configuration.UI_MODE_NIGHT_YES }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// <Scenario 2> Create a new Configuration object</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// This solution will destroy the original font scaling and other settings in the current Host App</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// You need to manually re-pass parameters such as densityDpi</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> appCompatContext </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">instance</span><span style="color:#ADBAC7;"><</span><span style="color:#F69D50;">Activity</span><span style="color:#ADBAC7;">>().</span><span style="color:#DCBDFB;">applyModuleTheme</span><span style="color:#ADBAC7;">(</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> theme </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> R.style.Theme_AppCompat,</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> configuration </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">Configuration</span><span style="color:#ADBAC7;">().</span><span style="color:#DCBDFB;">apply</span><span style="color:#ADBAC7;"> { uiMode </span><span style="color:#F47067;">=</span><span style="color:#ADBAC7;"> Configuration.UI_MODE_NIGHT_YES }</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> )</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#768390;">// Directly use this Context that wraps the Module App's theme to create a dialog</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#DCBDFB;">MaterialAlertDialogBuilder</span><span style="color:#ADBAC7;">(appCompatContext)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">setTitle</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"AppCompat Theme Dialog"</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">setMessage</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"I am an AppCompat theme dialog displayed in the Host App."</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">setPositiveButton</span><span style="color:#ADBAC7;">(</span><span style="color:#96D0FF;">"OK"</span><span style="color:#ADBAC7;">, </span><span style="color:#6CB6FF;">null</span><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> .</span><span style="color:#DCBDFB;">show</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 class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="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 way, we can create dialogs in the Host App very simply using <code>MaterialAlertDialogBuilder</code>.</p>`,66),d={class:"custom-container warning"},A=s("p",{class:"custom-container-title"},"Possible Problems",-1),y=s("p",null,[e("Because some "),s("strong",null,"androidx"),e(" dependent libraries or custom themes used by some apps may interfere with the actual style of the current "),s("strong",null,"MaterialAlertDialog"),e(", such as the button style of the dialog.")],-1),u=s("strong",null,"Module App Demo",-1),D={href:"https://github.com/HighCapable/YukiHookAPI/tree/master/samples/demo-module/src/main/java/com/highcapable/yukihookapi/demo_module/hook/factory/ComponentCompatFactory.kt",target:"_blank",rel:"noopener noreferrer"},v=s("p",null,[s("strong",null,"ClassCastException"),e(" may occur when some apps are created, please manually specify a new "),s("strong",null,"Configuration"),e(" instance to fix.")],-1),B=n(`<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/factory/YukiHookFactory#context-applymoduletheme-ext-method">Context.applyModuleTheme</a> method.</p></div><h2 id="classloader-conflict-problem" tabindex="-1"><a class="header-anchor" href="#classloader-conflict-problem" aria-hidden="true">#</a> ClassLoader Conflict Problem</h2><p>The content introduced on this page is to directly inject the resources of the Module App into the Host App.</p><p>Since the Module App and the Host App are not in the same process (the same <strong>APK</strong>), there may be a <code>ClassLoader</code> conflict.</p><p>If a <code>ClassLoader</code> conflict occurs, you may encounter a <code>ClassCastException</code>.</p><p><code>YukiHookAPI</code> has solved the problem of possible conflicts by default, and you need to configure the exclusion list by yourself in other cases.</p><p>The exclusion list determines whether these <code>Class</code> need to be loaded by the Module App or the Host App's <code>ClassLoader</code>.</p><blockquote><p>The following example</p></blockquote><div class="language-kotlin line-numbers-mode" data-ext="kt"><pre class="shiki github-dark-dimmed" style="background-color:#22272e;" tabindex="0"><code><span class="line"><span style="color:#768390;">// Exclude Class names belonging to the Host App</span></span>
|
|
<span class="line"><span style="color:#768390;">// They will be loaded by the Host App's ClassLoader</span></span>
|
|
<span class="line"><span style="color:#768390;">// The following content is for demonstration only</span></span>
|
|
<span class="line"><span style="color:#768390;">// DO NOT USE IT DIRECTLY, please refer to your actual situation</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">ModuleClassLoader.</span><span style="color:#DCBDFB;">excludeHostClasses</span><span style="color:#ADBAC7;">(</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"androidx.core.app.ActivityCompat"</span><span style="color:#ADBAC7;">,</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.Test"</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">)</span></span>
|
|
<span class="line"><span style="color:#768390;">// Exclude Class names belonging to the Module App</span></span>
|
|
<span class="line"><span style="color:#768390;">// They will be loaded by the ClassLoader of the Module App (the current Hook process)</span></span>
|
|
<span class="line"><span style="color:#768390;">// The following content is for demonstration only</span></span>
|
|
<span class="line"><span style="color:#768390;">// DO NOT USE IT DIRECTLY, please refer to your actual situation</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;">ModuleClassLoader.</span><span style="color:#DCBDFB;">excludeModuleClasses</span><span style="color:#ADBAC7;">(</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.entry.HookEntry"</span><span style="color:#ADBAC7;">,</span></span>
|
|
<span class="line"><span style="color:#ADBAC7;"> </span><span style="color:#96D0FF;">"com.demo.controller.ModuleController"</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></div><p>You need to set it before the method of injecting Module App's resources into the Host App is executed to take effect.</p><p>This function is only to solve the situation that <strong><code>Class</code> with the same name</strong> may exist in the Host App and Module App, such as shared SDK and dependencies.</p><p>In most cases, you will not use this function.</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/xposed/parasitic/reference/ModuleClassLoader">ModuleClassLoader</a>.</p></div>`,13);function C(m,h){const a=o("ExternalLinkIcon");return p(),t("div",null,[r,s("div",d,[A,y,s("p",null,[e("You can refer to the "),u,e(" in this case and see "),s("a",D,[e("here is the sample code"),c(a)]),e(" to fix this problem.")]),v]),B])}const g=l(i,[["render",C],["__file","host-inject.html.vue"]]);export{g as default};
|