diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f58b1e6..2caddc4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,6 @@ + xmlns:tools="http://schemas.android.com/tools"> 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 981c2ed..322de94 100644 --- a/app/src/main/java/com/fankes/tsbattery/hook/HookEntry.kt +++ b/app/src/main/java/com/fankes/tsbattery/hook/HookEntry.kt @@ -29,7 +29,7 @@ import com.highcapable.yukihookapi.hook.factory.configs import com.highcapable.yukihookapi.hook.factory.encase import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit -@InjectYukiHookWithXposed(isUsingResourcesHook = false) +@InjectYukiHookWithXposed object HookEntry : IYukiHookXposedInit { /** 是否完全支持当前版本 */ 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 900cb23..78456e9 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 @@ -52,10 +52,7 @@ import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources import com.highcapable.yukihookapi.hook.factory.method import com.highcapable.yukihookapi.hook.factory.processName import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities -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.log.loggerW +import com.highcapable.yukihookapi.hook.log.YLog import com.highcapable.yukihookapi.hook.type.android.BuildClass import com.highcapable.yukihookapi.hook.type.android.BundleClass import com.highcapable.yukihookapi.hook.type.android.ContextClass @@ -78,40 +75,48 @@ import java.lang.reflect.Proxy object QQTIMHooker : YukiBaseHooker() { /** QQ、TIM 存在的类 */ - const val JumpActivityClass = "${PackageName.QQ}.activity.JumpActivity" + const val JumpActivityClassName = "${PackageName.QQ}.activity.JumpActivity" + + /** QQ、TIM 存在的类 */ + private val JumpActivityClass by lazyClassOrNull(JumpActivityClassName) /** QQ、TIM 存在的类 (NT 版本不再存在) */ - private const val QQSettingSettingActivityClass = "${PackageName.QQ}.activity.QQSettingSettingActivity" + private val QQSettingSettingActivityClass by lazyClassOrNull("${PackageName.QQ}.activity.QQSettingSettingActivity") /** QQ 新版存在的类 (Pad 模式 - NT 版本不再存在) */ - private const val QQSettingSettingFragmentClass = "${PackageName.QQ}.fragment.QQSettingSettingFragment" + private val QQSettingSettingFragmentClass by lazyClassOrNull("${PackageName.QQ}.fragment.QQSettingSettingFragment") /** QQ、TIM 存在的类 (NT 版本不再存在) */ - private const val AboutActivityClass = "${PackageName.QQ}.activity.AboutActivity" + private val AboutActivityClass by lazyClassOrNull("${PackageName.QQ}.activity.AboutActivity") /** QQ 新版本存在的类 */ - private const val GeneralSettingActivityClass = "${PackageName.QQ}.activity.GeneralSettingActivity" + private val GeneralSettingActivityClass by lazyClassOrNull("${PackageName.QQ}.activity.GeneralSettingActivity") /** QQ 新版本 (NT) 存在的类 */ - private const val MainSettingFragmentClass = "${PackageName.QQ}.setting.main.MainSettingFragment" + private val MainSettingFragmentClass by lazyClassOrNull("${PackageName.QQ}.setting.main.MainSettingFragment") /** QQ 新版本 (NT) 存在的类 */ - private const val MainSettingConfigProviderClass = "${PackageName.QQ}.setting.main.MainSettingConfigProvider" + private val MainSettingConfigProviderClass by lazyClassOrNull("${PackageName.QQ}.setting.main.MainSettingConfigProvider") /** QQ、TIM 新版本存在的类 */ - private const val FormSimpleItemClass = "${PackageName.QQ}.widget.FormSimpleItem" + private val FormSimpleItemClass by lazyClassOrNull("${PackageName.QQ}.widget.FormSimpleItem") /** QQ、TIM 旧版本存在的类 */ - private const val FormCommonSingleLineItemClass = "${PackageName.QQ}.widget.FormCommonSingleLineItem" + private val FormCommonSingleLineItemClass by lazyClassOrNull("${PackageName.QQ}.widget.FormCommonSingleLineItem") /** QQ、TIM 存在的类 */ - private const val CoreServiceClass = "${PackageName.QQ}.app.CoreService" + private val CoreServiceClass by lazyClassOrNull("${PackageName.QQ}.app.CoreService") /** QQ、TIM 存在的类 */ - private const val CoreService_KernelServiceClass = "${PackageName.QQ}.app.CoreService\$KernelService" + private val CoreService_KernelServiceClass by lazyClassOrNull("${PackageName.QQ}.app.CoreService\$KernelService") /** 根据多个版本存的不同的类 */ - private val BaseChatPieClass = VariousClass("${PackageName.QQ}.activity.aio.core.BaseChatPie", "${PackageName.QQ}.activity.BaseChatPie") + private val BaseChatPieClass by lazyClassOrNull( + VariousClass( + "${PackageName.QQ}.activity.aio.core.BaseChatPie", + "${PackageName.QQ}.activity.BaseChatPie" + ) + ) /** 一个内部进程的名称 (与 X5 浏览器内核有关) */ private val privilegedProcessName = "$packageName:privileged_process" @@ -131,7 +136,7 @@ object QQTIMHooker : YukiBaseHooker() { * 在 QQ NT 中 [AboutActivityClass] 已被移除 - 以此作为判断条件 * @return [Boolean] */ - private val isQQNTVersion get() = isQQ && AboutActivityClass.hasClass().not() + private val isQQNTVersion get() = isQQ && AboutActivityClass == null /** 当前宿主的版本 */ private var hostVersionName = "" @@ -303,7 +308,7 @@ object QQTIMHooker : YukiBaseHooker() { } else -> { HookEntry.isHookClientSupport = false - loggerW(msg = "$hostVersionName not supported!") + YLog.warn("$hostVersionName not supported!") } } } @@ -313,72 +318,55 @@ object QQTIMHooker : YukiBaseHooker() { * @param methodName 方法名 */ private fun hookBaseChatPie(methodName: String) { - BaseChatPieClass.hook { - injectMember { - method { - name = methodName - emptyParam() - returnType = UnitType - } - intercept() - } - } + BaseChatPieClass?.method { + name = methodName + emptyParam() + returnType = UnitType + }?.hook()?.intercept() } /** Hook CoreService QQ、TIM */ private fun hookCoreService() { - CoreServiceClass.hook { + CoreServiceClass?.apply { if (isQQ) { - injectMember { - method { name = "startTempService" } - intercept() - }.ignoredNoSuchMemberFailure() - injectMember { - method { - name = "startCoreService" - param(BooleanType) - } - intercept() - }.ignoredNoSuchMemberFailure() - injectMember { - method { - name = "onStartCommand" - param(IntentClass, IntType, IntType) - } - replaceTo(any = 2) - }.ignoredNoSuchMemberFailure() - } - injectMember { - method { name = "onCreate" } - afterHook { - if (ConfigData.isEnableKillQQTimCoreService) - instance().apply { - ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) - stopSelf() - loggerD(msg = "Shutdown CoreService OK!") - } - } - } - } - CoreService_KernelServiceClass.hook { - injectMember { - method { name = "onCreate" } - afterHook { - if (ConfigData.isEnableKillQQTimCoreServiceChild) - instance().apply { - ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) - stopSelf() - loggerD(msg = "Shutdown CoreService\$KernelService OK!") - } - } - } - injectMember { + method { + name = "startTempService" + }.ignored().hook().intercept() + method { + name = "startCoreService" + param(BooleanType) + }.ignored().hook().intercept() method { name = "onStartCommand" param(IntentClass, IntType, IntType) - } - replaceTo(any = 2) - }.ignoredNoSuchMemberFailure() + }.ignored().hook().replaceTo(any = 2) + } + method { + name = "onCreate" + }.ignored().hook().after { + if (ConfigData.isEnableKillQQTimCoreService) + instance().apply { + ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) + stopSelf() + YLog.debug("Shutdown CoreService OK!") + } + } + } + CoreService_KernelServiceClass?.apply { + method { + name = "onCreate" + }.ignored().hook().after { + if (ConfigData.isEnableKillQQTimCoreServiceChild) + instance().apply { + ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE) + stopSelf() + YLog.debug("Shutdown CoreService\$KernelService OK!") + } + } + method { + name = "onStartCommand" + param(IntentClass, IntType, IntType) + }.ignored().hook().replaceTo(any = 2) } } @@ -390,63 +378,53 @@ object QQTIMHooker : YukiBaseHooker() { * 每个版本的差异暂未做排查 * 旧版本理论上没有这个类 */ - findClass(name = "${PackageName.QQ}.msf.service.y").hook { - injectMember { - method { - name = "a" - param(StringClass, LongType) - returnType = UnitType - } - intercept() - }.onAllFailure { loggerE(msg = "Hook MsfService Failed $it") } - }.ignoredHookClassNotFoundFailure() + "${PackageName.QQ}.msf.service.y".toClassOrNull() + ?.method { + name = "a" + param(StringClass, LongType) + returnType = UnitType + }?.ignored()?.hook()?.intercept() /** * 干掉自动上传服务的电源锁 * 每个版本的差异暂未做排查 */ - findClass(name = "com.tencent.upload.impl.UploadServiceImpl").hook { - injectMember { - method { name = "acquireWakeLockIfNot" } - intercept() - }.onAllFailure { loggerE(msg = "Hook UploadServiceImpl Failed $it") } - }.ignoredHookClassNotFoundFailure() + "com.tencent.upload.impl.UploadServiceImpl".toClassOrNull() + ?.method { + name = "acquireWakeLockIfNot" + }?.ignored()?.hook()?.intercept() /** - * Hook 掉一个一像素保活 [Activity] 真的我怎么都想不到讯哥的程序员做出这种事情 + * Hook 掉一个一像素保活 Activity 真的我怎么都想不到讯哥的程序员做出这种事情 * 这个东西经过测试会在锁屏的时候吊起来,解锁的时候自动 finish(),无限耍流氓耗电 * 2022/1/25 后期查证:锁屏界面消息快速回复窗口的解锁后拉起保活界面,也是毒瘤 */ - findClass(name = "${PackageName.QQ}.activity.QQLSUnlockActivity").hook { - injectMember { - method { - name = "onCreate" - param(BundleClass) - } + "${PackageName.QQ}.activity.QQLSUnlockActivity".toClassOrNull() + ?.method { + name = "onCreate" + param(BundleClass) + }?.ignored()?.hook { var origDevice = "" - beforeHook { + before { /** 由于在 onCreate 里有一行判断只要型号是 xiaomi 的设备就开电源锁,所以说这里临时替换成菊花厂 */ origDevice = Build.MANUFACTURER if (Build.MANUFACTURER.lowercase() == "xiaomi") BuildClass.field { name = "MANUFACTURER" }.get().set("HUAWEI") } - afterHook { + after { instance().finish() /** 这里再把型号替换回去 - 不影响应用变量等 Xposed 模块修改的型号 */ BuildClass.field { name = "MANUFACTURER" }.get().set(origDevice) } } - } /** * 这个东西同上 - * 反正也是一个一像素保活的 [Activity] + * 反正也是一个一像素保活的 Activity * 讯哥的程序员真的有你的 * 2022/1/25 后期查证:锁屏界面消息快速回复窗口 */ - findClass("${PackageName.QQ}.activity.QQLSActivity\$14", "ktq").hook { - injectMember { - method { name = "run" } - intercept() - }.ignoredAllFailure() - }.ignoredHookClassNotFoundFailure() + VariousClass("${PackageName.QQ}.activity.QQLSActivity\$14", "ktq").toClassOrNull() + ?.method { + name = "run" + }?.ignored()?.hook()?.intercept() /** * 这个是毒瘤核心类 * WakeLockMonitor @@ -457,144 +435,97 @@ object QQTIMHooker : YukiBaseHooker() { * 👮🏻 经过排查 Play 版本没这个类...... Emmmm 不想说啥了 * ✅ 备注:8.9.x 版本已经基本移除了这个功能,没有再发现存在这个类 */ - findClass(name = "com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor").hook { - injectMember { - method { - name = "onHook" - param(StringClass, AnyClass, AnyArrayClass, AnyClass) - } - intercept() - } - injectMember { - method { - name = "doReport" - param("com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor\$WakeLockEntity", IntType) - } - intercept() - } - injectMember { - method { - name = "afterHookedMethod" - param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam") - } - intercept() - } - injectMember { - method { - name = "beforeHookedMethod" - param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam") - } - intercept() - } - injectMember { - method { name = "onAppBackground" } - intercept() - } - injectMember { - method { - name = "onOtherProcReport" - param(BundleClass) - } - intercept() - } - injectMember { - method { name = "onProcessRun30Min" } - intercept() - } - injectMember { - method { name = "onProcessBG5Min" } - intercept() - } - injectMember { - method { - name = "writeReport" - param(BooleanType) - } - intercept() - } - }.ignoredHookClassNotFoundFailure() + "com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor".toClassOrNull()?.apply { + method { + name = "onHook" + param(StringClass, AnyClass, AnyArrayClass, AnyClass) + }.ignored().hook().intercept() + method { + name = "doReport" + param("com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor\$WakeLockEntity", IntType) + }.ignored().hook().intercept() + method { + name = "afterHookedMethod" + param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam") + }.ignored().hook().intercept() + method { + name = "beforeHookedMethod" + param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam") + }.ignored().hook().intercept() + method { + name = "onAppBackground" + }.ignored().hook().intercept() + method { + name = "onOtherProcReport" + param(BundleClass) + }.ignored().hook().intercept() + method { + name = "onProcessRun30Min" + }.ignored().hook().intercept() + method { + name = "onProcessBG5Min" + }.ignored().hook().intercept() + method { + name = "writeReport" + param(BooleanType) + }.ignored().hook().intercept() + } /** * 这个是毒瘤核心操作类 * 功能同上、全部拦截 * 👮🏻 经过排查 Play 版本也没这个类...... Emmmm 不想说啥了 * ✅ 备注:8.9.x 版本已经基本移除了这个功能,没有再发现存在这个类 */ - 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(StringClass, StringClass) - } - intercept() - } - injectMember { - method { - name = "onCmdRequest" - param(StringClass) - } - intercept() - } - injectMember { - method { - name = "addData" - paramCount = 4 - } - intercept() - } - injectMember { - method { - name = "onGpsScan" - paramCount = 2 - } - intercept() - } - }.ignoredHookClassNotFoundFailure() + "com.tencent.qapmsdk.qqbattery.QQBatteryMonitor".toClassOrNull()?.apply { + method { + name = "start" + }.ignored().hook().intercept() + method { + name = "stop" + }.ignored().hook().intercept() + method { + name = "handleMessage" + param(MessageClass) + }.ignored().hook().intercept() + method { + name = "startMonitorInner" + }.ignored().hook().intercept() + method { + name = "onAppBackground" + }.ignored().hook().intercept() + method { + name = "onAppForeground" + }.ignored().hook().intercept() + method { + name = "setLogWhite" + paramCount = 2 + }.ignored().hook().intercept() + method { + name = "setCmdWhite" + paramCount = 2 + }.ignored().hook().intercept() + method { + name = "onWriteLog" + param(StringClass, StringClass) + }.ignored().hook().intercept() + method { + name = "onCmdRequest" + param(StringClass) + }.ignored().hook().intercept() + method { + name = "addData" + paramCount = 4 + }.ignored().hook().intercept() + method { + name = "onGpsScan" + paramCount = 2 + }.ignored().hook().intercept() + } } /** Hook QQ 的设置界面添加模块设置入口 (新版) */ private fun hookQQSettingsUi() { - if (MainSettingFragmentClass.hasClass().not()) return loggerE(msg = "Could not found main setting class, hook aborted") + if (MainSettingFragmentClass == null) return YLog.error("Could not found main setting class, hook aborted") val kotlinUnit = "kotlin.Unit" val kotlinFunction0 = "kotlin.jvm.functions.Function0" val simpleItemProcessorClass = searchClass { @@ -605,7 +536,7 @@ object QQTIMHooker : YukiBaseHooker() { returnType = UnitType } field().count { it >= 6 } - }.get() ?: return loggerE(msg = "Could not found processor class, hook aborted") + }.get() ?: return YLog.error("Could not found processor class, hook aborted") /** * 创建入口点条目 @@ -623,7 +554,7 @@ object QQTIMHooker : YukiBaseHooker() { param { it[0].name == kotlinFunction0 } paramCount = 1 returnType = UnitType - }.giveAll().lastOrNull() ?: error("Could not found processor method") + }.giveAll().firstOrNull() ?: error("Could not found processor method") val proxyOnClick = Proxy.newProxyInstance(appClassLoader, arrayOf(onClickMethod.parameterTypes[0])) { any, method, args -> if (method.name == "invoke") { context.startModuleSettings() @@ -632,20 +563,15 @@ object QQTIMHooker : YukiBaseHooker() { }; onClickMethod.invoke(entryItem, proxyOnClick) } ?: error("Could not create TSBattery entry item") } - MainSettingConfigProviderClass.hook { - injectMember { - method { - param(ContextClass) - returnType = ListClass - } - afterHook { - val context = args().first().cast() ?: return@afterHook - val processor = result>() ?: return@afterHook - processor.add(1, processor[0]?.javaClass?.buildOf(arrayListOf().apply { add(createTSEntryItem(context)) }, "", "") { - param(ListClass, CharSequenceClass, CharSequenceClass) - }) - } - } + MainSettingConfigProviderClass?.method { + param(ContextClass) + returnType = ListClass + }?.hook()?.after { + val context = args().first().cast() ?: return@after + val processor = result>() ?: return@after + processor.add(1, processor[0]?.javaClass?.buildOf(arrayListOf().apply { add(createTSEntryItem(context)) }, "", "") { + param(ListClass, CharSequenceClass, CharSequenceClass) + }) } } @@ -656,10 +582,10 @@ object QQTIMHooker : YukiBaseHooker() { private fun hookQQSettingsUiLegacy(instance: Any?) { /** 当前的顶级 Item 实例 */ val formItemRefRoot = instance?.current()?.field { - type { it.name == FormSimpleItemClass || it.name == FormCommonSingleLineItemClass }.index(num = 1) + type { it == FormSimpleItemClass || it == FormCommonSingleLineItemClass }.index(num = 1) }?.cast() /** 创建一个新的 Item */ - FormSimpleItemClass.toClassOrNull()?.buildOf(instance?.compatToActivity()) { param(ContextClass) }?.current { + FormSimpleItemClass?.buildOf(instance?.compatToActivity()) { param(ContextClass) }?.current { method { name = "setLeftText" param(CharSequenceClass) @@ -705,44 +631,29 @@ object QQTIMHooker : YukiBaseHooker() { hookQQBaseChatPie() hookCoreService() hookQQDisgusting() - loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"") + YLog.info("All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"") } } /** 仅注入主进程 */ withProcess(mainProcessName) { /** Hook 跳转事件 */ - JumpActivityClass.hook { - injectMember { - method { - name = "doOnCreate" - param(BundleClass) - } - afterHook { instance().jumpToModuleSettings() } - } - } + JumpActivityClass?.method { + name = "doOnCreate" + param(BundleClass) + }?.hook()?.after { instance().jumpToModuleSettings() } /** Hook 设置界面入口点 */ if (isQQNTVersion) hookQQSettingsUi() else { /** 将条目注入设置界面 (Activity) */ - QQSettingSettingActivityClass.hook { - injectMember { - method { - name = "doOnCreate" - param(BundleClass) - } - afterHook { hookQQSettingsUiLegacy(instance) } - } - } + QQSettingSettingActivityClass?.method { + name = "doOnCreate" + param(BundleClass) + }?.hook()?.after { hookQQSettingsUiLegacy(instance) } /** 将条目注入设置界面 (Fragment) */ - QQSettingSettingFragmentClass.hook { - injectMember { - method { - name = "doOnCreateView" - paramCount = 3 - } - afterHook { hookQQSettingsUiLegacy(instance) } - } - }.ignoredHookClassNotFoundFailure() + QQSettingSettingFragmentClass?.method { + name = "doOnCreateView" + paramCount = 3 + }?.hook()?.after { hookQQSettingsUiLegacy(instance) } } } } 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 dc535e5..a1fd523 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 @@ -45,9 +45,10 @@ import com.fankes.tsbattery.utils.factory.dp 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.factory.method 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.log.YLog import com.highcapable.yukihookapi.hook.type.android.ViewClass /** @@ -58,16 +59,19 @@ import com.highcapable.yukihookapi.hook.type.android.ViewClass object WeChatHooker : YukiBaseHooker() { /** 微信存在的类 - 未测试每个版本是否都存在 */ - const val LauncherUIClass = "${PackageName.WECHAT}.ui.LauncherUI" + const val LauncherUIClassName = "${PackageName.WECHAT}.ui.LauncherUI" /** 微信存在的类 - 未测试每个版本是否都存在 */ - private const val EmptyActivityClass = "${PackageName.WECHAT}.ui.EmptyActivity" + private val LauncherUIClass by lazyClassOrNull("${PackageName.WECHAT}.ui.LauncherUI") /** 微信存在的类 - 未测试每个版本是否都存在 */ - private const val WelabMainUIClass = "${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI" + private val EmptyActivityClass by lazyClassOrNull("${PackageName.WECHAT}.ui.EmptyActivity") /** 微信存在的类 - 未测试每个版本是否都存在 */ - private const val SettingsUIClass = "${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI" + private val WelabMainUIClass by lazyClassOrNull("${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI") + + /** 微信存在的类 - 未测试每个版本是否都存在 */ + private val SettingsUIClass by lazyClassOrNull("${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI") /** TSBattery 图标 TAG 名称 */ private const val TSBARRERY_ICON_TAG = "tsbattery_icon" @@ -98,51 +102,41 @@ object WeChatHooker : YukiBaseHooker() { onCreate { ConfigData.init(context = this) registerModuleAppActivities(when { - EmptyActivityClass.hasClass() -> EmptyActivityClass - WelabMainUIClass.hasClass() -> WelabMainUIClass + EmptyActivityClass != null -> EmptyActivityClass + WelabMainUIClass != null -> WelabMainUIClass else -> error("Inject WeChat Activity Proxy failed, unsupport version $appVersionName($appVersionCode)") }) if (ConfigData.isDisableAllHook) return@onCreate hookSystemWakeLock() - loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"") + YLog.info("All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"") } } /** 仅注入主进程 */ withProcess(mainProcessName) { /** Hook 跳转事件 */ - LauncherUIClass.hook { - injectMember { - method { - name = "onResume" - emptyParam() - } - afterHook { instance().jumpToModuleSettings(isFinish = false) } - } - } + LauncherUIClass?.method { + name = "onResume" + emptyParam() + }?.hook()?.after { instance().jumpToModuleSettings(isFinish = false) } /** 向设置界面右上角添加按钮 */ - SettingsUIClass.hook { - injectMember { - method { - name = "onResume" - emptyParam() - } - afterHook { - method { - name = "get_fragment" - emptyParam() - superClass(isOnlySuperClass = true) - }.get(instance).call()?.current()?.method { - name = "getView" - emptyParam() - returnType = ViewClass - superClass(isOnlySuperClass = true) - }?.invoke()?.also { - it.context?.injectModuleAppResources() - runCatching { it.getChildAt(0) as? ViewGroup? }.getOrNull()?.also { rootView -> - if (rootView.findViewWithTag(TSBARRERY_ICON_TAG) == null) - rootView.addView(createPreferenceIcon(it.context)) - } - } + SettingsUIClass?.method { + name = "onResume" + emptyParam() + }?.hook()?.after { + SettingsUIClass?.method { + name = "get_fragment" + emptyParam() + superClass(isOnlySuperClass = true) + }?.get(instance)?.call()?.current()?.method { + name = "getView" + emptyParam() + returnType = ViewClass + superClass(isOnlySuperClass = true) + }?.invoke()?.also { + it.context?.injectModuleAppResources() + runCatching { it.getChildAt(0) as? ViewGroup? }.getOrNull()?.also { rootView -> + if (rootView.findViewWithTag(TSBARRERY_ICON_TAG) == null) + rootView.addView(createPreferenceIcon(it.context)) } } } diff --git a/app/src/main/java/com/fankes/tsbattery/hook/factory/BasicHookFactory.kt b/app/src/main/java/com/fankes/tsbattery/hook/factory/BasicHookFactory.kt index afa0d6b..1a47fcd 100644 --- a/app/src/main/java/com/fankes/tsbattery/hook/factory/BasicHookFactory.kt +++ b/app/src/main/java/com/fankes/tsbattery/hook/factory/BasicHookFactory.kt @@ -81,13 +81,8 @@ fun Activity.jumpToModuleSettings(isFinish: Boolean = true) { /** Hook 系统电源锁 */ fun PackageParam.hookSystemWakeLock() { - PowerManager_WakeLockClass.hook { - injectMember { - method { - name = "acquireLocked" - emptyParam() - } - intercept() - } - } + PowerManager_WakeLockClass.method { + name = "acquireLocked" + emptyParam() + }.hook().intercept() } \ No newline at end of file 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 a1de70b..d509112 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 @@ -189,7 +189,7 @@ class MainActivity : BaseActivity() { startActivity(Intent().apply { component = ComponentName( packageName, - if (packageName != PackageName.WECHAT) QQTIMHooker.JumpActivityClass else WeChatHooker.LauncherUIClass + if (packageName != PackageName.WECHAT) QQTIMHooker.JumpActivityClassName else WeChatHooker.LauncherUIClassName ) putExtra(JumpEvent.OPEN_MODULE_SETTING, YukiHookAPI.Status.compiledTimestamp) flags = Intent.FLAG_ACTIVITY_NEW_TASK diff --git a/app/src/main/java/com/fankes/tsbattery/utils/factory/DialogBuilderFactory.kt b/app/src/main/java/com/fankes/tsbattery/utils/factory/DialogBuilderFactory.kt index 583fdce..08561ca 100644 --- a/app/src/main/java/com/fankes/tsbattery/utils/factory/DialogBuilderFactory.kt +++ b/app/src/main/java/com/fankes/tsbattery/utils/factory/DialogBuilderFactory.kt @@ -19,7 +19,7 @@ * * This file is created by fankes on 2022/1/7. */ -@file:Suppress("unused", "OPT_IN_USAGE", "EXPERIMENTAL_API_USAGE") +@file:Suppress("unused") package com.fankes.tsbattery.utils.factory @@ -34,7 +34,6 @@ import androidx.appcompat.app.AlertDialog import com.fankes.tsbattery.R import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.progressindicator.CircularProgressIndicator -import com.highcapable.yukihookapi.annotation.CauseProblemsApi import com.highcapable.yukihookapi.hook.factory.applyModuleTheme /** @@ -134,7 +133,6 @@ class DialogBuilder(val context: Context) { fun cancel() = dialogInstance?.cancel() /** 显示对话框 */ - @CauseProblemsApi fun show() = runInSafe { instance?.create()?.apply { customLayoutView?.let { setView(it) } diff --git a/app/src/main/java/com/fankes/tsbattery/utils/factory/ExceptionFactory.kt b/app/src/main/java/com/fankes/tsbattery/utils/factory/ExceptionFactory.kt index 1132e9a..b4bc74d 100644 --- a/app/src/main/java/com/fankes/tsbattery/utils/factory/ExceptionFactory.kt +++ b/app/src/main/java/com/fankes/tsbattery/utils/factory/ExceptionFactory.kt @@ -23,7 +23,7 @@ package com.fankes.tsbattery.utils.factory -import com.highcapable.yukihookapi.hook.log.loggerE +import com.highcapable.yukihookapi.hook.log.YLog /** * 忽略异常返回值 @@ -78,5 +78,5 @@ inline fun safeOf(default: T, result: () -> T) = try { * @param block 正常回调 */ inline fun T.runInSafe(msg: String = "", block: () -> Unit) { - runCatching(block).onFailure { if (msg.isNotBlank()) loggerE(msg = msg, e = it) } + runCatching(block).onFailure { if (msg.isNotBlank()) YLog.error(msg, it) } } \ No newline at end of file diff --git a/app/src/main/java/com/fankes/tsbattery/utils/factory/FunctionFactory.kt b/app/src/main/java/com/fankes/tsbattery/utils/factory/FunctionFactory.kt index 43b4b3e..90bd46b 100644 --- a/app/src/main/java/com/fankes/tsbattery/utils/factory/FunctionFactory.kt +++ b/app/src/main/java/com/fankes/tsbattery/utils/factory/FunctionFactory.kt @@ -75,7 +75,7 @@ inline val Context.isNotSystemInDarkMode get() = !isSystemInDarkMode * @return [PackageInfo] or null */ private fun Context.getPackageInfoCompat(packageName: String, flag: Number = 0) = runCatching { - @Suppress("DEPRECATION") + @Suppress("DEPRECATION", "KotlinRedundantDiagnosticSuppress") if (Build.VERSION.SDK_INT >= 33) packageManager?.getPackageInfo(packageName, PackageInfoFlags.of(flag.toLong())) else packageManager?.getPackageInfo(packageName, flag.toInt())