8 Commits
2.4 ... 2.5

12 changed files with 341 additions and 86 deletions

7
.idea/misc.xml generated
View File

@@ -1,5 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DesignSurface">
<option name="filePathToZoomLevelMap">
<map>
<entry key="app/src/main/res/layout/activity_main.xml" value="0.375" />
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>

47
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,47 @@
# 开始贡献
欢迎为此项目进行新版本的适配代码贡献!<br/>
## 分支规定
不管是直接 Push 代码还是提交 Pull Request都必须使 commit 指向 master 分支。
## 代码格式规范
- 1.全部提交代码必须使用 IDE(Android Studio 或 IDEA) 进行格式化,未经格式化的代码将拒绝合并提交请求
- 2.代码必须使用 4 spaces 缩进格式化
## 代码注释规范
- 1.第一种注释方式:可使用在方法名或顶级变量名上
```kotlin
/** 注释内容 */
fun a() {
}
/**
* 注释名称
* @param test 方法名称
* @return 返回值名称
*/
fun a(test: String) {
}
```
- 2.第二种注释方式:仅可使用在变量后方
```kotlin
val a = "" // 变量注释
```
- ⚠️注意:只允许两个 // 后方要有空格
## 项目要求
- 1.调试性质或大批量注释代码,禁止提交
- 2.类名和方法名仅能由开发者进行修改和提交,禁止随意修改项目名称、方法名称以及类名
- 3.禁止随意更新项目依赖以及增加新的依赖,有问题请提前提交到 issues 进行说明
- 4.禁止更新项目版本号,版本号交由开发者合并代码并发布 release 版本
- 5.代码语言要求,请统一使用 Kotlin除特殊情况外不接受其他语言的提交
- 6.以上

View File

