mirror of
https://github.com/fankes/TSBattery.git
synced 2025-09-04 17:55:30 +08:00
Compare commits
42 Commits
Author | SHA1 | Date | |
---|---|---|---|
c4de8ae448
|
|||
9e092742da
|
|||
fb27c107f4
|
|||
2be9a3d934
|
|||
d7dbecb65c
|
|||
6c2b3f12b3
|
|||
f1c520586a
|
|||
e9c99343c3
|
|||
20de713ffd
|
|||
3b78e8a515
|
|||
cf898092bd
|
|||
251a5151df
|
|||
59e93bc040
|
|||
d440e85be4
|
|||
e1dc99de01
|
|||
4eab1f7046
|
|||
3fc294dd8d
|
|||
a2c06cc201 | |||
6f39d5fdab | |||
5ada7585e3 | |||
31b8f157e5 | |||
e71f137f74 | |||
9e9bbcc8ca | |||
8043457a6e | |||
d4a1536d70 | |||
5c784f65f8 | |||
1c6c6e6480 | |||
4712d0063b | |||
583c72470b | |||
8cf945b670 | |||
6fba93e1fa | |||
288563ef68 | |||
d1e4c17817 | |||
c8ec50cb29 | |||
b6e042b9d0 | |||
3c4789d9a0 | |||
46ff5f4bcf | |||
09eeeeab5f | |||
f285e6f96d | |||
fb90d4051b | |||
911eb042a6 | |||
9d48732140 |
25
README.md
25
README.md
@@ -2,40 +2,46 @@
|
|||||||
|
|
||||||
[](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)
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
<br/>
|
<br/>
|
||||||
A new way to save your battery avoid cancer apps hacker it.<br/>
|
A new way to save your battery avoid cancer apps hacker it.
|
||||||
|
|
||||||
TSBattery 是一个旨在使 QQ、TIM、微信 变得更省电的开源 Xposed 模块。
|
TSBattery 是一个旨在使 QQ、TIM、微信 变得更省电的开源 Xposed 模块。
|
||||||
|
|
||||||
# Developer
|
## Developer
|
||||||
|
|
||||||
[酷安 @星夜不荟](http://www.coolapk.com/u/876977)
|
[酷安 @星夜不荟](http://www.coolapk.com/u/876977)
|
||||||
|
|
||||||
# 适配说明
|
## 适配说明
|
||||||
|
|
||||||
- 支持并建议使用 <b>LSPosed</b>(若作用域没有自动出现推荐请勾选 QQ、TIM、微信)
|
- 支持并建议使用 <b>LSPosed</b>(若作用域没有自动出现推荐请勾选 QQ、TIM、微信)
|
||||||
|
|
||||||
- 可以使用 <b>~~EdXposed~~</b>,但随时停止支持
|
- 可以使用 <b>~~EdXposed~~</b>,但随时停止支持
|
||||||
|
|
||||||
- <b>太极无极 · 阴</b> 支持性不是很好,建议使用 <b>太极无极 · 阳</b>
|
- <b>太极无极 · 阴</b> 支持性不是很好,建议使用 <b>太极无极 · 阳</b>
|
||||||
|
|
||||||
- 支持 <b>Pine</b>(梦境模块) 但是部分功能有限制
|
- 支持 <b>Pine</b>(梦境模块) 但是部分功能有限制
|
||||||
|
|
||||||
- 请不要使用 <b>~~应用转生~~</b>,发生封号情况后果自负
|
- 请不要使用 <b>~~应用转生~~</b>,发生封号情况后果自负
|
||||||
|
|
||||||
# 请勿用于非法用途
|
## 请勿用于非法用途
|
||||||
|
|
||||||
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
|
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
|
||||||
|
|
||||||
- 本模块发布地址仅有 [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)、
|
- 本模块发布地址仅有 [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)、
|
||||||
[Release](https://github.com/fankes/TSBattery/releases) 及 [蓝奏云](https://fankes.lanzouy.com/b02zfz3sj),从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
|
[Release](https://github.com/fankes/TSBattery/releases) 及 [蓝奏云](https://fankes.lanzouy.com/b02zfz3sj),从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
|
||||||
|
|
||||||
# 开始贡献
|
## 开始贡献
|
||||||
|
|
||||||
欢迎为此项目进行新版本的适配代码贡献!<br/>
|
欢迎为此项目进行新版本的适配代码贡献!<br/>
|
||||||
|
|
||||||
- [CONTRIBUTING](https://github.com/fankes/TSBattery/blob/master/CONTRIBUTING.md)
|
- [CONTRIBUTING](https://github.com/fankes/TSBattery/blob/master/CONTRIBUTING.md)
|
||||||
|
|
||||||
# 许可证
|
## 许可证
|
||||||
|
|
||||||
- [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)
|
- [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)
|
||||||
|
|
||||||
@@ -56,5 +62,6 @@ You should have received a copy of the GNU Affero General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
```
|
```
|
||||||
|
|
||||||
Powered by [YukiHookAPI](https://github.com/fankes/YukiHookAPI)<br/><br/>
|
Powered by [YukiHookAPI](https://github.com/fankes/YukiHookAPI)
|
||||||
|
|
||||||
版权所有 © 2019-2022 Fankes Studio(qzmmcn@163.com)
|
版权所有 © 2019-2022 Fankes Studio(qzmmcn@163.com)
|
@@ -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.4'
|
id 'com.google.devtools.ksp' version '1.6.21-1.0.5'
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
@@ -25,20 +25,14 @@ android {
|
|||||||
versionCode rootProject.ext.appVersionCode
|
versionCode rootProject.ext.appVersionCode
|
||||||
versionName rootProject.ext.appVersionName
|
versionName rootProject.ext.appVersionName
|
||||||
|
|
||||||
kotlinOptions {
|
|
||||||
freeCompilerArgs = [
|
|
||||||
'-Xno-param-assertions',
|
|
||||||
'-Xno-call-assertions',
|
|
||||||
'-Xno-receiver-assertions'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
minifyEnabled true
|
minifyEnabled rootProject.ext.enableR8
|
||||||
|
shrinkResources rootProject.ext.enableR8
|
||||||
|
zipAlignEnabled rootProject.ext.enableR8
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
@@ -49,38 +43,29 @@ android {
|
|||||||
}
|
}
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '11'
|
jvmTarget = '11'
|
||||||
|
freeCompilerArgs = [
|
||||||
|
'-Xno-param-assertions',
|
||||||
|
'-Xno-call-assertions',
|
||||||
|
'-Xno-receiver-assertions'
|
||||||
|
]
|
||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding true
|
viewBinding true
|
||||||
}
|
}
|
||||||
|
lintOptions {
|
||||||
|
checkReleaseBuilds false
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 移除无效耗时 lint Task */
|
|
||||||
tasks.whenTaskAdded {
|
|
||||||
task -> if (task.name == "lintVitalRelease") task.enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 移除无效耗时 lint Task */
|
|
||||||
tasks.whenTaskAdded {
|
|
||||||
task -> if (task.name == "lintVitalAnalyzeRelease") task.enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 移除无效耗时 lint Task */
|
|
||||||
tasks.whenTaskAdded {
|
|
||||||
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compileOnly 'de.robv.android.xposed:api:82'
|
compileOnly 'de.robv.android.xposed:api:82'
|
||||||
implementation 'com.highcapable.yukihookapi:api:1.0.69'
|
implementation 'com.highcapable.yukihookapi:api:1.0.92'
|
||||||
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.69'
|
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.92'
|
||||||
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
|
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.core:core-ktx:1.7.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
implementation 'com.google.android.material:material:1.5.0'
|
implementation 'com.google.android.material:material:1.6.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||||
|
8
app/proguard-rules.pro
vendored
8
app/proguard-rules.pro
vendored
@@ -20,7 +20,6 @@
|
|||||||
# hide the original source file name.
|
# hide the original source file name.
|
||||||
#-renamesourcefileattribute SourceFile
|
#-renamesourcefileattribute SourceFile
|
||||||
|
|
||||||
-dontwarn
|
|
||||||
-ignorewarnings
|
-ignorewarnings
|
||||||
-optimizationpasses 10
|
-optimizationpasses 10
|
||||||
-dontusemixedcaseclassnames
|
-dontusemixedcaseclassnames
|
||||||
@@ -35,13 +34,6 @@
|
|||||||
-renamesourcefileattribute P
|
-renamesourcefileattribute P
|
||||||
-keepattributes SourceFile,LineNumberTable
|
-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
-keep public class * extends android.app.Activity
|
|
||||||
-keep public class * extends android.app.Application
|
|
||||||
-keep public class * extends android.app.Service
|
|
||||||
-keep public class * extends android.content.ContentProvider
|
|
||||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
|
||||||
-keep public class * extends android.preference.Preference
|
|
||||||
|
|
||||||
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
|
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
|
||||||
public static *** throwUninitializedProperty(...);
|
public static *** throwUninitializedProperty(...);
|
||||||
public static *** throwUninitializedPropertyAccessException(...);
|
public static *** throwUninitializedPropertyAccessException(...);
|
||||||
|
@@ -19,31 +19,15 @@
|
|||||||
*
|
*
|
||||||
* This file is Created by fankes on 2021/11/9.
|
* This file is Created by fankes on 2021/11/9.
|
||||||
*/
|
*/
|
||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package com.fankes.tsbattery.application
|
package com.fankes.tsbattery.application
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication
|
||||||
|
|
||||||
class TSApplication : Application() {
|
class TSApplication : ModuleApplication() {
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
/** 全局静态实例 */
|
|
||||||
private var context: TSApplication? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 调用全局静态实例
|
|
||||||
* @return [TSApplication]
|
|
||||||
*/
|
|
||||||
val appContext get() = context ?: error("App is death")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
/** 设置静态实例 */
|
|
||||||
context = this
|
|
||||||
/** 跟随系统夜间模式 */
|
/** 跟随系统夜间模式 */
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM)
|
||||||
}
|
}
|
||||||
|
@@ -32,6 +32,7 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||||
|
import android.view.ViewGroup.MarginLayoutParams
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import com.fankes.tsbattery.BuildConfig
|
import com.fankes.tsbattery.BuildConfig
|
||||||
import com.fankes.tsbattery.data.DataConst
|
import com.fankes.tsbattery.data.DataConst
|
||||||
@@ -39,6 +40,7 @@ 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.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
|
||||||
@@ -50,10 +52,10 @@ import com.highcapable.yukihookapi.hook.log.loggerE
|
|||||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||||
import com.highcapable.yukihookapi.hook.type.android.*
|
import com.highcapable.yukihookapi.hook.type.android.*
|
||||||
import com.highcapable.yukihookapi.hook.type.java.*
|
import com.highcapable.yukihookapi.hook.type.java.*
|
||||||
import com.highcapable.yukihookapi.hook.xposed.proxy.YukiHookXposedInitProxy
|
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
|
||||||
|
|
||||||
@InjectYukiHookWithXposed
|
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
|
||||||
class HookEntry : YukiHookXposedInitProxy {
|
class HookEntry : IYukiHookXposedInit {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@@ -128,10 +130,14 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
interceptBaseChatPie(methodName = "bk")
|
interceptBaseChatPie(methodName = "bk")
|
||||||
interceptBaseChatPie(methodName = "bl")
|
interceptBaseChatPie(methodName = "bl")
|
||||||
}
|
}
|
||||||
"8.8.83", "8.8.85" -> {
|
"8.8.83", "8.8.85", "8.8.88", "8.8.90" -> {
|
||||||
interceptBaseChatPie(methodName = "bl")
|
interceptBaseChatPie(methodName = "bl")
|
||||||
interceptBaseChatPie(methodName = "bm")
|
interceptBaseChatPie(methodName = "bm")
|
||||||
}
|
}
|
||||||
|
"8.8.93" -> {
|
||||||
|
interceptBaseChatPie(methodName = "J3")
|
||||||
|
interceptBaseChatPie(methodName = "S")
|
||||||
|
}
|
||||||
else -> loggerD(msg = "$version not supported!")
|
else -> loggerD(msg = "$version not supported!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,11 +179,11 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
beforeHook {
|
beforeHook {
|
||||||
if (prefs.get(DataConst.ENABLE_NOTIFY_TIP))
|
if (prefs.get(DataConst.ENABLE_NOTIFY_TIP))
|
||||||
when (firstArgs<CharSequence>()) {
|
when (args().first().cast<CharSequence>()) {
|
||||||
"QQ正在后台运行" ->
|
"QQ正在后台运行" ->
|
||||||
args().set("QQ正在后台运行 - TSBattery 守护中")
|
args().first().set("QQ正在后台运行 - TSBattery 守护中")
|
||||||
"TIM正在后台运行" ->
|
"TIM正在后台运行" ->
|
||||||
args().set("TIM正在后台运行 - TSBattery 守护中")
|
args().first().set("TIM正在后台运行 - TSBattery 守护中")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,21 +273,21 @@ 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" }
|
||||||
@@ -313,7 +319,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
param(IntentClass, IntType, IntType)
|
param(IntentClass, IntType, IntType)
|
||||||
}
|
}
|
||||||
replaceTo(any = 2)
|
replaceTo(any = 2)
|
||||||
}
|
}.ignoredNoSuchMemberFailure()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,48 +336,28 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
afterHook {
|
afterHook {
|
||||||
/** 是否启用 Hook */
|
/** 是否启用 Hook */
|
||||||
if (prefs.get(DataConst.ENABLE_SETTING_TIP).not()) return@afterHook
|
if (prefs.get(DataConst.ENABLE_SETTING_TIP).not()) return@afterHook
|
||||||
|
|
||||||
/** 当前的顶级 Item 实例 */
|
/** 当前的顶级 Item 实例 */
|
||||||
var formItemRefRoot: View? = null
|
val formItemRefRoot = field {
|
||||||
|
type(FormSimpleItemClass).index(num = 1)
|
||||||
/**
|
|
||||||
* 使用循环筛选
|
|
||||||
* @param target 目标变量名称
|
|
||||||
* @return [View] or null
|
|
||||||
*/
|
|
||||||
fun match(target: String) = runCatching {
|
|
||||||
field {
|
|
||||||
name = target
|
|
||||||
type = FormSimpleItemClass.clazz
|
|
||||||
}.ignoredError().get(instance).cast() ?: field {
|
}.ignoredError().get(instance).cast() ?: field {
|
||||||
name = target
|
type(FormCommonSingleLineItemClass).index(num = 1)
|
||||||
type = FormCommonSingleLineItemClass.clazz
|
|
||||||
}.ignoredError().get(instance).cast<View?>()
|
}.ignoredError().get(instance).cast<View?>()
|
||||||
}.getOrNull()
|
|
||||||
/** 循环出当前设置界面存在的顶级 Item */
|
|
||||||
arrayOf(
|
|
||||||
"a", "b", "c", "d", "e", "f", "g",
|
|
||||||
"h", "i", "j", "k", "l", "m", "n",
|
|
||||||
"o", "p", "q", "r", "s", "t", "u",
|
|
||||||
"v", "w", "x", "y", "z", "A", "B"
|
|
||||||
).forEach { match(it)?.also { e -> formItemRefRoot = e } }
|
|
||||||
/** 创建一个新的 Item */
|
/** 创建一个新的 Item */
|
||||||
FormSimpleItemClass.clazz.constructor { param(ContextClass) }.get().newInstance<View>(instance)?.also {
|
FormSimpleItemClass.clazz.buildOf<View>(instance) { param(ContextClass) }?.current {
|
||||||
it.javaClass.apply {
|
|
||||||
method {
|
method {
|
||||||
name = "setLeftText"
|
name = "setLeftText"
|
||||||
param(CharSequenceType)
|
param(CharSequenceType)
|
||||||
}.get(it).call("TSBattery")
|
}.call("TSBattery")
|
||||||
method {
|
method {
|
||||||
name = "setRightText"
|
name = "setRightText"
|
||||||
param(CharSequenceType)
|
param(CharSequenceType)
|
||||||
}.get(it).call(prefs.get(DataConst.ENABLE_MODULE_VERSION))
|
}.call(prefs.get(DataConst.ENABLE_MODULE_VERSION))
|
||||||
method {
|
method {
|
||||||
name = "setBgType"
|
name = "setBgType"
|
||||||
param(IntType)
|
param(IntType)
|
||||||
}.get(it).call(2)
|
}.call(if (isQQ) 0 else 2)
|
||||||
}
|
}?.apply {
|
||||||
it.setOnClickListener {
|
setOnClickListener {
|
||||||
instance<Activity>().apply {
|
instance<Activity>().apply {
|
||||||
showDialog {
|
showDialog {
|
||||||
title = "TSBattery 守护中"
|
title = "TSBattery 守护中"
|
||||||
@@ -398,14 +384,16 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.apply {
|
}?.also { item ->
|
||||||
var listGroup = formItemRefRoot?.parent as? ViewGroup?
|
var listGroup = formItemRefRoot?.parent as? ViewGroup?
|
||||||
val lparam = (if (listGroup?.childCount == 1) {
|
val lparam = (if (listGroup?.childCount == 1) {
|
||||||
listGroup = listGroup.parent as? ViewGroup
|
listGroup = listGroup.parent as? ViewGroup
|
||||||
(formItemRefRoot?.parent as? View?)?.layoutParams
|
(formItemRefRoot?.parent as? View?)?.layoutParams
|
||||||
} else formItemRefRoot?.layoutParams) ?: ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
} else formItemRefRoot?.layoutParams) ?: ViewGroup.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
|
||||||
|
/** 设置圆角和间距 */
|
||||||
|
if (isQQ) (lparam as? MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0)
|
||||||
/** 将 Item 添加到设置界面 */
|
/** 将 Item 添加到设置界面 */
|
||||||
listGroup?.also { if (isQQ) it.addView(this, lparam) else it.addView(this, 0, lparam) }
|
listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -416,6 +404,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
debugTag = "TSBattery"
|
debugTag = "TSBattery"
|
||||||
isDebug = false
|
isDebug = false
|
||||||
isEnableModulePrefsCache = false
|
isEnableModulePrefsCache = false
|
||||||
|
isEnableDataChannel = false
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onHook() = encase {
|
override fun onHook() = encase {
|
||||||
@@ -518,21 +507,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()
|
||||||
}
|
}
|
||||||
@@ -566,6 +555,7 @@ class HookEntry : YukiHookXposedInitProxy {
|
|||||||
/**
|
/**
|
||||||
* 这个是毒瘤核心操作类
|
* 这个是毒瘤核心操作类
|
||||||
* 功能同上、全部拦截
|
* 功能同上、全部拦截
|
||||||
|
* 👮🏻 经过排查 Play 版本也没这个类...... Emmmm 不想说啥了
|
||||||
*/
|
*/
|
||||||
findClass(name = "com.tencent.qapmsdk.qqbattery.QQBatteryMonitor").hook {
|
findClass(name = "com.tencent.qapmsdk.qqbattery.QQBatteryMonitor").hook {
|
||||||
injectMember {
|
injectMember {
|
||||||
|
@@ -37,10 +37,9 @@ import com.fankes.tsbattery.hook.HookConst.WECHAT_PACKAGE_NAME
|
|||||||
import com.fankes.tsbattery.ui.activity.base.BaseActivity
|
import com.fankes.tsbattery.ui.activity.base.BaseActivity
|
||||||
import com.fankes.tsbattery.utils.factory.*
|
import com.fankes.tsbattery.utils.factory.*
|
||||||
import com.fankes.tsbattery.utils.tool.GithubReleaseTool
|
import com.fankes.tsbattery.utils.tool.GithubReleaseTool
|
||||||
import com.highcapable.yukihookapi.hook.factory.isModuleActive
|
import com.fankes.tsbattery.utils.tool.YukiPromoteTool
|
||||||
import com.highcapable.yukihookapi.hook.factory.isTaiChiModuleActive
|
import com.highcapable.yukihookapi.YukiHookAPI
|
||||||
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
||||||
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
|
|
||||||
|
|
||||||
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
class MainActivity : BaseActivity<ActivityMainBinding>() {
|
||||||
|
|
||||||
@@ -48,7 +47,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.8.85 (8.2.11、8.5.5~8.8.85)"
|
"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.8.88、8.8.90、8.8.93 (8.2.11、8.5.5~8.8.93)"
|
||||||
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
|
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
|
||||||
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼"
|
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼"
|
||||||
|
|
||||||
@@ -66,7 +65,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 判断 Hook 状态 */
|
/** 判断 Hook 状态 */
|
||||||
if (isModuleActive) {
|
if (YukiHookAPI.Status.isModuleActive) {
|
||||||
binding.mainLinStatus.setBackgroundResource(R.drawable.bg_green_round)
|
binding.mainLinStatus.setBackgroundResource(R.drawable.bg_green_round)
|
||||||
binding.mainImgStatus.setImageResource(R.mipmap.ic_success)
|
binding.mainImgStatus.setImageResource(R.mipmap.ic_success)
|
||||||
binding.mainTextStatus.text = "模块已激活"
|
binding.mainTextStatus.text = "模块已激活"
|
||||||
@@ -74,6 +73,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
refreshActivateExecutor()
|
refreshActivateExecutor()
|
||||||
/** 写入激活的模块版本 */
|
/** 写入激活的模块版本 */
|
||||||
modulePrefs.put(DataConst.ENABLE_MODULE_VERSION, moduleVersion)
|
modulePrefs.put(DataConst.ENABLE_MODULE_VERSION, moduleVersion)
|
||||||
|
/** 推广、恰饭 */
|
||||||
|
YukiPromoteTool.promote(context = this)
|
||||||
} else
|
} else
|
||||||
showDialog {
|
showDialog {
|
||||||
title = "模块没有激活"
|
title = "模块没有激活"
|
||||||
@@ -89,7 +90,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
noCancelable()
|
noCancelable()
|
||||||
}
|
}
|
||||||
/** 推荐使用 LSPosed */
|
/** 推荐使用 LSPosed */
|
||||||
if (isTaiChiModuleActive)
|
if (YukiHookAPI.Status.isTaiChiModuleActive)
|
||||||
showDialog {
|
showDialog {
|
||||||
title = "兼容性提示"
|
title = "兼容性提示"
|
||||||
msg = "若你的设备已 Root,推荐使用 LSPosed 激活模块,太极可能会出现模块设置无法保存的问题。"
|
msg = "若你的设备已 Root,推荐使用 LSPosed 激活模块,太极可能会出现模块设置无法保存的问题。"
|
||||||
@@ -201,10 +202,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
/** 刷新模块激活使用的方式 */
|
/** 刷新模块激活使用的方式 */
|
||||||
private fun refreshActivateExecutor() {
|
private fun refreshActivateExecutor() {
|
||||||
when {
|
when {
|
||||||
YukiHookModuleStatus.executorVersion > 0 ->
|
YukiHookAPI.Status.executorVersion > 0 ->
|
||||||
binding.mainTextApiWay.text =
|
binding.mainTextApiWay.text =
|
||||||
"Activated by ${YukiHookModuleStatus.executorName} API ${YukiHookModuleStatus.executorVersion}"
|
"Activated by ${YukiHookAPI.Status.executorName} API ${YukiHookAPI.Status.executorVersion}"
|
||||||
isTaiChiModuleActive -> binding.mainTextApiWay.text = "Activated by TaiChi"
|
YukiHookAPI.Status.isTaiChiModuleActive -> binding.mainTextApiWay.text = "Activated by TaiChi"
|
||||||
else -> binding.mainTextApiWay.text = "Activated by anonymous"
|
else -> binding.mainTextApiWay.text = "Activated by anonymous"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,12 +23,14 @@
|
|||||||
|
|
||||||
package com.fankes.tsbattery.ui.activity.base
|
package com.fankes.tsbattery.ui.activity.base
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import androidx.core.view.ViewCompat
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.fankes.tsbattery.R
|
import com.fankes.tsbattery.R
|
||||||
import com.fankes.tsbattery.utils.factory.isNotSystemInDarkMode
|
import com.fankes.tsbattery.utils.factory.isNotSystemInDarkMode
|
||||||
import com.gyf.immersionbar.ktx.immersionBar
|
|
||||||
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
|
||||||
import java.lang.reflect.ParameterizedType
|
import java.lang.reflect.ParameterizedType
|
||||||
@@ -52,13 +54,14 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
|
|||||||
/** 隐藏系统的标题栏 */
|
/** 隐藏系统的标题栏 */
|
||||||
supportActionBar?.hide()
|
supportActionBar?.hide()
|
||||||
/** 初始化沉浸状态栏 */
|
/** 初始化沉浸状态栏 */
|
||||||
immersionBar {
|
ViewCompat.getWindowInsetsController(window.decorView)?.apply {
|
||||||
statusBarColor(R.color.colorThemeBackground)
|
isAppearanceLightStatusBars = isNotSystemInDarkMode
|
||||||
autoDarkModeEnable(true)
|
isAppearanceLightNavigationBars = isNotSystemInDarkMode
|
||||||
statusBarDarkFont(isNotSystemInDarkMode)
|
}
|
||||||
navigationBarColor(R.color.colorThemeBackground)
|
ResourcesCompat.getColor(resources, R.color.colorThemeBackground, null).also {
|
||||||
navigationBarDarkIcon(isNotSystemInDarkMode)
|
window?.statusBarColor = it
|
||||||
fitsSystemWindows(true)
|
window?.navigationBarColor = it
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) window?.navigationBarDividerColor = it
|
||||||
}
|
}
|
||||||
/** 装载子类 */
|
/** 装载子类 */
|
||||||
onCreate()
|
onCreate()
|
||||||
|
@@ -37,17 +37,17 @@ 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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造对话框
|
* 构造对话框
|
||||||
* @param isUseBlackTheme 是否使用深色主题
|
* @param isUseBlackTheme 是否使用深色主题
|
||||||
* @param it 对话框方法体
|
* @param initiate 对话框方法体
|
||||||
*/
|
*/
|
||||||
fun Context.showDialog(isUseBlackTheme: Boolean = false, it: DialogBuilder.() -> Unit) =
|
fun Context.showDialog(isUseBlackTheme: Boolean = false, initiate: DialogBuilder.() -> Unit) =
|
||||||
DialogBuilder(this, isUseBlackTheme).apply(it).show()
|
DialogBuilder(context = this, isUseBlackTheme).apply(initiate).show()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对话框构造器
|
* 对话框构造器
|
||||||
@@ -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 // 自定义布局
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,34 +140,34 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
|
|||||||
/**
|
/**
|
||||||
* 设置对话框确定按钮
|
* 设置对话框确定按钮
|
||||||
* @param text 按钮文本内容
|
* @param text 按钮文本内容
|
||||||
* @param it 点击事件
|
* @param callback 点击事件
|
||||||
*/
|
*/
|
||||||
fun confirmButton(text: String = "确定", it: () -> Unit = {}) {
|
fun confirmButton(text: String = "确定", callback: () -> Unit = {}) {
|
||||||
if (isUsingAndroidX)
|
if (isUsingAndroidX)
|
||||||
runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> it() } }
|
runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> callback() } }
|
||||||
else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> it() } }
|
else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> callback() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置对话框取消按钮
|
* 设置对话框取消按钮
|
||||||
* @param text 按钮文本内容
|
* @param text 按钮文本内容
|
||||||
* @param it 点击事件
|
* @param callback 点击事件
|
||||||
*/
|
*/
|
||||||
fun cancelButton(text: String = "取消", it: () -> Unit = {}) {
|
fun cancelButton(text: String = "取消", callback: () -> Unit = {}) {
|
||||||
if (isUsingAndroidX)
|
if (isUsingAndroidX)
|
||||||
runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> it() } }
|
runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> callback() } }
|
||||||
else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> it() } }
|
else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> callback() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置对话框第三个按钮
|
* 设置对话框第三个按钮
|
||||||
* @param text 按钮文本内容
|
* @param text 按钮文本内容
|
||||||
* @param it 点击事件
|
* @param callback 点击事件
|
||||||
*/
|
*/
|
||||||
fun neutralButton(text: String = "更多", it: () -> Unit = {}) {
|
fun neutralButton(text: String = "更多", callback: () -> Unit = {}) {
|
||||||
if (isUsingAndroidX)
|
if (isUsingAndroidX)
|
||||||
runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> it() } }
|
runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> callback() } }
|
||||||
else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> it() } }
|
else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> callback() } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 取消对话框 */
|
/** 取消对话框 */
|
||||||
|
@@ -35,8 +35,8 @@ import android.net.Uri
|
|||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import com.fankes.tsbattery.application.TSApplication.Companion.appContext
|
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统深色模式是否开启
|
* 系统深色模式是否开启
|
||||||
@@ -137,13 +137,13 @@ fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).sho
|
|||||||
* 弹出 [Snackbar]
|
* 弹出 [Snackbar]
|
||||||
* @param msg 提示内容
|
* @param msg 提示内容
|
||||||
* @param actionText 按钮文本 - 不写默认取消按钮
|
* @param actionText 按钮文本 - 不写默认取消按钮
|
||||||
* @param it 按钮事件回调
|
* @param callback 按钮事件回调
|
||||||
*/
|
*/
|
||||||
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) =
|
fun Context.snake(msg: String, actionText: String = "", callback: () -> 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(if (isSystemInDarkMode) Color.BLACK else Color.WHITE)
|
setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE)
|
||||||
setAction(actionText) { it() }
|
setAction(actionText) { callback() }
|
||||||
}.show()
|
}.show()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -19,15 +19,21 @@
|
|||||||
*
|
*
|
||||||
* This file is Created by fankes on 2022/3/20.
|
* This file is Created by fankes on 2022/3/20.
|
||||||
*/
|
*/
|
||||||
|
@file:Suppress("NewApi")
|
||||||
|
|
||||||
package com.fankes.tsbattery.utils.tool
|
package com.fankes.tsbattery.utils.tool
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.icu.text.SimpleDateFormat
|
||||||
|
import android.icu.util.Calendar
|
||||||
|
import android.icu.util.TimeZone
|
||||||
import com.fankes.tsbattery.utils.factory.*
|
import com.fankes.tsbattery.utils.factory.*
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 Github Release 最新版本工具类
|
* 获取 Github Release 最新版本工具类
|
||||||
@@ -44,9 +50,9 @@ object GithubReleaseTool {
|
|||||||
* 获取最新版本信息
|
* 获取最新版本信息
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param version 当前版本
|
* @param version 当前版本
|
||||||
* @param it 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体)
|
* @param result 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体)
|
||||||
*/
|
*/
|
||||||
fun checkingForUpdate(context: Context, version: String, it: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) {
|
fun checkingForUpdate(context: Context, version: String, result: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) {
|
||||||
OkHttpClient().newBuilder().build().newCall(
|
OkHttpClient().newBuilder().build().newCall(
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
.url("https://api.github.com/repos/$REPO_AUTHOR/$REPO_NAME/releases/latest")
|
.url("https://api.github.com/repos/$REPO_AUTHOR/$REPO_NAME/releases/latest")
|
||||||
@@ -61,7 +67,7 @@ object GithubReleaseTool {
|
|||||||
name = getString("name"),
|
name = getString("name"),
|
||||||
htmlUrl = getString("html_url"),
|
htmlUrl = getString("html_url"),
|
||||||
content = getString("body"),
|
content = getString("body"),
|
||||||
date = getString("published_at").replace(oldValue = "T", newValue = " ").replace(oldValue = "Z", newValue = "")
|
date = getString("published_at").localTime()
|
||||||
).apply {
|
).apply {
|
||||||
fun showUpdate() = context.showDialog {
|
fun showUpdate() = context.showDialog {
|
||||||
title = "最新版本 $name"
|
title = "最新版本 $name"
|
||||||
@@ -72,7 +78,7 @@ object GithubReleaseTool {
|
|||||||
}
|
}
|
||||||
if (name != version) (context as? Activity?)?.runOnUiThread {
|
if (name != version) (context as? Activity?)?.runOnUiThread {
|
||||||
showUpdate()
|
showUpdate()
|
||||||
it(name) { showUpdate() }
|
result(name) { showUpdate() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,9 +89,9 @@ object GithubReleaseTool {
|
|||||||
/**
|
/**
|
||||||
* 检查网络连接情况
|
* 检查网络连接情况
|
||||||
* @param context 实例
|
* @param context 实例
|
||||||
* @param it 已连接回调
|
* @param callback 已连接回调
|
||||||
*/
|
*/
|
||||||
private fun checkingInternetConnect(context: Context, it: () -> Unit) = runInSafe {
|
private fun checkingInternetConnect(context: Context, callback: () -> Unit) = runInSafe {
|
||||||
if (isNetWorkSuccess)
|
if (isNetWorkSuccess)
|
||||||
OkHttpClient().newBuilder().build().newCall(
|
OkHttpClient().newBuilder().build().newCall(
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
@@ -106,11 +112,23 @@ object GithubReleaseTool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) = runInSafe {
|
override fun onResponse(call: Call, response: Response) = runInSafe {
|
||||||
(context as? Activity?)?.runOnUiThread { runInSafe { it() } }
|
(context as? Activity?)?.runOnUiThread { runInSafe { callback() } }
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化时间为本地时区
|
||||||
|
* @return [String] 本地时区时间
|
||||||
|
*/
|
||||||
|
private fun String.localTime() = replace(oldValue = "T", newValue = " ").replace(oldValue = "Z", newValue = "").let {
|
||||||
|
runCatching {
|
||||||
|
val local = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).apply { timeZone = Calendar.getInstance().timeZone }
|
||||||
|
val current = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).apply { timeZone = TimeZone.getTimeZone("GMT") }
|
||||||
|
local.format(current.parse(it))
|
||||||
|
}.getOrNull() ?: it
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Github Release bean
|
* Github Release bean
|
||||||
* @param name 版本名称
|
* @param name 版本名称
|
||||||
|
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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/5/30.
|
||||||
|
*/
|
||||||
|
package com.fankes.tsbattery.utils.tool
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.fankes.tsbattery.BuildConfig
|
||||||
|
import com.fankes.tsbattery.utils.factory.openBrowser
|
||||||
|
import com.fankes.tsbattery.utils.factory.showDialog
|
||||||
|
import com.highcapable.yukihookapi.YukiHookAPI
|
||||||
|
import com.highcapable.yukihookapi.hook.factory.modulePrefs
|
||||||
|
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [YukiHookAPI] 的自动推广工具类
|
||||||
|
*/
|
||||||
|
object YukiPromoteTool {
|
||||||
|
|
||||||
|
/** 推广已读存储键值 */
|
||||||
|
private val YUKI_PROMOTE_READED = PrefsData("yuki_promote_readed_${BuildConfig.VERSION_NAME}", false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示推广对话框
|
||||||
|
* @param context 实例
|
||||||
|
*/
|
||||||
|
fun promote(context: Context) {
|
||||||
|
fun saveReaded() = context.modulePrefs.put(YUKI_PROMOTE_READED, value = true)
|
||||||
|
if (context.modulePrefs.get(YUKI_PROMOTE_READED).not())
|
||||||
|
context.showDialog {
|
||||||
|
title = "面向开发者的推广"
|
||||||
|
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
|
||||||
|
"快来体验 YukiHookAPI,这是一个使用 Kotlin 重新构建的高效 Xposed Hook API,助你的开发变得更轻松。"
|
||||||
|
confirmButton(text = "去看看") {
|
||||||
|
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
|
||||||
|
saveReaded()
|
||||||
|
}
|
||||||
|
cancelButton(text = "我不是开发者") { saveReaded() }
|
||||||
|
noCancelable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
build.gradle
11
build.gradle
@@ -1,12 +1,13 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'com.android.application' version '7.1.2' apply false
|
id 'com.android.application' version '7.2.0' apply false
|
||||||
id 'com.android.library' version '7.1.2' apply false
|
id 'com.android.library' version '7.2.0' apply false
|
||||||
id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
|
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
appVersionName = "3.6"
|
appVersionName = "3.96"
|
||||||
appVersionCode = 14
|
appVersionCode = 19
|
||||||
|
enableR8 = true
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
task clean(type: Delete) {
|
||||||
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,6 +1,6 @@
|
|||||||
#Mon Feb 14 23:27:58 CST 2022
|
#Wed May 25 04:34:58 CST 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
Reference in New Issue
Block a user