mirror of
https://github.com/fankes/TSBattery.git
synced 2025-09-04 17:55:30 +08:00
Compare commits
59 Commits
Author | SHA1 | Date | |
---|---|---|---|
b7015f8a69
|
|||
d39f50642a
|
|||
5a6a61b4be
|
|||
114ec89764
|
|||
476b6d6be6
|
|||
53249108d1
|
|||
147e4c117e
|
|||
276820fdc5
|
|||
0b7ade9076
|
|||
6c26a8b0cd
|
|||
d925873c4c
|
|||
9fb52332d5
|
|||
bf92f0241c
|
|||
7ec8de4be0
|
|||
df949cf56b
|
|||
f1061b27fa
|
|||
b8543130cc
|
|||
9ae395ecee
|
|||
8d2d233b93
|
|||
70757b1594
|
|||
a14a38e00f
|
|||
910c67a943
|
|||
6a31eef23e
|
|||
0517df5dc4
|
|||
f25472b124
|
|||
ebb68c69b4
|
|||
c89eb39a75
|
|||
43e0dff6cb
|
|||
215d680955
|
|||
c25f316512
|
|||
798a55a328
|
|||
3dea65c4c6
|
|||
46efaf7083
|
|||
760b7a42cd
|
|||
6be267f74d
|
|||
7d1dbbbf44
|
|||
fb0182f075
|
|||
80e89d087f
|
|||
c5711338e3
|
|||
2fac3c2709
|
|||
7b65ca01fb
|
|||
4d75fb9e8c
|
|||
13d25dcafd
|
|||
1298077c9f
|
|||
374ffaab4f
|
|||
76904665cc
|
|||
dfdb18dcb7
|
|||
d1fb794284
|
|||
3adaad1040
|
|||
39b132cc1a
|
|||
13837b3b33
|
|||
4405808ff3
|
|||
7c66519e2d
|
|||
9b620d7688
|
|||
cde830b804
|
|||
884a743338
|
|||
e9aa721902
|
|||
fa967c8dfb
|
|||
7fe6bd91f0
|
@@ -10,6 +10,24 @@ ktlint_standard_argument-list-wrapping = disabled
|
||||
ktlint_standard_parameter-list-wrapping = disabled
|
||||
ktlint_standard_trailing-comma-on-declaration-site = disabled
|
||||
ktlint_function_signature_body_expression_wrapping = multiline
|
||||
ktlint_standard_string-template-indent = disabled
|
||||
ktlint_standard_function-signature = disabled
|
||||
ktlint_standard_trailing-comma-on-call-site = disabled
|
||||
ktlint_standard_multiline-expression-wrapping = disabled
|
||||
ktlint_standard_no-empty-first-line-in-class-body = disabled
|
||||
ktlint_standard_if-else-wrapping = disabled
|
||||
ktlint_standard_if-else-bracing = disabled
|
||||
ktlint_standard_statement-wrapping = disabled
|
||||
ktlint_standard_blank-line-before-declaration = disabled
|
||||
ktlint_standard_no-empty-file = disabled
|
||||
ktlint_standard_property-naming = disabled
|
||||
ktlint_standard_function-naming = disabled
|
||||
ktlint_standard_chain-method-continuation = disabled
|
||||
ktlint_standard_class-signature = disabled
|
||||
ktlint_standard_condition-wrapping = disabled
|
||||
ktlint_standard_class-signature = disabled
|
||||
ktlint_standard_no-trailing-spaces = disabled
|
||||
ktlint_standard_multiline-loop = disabled
|
||||
ij_continuation_indent_size = 2
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
|
12
.github/workflows/commit_ci.yml
vendored
12
.github/workflows/commit_ci.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
See commit detail [here](${{ github.event.head_commit.url }})
|
||||
COMMIT_URL: ${{ github.event.head_commit.url }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare GitHub Env
|
||||
run: |
|
||||
GITHUB_SHA=${{ github.sha }}
|
||||
@@ -37,10 +37,10 @@ jobs:
|
||||
uses: jwlawson/actions-setup-cmake@v1
|
||||
with:
|
||||
cmake-version: '3.22.1'
|
||||
- name: Prepare Java 17
|
||||
uses: actions/setup-java@v3
|
||||
- name: Prepare Java 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
java-package: jdk
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
@@ -69,12 +69,12 @@ jobs:
|
||||
echo "DEBUG_APK_PATH=$(find ${{ env.APK_OUTPUT_PATH }}/debug -name '*.apk')" >> $GITHUB_ENV
|
||||
echo "RELEASE_APK_PATH=$(find ${{ env.APK_OUTPUT_PATH }}/release -name '*.apk')" >> $GITHUB_ENV
|
||||
- name: Upload Artifacts (Debug)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: ${{ env.DEBUG_APK_PATH }}
|
||||
name: TSBattery-debug-${{ github.event.head_commit.id }}
|
||||
- name: Upload Artifacts (Release)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: ${{ env.RELEASE_APK_PATH }}
|
||||
name: TSBattery-release-${{ github.event.head_commit.id }}
|
||||
|
12
.github/workflows/pull_request_ci.yml
vendored
12
.github/workflows/pull_request_ci.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
env:
|
||||
APK_OUTPUT_PATH: 'app/build/outputs/apk'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Prepare GitHub Env
|
||||
run: |
|
||||
GITHUB_SHA=${{ github.sha }}
|
||||
@@ -27,10 +27,10 @@ jobs:
|
||||
uses: jwlawson/actions-setup-cmake@v1
|
||||
with:
|
||||
cmake-version: '3.22.1'
|
||||
- name: Prepare Java 17
|
||||
uses: actions/setup-java@v3
|
||||
- name: Prepare Java 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
java-package: jdk
|
||||
distribution: 'temurin'
|
||||
cache: 'gradle'
|
||||
@@ -59,12 +59,12 @@ jobs:
|
||||
echo "DEBUG_APK_PATH=$(find ${{ env.APK_OUTPUT_PATH }}/debug -name '*.apk')" >> $GITHUB_ENV
|
||||
echo "RELEASE_APK_PATH=$(find ${{ env.APK_OUTPUT_PATH }}/release -name '*.apk')" >> $GITHUB_ENV
|
||||
- name: Upload Artifacts (Debug)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: ${{ env.DEBUG_APK_PATH }}
|
||||
name: TSBattery-debug-${{ github.event.head_commit.id }}
|
||||
- name: Upload Artifacts (Release)
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: ${{ env.RELEASE_APK_PATH }}
|
||||
name: TSBattery-release-${{ github.event.head_commit.id }}
|
117
.gitignore
vendored
117
.gitignore
vendored
@@ -1,15 +1,110 @@
|
||||
## Fully .gtignore for IntelliJ, Android Studio and Gradle based Java projects
|
||||
## References:
|
||||
## - https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
## - https://github.com/android/platform-samples/blob/main/.gitignore
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
.idea/.name
|
||||
.idea/artifacts
|
||||
.idea/compiler.xml
|
||||
.idea/jarRepositories.xml
|
||||
.idea/modules.xml
|
||||
.idea/*.iml
|
||||
.idea/modules
|
||||
.idea/caches
|
||||
.idea/material_theme**
|
||||
.idea/other.xml
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
*.ipr
|
||||
|
||||
# Kotlin
|
||||
.kotlin
|
||||
|
||||
# Misc
|
||||
.idea/misc.xml
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
# Android studio 3.1+ additional
|
||||
.idea/deployment*.xml
|
||||
.idea/assetWizardSettings.xml
|
||||
.idea/androidTestResultsUserPreferences.xml
|
||||
|
||||
# Android projects
|
||||
**/local.properties
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
|
||||
# Gradle projects
|
||||
.gradle
|
||||
build/
|
||||
|
||||
# Mkdocs temporary serving folder
|
||||
docs-gen
|
||||
site
|
||||
*.bak
|
||||
.idea/appInsightsSettings.xml
|
||||
|
||||
# Mac OS
|
||||
.DS_Store
|
5
.idea/.gitignore
generated
vendored
5
.idea/.gitignore
generated
vendored
@@ -1,5 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
/gradle.xml
|
||||
/misc.xml
|
6
.idea/AndroidProjectSystem.xml
generated
Normal file
6
.idea/AndroidProjectSystem.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AndroidProjectSystem">
|
||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
||||
</component>
|
||||
</project>
|
26
.idea/appInsightsSettings.xml
generated
26
.idea/appInsightsSettings.xml
generated
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AppInsightsSettings">
|
||||
<option name="tabSettings">
|
||||
<map>
|
||||
<entry key="Firebase Crashlytics">
|
||||
<value>
|
||||
<InsightsFilterSettings>
|
||||
<option name="connection">
|
||||
<ConnectionSetting>
|
||||
<option name="appId" value="PLACEHOLDER" />
|
||||
<option name="mobileSdkAppId" value="" />
|
||||
<option name="projectId" value="" />
|
||||
<option name="projectNumber" value="" />
|
||||
</ConnectionSetting>
|
||||
</option>
|
||||
<option name="signal" value="SIGNAL_UNSPECIFIED" />
|
||||
<option name="timeIntervalDays" value="THIRTY_DAYS" />
|
||||
<option name="visibilityType" value="ALL" />
|
||||
</InsightsFilterSettings>
|
||||
</value>
|
||||
</entry>
|
||||
</map>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
6
.idea/compiler.xml
generated
6
.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
</component>
|
||||
</project>
|
10
.idea/deploymentTargetDropDown.xml
generated
10
.idea/deploymentTargetDropDown.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<value>
|
||||
<entry key="app">
|
||||
<State />
|
||||
</entry>
|
||||
</value>
|
||||
</component>
|
||||
</project>
|
45
.idea/jarRepositories.xml
generated
45
.idea/jarRepositories.xml
generated
@@ -1,45 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RemoteRepositoriesConfiguration">
|
||||
<remote-repository>
|
||||
<option name="id" value="central" />
|
||||
<option name="name" value="Maven Central repository" />
|
||||
<option name="url" value="https://repo1.maven.org/maven2" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="jboss.community" />
|
||||
<option name="name" value="JBoss Community repository" />
|
||||
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="MavenRepo" />
|
||||
<option name="name" value="MavenRepo" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="BintrayJCenter" />
|
||||
<option name="name" value="BintrayJCenter" />
|
||||
<option name="url" value="https://jcenter.bintray.com/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="Google" />
|
||||
<option name="name" value="Google" />
|
||||
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven3" />
|
||||
<option name="name" value="maven3" />
|
||||
<option name="url" value="https://www.jitpack.io" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven" />
|
||||
<option name="name" value="maven" />
|
||||
<option name="url" value="https://maven.aliyun.com/nexus/content/groups/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven2" />
|
||||
<option name="name" value="maven2" />
|
||||
<option name="url" value="https://maven.aliyun.com/nexus/content/repositories/jcenter" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
2
.idea/kotlinc.xml
generated
2
.idea/kotlinc.xml
generated
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="1.9.10" />
|
||||
<option name="version" value="2.1.10" />
|
||||
</component>
|
||||
</project>
|
7
.idea/ktlint-plugin.xml
generated
Normal file
7
.idea/ktlint-plugin.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="KtLint plugin">
|
||||
<ktlintMode>MANUAL</ktlintMode>
|
||||
<formatOnSave>false</formatOnSave>
|
||||
</component>
|
||||
</project>
|
17
.idea/runConfigurations.xml
generated
Normal file
17
.idea/runConfigurations.xml
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
76
README.md
76
README.md
@@ -1,17 +1,17 @@
|
||||
# TSBattery
|
||||
|
||||
[](https://github.com/fankes/TSBattery/blob/master/LICENSE)
|
||||
[](https://github.com/fankes/TSBattery/actions/workflows/commit_ci.yml)
|
||||
[](https://github.com/fankes/TSBattery/releases)
|
||||

|
||||

|
||||
[](https://github.com/fankes/TSBattery/blob/master/LICENSE)
|
||||
[](https://github.com/fankes/TSBattery/actions/workflows/commit_ci.yml)
|
||||
[](https://github.com/fankes/TSBattery/releases)
|
||||

|
||||

|
||||
|
||||
[](https://t.me/TSBATTERY_CI)
|
||||
[](https://t.me/XiaofangInternet)
|
||||
[](https://qm.qq.com/cgi-bin/qm/qr?k=dp2h5YhWiga9WWb_Oh7kSHmx01X8I8ii&jump_from=webapi&authKey=Za5CaFP0lk7+Zgsk2KpoBD7sSaYbeXbsDgFjiWelOeH4VSionpxFJ7V0qQBSqvFM)
|
||||
[](https://pd.qq.com/s/44gcy28h)
|
||||
[](https://t.me/TSBattery_CI)
|
||||
[](https://t.me/XiaofangInternet)
|
||||
[](https://qm.qq.com/cgi-bin/qm/qr?k=dp2h5YhWiga9WWb_Oh7kSHmx01X8I8ii&jump_from=webapi&authKey=Za5CaFP0lk7+Zgsk2KpoBD7sSaYbeXbsDgFjiWelOeH4VSionpxFJ7V0qQBSqvFM)
|
||||
[](https://pd.qq.com/s/44gcy28h)
|
||||
|
||||

|
||||
<img src="app/src/main/ic_launcher-playstore.png" width = "100" height = "100" alt="LOGO"/>
|
||||
|
||||
A new way to save your battery avoid cancer apps hacker it.
|
||||
|
||||
@@ -34,40 +34,48 @@ This Xposed Module is for use by specific apps for users in mainland China, you
|
||||
- 如果在微信设置界面右上角你无法找到 **TSBattery**
|
||||
的图标,请尝试同时激活 [WeXposed (微X模块)](https://github.com/Xposed-Modules-Repo/com.fkzhang.wechatxposed)
|
||||
|
||||
## 发行渠道说明
|
||||
## 发行渠道
|
||||
|
||||
- [Automatic Build on Commit](https://github.com/fankes/TSBattery/actions/workflows/commit_ci.yml)
|
||||
| <img src="https://avatars.githubusercontent.com/in/15368?s=64&v=4" width = "30" height = "30" alt="LOGO"/> | [GitHub CI](https://github.com/fankes/TSBattery/actions/workflows/commit_ci.yml) | CI 自动构建 (测试版) |
|
||||
|------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------|---------------|
|
||||
|
||||
上述更新为代码 `commit` 后自动触发,具体更新内容可点击上方的文字前往 **GitHub Actions** 进行查看,本更新由开源的流程自动编译发布,
|
||||
**不保证其稳定性**, 所发布的版本**仅供测试**,且不会特殊说明甚至可能会变更版本号或保持与当前稳定版相同的版本号。
|
||||
| <img src="https://github.com/peter-iakovlev/Telegram/blob/public/Icon.png?raw=true" width = "30" height = "30" alt="LOGO"/> | [Telegram CI 频道](https://t.me/TSBattery_CI) | CI 自动构建 (测试版) |
|
||||
|-----------------------------------------------------------------------------------------------------------------------------|---------------------------------------------|---------------|
|
||||
|
||||
如果你需要直接下载 CI 自动构建打包的安装包,请点击顶部的 `CI builds | Telegram` 标签加入 Telegram CI 自动构建频道。
|
||||
| <img src="https://avatars.githubusercontent.com/in/15368?s=64&v=4" width = "30" height = "30" alt="LOGO"/> | [GitHub Releases](https://github.com/fankes/TSBattery/releases) | 正式版 (稳定版) |
|
||||
|------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------|-----------|
|
||||
|
||||
- [Release](https://github.com/fankes/TSBattery/releases)
|
||||
- [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)
|
||||
- [蓝奏云 **密码:tsbt**](https://fankes.lanzouy.com/b02zfz3sj)
|
||||
| <img src="https://avatars.githubusercontent.com/u/78217009?s=200&v=4?raw=true" width = "30" height = "30" alt="LOGO"/> | [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases) | 正式版 (稳定版) |
|
||||
|------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|-----------|
|
||||
|
||||
上述更新为手动发布的稳定版,具体更新内容可点击上方的文字前往指定的发布页面查看,稳定版的更新将会同时发布到上述地址中,同步更新。
|
||||
| <img src="https://github.com/fankes/fankes/assets/37344460/82113d3c-aa7b-4dd1-95c7-cda650065c12" width = "30" height = "30" alt="LOGO"/> | [123 云盘 **(密码:tsbt)**](https://www.123pan.com/s/5SlUVv-N8DBh.html) | 正式版 (稳定版) |
|
||||
|------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------|-----------|
|
||||
|
||||
本模块发布地址仅限于上述所列出的地址,从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
|
||||
|
||||
## 请勿用于非法用途
|
||||
## 注意事项
|
||||
|
||||
本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
|
||||
<h3>1. 本软件免费、由兴趣驱动开发,仅供学习交流使用。如果你是从其他非官方渠道付费获得本软件,可能已遭遇欺诈,欢迎向我们举报可疑行为。</h3>
|
||||
|
||||
<h3>2. 本软件采用 <strong>GNU Affero General Public License (AGPL 3.0)</strong> 许可证。根据该许可证的要求:</h3>
|
||||
|
||||
- 任何衍生作品必须采用相同的 AGPL 许可证
|
||||
- 分发本软件或其修改版本时,必须提供完整的源代码
|
||||
- 必须保留原始的版权声明及许可证信息
|
||||
- 不得额外施加限制来限制他人对本软件的自由使用
|
||||
|
||||
<h3>3. 我们鼓励在遵守 AGPL 3.0 条款的前提下进行自由传播和改进,但请尊重作者署名权,勿冒用原作者名义。</h3>
|
||||
|
||||
## 项目推广
|
||||
|
||||
如果你正在寻找一个可以自动管理 Gradle 项目依赖的 Gradle 插件,你可以了解一下 [SweetDependency](https://github.com/HighCapable/SweetDependency) 项目。
|
||||
|
||||
如果你正在寻找一个可以自动生成属性键值的 Gradle 插件,你可以了解一下 [SweetProperty](https://github.com/HighCapable/SweetProperty) 项目。
|
||||
|
||||
本项目同样使用了 **SweetDependency** 和 **SweetProperty**。
|
||||
|
||||
## 捐赠支持
|
||||
|
||||
工作不易,无意外情况此项目将继续维护下去,提供更多可能,欢迎打赏。
|
||||
|
||||
<img src="https://github.com/fankes/fankes/blob/main/img-src/payment_code.jpg?raw=true" width = "500" alt="Payment Code"/>
|
||||
<!--suppress HtmlDeprecatedAttribute -->
|
||||
<div align="center">
|
||||
<h2>嘿,还请君留步!👋</h2>
|
||||
<h3>这里有 Android 开发工具、UI 设计、Gradle 插件、Xposed 模块和实用软件等相关项目。</h3>
|
||||
<h3>如果下方的项目能为你提供帮助,不妨为我点个 star 吧!</h3>
|
||||
<h3>所有项目免费、开源,遵循对应开源许可协议。</h3>
|
||||
<h1><a href="https://github.com/fankes/fankes/blob/main/project-promote/README-zh-CN.md">→ 查看更多关于我的项目,请点击这里 ←</a></h1>
|
||||
</div>
|
||||
|
||||
## Star History
|
||||
|
||||
@@ -78,7 +86,7 @@ This Xposed Module is for use by specific apps for users in mainland China, you
|
||||
- [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.html)
|
||||
|
||||
```
|
||||
Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
@@ -96,4 +104,4 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Powered by [YukiHookAPI](https://github.com/HighCapable/YukiHookAPI)
|
||||
|
||||
版权所有 © 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
版权所有 © 2017 Fankes Studio(qzmmcn@163.com)
|
2
app/.gitignore
vendored
2
app/.gitignore
vendored
@@ -1,4 +1,2 @@
|
||||
/build
|
||||
/release
|
||||
/src/main/assets/xposed_init
|
||||
/src/main/resources/META-INF/yukihookapi_init
|
@@ -38,14 +38,6 @@ android {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
freeCompilerArgs = listOf(
|
||||
"-Xno-param-assertions",
|
||||
"-Xno-call-assertions",
|
||||
"-Xno-receiver-assertions"
|
||||
)
|
||||
}
|
||||
buildFeatures {
|
||||
buildConfig = true
|
||||
viewBinding = true
|
||||
@@ -58,7 +50,18 @@ androidComponents {
|
||||
onVariants(selector().all()) {
|
||||
it.outputs.forEach { output ->
|
||||
val currentType = it.buildType
|
||||
val currentSuffix = property.github.ci.commit.id.let { suffix -> if (suffix.isNotBlank()) "-$suffix" else "" }
|
||||
|
||||
// Workaround for GitHub Actions.
|
||||
// Why? I don't know, but it works.
|
||||
// Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
|
||||
// public inline fun CharSequence.isNotBlank(): Boolean defined in kotlin.text.
|
||||
@Suppress("UNNECESSARY_SAFE_CALL", "RemoveRedundantCallsOfConversionMethods")
|
||||
val currentSuffix = property.github.ci.commit.id?.let { suffix ->
|
||||
// Workaround for GitHub Actions.
|
||||
// Strongly transfer type to [String].
|
||||
val sSuffix = suffix.toString()
|
||||
if (sSuffix.isNotBlank()) "-$sSuffix" else ""
|
||||
}
|
||||
val currentVersion = "${output.versionName.get()}$currentSuffix(${output.versionCode.get()})"
|
||||
if (output is com.android.build.api.variant.impl.VariantOutputImpl)
|
||||
output.outputFileName.set("${property.project.name}-v$currentVersion-$currentType.apk")
|
||||
@@ -70,6 +73,13 @@ dependencies {
|
||||
compileOnly(de.robv.android.xposed.api)
|
||||
implementation(com.highcapable.yukihookapi.api)
|
||||
ksp(com.highcapable.yukihookapi.ksp.xposed)
|
||||
ksp(com.highcapable.hikage.hikage.compiler)
|
||||
implementation(com.highcapable.kavaref.kavaref.core)
|
||||
implementation(com.highcapable.kavaref.kavaref.extension)
|
||||
implementation(com.highcapable.hikage.hikage.core)
|
||||
implementation(com.highcapable.hikage.hikage.extension)
|
||||
implementation(com.highcapable.hikage.hikage.widget.androidx)
|
||||
implementation(com.highcapable.hikage.hikage.widget.material)
|
||||
implementation(com.fankes.projectpromote.project.promote)
|
||||
implementation(org.luckypray.dexkit)
|
||||
implementation(com.github.duanhong169.drawabletoolbox)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
@@ -26,8 +26,11 @@ package com.fankes.tsbattery.hook.entity
|
||||
import android.app.Activity
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Message
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.app.ServiceCompat
|
||||
@@ -44,29 +47,17 @@ import com.fankes.tsbattery.hook.factory.startModuleSettings
|
||||
import com.fankes.tsbattery.hook.helper.DexKitHelper
|
||||
import com.fankes.tsbattery.utils.factory.appVersionName
|
||||
import com.fankes.tsbattery.utils.factory.dp
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.kavaref.KavaRef.Companion.asResolver
|
||||
import com.highcapable.kavaref.KavaRef.Companion.resolve
|
||||
import com.highcapable.kavaref.extension.ArrayClass
|
||||
import com.highcapable.kavaref.extension.VariousClass
|
||||
import com.highcapable.kavaref.extension.classOf
|
||||
import com.highcapable.kavaref.extension.createInstanceAsTypeOrNull
|
||||
import com.highcapable.kavaref.extension.createInstanceOrNull
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.buildOf
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.factory.field
|
||||
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
|
||||
import com.highcapable.yukihookapi.hook.factory.method
|
||||
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
|
||||
import com.highcapable.yukihookapi.hook.log.YLog
|
||||
import com.highcapable.yukihookapi.hook.type.android.BuildClass
|
||||
import com.highcapable.yukihookapi.hook.type.android.BundleClass
|
||||
import com.highcapable.yukihookapi.hook.type.android.ContextClass
|
||||
import com.highcapable.yukihookapi.hook.type.android.IntentClass
|
||||
import com.highcapable.yukihookapi.hook.type.android.MessageClass
|
||||
import com.highcapable.yukihookapi.hook.type.java.AnyArrayClass
|
||||
import com.highcapable.yukihookapi.hook.type.java.AnyClass
|
||||
import com.highcapable.yukihookapi.hook.type.java.BooleanType
|
||||
import com.highcapable.yukihookapi.hook.type.java.CharSequenceClass
|
||||
import com.highcapable.yukihookapi.hook.type.java.IntType
|
||||
import com.highcapable.yukihookapi.hook.type.java.ListClass
|
||||
import com.highcapable.yukihookapi.hook.type.java.LongType
|
||||
import com.highcapable.yukihookapi.hook.type.java.StringClass
|
||||
import com.highcapable.yukihookapi.hook.type.java.UnitType
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Proxy
|
||||
|
||||
@@ -119,6 +110,9 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
)
|
||||
)
|
||||
|
||||
/** 是否存在 [BaseChatPieClass] */
|
||||
private val hasBaseChatPieClass by lazy { BaseChatPieClass != null }
|
||||
|
||||
/**
|
||||
* DexKit 搜索结果数据实现类
|
||||
*/
|
||||
@@ -147,7 +141,7 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
* 在 QQ NT 中 [AboutActivityClass] 已被移除 - 以此作为判断条件
|
||||
* @return [Boolean]
|
||||
*/
|
||||
private val isQQNTVersion get() = isQQ && AboutActivityClass == null
|
||||
private val isQQNTVersion get() = AboutActivityClass == null
|
||||
|
||||
/** 当前宿主的版本 */
|
||||
private var hostVersionName = "<unknown>"
|
||||
@@ -156,7 +150,9 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
* 通过 [Activity] or [Fragment] 实例得到上下文
|
||||
* @return [Activity] or null
|
||||
*/
|
||||
private fun Any.compatToActivity() = if (this is Activity) this else current().method { name = "getActivity"; superClass() }.invoke()
|
||||
private fun Any.compatToActivity() = if (this !is Activity)
|
||||
asResolver().optional().firstMethodOrNull { name = "getActivity"; superclass() }?.invoke()
|
||||
else this
|
||||
|
||||
/** 使用 DexKit 进行搜索 */
|
||||
private fun searchUsingDexKit() {
|
||||
@@ -169,18 +165,18 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
declaredClass(baseChatPieClassName)
|
||||
usingStrings("remainScreenOn")
|
||||
paramCount = 0
|
||||
returnType = UnitType.name
|
||||
returnType = Void.TYPE.name
|
||||
}
|
||||
}.firstOrNull()?.getMethodInstance(classLoader)
|
||||
}.singleOrNull()?.getMethodInstance(classLoader)
|
||||
DexKitData.BaseChatPie_CancelRemainScreenOnMethod =
|
||||
findMethod {
|
||||
matcher {
|
||||
declaredClass(baseChatPieClassName)
|
||||
usingStrings("cancelRemainScreenOn")
|
||||
paramCount = 0
|
||||
returnType = UnitType.name
|
||||
returnType = Void.TYPE.name
|
||||
}
|
||||
}.firstOrNull()?.getMethodInstance(classLoader)
|
||||
}.singleOrNull()?.getMethodInstance(classLoader)
|
||||
}
|
||||
val kotlinFunction0 = "kotlin.jvm.functions.Function0"
|
||||
findClass {
|
||||
@@ -189,26 +185,26 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
methods {
|
||||
add {
|
||||
name = "<init>"
|
||||
paramTypes(ContextClass.name, IntType.name, CharSequenceClass.name, IntType.name)
|
||||
paramTypes(classOf<Context>().name, classOf<Int>().name, classOf<CharSequence>().name, classOf<Int>().name)
|
||||
}
|
||||
add {
|
||||
paramTypes(kotlinFunction0)
|
||||
returnType = UnitType.name
|
||||
returnType = Void.TYPE.name
|
||||
}
|
||||
}
|
||||
fields { count(6..Int.MAX_VALUE) }
|
||||
}
|
||||
}.firstOrNull()?.name?.also { className ->
|
||||
}.singleOrNull()?.name?.also { className ->
|
||||
DexKitData.SimpleItemProcessorClass = className.toClass()
|
||||
DexKitData.SimpleItemProcessorClass_OnClickMethod =
|
||||
findMethod {
|
||||
matcher {
|
||||
declaredClass = className
|
||||
paramTypes(kotlinFunction0)
|
||||
returnType = UnitType.name
|
||||
returnType = Void.TYPE.name
|
||||
usingNumbers(2)
|
||||
}
|
||||
}.firstOrNull()?.getMethodInstance(classLoader)
|
||||
}.singleOrNull()?.getMethodInstance(classLoader)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -221,8 +217,14 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
* remainScreenOn、cancelRemainScreenOn
|
||||
*
|
||||
* 这两个方法一个是挂起电源锁常驻亮屏 - 一个是停止常驻亮屏
|
||||
*
|
||||
* - 在 QQ NT 版本中完全移除了 BaseChatPie 类 - 所以不再处理
|
||||
*/
|
||||
private fun hookQQBaseChatPie() {
|
||||
if (hasBaseChatPieClass.not()) {
|
||||
HookEntry.isHookClientSupport = true
|
||||
return YLog.debug("Start for QQ NT version,.")
|
||||
}
|
||||
/**
|
||||
* 打印警告信息
|
||||
* @param index 序号
|
||||
@@ -237,23 +239,23 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
|
||||
/** Hook CoreService QQ、TIM */
|
||||
private fun hookCoreService() {
|
||||
CoreServiceClass?.apply {
|
||||
CoreServiceClass?.resolve()?.optional()?.apply {
|
||||
if (isQQ) {
|
||||
method {
|
||||
firstMethodOrNull {
|
||||
name = "startTempService"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "startCoreService"
|
||||
param(BooleanType)
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
parameters(Boolean::class)
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onStartCommand"
|
||||
param(IntentClass, IntType, IntType)
|
||||
}.ignored().hook().replaceTo(any = 2)
|
||||
parameters(Intent::class, Int::class, Int::class)
|
||||
}?.hook()?.replaceTo(any = 2)
|
||||
}
|
||||
method {
|
||||
firstMethodOrNull {
|
||||
name = "onCreate"
|
||||
}.ignored().hook().after {
|
||||
}?.hook()?.after {
|
||||
if (ConfigData.isEnableKillQQTimCoreService)
|
||||
instance<Service>().apply {
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
@@ -262,10 +264,10 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
CoreService_KernelServiceClass?.apply {
|
||||
method {
|
||||
CoreService_KernelServiceClass?.resolve()?.optional()?.apply {
|
||||
firstMethodOrNull {
|
||||
name = "onCreate"
|
||||
}.ignored().hook().after {
|
||||
}?.hook()?.after {
|
||||
if (ConfigData.isEnableKillQQTimCoreServiceChild)
|
||||
instance<Service>().apply {
|
||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||
@@ -273,10 +275,10 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
YLog.debug("Shutdown CoreService\$KernelService OK!")
|
||||
}
|
||||
}
|
||||
method {
|
||||
firstMethodOrNull {
|
||||
name = "onStartCommand"
|
||||
param(IntentClass, IntType, IntType)
|
||||
}.ignored().hook().replaceTo(any = 2)
|
||||
parameters(Intent::class, Int::class, Int::class)
|
||||
}?.hook()?.replaceTo(any = 2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,40 +291,46 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
* 旧版本理论上没有这个类
|
||||
*/
|
||||
"${PackageName.QQ}.msf.service.y".toClassOrNull()
|
||||
?.method {
|
||||
?.resolve()
|
||||
?.optional(silent = true)
|
||||
?.firstMethodOrNull {
|
||||
name = "a"
|
||||
param(StringClass, LongType)
|
||||
returnType = UnitType
|
||||
}?.ignored()?.hook()?.intercept()
|
||||
parameters(String::class, Long::class)
|
||||
returnType = Void.TYPE
|
||||
}?.hook()?.intercept()
|
||||
/**
|
||||
* 干掉自动上传服务的电源锁
|
||||
* 每个版本的差异暂未做排查
|
||||
*/
|
||||
"com.tencent.upload.impl.UploadServiceImpl".toClassOrNull()
|
||||
?.method {
|
||||
?.resolve()
|
||||
?.optional(silent = true)
|
||||
?.firstMethodOrNull {
|
||||
name = "acquireWakeLockIfNot"
|
||||
}?.ignored()?.hook()?.intercept()
|
||||
}?.hook()?.intercept()
|
||||
/**
|
||||
* Hook 掉一个一像素保活 Activity 真的我怎么都想不到讯哥的程序员做出这种事情
|
||||
* 这个东西经过测试会在锁屏的时候吊起来,解锁的时候自动 finish(),无限耍流氓耗电
|
||||
* 2022/1/25 后期查证:锁屏界面消息快速回复窗口的解锁后拉起保活界面,也是毒瘤
|
||||
*/
|
||||
"${PackageName.QQ}.activity.QQLSUnlockActivity".toClassOrNull()
|
||||
?.method {
|
||||
?.resolve()
|
||||
?.optional(silent = true)
|
||||
?.firstMethodOrNull {
|
||||
name = "onCreate"
|
||||
param(BundleClass)
|
||||
}?.ignored()?.hook {
|
||||
parameters(Bundle::class)
|
||||
}?.hook {
|
||||
var origDevice = ""
|
||||
before {
|
||||
/** 由于在 onCreate 里有一行判断只要型号是 xiaomi 的设备就开电源锁,所以说这里临时替换成菊花厂 */
|
||||
origDevice = Build.MANUFACTURER
|
||||
if (Build.MANUFACTURER.lowercase() == "xiaomi")
|
||||
BuildClass.field { name = "MANUFACTURER" }.get().set("HUAWEI")
|
||||
Build::class.resolve().firstField { name = "MANUFACTURER" }.set("HUAWEI")
|
||||
}
|
||||
after {
|
||||
instance<Activity>().finish()
|
||||
/** 这里再把型号替换回去 - 不影响应用变量等 Xposed 模块修改的型号 */
|
||||
BuildClass.field { name = "MANUFACTURER" }.get().set(origDevice)
|
||||
Build::class.resolve().firstField { name = "MANUFACTURER" }.set(origDevice)
|
||||
}
|
||||
}
|
||||
/**
|
||||
@@ -332,9 +340,11 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
* 2022/1/25 后期查证:锁屏界面消息快速回复窗口
|
||||
*/
|
||||
VariousClass("${PackageName.QQ}.activity.QQLSActivity\$14", "ktq").toClassOrNull()
|
||||
?.method {
|
||||
?.resolve()
|
||||
?.optional(silent = true)
|
||||
?.firstMethodOrNull {
|
||||
name = "run"
|
||||
}?.ignored()?.hook()?.intercept()
|
||||
}?.hook()?.intercept()
|
||||
/**
|
||||
* 这个是毒瘤核心类
|
||||
* WakeLockMonitor
|
||||
@@ -345,92 +355,98 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
* 👮🏻 经过排查 Play 版本没这个类...... Emmmm 不想说啥了
|
||||
* ✅ 备注:8.9.x 版本已经基本移除了这个功能,没有再发现存在这个类
|
||||
*/
|
||||
"com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor".toClassOrNull()?.apply {
|
||||
method {
|
||||
name = "onHook"
|
||||
param(StringClass, AnyClass, AnyArrayClass, AnyClass)
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "doReport"
|
||||
param("com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor\$WakeLockEntity", IntType)
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "afterHookedMethod"
|
||||
param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "beforeHookedMethod"
|
||||
param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onAppBackground"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onOtherProcReport"
|
||||
param(BundleClass)
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onProcessRun30Min"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onProcessBG5Min"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "writeReport"
|
||||
param(BooleanType)
|
||||
}.ignored().hook().intercept()
|
||||
}
|
||||
"com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor".toClassOrNull()
|
||||
?.resolve()
|
||||
?.optional(silent = true)
|
||||
?.apply {
|
||||
firstMethodOrNull {
|
||||
name = "onHook"
|
||||
parameters(String::class, Any::class, ArrayClass(Any::class), Any::class)
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "doReport"
|
||||
parameters("com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor\$WakeLockEntity", Int::class)
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "afterHookedMethod"
|
||||
parameters("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "beforeHookedMethod"
|
||||
parameters("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onAppBackground"
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onOtherProcReport"
|
||||
parameters(Bundle::class)
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onProcessRun30Min"
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onProcessBG5Min"
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "writeReport"
|
||||
parameters(Boolean::class)
|
||||
}?.hook()?.intercept()
|
||||
}
|
||||
/**
|
||||
* 这个是毒瘤核心操作类
|
||||
* 功能同上、全部拦截
|
||||
* 👮🏻 经过排查 Play 版本也没这个类...... Emmmm 不想说啥了
|
||||
* ✅ 备注:8.9.x 版本已经基本移除了这个功能,没有再发现存在这个类
|
||||
*/
|
||||
"com.tencent.qapmsdk.qqbattery.QQBatteryMonitor".toClassOrNull()?.apply {
|
||||
method {
|
||||
name = "start"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "stop"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "handleMessage"
|
||||
param(MessageClass)
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "startMonitorInner"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onAppBackground"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onAppForeground"
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "setLogWhite"
|
||||
paramCount = 2
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "setCmdWhite"
|
||||
paramCount = 2
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onWriteLog"
|
||||
param(StringClass, StringClass)
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onCmdRequest"
|
||||
param(StringClass)
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "addData"
|
||||
paramCount = 4
|
||||
}.ignored().hook().intercept()
|
||||
method {
|
||||
name = "onGpsScan"
|
||||
paramCount = 2
|
||||
}.ignored().hook().intercept()
|
||||
}
|
||||
"com.tencent.qapmsdk.qqbattery.QQBatteryMonitor".toClassOrNull()
|
||||
?.resolve()
|
||||
?.optional(silent = true)
|
||||
?.apply {
|
||||
firstMethodOrNull {
|
||||
name = "start"
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "stop"
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "handleMessage"
|
||||
parameters(Message::class)
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "startMonitorInner"
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onAppBackground"
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onAppForeground"
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "setLogWhite"
|
||||
parameterCount = 2
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "setCmdWhite"
|
||||
parameterCount = 2
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onWriteLog"
|
||||
parameters(String::class, String::class)
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onCmdRequest"
|
||||
parameters(String::class)
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "addData"
|
||||
parameterCount = 4
|
||||
}?.hook()?.intercept()
|
||||
firstMethodOrNull {
|
||||
name = "onGpsScan"
|
||||
parameterCount = 2
|
||||
}?.hook()?.intercept()
|
||||
}
|
||||
}
|
||||
|
||||
/** Hook QQ 的设置界面添加模块设置入口 (新版) */
|
||||
@@ -448,27 +464,30 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
/** 为了使用图标资源 ID - 这里需要重新注入模块资源防止不生效 */
|
||||
context.injectModuleAppResources()
|
||||
val iconResId = if (context.isQQNightMode()) R.mipmap.ic_tsbattery_entry_night else R.mipmap.ic_tsbattery_entry_day
|
||||
return simpleItemProcessorClass.buildOf(context, R.id.tsbattery_qq_entry_item_id, "TSBattery", iconResId) {
|
||||
param(ContextClass, IntType, CharSequenceClass, IntType)
|
||||
}?.also { entryItem ->
|
||||
return simpleItemProcessorClass.createInstanceOrNull(context, R.id.tsbattery_qq_entry_item_id, "TSBattery", iconResId)?.also { item ->
|
||||
val onClickMethod = DexKitData.SimpleItemProcessorClass_OnClickMethod ?: error("Could not found processor method")
|
||||
val proxyOnClick = Proxy.newProxyInstance(appClassLoader, arrayOf(onClickMethod.parameterTypes[0])) { any, method, args ->
|
||||
if (method.name == "invoke") {
|
||||
context.startModuleSettings()
|
||||
kotlinUnit.toClass().field { name = "INSTANCE" }.get().any()
|
||||
kotlinUnit.toClass().resolve().firstField { name = "INSTANCE" }.get()
|
||||
} else method.invoke(any, args)
|
||||
}; onClickMethod.invoke(entryItem, proxyOnClick)
|
||||
}; onClickMethod.invoke(item, proxyOnClick)
|
||||
} ?: error("Could not create TSBattery entry item")
|
||||
}
|
||||
MainSettingConfigProviderClass?.method {
|
||||
param(ContextClass)
|
||||
returnType = ListClass
|
||||
MainSettingConfigProviderClass?.resolve()?.optional()?.firstMethodOrNull {
|
||||
parameters(Context::class)
|
||||
returnType = List::class
|
||||
}?.hook()?.after {
|
||||
val context = args().first().cast<Context>() ?: return@after
|
||||
val processor = result<MutableList<Any?>>() ?: return@after
|
||||
processor.add(1, processor[0]?.javaClass?.buildOf(arrayListOf<Any>().apply { add(createTSEntryItem(context)) }, "", "") {
|
||||
param(ListClass, CharSequenceClass, CharSequenceClass)
|
||||
})
|
||||
processor.add(
|
||||
1,
|
||||
processor[0]?.javaClass?.createInstanceOrNull(
|
||||
arrayListOf<Any>().apply {
|
||||
add(createTSEntryItem(context))
|
||||
}.toList(), "", ""
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,35 +497,38 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
*/
|
||||
private fun hookQQSettingsUiLegacy(instance: Any?) {
|
||||
/** 当前的顶级 Item 实例 */
|
||||
val formItemRefRoot = instance?.current()?.field {
|
||||
type { it == FormSimpleItemClass || it == FormCommonSingleLineItemClass }.index(num = 1)
|
||||
}?.cast<View?>()
|
||||
val formItemRefRoot = instance?.asResolver()?.optional()?.lastFieldOrNull {
|
||||
type { it == FormSimpleItemClass || it == FormCommonSingleLineItemClass }
|
||||
}?.get<View>()
|
||||
|
||||
/** 创建一个新的 Item */
|
||||
FormSimpleItemClass?.buildOf<View>(instance?.compatToActivity()) { param(ContextClass) }?.current {
|
||||
method {
|
||||
val item = FormSimpleItemClass?.createInstanceAsTypeOrNull<View>(instance?.compatToActivity())
|
||||
item?.asResolver()?.optional()?.apply {
|
||||
firstMethodOrNull {
|
||||
name = "setLeftText"
|
||||
param(CharSequenceClass)
|
||||
}.call("TSBattery")
|
||||
method {
|
||||
parameters(CharSequence::class)
|
||||
}?.invoke("TSBattery")
|
||||
firstMethodOrNull {
|
||||
name = "setRightText"
|
||||
param(CharSequenceClass)
|
||||
}.call(ModuleVersion.toString())
|
||||
method {
|
||||
parameters(CharSequence::class)
|
||||
}?.invoke(ModuleVersion.toString())
|
||||
firstMethodOrNull {
|
||||
name = "setBgType"
|
||||
param(IntType)
|
||||
}.call(if (isQQ) 0 else 2)
|
||||
}?.apply { setOnClickListener { context.startModuleSettings() } }?.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(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
/** 设置圆角和间距 */
|
||||
if (isQQ) (lparam as? ViewGroup.MarginLayoutParams?)?.setMargins(0, 15.dp(item.context), 0, 0)
|
||||
/** 将 Item 添加到设置界面 */
|
||||
listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) }
|
||||
parameters(Int::class)
|
||||
}?.invoke(if (isQQ) 0 else 2)
|
||||
}
|
||||
item ?: return
|
||||
item.setOnClickListener { it.context.startModuleSettings() }
|
||||
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(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
|
||||
/** 设置圆角和间距 */
|
||||
if (isQQ) (lparam as? ViewGroup.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 onHook() {
|
||||
@@ -535,22 +557,22 @@ object QQTIMHooker : YukiBaseHooker() {
|
||||
/** 仅注入主进程 */
|
||||
withProcess(mainProcessName) {
|
||||
/** Hook 跳转事件 */
|
||||
JumpActivityClass?.method {
|
||||
JumpActivityClass?.resolve()?.optional()?.firstMethodOrNull {
|
||||
name = "doOnCreate"
|
||||
param(BundleClass)
|
||||
parameters(Bundle::class)
|
||||
}?.hook()?.after { instance<Activity>().jumpToModuleSettings() }
|
||||
/** Hook 设置界面入口点 */
|
||||
if (isQQNTVersion) hookQQSettingsUi()
|
||||
else {
|
||||
/** 将条目注入设置界面 (Activity) */
|
||||
QQSettingSettingActivityClass?.method {
|
||||
QQSettingSettingActivityClass?.resolve()?.optional()?.firstMethodOrNull {
|
||||
name = "doOnCreate"
|
||||
param(BundleClass)
|
||||
parameters(Bundle::class)
|
||||
}?.hook()?.after { hookQQSettingsUiLegacy(instance) }
|
||||
/** 将条目注入设置界面 (Fragment) */
|
||||
QQSettingSettingFragmentClass?.method {
|
||||
QQSettingSettingFragmentClass?.resolve()?.optional()?.firstMethodOrNull {
|
||||
name = "doOnCreateView"
|
||||
paramCount = 3
|
||||
parameterCount = 3
|
||||
}?.hook()?.after { hookQQSettingsUiLegacy(instance) }
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
@@ -42,14 +42,13 @@ import com.fankes.tsbattery.utils.factory.absoluteStatusBarHeight
|
||||
import com.fankes.tsbattery.utils.factory.appVersionCode
|
||||
import com.fankes.tsbattery.utils.factory.appVersionName
|
||||
import com.fankes.tsbattery.utils.factory.dp
|
||||
import com.highcapable.kavaref.KavaRef.Companion.asResolver
|
||||
import com.highcapable.kavaref.KavaRef.Companion.resolve
|
||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
|
||||
import com.highcapable.yukihookapi.hook.factory.method
|
||||
import com.highcapable.yukihookapi.hook.factory.processName
|
||||
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
|
||||
import com.highcapable.yukihookapi.hook.log.YLog
|
||||
import com.highcapable.yukihookapi.hook.type.android.ViewClass
|
||||
|
||||
/**
|
||||
* Hook 微信
|
||||
@@ -114,24 +113,24 @@ object WeChatHooker : YukiBaseHooker() {
|
||||
/** 仅注入主进程 */
|
||||
withProcess(mainProcessName) {
|
||||
/** Hook 跳转事件 */
|
||||
LauncherUIClass?.method {
|
||||
LauncherUIClass?.resolve()?.optional()?.firstMethodOrNull {
|
||||
name = "onResume"
|
||||
emptyParam()
|
||||
emptyParameters()
|
||||
}?.hook()?.after { instance<Activity>().jumpToModuleSettings(isFinish = false) }
|
||||
/** 向设置界面右上角添加按钮 */
|
||||
SettingsUIClass?.method {
|
||||
SettingsUIClass?.resolve()?.optional()?.firstMethodOrNull {
|
||||
name = "onResume"
|
||||
emptyParam()
|
||||
emptyParameters()
|
||||
}?.hook()?.after {
|
||||
SettingsUIClass?.method {
|
||||
SettingsUIClass?.resolve()?.optional()?.firstMethodOrNull {
|
||||
name = "get_fragment"
|
||||
emptyParam()
|
||||
superClass(isOnlySuperClass = true)
|
||||
}?.get(instance)?.call()?.current()?.method {
|
||||
emptyParameters()
|
||||
superclass()
|
||||
}?.of(instance)?.invoke()?.asResolver()?.optional()?.firstMethodOrNull {
|
||||
name = "getView"
|
||||
emptyParam()
|
||||
returnType = ViewClass
|
||||
superClass(isOnlySuperClass = true)
|
||||
emptyParameters()
|
||||
returnType = View::class
|
||||
superclass()
|
||||
}?.invoke<ViewGroup?>()?.also {
|
||||
it.context?.injectModuleAppResources()
|
||||
runCatching { it.getChildAt(0) as? ViewGroup? }.getOrNull()?.also { rootView ->
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
@@ -24,17 +24,17 @@ package com.fankes.tsbattery.hook.factory
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.PowerManager
|
||||
import androidx.appcompat.app.AppCompatDelegate
|
||||
import com.fankes.tsbattery.const.JumpEvent
|
||||
import com.fankes.tsbattery.const.PackageName
|
||||
import com.fankes.tsbattery.hook.entity.QQTIMHooker.toClass
|
||||
import com.fankes.tsbattery.ui.activity.parasitic.ConfigActivity
|
||||
import com.highcapable.kavaref.KavaRef.Companion.asResolver
|
||||
import com.highcapable.kavaref.KavaRef.Companion.resolve
|
||||
import com.highcapable.kavaref.extension.VariousClass
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import com.highcapable.yukihookapi.hook.bean.VariousClass
|
||||
import com.highcapable.yukihookapi.hook.factory.field
|
||||
import com.highcapable.yukihookapi.hook.factory.method
|
||||
import com.highcapable.yukihookapi.hook.param.PackageParam
|
||||
import com.highcapable.yukihookapi.hook.type.android.PowerManager_WakeLockClass
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
/** QQ、TIM 存在的类 */
|
||||
@@ -47,14 +47,27 @@ private val ThemeUtilClass = VariousClass("${PackageName.QQ}.theme.ThemeUtil", "
|
||||
* QQ、TIM 主题是否为夜间模式
|
||||
* @return [Boolean]
|
||||
*/
|
||||
fun Context.isQQNightMode() = runCatching {
|
||||
ThemeUtilClass.get(classLoader).method {
|
||||
name = "getUserCurrentThemeId"
|
||||
paramCount = 1
|
||||
}.get().string(MobileQQClass.toClass(classLoader)
|
||||
.field { name = "sMobileQQ" }.ignored().get().current(ignored = true)?.field { name = "mAppRuntime" }?.any()
|
||||
).let { it.endsWith("1103") || it.endsWith("2920") }
|
||||
}.getOrNull() ?: false
|
||||
fun Context.isQQNightMode(): Boolean {
|
||||
val sMobileQQ = MobileQQClass.toClass(classLoader).resolve()
|
||||
.optional()
|
||||
.firstFieldOrNull {
|
||||
name = "sMobileQQ"
|
||||
superclass()
|
||||
}?.get()
|
||||
val mAppRuntime = sMobileQQ?.asResolver()
|
||||
?.optional()
|
||||
?.firstFieldOrNull {
|
||||
name = "mAppRuntime"
|
||||
superclass()
|
||||
}?.get()
|
||||
val currentThemeId = ThemeUtilClass.load(classLoader).resolve()
|
||||
.optional()
|
||||
.firstMethodOrNull {
|
||||
name = "getUserCurrentThemeId"
|
||||
parameterCount = 1
|
||||
}?.invokeQuietly<String>(mAppRuntime)
|
||||
return currentThemeId?.let { it.endsWith("1103") || it.endsWith("2920") } == true
|
||||
}
|
||||
|
||||
/** 启动模块设置 [Activity] */
|
||||
fun Context.startModuleSettings() {
|
||||
@@ -81,8 +94,14 @@ fun Activity.jumpToModuleSettings(isFinish: Boolean = true) {
|
||||
|
||||
/** Hook 系统电源锁 */
|
||||
fun PackageParam.hookSystemWakeLock() {
|
||||
PowerManager_WakeLockClass.method {
|
||||
name = "acquireLocked"
|
||||
emptyParam()
|
||||
}.hook().intercept()
|
||||
PowerManager.WakeLock::class.resolve().apply {
|
||||
firstMethod {
|
||||
name = "acquireLocked"
|
||||
emptyParameters()
|
||||
}.hook().intercept()
|
||||
firstMethod {
|
||||
name = "release"
|
||||
parameters(Int::class)
|
||||
}.hook().intercept()
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
@@ -51,6 +51,6 @@ object DexKitHelper {
|
||||
*/
|
||||
fun create(param: PackageParam, initiate: DexKitBridge.() -> Unit) {
|
||||
load()
|
||||
runCatching { DexKitBridge.create(param.appInfo.sourceDir)?.use { initiate(it) } }
|
||||
runCatching { DexKitBridge.create(param.appInfo.sourceDir).use { initiate(it) } }
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
@@ -21,19 +21,22 @@
|
||||
*/
|
||||
package com.fankes.tsbattery.ui.activity.base
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.viewbinding.ViewBinding
|
||||
import com.fankes.tsbattery.R
|
||||
import com.fankes.tsbattery.utils.factory.isNotSystemInDarkMode
|
||||
import com.highcapable.yukihookapi.hook.factory.current
|
||||
import com.highcapable.yukihookapi.hook.factory.method
|
||||
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
|
||||
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.base.ModuleAppCompatActivity
|
||||
import com.highcapable.kavaref.KavaRef.Companion.resolve
|
||||
import com.highcapable.kavaref.extension.genericSuperclassTypeArguments
|
||||
import com.highcapable.kavaref.extension.toClassOrNull
|
||||
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.proxy.ModuleActivity
|
||||
|
||||
abstract class BaseActivity<VB : ViewBinding> : ModuleAppCompatActivity() {
|
||||
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity(), ModuleActivity {
|
||||
|
||||
override val moduleTheme get() = R.style.Theme_TSBattery
|
||||
|
||||
@@ -41,11 +44,14 @@ abstract class BaseActivity<VB : ViewBinding> : ModuleAppCompatActivity() {
|
||||
lateinit var binding: VB
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
delegate.onCreate(savedInstanceState)
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = current().generic()?.argument()?.method {
|
||||
val bindingClass = javaClass.genericSuperclassTypeArguments().firstOrNull()?.toClassOrNull()
|
||||
binding = bindingClass?.resolve()?.optional()?.firstMethodOrNull {
|
||||
name = "inflate"
|
||||
param(LayoutInflaterClass)
|
||||
}?.get()?.invoke<VB>(layoutInflater) ?: error("binding failed")
|
||||
parameters(LayoutInflater::class)
|
||||
}?.invoke<VB>(layoutInflater) ?: error("binding failed")
|
||||
if (Build.VERSION.SDK_INT >= 35) binding.root.fitsSystemWindows = true
|
||||
setContentView(binding.root)
|
||||
/** 隐藏系统的标题栏 */
|
||||
supportActionBar?.hide()
|
||||
@@ -54,6 +60,7 @@ abstract class BaseActivity<VB : ViewBinding> : ModuleAppCompatActivity() {
|
||||
isAppearanceLightStatusBars = isNotSystemInDarkMode
|
||||
isAppearanceLightNavigationBars = isNotSystemInDarkMode
|
||||
}
|
||||
@Suppress("DEPRECATION")
|
||||
ResourcesCompat.getColor(resources, R.color.colorThemeBackground, null).also {
|
||||
window?.statusBarColor = it
|
||||
window?.navigationBarColor = it
|
||||
@@ -65,4 +72,16 @@ abstract class BaseActivity<VB : ViewBinding> : ModuleAppCompatActivity() {
|
||||
|
||||
/** 回调 [onCreate] 方法 */
|
||||
abstract fun onCreate()
|
||||
|
||||
override fun getClassLoader() = delegate.getClassLoader()
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
delegate.onConfigurationChanged(newConfig)
|
||||
super.onConfigurationChanged(newConfig)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
delegate.onRestoreInstanceState(savedInstanceState)
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
}
|
||||
}
|
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017 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 2025/4/21.
|
||||
*/
|
||||
@file:Suppress("DEPRECATION")
|
||||
|
||||
package com.fankes.tsbattery.ui.activity.base
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.widget.FrameLayout
|
||||
import androidx.annotation.CallSuper
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import com.fankes.tsbattery.R
|
||||
import com.fankes.tsbattery.utils.factory.isNotSystemInDarkMode
|
||||
import com.highcapable.yukihookapi.hook.xposed.parasitic.activity.proxy.ModuleActivity
|
||||
import android.R as Android_R
|
||||
|
||||
abstract class BaseActivity2 : AppCompatActivity(), ModuleActivity {
|
||||
|
||||
override val moduleTheme get() = R.style.Theme_TSBattery
|
||||
|
||||
@CallSuper
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
delegate.onCreate(savedInstanceState)
|
||||
super.onCreate(savedInstanceState)
|
||||
/** 隐藏系统的标题栏 */
|
||||
supportActionBar?.hide()
|
||||
/** 初始化沉浸状态栏 */
|
||||
WindowCompat.getInsetsController(window, window.decorView).apply {
|
||||
isAppearanceLightStatusBars = isNotSystemInDarkMode
|
||||
isAppearanceLightNavigationBars = isNotSystemInDarkMode
|
||||
}
|
||||
ResourcesCompat.getColor(resources, R.color.colorThemeBackground, null).also {
|
||||
window?.statusBarColor = it
|
||||
window?.navigationBarColor = it
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) window?.navigationBarDividerColor = it
|
||||
}
|
||||
/** 装载子类 */
|
||||
onCreate()
|
||||
if (Build.VERSION.SDK_INT >= 35) findViewById<FrameLayout>(Android_R.id.content).getChildAt(0)?.fitsSystemWindows = true
|
||||
}
|
||||
|
||||
/** 回调 [onCreate] 方法 */
|
||||
abstract fun onCreate()
|
||||
|
||||
override fun getClassLoader() = delegate.getClassLoader()
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
delegate.onConfigurationChanged(newConfig)
|
||||
super.onConfigurationChanged(newConfig)
|
||||
}
|
||||
|
||||
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
|
||||
delegate.onRestoreInstanceState(savedInstanceState)
|
||||
super.onRestoreInstanceState(savedInstanceState)
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
@@ -23,22 +23,27 @@
|
||||
|
||||
package com.fankes.tsbattery.ui.activity.parasitic
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.animation.LayoutTransition
|
||||
import android.content.res.Resources
|
||||
import android.graphics.Typeface
|
||||
import android.view.Gravity
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.setPadding
|
||||
import androidx.core.view.updateMargins
|
||||
import androidx.core.view.updateMarginsRelative
|
||||
import androidx.core.view.updatePadding
|
||||
import com.fankes.projectpromote.ProjectPromote
|
||||
import com.fankes.tsbattery.R
|
||||
import com.fankes.tsbattery.const.ModuleVersion
|
||||
import com.fankes.tsbattery.const.PackageName
|
||||
import com.fankes.tsbattery.data.ConfigData
|
||||
import com.fankes.tsbattery.data.ConfigData.bind
|
||||
import com.fankes.tsbattery.databinding.ActivityConfigBinding
|
||||
import com.fankes.tsbattery.hook.HookEntry
|
||||
import com.fankes.tsbattery.hook.entity.QQTIMHooker
|
||||
import com.fankes.tsbattery.ui.activity.MainActivity
|
||||
import com.fankes.tsbattery.ui.activity.base.BaseActivity
|
||||
import com.fankes.tsbattery.ui.activity.base.BaseActivity2
|
||||
import com.fankes.tsbattery.utils.factory.appIconOf
|
||||
import com.fankes.tsbattery.utils.factory.appNameOf
|
||||
import com.fankes.tsbattery.utils.factory.appVersionCode
|
||||
@@ -47,98 +52,510 @@ import com.fankes.tsbattery.utils.factory.showDialog
|
||||
import com.fankes.tsbattery.utils.factory.snake
|
||||
import com.fankes.tsbattery.utils.tool.GithubReleaseTool
|
||||
import com.fankes.tsbattery.wrapper.BuildConfigWrapper
|
||||
import com.highcapable.betterandroid.ui.extension.component.base.getThemeAttrsDrawable
|
||||
import com.highcapable.betterandroid.ui.extension.component.startActivity
|
||||
import com.highcapable.betterandroid.ui.extension.graphics.toNormalColorStateList
|
||||
import com.highcapable.betterandroid.ui.extension.view.textColor
|
||||
import com.highcapable.betterandroid.ui.extension.view.tooltipTextCompat
|
||||
import com.highcapable.betterandroid.ui.extension.view.updateMargins
|
||||
import com.highcapable.betterandroid.ui.extension.view.updatePadding
|
||||
import com.highcapable.betterandroid.ui.extension.view.updateTypeface
|
||||
import com.highcapable.hikage.extension.setContentView
|
||||
import com.highcapable.hikage.widget.android.widget.ImageView
|
||||
import com.highcapable.hikage.widget.android.widget.LinearLayout
|
||||
import com.highcapable.hikage.widget.android.widget.TextView
|
||||
import com.highcapable.hikage.widget.androidx.cardview.widget.CardView
|
||||
import com.highcapable.hikage.widget.androidx.core.widget.NestedScrollView
|
||||
import com.highcapable.hikage.widget.com.fankes.tsbattery.ui.widget.MaterialSwitch
|
||||
import com.highcapable.yukihookapi.YukiHookAPI
|
||||
import com.highcapable.yukihookapi.hook.factory.classOf
|
||||
import kotlin.system.exitProcess
|
||||
import android.R as Android_R
|
||||
|
||||
class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
|
||||
class ConfigActivity : BaseActivity2() {
|
||||
|
||||
private lateinit var updateVersionText: TextView
|
||||
private lateinit var needRestartTipText: TextView
|
||||
private lateinit var currentModeText: TextView
|
||||
private lateinit var itemQQTimConfig: LinearLayout
|
||||
|
||||
override fun onCreate() {
|
||||
setContentView {
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(matchParent = true),
|
||||
init = {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
setBackgroundResource(R.color.colorThemeBackground)
|
||||
}
|
||||
) {
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true),
|
||||
init = {
|
||||
gravity = Gravity.CENTER or Gravity.START
|
||||
setPadding(15.dp)
|
||||
}
|
||||
) {
|
||||
ImageView(
|
||||
lparams = LayoutParams(20.dp, 20.dp) {
|
||||
marginStart = 10.dp
|
||||
marginEnd = 20.dp
|
||||
}
|
||||
) {
|
||||
imageTintList = stateColorResource(R.color.colorTextGray)
|
||||
tooltipTextCompat = "返回"
|
||||
setImageResource(R.drawable.ic_back)
|
||||
background = getThemeAttrsDrawable(Android_R.attr.selectableItemBackgroundBorderless)
|
||||
setOnClickListener { finish() }
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams(width = 0) {
|
||||
marginEnd = 2.dp
|
||||
weight = 1f
|
||||
}
|
||||
) {
|
||||
isSingleLine = true
|
||||
textSize = 19f
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
text = "TSBattery 设置 (${appName.trim()})"
|
||||
updateTypeface(Typeface.BOLD)
|
||||
}
|
||||
ImageView(
|
||||
lparams = LayoutParams(23.dp, 23.dp) {
|
||||
marginEnd = 10.dp
|
||||
}
|
||||
) {
|
||||
setPadding(1.dp)
|
||||
imageTintList = stateColorResource(R.color.colorTextGray)
|
||||
tooltipTextCompat = "打开模块主界面"
|
||||
setImageResource(R.drawable.ic_icon)
|
||||
background = getThemeAttrsDrawable(Android_R.attr.selectableItemBackgroundBorderless)
|
||||
setOnClickListener {
|
||||
showDialog {
|
||||
title = "打开模块主界面"
|
||||
msg = "点击确定后将打开模块主界面,如果未安装模块本体将尝试打开寄生界面。"
|
||||
confirmButton {
|
||||
runCatching {
|
||||
startActivity(
|
||||
packageName = BuildConfigWrapper.APPLICATION_ID,
|
||||
activityClass = classOf<MainActivity>().name
|
||||
)
|
||||
}.onFailure {
|
||||
runCatching {
|
||||
startActivity<MainActivity>()
|
||||
}.onFailure { snake(msg = "打开失败,请确认你已安装模块 APP 或在模块更新后重启过$appName\n$it") }
|
||||
}
|
||||
}
|
||||
cancelButton()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NestedScrollView(
|
||||
lparams = LayoutParams(matchParent = true),
|
||||
init = {
|
||||
setFadingEdgeLength(10.dp)
|
||||
isVerticalFadingEdgeEnabled = true
|
||||
isVerticalScrollBarEnabled = false
|
||||
isHorizontalScrollBarEnabled = false
|
||||
}
|
||||
) {
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true),
|
||||
init = {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
layoutTransition = LayoutTransition()
|
||||
updatePadding(bottom = 15.dp)
|
||||
}
|
||||
) {
|
||||
repeat(2) { index ->
|
||||
TextView(
|
||||
lparams = LayoutParams(widthMatchParent = true) {
|
||||
updateMargins(horizontal = 15.dp)
|
||||
updateMargins(bottom = 5.dp)
|
||||
}
|
||||
) {
|
||||
setBackgroundResource(R.drawable.bg_orange_round)
|
||||
setPadding(5.dp)
|
||||
gravity = Gravity.CENTER
|
||||
textSize = 13f
|
||||
textColor = colorResource(R.color.white)
|
||||
text = when (index) {
|
||||
0 -> "点击更新 %1"
|
||||
else -> "新的设置需要重新启动${appName}才能生效"
|
||||
}
|
||||
isVisible = false
|
||||
when (index) {
|
||||
0 -> updateVersionText = this
|
||||
else -> {
|
||||
needRestartTipText = this
|
||||
setOnClickListener {
|
||||
showDialog {
|
||||
title = "需要重新启动"
|
||||
msg = "你必须重新启动${appName}才能使当前更改生效,现在重新启动吗?"
|
||||
confirmButton {
|
||||
cancel()
|
||||
finish()
|
||||
exitProcess(status = 0)
|
||||
}
|
||||
cancelButton(text = "稍后再说") {
|
||||
cancel()
|
||||
it.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true) {
|
||||
updateMargins(horizontal = 15.dp)
|
||||
updateMargins(top = 5.dp)
|
||||
},
|
||||
init = {
|
||||
setBackgroundResource(R.drawable.bg_permotion_round)
|
||||
setPadding(15.dp)
|
||||
gravity = Gravity.CENTER
|
||||
}
|
||||
) {
|
||||
ImageView(
|
||||
lparams = LayoutParams(45.dp, 45.dp) {
|
||||
marginEnd = 15.dp
|
||||
}
|
||||
) {
|
||||
setImageDrawable(appIconOf())
|
||||
}
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true),
|
||||
init = {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
}
|
||||
) {
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true) {
|
||||
bottomMargin = 5.dp
|
||||
gravity = Gravity.CENTER or Gravity.START
|
||||
}
|
||||
) {
|
||||
TextView(
|
||||
lparams = LayoutParams {
|
||||
marginEnd = 7.dp
|
||||
}
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 15f
|
||||
text = appName.trim()
|
||||
}
|
||||
TextView {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
text = "$appVersionName($appVersionCode)"
|
||||
alpha = 0.85f
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams {
|
||||
updateMargins(horizontal = 6.dp)
|
||||
}
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
text = "|"
|
||||
alpha = 0.85f
|
||||
}
|
||||
TextView {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
text = "模块版本:$ModuleVersion"
|
||||
alpha = 0.85f
|
||||
}
|
||||
}
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true),
|
||||
init = {
|
||||
gravity = Gravity.CENTER or Gravity.START
|
||||
}
|
||||
) {
|
||||
CardView(
|
||||
lparams = LayoutParams(13.dp, 13.dp) {
|
||||
marginEnd = 6.dp
|
||||
},
|
||||
init = {
|
||||
setCardBackgroundColor(colorResource(R.color.colorThemeBackground))
|
||||
radius = 50f.dp
|
||||
elevation = 0f
|
||||
}
|
||||
) {
|
||||
ImageView(
|
||||
lparams = LayoutParams(13.dp, 13.dp)
|
||||
) {
|
||||
setImageResource(if (HookEntry.isHookClientSupport)
|
||||
R.drawable.ic_success
|
||||
else R.drawable.ic_error)
|
||||
imageTintList = (if (HookEntry.isHookClientSupport)
|
||||
0xFF26A69A
|
||||
else 0xFFFF7043).toInt().toNormalColorStateList()
|
||||
}
|
||||
}
|
||||
if (!HookEntry.isHookClientSupport)
|
||||
LinearLayout(
|
||||
lparams = LayoutParams {
|
||||
marginEnd = 6.dp
|
||||
},
|
||||
init = {
|
||||
gravity = Gravity.CENTER or Gravity.START
|
||||
}
|
||||
) {
|
||||
TextView {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
alpha = 0.85f
|
||||
text = "未适配"
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams {
|
||||
updateMarginsRelative(start = 6.dp)
|
||||
}
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
text = "|"
|
||||
alpha = 0.85f
|
||||
}
|
||||
}
|
||||
TextView {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
alpha = 0.85f
|
||||
currentModeText = this
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams {
|
||||
updateMarginsRelative(start = 6.dp)
|
||||
}
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
text = "|"
|
||||
alpha = 0.85f
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams {
|
||||
updateMarginsRelative(start = 6.dp)
|
||||
}
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
text = "${YukiHookAPI.Status.Executor.name} API ${YukiHookAPI.Status.Executor.apiLevel}"
|
||||
alpha = 0.85f
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams(widthMatchParent = true) {
|
||||
updateMargins(horizontal = 15.dp)
|
||||
updateMargins(top = 15.dp)
|
||||
}
|
||||
) {
|
||||
setBackgroundResource(R.drawable.bg_permotion_round)
|
||||
setPadding(15.dp)
|
||||
textSize = 12f
|
||||
textColor = colorResource(R.color.colorTextDark)
|
||||
setLineSpacing(10f.dp, 1f)
|
||||
text = "模块只对挂后台锁屏情况下有省电效果,请不要将过多的群提醒,消息通知打开,这样子在使用过程时照样会极其耗电。\n" +
|
||||
"持续常驻使用${appName}依然会耗电,任何软件都是如此,模块是无法帮你做到前台不耗电的。"
|
||||
}
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true) {
|
||||
updateMargins(horizontal = 15.dp)
|
||||
updateMargins(top = 15.dp)
|
||||
},
|
||||
init = {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
}
|
||||
) {
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true),
|
||||
init = {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
gravity = Gravity.CENTER
|
||||
setBackgroundResource(R.drawable.bg_permotion_round)
|
||||
updatePadding(horizontal = 15.dp)
|
||||
updatePadding(top = 10.dp, bottom = 15.dp)
|
||||
}
|
||||
) {
|
||||
MaterialSwitch(
|
||||
lparams = LayoutParams(widthMatchParent = true, height = 35.dp) {
|
||||
bottomMargin = 5.dp
|
||||
}
|
||||
) {
|
||||
text = "停用省电策略"
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 15f
|
||||
bind(ConfigData.DISABLE_ALL_HOOK) {
|
||||
refreshConfigItems()
|
||||
refreshCurrentModeText()
|
||||
showNeedRestartTip()
|
||||
}
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams(widthMatchParent = true)
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
alpha = 0.6f
|
||||
setLineSpacing(6f.dp, 1f)
|
||||
text = "选择停用后模块将关闭所有省电功能,模块停止使用。"
|
||||
}
|
||||
}
|
||||
}
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true) {
|
||||
updateMargins(horizontal = 15.dp)
|
||||
updateMargins(top = 15.dp)
|
||||
},
|
||||
init = {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
itemQQTimConfig = this
|
||||
}
|
||||
) {
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true),
|
||||
init = {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
gravity = Gravity.CENTER
|
||||
setBackgroundResource(R.drawable.bg_permotion_round)
|
||||
updatePadding(horizontal = 15.dp)
|
||||
updatePadding(top = 10.dp, bottom = 15.dp)
|
||||
}
|
||||
) {
|
||||
MaterialSwitch(
|
||||
lparams = LayoutParams(widthMatchParent = true, height = 35.dp) {
|
||||
bottomMargin = 5.dp
|
||||
}
|
||||
) {
|
||||
text = "启用保守模式"
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 15f
|
||||
bind(ConfigData.ENABLE_QQ_TIM_PROTECT_MODE) {
|
||||
refreshCurrentModeText()
|
||||
showNeedRestartTip()
|
||||
}
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams(widthMatchParent = true)
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
alpha = 0.6f
|
||||
setLineSpacing(6f.dp, 1f)
|
||||
text = "此选项默认关闭,默认情况下模块将会干掉${appName}自身的电源锁控制类,开启后模块将只对系统电源锁生效," +
|
||||
"如果你的${appName}视频通话等设置发生了故障,可以尝试开启这个功能。"
|
||||
}
|
||||
}
|
||||
LinearLayout(
|
||||
lparams = LayoutParams(widthMatchParent = true) {
|
||||
topMargin = 15.dp
|
||||
},
|
||||
init = {
|
||||
orientation = LinearLayout.VERTICAL
|
||||
gravity = Gravity.CENTER
|
||||
setBackgroundResource(R.drawable.bg_permotion_round)
|
||||
updatePadding(horizontal = 15.dp)
|
||||
updatePadding(top = 10.dp, bottom = 15.dp)
|
||||
}
|
||||
) {
|
||||
MaterialSwitch(
|
||||
lparams = LayoutParams(widthMatchParent = true, height = 35.dp) {
|
||||
bottomMargin = 5.dp
|
||||
}
|
||||
) {
|
||||
text = "关闭 CoreService"
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 15f
|
||||
bind(ConfigData.ENABLE_KILL_QQ_TIM_CORESERVICE) { showNeedRestartTip() }
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams(widthMatchParent = true) {
|
||||
bottomMargin = 10.dp
|
||||
}
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
alpha = 0.6f
|
||||
setLineSpacing(6f.dp, 1f)
|
||||
text = "关闭后可能会影响消息接收与视频通话,但是会达到省电效果,如果你的系统拥有推送服务 (HMS) 或 (MIPUSH) 可以尝试关闭。"
|
||||
}
|
||||
MaterialSwitch(
|
||||
lparams = LayoutParams(widthMatchParent = true, height = 35.dp) {
|
||||
bottomMargin = 5.dp
|
||||
}
|
||||
) {
|
||||
text = "关闭 CoreService\$KernelService"
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 15f
|
||||
bind(ConfigData.ENABLE_KILLE_QQ_TIM_CORESERVICE_CHILD) { showNeedRestartTip() }
|
||||
}
|
||||
TextView(
|
||||
lparams = LayoutParams(widthMatchParent = true)
|
||||
) {
|
||||
isSingleLine = true
|
||||
textColor = colorResource(R.color.colorTextGray)
|
||||
textSize = 12f
|
||||
alpha = 0.6f
|
||||
setLineSpacing(6f.dp, 1f)
|
||||
text = "这是一个辅助子服务,理论主服务关闭后子服务同样不会被启动,建议在保证消息接收的前提下可以尝试关闭子服务。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 检查更新 */
|
||||
GithubReleaseTool.checkingForUpdate(context = this, ModuleVersion.NAME) { version, function ->
|
||||
binding.updateVersionText.apply {
|
||||
updateVersionText.apply {
|
||||
text = "点击更新 $version"
|
||||
isVisible = true
|
||||
setOnClickListener { function() }
|
||||
}
|
||||
}
|
||||
binding.titleBackIcon.setOnClickListener { finish() }
|
||||
binding.titleModuleIcon.setOnClickListener {
|
||||
showDialog {
|
||||
title = "打开模块主界面"
|
||||
msg = "点击确定后将打开模块主界面,如果未安装模块本体将尝试打开寄生界面。"
|
||||
confirmButton {
|
||||
runCatching {
|
||||
startActivity(Intent().apply {
|
||||
component = ComponentName(BuildConfigWrapper.APPLICATION_ID, MainActivity::class.java.name)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
})
|
||||
}.onFailure {
|
||||
runCatching {
|
||||
startActivity(Intent(this@ConfigActivity, MainActivity::class.java))
|
||||
}.onFailure { snake(msg = "打开失败,请确认你已安装模块 APP 或在模块更新后重启过$appName\n$it") }
|
||||
}
|
||||
}
|
||||
cancelButton()
|
||||
}
|
||||
}
|
||||
binding.titleNameText.text = "TSBattery 设置 (${appName.trim()})"
|
||||
binding.appIcon.setImageDrawable(appIconOf())
|
||||
binding.appName.text = appName.trim()
|
||||
binding.appVersion.text = "$appVersionName($appVersionCode)"
|
||||
binding.moduleVersion.text = ModuleVersion.toString()
|
||||
binding.activeModeIcon.isVisible = HookEntry.isHookClientSupport
|
||||
binding.inactiveModeIcon.isGone = HookEntry.isHookClientSupport
|
||||
binding.unsupportItem.isGone = HookEntry.isHookClientSupport
|
||||
binding.executorInfoText.text = "${YukiHookAPI.Status.Executor.name} API ${YukiHookAPI.Status.Executor.apiLevel}"
|
||||
binding.needRestartTipText.replaceToAppName()
|
||||
binding.needRestartTipText.setOnClickListener {
|
||||
showDialog {
|
||||
title = "需要重新启动"
|
||||
msg = "你必须重新启动${appName}才能使当前更改生效,现在重新启动吗?"
|
||||
confirmButton {
|
||||
cancel()
|
||||
finish()
|
||||
exitProcess(status = 0)
|
||||
}
|
||||
cancelButton(text = "稍后再说") {
|
||||
cancel()
|
||||
it.isVisible = false
|
||||
}
|
||||
}
|
||||
}
|
||||
/** 刷新当前模式文本 */
|
||||
fun refreshCurrentModeText() {
|
||||
binding.currentModeText.text = when {
|
||||
ConfigData.isDisableAllHook -> "模块已停用"
|
||||
packageName == PackageName.WECHAT -> "基础省电模式"
|
||||
ConfigData.isEnableQQTimProtectMode -> "保守模式"
|
||||
else -> "完全模式"
|
||||
}
|
||||
}
|
||||
refreshCurrentModeText()
|
||||
/** 刷新配置条目显示隐藏状态 */
|
||||
fun refreshConfigItems() {
|
||||
binding.itemQqTimConfig.isVisible = packageName != PackageName.WECHAT && ConfigData.isDisableAllHook.not()
|
||||
}
|
||||
refreshConfigItems()
|
||||
binding.infoTipText.replaceToAppName()
|
||||
binding.qqTimProtectTipText.replaceToAppName()
|
||||
binding.disableAllHookSwitch.bind(ConfigData.DISABLE_ALL_HOOK) { refreshConfigItems(); refreshCurrentModeText(); showNeedRestartTip() }
|
||||
binding.qqTimProtectModeSwitch.bind(ConfigData.ENABLE_QQ_TIM_PROTECT_MODE) { refreshCurrentModeText(); showNeedRestartTip() }
|
||||
binding.qqTimCoreServiceSwitch.bind(ConfigData.ENABLE_KILL_QQ_TIM_CORESERVICE) { showNeedRestartTip() }
|
||||
binding.qqTimCoreServiceChildSwitch.bind(ConfigData.ENABLE_KILLE_QQ_TIM_CORESERVICE_CHILD) { showNeedRestartTip() }
|
||||
/** 推广、恰饭 */
|
||||
ProjectPromote.show(activity = this, ModuleVersion.toString())
|
||||
}
|
||||
|
||||
/** 显示需要重新启动提示 */
|
||||
private fun showNeedRestartTip() {
|
||||
binding.needRestartTipText.isVisible = true
|
||||
needRestartTipText.isVisible = true
|
||||
}
|
||||
|
||||
/** 替换占位符到当前 APP 名称 */
|
||||
private fun TextView.replaceToAppName() {
|
||||
text = text.toString().replace("{APP_NAME}", appName)
|
||||
/** 刷新配置条目显示隐藏状态 */
|
||||
private fun refreshConfigItems() {
|
||||
itemQQTimConfig.isVisible = packageName != PackageName.WECHAT && ConfigData.isDisableAllHook.not()
|
||||
}
|
||||
|
||||
/** 刷新当前模式文本 */
|
||||
private fun refreshCurrentModeText() {
|
||||
currentModeText.text = when {
|
||||
ConfigData.isDisableAllHook -> "模块已停用"
|
||||
packageName == PackageName.WECHAT -> "基础省电模式"
|
||||
ConfigData.isEnableQQTimProtectMode -> "保守模式"
|
||||
else -> "完全模式"
|
||||
}
|
||||
}
|
||||
|
||||
/** 重新设置 DPI 防止 QQ、TIM 修改它 */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
@@ -31,8 +31,10 @@ import android.util.AttributeSet
|
||||
import androidx.appcompat.widget.SwitchCompat
|
||||
import com.fankes.tsbattery.utils.factory.dp
|
||||
import com.fankes.tsbattery.utils.factory.isSystemInDarkMode
|
||||
import com.highcapable.hikage.annotation.HikageView
|
||||
import top.defaults.drawabletoolbox.DrawableBuilder
|
||||
|
||||
@HikageView
|
||||
class MaterialSwitch(context: Context, attrs: AttributeSet?) : SwitchCompat(context, attrs) {
|
||||
|
||||
private fun toColors(selected: Int, pressed: Int, normal: Int): ColorStateList {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
|
||||
* Copyright (C) 2017-2023 Fankes Studio(qzmmcn@163.com)
|
||||
* Copyright (C) 2017 Fankes Studio(qzmmcn@163.com)
|
||||
* https://github.com/fankes/TSBattery
|
||||
*
|
||||
* This software is non-free but opensource software: you can redistribute it
|
||||
|
@@ -1,418 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/colorThemeBackground"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.activity.parasitic.ConfigActivity"
|
||||
tools:ignore="HardcodedText,ContentDescription,UnusedAttribute,UselessParent">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center|start"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="15dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingBottom="15dp">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/title_back_icon"
|
||||
style="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginEnd="20dp"
|
||||
android:src="@drawable/ic_back"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="返回" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_name_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="2.5dp"
|
||||
android:layout_weight="1"
|
||||
android:singleLine="true"
|
||||
android:text="@string/app_name"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="19sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/title_module_icon"
|
||||
android:layout_width="23dp"
|
||||
android:layout_height="23dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:padding="1.5dp"
|
||||
android:src="@drawable/ic_icon"
|
||||
android:tint="@color/colorTextGray"
|
||||
android:tooltipText="打开模块主界面" />
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fadingEdgeLength="10dp"
|
||||
android:orientation="vertical"
|
||||
android:requiresFadingEdge="vertical"
|
||||
android:scrollbars="none">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:animateLayoutChanges="true"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="15dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/update_version_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="@drawable/bg_orange_round"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:text="点击更新 %1"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/need_restart_tip_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="@drawable/bg_orange_round"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:text="新的设置需要重新启动{APP_NAME}才能生效"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="13sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal"
|
||||
android:padding="15dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="45dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_marginEnd="15dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:gravity="center|start">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="7.5dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="6dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:text="|"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:text="模块版本:"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/module_version"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="13dp"
|
||||
android:layout_height="13dp"
|
||||
android:layout_marginEnd="6dp"
|
||||
app:cardBackgroundColor="@color/colorThemeBackground"
|
||||
app:cardCornerRadius="50dp"
|
||||
app:cardElevation="0dp">
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/active_mode_icon"
|
||||
android:layout_width="13dp"
|
||||
android:layout_height="13dp"
|
||||
android:src="@drawable/ic_success"
|
||||
android:tint="#FF26A69A"
|
||||
android:visibility="gone" />
|
||||
|
||||
<androidx.constraintlayout.utils.widget.ImageFilterView
|
||||
android:id="@+id/inactive_mode_icon"
|
||||
android:layout_width="13dp"
|
||||
android:layout_height="13dp"
|
||||
android:src="@drawable/ic_error"
|
||||
android:tint="#FF7043"
|
||||
android:visibility="gone" />
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/unsupport_item"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:gravity="center|start"
|
||||
android:visibility="gone">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:text="未适配"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:text="|"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_mode_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:text="|"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/executor_info_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="6dp"
|
||||
android:alpha="0.85"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/info_tip_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:alpha="0.8"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:lineSpacingExtra="10dp"
|
||||
android:padding="15dp"
|
||||
android:text="模块只对挂后台锁屏情况下有省电效果,请不要将过多的群提醒,消息通知打开,这样子在使用过程时照样会极其耗电。\n持续常驻使用{APP_NAME}依然会耗电,任何软件都是如此,模块是无法帮你做到前台不耗电的。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingBottom="15dp">
|
||||
|
||||
<com.fankes.tsbattery.ui.widget.MaterialSwitch
|
||||
android:id="@+id/disable_all_hook_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:alpha="0.6"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="选择停用后模块将关闭所有省电功能,模块停止使用。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/item_qq_tim_config"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginTop="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingRight="15dp">
|
||||
|
||||
<com.fankes.tsbattery.ui.widget.MaterialSwitch
|
||||
android:id="@+id/qq_tim_protect_mode_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:id="@+id/qq_tim_protect_tip_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:alpha="0.6"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="此选项默认关闭,默认情况下模块将会干掉{APP_NAME}自身的电源锁控制类,开启后模块将只对系统电源锁生效,如果你的{APP_NAME}视频通话等设置发生了故障,可以尝试开启这个功能。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="15dp"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:elevation="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:paddingLeft="15dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingRight="15dp"
|
||||
android:paddingBottom="15dp">
|
||||
|
||||
<com.fankes.tsbattery.ui.widget.MaterialSwitch
|
||||
android:id="@+id/qq_tim_core_service_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:text="关闭 CoreService"
|
||||
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="关闭后可能会影响消息接收与视频通话,但是会达到省电效果,如果你的系统拥有推送服务 (HMS) 或 (MIPUSH) 可以尝试关闭。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<com.fankes.tsbattery.ui.widget.MaterialSwitch
|
||||
android:id="@+id/qq_tim_core_service_child_switch"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:text="关闭 CoreService$KernelService"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="15sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:alpha="0.6"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:text="这是一个辅助子服务,理论主服务关闭后子服务同样不会被启动,建议在保证消息接收的前提下可以尝试关闭子服务。"
|
||||
android:textColor="@color/colorTextDark"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</LinearLayout>
|
@@ -635,6 +635,35 @@
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="11sp" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="15dp"
|
||||
android:layout_marginRight="15dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
android:background="@drawable/bg_permotion_round"
|
||||
android:gravity="center|start"
|
||||
android:orientation="horizontal"
|
||||
android:padding="10dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="35dp"
|
||||
android:layout_height="35dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@mipmap/ic_kavaref" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:autoLink="web"
|
||||
android:ellipsize="end"
|
||||
android:lineSpacingExtra="6dp"
|
||||
android:maxLines="2"
|
||||
android:text="此模块使用 KavaRef 强力驱动。\n了解更多 https://github.com/HighCapable/KavaRef"
|
||||
android:textColor="@color/colorTextGray"
|
||||
android:textSize="11sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</LinearLayout>
|
BIN
app/src/main/res/mipmap-xxhdpi/ic_kavaref.png
Normal file
BIN
app/src/main/res/mipmap-xxhdpi/ic_kavaref.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
@@ -1,5 +1,21 @@
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
||||
|
||||
plugins {
|
||||
autowire(libs.plugins.android.application) apply false
|
||||
autowire(libs.plugins.kotlin.android) apply false
|
||||
autowire(libs.plugins.kotlin.ksp) apply false
|
||||
}
|
||||
|
||||
allprojects {
|
||||
tasks.withType<KotlinJvmCompile>().configureEach {
|
||||
compilerOptions {
|
||||
jvmTarget = JvmTarget.JVM_17
|
||||
freeCompilerArgs.addAll(
|
||||
"-Xno-param-assertions",
|
||||
"-Xno-call-assertions",
|
||||
"-Xno-receiver-assertions"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@@ -3,12 +3,11 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||
android.useAndroidX=true
|
||||
android.nonTransitiveRClass=true
|
||||
kotlin.code.style=official
|
||||
kotlin.incremental.useClasspathSnapshot=true
|
||||
# Project Configuration
|
||||
project.name=TSBattery
|
||||
project.android.compileSdk=34
|
||||
project.android.compileSdk=36
|
||||
project.android.minSdk=24
|
||||
project.android.targetSdk=34
|
||||
project.android.targetSdk=36
|
||||
project.app.packageName=com.fankes.tsbattery
|
||||
project.app.versionName="4.4"
|
||||
project.app.versionCode=30
|
||||
|
@@ -22,13 +22,13 @@ repositories:
|
||||
plugins:
|
||||
com.android.application:
|
||||
alias: android-application
|
||||
version: 8.1.2
|
||||
version: 8.12.1
|
||||
org.jetbrains.kotlin.android:
|
||||
alias: kotlin-android
|
||||
version: 1.9.10
|
||||
version: 2.2.10
|
||||
com.google.devtools.ksp:
|
||||
alias: kotlin-ksp
|
||||
version: 1.9.10-1.0.13
|
||||
version: 2.2.10-2.0.2
|
||||
|
||||
libraries:
|
||||
com.fankes.projectpromote:
|
||||
@@ -43,36 +43,52 @@ libraries:
|
||||
rovo89-xposed-api
|
||||
com.highcapable.yukihookapi:
|
||||
api:
|
||||
version: 1.2.0
|
||||
version: 1.3.0
|
||||
ksp-xposed:
|
||||
version-ref: <this>::api
|
||||
com.highcapable.kavaref:
|
||||
kavaref-core:
|
||||
version: 1.0.1
|
||||
kavaref-extension:
|
||||
version: 1.0.1
|
||||
com.highcapable.hikage:
|
||||
hikage-core:
|
||||
version: 1.0.2
|
||||
hikage-compiler:
|
||||
version: 1.0.1
|
||||
hikage-extension:
|
||||
version: 1.0.1
|
||||
hikage-widget-androidx:
|
||||
version: 1.0.1
|
||||
hikage-widget-material:
|
||||
version: 1.0.1
|
||||
org.luckypray:
|
||||
dexkit:
|
||||
version: 2.0.0-rc7
|
||||
version: 2.0.6
|
||||
com.github.duanhong169:
|
||||
drawabletoolbox:
|
||||
version: 1.0.7
|
||||
com.squareup.okhttp3:
|
||||
okhttp:
|
||||
version: 5.0.0-alpha.11
|
||||
version: 5.1.0
|
||||
androidx.core:
|
||||
core-ktx:
|
||||
version: 1.12.0
|
||||
version: 1.17.0
|
||||
androidx.appcompat:
|
||||
appcompat:
|
||||
version: 1.6.1
|
||||
version: 1.7.1
|
||||
com.google.android.material:
|
||||
material:
|
||||
version: 1.10.0
|
||||
version: 1.12.0
|
||||
androidx.constraintlayout:
|
||||
constraintlayout:
|
||||
version: 2.1.4
|
||||
version: 2.2.1
|
||||
androidx.test.ext:
|
||||
junit:
|
||||
version: 1.1.5
|
||||
version: 1.3.0
|
||||
androidx.test.espresso:
|
||||
espresso-core:
|
||||
version: 3.5.1
|
||||
version: 3.7.0
|
||||
junit:
|
||||
junit:
|
||||
version: 4.13.2
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStorePath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
@@ -6,8 +6,8 @@ pluginManagement {
|
||||
}
|
||||
}
|
||||
plugins {
|
||||
id("com.highcapable.sweetdependency") version "1.0.2"
|
||||
id("com.highcapable.sweetproperty") version "1.0.3"
|
||||
id("com.highcapable.sweetdependency") version "1.0.4"
|
||||
id("com.highcapable.sweetproperty") version "1.0.8"
|
||||
}
|
||||
sweetProperty {
|
||||
global {
|
||||
@@ -15,7 +15,11 @@ sweetProperty {
|
||||
permanentKeyValues("GITHUB_CI_COMMIT_ID" to "")
|
||||
generateFrom(ROOT_PROJECT, SYSTEM_ENV)
|
||||
}
|
||||
sourcesCode { includeKeys("GITHUB_CI_COMMIT_ID") }
|
||||
sourcesCode {
|
||||
includeKeys("GITHUB_CI_COMMIT_ID")
|
||||
// 关闭类型自动转换功能,防止一些特殊 "COMMIT ID" 被生成为数值
|
||||
isEnableTypeAutoConversion = false
|
||||
}
|
||||
}
|
||||
rootProject { all { isEnable = false } }
|
||||
}
|
||||
|
Reference in New Issue
Block a user