mirror of
https://github.com/fankes/TSBattery.git
synced 2025-09-07 03:06:06 +08:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
f285e6f96d | |||
fb90d4051b | |||
911eb042a6 | |||
9d48732140 | |||
2d31d46cd2 | |||
3a1a20e688 | |||
24346c056f | |||
e05c8fce30 | |||
e1b15c4c0a | |||
5b99288ea8 | |||
da958920b3 | |||
035e07db89 | |||
90de1612f3 | |||
9d2a87449d | |||
7a8bc6c8f8 | |||
b1e1e15412 | |||
569d4e278a | |||
2729724e93 | |||
64f87bd69f |
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -10,7 +10,7 @@
|
|||||||
<entry key="app/src/main/res/drawable/dark_round.xml" value="0.4482051282051282" />
|
<entry key="app/src/main/res/drawable/dark_round.xml" value="0.4482051282051282" />
|
||||||
<entry key="app/src/main/res/drawable/permotion_round.xml" value="0.4482051282051282" />
|
<entry key="app/src/main/res/drawable/permotion_round.xml" value="0.4482051282051282" />
|
||||||
<entry key="app/src/main/res/drawable/red_round.xml" value="0.4482051282051282" />
|
<entry key="app/src/main/res/drawable/red_round.xml" value="0.4482051282051282" />
|
||||||
<entry key="app/src/main/res/layout/activity_main.xml" value="0.3504380475594493" />
|
<entry key="app/src/main/res/layout/activity_main.xml" value="0.3413246647704185" />
|
||||||
<entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.2495" />
|
<entry key="app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml" value="0.2495" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
[](https://github.com/fankes/TSBattery)
|
[](https://github.com/fankes/TSBattery)
|
||||||
[](https://github.com/fankes/TSBattery/blob/master/LICENSE)
|
[](https://github.com/fankes/TSBattery/blob/master/LICENSE)
|
||||||
[](https://github.com/fankes/TSBattery/releases)
|
[](https://github.com/fankes/TSBattery/releases)
|
||||||
[](https://github.com/fankes/TSBattery/releases)
|
[](https://github.com/fankes/TSBattery/releases)
|
||||||
[](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)
|
[](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)
|
||||||
[](https://t.me/XiaofangInternet)
|
[](https://t.me/XiaofangInternet)
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application'
|
id 'com.android.application'
|
||||||
id 'kotlin-android'
|
id 'kotlin-android'
|
||||||
id 'com.google.devtools.ksp' version '1.6.10-1.0.2'
|
id 'com.google.devtools.ksp' version '1.6.10-1.0.4'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -44,33 +44,17 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_11
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
targetCompatibility JavaVersion.VERSION_11
|
||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '1.8'
|
jvmTarget = '11'
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding true
|
viewBinding true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly 'de.robv.android.xposed:api:82'
|
|
||||||
implementation 'com.highcapable.yukihookapi:api:1.0.6'
|
|
||||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.6'
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
|
||||||
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
|
|
||||||
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.0'
|
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
|
||||||
testImplementation 'junit:junit:4.13.2'
|
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 移除无效耗时 lint Task */
|
/** 移除无效耗时 lint Task */
|
||||||
tasks.whenTaskAdded {
|
tasks.whenTaskAdded {
|
||||||
task -> if (task.name == "lintVitalRelease") task.enabled = false
|
task -> if (task.name == "lintVitalRelease") task.enabled = false
|
||||||
@@ -84,4 +68,20 @@ tasks.whenTaskAdded {
|
|||||||
/** 移除无效耗时 lint Task */
|
/** 移除无效耗时 lint Task */
|
||||||
tasks.whenTaskAdded {
|
tasks.whenTaskAdded {
|
||||||
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
|
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly 'de.robv.android.xposed:api:82'
|
||||||
|
implementation 'com.highcapable.yukihookapi:api:1.0.70'
|
||||||
|
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.70'
|
||||||
|
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
||||||
|
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
|
||||||
|
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.0'
|
||||||
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
|
implementation 'com.google.android.material:material:1.5.0'
|
||||||
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
|
testImplementation 'junit:junit:4.13.2'
|
||||||
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||||
}
|
}
|
@@ -26,14 +26,15 @@
|
|||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposedmodule"
|
android:name="xposedmodule"
|
||||||
android:value="true" />
|
android:value="true" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposeddescription"
|
android:name="xposeddescription"
|
||||||
android:value="Tencent 社交毒瘤一键省电模块。\n目前支持 QQ、TIM、微信\n开发者:酷安 @星夜不荟" />
|
android:value="Tencent 社交毒瘤一键省电模块。\n目前支持 QQ、TIM、微信\n开发者:酷安 @星夜不荟" />
|
||||||
|
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="xposedminversion"
|
android:name="xposedminversion"
|
||||||
android:value="93" />
|
android:value="93" />
|
||||||
|
<meta-data
|
||||||
|
android:name="xposedscope"
|
||||||
|
android:resource="@array/module_scope" />
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name="com.fankes.tsbattery.ui.activity.MainActivity"
|
android:name="com.fankes.tsbattery.ui.activity.MainActivity"
|
||||||
|
37
app/src/main/java/com/fankes/tsbattery/data/DataConst.kt
Normal file
37
app/src/main/java/com/fankes/tsbattery/data/DataConst.kt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||||
|
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
|
||||||
|
* https://github.com/fankes/TSBattery
|
||||||
|
*
|
||||||
|
* This software is non-free but opensource software: you can redistribute it
|
||||||
|
* and/or modify it under the terms of the GNU Affero General Public License
|
||||||
|
* as published by the Free Software Foundation; either
|
||||||
|
* version 3 of the License, or any later version.
|
||||||
|
*
|
||||||
|
* This software is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* and eula along with this software. If not, see
|
||||||
|
* <https://www.gnu.org/licenses/>
|
||||||
|
*
|
||||||
|
* This file is Created by fankes on 2022/3/28.
|
||||||
|
*/
|
||||||
|
package com.fankes.tsbattery.data
|
||||||
|
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
|
||||||
|
|
||||||
|
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)
|
||||||
|
val DISABLE_WECHAT_HOOK = PrefsData("_disable_wechat_hook", false)
|
||||||
|
val ENABLE_MODULE_VERSION = PrefsData("_module_version", "")
|
||||||
|
}
|
@@ -23,15 +23,6 @@ package com.fankes.tsbattery.hook
|
|||||||
|
|
||||||
object HookConst {
|
object HookConst {
|
||||||
|
|
||||||
const val ENABLE_HIDE_ICON = "_hide_icon"
|
|
||||||
const val ENABLE_RUN_INFO = "_tip_run_info"
|
|
||||||
const val ENABLE_NOTIFY_TIP = "_tip_in_notify"
|
|
||||||
const val ENABLE_QQTIM_WHITE_MODE = "_qqtim_white_mode"
|
|
||||||
const val ENABLE_QQTIM_CORESERVICE_BAN = "_qqtim_core_service_ban"
|
|
||||||
const val ENABLE_QQTIM_CORESERVICE_CHILD_BAN = "_qqtim_core_service_child_ban"
|
|
||||||
const val DISABLE_WECHAT_HOOK = "_disable_wechat_hook"
|
|
||||||
const val ENABLE_MODULE_VERSION = "_module_version"
|
|
||||||
|
|
||||||
const val QQ_PACKAGE_NAME = "com.tencent.mobileqq"
|
const val QQ_PACKAGE_NAME = "com.tencent.mobileqq"
|
||||||
const val TIM_PACKAGE_NAME = "com.tencent.tim"
|
const val TIM_PACKAGE_NAME = "com.tencent.tim"
|
||||||
const val WECHAT_PACKAGE_NAME = "com.tencent.mm"
|
const val WECHAT_PACKAGE_NAME = "com.tencent.mm"
|
||||||
|
@@ -25,26 +25,28 @@ package com.fankes.tsbattery.hook
|
|||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Service
|
import android.app.Service
|
||||||
|
import android.content.ComponentName
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import com.fankes.tsbattery.hook.HookConst.DISABLE_WECHAT_HOOK
|
import android.view.View
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_MODULE_VERSION
|
import android.view.ViewGroup
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_NOTIFY_TIP
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_QQTIM_CORESERVICE_BAN
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_QQTIM_CORESERVICE_CHILD_BAN
|
import android.view.ViewGroup.MarginLayoutParams
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_QQTIM_WHITE_MODE
|
import android.widget.Toast
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_RUN_INFO
|
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.QQ_PACKAGE_NAME
|
||||||
import com.fankes.tsbattery.hook.HookConst.TIM_PACKAGE_NAME
|
import com.fankes.tsbattery.hook.HookConst.TIM_PACKAGE_NAME
|
||||||
import com.fankes.tsbattery.hook.HookConst.WECHAT_PACKAGE_NAME
|
import com.fankes.tsbattery.hook.HookConst.WECHAT_PACKAGE_NAME
|
||||||
|
import com.fankes.tsbattery.ui.activity.MainActivity
|
||||||
|
import com.fankes.tsbattery.utils.factory.dp
|
||||||
import com.fankes.tsbattery.utils.factory.showDialog
|
import com.fankes.tsbattery.utils.factory.showDialog
|
||||||
import com.fankes.tsbattery.utils.factory.versionCode
|
import com.fankes.tsbattery.utils.factory.versionCode
|
||||||
import com.fankes.tsbattery.utils.factory.versionName
|
import com.fankes.tsbattery.utils.factory.versionName
|
||||||
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
|
||||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||||
import com.highcapable.yukihookapi.hook.factory.configs
|
import com.highcapable.yukihookapi.hook.factory.*
|
||||||
import com.highcapable.yukihookapi.hook.factory.encase
|
|
||||||
import com.highcapable.yukihookapi.hook.factory.field
|
|
||||||
import com.highcapable.yukihookapi.hook.log.loggerD
|
import com.highcapable.yukihookapi.hook.log.loggerD
|
||||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
import com.highcapable.yukihookapi.hook.log.loggerE
|
||||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||||
@@ -66,6 +68,12 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
/** QQ、TIM 存在的类 */
|
/** QQ、TIM 存在的类 */
|
||||||
private const val CoreService_KernelServiceClass = "$QQ_PACKAGE_NAME.app.CoreService\$KernelService"
|
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"
|
private const val LauncherUIClass = "$WECHAT_PACKAGE_NAME.ui.LauncherUI"
|
||||||
|
|
||||||
@@ -122,7 +130,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
interceptBaseChatPie(methodName = "bk")
|
interceptBaseChatPie(methodName = "bk")
|
||||||
interceptBaseChatPie(methodName = "bl")
|
interceptBaseChatPie(methodName = "bl")
|
||||||
}
|
}
|
||||||
"8.8.83" -> {
|
"8.8.83", "8.8.85" -> {
|
||||||
interceptBaseChatPie(methodName = "bl")
|
interceptBaseChatPie(methodName = "bl")
|
||||||
interceptBaseChatPie(methodName = "bm")
|
interceptBaseChatPie(methodName = "bm")
|
||||||
}
|
}
|
||||||
@@ -166,8 +174,8 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
param(CharSequenceType)
|
param(CharSequenceType)
|
||||||
}
|
}
|
||||||
beforeHook {
|
beforeHook {
|
||||||
if (prefs.getBoolean(ENABLE_NOTIFY_TIP, default = true))
|
if (prefs.get(DataConst.ENABLE_NOTIFY_TIP))
|
||||||
when (firstArgs as CharSequence) {
|
when (firstArgs<CharSequence>()) {
|
||||||
"QQ正在后台运行" ->
|
"QQ正在后台运行" ->
|
||||||
args().set("QQ正在后台运行 - TSBattery 守护中")
|
args().set("QQ正在后台运行 - TSBattery 守护中")
|
||||||
"TIM正在后台运行" ->
|
"TIM正在后台运行" ->
|
||||||
@@ -195,20 +203,20 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
param(BundleClass)
|
param(BundleClass)
|
||||||
}
|
}
|
||||||
afterHook {
|
afterHook {
|
||||||
if (prefs.getBoolean(ENABLE_RUN_INFO))
|
if (prefs.get(DataConst.ENABLE_RUN_INFO))
|
||||||
instance<Activity>().apply {
|
instance<Activity>().apply {
|
||||||
showDialog {
|
showDialog {
|
||||||
title = "TSBattery 已激活"
|
title = "TSBattery 已激活"
|
||||||
msg = "[提示模块运行信息功能已打开]\n\n" +
|
msg = "[提示模块运行信息功能已打开]\n\n" +
|
||||||
"模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" +
|
"模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" +
|
||||||
"已生效模块版本:${prefs.getString(ENABLE_MODULE_VERSION)}\n" +
|
"已生效模块版本:${prefs.get(DataConst.ENABLE_MODULE_VERSION)}\n" +
|
||||||
"当前模式:${if (prefs.getBoolean(ENABLE_QQTIM_WHITE_MODE)) "保守模式" else "完全模式"}" +
|
"当前模式:${if (prefs.get(DataConst.ENABLE_QQTIM_WHITE_MODE)) "保守模式" else "完全模式"}" +
|
||||||
"\n\n包名:${packageName}\n版本:$versionName($versionCode)" +
|
"\n\n包名:${packageName}\n版本:$versionName($versionCode)" +
|
||||||
"\n\n模块只对挂后台锁屏情况下有省电效果," +
|
"\n\n模块只对挂后台锁屏情况下有省电效果," +
|
||||||
"请不要将过多的群提醒,消息通知打开,这样子在使用过程时照样会极其耗电。\n\n" +
|
"请不要将过多的群提醒,消息通知打开,这样子在使用过程时照样会极其耗电。\n\n" +
|
||||||
"如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n\n" +
|
"如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n\n" +
|
||||||
"持续常驻使用 QQ 依然会耗电,任何软件都是如此," +
|
"持续常驻使用 QQ、TIM 依然会耗电,任何软件都是如此," +
|
||||||
"模块无法帮你做到前台不耗电,永远记住这一点。\n\n" +
|
"模块是无法帮你做到前台不耗电的。\n\n" +
|
||||||
"开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。"
|
"开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。"
|
||||||
confirmButton(text = "我知道了")
|
confirmButton(text = "我知道了")
|
||||||
noCancelable()
|
noCancelable()
|
||||||
@@ -228,19 +236,19 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
param(BundleClass)
|
param(BundleClass)
|
||||||
}
|
}
|
||||||
afterHook {
|
afterHook {
|
||||||
if (prefs.getBoolean(ENABLE_RUN_INFO))
|
if (prefs.get(DataConst.ENABLE_RUN_INFO))
|
||||||
instance<Activity>().apply {
|
instance<Activity>().apply {
|
||||||
showDialog(isUseBlackTheme = true) {
|
showDialog(isUseBlackTheme = true) {
|
||||||
title = "TSBattery 已激活"
|
title = "TSBattery 已激活"
|
||||||
msg = "[提示模块运行信息功能已打开]\n\n" +
|
msg = "[提示模块运行信息功能已打开]\n\n" +
|
||||||
"模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" +
|
"模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" +
|
||||||
"已生效模块版本:${prefs.getString(ENABLE_MODULE_VERSION)}\n" +
|
"已生效模块版本:${prefs.get(DataConst.ENABLE_MODULE_VERSION)}\n" +
|
||||||
"当前模式:基础省电" +
|
"当前模式:基础省电" +
|
||||||
"\n\n包名:${packageName}\n版本:$versionName($versionCode)" +
|
"\n\n包名:${packageName}\n版本:$versionName($versionCode)" +
|
||||||
"\n\n当前只支持微信的基础省电,即系统电源锁,后续会继续适配微信相关的省电功能(在新建文件夹了)。\n\n" +
|
"\n\n当前只支持微信的基础省电,即系统电源锁,后续会继续适配微信相关的省电功能(在新建文件夹了)。\n\n" +
|
||||||
"如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n\n" +
|
"如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n\n" +
|
||||||
"持续常驻使用微信依然会耗电,任何软件都是如此," +
|
"持续常驻使用微信依然会耗电,任何软件都是如此," +
|
||||||
"模块无法帮你做到前台不耗电,永远记住这一点。\n\n" +
|
"模块是无法帮你做到前台不耗电的。\n\n" +
|
||||||
"开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。"
|
"开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。"
|
||||||
confirmButton(text = "我知道了")
|
confirmButton(text = "我知道了")
|
||||||
noCancelable()
|
noCancelable()
|
||||||
@@ -261,29 +269,29 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
injectMember {
|
injectMember {
|
||||||
method { name = "startTempService" }
|
method { name = "startTempService" }
|
||||||
intercept()
|
intercept()
|
||||||
}
|
}.ignoredNoSuchMemberFailure()
|
||||||
injectMember {
|
injectMember {
|
||||||
method {
|
method {
|
||||||
name = "startCoreService"
|
name = "startCoreService"
|
||||||
param(BooleanType)
|
param(BooleanType)
|
||||||
}
|
}
|
||||||
intercept()
|
intercept()
|
||||||
}
|
}.ignoredNoSuchMemberFailure()
|
||||||
injectMember {
|
injectMember {
|
||||||
method {
|
method {
|
||||||
name = "onStartCommand"
|
name = "onStartCommand"
|
||||||
param(IntentClass, IntType, IntType)
|
param(IntentClass, IntType, IntType)
|
||||||
}
|
}
|
||||||
replaceTo(any = 2)
|
replaceTo(any = 2)
|
||||||
}
|
}.ignoredNoSuchMemberFailure()
|
||||||
}
|
}
|
||||||
injectMember {
|
injectMember {
|
||||||
method { name = "onCreate" }
|
method { name = "onCreate" }
|
||||||
afterHook {
|
afterHook {
|
||||||
if (prefs.getBoolean(ENABLE_QQTIM_CORESERVICE_BAN))
|
if (prefs.get(DataConst.ENABLE_QQTIM_CORESERVICE_BAN))
|
||||||
instance<Service>().apply {
|
instance<Service>().apply {
|
||||||
stopForeground(true)
|
stopForeground(true)
|
||||||
stopService(Intent(applicationContext, javaClass))
|
stopSelf()
|
||||||
loggerD(msg = "Shutdown CoreService OK!")
|
loggerD(msg = "Shutdown CoreService OK!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,10 +301,10 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
injectMember {
|
injectMember {
|
||||||
method { name = "onCreate" }
|
method { name = "onCreate" }
|
||||||
afterHook {
|
afterHook {
|
||||||
if (prefs.getBoolean(ENABLE_QQTIM_CORESERVICE_CHILD_BAN))
|
if (prefs.get(DataConst.ENABLE_QQTIM_CORESERVICE_CHILD_BAN))
|
||||||
instance<Service>().apply {
|
instance<Service>().apply {
|
||||||
stopForeground(true)
|
stopForeground(true)
|
||||||
stopService(Intent(applicationContext, javaClass))
|
stopSelf()
|
||||||
loggerD(msg = "Shutdown CoreService\$KernelService OK!")
|
loggerD(msg = "Shutdown CoreService\$KernelService OK!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,10 +315,87 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
param(IntentClass, IntType, IntType)
|
param(IntentClass, IntType, IntType)
|
||||||
}
|
}
|
||||||
replaceTo(any = 2)
|
replaceTo(any = 2)
|
||||||
}
|
}.ignoredNoSuchMemberFailure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将激活状态插入到设置页面
|
||||||
|
* @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 实例 */
|
||||||
|
val formItemRefRoot = field {
|
||||||
|
type(FormSimpleItemClass).index(num = 1)
|
||||||
|
}.ignoredError().get(instance).cast() ?: field {
|
||||||
|
type(FormCommonSingleLineItemClass).index(num = 1)
|
||||||
|
}.ignoredError().get(instance).cast<View?>()
|
||||||
|
/** 创建一个新的 Item */
|
||||||
|
FormSimpleItemClass.clazz.buildOf<View>(instance) { param(ContextClass) }?.current {
|
||||||
|
method {
|
||||||
|
name = "setLeftText"
|
||||||
|
param(CharSequenceType)
|
||||||
|
}.call("TSBattery")
|
||||||
|
method {
|
||||||
|
name = "setRightText"
|
||||||
|
param(CharSequenceType)
|
||||||
|
}.call(prefs.get(DataConst.ENABLE_MODULE_VERSION))
|
||||||
|
method {
|
||||||
|
name = "setBgType"
|
||||||
|
param(IntType)
|
||||||
|
}.call(if (isQQ) 0 else 2)
|
||||||
|
}?.apply {
|
||||||
|
setOnClickListener {
|
||||||
|
instance<Activity>().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 = "关闭")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}?.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(MATCH_PARENT, WRAP_CONTENT)
|
||||||
|
/** 设置圆角和间距 */
|
||||||
|
if (isQQ) (lparam as? MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0)
|
||||||
|
/** 将 Item 添加到设置界面 */
|
||||||
|
listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onInit() = configs {
|
override fun onInit() = configs {
|
||||||
debugTag = "TSBattery"
|
debugTag = "TSBattery"
|
||||||
isDebug = false
|
isDebug = false
|
||||||
@@ -323,7 +408,8 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
hookNotification()
|
hookNotification()
|
||||||
hookCoreService(isQQ = true)
|
hookCoreService(isQQ = true)
|
||||||
hookModuleRunningInfo(isQQTIM = true)
|
hookModuleRunningInfo(isQQTIM = true)
|
||||||
if (prefs.getBoolean(ENABLE_QQTIM_WHITE_MODE)) return@loadApp
|
hookQQSettingsSettingActivity(isQQ = true)
|
||||||
|
if (prefs.get(DataConst.ENABLE_QQTIM_WHITE_MODE)) return@loadApp
|
||||||
/** 通过在 [SplashActivityClass] 里取到应用的版本号 */
|
/** 通过在 [SplashActivityClass] 里取到应用的版本号 */
|
||||||
SplashActivityClass.hook {
|
SplashActivityClass.hook {
|
||||||
injectMember {
|
injectMember {
|
||||||
@@ -334,43 +420,6 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
afterHook { hookQQBaseChatPie(instance<Activity>().versionName) }
|
afterHook { hookQQBaseChatPie(instance<Activity>().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()
|
|
||||||
/**
|
/**
|
||||||
* 干掉消息收发功能的电源锁
|
* 干掉消息收发功能的电源锁
|
||||||
* 每个版本的差异暂未做排查
|
* 每个版本的差异暂未做排查
|
||||||
@@ -427,7 +476,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
* 讯哥的程序员真的有你的
|
* 讯哥的程序员真的有你的
|
||||||
* 2022/1/25 后期查证:锁屏界面消息快速回复窗口
|
* 2022/1/25 后期查证:锁屏界面消息快速回复窗口
|
||||||
*/
|
*/
|
||||||
findClass(name = "$QQ_PACKAGE_NAME.activity.QQLSActivity\$14").hook {
|
findClass("$QQ_PACKAGE_NAME.activity.QQLSActivity\$14", "ktq").hook {
|
||||||
injectMember {
|
injectMember {
|
||||||
method { name = "run" }
|
method { name = "run" }
|
||||||
intercept()
|
intercept()
|
||||||
@@ -453,21 +502,21 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
injectMember {
|
injectMember {
|
||||||
method {
|
method {
|
||||||
name = "doReport"
|
name = "doReport"
|
||||||
param(("com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor\$WakeLockEntity").clazz, IntType)
|
param("com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor\$WakeLockEntity", IntType)
|
||||||
}
|
}
|
||||||
intercept()
|
intercept()
|
||||||
}
|
}
|
||||||
injectMember {
|
injectMember {
|
||||||
method {
|
method {
|
||||||
name = "afterHookedMethod"
|
name = "afterHookedMethod"
|
||||||
param(("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam").clazz)
|
param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
||||||
}
|
}
|
||||||
intercept()
|
intercept()
|
||||||
}
|
}
|
||||||
injectMember {
|
injectMember {
|
||||||
method {
|
method {
|
||||||
name = "beforeHookedMethod"
|
name = "beforeHookedMethod"
|
||||||
param(("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam").clazz)
|
param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
||||||
}
|
}
|
||||||
intercept()
|
intercept()
|
||||||
}
|
}
|
||||||
@@ -497,12 +546,81 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
intercept()
|
intercept()
|
||||||
}
|
}
|
||||||
|
}.ignoredHookClassNotFoundFailure()
|
||||||
|
/**
|
||||||
|
* 这个是毒瘤核心操作类
|
||||||
|
* 功能同上、全部拦截
|
||||||
|
* 👮🏻 经过排查 Play 版本也没这个类...... Emmmm 不想说啥了
|
||||||
|
*/
|
||||||
|
findClass(name = "com.tencent.qapmsdk.qqbattery.QQBatteryMonitor").hook {
|
||||||
|
injectMember {
|
||||||
|
method { name = "start" }
|
||||||
|
intercept()
|
||||||
|
}
|
||||||
|
injectMember {
|
||||||
|
method { name = "stop" }
|
||||||
|
intercept()
|
||||||
|
}
|
||||||
injectMember {
|
injectMember {
|
||||||
method {
|
method {
|
||||||
name = "handleMessage"
|
name = "handleMessage"
|
||||||
param(MessageClass)
|
param(MessageClass)
|
||||||
}
|
}
|
||||||
replaceToFalse()
|
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()
|
}.ignoredHookClassNotFoundFailure()
|
||||||
}
|
}
|
||||||
@@ -511,9 +629,10 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
hookNotification()
|
hookNotification()
|
||||||
hookCoreService(isQQ = false)
|
hookCoreService(isQQ = false)
|
||||||
hookModuleRunningInfo(isQQTIM = true)
|
hookModuleRunningInfo(isQQTIM = true)
|
||||||
|
hookQQSettingsSettingActivity(isQQ = false)
|
||||||
}
|
}
|
||||||
loadApp(WECHAT_PACKAGE_NAME) {
|
loadApp(WECHAT_PACKAGE_NAME) {
|
||||||
if (prefs.getBoolean(DISABLE_WECHAT_HOOK)) return@loadApp
|
if (prefs.get(DataConst.DISABLE_WECHAT_HOOK)) return@loadApp
|
||||||
hookSystemWakeLock()
|
hookSystemWakeLock()
|
||||||
hookModuleRunningInfo(isQQTIM = false)
|
hookModuleRunningInfo(isQQTIM = false)
|
||||||
loggerD(msg = "ウイチャット:それが機能するかどうかはわかりませんでした")
|
loggerD(msg = "ウイチャット:それが機能するかどうかはわかりませんでした")
|
||||||
|
@@ -29,15 +29,8 @@ import android.view.HapticFeedbackConstants
|
|||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.fankes.tsbattery.BuildConfig
|
import com.fankes.tsbattery.BuildConfig
|
||||||
import com.fankes.tsbattery.R
|
import com.fankes.tsbattery.R
|
||||||
|
import com.fankes.tsbattery.data.DataConst
|
||||||
import com.fankes.tsbattery.databinding.ActivityMainBinding
|
import com.fankes.tsbattery.databinding.ActivityMainBinding
|
||||||
import com.fankes.tsbattery.hook.HookConst.DISABLE_WECHAT_HOOK
|
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_HIDE_ICON
|
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_MODULE_VERSION
|
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_NOTIFY_TIP
|
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_QQTIM_CORESERVICE_BAN
|
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_QQTIM_CORESERVICE_CHILD_BAN
|
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_QQTIM_WHITE_MODE
|
|
||||||
import com.fankes.tsbattery.hook.HookConst.ENABLE_RUN_INFO
|
|
||||||
import com.fankes.tsbattery.hook.HookConst.QQ_PACKAGE_NAME
|
import com.fankes.tsbattery.hook.HookConst.QQ_PACKAGE_NAME
|
||||||
import com.fankes.tsbattery.hook.HookConst.TIM_PACKAGE_NAME
|
import com.fankes.tsbattery.hook.HookConst.TIM_PACKAGE_NAME
|
||||||
import com.fankes.tsbattery.hook.HookConst.WECHAT_PACKAGE_NAME
|
import com.fankes.tsbattery.hook.HookConst.WECHAT_PACKAGE_NAME
|
||||||
@@ -55,7 +48,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
|
|
||||||
private const val moduleVersion = BuildConfig.VERSION_NAME
|
private const val moduleVersion = BuildConfig.VERSION_NAME
|
||||||
private const val qqSupportVersion =
|
private const val qqSupportVersion =
|
||||||
"8.2.11(Play)、8.8.17、8.8.23、8.8.35、8.8.38、8.8.50、8.8.55、8.8.68、8.8.80、8.8.83 (8.2.11、8.5.5~8.8.83)"
|
"8.2.11(Play)、8.8.17、8.8.23、8.8.35、8.8.38、8.8.50、8.8.55、8.8.68、8.8.80、8.8.83、8.8.85 (8.2.11、8.5.5~8.8.85)"
|
||||||
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
|
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
|
||||||
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼"
|
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼"
|
||||||
|
|
||||||
@@ -80,7 +73,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
binding.mainTextApiWay.isVisible = true
|
binding.mainTextApiWay.isVisible = true
|
||||||
refreshActivateExecutor()
|
refreshActivateExecutor()
|
||||||
/** 写入激活的模块版本 */
|
/** 写入激活的模块版本 */
|
||||||
modulePrefs.putString(ENABLE_MODULE_VERSION, moduleVersion)
|
modulePrefs.put(DataConst.ENABLE_MODULE_VERSION, moduleVersion)
|
||||||
} else
|
} else
|
||||||
showDialog {
|
showDialog {
|
||||||
title = "模块没有激活"
|
title = "模块没有激活"
|
||||||
@@ -144,34 +137,35 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
it.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
it.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
|
||||||
}
|
}
|
||||||
/** 获取 Sp 存储的信息 */
|
/** 获取 Sp 存储的信息 */
|
||||||
binding.qqtimProtectModeSwitch.isChecked = modulePrefs.getBoolean(ENABLE_QQTIM_WHITE_MODE)
|
binding.qqtimProtectModeSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_QQTIM_WHITE_MODE)
|
||||||
binding.qqTimCoreServiceSwitch.isChecked = modulePrefs.getBoolean(ENABLE_QQTIM_CORESERVICE_BAN)
|
binding.qqTimCoreServiceSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_QQTIM_CORESERVICE_BAN)
|
||||||
binding.qqTimCoreServiceKnSwitch.isChecked = modulePrefs.getBoolean(ENABLE_QQTIM_CORESERVICE_CHILD_BAN)
|
binding.qqTimCoreServiceKnSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_QQTIM_CORESERVICE_CHILD_BAN)
|
||||||
binding.wechatDisableHookSwitch.isChecked = modulePrefs.getBoolean(DISABLE_WECHAT_HOOK)
|
binding.wechatDisableHookSwitch.isChecked = modulePrefs.get(DataConst.DISABLE_WECHAT_HOOK)
|
||||||
binding.hideIconInLauncherSwitch.isChecked = modulePrefs.getBoolean(ENABLE_HIDE_ICON)
|
binding.hideIconInLauncherSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_HIDE_ICON)
|
||||||
binding.notifyModuleInfoSwitch.isChecked = modulePrefs.getBoolean(ENABLE_RUN_INFO)
|
binding.notifyModuleInfoSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_RUN_INFO)
|
||||||
binding.notifyNotifyTipSwitch.isChecked = modulePrefs.getBoolean(ENABLE_NOTIFY_TIP, default = true)
|
binding.notifyNotifyTipSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_NOTIFY_TIP)
|
||||||
|
binding.settingModuleTipSwitch.isChecked = modulePrefs.get(DataConst.ENABLE_SETTING_TIP)
|
||||||
binding.qqtimProtectModeSwitch.setOnCheckedChangeListener { btn, b ->
|
binding.qqtimProtectModeSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_QQTIM_WHITE_MODE, b)
|
modulePrefs.put(DataConst.ENABLE_QQTIM_WHITE_MODE, b)
|
||||||
snake(msg = "修改需要重启 QQ 以生效")
|
snake(msg = "修改需要重启 QQ 以生效")
|
||||||
}
|
}
|
||||||
binding.qqTimCoreServiceSwitch.setOnCheckedChangeListener { btn, b ->
|
binding.qqTimCoreServiceSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_QQTIM_CORESERVICE_BAN, b)
|
modulePrefs.put(DataConst.ENABLE_QQTIM_CORESERVICE_BAN, b)
|
||||||
}
|
}
|
||||||
binding.qqTimCoreServiceKnSwitch.setOnCheckedChangeListener { btn, b ->
|
binding.qqTimCoreServiceKnSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_QQTIM_CORESERVICE_CHILD_BAN, b)
|
modulePrefs.put(DataConst.ENABLE_QQTIM_CORESERVICE_CHILD_BAN, b)
|
||||||
}
|
}
|
||||||
binding.wechatDisableHookSwitch.setOnCheckedChangeListener { btn, b ->
|
binding.wechatDisableHookSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(DISABLE_WECHAT_HOOK, b)
|
modulePrefs.put(DataConst.DISABLE_WECHAT_HOOK, b)
|
||||||
snake(msg = "修改需要重启微信以生效")
|
snake(msg = "修改需要重启微信以生效")
|
||||||
}
|
}
|
||||||
binding.hideIconInLauncherSwitch.setOnCheckedChangeListener { btn, b ->
|
binding.hideIconInLauncherSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_HIDE_ICON, b)
|
modulePrefs.put(DataConst.ENABLE_HIDE_ICON, b)
|
||||||
packageManager.setComponentEnabledSetting(
|
packageManager.setComponentEnabledSetting(
|
||||||
ComponentName(this@MainActivity, "com.fankes.tsbattery.Home"),
|
ComponentName(this@MainActivity, "com.fankes.tsbattery.Home"),
|
||||||
if (b) PackageManager.COMPONENT_ENABLED_STATE_DISABLED else PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
if (b) PackageManager.COMPONENT_ENABLED_STATE_DISABLED else PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
|
||||||
@@ -179,12 +173,16 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
binding.notifyModuleInfoSwitch.setOnCheckedChangeListener { btn, b ->
|
binding.notifyModuleInfoSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_RUN_INFO, b)
|
modulePrefs.put(DataConst.ENABLE_RUN_INFO, b)
|
||||||
}
|
}
|
||||||
binding.notifyNotifyTipSwitch.setOnCheckedChangeListener { btn, b ->
|
binding.notifyNotifyTipSwitch.setOnCheckedChangeListener { btn, b ->
|
||||||
if (!btn.isPressed) return@setOnCheckedChangeListener
|
if (btn.isPressed.not()) return@setOnCheckedChangeListener
|
||||||
modulePrefs.putBoolean(ENABLE_NOTIFY_TIP, b)
|
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 */
|
/** 快捷操作 QQ */
|
||||||
binding.quickQqButton.setOnClickListener { openSelfSetting(QQ_PACKAGE_NAME) }
|
binding.quickQqButton.setOnClickListener { openSelfSetting(QQ_PACKAGE_NAME) }
|
||||||
|
@@ -31,6 +31,7 @@ import android.util.AttributeSet
|
|||||||
import androidx.appcompat.widget.SwitchCompat
|
import androidx.appcompat.widget.SwitchCompat
|
||||||
import com.fankes.tsbattery.utils.drawable.drawabletoolbox.DrawableBuilder
|
import com.fankes.tsbattery.utils.drawable.drawabletoolbox.DrawableBuilder
|
||||||
import com.fankes.tsbattery.utils.factory.dp
|
import com.fankes.tsbattery.utils.factory.dp
|
||||||
|
import com.fankes.tsbattery.utils.factory.isSystemInDarkMode
|
||||||
|
|
||||||
class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(context, attrs) {
|
class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(context, attrs) {
|
||||||
|
|
||||||
@@ -43,6 +44,8 @@ class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(cont
|
|||||||
return ColorStateList(states, colors)
|
return ColorStateList(states, colors)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val thumbColor get() = if (context.isSystemInDarkMode) 0xFF7C7C7C else 0xFFCCCCCC
|
||||||
|
|
||||||
init {
|
init {
|
||||||
trackDrawable = DrawableBuilder()
|
trackDrawable = DrawableBuilder()
|
||||||
.rectangle()
|
.rectangle()
|
||||||
@@ -62,8 +65,8 @@ class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(cont
|
|||||||
.build()
|
.build()
|
||||||
trackTintList = toColors(
|
trackTintList = toColors(
|
||||||
0xFF656565.toInt(),
|
0xFF656565.toInt(),
|
||||||
0xFFCCCCCC.toInt(),
|
thumbColor.toInt(),
|
||||||
0xFFCCCCCC.toInt()
|
thumbColor.toInt()
|
||||||
)
|
)
|
||||||
isSingleLine = true
|
isSingleLine = true
|
||||||
ellipsize = TextUtils.TruncateAt.END
|
ellipsize = TextUtils.TruncateAt.END
|
||||||
|
@@ -37,7 +37,7 @@ import android.widget.TextView
|
|||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.highcapable.yukihookapi.annotation.DoNotUseField
|
import com.highcapable.yukihookapi.annotation.CauseProblemsApi
|
||||||
import com.highcapable.yukihookapi.hook.factory.method
|
import com.highcapable.yukihookapi.hook.factory.method
|
||||||
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
|
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
|
|||||||
|
|
||||||
private var dialogInstance: Dialog? = null // 对话框实例
|
private var dialogInstance: Dialog? = null // 对话框实例
|
||||||
|
|
||||||
@DoNotUseField
|
@CauseProblemsApi
|
||||||
var customLayoutView: View? = null // 自定义布局
|
var customLayoutView: View? = null // 自定义布局
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
*
|
*
|
||||||
* This file is Created by fankes on 2022/1/7.
|
* This file is Created by fankes on 2022/1/7.
|
||||||
*/
|
*/
|
||||||
@file:Suppress("DEPRECATION")
|
@file:Suppress("DEPRECATION", "unused")
|
||||||
|
|
||||||
package com.fankes.tsbattery.utils.factory
|
package com.fankes.tsbattery.utils.factory
|
||||||
|
|
||||||
@@ -42,8 +42,7 @@ import com.google.android.material.snackbar.Snackbar
|
|||||||
* 系统深色模式是否开启
|
* 系统深色模式是否开启
|
||||||
* @return [Boolean] 是否开启
|
* @return [Boolean] 是否开启
|
||||||
*/
|
*/
|
||||||
val isSystemInDarkMode
|
val isSystemInDarkMode get() = appContext.isSystemInDarkMode
|
||||||
get() = (appContext.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统深色模式是否没开启
|
* 系统深色模式是否没开启
|
||||||
@@ -51,6 +50,18 @@ val isSystemInDarkMode
|
|||||||
*/
|
*/
|
||||||
inline val isNotSystemInDarkMode get() = !isSystemInDarkMode
|
inline val isNotSystemInDarkMode get() = !isSystemInDarkMode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统深色模式是否开启
|
||||||
|
* @return [Boolean] 是否开启
|
||||||
|
*/
|
||||||
|
val Context.isSystemInDarkMode get() = (resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 系统深色模式是否没开启
|
||||||
|
* @return [Boolean] 是否开启
|
||||||
|
*/
|
||||||
|
inline val Context.isNotSystemInDarkMode get() = !isSystemInDarkMode
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 得到安装包信息
|
* 得到安装包信息
|
||||||
* @return [PackageInfo]
|
* @return [PackageInfo]
|
||||||
@@ -131,7 +142,7 @@ fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).sho
|
|||||||
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) =
|
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) =
|
||||||
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG).apply {
|
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG).apply {
|
||||||
if (actionText.isBlank()) return@apply
|
if (actionText.isBlank()) return@apply
|
||||||
setActionTextColor(Color.WHITE)
|
setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE)
|
||||||
setAction(actionText) { it() }
|
setAction(actionText) { it() }
|
||||||
}.show()
|
}.show()
|
||||||
|
|
||||||
@@ -146,7 +157,7 @@ fun Context.openSelfSetting(packageName: String = appContext.packageName) = runC
|
|||||||
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||||
data = Uri.fromParts("package", packageName, null)
|
data = Uri.fromParts("package", packageName, null)
|
||||||
})
|
})
|
||||||
else toast(msg = "你没有安装此应用")
|
else snake(msg = "你没有安装此应用")
|
||||||
}.onFailure { toast(msg = "启动 $packageName 应用信息失败") }
|
}.onFailure { toast(msg = "启动 $packageName 应用信息失败") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -543,6 +543,25 @@
|
|||||||
android:textColor="@color/colorTextDark"
|
android:textColor="@color/colorTextDark"
|
||||||
android:textSize="12sp" />
|
android:textSize="12sp" />
|
||||||
|
|
||||||
|
<com.fankes.tsbattery.ui.view.MaterialSwitch
|
||||||
|
android:id="@+id/setting_module_tip_switch"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="35dp"
|
||||||
|
android:layout_marginBottom="5dp"
|
||||||
|
android:text="设置页面显示守护状态"
|
||||||
|
android:textColor="@color/colorTextGray"
|
||||||
|
android:textSize="15sp" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="10dp"
|
||||||
|
android:alpha="0.6"
|
||||||
|
android:lineSpacingExtra="6dp"
|
||||||
|
android:text="此功能仅支持 QQ、TIM,开启后将会在宿主设置页面显示一个条目来展示激活状态,与大部分 QQ、TIM 模块显示方式一致,建议保持开启以快速确定模块是否正常生效。"
|
||||||
|
android:textColor="@color/colorTextDark"
|
||||||
|
android:textSize="12sp" />
|
||||||
|
|
||||||
<com.fankes.tsbattery.ui.view.MaterialSwitch
|
<com.fankes.tsbattery.ui.view.MaterialSwitch
|
||||||
android:id="@+id/notify_module_info_switch"
|
android:id="@+id/notify_module_info_switch"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
8
app/src/main/res/values/array.xml
Normal file
8
app/src/main/res/values/array.xml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string-array name="module_scope">
|
||||||
|
<item>com.tencent.mobileqq</item>
|
||||||
|
<item>com.tencent.tim</item>
|
||||||
|
<item>com.tencent.mm</item>
|
||||||
|
</string-array>
|
||||||
|
</resources>
|
@@ -5,8 +5,8 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
appVersionName = "3.5"
|
appVersionName = "3.7"
|
||||||
appVersionCode = 13
|
appVersionCode = 15
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
Reference in New Issue
Block a user