From 24346c056f600f294fc37d4156e993c8bf0fabc8 Mon Sep 17 00:00:00 2001 From: Fankesyooni Date: Thu, 31 Mar 2022 14:58:54 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E8=AE=BE=E7=BD=AE=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=98=BE=E7=A4=BA=E5=AE=88=E6=8A=A4=E7=8A=B6=E6=80=81?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=8A=A0=E5=85=A5=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E7=9C=81=E7=94=B5=20Hook=20=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 2 +- app/build.gradle | 2 +- .../com/fankes/tsbattery/data/DataConst.kt | 1 + .../com/fankes/tsbattery/hook/HookEntry.kt | 236 ++++++++++++++---- .../tsbattery/ui/activity/MainActivity.kt | 5 + app/src/main/res/layout/activity_main.xml | 19 ++ 6 files changed, 219 insertions(+), 46 deletions(-) diff --git a/.idea/misc.xml b/.idea/misc.xml index 255706a..3ffbf03 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -10,7 +10,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 3564ec4..34591d5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -38,7 +38,7 @@ android { buildTypes { release { - minifyEnabled true + minifyEnabled false signingConfig signingConfigs.debug proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } diff --git a/app/src/main/java/com/fankes/tsbattery/data/DataConst.kt b/app/src/main/java/com/fankes/tsbattery/data/DataConst.kt index 363e452..a5a1ead 100644 --- a/app/src/main/java/com/fankes/tsbattery/data/DataConst.kt +++ b/app/src/main/java/com/fankes/tsbattery/data/DataConst.kt @@ -28,6 +28,7 @@ object DataConst { val ENABLE_HIDE_ICON = PrefsData("_hide_icon", false) val ENABLE_RUN_INFO = PrefsData("_tip_run_info", false) val ENABLE_NOTIFY_TIP = PrefsData("_tip_in_notify", true) + val ENABLE_SETTING_TIP = PrefsData("_tip_in_setting", true) val ENABLE_QQTIM_WHITE_MODE = PrefsData("_qqtim_white_mode", false) val ENABLE_QQTIM_CORESERVICE_BAN = PrefsData("_qqtim_core_service_ban", false) val ENABLE_QQTIM_CORESERVICE_CHILD_BAN = PrefsData("_qqtim_core_service_child_ban", false) 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 f2997a0..300c0d0 100644 --- a/app/src/main/java/com/fankes/tsbattery/hook/HookEntry.kt +++ b/app/src/main/java/com/fankes/tsbattery/hook/HookEntry.kt @@ -25,19 +25,26 @@ package com.fankes.tsbattery.hook import android.app.Activity import android.app.Service +import android.content.ComponentName +import android.content.Intent import android.os.Build +import android.view.View +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.widget.Toast +import com.fankes.tsbattery.BuildConfig import com.fankes.tsbattery.data.DataConst import com.fankes.tsbattery.hook.HookConst.QQ_PACKAGE_NAME import com.fankes.tsbattery.hook.HookConst.TIM_PACKAGE_NAME import com.fankes.tsbattery.hook.HookConst.WECHAT_PACKAGE_NAME +import com.fankes.tsbattery.ui.activity.MainActivity import com.fankes.tsbattery.utils.factory.showDialog import com.fankes.tsbattery.utils.factory.versionCode import com.fankes.tsbattery.utils.factory.versionName import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed import com.highcapable.yukihookapi.hook.bean.VariousClass -import com.highcapable.yukihookapi.hook.factory.configs -import com.highcapable.yukihookapi.hook.factory.encase -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.param.PackageParam @@ -59,6 +66,12 @@ class HookEntry : YukiHookXposedInitProxy { /** QQ、TIM 存在的类 */ private const val CoreService_KernelServiceClass = "$QQ_PACKAGE_NAME.app.CoreService\$KernelService" + /** QQ、TIM 新版本存在的类 */ + private const val FormSimpleItemClass = "$QQ_PACKAGE_NAME.widget.FormSimpleItem" + + /** QQ、TIM 旧版本存在的类 */ + private const val FormCommonSingleLineItemClass = "$QQ_PACKAGE_NAME.widget.FormCommonSingleLineItem" + /** 微信存在的类 */ private const val LauncherUIClass = "$WECHAT_PACKAGE_NAME.ui.LauncherUI" @@ -200,8 +213,8 @@ class HookEntry : YukiHookXposedInitProxy { "\n\n模块只对挂后台锁屏情况下有省电效果," + "请不要将过多的群提醒,消息通知打开,这样子在使用过程时照样会极其耗电。\n\n" + "如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n\n" + - "持续常驻使用 QQ 依然会耗电,任何软件都是如此," + - "模块无法帮你做到前台不耗电,永远记住这一点。\n\n" + + "持续常驻使用 QQ、TIM 依然会耗电,任何软件都是如此," + + "模块是无法帮你做到前台不耗电的。\n\n" + "开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。" confirmButton(text = "我知道了") noCancelable() @@ -233,7 +246,7 @@ class HookEntry : YukiHookXposedInitProxy { "\n\n当前只支持微信的基础省电,即系统电源锁,后续会继续适配微信相关的省电功能(在新建文件夹了)。\n\n" + "如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n\n" + "持续常驻使用微信依然会耗电,任何软件都是如此," + - "模块无法帮你做到前台不耗电,永远记住这一点。\n\n" + + "模块是无法帮你做到前台不耗电的。\n\n" + "开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。" confirmButton(text = "我知道了") noCancelable() @@ -304,6 +317,101 @@ class HookEntry : YukiHookXposedInitProxy { } } + /** + * 将激活状态插入到设置页面 + * @param isQQ 是否为 QQ - 单独处理 + */ + private fun PackageParam.hookQQSettingsSettingActivity(isQQ: Boolean) = + findClass(name = "$QQ_PACKAGE_NAME.activity.QQSettingSettingActivity").hook { + injectMember { + method { + name = "doOnCreate" + param(BundleClass) + afterHook { + /** 是否启用 Hook */ + if (prefs.get(DataConst.ENABLE_SETTING_TIP).not()) return@afterHook + + /** 当前的顶级 Item 实例 */ + var formItemRefRoot: View? = null + + /** + * 使用循环筛选 + * @param target 目标变量名称 + * @return [View] or null + */ + fun match(target: String) = runCatching { + field { + name = target + type = FormSimpleItemClass.clazz + }.ignoredError().get(instance).cast() ?: field { + name = target + type = FormCommonSingleLineItemClass.clazz + }.ignoredError().get(instance).cast() + }.getOrNull() + /** 循环出当前设置界面存在的顶级 Item */ + arrayOf( + "a", "b", "c", "d", "e", "f", "g", + "h", "i", "j", "k", "l", "m", "n", + "o", "p", "q", "r", "s", "t", "u", + "v", "w", "x", "y", "z", "A", "B" + ).forEach { match(it)?.also { e -> formItemRefRoot = e } } + /** 创建一个新的 Item */ + FormSimpleItemClass.clazz.constructor { param(ContextClass) }.get().newInstance(instance)?.also { + it.javaClass.apply { + method { + name = "setLeftText" + param(CharSequenceType) + }.get(it).call("TSBattery") + method { + name = "setRightText" + param(CharSequenceType) + }.get(it).call(prefs.get(DataConst.ENABLE_MODULE_VERSION)) + method { + name = "setBgType" + param(IntType) + }.get(it).call(2) + } + it.setOnClickListener { + instance().apply { + showDialog { + title = "TSBattery 守护中" + msg = "已生效模块版本:${prefs.get(DataConst.ENABLE_MODULE_VERSION)}\n" + + "当前模式:${if (prefs.get(DataConst.ENABLE_QQTIM_WHITE_MODE)) "保守模式" else "完全模式"}" + + "\n\n包名:${packageName}\n版本:$versionName($versionCode)" + + "\n\n模块只对挂后台锁屏情况下有省电效果," + + "请不要将过多的群提醒,消息通知打开,这样子在使用过程时照样会极其耗电。\n\n" + + "持续常驻使用 QQ、TIM 依然会耗电,任何软件都是如此," + + "模块是无法帮你做到前台不耗电的。\n\n" + + "开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。" + confirmButton(text = "打开模块设置") { + runCatching { + startActivity(Intent().apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK + component = ComponentName( + BuildConfig.APPLICATION_ID, + MainActivity::class.java.name + ) + }) + }.onFailure { Toast.makeText(context, "启动失败", Toast.LENGTH_SHORT).show() } + } + cancelButton(text = "关闭") + } + } + } + }.apply { + 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(MATCH_PARENT, WRAP_CONTENT) + /** 将 Item 添加到设置界面 */ + listGroup?.also { if (isQQ) it.addView(this, lparam) else it.addView(this, 0, lparam) } + } + } + } + } + } + override fun onInit() = configs { debugTag = "TSBattery" isDebug = false @@ -316,6 +424,7 @@ class HookEntry : YukiHookXposedInitProxy { hookNotification() hookCoreService(isQQ = true) hookModuleRunningInfo(isQQTIM = true) + hookQQSettingsSettingActivity(isQQ = true) if (prefs.get(DataConst.ENABLE_QQTIM_WHITE_MODE)) return@loadApp /** 通过在 [SplashActivityClass] 里取到应用的版本号 */ SplashActivityClass.hook { @@ -327,43 +436,6 @@ class HookEntry : YukiHookXposedInitProxy { afterHook { hookQQBaseChatPie(instance().versionName) } } } - /** - * 一个不知道是什么作用的电源锁 - * 同样直接干掉 - */ - findClass(name = "com.tencent.mars.ilink.comm.WakerLock").hook { - injectMember { - method { - name = "lock" - param(LongType) - } - intercept() - }.ignoredAllFailure() - }.ignoredHookClassNotFoundFailure() - /** - * 一个不知道是什么作用的电源锁 - * 同样直接干掉 - */ - findClass(name = "com.tencent.mars.comm.WakerLock").hook { - injectMember { - method { - name = "lock" - param(LongType) - } - intercept() - }.ignoredAllFailure() - injectMember { - method { - name = "lock" - param(StringType) - } - intercept() - }.ignoredAllFailure() - injectMember { - method { name = "lock" } - intercept() - }.ignoredAllFailure() - }.ignoredHookClassNotFoundFailure() /** * 干掉消息收发功能的电源锁 * 每个版本的差异暂未做排查 @@ -420,7 +492,7 @@ class HookEntry : YukiHookXposedInitProxy { * 讯哥的程序员真的有你的 * 2022/1/25 后期查证:锁屏界面消息快速回复窗口 */ - findClass(name = "$QQ_PACKAGE_NAME.activity.QQLSActivity\$14").hook { + findClass("$QQ_PACKAGE_NAME.activity.QQLSActivity\$14", "ktq").hook { injectMember { method { name = "run" } intercept() @@ -491,12 +563,88 @@ class HookEntry : YukiHookXposedInitProxy { intercept() } }.ignoredHookClassNotFoundFailure() + /** + * 这个是毒瘤核心操作类 + * 功能同上、全部拦截 + */ + findClass(name = "com.tencent.qapmsdk.qqbattery.QQBatteryMonitor").hook { + injectMember { + method { name = "start" } + intercept() + } + injectMember { + method { name = "stop" } + intercept() + } + injectMember { + method { + name = "handleMessage" + param(MessageClass) + } + replaceToTrue() + } + injectMember { + method { name = "startMonitorInner" } + intercept() + } + injectMember { + method { name = "onAppBackground" } + intercept() + } + injectMember { + method { name = "onAppForeground" } + intercept() + } + injectMember { + method { + name = "setLogWhite" + paramCount = 2 + } + intercept() + } + injectMember { + method { + name = "setCmdWhite" + paramCount = 2 + } + intercept() + } + injectMember { + method { + name = "onWriteLog" + param(StringType, StringType) + } + intercept() + } + injectMember { + method { + name = "onCmdRequest" + param(StringType) + } + intercept() + } + injectMember { + method { + name = "addData" + paramCount = 4 + } + intercept() + } + injectMember { + method { + name = "onGpsScan" + paramCount = 2 + } + intercept() + } + }.ignoredHookClassNotFoundFailure() } loadApp(TIM_PACKAGE_NAME) { hookSystemWakeLock() hookNotification() hookCoreService(isQQ = false) hookModuleRunningInfo(isQQTIM = true) + hookQQSettingsSettingActivity(isQQ = false) } loadApp(WECHAT_PACKAGE_NAME) { if (prefs.get(DataConst.DISABLE_WECHAT_HOOK)) return@loadApp diff --git a/app/src/main/java/com/fankes/tsbattery/ui/activity/MainActivity.kt b/app/src/main/java/com/fankes/tsbattery/ui/activity/MainActivity.kt index ea82ab2..b7da053 100644 --- a/app/src/main/java/com/fankes/tsbattery/ui/activity/MainActivity.kt +++ b/app/src/main/java/com/fankes/tsbattery/ui/activity/MainActivity.kt @@ -144,6 +144,7 @@ class MainActivity : BaseActivity() { binding.hideIconInLauncherSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HIDE_ICON) binding.notifyModuleInfoSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_RUN_INFO) binding.notifyNotifyTipSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_TIP) + binding.settingModuleTipSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_SETTING_TIP) binding.qqtimProtectModeSwitch.setOnCheckedChangeListener { btn, b -> if (btn.isPressed.not()) return@setOnCheckedChangeListener modulePrefs.put(DataConst.ENABLE_QQTIM_WHITE_MODE, b) @@ -179,6 +180,10 @@ class MainActivity : BaseActivity() { if (btn.isPressed.not()) return@setOnCheckedChangeListener modulePrefs.put(DataConst.ENABLE_NOTIFY_TIP, b) } + binding.settingModuleTipSwitch.setOnCheckedChangeListener { btn, b -> + if (btn.isPressed.not()) return@setOnCheckedChangeListener + modulePrefs.put(DataConst.ENABLE_SETTING_TIP, b) + } /** 快捷操作 QQ */ binding.quickQqButton.setOnClickListener { openSelfSetting(QQ_PACKAGE_NAME) } /** 快捷操作 TIM */ diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 56c91ea..2d8dc1d 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -543,6 +543,25 @@ android:textColor="@color/colorTextDark" android:textSize="12sp" /> + + + +