diff --git a/app/src/main/java/com/fankes/tsbattery/hook/HookEntry.kt b/app/src/main/java/com/fankes/tsbattery/hook/HookEntry.kt index 84a26cc..f391c11 100644 --- a/app/src/main/java/com/fankes/tsbattery/hook/HookEntry.kt +++ b/app/src/main/java/com/fankes/tsbattery/hook/HookEntry.kt @@ -24,15 +24,11 @@ package com.fankes.tsbattery.hook import com.fankes.tsbattery.const.PackageName -import com.fankes.tsbattery.data.ConfigData import com.fankes.tsbattery.hook.entity.QQTIMHooker import com.fankes.tsbattery.hook.entity.WeChatHooker -import com.fankes.tsbattery.utils.factory.versionName import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed import com.highcapable.yukihookapi.hook.factory.configs import com.highcapable.yukihookapi.hook.factory.encase -import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities -import com.highcapable.yukihookapi.hook.param.PackageParam import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit @InjectYukiHookWithXposed(isUsingResourcesHook = false) @@ -50,31 +46,9 @@ class HookEntry : IYukiHookXposedInit { isEnableDataChannel = false } - /** - * 装载对象是否为 QQ、TIM、微信 - * @return [Boolean] - */ - private fun PackageParam.isCurrentScope() = packageName.let { it == PackageName.QQ || it == PackageName.TIM || it == PackageName.WECHAT } - override fun onHook() = encase { - loadApp { - if (isCurrentScope()) onAppLifecycle { - attachBaseContext { baseContext, hasCalledSuper -> - if (hasCalledSuper) return@attachBaseContext - ConfigData.init(baseContext) - when (baseContext.packageName) { - PackageName.QQ, PackageName.TIM -> loadHooker(QQTIMHooker.apply { appVersionName = baseContext.versionName }) - PackageName.WECHAT -> loadHooker(WeChatHooker) - } - } - onCreate { - when (packageName) { - PackageName.QQ, PackageName.TIM -> - registerModuleAppActivities(proxy = "${PackageName.QQ}.activity.QQSettingSettingActivity") - PackageName.WECHAT -> registerModuleAppActivities(proxy = "${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI") - } - } - } - } + loadApp(PackageName.QQ) { loadHooker(QQTIMHooker) } + loadApp(PackageName.TIM) { loadHooker(QQTIMHooker) } + loadApp(PackageName.WECHAT) { loadHooker(WeChatHooker) } } } diff --git a/app/src/main/java/com/fankes/tsbattery/hook/entity/QQTIMHooker.kt b/app/src/main/java/com/fankes/tsbattery/hook/entity/QQTIMHooker.kt index 94267f0..81a1262 100644 --- a/app/src/main/java/com/fankes/tsbattery/hook/entity/QQTIMHooker.kt +++ b/app/src/main/java/com/fankes/tsbattery/hook/entity/QQTIMHooker.kt @@ -35,13 +35,13 @@ import com.fankes.tsbattery.hook.factory.hookSystemWakeLock import com.fankes.tsbattery.hook.factory.jumpToModuleSettings import com.fankes.tsbattery.hook.factory.startModuleSettings import com.fankes.tsbattery.utils.factory.dp +import com.fankes.tsbattery.utils.factory.versionName import com.highcapable.yukihookapi.hook.bean.VariousClass import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker -import com.highcapable.yukihookapi.hook.factory.buildOf -import com.highcapable.yukihookapi.hook.factory.current -import com.highcapable.yukihookapi.hook.factory.field +import com.highcapable.yukihookapi.hook.factory.* import com.highcapable.yukihookapi.hook.log.loggerD import com.highcapable.yukihookapi.hook.log.loggerE +import com.highcapable.yukihookapi.hook.log.loggerI import com.highcapable.yukihookapi.hook.type.android.* import com.highcapable.yukihookapi.hook.type.java.* @@ -79,7 +79,7 @@ object QQTIMHooker : YukiBaseHooker() { private val isQQ get() = packageName == PackageName.QQ /** 当前宿主的版本 */ - var appVersionName = "" + private var appVersionName = "" /** * 这个类 QQ 的 BaseChatPie 是控制聊天界面的 @@ -500,67 +500,74 @@ object QQTIMHooker : YukiBaseHooker() { } override fun onHook() { - /** Hook 跳转事件 */ - JumpActivityClass.hook { - injectMember { - method { - name = "doOnCreate" - param(BundleClass) - } - afterHook { instance().jumpToModuleSettings() } + onAppLifecycle { + onCreate { + appVersionName = versionName + ConfigData.init(context = this) + registerModuleAppActivities(QQSettingSettingActivityClass) + if (ConfigData.isDisableAllHook) return@onCreate + hookSystemWakeLock() + hookQQBaseChatPie() + hookCoreService() + hookQQDisgusting() + loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"") } } - /** 将条目注入设置界面 */ - QQSettingSettingActivityClass.hook { - injectMember { - method { - name = "doOnCreate" - param(BundleClass) + /** 仅注入主进程 */ + withProcess(mainProcessName) { + /** Hook 跳转事件 */ + JumpActivityClass.hook { + injectMember { + method { + name = "doOnCreate" + param(BundleClass) + } + afterHook { instance().jumpToModuleSettings() } } - afterHook { - /** 当前的顶级 Item 实例 */ - val formItemRefRoot = field { - type(FormSimpleItemClass).index(num = 1) - }.ignored().get(instance).cast() ?: field { - type(FormCommonSingleLineItemClass).index(num = 1) - }.ignored().get(instance).cast() - /** 创建一个新的 Item */ - FormSimpleItemClass.toClassOrNull()?.buildOf(instance) { param(ContextClass) }?.current { - method { - name = "setLeftText" - param(CharSequenceType) - }.call("TSBattery") - method { - name = "setRightText" - param(CharSequenceType) - }.call(BuildConfig.VERSION_NAME) - method { - name = "setBgType" - param(IntType) - }.call(if (isQQ) 0 else 2) - }?.apply { setOnClickListener { instance().startModuleSettings() } }?.also { item -> - var listGroup = formItemRefRoot?.parent as? ViewGroup? - val lparam = (if (listGroup?.childCount == 1) { - listGroup = listGroup.parent as? ViewGroup - (formItemRefRoot?.parent as? View?)?.layoutParams - } else formItemRefRoot?.layoutParams) - ?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - /** 设置圆角和间距 */ - if (isQQ) (lparam as? ViewGroup.MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0) - /** 将 Item 添加到设置界面 */ - listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) } + } + /** 将条目注入设置界面 */ + QQSettingSettingActivityClass.hook { + injectMember { + method { + name = "doOnCreate" + param(BundleClass) + } + afterHook { + /** 当前的顶级 Item 实例 */ + val formItemRefRoot = field { + type(FormSimpleItemClass).index(num = 1) + }.ignored().get(instance).cast() ?: field { + type(FormCommonSingleLineItemClass).index(num = 1) + }.ignored().get(instance).cast() + /** 创建一个新的 Item */ + FormSimpleItemClass.toClassOrNull()?.buildOf(instance) { param(ContextClass) }?.current { + method { + name = "setLeftText" + param(CharSequenceType) + }.call("TSBattery") + method { + name = "setRightText" + param(CharSequenceType) + }.call(BuildConfig.VERSION_NAME) + method { + name = "setBgType" + param(IntType) + }.call(if (isQQ) 0 else 2) + }?.apply { setOnClickListener { instance().startModuleSettings() } }?.also { item -> + var listGroup = formItemRefRoot?.parent as? ViewGroup? + val lparam = (if (listGroup?.childCount == 1) { + listGroup = listGroup.parent as? ViewGroup + (formItemRefRoot?.parent as? View?)?.layoutParams + } else formItemRefRoot?.layoutParams) + ?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + /** 设置圆角和间距 */ + if (isQQ) (lparam as? ViewGroup.MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0) + /** 将 Item 添加到设置界面 */ + listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) } + } } } } } - if (ConfigData.isDisableAllHook) return - /** Hook 系统电源锁 */ - hookSystemWakeLock() - /** Hook 聊天界面 */ - hookQQBaseChatPie() - /** Hook CoreService */ - hookCoreService() - /** Hook QQ 不省电的功能 */ - hookQQDisgusting() } } \ No newline at end of file diff --git a/app/src/main/java/com/fankes/tsbattery/hook/entity/WeChatHooker.kt b/app/src/main/java/com/fankes/tsbattery/hook/entity/WeChatHooker.kt index b3fbb77..122ca3c 100644 --- a/app/src/main/java/com/fankes/tsbattery/hook/entity/WeChatHooker.kt +++ b/app/src/main/java/com/fankes/tsbattery/hook/entity/WeChatHooker.kt @@ -36,10 +36,14 @@ import com.fankes.tsbattery.hook.factory.jumpToModuleSettings import com.fankes.tsbattery.hook.factory.startModuleSettings import com.fankes.tsbattery.utils.factory.absoluteStatusBarHeight import com.fankes.tsbattery.utils.factory.dp +import com.fankes.tsbattery.utils.factory.versionCode +import com.fankes.tsbattery.utils.factory.versionName import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker import com.highcapable.yukihookapi.hook.factory.current import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources -import com.highcapable.yukihookapi.hook.log.loggerD +import com.highcapable.yukihookapi.hook.factory.processName +import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities +import com.highcapable.yukihookapi.hook.log.loggerI import com.highcapable.yukihookapi.hook.type.android.BundleClass /** @@ -52,57 +56,76 @@ object WeChatHooker : YukiBaseHooker() { /** 微信存在的类 - 未测试每个版本是否都存在 */ const val LauncherUIClass = "${PackageName.WECHAT}.ui.LauncherUI" + /** 微信存在的类 - 未测试每个版本是否都存在 */ + private const val EmptyActivityClass = "${PackageName.WECHAT}.ui.EmptyActivity" + + /** 微信存在的类 - 未测试每个版本是否都存在 */ + private const val WelabMainUIClass = "${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI" + /** 微信存在的类 - 未测试每个版本是否都存在 */ private const val SettingsUIClass = "${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI" override fun onHook() { - /** Hook 跳转事件 */ - LauncherUIClass.hook { - injectMember { - method { - name = "onResume" - emptyParam() - } - afterHook { instance().jumpToModuleSettings(isFinish = false) } + onAppLifecycle { + onCreate { + ConfigData.init(context = this) + registerModuleAppActivities( + when { + EmptyActivityClass.hasClass() -> EmptyActivityClass + WelabMainUIClass.hasClass() -> WelabMainUIClass + else -> error("Inject WeChat Activity Proxy failed, unsupport version $versionName($versionCode)") + } + ) + if (ConfigData.isDisableAllHook) return@onCreate + hookSystemWakeLock() + loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"") } } - /** 向设置界面右上角添加按钮 */ - SettingsUIClass.hook { - injectMember { - method { - name = "onCreate" - param(BundleClass) - } - afterHook { + /** 仅注入主进程 */ + withProcess(mainProcessName) { + /** Hook 跳转事件 */ + LauncherUIClass.hook { + injectMember { method { - name = "get_fragment" + name = "onResume" emptyParam() - superClass(isOnlySuperClass = true) - }.get(instance).call()?.current() - ?.field { name = "mController" } - ?.current()?.method { name = "getContentView" } - ?.invoke()?.addView(LinearLayout(instance()).apply { - context.injectModuleAppResources() - gravity = Gravity.END or Gravity.BOTTOM - layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) - addView(ImageView(context).apply { - layoutParams = ViewGroup.MarginLayoutParams(20.dp(context), 20.dp(context)).apply { - topMargin = context.absoluteStatusBarHeight + 15.dp(context) - rightMargin = 20.dp(context) - } - setColorFilter(ResourcesCompat.getColor(resources, R.color.colorTextGray, null)) - setImageResource(R.drawable.ic_icon) - if (Build.VERSION.SDK_INT >= 26) tooltipText = "TSBattery 设置" - setOnClickListener { context.startModuleSettings() } + } + afterHook { instance().jumpToModuleSettings(isFinish = false) } + } + } + /** 向设置界面右上角添加按钮 */ + SettingsUIClass.hook { + injectMember { + method { + name = "onCreate" + param(BundleClass) + } + afterHook { + method { + name = "get_fragment" + emptyParam() + superClass(isOnlySuperClass = true) + }.get(instance).call()?.current() + ?.field { name = "mController" } + ?.current()?.method { name = "getContentView" } + ?.invoke()?.addView(LinearLayout(instance()).apply { + context.injectModuleAppResources() + gravity = Gravity.END or Gravity.BOTTOM + layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + addView(ImageView(context).apply { + layoutParams = ViewGroup.MarginLayoutParams(20.dp(context), 20.dp(context)).apply { + topMargin = context.absoluteStatusBarHeight + 15.dp(context) + rightMargin = 20.dp(context) + } + setColorFilter(ResourcesCompat.getColor(resources, R.color.colorTextGray, null)) + setImageResource(R.drawable.ic_icon) + if (Build.VERSION.SDK_INT >= 26) tooltipText = "TSBattery 设置" + setOnClickListener { context.startModuleSettings() } + }) }) - }) + } } } } - if (ConfigData.isDisableAllHook) return - /** Hook 系统电源锁 */ - hookSystemWakeLock() - /** 日志省电大法 */ - loggerD(msg = "ウイチャット:それが機能するかどうかはわかりませんでした") } } \ No newline at end of file