@@ -1,44 +1,43 @@
# TSBattery
![Eclipse Marketplace](https://img.shields.io/badge/build-passing-brightgreen)
![Eclipse Marketplace](https://img.shields.io/badge/license-GPL3.0-blue)
![Eclipse Marketplace](https://img.shields.io/badge/version-v2.4-green)
![Eclipse Marketplace](https://img.shields.io/badge/version-v2.5-green)
<br/><br/>
TSBattery a new way to save your battery avoid cancer apps hacker it.<br/>
TSBattery 是一个旨在使 QQ、TIM 变得更省电的开源 Xposed 模块
# 开始使用
点击下载最新版本
<a href='https://github.com/fankes/TSBattery/releases'>![Eclipse Marketplace](https://img.shields.io/badge/download-v2.4-green)</a>
<br/><br/>
⚠️适配说明:此模块支持原生 Xposed、Lsposed(作用域 QQ、TIM 如果不起作用勾选系统框架)、EdXposed(不推荐)、太极无极(阴和阳)、Pine(梦境模块)
# 禁止任何商业用途
本模块完全开源免费,如果好用你可以打赏支持开发,严禁未经许可进行二改贩卖,违者必惩必究。
# 开始贡献
欢迎为此项目进行新版本的适配代码贡献!<br/>
## 代码规范:
### 1.全部提交代码必须使用 IDE(Android Studio 或 IDEA) 进行格式化,未经格式化的代码将拒绝合并提交请求
### 2.代码必须使用 4 spaces 缩进格式化
### 3.代码注释规范:
1.第一种注释方式:可使用在方法名或顶级变量名上
```kotlin
/** 注释内容 */
fun a() {
}
TSBattery 是一个旨在使 QQ、TIM、微信 变得更省电的开源 Xposed 模块
# 开始使用
点击下载最新版本
<a href='https://github.com/fankes/TSBattery/releases'>![Eclipse Marketplace](https://img.shields.io/badge/download-v2.5-green)</a>
<br/><br/>
⚠️适配说明:此模块支持原生 Xposed、Lsposed(作用域 QQ、TIM、微信 如果不起作用勾选系统框架)、EdXposed(不推荐)、太极无极(阴和阳)、Pine(梦境模块)
# 禁止任何商业用途
本模块完全开源免费,如果好用你可以打赏支持开发,严禁未经许可进行二改贩卖,违者必惩必究。
# 开始贡献
欢迎为此项目进行新版本的适配代码贡献!<br/>
- [CONTRIBUTING](https://github.com/fankes/TSBattery/blob/master/CONTRIBUTING.md)
# 许可证
- [GPL-3.0](https://www.gnu.org/licenses/gpl-3.0.html)
/**
* 注释名称
* @param test 方法名称
* @return 返回值名称
*/
fun a(test: String) {
}
```
2.第二种注释方式:仅可使用在变量后方
```kotlin
val a = "" // 变量注释
```
⚠️注意:只允许两个 // 后方要有空格
### 4.调试性质或大批量注释代码,禁止提交
### 5.类名和方法名仅能由开发者进行修改和提交,禁止随意修改项目名称、方法名称以及类名
### 6.禁止随意更新项目依赖以及增加新的依赖,有问题请提前提交到 issues 进行说明
### 7.禁止更新项目版本号,版本号交由开发者合并代码并发布 release 版本
### 8.代码语言要求,请统一使用 Kotlin除特殊情况外不接受其他语言的提交
Copyright (C) 2020-2021 Fankes Studio(qzmmcn@163.com)
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program 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 General Public License for more details.
```

View File

@@ -21,9 +21,9 @@ android {
applicationId "com.fankes.tsbattery"
minSdkVersion 22
//noinspection ExpiredTargetSdkVersion
targetSdkVersion 28
versionCode 7
versionName "2.4"
targetSdkVersion 26
versionCode 8
versionName "2.5"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

View File

@@ -21,7 +21,7 @@
<!-- 模块描述 -->
<meta-data
android:name="xposeddescription"
android:value="抵制毒瘤拒绝疯狂耗电Tencent 社交毒瘤一键省电模块(目前支持 QQ、TIM)通过干掉电源锁常驻减少电量消耗理论支持最新版本。by 酷安 @星夜不荟" />
android:value="抵制毒瘤拒绝疯狂耗电Tencent 社交毒瘤一键省电模块(目前支持 QQ、TIM、微信)通过干掉电源锁常驻减少电量消耗理论支持最新版本。by 酷安 @星夜不荟" />
<!-- 最低xposed版本号 -->
<meta-data
@@ -31,7 +31,8 @@
<activity
android:name="com.fankes.tsbattery.ui.MainActivity"
android:exported="true"
android:label="@string/app_name">
android:label="@string/app_name"
android:screenOrientation="behind">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
@@ -44,6 +45,7 @@
android:enabled="true"
android:exported="true"
android:label="@string/app_name"
android:screenOrientation="behind"
android:targetActivity="com.fankes.tsbattery.ui.MainActivity">
<intent-filter>

View File

@@ -86,7 +86,7 @@ class HookMain : IXposedHookLoadPackage {
}
/**
* 这个类 BaseChatPie 是控制聊天界面的
* 这个类 QQ 的 BaseChatPie 是控制聊天界面的
* 里面有两个随机混淆的方法 ⬇️
* remainScreenOn、cancelRemainScreenOn
* 这两个方法一个是挂起电源锁常驻亮屏
@@ -96,7 +96,7 @@ class HookMain : IXposedHookLoadPackage {
* ⚠️ Hook 错了方法会造成闪退!
* @param version QQ 版本
*/
private fun XC_LoadPackage.LoadPackageParam.hookBaseChatPie(version: String) {
private fun XC_LoadPackage.LoadPackageParam.hookQQBaseChatPie(version: String) {
when (version) {
"8.8.17" -> {
replaceToNull(BASE_CHAT_PIE, "bd")
@@ -106,7 +106,8 @@ class HookMain : IXposedHookLoadPackage {
replaceToNull(BASE_CHAT_PIE, "bf")
replaceToNull(BASE_CHAT_PIE, "bg")
}
"8.8.38" -> {
/** 8.8.35 贡献者StarWishsama */
"8.8.35", "8.8.38" -> {
replaceToNull(BASE_CHAT_PIE, "bi")
replaceToNull(BASE_CHAT_PIE, "bj")
}
@@ -124,7 +125,7 @@ class HookMain : IXposedHookLoadPackage {
* @param content
*/
private fun logD(content: String) {
XposedBridge.log(content)
XposedBridge.log("[TSBattery][D]>$content")
Log.d("TSBattery", content)
}
@@ -133,10 +134,32 @@ class HookMain : IXposedHookLoadPackage {
* @param content
*/
private fun logE(content: String, e: Throwable? = null) {
XposedBridge.log(content)
XposedBridge.log("[TSBattery][E]>$content")
XposedBridge.log(e)
Log.e("TSBattery", content, e)
}
/** Hook 系统电源锁 */
private fun XC_LoadPackage.LoadPackageParam.hookSystemWakeLock() {
runWithoutError("wakeLock acquire()") {
XposedHelpers.findAndHookMethod(
"android.os.PowerManager\$WakeLock",
classLoader,
"acquire",
replaceToNull
)
}
runWithoutError("hook wakeLock acquire(time)") {
XposedHelpers.findAndHookMethod(
"android.os.PowerManager\$WakeLock",
classLoader,
"acquire",
Long::class.java,
replaceToNull
)
}
}
override fun handleLoadPackage(lpparam: XC_LoadPackage.LoadPackageParam?) {
if (lpparam == null) return
when (lpparam.packageName) {
@@ -150,23 +173,7 @@ class HookMain : IXposedHookLoadPackage {
)
/** 经过测试 QQ 与 TIM 这两个是一个模子里面的东西,所以他们的类名也基本上是一样的 */
"com.tencent.mobileqq", "com.tencent.tim" -> {
runWithoutError("wakeLock acquire()") {
XposedHelpers.findAndHookMethod(
"android.os.PowerManager\$WakeLock",
lpparam.classLoader,
"acquire",
replaceToNull
)
}
runWithoutError("hook wakeLock acquire(time)") {
XposedHelpers.findAndHookMethod(
"android.os.PowerManager\$WakeLock",
lpparam.classLoader,
"acquire",
Long::class.java,
replaceToNull
)
}
lpparam.hookSystemWakeLock()
/** 增加通知栏文本显示守护状态 */
runWithoutError("Notification") {
XposedHelpers.findAndHookMethod(
@@ -252,7 +259,7 @@ class HookMain : IXposedHookLoadPackage {
/** 这个地方我们只处理 QQ */
runWithoutError("BaseChatPie") {
if (name == "com.tencent.mobileqq")
lpparam.hookBaseChatPie(version)
lpparam.hookQQBaseChatPie(version)
}
}
})
@@ -394,6 +401,57 @@ class HookMain : IXposedHookLoadPackage {
logD("hook Completed!")
}
}
/** 微信 */
"com.tencent.mm" -> {
lpparam.hookSystemWakeLock()
/** 判断是否开启提示模块运行信息 */
if (XPrefUtils.getBoolean(HookMedium.ENABLE_RUN_INFO))
runWithoutError("LauncherUI") {
/**
* Hook 启动界面的第一个 [Activity]
* 在里面加入提示运行信息的对话框测试模块是否激活
*/
XposedHelpers.findAndHookMethod(
"com.tencent.mm.ui.LauncherUI",
lpparam.classLoader,
"onCreate",
Bundle::class.java,
object : XC_MethodHook() {
override fun afterHookedMethod(param: MethodHookParam?) {
val self = param?.thisObject as? Activity ?: return
runWithoutError("模块已激活,但显示信息弹窗失败了") {
AlertDialog.Builder(
self,
android.R.style.Theme_Material_Light_Dialog
).setCancelable(false)
.setTitle("TSBattery 已激活")
.setMessage(
"[提示模块运行信息功能已打开]\n" +
"模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" +
"已生效模块版本:${XPrefUtils.getString(HookMedium.ENABLE_MODULE_VERSION)}\n" +
"当前模式:基础省电" +
"\n\n包名:${self.packageName}\n版本:${
self.packageManager.getPackageInfo(
self.packageName,
0
).versionName
}(${
self.packageManager.getPackageInfo(
self.packageName,
0
).versionCode
})" + "\n\nPS当前只支持微信的基础省电即系统电源锁后续会继续适配微信相关的省电功能(在新建文件夹了)"
)
.setPositiveButton("我知道了", null)
.show()
}
}
})
}
// TODO 新建文件夹
logD("それが機能するかどうかはわかりません")
}
}
}
}

View File

@@ -52,7 +52,9 @@ class MainActivity : AppCompatActivity() {
companion object {
private const val moduleVersion = BuildConfig.VERSION_NAME
private const val moduleSupport = "QQ 8.5.5~8.8.50、TIM 2+"
private const val qqSupportVersion = "8.8.17、8.8.23、8.8.35、8.8.38、8.8.50 (8.5.5~8.8.50)"
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能敬请期待"
/** 声明当前实例 */
var instance: MainActivity? = null
@@ -86,7 +88,8 @@ class MainActivity : AppCompatActivity() {
.setTitle("模块没有激活")
.setMessage(
"检测到模块没有激活,模块需要 Xposed 环境依赖,同时需要系统拥有 Root 权限(太极阴可以免 Root),请自行查看本页面使用帮助与说明第三条。\n" +
"太极、应用转生、梦境(Pine)和第三方 Xposed 激活后可能不会提示激活,若想验证是否激活请打开“提示模块运行信息”自行检查,如果生效就代表模块运行正常,这里的激活状态只是一个显示意义上的存在。\n" +
"太极、应用转生、梦境(Pine)和第三方 Xposed 激活后可能不会提示激活,若想验证是否激活请打开“提示模块运行信息”自行检查," +
"如果生效就代表模块运行正常,这里的激活状态只是一个显示意义上的存在。\n" +
"太极(无极)在 MIUI 设备上会提示打开授权,请进行允许,然后再次打开本应用查看激活状态。"
)
.setPositiveButton("我知道了", null)
@@ -94,7 +97,36 @@ class MainActivity : AppCompatActivity() {
.show()
/** 设置文本 */
findViewById<TextView>(R.id.main_text_version).text = "当前版本:$moduleVersion"
findViewById<TextView>(R.id.main_text_support).text = "支持 $moduleSupport"
findViewById<TextView>(R.id.main_text_support_qq).apply {
text = qqSupportVersion
setOnClickListener {
AlertDialog.Builder(this@MainActivity)
.setTitle("兼容的 QQ 版本")
.setMessage(qqSupportVersion)
.setPositiveButton("我知道了", null)
.show()
}
}
findViewById<TextView>(R.id.main_text_support_tim).apply {
text = timSupportVersion
setOnClickListener {
AlertDialog.Builder(this@MainActivity)
.setTitle("兼容的 TIM 版本")
.setMessage(timSupportVersion)
.setPositiveButton("我知道了", null)
.show()
}
}
findViewById<TextView>(R.id.main_text_support_wechat).apply {
text = wechatSupportVersion
setOnClickListener {
AlertDialog.Builder(this@MainActivity)
.setTitle("兼容的微信版本")
.setMessage(wechatSupportVersion)
.setPositiveButton("我知道了", null)
.show()
}
}
/** 初始化 View */
val protectModeSwitch = findViewById<SwitchCompat>(R.id.protect_mode_switch)
val hideIconInLauncherSwitch = findViewById<SwitchCompat>(R.id.hide_icon_in_launcher_switch)
@@ -220,6 +252,11 @@ class MainActivity : AppCompatActivity() {
}
}
override fun onBackPressed() {
setWorldReadable()
super.onBackPressed()
}
override fun onDestroy() {
super.onDestroy()
/** 销毁实例防止内存泄漏 */

View File

@@ -5,7 +5,7 @@
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".ui.MainActivity"
tools:ignore="HardcodedText">
tools:ignore="HardcodedText,UseCompoundDrawables,ContentDescription">
<LinearLayout
android:layout_width="match_parent"
@@ -28,7 +28,10 @@
android:id="@+id/main_lin_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:layout_marginRight="15dp"
android:layout_marginBottom="5dp"
android:background="@drawable/dark_round"
android:elevation="3dp"
android:gravity="center">
@@ -61,27 +64,120 @@
android:id="@+id/main_text_version"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:layout_marginBottom="10dp"
android:alpha="0.8"
android:text="当前版本:%1"
android:textColor="@color/white"
android:textSize="13sp" />
<TextView
android:id="@+id/main_text_support"
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="3dp"
android:alpha="0.8"
android:text="支持 %1"
android:textColor="@color/white"
android:textSize="12sp" />
android:layout_marginBottom="7dp"
android:gravity="center|start"
android:orientation="horizontal">
<ImageView
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginEnd="5dp"
android:src="@mipmap/qq_icon" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:alpha="0.8"
android:text="兼容"
android:textColor="@color/white"
android:textSize="11sp" />
<TextView
android:id="@+id/main_text_support_qq"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.8"
android:ellipsize="end"
android:singleLine="true"
android:text="%1"
android:textColor="@color/white"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="7dp"
android:gravity="center|start"
android:orientation="horizontal">
<ImageView
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginEnd="5dp"
android:src="@mipmap/tim_icon" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:alpha="0.8"
android:text="兼容"
android:textColor="@color/white"
android:textSize="11sp" />
<TextView
android:id="@+id/main_text_support_tim"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.8"
android:ellipsize="end"
android:singleLine="true"
android:text="%1"
android:textColor="@color/white"
android:textSize="11sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:gravity="center|start"
android:orientation="horizontal">
<ImageView
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginEnd="5dp"
android:src="@mipmap/wechat_icon" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="5dp"
android:alpha="0.8"
android:text="兼容"
android:textColor="@color/white"
android:textSize="11sp" />
<TextView
android:id="@+id/main_text_support_wechat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.8"
android:ellipsize="end"
android:singleLine="true"
android:text="%1"
android:textColor="@color/white"
android:textSize="11sp" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:alpha="0.6"
android:text="理论在小更新内还会生效,如果失效请看下方的联系方式"
android:lineSpacingExtra="5dp"
android:text="上述列出的版本号为最佳兼容版本,你可以点击进行查看。\n这些版本在适配范围内的应用都将有效但可能不能达到最佳使用效果。\n如果当前版本失效请看下方的联系方式。"
android:textColor="@color/white"
android:textSize="10sp"
tools:ignore="SmallSp" />
@@ -129,7 +225,7 @@
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="此选项默认关闭,默认情况下模块将会干掉 QQ 和 TIM 自身的电源锁控制类,开启后模块将只对系统电源锁生效,如果你的 QQ 或 TIM 视频通话等设置发生了故障,可以尝试开启这个功能,开启后请重启 QQ 或 TIM。"
android:text="此选项默认关闭,默认情况下模块将会干掉 QQ 和 TIM 自身的电源锁控制类,开启后模块将只对系统电源锁生效,如果你的 QQ 或 TIM 视频通话等设置发生了故障,可以尝试开启这个功能,开启后请重启 QQ 或 TIM,暂不支持微信。"
android:textColor="#777777"
android:textSize="12sp" />
</LinearLayout>
@@ -161,7 +257,7 @@
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="模块工作正常情况下不要开启,如果你想测试模块是否正常激活,可以打开此提示,开启后将会在启动 QQTIM 的时候提示运行信息。"
android:text="模块工作正常情况下不要开启,如果你想测试模块是否正常激活,可以打开此提示,开启后将会在启动 QQTIM 或微信的时候提示运行信息。"
android:textColor="#777777"
android:textSize="12sp" />
</LinearLayout>
@@ -276,6 +372,16 @@
android:textColor="#777777"
android:textSize="12sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:alpha="0.8"
android:lineSpacingExtra="6dp"
android:text="Q.关于目前微信的适配情况?\nA.微信适配尚在实验阶段,敬请期待。"
android:textColor="#777777"
android:textSize="12sp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -366,8 +472,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:src="@mipmap/qr_pay"
tools:ignore="ContentDescription" />
android:src="@mipmap/qr_pay" />
<TextView
android:layout_width="match_parent"

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
ext.kotlin_version = "1.6.0"
ext.kotlin_version = "1.6.10"
repositories {
google()
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
@@ -9,7 +9,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:7.0.3"
classpath "com.android.tools.build:gradle:7.0.4"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong