refactor: merge ModuleAppActivity, ModuleAppCompatActivity to ModuleActivity and some tweaks

This commit is contained in:
2025-06-18 20:39:26 +08:00
parent 701cbe0fc0
commit 14399538ea
15 changed files with 270 additions and 157 deletions

View File

@@ -44,6 +44,8 @@ dependencies {
implementation(org.lsposed.hiddenapibypass.hiddenapibypass)
implementation(com.highcapable.kavaref.kavaref.core)
implementation(com.highcapable.kavaref.kavaref.extension)
implementation(com.highcapable.betterandroid.ui.extension)
implementation(com.highcapable.betterandroid.system.extension)
implementation(androidx.core.core.ktx)
implementation(androidx.appcompat.appcompat)
implementation(androidx.preference.preference.ktx)

View File

@@ -21,7 +21,7 @@
*/
package com.highcapable.yukihookapi.hook.core.api.reflect
import android.os.Build
import com.highcapable.betterandroid.system.extension.tool.SystemVersion
import com.highcapable.kavaref.resolver.processor.MemberProcessor
import org.lsposed.hiddenapibypass.HiddenApiBypass
import java.lang.reflect.Constructor
@@ -49,21 +49,13 @@ class AndroidHiddenApiBypassResolver private constructor() : MemberProcessor.Res
fun get() = self
}
override fun <T : Any> getDeclaredConstructors(declaringClass: Class<T>): List<Constructor<T>> {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
return super.getDeclaredConstructors(declaringClass)
val constructors = HiddenApiBypass.getDeclaredMethods(declaringClass)
.filterIsInstance<Constructor<T>>()
.toList()
return constructors
}
override fun <T : Any> getDeclaredConstructors(declaringClass: Class<T>): List<Constructor<T>> =
SystemVersion.require(SystemVersion.P, super.getDeclaredConstructors(declaringClass)) {
HiddenApiBypass.getDeclaredMethods(declaringClass).filterIsInstance<Constructor<T>>().toList()
}
override fun <T : Any> getDeclaredMethods(declaringClass: Class<T>): List<Method> {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P)
return super.getDeclaredMethods(declaringClass)
val methods = HiddenApiBypass.getDeclaredMethods(declaringClass)
.filterIsInstance<Method>()
.toList()
return methods
}
override fun <T : Any> getDeclaredMethods(declaringClass: Class<T>): List<Method> =
SystemVersion.require(SystemVersion.P, super.getDeclaredMethods(declaringClass)) {
HiddenApiBypass.getDeclaredMethods(declaringClass).filterIsInstance<Method>().toList()
}
}

View File

@@ -28,20 +28,19 @@ import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.content.res.Resources
import android.os.Build
import android.os.Process
import android.view.ContextThemeWrapper
import android.widget.ImageView
import androidx.annotation.RequiresApi
import androidx.annotation.StyleRes
import androidx.core.net.toUri
import com.highcapable.betterandroid.system.extension.tool.SystemVersion
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.xposed.channel.YukiHookDataChannel
import com.highcapable.yukihookapi.hook.xposed.parasitic.AppParasitics
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.base.ModuleAppActivity
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.base.ModuleAppCompatActivity
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.proxy.ModuleActivity
import com.highcapable.yukihookapi.hook.xposed.parasitic.context.wrapper.ModuleContextThemeWrapper
import com.highcapable.yukihookapi.hook.xposed.prefs.YukiHookPrefsBridge
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
@@ -163,7 +162,7 @@ fun Resources.injectModuleAppResources() = AppParasitics.injectModuleAppResource
*
* 使用此方法会在未注册的 [Activity] 在 Hook APP (宿主) 中启动时自动调用 [injectModuleAppResources] 注入当前 Xposed 模块的资源
*
* - 你要将需要在宿主启动的 [Activity] 继承于 [ModuleAppActivity] or [ModuleAppCompatActivity]
* - 你要将需要在宿主启动的 [Activity] 实现 [ModuleActivity] 接口
*
* 详情请参考 [注册模块 Activity](https://highcapable.github.io/YukiHookAPI/zh-cn/api/special-features/host-inject#%E6%B3%A8%E5%86%8C%E6%A8%A1%E5%9D%97-activity)
*
@@ -174,7 +173,7 @@ fun Resources.injectModuleAppResources() = AppParasitics.injectModuleAppResource
* - 最低支持 Android 7.0 (API 24)
* @param proxy 代理的 [Activity] - 必须存在于宿主的 AndroidMainifest 清单中 - 不填使用默认 [Activity]
*/
@RequiresApi(Build.VERSION_CODES.N)
@RequiresApi(SystemVersion.N)
fun Context.registerModuleAppActivities(proxy: Any? = null) = AppParasitics.registerModuleAppActivities(context = this, proxy)
/**

View File

@@ -23,7 +23,6 @@
package com.highcapable.yukihookapi.hook.xposed.channel
import android.annotation.SuppressLint
import android.app.Activity
import android.app.ActivityManager
import android.app.Application
@@ -32,11 +31,13 @@ import android.content.Context
import android.content.Context.ACTIVITY_SERVICE
import android.content.Intent
import android.content.IntentFilter
import android.os.Build
import android.os.Bundle
import android.os.Parcel
import android.os.Parcelable
import android.os.TransactionTooLargeException
import com.highcapable.betterandroid.system.extension.component.BroadcastReceiver
import com.highcapable.betterandroid.system.extension.component.registerReceiver
import com.highcapable.betterandroid.system.extension.component.sendBroadcast
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.log.YLog
import com.highcapable.yukihookapi.hook.log.data.YLogData
@@ -142,26 +143,21 @@ class YukiHookDataChannel private constructor() {
private var isAllowSendTooLargeData = false
/** 广播接收器 */
private val handlerReceiver by lazy {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (intent == null) return
intent.action?.also { action ->
runCatching {
receiverCallbacks.takeIf { it.isNotEmpty() }?.apply {
mutableListOf<String>().also { destroyedCallbacks ->
forEach { (key, it) ->
when {
(it.first as? Activity?)?.isDestroyed == true -> destroyedCallbacks.add(key)
isCurrentBroadcast(it.first) -> it.second(action, intent)
}
}
destroyedCallbacks.takeIf { it.isNotEmpty() }?.forEach { remove(it) }
private val handlerReceiver = BroadcastReceiver { _, intent ->
intent.action?.also { action ->
runCatching {
receiverCallbacks.takeIf { it.isNotEmpty() }?.apply {
mutableListOf<String>().also { destroyedCallbacks ->
forEach { (key, it) ->
when {
(it.first as? Activity?)?.isDestroyed == true -> destroyedCallbacks.add(key)
isCurrentBroadcast(it.first) -> it.second(action, intent)
}
}
}.onFailure { YLog.innerE("Received action \"$action\" failed", it) }
destroyedCallbacks.takeIf { it.isNotEmpty() }?.forEach { remove(it) }
}
}
}
}.onFailure { YLog.innerE("Received action \"$action\" failed", it) }
}
}
@@ -208,18 +204,10 @@ class YukiHookDataChannel private constructor() {
internal fun register(context: Context?, packageName: String = context?.packageName ?: "") {
if (YukiHookAPI.Configs.isEnableDataChannel.not() || context == null) return
receiverContext = context
IntentFilter().apply {
val filter = IntentFilter().apply {
addAction(if (isXposedEnvironment) hostActionName(packageName) else moduleActionName(context))
}.also { filter ->
/**
* 从 Android 14 (及预览版) 开始
* 外部广播必须声明 [Context.RECEIVER_EXPORTED]
*/
@SuppressLint("UnspecifiedRegisterReceiverFlag")
if (Build.VERSION.SDK_INT >= 33)
context.registerReceiver(handlerReceiver, filter, Context.RECEIVER_EXPORTED)
else context.registerReceiver(handlerReceiver, filter)
}
context.registerReceiver(filter, exported = true, body = handlerReceiver)
/** 排除模块环境下模块注册自身广播 */
if (isXposedEnvironment.not()) return
nameSpace(context, packageName).with {
@@ -696,13 +684,13 @@ class YukiHookDataChannel private constructor() {
*/
private fun pushReceiver(wrapper: ChannelDataWrapper<*>) {
/** 发送广播 */
(context ?: AppParasitics.currentApplication)?.sendBroadcast(Intent().apply {
(context ?: AppParasitics.currentApplication)?.sendBroadcast {
action = if (isXposedEnvironment) moduleActionName() else hostActionName(packageName)
/** 由于系统框架的包名可能不唯一 - 为防止发生问题不再对系统框架的广播设置接收者包名 */
if (packageName != AppParasitics.SYSTEM_FRAMEWORK_NAME)
setPackage(if (isXposedEnvironment) YukiXposedModule.modulePackageName else packageName)
putExtra(wrapper.instance.key + keyNonRepeatName, wrapper)
}) ?: YLog.innerE("Failed to sendBroadcast like \"${wrapper.instance.key}\", because got null context in \"$packageName\"")
} ?: YLog.innerE("Failed to sendBroadcast like \"${wrapper.instance.key}\", because got null context in \"$packageName\"")
}
}
}

View File

@@ -30,7 +30,6 @@ import android.app.ActivityManager
import android.app.AndroidAppHelper
import android.app.Application
import android.app.Instrumentation
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
@@ -39,10 +38,11 @@ import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.content.res.Resources
import android.os.Build
import android.os.Handler
import android.os.UserHandle
import androidx.annotation.RequiresApi
import com.highcapable.betterandroid.system.extension.component.registerReceiver
import com.highcapable.betterandroid.system.extension.tool.SystemVersion
import com.highcapable.kavaref.KavaRef.Companion.resolve
import com.highcapable.kavaref.extension.classOf
import com.highcapable.kavaref.extension.lazyClass
@@ -363,20 +363,8 @@ internal object AppParasitics {
* @param result 回调 - ([Context] 当前实例, [Intent] 当前对象)
*/
fun IntentFilter.registerReceiver(result: (Context, Intent) -> Unit) {
object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
if (context == null || intent == null) return
result(context, intent)
}
}.also { receiver ->
/**
* 从 Android 14 (及预览版) 开始
* 外部广播必须声明 [Context.RECEIVER_EXPORTED]
*/
@SuppressLint("UnspecifiedRegisterReceiverFlag")
if (Build.VERSION.SDK_INT >= 33)
it.registerReceiver(receiver, this, Context.RECEIVER_EXPORTED)
else it.registerReceiver(receiver, this)
it.registerReceiver(filter = this, exported = true) { context, intent ->
result(context, intent)
}
}
hostApplication = it
@@ -431,13 +419,13 @@ internal object AppParasitics {
* @param context 当前 [Context]
* @param proxy 代理的 [Activity]
*/
@RequiresApi(Build.VERSION_CODES.N)
@RequiresApi(SystemVersion.N)
internal fun registerModuleAppActivities(context: Context, proxy: Any?) {
if (isActivityProxyRegistered) return
if (YukiXposedModule.isXposedEnvironment.not()) return YLog.innerW("You can only register Activity Proxy in Xposed Environment")
if (context.packageName == YukiXposedModule.modulePackageName) return YLog.innerE("You cannot register Activity Proxy into yourself")
@SuppressLint("ObsoleteSdkInt")
if (Build.VERSION.SDK_INT < 24) return YLog.innerE("Activity Proxy only support for Android 7.0 (API 24) or higher")
if (SystemVersion.isLowTo(SystemVersion.N)) return YLog.innerE("Activity Proxy only support for Android 7.0 (API 24) or higher")
runCatching {
ActivityProxyConfig.apply {
proxyIntentName = "${YukiXposedModule.modulePackageName}.ACTIVITY_PROXY_INTENT"

View File

@@ -23,45 +23,38 @@
package com.highcapable.yukihookapi.hook.xposed.parasitic.activity.base
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import androidx.annotation.CallSuper
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiXposedModule
import com.highcapable.yukihookapi.hook.xposed.parasitic.reference.ModuleClassLoader
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.proxy.ModuleActivity
/**
* 代理 [Activity]
*
* 继承于此类的 [Activity] 可以同时在宿主与模块中启动
* - 由于超类继承者的不唯一性 - 此类已弃用 - 在之后的版本中将直接被删除
*
* - 在 (Xposed) 宿主环境需要在宿主启动时调用 [Context.registerModuleAppActivities] 进行注册
* - 请现在参考并迁移到 [ModuleActivity]
*/
open class ModuleAppActivity : Activity() {
@Deprecated(message = "请使用新方式来实现此功能")
open class ModuleAppActivity : Activity(), ModuleActivity {
/**
* 设置当前代理的 [Activity] 类名
*
* 留空则使用 [Context.registerModuleAppActivities] 时设置的类名
*
* - 代理的 [Activity] 类名必须存在于宿主的 AndroidMainifest 清单中
* @return [String]
*/
open val proxyClassName get() = ""
override fun getClassLoader(): ClassLoader? = ModuleClassLoader.instance()
override fun getClassLoader() = delegate.getClassLoader()
@CallSuper
override fun onConfigurationChanged(newConfig: Configuration) {
if (YukiXposedModule.isXposedEnvironment) injectModuleAppResources()
delegate.onConfigurationChanged(newConfig)
super.onConfigurationChanged(newConfig)
}
@CallSuper
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
savedInstanceState.getBundle("android:viewHierarchyState")?.classLoader = classLoader
delegate.onRestoreInstanceState(savedInstanceState)
super.onRestoreInstanceState(savedInstanceState)
}
@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
delegate.onCreate(savedInstanceState)
super.onCreate(savedInstanceState)
}
}

View File

@@ -22,61 +22,39 @@
*/
package com.highcapable.yukihookapi.hook.xposed.parasitic.activity.base
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import androidx.annotation.CallSuper
import androidx.appcompat.app.AppCompatActivity
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiXposedModule
import com.highcapable.yukihookapi.hook.xposed.parasitic.reference.ModuleClassLoader
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.proxy.ModuleActivity
/**
* 代理 [AppCompatActivity]
*
* 继承于此类的 [Activity] 可以同时在宿主与模块中启动
* - 由于超类继承者的不唯一性 - 此类已弃用 - 在之后的版本中将直接被删除
*
* - 在 (Xposed) 宿主环境需要在宿主启动时调用 [Context.registerModuleAppActivities] 进行注册
*
* - 在 (Xposed) 宿主环境需要重写 [moduleTheme] 设置 AppCompat 主题 - 否则会无法启动
* - 请现在参考并迁移到 [ModuleActivity]
*/
open class ModuleAppCompatActivity : AppCompatActivity() {
@Deprecated(message = "请使用新方式来实现此功能")
open class ModuleAppCompatActivity : AppCompatActivity(), ModuleActivity {
/**
* 设置当前代理的 [Activity] 类名
*
* 留空则使用 [Context.registerModuleAppActivities] 时设置的类名
*
* - 代理的 [Activity] 类名必须存在于宿主的 AndroidMainifest 清单中
* @return [String]
*/
open val proxyClassName get() = ""
/**
* 设置当前代理的 [Activity] 主题
* @return [Int]
*/
open val moduleTheme get() = -1
override fun getClassLoader(): ClassLoader? = ModuleClassLoader.instance()
override fun getClassLoader() = delegate.getClassLoader()
@CallSuper
override fun onConfigurationChanged(newConfig: Configuration) {
if (YukiXposedModule.isXposedEnvironment) injectModuleAppResources()
delegate.onConfigurationChanged(newConfig)
super.onConfigurationChanged(newConfig)
}
@CallSuper
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
savedInstanceState.getBundle("android:viewHierarchyState")?.classLoader = classLoader
delegate.onRestoreInstanceState(savedInstanceState)
super.onRestoreInstanceState(savedInstanceState)
}
@CallSuper
override fun onCreate(savedInstanceState: Bundle?) {
if (YukiXposedModule.isXposedEnvironment && moduleTheme != -1) setTheme(moduleTheme)
delegate.onCreate(savedInstanceState)
super.onCreate(savedInstanceState)
}
}

View File

@@ -26,11 +26,11 @@ package com.highcapable.yukihookapi.hook.xposed.parasitic.activity.delegate.call
import android.app.Activity
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.os.Message
import com.highcapable.betterandroid.system.extension.tool.SystemVersion
import com.highcapable.kavaref.KavaRef.Companion.resolve
import com.highcapable.kavaref.extension.lazyClass
import com.highcapable.yukihookapi.hook.core.api.reflect.AndroidHiddenApiBypassResolver
@@ -93,7 +93,7 @@ internal object HandlerDelegateCaller {
if (intent?.hasExtra(ActivityProxyConfig.proxyIntentName) == true) {
@Suppress("DEPRECATION")
val subIntent = intent.getParcelableExtra<Intent>(ActivityProxyConfig.proxyIntentName)
if (Build.VERSION.SDK_INT >= 31) {
if (SystemVersion.isHighOrEqualsTo(SystemVersion.S)) {
val currentActivityThread = ActivityThreadClass.resolve()
.processor(AndroidHiddenApiBypassResolver.get())
.optional(silent = true)

View File

@@ -32,9 +32,8 @@ import com.highcapable.kavaref.extension.hasClass
import com.highcapable.kavaref.extension.isSubclassOf
import com.highcapable.kavaref.extension.toClassOrNull
import com.highcapable.yukihookapi.hook.xposed.parasitic.AppParasitics
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.base.ModuleAppActivity
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.base.ModuleAppCompatActivity
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.config.ActivityProxyConfig
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.proxy.ModuleActivity
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
@@ -75,10 +74,8 @@ internal object IActivityManagerProxyCaller {
fun String.verify() = if (AppParasitics.hostApplication?.classLoader?.hasClass(this) == true) this else null
setClassName(component.packageName, component.className.toClassOrNull()?.runCatching {
when {
this isSubclassOf ModuleAppActivity::class ->
createInstanceAsTypeOrNull<ModuleAppActivity>()?.proxyClassName?.verify()
this isSubclassOf ModuleAppCompatActivity::class ->
createInstanceAsTypeOrNull<ModuleAppCompatActivity>()?.proxyClassName?.verify()
this isSubclassOf ModuleActivity::class ->
createInstanceAsTypeOrNull<ModuleActivity>()?.proxyClassName?.verify()
else -> null
}
}?.getOrNull() ?: ActivityProxyConfig.proxyClassName)

View File

@@ -0,0 +1,133 @@
/*
* YukiHookAPI - An efficient Hook API and Xposed Module solution built in Kotlin.
* Copyright (C) 2019 HighCapable
* https://github.com/HighCapable/YukiHookAPI
*
* Apache License Version 2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* This file is created by fankes on 2025/6/18.
*/
@file:Suppress("UNUSED_PARAMETER")
package com.highcapable.yukihookapi.hook.xposed.parasitic.activity.proxy
import android.app.Activity
import android.content.Context
import android.content.res.Configuration
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
import com.highcapable.yukihookapi.hook.xposed.bridge.YukiXposedModule
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.proxy.ModuleActivity.Delegate
import com.highcapable.yukihookapi.hook.xposed.parasitic.reference.ModuleClassLoader
/**
* 模块 [Activity] 代理接口
*
* 实现了此接口的 [Activity] 可以同时在宿主与模块中启动
*
* - 在 (Xposed) 宿主环境需要在宿主启动时调用 [Context.registerModuleAppActivities] 进行注册
*
* - 在 (Xposed) 宿主环境需要重写 [moduleTheme] 设置 AppCompat 主题 (如果当前是 [AppCompatActivity]) - 否则会无法启动
*
* 请参考下方示例手动调用 [delegate] 对 [Activity] 完成必要方法的注册 - 建议在自己的 `BaseActivity` 中实现此接口并重写相关方法 -
* 然后继承自此 `BaseActivity` 来实现模块 [Activity] 的代理
*
* ```kotlin
* abstract class BaseActivity : AppCompatActivity(), ModuleActivity {
*
* // 设置 AppCompat 主题 (如果当前是 [AppCompatActivity])
* override val moduleTheme get() = R.style.YourAppTheme
*
* override fun getClassLoader() = delegate.getClassLoader()
*
* override fun onCreate(savedInstanceState: Bundle?) {
* delegate.onCreate(savedInstanceState)
* super.onCreate(savedInstanceState)
* }
*
* override fun onConfigurationChanged(newConfig: Configuration) {
* delegate.onConfigurationChanged(newConfig)
* super.onConfigurationChanged(newConfig)
* }
*
* override fun onRestoreInstanceState(savedInstanceState: Bundle) {
* delegate.onRestoreInstanceState(savedInstanceState)
* super.onRestoreInstanceState(savedInstanceState)
* }
* }
* ```
* @see Delegate
*/
interface ModuleActivity {
/**
* 模块 [Activity] 代理提供者
*/
class Delegate internal constructor(private val self: ModuleActivity) {
private val selfActivity get() = self as? Activity ?: error("ModuleActivity must be implemented an Activity")
/**
* @see Activity.getClassLoader
*/
fun getClassLoader() = ModuleClassLoader.instance()
/**
* @see Activity.onCreate
*/
fun onCreate(savedInstanceState: Bundle?) {
if (YukiXposedModule.isXposedEnvironment && self.moduleTheme != -1)
selfActivity.setTheme(self.moduleTheme)
}
/**
* @see Activity.onConfigurationChanged
*/
fun onConfigurationChanged(newConfig: Configuration) {
if (YukiXposedModule.isXposedEnvironment) selfActivity.injectModuleAppResources()
}
/**
* @see Activity.onRestoreInstanceState
*/
fun onRestoreInstanceState(savedInstanceState: Bundle) {
savedInstanceState.getBundle("android:viewHierarchyState")?.classLoader = selfActivity.classLoader
}
}
/**
* 获取当前 [ModuleActivity] 的 [Delegate] 实例
* @return [Delegate]
*/
val delegate get() = Delegate(self = this)
/**
* 设置当前代理的 [Activity] 主题
* @return [Int]
*/
val moduleTheme get() = -1
/**
* 设置当前代理的 [Activity] 类名
*
* 留空则使用 [Context.registerModuleAppActivities] 时设置的类名
*
* - 代理的 [Activity] 类名必须存在于宿主的 AndroidMainifest 清单中
* @return [String]
*/
val proxyClassName get() = ""
}