55 Commits
4.0 ... 4.2

Author SHA1 Message Date
3c30c532a4 Update version to 4.2 | Support many QQ 8.9.x version 2023-01-14 00:37:02 +08:00
8f7772d047 Modify remove localTime function time second format and change description text in GithubReleaseTool 2023-01-14 00:16:45 +08:00
c148a535c8 Modify change promote message in YukiPromoteTool 2023-01-14 00:13:53 +08:00
a5448a2c61 Modify remove "endsWith" method's param name statement 2023-01-14 00:12:55 +08:00
a8a01e8afa Modify change related description text in activity_main 2023-01-14 00:08:34 +08:00
c322c3dc29 Modify change related description text in MainActivity 2023-01-14 00:00:33 +08:00
2e9761f01a Added executor info and change some description text in ConfigActivity, activity_config 2023-01-13 23:57:52 +08:00
0fd1a33533 Modify remove "replace" method's param name statement 2023-01-13 23:20:26 +08:00
e465739f95 Modify remove instanceClass param for hookQQSettingsUI function in QQTIMHooker 2023-01-13 22:38:14 +08:00
52f992a6cd Modify change related description text in activity_config 2023-01-13 22:24:25 +08:00
37be07f11d Modify change isOnFailureThrowToApp to false for onAppLifecycle event in QQTIMHooker 2023-01-13 22:19:53 +08:00
d8d9fc8c41 Modify make HookEntry singleton 2023-01-13 22:13:50 +08:00
f27fdb2f25 Modify merge to YukiHookAPI new usage 2023-01-13 04:56:15 +08:00
3629ca3df5 Update Gradle & Kotlin
- Update Kotlin version to 1.7.22
- Update Gradle version to 7.6
- Update Gradle dependencies
2023-01-13 04:53:45 +08:00
12a1c12f8a Update YukiHookAPI 2023-01-13 04:50:50 +08:00
bc41ac2bdc Fix internal browser X5 kernel issues (cause QQ crashed) 2023-01-12 15:00:52 +08:00
5f13e203f0 Fix WeChat SettingsUI's top right TSBattery icon lost problem when version >= 8.0.28 2023-01-12 03:17:01 +08:00
69a68999a5 Fix not found QQSettingSettingFragment Class when not in Pad Mode (disabled error output) 2023-01-11 02:45:02 +08:00
bc48d59b59 Fix TaiChi activation state lost problem for API version higher than 30 2023-01-02 17:43:24 +08:00
cadf7b8873 Modify support QQ 8.9.28 2023-01-01 01:06:11 +08:00
7f0c8dd2b5 Modify support QQ 8.9.25 2022-12-16 02:21:14 +08:00
67349c45fd Modify support QQ 8.9.23 2022-11-30 22:37:34 +08:00
4ab612d5fa Modify add release channel description, release status description in README 2022-11-26 00:30:31 +08:00
bb4b942dae Added automatic build workflows for Github Actions 2022-11-26 00:29:54 +08:00
ff0931b7bc Modify support QQ 8.9.20 2022-11-18 01:50:26 +08:00
fc42a0ddf0 Modify support QQ 8.9.19 2022-11-08 23:45:27 +08:00
abab096ae0 Modify support QQ 8.9.18 2022-11-03 10:35:47 +08:00
ce8e786b5b Modify change logo url to raw in README 2022-11-03 10:35:32 +08:00
dd6c69b337 Modify remove wrap/part at the end of file 2022-11-03 10:18:47 +08:00
69564cccf6 Update Gradle & PlatformSDK
- Update Kotlin version to 1.7.20
2022-11-03 10:17:50 +08:00
a8c16d7823 Modify support QQ Pad Mode for QQ Settings UI entry item since 8.9.15 2022-10-22 02:00:57 +08:00
3616919978 Update Gradle dependencies 2022-10-22 01:11:11 +08:00
c5dfbcbe0d Modify support QQ 8.9.15 2022-10-22 01:09:32 +08:00
f21e8769e0 Modify change not support version log to warn level in QQTIMHooker 2022-10-21 21:24:57 +08:00
eada17db44 Update Gradle & PlatformSDK
- Update Android Gradle Plugin version to 7.3.1
- Update Kotlin version to 1.7.20
2022-10-20 00:20:13 +08:00
67209859c4 Modify merge to new usage in HookEntry 2022-10-04 07:29:37 +08:00
a65b3c1dbe Update YukiHookAPI 2022-10-04 07:28:56 +08:00
6375aa7844 Update README.md 2022-10-02 22:57:46 +08:00
cbd6fd038d Modify merge all png elements to svg elements 2022-10-02 22:55:44 +08:00
7fcf9228f4 Modify change icon to svg in activity_main 2022-10-02 21:38:49 +08:00
d995c69b5c Fix variable name shadowed bug in QQTIMHooker 2022-10-02 21:26:17 +08:00
376a2a5890 Modify compatible with API 33 2022-10-01 02:16:55 +08:00
e2ff60e2ef Modify standard code naming in FunctionFactory 2022-10-01 00:46:56 +08:00
ad0b6d253a Update YukiHookAPI 2022-09-30 23:47:24 +08:00
76af063ed8 Modify change code note in MainActivity 2022-09-30 22:21:16 +08:00
e0fdf269a0 Modify optimize code style in HookEntry 2022-09-30 22:14:07 +08:00
b1d4cd4017 Added Project icon 2022-09-30 22:10:48 +08:00
1337d7cf31 Update version to 4.1 | Support QQ 8.9.13 2022-09-30 05:18:28 +08:00
8855595b80 Fix Non-Activity dialog destroy problem in DialogBuilderFactory 2022-09-30 05:16:31 +08:00
4bf53efa7a Fix QQ, TIM make Activity DPI deformation problem 2022-09-30 05:06:12 +08:00
7f2e97a94e Modify change Activity Proxy Class from QQSettingSettingActivity to AboutActivity in QQTIMHooker 2022-09-30 04:57:38 +08:00
16e0278369 Modify support QQ、TIM night mode theme 2022-09-30 04:57:17 +08:00
20f6d5529f Update YuiHookAPI 2022-09-30 03:39:29 +08:00
08d7676478 Fix change hook entry inject function try fix some Non-Root Hook Framework not work, such as TaiChi 2022-09-30 00:02:48 +08:00
a67faed81c Modify support QQ 8.9.13 2022-09-29 21:38:31 +08:00
41 changed files with 729 additions and 275 deletions

63
.github/workflows/commit_ci.yml vendored Normal file
View File

@@ -0,0 +1,63 @@
name: Automatic Build on Commit
on:
workflow_dispatch:
push:
branches: [ master ]
paths-ignore:
- '**.md'
- '**.txt'
- '.github/**'
- '!.github/workflows/**'
jobs:
build:
name: Build CI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1
with:
cmake-version: '3.22.1'
- name: Prepare Java 11
uses: actions/setup-java@v3
with:
java-version: 11
java-package: jdk
distribution: 'temurin'
cache: 'gradle'
- name: Cache Gradle Dependencies
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
!~/.gradle/caches/build-cache-*
key: gradle-deps-core-${{ hashFiles('**/build.gradle') }}
restore-keys: |
gradle-deps
- name: Cache Gradle Build
uses: actions/cache@v3
with:
path: |
~/.gradle/caches/build-cache-*
key: gradle-builds-core-${{ github.sha }}
restore-keys: |
gradle-builds
- name: Build with Gradle
run: |
./gradlew :app:assembleDebug
./gradlew :app:assembleRelease
echo "DEBUG_APK_FILE=$(find app/build/outputs/apk/debug -name '*.apk')" >> $GITHUB_ENV
echo "RELEASE_APK_FILE=$(find app/build/outputs/apk/release -name '*.apk')" >> $GITHUB_ENV
- name: Upload Artifacts(debug)
uses: actions/upload-artifact@v3
with:
path: ${{ env.DEBUG_APK_FILE }}
name: app-debug
- name: Upload Artifacts(release)
uses: actions/upload-artifact@v3
with:
path: ${{ env.RELEASE_APK_FILE }}
name: app-release

62
.github/workflows/pull_request_ci.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: Pull Request Checker
on:
pull_request:
branches: [ master ]
paths-ignore:
- '**.md'
- '**.txt'
- '.github/**'
- '!.github/workflows/**'
jobs:
build:
name: Pull request check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup cmake
uses: jwlawson/actions-setup-cmake@v1
with:
cmake-version: '3.22.1'
- name: Prepare Java 11
uses: actions/setup-java@v3
with:
java-version: 11
java-package: jdk
distribution: 'temurin'
cache: 'gradle'
- name: Cache Gradle Dependencies
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
!~/.gradle/caches/build-cache-*
key: gradle-deps-core-${{ hashFiles('**/build.gradle') }}
restore-keys: |
gradle-deps
- name: Cache Gradle Build
uses: actions/cache@v3
with:
path: |
~/.gradle/caches/build-cache-*
key: gradle-builds-core-${{ github.sha }}
restore-keys: |
gradle-builds
- name: Build with Gradle
run: |
./gradlew :app:assembleDebug
./gradlew :app:assembleRelease
echo "DEBUG_APK_FILE=$(find app/build/outputs/apk/debug -name '*.apk')" >> $GITHUB_ENV
echo "RELEASE_APK_FILE=$(find app/build/outputs/apk/release -name '*.apk')" >> $GITHUB_ENV
- name: Upload Artifacts(debug)
uses: actions/upload-artifact@v3
with:
path: ${{ env.DEBUG_APK_FILE }}
name: app-debug
- name: Upload Artifacts(release)
uses: actions/upload-artifact@v3
with:
path: ${{ env.RELEASE_APK_FILE }}
name: app-release

BIN
.idea/icon.png generated Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

6
.idea/kotlinc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="1.7.20" />
</component>
</project>

View File

@@ -2,12 +2,12 @@
[![Blank](https://img.shields.io/badge/build-passing-brightgreen)](https://github.com/fankes/TSBattery)
[![Blank](https://img.shields.io/badge/license-AGPL3.0-blue)](https://github.com/fankes/TSBattery/blob/master/LICENSE)
[![Blank](https://img.shields.io/badge/version-v4.0-green)](https://github.com/fankes/TSBattery/releases)
[![Blank](https://img.shields.io/badge/version-v4.2-green)](https://github.com/fankes/TSBattery/releases)
[![Blank](https://img.shields.io/github/downloads/fankes/TSBattery/total?label=Release)](https://github.com/fankes/TSBattery/releases)
[![Blank](https://img.shields.io/github/downloads/Xposed-Modules-Repo/com.fankes.tsbattery/total?label=LSPosed%20Repo&logo=Android&style=flat&labelColor=F48FB1&logoColor=ffffff)](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)
[![Telegram](https://img.shields.io/badge/Follow-Telegram-blue.svg?logo=telegram)](https://t.me/XiaofangInternet)
<br/><br/>
![banner](https://github.com/fankes/TSBattery/blob/master/banner.png)<br/>
![banner](https://github.com/fankes/TSBattery/blob/master/banner.png?raw=true)<br/>
A new way to save your battery avoid cancer apps hacker it.
TSBattery 是一个旨在使 QQ、TIM、微信 变得更省电的开源 Xposed 模块。
@@ -18,22 +18,49 @@ TSBattery 是一个旨在使 QQ、TIM、微信 变得更省电的开源 Xposed
## 适配说明
- 支持并建议使用 <b>LSPosed</b>(若作用域没有自动出现推荐请勾选 QQ、TIM、微信)
- 支持并建议使用 **LSPosed**(若作用域没有自动出现推荐请勾选 QQ、TIM、微信)
- 可以使用 <b>~~EdXposed~~</b>,但随时停止支持
- 可以使用 **~~EdXposed~~**,但随时停止支持
- <b>太极无极 · 阴</b> 支持性不是很好,建议使用 <b>太极无极 · 阳</b>
- **太极无极 · 阴** 支持性不是很好,建议使用 **太极无极 · 阳****LSPatch (推荐)**
- 支持 <b>Pine</b>(梦境模块) 但是部分功能有限制
- 支持 **Pine**(梦境模块) 但是部分功能有限制
- 请不要使用 <b>~~应用转生~~</b>,发生封号情况后果自负
- 请不要使用 **~~应用转生~~**,发生封号情况后果自负
- 如果微信不能在 **LSPosed** 中生效,请尝试勾选任意包含微信作用域的模块,例如 **微X模块**
## 请勿用于非法用途
- 本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
本模块完全开源免费,如果好用你可以打赏支持开发,但是请不要用于非法用途。
- 本模块发布地址仅有 [Xposed-Modules-Repo](https://github.com/Xposed-Modules-Repo/com.fankes.tsbattery/releases)、
[Release](https://github.com/fankes/TSBattery/releases) 及 [蓝奏云](https://fankes.lanzouy.com/b02zfz3sj),从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
## 发行渠道说明
- [Automatic Build on Commit](https://github.com/fankes/TSBattery/actions/workflows/commit_ci.yml)
上述更新为代码 `commit` 后自动触发,具体更新内容可点击上方的文字前往 **Github Actions** 进行查看,本更新由开源的流程自动编译发布,**不保证其稳定性**,所发布的版本**仅供测试**,且不会特殊说明甚至可能会变更版本号或保持与当前稳定版相同的版本号。
- [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)
上述更新为手动发布的稳定版,具体更新内容可点击上方的文字前往指定的发布页面查看,稳定版的更新将会同时发布到上述地址中,同步更新。
本模块发布地址仅限于上述所列出的地址,从其他非正规渠道下载到的版本或对您造成任何影响均与我们无关。
## 发行状态说明
![Blank](https://img.shields.io/badge/build-passing-brightgreen)
上述状态为当前稳定版与自动构建版本一致或当前代码改动与稳定版无功能差异。
![Blank](https://img.shields.io/badge/build-pending-dbab09)
上述状态为存在自动构建版本和新功能的更新但当前并未发布稳定版,处于预发行状态。
![Blank](https://img.shields.io/badge/build-problem-red)
上述状态为当前发行的稳定版可能存在严重问题但并未及时进行修复且并未发布稳定版。
## 开始贡献

View File

@@ -1,7 +1,7 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.devtools.ksp' version '1.7.10-1.0.6'
id 'com.google.devtools.ksp' version '1.7.22-1.0.8'
}
android {
@@ -59,15 +59,15 @@ android {
dependencies {
compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.1.1'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.1'
implementation 'com.highcapable.yukihookapi:api:1.1.5'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.1.5'
implementation 'com.github.duanhong169:drawabletoolbox:1.0.7'
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.7'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.5.1'
implementation 'com.google.android.material:material:1.6.1'
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}

View File

@@ -11,6 +11,10 @@
<package android:name="com.tencent.mobileqq" />
<package android:name="com.tencent.tim" />
<package android:name="com.tencent.mm" />
<intent>
<action android:name="android.intent.action.MAIN" />
</intent>
</queries>
<application

View File

@@ -24,25 +24,18 @@
package com.fankes.tsbattery.hook
import com.fankes.tsbattery.const.PackageName
import com.fankes.tsbattery.data.ConfigData
import com.fankes.tsbattery.hook.entity.QQTIMHooker
import com.fankes.tsbattery.hook.entity.WeChatHooker
import com.fankes.tsbattery.utils.factory.versionName
import com.highcapable.yukihookapi.annotation.xposed.InjectYukiHookWithXposed
import com.highcapable.yukihookapi.hook.factory.configs
import com.highcapable.yukihookapi.hook.factory.encase
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
import com.highcapable.yukihookapi.hook.param.PackageParam
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
class HookEntry : IYukiHookXposedInit {
companion object {
object HookEntry : IYukiHookXposedInit {
/** 是否完全支持当前版本 */
var isHookClientSupport = true
}
override fun onInit() = configs {
debugLog { tag = "TSBattery" }
@@ -50,31 +43,8 @@ class HookEntry : IYukiHookXposedInit {
isEnableDataChannel = false
}
/**
* 装载对象是否为 QQ、TIM、微信
* @return [Boolean]
*/
private fun PackageParam.isCurrentScope() = packageName.let { it == PackageName.QQ || it == PackageName.TIM || it == PackageName.WECHAT }
override fun onHook() = encase {
loadApp {
if (isCurrentScope()) onAppLifecycle {
attachBaseContext { baseContext, hasCalledSuper ->
if (hasCalledSuper) return@attachBaseContext
ConfigData.init(baseContext)
when (baseContext.packageName) {
PackageName.QQ, PackageName.TIM -> loadHooker(QQTIMHooker.apply { appVersionName = baseContext.versionName })
PackageName.WECHAT -> loadHooker(WeChatHooker)
}
}
onCreate {
when (packageName) {
PackageName.QQ, PackageName.TIM ->
registerModuleAppActivities(proxy = "${PackageName.QQ}.activity.QQSettingSettingActivity")
PackageName.WECHAT -> registerModuleAppActivities(proxy = "${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI")
}
}
}
}
loadApp(PackageName.QQ, PackageName.TIM) { loadHooker(QQTIMHooker) }
loadApp(PackageName.WECHAT, WeChatHooker)
}
}

View File

@@ -23,10 +23,12 @@ package com.fankes.tsbattery.hook.entity
import android.app.Activity
import android.app.Service
import android.content.res.Configuration
import android.os.Build
import android.view.View
import android.view.ViewGroup
import androidx.core.app.ServiceCompat
import androidx.fragment.app.Fragment
import com.fankes.tsbattery.BuildConfig
import com.fankes.tsbattery.const.PackageName
import com.fankes.tsbattery.data.ConfigData
@@ -34,14 +36,15 @@ import com.fankes.tsbattery.hook.HookEntry
import com.fankes.tsbattery.hook.factory.hookSystemWakeLock
import com.fankes.tsbattery.hook.factory.jumpToModuleSettings
import com.fankes.tsbattery.hook.factory.startModuleSettings
import com.fankes.tsbattery.utils.factory.appVersionName
import com.fankes.tsbattery.utils.factory.dp
import com.highcapable.yukihookapi.hook.bean.VariousClass
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.*
import com.highcapable.yukihookapi.hook.log.loggerD
import com.highcapable.yukihookapi.hook.log.loggerE
import com.highcapable.yukihookapi.hook.log.loggerI
import com.highcapable.yukihookapi.hook.log.loggerW
import com.highcapable.yukihookapi.hook.type.android.*
import com.highcapable.yukihookapi.hook.type.java.*
@@ -56,6 +59,12 @@ object QQTIMHooker : YukiBaseHooker() {
/** QQ、TIM 存在的类 */
private const val QQSettingSettingActivityClass = "${PackageName.QQ}.activity.QQSettingSettingActivity"
/** QQ 新版存在的类 (Pad 模式) */
private const val QQSettingSettingFragmentClass = "${PackageName.QQ}.fragment.QQSettingSettingFragment"
/** QQ、TIM 存在的类 */
private const val AboutActivityClass = "${PackageName.QQ}.activity.AboutActivity"
/** QQ、TIM 新版本存在的类 */
private const val FormSimpleItemClass = "${PackageName.QQ}.widget.FormSimpleItem"
@@ -72,6 +81,12 @@ object QQTIMHooker : YukiBaseHooker() {
private val BaseChatPieClass =
VariousClass("${PackageName.QQ}.activity.aio.core.BaseChatPie", "${PackageName.QQ}.activity.BaseChatPie")
/** 一个内部进程的名称 (与 X5 浏览器内核有关) */
private val privilegedProcessName = "$packageName:privileged_process"
/** 默认的 [Configuration] */
var baseConfiguration: Configuration? = null
/**
* 当前是否为 QQ
* @return [Boolean]
@@ -79,7 +94,13 @@ object QQTIMHooker : YukiBaseHooker() {
private val isQQ get() = packageName == PackageName.QQ
/** 当前宿主的版本 */
var appVersionName = "<unknown>"
private var hostVersionName = "<unknown>"
/**
* 通过 [Activity] or [Fragment] 实例得到上下文
* @return [Activity] or null
*/
private fun Any.compatToActivity() = if (this is Activity) this else current().method { name = "getActivity"; superClass() }.invoke()
/**
* 这个类 QQ 的 BaseChatPie 是控制聊天界面的
@@ -99,7 +120,7 @@ object QQTIMHooker : YukiBaseHooker() {
* - ❗Hook 错了方法会造成闪退!
*/
private fun hookQQBaseChatPie() {
if (isQQ) when (appVersionName) {
if (isQQ) when (hostVersionName) {
"8.0.0" -> {
hookBaseChatPie(methodName = "bq")
hookBaseChatPie(methodName = "aL")
@@ -204,9 +225,25 @@ object QQTIMHooker : YukiBaseHooker() {
hookBaseChatPie(methodName = "H3")
hookBaseChatPie(methodName = "N")
}
"8.9.13" -> {
hookBaseChatPie(methodName = "y3")
hookBaseChatPie(methodName = "H")
}
"8.9.15", "8.9.18", "8.9.19", "8.9.20" -> {
hookBaseChatPie(methodName = "w3")
hookBaseChatPie(methodName = "H")
}
"8.9.23", "8.9.25" -> {
hookBaseChatPie(methodName = "z3")
hookBaseChatPie(methodName = "H")
}
"8.9.28" -> {
hookBaseChatPie(methodName = "A3")
hookBaseChatPie(methodName = "H")
}
else -> {
HookEntry.isHookClientSupport = false
loggerD(msg = "$appVersionName not supported!")
loggerW(msg = "$hostVersionName not supported!")
}
}
}
@@ -297,7 +334,7 @@ object QQTIMHooker : YukiBaseHooker() {
injectMember {
method {
name = "a"
param(StringType, LongType)
param(StringClass, LongType)
returnType = UnitType
}
intercept()
@@ -364,7 +401,7 @@ object QQTIMHooker : YukiBaseHooker() {
injectMember {
method {
name = "onHook"
param(StringType, AnyType, AnyArrayClass, AnyType)
param(StringClass, AnyClass, AnyArrayClass, AnyClass)
}
intercept()
}
@@ -467,14 +504,14 @@ object QQTIMHooker : YukiBaseHooker() {
injectMember {
method {
name = "onWriteLog"
param(StringType, StringType)
param(StringClass, StringClass)
}
intercept()
}
injectMember {
method {
name = "onCmdRequest"
param(StringType)
param(StringClass)
}
intercept()
}
@@ -495,46 +532,30 @@ object QQTIMHooker : YukiBaseHooker() {
}.ignoredHookClassNotFoundFailure()
}
override fun onHook() {
/** Hook 跳转事件 */
JumpActivityClass.hook {
injectMember {
method {
name = "doOnCreate"
param(BundleClass)
}
afterHook { instance<Activity>().jumpToModuleSettings() }
}
}
/** 将条目注入设置界面 */
QQSettingSettingActivityClass.hook {
injectMember {
method {
name = "doOnCreate"
param(BundleClass)
}
afterHook {
/**
* Hook QQ 的设置界面添加模块设置入口
* @param instance 当前设置界面实例
*/
private fun hookQQSettingsUI(instance: Any?) {
/** 当前的顶级 Item 实例 */
val formItemRefRoot = field {
type(FormSimpleItemClass).index(num = 1)
}.ignored().get(instance).cast() ?: field {
type(FormCommonSingleLineItemClass).index(num = 1)
}.ignored().get(instance).cast<View?>()
val formItemRefRoot = instance?.current()?.field {
type { it.name == FormSimpleItemClass || it.name == FormCommonSingleLineItemClass }.index(num = 1)
}?.cast<View?>()
/** 创建一个新的 Item */
FormSimpleItemClass.toClassOrNull()?.buildOf<View>(instance) { param(ContextClass) }?.current {
FormSimpleItemClass.toClassOrNull()?.buildOf<View>(instance?.compatToActivity()) { param(ContextClass) }?.current {
method {
name = "setLeftText"
param(CharSequenceType)
param(CharSequenceClass)
}.call("TSBattery")
method {
name = "setRightText"
param(CharSequenceType)
}.call(BuildConfig.VERSION_NAME)
param(CharSequenceClass)
}.call("${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})")
method {
name = "setBgType"
param(IntType)
}.call(if (isQQ) 0 else 2)
}?.apply { setOnClickListener { instance<Activity>().startModuleSettings() } }?.also { item ->
}?.apply { setOnClickListener { context.startModuleSettings() } }?.also { item ->
var listGroup = formItemRefRoot?.parent as? ViewGroup?
val lparam = (if (listGroup?.childCount == 1) {
listGroup = listGroup.parent as? ViewGroup
@@ -547,16 +568,58 @@ object QQTIMHooker : YukiBaseHooker() {
listGroup?.also { if (isQQ) it.addView(item, lparam) else it.addView(item, 0, lparam) }
}
}
override fun onHook() {
onAppLifecycle(isOnFailureThrowToApp = false) {
attachBaseContext { baseContext, hasCalledSuper ->
if (hasCalledSuper.not()) baseConfiguration = baseContext.resources.configuration
}
}
if (ConfigData.isDisableAllHook) return
/** Hook 系统电源锁 */
onCreate {
hostVersionName = appVersionName
/** 不注入此进程防止部分系统发生 X5 浏览器内核崩溃问题 */
if (processName.startsWith(privilegedProcessName)) return@onCreate
ConfigData.init(context = this)
registerModuleAppActivities(AboutActivityClass)
if (ConfigData.isDisableAllHook) return@onCreate
hookSystemWakeLock()
/** Hook 聊天界面 */
hookQQBaseChatPie()
/** Hook CoreService */
hookCoreService()
/** Hook QQ 不省电的功能 */
hookQQDisgusting()
loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"")
}
}
/** 仅注入主进程 */
withProcess(mainProcessName) {
/** Hook 跳转事件 */
JumpActivityClass.hook {
injectMember {
method {
name = "doOnCreate"
param(BundleClass)
}
afterHook { instance<Activity>().jumpToModuleSettings() }
}
}
/** 将条目注入设置界面 (Activity) */
QQSettingSettingActivityClass.hook {
injectMember {
method {
name = "doOnCreate"
param(BundleClass)
}
afterHook { hookQQSettingsUI(instance) }
}
}
/** 将条目注入设置界面 (Fragment) */
QQSettingSettingFragmentClass.hook {
injectMember {
method {
name = "doOnCreateView"
paramCount = 3
}
afterHook { hookQQSettingsUI(instance) }
}
}.ignoredHookClassNotFoundFailure()
}
}
}

View File

@@ -22,8 +22,10 @@
package com.fankes.tsbattery.hook.entity
import android.app.Activity
import android.content.Context
import android.os.Build
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout
@@ -35,12 +37,16 @@ import com.fankes.tsbattery.hook.factory.hookSystemWakeLock
import com.fankes.tsbattery.hook.factory.jumpToModuleSettings
import com.fankes.tsbattery.hook.factory.startModuleSettings
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.yukihookapi.hook.entity.YukiBaseHooker
import com.highcapable.yukihookapi.hook.factory.current
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
import com.highcapable.yukihookapi.hook.log.loggerD
import com.highcapable.yukihookapi.hook.type.android.BundleClass
import com.highcapable.yukihookapi.hook.factory.processName
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
import com.highcapable.yukihookapi.hook.log.loggerI
import com.highcapable.yukihookapi.hook.type.android.ViewClass
/**
* Hook 微信
@@ -52,10 +58,57 @@ object WeChatHooker : YukiBaseHooker() {
/** 微信存在的类 - 未测试每个版本是否都存在 */
const val LauncherUIClass = "${PackageName.WECHAT}.ui.LauncherUI"
/** 微信存在的类 - 未测试每个版本是否都存在 */
private const val EmptyActivityClass = "${PackageName.WECHAT}.ui.EmptyActivity"
/** 微信存在的类 - 未测试每个版本是否都存在 */
private const val WelabMainUIClass = "${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI"
/** 微信存在的类 - 未测试每个版本是否都存在 */
private const val SettingsUIClass = "${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI"
/** TSBattery 图标 TAG 名称 */
private const val TSBARRERY_ICON_TAG = "tsbattery_icon"
/**
* 创建 TSBattery 图标
* @param context 当前实例
* @return [LinearLayout]
*/
private fun createPreferenceIcon(context: Context) = LinearLayout(context).apply {
tag = TSBARRERY_ICON_TAG
gravity = Gravity.END or Gravity.BOTTOM
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
addView(ImageView(context).apply {
layoutParams = ViewGroup.MarginLayoutParams(20.dp(context), 20.dp(context)).apply {
topMargin = context.absoluteStatusBarHeight + 15.dp(context)
rightMargin = 20.dp(context)
}
setColorFilter(ResourcesCompat.getColor(resources, R.color.colorTextGray, null))
setImageResource(R.drawable.ic_icon)
if (Build.VERSION.SDK_INT >= 26) tooltipText = "TSBattery 设置"
setOnClickListener { context.startModuleSettings() }
})
}
override fun onHook() {
onAppLifecycle {
onCreate {
ConfigData.init(context = this)
registerModuleAppActivities(
when {
EmptyActivityClass.hasClass() -> EmptyActivityClass
WelabMainUIClass.hasClass() -> WelabMainUIClass
else -> error("Inject WeChat Activity Proxy failed, unsupport version $appVersionName($appVersionCode)")
}
)
if (ConfigData.isDisableAllHook) return@onCreate
hookSystemWakeLock()
loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"")
}
}
/** 仅注入主进程 */
withProcess(mainProcessName) {
/** Hook 跳转事件 */
LauncherUIClass.hook {
injectMember {
@@ -70,39 +123,29 @@ object WeChatHooker : YukiBaseHooker() {
SettingsUIClass.hook {
injectMember {
method {
name = "onCreate"
param(BundleClass)
name = "onResume"
emptyParam()
}
afterHook {
method {
name = "get_fragment"
emptyParam()
superClass(isOnlySuperClass = true)
}.get(instance).call()?.current()
?.field { name = "mController" }
?.current()?.method { name = "getContentView" }
?.invoke<ViewGroup>()?.addView(LinearLayout(instance()).apply {
context.injectModuleAppResources()
gravity = Gravity.END or Gravity.BOTTOM
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
addView(ImageView(context).apply {
layoutParams = ViewGroup.MarginLayoutParams(20.dp(context), 20.dp(context)).apply {
topMargin = context.absoluteStatusBarHeight + 15.dp(context)
rightMargin = 20.dp(context)
}
setColorFilter(ResourcesCompat.getColor(resources, R.color.colorTextGray, null))
setImageResource(R.drawable.ic_icon)
if (Build.VERSION.SDK_INT >= 26) tooltipText = "TSBattery 设置"
setOnClickListener { context.startModuleSettings() }
})
})
}.get(instance).call()?.current()?.method {
name = "getView"
emptyParam()
returnType = ViewClass
superClass(isOnlySuperClass = true)
}?.invoke<ViewGroup?>()?.also {
it.context?.injectModuleAppResources()
runCatching { it.getChildAt(0) as? ViewGroup? }.getOrNull()?.also { rootView ->
if (rootView.findViewWithTag<View>(TSBARRERY_ICON_TAG) == null)
rootView.addView(createPreferenceIcon(it.context))
}
}
}
}
}
}
if (ConfigData.isDisableAllHook) return
/** Hook 系统电源锁 */
hookSystemWakeLock()
/** 日志省电大法 */
loggerD(msg = "ウイチャット:それが機能するかどうかはわかりませんでした")
}
}

View File

@@ -24,15 +24,45 @@ package com.fankes.tsbattery.hook.factory
import android.app.Activity
import android.content.Context
import android.content.Intent
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.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 存在的类 */
private const val MobileQQClass = "mqq.app.MobileQQ"
/** QQ、TIM 存在的类 */
private val ThemeUtilClass = VariousClass("${PackageName.QQ}.theme.ThemeUtil", "${PackageName.QQ}.vas.theme.api.ThemeUtil")
/**
* QQ、TIM 主题是否为夜间模式
* @return [Boolean]
*/
private 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
/** 启动模块设置 [Activity] */
fun Context.startModuleSettings() = startActivity(Intent(this, ConfigActivity::class.java))
fun Context.startModuleSettings() {
/** 为 QQ、TIM 适配夜间模式 */
if (packageName == PackageName.QQ || packageName == PackageName.TIM)
AppCompatDelegate.setDefaultNightMode(if (isQQNightMode()) AppCompatDelegate.MODE_NIGHT_YES else AppCompatDelegate.MODE_NIGHT_NO)
startActivity(Intent(this, ConfigActivity::class.java))
}
/**
* 跳转模块设置 [Activity]

View File

@@ -53,7 +53,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
"8.8.20", "8.8.23", "8.8.28", "8.8.33", "8.8.35", "8.8.38", "8.8.50",
"8.8.55", "8.8.68", "8.8.80", "8.8.83", "8.8.85", "8.8.88", "8.8.90",
"8.8.93", "8.8.95", "8.8.98", "8.9.0", "8.9.1", "8.9.2", "8.9.3",
"8.9.5", "8.9.8", "8.9.10"
"8.9.5", "8.9.8", "8.9.10", "8.9.13", "8.9.15", "8.9.18", "8.9.19",
"8.9.20", "8.9.23", "8.9.25", "8.9.28"
)
private val qqSupportVersion by lazy {
if (qqSupportVersions.isNotEmpty()) {
@@ -62,8 +63,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
"${value.trim().let { it.substring(0, it.lastIndex) }}\n\n其余版本请自行测试是否有效。"
} else "empty"
}
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼"
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼"
/** 预发布的版本标识 */
private const val pendingFlag = ""
@@ -81,7 +82,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
/** 判断 Hook 状态 */
if (YukiHookAPI.Status.isModuleActive) {
binding.mainLinStatus.setBackgroundResource(R.drawable.bg_green_round)
binding.mainImgStatus.setImageResource(R.mipmap.ic_success)
binding.mainImgStatus.setImageResource(R.drawable.ic_success)
binding.mainTextStatus.text = "模块已激活"
binding.mainTextApiWay.isVisible = true
refreshActivateExecutor()
@@ -95,9 +96,9 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
noCancelable()
}
/** 设置安装状态 */
binding.mainTextQqVer.text = if (PackageName.QQ.isInstall) version(PackageName.QQ) else "未安装"
binding.mainTextTimVer.text = if (PackageName.TIM.isInstall) version(PackageName.TIM) else "未安装"
binding.mainTextWechatVer.text = if (PackageName.WECHAT.isInstall) version(PackageName.WECHAT) else "未安装"
binding.mainTextQqVer.text = PackageName.QQ.takeIf { isInstall(it) }?.let { appVersionBrandOf(it) } ?: "未安装"
binding.mainTextTimVer.text = PackageName.TIM.takeIf { isInstall(it) }?.let { appVersionBrandOf(it) } ?: "未安装"
binding.mainTextWechatVer.text = PackageName.WECHAT.takeIf { isInstall(it) }?.let { appVersionBrandOf(it) } ?: "未安装"
/** 设置文本 */
binding.mainTextVersion.text = "模块版本:${BuildConfig.VERSION_NAME} $pendingFlag"
binding.mainQqItem.setOnClickListener {
@@ -127,7 +128,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
/** 振动提醒 */
it.performHapticFeedback(HapticFeedbackConstants.KEYBOARD_TAP)
}
/** 获取 Sp 存储的信息 */
/** 设置桌面图标显示隐藏 */
binding.hideIconInLauncherSwitch.isChecked = isLauncherIconShowing.not()
binding.hideIconInLauncherSwitch.setOnCheckedChangeListener { btn, b ->
if (btn.isPressed.not()) return@setOnCheckedChangeListener
@@ -152,7 +153,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
* @param packageName 包名
*/
private fun startModuleSettings(packageName: String) {
if (packageName.isInstall) runCatching {
if (isInstall(packageName)) runCatching {
startActivity(Intent().apply {
component = ComponentName(
packageName,
@@ -166,12 +167,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
/** 刷新模块激活使用的方式 */
private fun refreshActivateExecutor() {
when {
YukiHookAPI.Status.executorVersion > 0 ->
binding.mainTextApiWay.text =
"Activated by ${YukiHookAPI.Status.executorName} API ${YukiHookAPI.Status.executorVersion}"
YukiHookAPI.Status.isTaiChiModuleActive -> binding.mainTextApiWay.text = "Activated by TaiChi"
else -> binding.mainTextApiWay.text = "Activated by anonymous"
}
if (YukiHookAPI.Status.Executor.apiLevel > 0)
binding.mainTextApiWay.text = "Activated by ${YukiHookAPI.Status.Executor.name} API ${YukiHookAPI.Status.Executor.apiLevel}"
else binding.mainTextApiWay.text = "Activated by ${YukiHookAPI.Status.Executor.name}"
}
}

View File

@@ -19,12 +19,13 @@
*
* This file is Created by fankes on 2022/9/28.
*/
@file:Suppress("SetTextI18n")
@file:Suppress("SetTextI18n", "DEPRECATION")
package com.fankes.tsbattery.ui.activity.parasitic
import android.content.ComponentName
import android.content.Intent
import android.content.res.Resources
import android.widget.TextView
import androidx.core.view.isGone
import androidx.core.view.isVisible
@@ -34,10 +35,12 @@ 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.utils.factory.*
import com.fankes.tsbattery.utils.tool.GithubReleaseTool
import com.highcapable.yukihookapi.YukiHookAPI
import kotlin.system.exitProcess
class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
@@ -68,20 +71,21 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
}
}
binding.titleNameText.text = "TSBattery 设置 (${appName.trim()})"
binding.appIcon.setImageDrawable(findAppIcon())
binding.appIcon.setImageDrawable(appIconOf())
binding.appName.text = appName.trim()
binding.appVersion.text = "${versionName}($versionCode)"
binding.appVersion.text = "${appVersionName}($appVersionCode)"
binding.moduleVersion.text = "${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})"
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}"
/** 刷新当前模式文本 */
fun refreshCurrentModeText() {
binding.currentModeText.text = when {
ConfigData.isDisableAllHook -> "模块已停用"
packageName == PackageName.WECHAT -> "仅限基础省电模式"
ConfigData.isEnableQQTimProtectMode -> "已启用保守模式"
else -> "已启用完全模式"
packageName == PackageName.WECHAT -> "基础省电模式"
ConfigData.isEnableQQTimProtectMode -> "保守模式"
else -> "完全模式"
}
}
refreshCurrentModeText()
@@ -114,12 +118,23 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
/** 替换占位符到当前 APP 名称 */
private fun TextView.replaceToAppName() {
text = text.toString().replace(oldValue = "{APP_NAME}", appName)
text = text.toString().replace("{APP_NAME}", appName)
}
/** 重新设置 DPI 防止 QQ、TIM 修改它 */
override fun getResources(): Resources? = super.getResources().apply {
if (packageName == PackageName.QQ || packageName == PackageName.TIM)
QQTIMHooker.baseConfiguration?.also {
updateConfiguration(configuration.apply {
fontScale = it.fontScale
densityDpi = it.densityDpi
}, displayMetrics)
}
}
/**
* 获取当前 APP 名称
* @return [String]
*/
private val appName by lazy { findAppName().let { if (packageName == PackageName.WECHAT) it else " $it " } }
private val appName by lazy { appNameOf().let { if (packageName == PackageName.WECHAT) it else " $it " } }
}

View File

@@ -132,7 +132,7 @@ class DialogBuilder(val context: Context) {
/** 显示对话框 */
@CauseProblemsApi
fun show() {
fun show() = runInSafe {
instance?.create()?.apply {
customLayoutView?.let { setView(it) }
dialogInstance = this

View File

@@ -19,7 +19,7 @@
*
* This file is Created by fankes on 2022/1/7.
*/
@file:Suppress("DEPRECATION", "unused", "DiscouragedApi", "InternalInsetResource")
@file:Suppress("unused", "DiscouragedApi", "InternalInsetResource")
package com.fankes.tsbattery.utils.factory
@@ -29,14 +29,17 @@ import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.PackageInfoFlags
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.widget.Toast
import androidx.core.content.getSystemService
import androidx.core.content.pm.PackageInfoCompat
import com.fankes.tsbattery.BuildConfig
import com.google.android.material.snackbar.Snackbar
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
@@ -66,76 +69,75 @@ val Context.isSystemInDarkMode get() = (resources.configuration.uiMode and Confi
inline val Context.isNotSystemInDarkMode get() = !isSystemInDarkMode
/**
* 得到安装包信息
* @return [PackageInfo]
* 得到 APP 安装包信息 (兼容)
* @param packageName APP 包名
* @param flag [PackageInfoFlags]
* @return [PackageInfo] or null
*/
val Context.packageInfo get() = packageManager?.getPackageInfo(packageName, 0) ?: PackageInfo()
private fun Context.getPackageInfoCompat(packageName: String, flag: Number = 0) = runCatching {
@Suppress("DEPRECATION")
if (Build.VERSION.SDK_INT >= 33)
packageManager?.getPackageInfo(packageName, PackageInfoFlags.of(flag.toLong()))
else packageManager?.getPackageInfo(packageName, flag.toInt())
}.getOrNull()
/**
* 判断应用是否安装
* @return [Boolean]
*/
val String.isInstall
get() = try {
appContext.packageManager.getPackageInfo(
this,
PackageManager.GET_UNINSTALLED_PACKAGES
)
true
} catch (e: Exception) {
false
}
/**
* 得到版本信息
* @return [String]
*/
val Context.versionName get() = packageInfo.versionName ?: ""
/**
* 得到版本号
* 得到 APP 版本号 (兼容 [PackageInfo.getLongVersionCode])
* @return [Int]
*/
val Context.versionCode get() = packageInfo.versionCode
private val PackageInfo.versionCodeCompat get() = PackageInfoCompat.getLongVersionCode(this)
/**
* 得到版本信息与版本号
* @param packageName 包名
* 判断 APP 是否安装
* @param packageName APP 包名
* @return [Boolean]
*/
fun Context.isInstall(packageName: String) = getPackageInfoCompat(packageName)?.let { true } ?: false
/**
* 得到 APP 版本信息
* @return [String]
*/
fun Context.version(packageName: String) = safeOfNothing {
packageManager?.getPackageInfo(packageName, 0)?.let {
"${it.versionName}(${it.versionCode})"
} ?: ""
}
val Context.appVersionName get() = getPackageInfoCompat(packageName)?.versionName ?: ""
/**
* 得到 APP 版本号
* @return [Int]
*/
val Context.appVersionCode get() = getPackageInfoCompat(packageName)?.versionCodeCompat
/**
* 得到 APP 版本信息与版本号
* @param packageName APP 包名 - 默认为当前 APP
* @return [String]
*/
fun Context.appVersionBrandOf(packageName: String = getPackageName()) =
getPackageInfoCompat(packageName)?.let { "${it.versionName}(${it.versionCodeCompat})" } ?: ""
/**
* 得到 APP 名称
* @param name APP 包名 - 默认为当前 APP
* @param packageName APP 包名 - 默认为当前 APP
* @return [String]
*/
fun Context.findAppName(name: String = packageName) =
safeOfNothing { packageManager?.getPackageInfo(name, 0)?.applicationInfo?.loadLabel(packageManager).toString() }
fun Context.appNameOf(packageName: String = getPackageName()) =
getPackageInfoCompat(packageName)?.applicationInfo?.loadLabel(packageManager)?.toString() ?: ""
/**
* 得到 APP 图标
* @param name APP 包名 - 默认为当前 APP
* @param packageName APP 包名 - 默认为当前 APP
* @return [Drawable] or null
*/
fun Context.findAppIcon(name: String = packageName) =
safeOfNull { packageManager?.getPackageInfo(name, 0)?.applicationInfo?.loadIcon(packageManager) }
fun Context.appIconOf(packageName: String = getPackageName()) = getPackageInfoCompat(packageName)?.applicationInfo?.loadIcon(packageManager)
/**
* 网络连接是否正常
* @return [Boolean] 网络是否连接
*/
val isNetWorkSuccess get() = appContext.isNetWorkSuccess
/**
* 网络连接是否正常
* @return [Boolean] 网络是否连接
*/
val Context.isNetWorkSuccess get() = safeOfFalse { getSystemService<ConnectivityManager>()?.activeNetworkInfo != null }
val Context.isNetWorkSuccess
get() = safeOfFalse {
@Suppress("DEPRECATION")
getSystemService<ConnectivityManager>()?.activeNetworkInfo != null
}
/**
* dp 转换为 pxInt
@@ -190,7 +192,7 @@ fun Context.snake(msg: String, actionText: String = "", callback: () -> Unit = {
* @param packageName 包名
*/
fun Context.openSelfSetting(packageName: String = appContext.packageName) = runCatching {
if (packageName.isInstall)
if (isInstall(packageName))
startActivity(Intent().apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS

View File

@@ -103,7 +103,7 @@ object GithubReleaseTool {
(context as? Activity?)?.runOnUiThread {
context.showDialog {
title = "网络不可用"
msg = "模块的联网权限可能已被禁用,请开启联网权限以定期检查更新。"
msg = "应用的联网权限可能已被禁用,请开启联网权限以定期检查更新。"
confirmButton(text = "去开启") { context.openSelfSetting() }
cancelButton()
noCancelable()
@@ -121,10 +121,10 @@ object GithubReleaseTool {
* 格式化时间为本地时区
* @return [String] 本地时区时间
*/
private fun String.localTime() = replace(oldValue = "T", newValue = " ").replace(oldValue = "Z", newValue = "").let {
private fun String.localTime() = replace("T", " ").replace("Z", "").let {
runCatching {
val local = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).apply { timeZone = Calendar.getInstance().timeZone }
val current = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).apply { timeZone = TimeZone.getTimeZone("GMT") }
val local = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ROOT).apply { timeZone = Calendar.getInstance().timeZone }
val current = SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.ROOT).apply { timeZone = TimeZone.getTimeZone("GMT") }
local.format(current.parse(it))
}.getOrNull() ?: it
}

View File

@@ -47,7 +47,7 @@ object YukiPromoteTool {
context.showDialog {
title = "面向开发者的推广"
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
"快来体验 YukiHookAPI这是一个使用 Kotlin 重新构建的高效 Xposed Hook API助你的开发变得更轻松。"
"快来体验 YukiHookAPI这是一个使用 Kotlin 构建的高效 Hook API 与 Xposed 模块解决方案,助你的开发变得更轻松。"
confirmButton(text = "去看看") {
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
saveReaded()

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="150.1dp"
android:height="150dp"
android:viewportWidth="1025"
android:viewportHeight="1024">
<path
android:fillColor="#ffffff"
android:pathData="M983.8,314.4c-25.7,-60.8 -62.5,-115.4 -109.4,-162.3 -46.9,-46.9 -101.5,-83.7 -162.3,-109.4 -62.9,-26.7 -129.9,-40.2 -198.8,-40.2S377.5,16 314.5,42.7C253.8,68.4 199.1,105.2 152.3,152.2c-46.9,46.9 -83.7,101.5 -109.4,162.3 -26.7,62.9 -40.2,129.9 -40.2,198.8s13.5,135.8 40.2,198.8c25.7,60.8 62.5,115.4 109.4,162.3 46.9,46.9 101.5,83.7 162.3,109.4 62.9,26.7 129.9,40.2 198.8,40.2s135.8,-13.5 198.8,-40.2c60.8,-25.7 115.4,-62.5 162.3,-109.4 46.9,-46.9 83.7,-101.5 109.4,-162.3 26.7,-62.9 40.2,-129.9 40.2,-198.8s-13.6,-135.9 -40.3,-198.9zM550.5,768.2c0,21 -17,38 -38,38s-38,-17 -38,-38L474.5,395.6c0,-21 17,-38 38,-38s38,17 38,38v372.6zM510.8,305.5c-29.2,0 -52.7,-23.7 -52.7,-52.7 0,-29.2 23.7,-52.7 52.7,-52.7 29.2,0 52.7,23.7 52.7,52.7 0.1,29.2 -23.6,52.7 -52.7,52.7z" />
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="192dp"
android:height="150.39165dp"
android:viewportWidth="1307"
android:viewportHeight="1024">
<path
android:fillColor="#ffffff"
android:pathData="M268.7,566.5h929.6c36.3,0 72.6,-29 72.6,-72.6 0,-36.3 -29,-72.6 -72.6,-72.6H305l297.8,-297.8c29,-29 29,-72.6 0,-101.7 -29,-29 -72.6,-29 -101.7,0L72.6,450.3c-14.5,14.5 -21.8,36.3 -21.8,58.1 0,21.8 0,43.6 21.8,58.1l428.5,428.5c29,29 72.6,29 101.7,0 29,-29 29,-72.6 0,-101.7l-334.1,-326.8z" />
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="150dp"
android:height="150dp"
android:viewportWidth="896"
android:viewportHeight="896">
<path
android:fillColor="#ffffff"
android:pathData="M448,0C200.58,0 0,200.58 0,448 0,695.42 200.58,896 448,896 695.42,896 896,695.42 896,448 896,200.58 695.42,0 448,0ZM663,612.05a36.11,36.11 0,0 1,0 50.95,36.11 36.11,0 0,1 -50.91,0L448,498.91 284,663a36.11,36.11 0,0 1,-51 0,36.11 36.11,0 0,1 0,-50.91L397,448.09 233,284a36.11,36.11 0,0 1,0 -51,36.11 36.11,0 0,1 51,0l164,164.09 164,-164a36.11,36.11 0,0 1,51 -0.09,36.11 36.11,0 0,1 0,51L498.91,448Z" />
</vector>

View File

@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#00000000"
android:pathData="M19,4H37L26,18H41L17,44L22,25H8L19,4Z"
android:strokeWidth="4"
android:strokeColor="#ffffff"
android:strokeLineJoin="round" />
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="150dp"
android:height="150dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#ffffff"
android:pathData="M512,12.6c-282.8,0 -512,229.2 -512,512 0,226.2 146.7,418.1 350.1,485.8 25.6,4.7 35,-11.1 35,-24.6 0,-12.2 -0.5,-52.5 -0.7,-95.3 -142.5,31 -172.5,-60.4 -172.5,-60.4 -23.3,-59.2 -56.8,-74.9 -56.8,-74.9 -46.5,-31.8 3.5,-31.1 3.5,-31.1 51.4,3.6 78.5,52.8 78.5,52.8 45.7,78.3 119.8,55.6 149,42.6 4.6,-33.1 17.9,-55.7 32.5,-68.5 -113.7,-12.9 -233.3,-56.9 -233.3,-253 0,-55.9 20,-101.6 52.8,-137.4 -5.3,-12.9 -22.8,-65 5,-135.5 0,0 43,-13.8 140.8,52.5 40.8,-11.4 84.6,-17 128.2,-17.2 43.5,0.2 87.3,5.9 128.3,17.2 97.7,-66.2 140.6,-52.5 140.6,-52.5 27.9,70.5 10.3,122.6 5,135.5 32.8,35.8 52.7,81.5 52.7,137.4 0,196.6 -119.8,239.9 -233.8,252.6 18.4,15.9 34.7,47 34.7,94.8 0,68.5 -0.6,123.6 -0.6,140.5 0,13.6 9.2,29.6 35.2,24.6 203.3,-67.8 349.9,-259.6 349.9,-485.8 0,-282.8 -229.2,-512 -512,-512z" />
</vector>

View File

@@ -0,0 +1,25 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#00000000"
android:pathData="M9,18V42H39V18L24,6L9,18Z"
android:strokeWidth="4"
android:strokeColor="#ffffff"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M19,29V42H29V29H19Z"
android:strokeWidth="4"
android:strokeColor="#ffffff"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M9,42H39"
android:strokeWidth="4"
android:strokeColor="#ffffff"
android:strokeLineCap="round" />
</vector>

View File

@@ -5,5 +5,5 @@
android:viewportHeight="1024">
<path
android:fillColor="#FFffff"
android:pathData="M717.48,354.1a33.64,33.64 0,0 0,-17.41 -21.56,37.17 37.17,0 0,0 -28.42,-3.38c-65.54,17.77 -123.8,43.16 -174.69,76.19 -50.89,33.02 -93.9,70.76 -129.02,113.15 -35.12,42.5 -69.48,94.52 -102.96,156.11 -5.22,9.57 -6.66,18.69 -4.35,27.44a33.64,33.64 0,0 0,17.36 21.5,37.17 37.17,0 0,0 28.47,3.43 40.4,40.4 0,0 0,22.94 -17.36c7.99,-11.47 18.69,-28.16 32.1,-50.07 13.41,-21.91 23.04,-37.38 28.77,-46.39 40.29,-59.14 83.05,-104.96 128.15,-137.42 45.16,-32.46 102.4,-58.06 171.78,-76.85a37.58,37.58 0,0 0,22.99 -17.31,34 34,0 0,0 4.35,-27.44l-0.05,-0.05zM928.53,194c9.47,35.58 15.36,72.76 17.82,111.51 5.38,88.52 -9.37,169.47 -44.34,242.84 -35.02,73.37 -87.24,141.31 -156.67,203.93 -67.74,61.75 -142.64,103.73 -224.77,125.95a490.8,490.8 0,0 1,-164.25 16.13c-5.99,-0.36 -24.22,-3.89 -54.68,-10.5 -30.41,-6.66 -49.87,-8.81 -58.27,-6.55 -5.89,1.64 -11.52,9.57 -16.95,23.91 -5.43,14.34 -10.24,29.7 -14.34,46.08 -4.1,16.33 -10.24,32.05 -18.43,47.1 -8.19,15.1 -17.61,24.06 -28.26,26.93a60.47,60.47 0,0 1,-29.7 1.43,52.99 52.99,0 0,1 -20.58,-8.91 245.91,245.91 0,0 1,-26.06 -24.93,30.31 30.31,0 0,1 -7.53,-9.73 34.66,34.66 0,0 1,-2.87 -7.37c-3.48,-13.11 -1.43,-28.42 6.14,-45.93a209.92,209.92 0,0 1,27.6 -46.95c10.85,-13.82 20.58,-27.65 29.03,-41.63 8.5,-13.93 11.78,-24.47 9.93,-31.64 -0.41,-1.48 -4.86,-7.94 -13.36,-19.25a197.63,197.63 0,0 1,-15.36 -22.37,355.48 355.48,0 0,1 -20.48,-57.14 338.43,338.43 0,0 1,-8.86 -130.15,349.9 349.9,0 0,1 37.89,-121.5A504.68,504.68 0,0 1,204.3 351.74a531.35,531.35 0,0 1,97.95 -84.07c18.43,-12.24 43.72,-24.22 75.93,-35.94 32.1,-11.72 64.56,-22.32 97.38,-31.74 32.56,-9.42 65.02,-19.46 97.23,-30a455.37,455.37 0,0 0,86.32 -37.89c25.4,-14.64 43.42,-30.87 54.02,-48.64l11.78,-20.99 12.08,-20.17c7.99,-13.41 11.98,-18.48 11.83,-15.26 -0.1,3.28 5.79,-1.54 17.66,-14.44 11.93,-12.9 19.66,-15.87 23.24,-8.96 14.34,-3.89 29.49,1.23 45.62,15.36 16.13,14.08 30.41,32.72 42.8,55.86 12.44,23.19 23.04,45.21 31.74,66.15 8.7,20.94 14.9,38.55 18.64,52.74l0.05,0.26z"/>
android:pathData="M717.48,354.1a33.64,33.64 0,0 0,-17.41 -21.56,37.17 37.17,0 0,0 -28.42,-3.38c-65.54,17.77 -123.8,43.16 -174.69,76.19 -50.89,33.02 -93.9,70.76 -129.02,113.15 -35.12,42.5 -69.48,94.52 -102.96,156.11 -5.22,9.57 -6.66,18.69 -4.35,27.44a33.64,33.64 0,0 0,17.36 21.5,37.17 37.17,0 0,0 28.47,3.43 40.4,40.4 0,0 0,22.94 -17.36c7.99,-11.47 18.69,-28.16 32.1,-50.07 13.41,-21.91 23.04,-37.38 28.77,-46.39 40.29,-59.14 83.05,-104.96 128.15,-137.42 45.16,-32.46 102.4,-58.06 171.78,-76.85a37.58,37.58 0,0 0,22.99 -17.31,34 34,0 0,0 4.35,-27.44l-0.05,-0.05zM928.53,194c9.47,35.58 15.36,72.76 17.82,111.51 5.38,88.52 -9.37,169.47 -44.34,242.84 -35.02,73.37 -87.24,141.31 -156.67,203.93 -67.74,61.75 -142.64,103.73 -224.77,125.95a490.8,490.8 0,0 1,-164.25 16.13c-5.99,-0.36 -24.22,-3.89 -54.68,-10.5 -30.41,-6.66 -49.87,-8.81 -58.27,-6.55 -5.89,1.64 -11.52,9.57 -16.95,23.91 -5.43,14.34 -10.24,29.7 -14.34,46.08 -4.1,16.33 -10.24,32.05 -18.43,47.1 -8.19,15.1 -17.61,24.06 -28.26,26.93a60.47,60.47 0,0 1,-29.7 1.43,52.99 52.99,0 0,1 -20.58,-8.91 245.91,245.91 0,0 1,-26.06 -24.93,30.31 30.31,0 0,1 -7.53,-9.73 34.66,34.66 0,0 1,-2.87 -7.37c-3.48,-13.11 -1.43,-28.42 6.14,-45.93a209.92,209.92 0,0 1,27.6 -46.95c10.85,-13.82 20.58,-27.65 29.03,-41.63 8.5,-13.93 11.78,-24.47 9.93,-31.64 -0.41,-1.48 -4.86,-7.94 -13.36,-19.25a197.63,197.63 0,0 1,-15.36 -22.37,355.48 355.48,0 0,1 -20.48,-57.14 338.43,338.43 0,0 1,-8.86 -130.15,349.9 349.9,0 0,1 37.89,-121.5A504.68,504.68 0,0 1,204.3 351.74a531.35,531.35 0,0 1,97.95 -84.07c18.43,-12.24 43.72,-24.22 75.93,-35.94 32.1,-11.72 64.56,-22.32 97.38,-31.74 32.56,-9.42 65.02,-19.46 97.23,-30a455.37,455.37 0,0 0,86.32 -37.89c25.4,-14.64 43.42,-30.87 54.02,-48.64l11.78,-20.99 12.08,-20.17c7.99,-13.41 11.98,-18.48 11.83,-15.26 -0.1,3.28 5.79,-1.54 17.66,-14.44 11.93,-12.9 19.66,-15.87 23.24,-8.96 14.34,-3.89 29.49,1.23 45.62,15.36 16.13,14.08 30.41,32.72 42.8,55.86 12.44,23.19 23.04,45.21 31.74,66.15 8.7,20.94 14.9,38.55 18.64,52.74l0.05,0.26z" />
</vector>

View File

@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#00000000"
android:pathData="M24,44C29.523,44 34.523,41.761 38.142,38.142C41.761,34.523 44,29.523 44,24C44,18.477 41.761,13.477 38.142,9.858C34.523,6.239 29.523,4 24,4C18.477,4 13.477,6.239 9.858,9.858C6.239,13.477 4,18.477 4,24C4,29.523 6.239,34.523 9.858,38.142C13.477,41.761 18.477,44 24,44Z"
android:strokeWidth="4"
android:strokeColor="#ffffff"
android:strokeLineJoin="round" />
<path
android:fillColor="#ffffff"
android:fillType="evenOdd"
android:pathData="M24,11C25.381,11 26.5,12.119 26.5,13.5C26.5,14.881 25.381,16 24,16C22.619,16 21.5,14.881 21.5,13.5C21.5,12.119 22.619,11 24,11Z" />
<path
android:fillColor="#00000000"
android:pathData="M24.5,34V20H23.5H22.5"
android:strokeWidth="4"
android:strokeColor="#ffffff"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
<path
android:fillColor="#00000000"
android:pathData="M21,34H28"
android:strokeWidth="4"
android:strokeColor="#ffffff"
android:strokeLineCap="round"
android:strokeLineJoin="round" />
</vector>

View File

@@ -3,12 +3,13 @@
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<group android:scaleX="0.03609375"
<group
android:scaleX="0.03609375"
android:scaleY="0.03609375"
android:translateX="35.52"
android:translateY="35.52">
<path
android:fillColor="#FFffff"
android:pathData="M717.48,354.1a33.64,33.64 0,0 0,-17.41 -21.56,37.17 37.17,0 0,0 -28.42,-3.38c-65.54,17.77 -123.8,43.16 -174.69,76.19 -50.89,33.02 -93.9,70.76 -129.02,113.15 -35.12,42.5 -69.48,94.52 -102.96,156.11 -5.22,9.57 -6.66,18.69 -4.35,27.44a33.64,33.64 0,0 0,17.36 21.5,37.17 37.17,0 0,0 28.47,3.43 40.4,40.4 0,0 0,22.94 -17.36c7.99,-11.47 18.69,-28.16 32.1,-50.07 13.41,-21.91 23.04,-37.38 28.77,-46.39 40.29,-59.14 83.05,-104.96 128.15,-137.42 45.16,-32.46 102.4,-58.06 171.78,-76.85a37.58,37.58 0,0 0,22.99 -17.31,34 34,0 0,0 4.35,-27.44l-0.05,-0.05zM928.53,194c9.47,35.58 15.36,72.76 17.82,111.51 5.38,88.52 -9.37,169.47 -44.34,242.84 -35.02,73.37 -87.24,141.31 -156.67,203.93 -67.74,61.75 -142.64,103.73 -224.77,125.95a490.8,490.8 0,0 1,-164.25 16.13c-5.99,-0.36 -24.22,-3.89 -54.68,-10.5 -30.41,-6.66 -49.87,-8.81 -58.27,-6.55 -5.89,1.64 -11.52,9.57 -16.95,23.91 -5.43,14.34 -10.24,29.7 -14.34,46.08 -4.1,16.33 -10.24,32.05 -18.43,47.1 -8.19,15.1 -17.61,24.06 -28.26,26.93a60.47,60.47 0,0 1,-29.7 1.43,52.99 52.99,0 0,1 -20.58,-8.91 245.91,245.91 0,0 1,-26.06 -24.93,30.31 30.31,0 0,1 -7.53,-9.73 34.66,34.66 0,0 1,-2.87 -7.37c-3.48,-13.11 -1.43,-28.42 6.14,-45.93a209.92,209.92 0,0 1,27.6 -46.95c10.85,-13.82 20.58,-27.65 29.03,-41.63 8.5,-13.93 11.78,-24.47 9.93,-31.64 -0.41,-1.48 -4.86,-7.94 -13.36,-19.25a197.63,197.63 0,0 1,-15.36 -22.37,355.48 355.48,0 0,1 -20.48,-57.14 338.43,338.43 0,0 1,-8.86 -130.15,349.9 349.9,0 0,1 37.89,-121.5A504.68,504.68 0,0 1,204.3 351.74a531.35,531.35 0,0 1,97.95 -84.07c18.43,-12.24 43.72,-24.22 75.93,-35.94 32.1,-11.72 64.56,-22.32 97.38,-31.74 32.56,-9.42 65.02,-19.46 97.23,-30a455.37,455.37 0,0 0,86.32 -37.89c25.4,-14.64 43.42,-30.87 54.02,-48.64l11.78,-20.99 12.08,-20.17c7.99,-13.41 11.98,-18.48 11.83,-15.26 -0.1,3.28 5.79,-1.54 17.66,-14.44 11.93,-12.9 19.66,-15.87 23.24,-8.96 14.34,-3.89 29.49,1.23 45.62,15.36 16.13,14.08 30.41,32.72 42.8,55.86 12.44,23.19 23.04,45.21 31.74,66.15 8.7,20.94 14.9,38.55 18.64,52.74l0.05,0.26z"/>
android:pathData="M717.48,354.1a33.64,33.64 0,0 0,-17.41 -21.56,37.17 37.17,0 0,0 -28.42,-3.38c-65.54,17.77 -123.8,43.16 -174.69,76.19 -50.89,33.02 -93.9,70.76 -129.02,113.15 -35.12,42.5 -69.48,94.52 -102.96,156.11 -5.22,9.57 -6.66,18.69 -4.35,27.44a33.64,33.64 0,0 0,17.36 21.5,37.17 37.17,0 0,0 28.47,3.43 40.4,40.4 0,0 0,22.94 -17.36c7.99,-11.47 18.69,-28.16 32.1,-50.07 13.41,-21.91 23.04,-37.38 28.77,-46.39 40.29,-59.14 83.05,-104.96 128.15,-137.42 45.16,-32.46 102.4,-58.06 171.78,-76.85a37.58,37.58 0,0 0,22.99 -17.31,34 34,0 0,0 4.35,-27.44l-0.05,-0.05zM928.53,194c9.47,35.58 15.36,72.76 17.82,111.51 5.38,88.52 -9.37,169.47 -44.34,242.84 -35.02,73.37 -87.24,141.31 -156.67,203.93 -67.74,61.75 -142.64,103.73 -224.77,125.95a490.8,490.8 0,0 1,-164.25 16.13c-5.99,-0.36 -24.22,-3.89 -54.68,-10.5 -30.41,-6.66 -49.87,-8.81 -58.27,-6.55 -5.89,1.64 -11.52,9.57 -16.95,23.91 -5.43,14.34 -10.24,29.7 -14.34,46.08 -4.1,16.33 -10.24,32.05 -18.43,47.1 -8.19,15.1 -17.61,24.06 -28.26,26.93a60.47,60.47 0,0 1,-29.7 1.43,52.99 52.99,0 0,1 -20.58,-8.91 245.91,245.91 0,0 1,-26.06 -24.93,30.31 30.31,0 0,1 -7.53,-9.73 34.66,34.66 0,0 1,-2.87 -7.37c-3.48,-13.11 -1.43,-28.42 6.14,-45.93a209.92,209.92 0,0 1,27.6 -46.95c10.85,-13.82 20.58,-27.65 29.03,-41.63 8.5,-13.93 11.78,-24.47 9.93,-31.64 -0.41,-1.48 -4.86,-7.94 -13.36,-19.25a197.63,197.63 0,0 1,-15.36 -22.37,355.48 355.48,0 0,1 -20.48,-57.14 338.43,338.43 0,0 1,-8.86 -130.15,349.9 349.9,0 0,1 37.89,-121.5A504.68,504.68 0,0 1,204.3 351.74a531.35,531.35 0,0 1,97.95 -84.07c18.43,-12.24 43.72,-24.22 75.93,-35.94 32.1,-11.72 64.56,-22.32 97.38,-31.74 32.56,-9.42 65.02,-19.46 97.23,-30a455.37,455.37 0,0 0,86.32 -37.89c25.4,-14.64 43.42,-30.87 54.02,-48.64l11.78,-20.99 12.08,-20.17c7.99,-13.41 11.98,-18.48 11.83,-15.26 -0.1,3.28 5.79,-1.54 17.66,-14.44 11.93,-12.9 19.66,-15.87 23.24,-8.96 14.34,-3.89 29.49,1.23 45.62,15.36 16.13,14.08 30.41,32.72 42.8,55.86 12.44,23.19 23.04,45.21 31.74,66.15 8.7,20.94 14.9,38.55 18.64,52.74l0.05,0.26z" />
</group>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="150dp"
android:height="150dp"
android:viewportWidth="1008.7"
android:viewportHeight="1008.7">
<path
android:fillColor="#ffffff"
android:pathData="M504.4,0C226.3,0 0,226.3 0,504.4 0,782.5 226.3,1008.7 504.4,1008.7c278.1,0 504.4,-226.3 504.4,-504.4C1008.7,226.3 782.5,0 504.4,0ZM786.6,407.7 L458.6,743.9c-7.8,8 -18.6,12.6 -29.8,12.6h-0.2c-11.1,0 -21.8,-4.4 -29.7,-12.3L222.5,567.9c-16.4,-16.4 -16.4,-43 0,-59.4 16.4,-16.4 43,-16.4 59.4,0L428.2,654.8 726.5,348.9c16.3,-16.6 42.9,-16.9 59.4,-0.7 16.6,16.2 16.9,42.8 0.7,59.4z" />
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="150dp"
android:height="150dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#ffffff"
android:pathData="m512,794a44.8,44.8 0,1 1,44.8 -44.8,44.8 44.8,0 0,1 -44.8,44.8zM471.9,230.8a40.1,40.1 0,0 1,80.2 0v369.1a40.1,40.1 0,0 1,-79.8 0zM512,0A512,512 0,1 0,1024 512,512 512,0 0,0 512,0Z" />
</vector>

View File

@@ -26,7 +26,7 @@
android:layout_height="20dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="20dp"
android:src="@mipmap/ic_back"
android:src="@drawable/ic_back"
android:tint="@color/colorTextGray"
android:tooltipText="返回" />
@@ -178,7 +178,7 @@
android:id="@+id/active_mode_icon"
android:layout_width="13dp"
android:layout_height="13dp"
android:src="@mipmap/ic_success"
android:src="@drawable/ic_success"
android:tint="#FF26A69A"
android:visibility="gone" />
@@ -186,7 +186,7 @@
android:id="@+id/inactive_mode_icon"
android:layout_width="13dp"
android:layout_height="13dp"
android:src="@mipmap/ic_error"
android:src="@drawable/ic_error"
android:tint="#FF7043"
android:visibility="gone" />
</androidx.cardview.widget.CardView>
@@ -204,7 +204,7 @@
android:layout_height="wrap_content"
android:alpha="0.85"
android:singleLine="true"
android:text="检测到未适配的版本"
android:text="未适配"
android:textColor="@color/colorTextGray"
android:textSize="12sp" />
@@ -227,6 +227,26 @@
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>
@@ -355,7 +375,7 @@
android:layout_marginBottom="10dp"
android:alpha="0.6"
android:lineSpacingExtra="6dp"
android:text="关闭后可能会影响消息接收与视频通话,但是会达到省电效果,如果你的系统拥有推送服务(HMS)或(GMS)可以尝试关闭。"
android:text="关闭后可能会影响消息接收与视频通话,但是会达到省电效果,如果你的系统拥有推送服务 (HMS) 或 (MIPUSH) 可以尝试关闭。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />

View File

@@ -36,7 +36,7 @@
android:layout_height="27dp"
android:layout_marginEnd="5dp"
android:alpha="0.85"
android:src="@mipmap/ic_github"
android:src="@drawable/ic_github"
android:tint="@color/colorTextGray"
android:tooltipText="项目地址" />
</LinearLayout>
@@ -59,7 +59,7 @@
android:layout_height="25dp"
android:layout_marginStart="25dp"
android:layout_marginEnd="5dp"
android:src="@mipmap/ic_warn"
android:src="@drawable/ic_warn"
android:tint="@color/white" />
<LinearLayout
@@ -250,7 +250,7 @@
android:layout_height="15dp"
android:layout_marginEnd="15dp"
android:alpha="0.85"
android:src="@mipmap/ic_about"
android:src="@drawable/ic_about"
android:tint="@color/colorTextDark" />
<TextView
@@ -282,11 +282,21 @@
android:layout_marginBottom="10dp"
android:gravity="center|start">
<ImageView
<androidx.cardview.widget.CardView
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginEnd="10dp"
android:src="@mipmap/ic_shot_icon" />
app:cardBackgroundColor="#FF00BCD4"
app:cardCornerRadius="50dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:padding="2.5dp"
android:src="@drawable/ic_fast_op" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="match_parent"
@@ -364,11 +374,21 @@
android:layout_height="wrap_content"
android:gravity="center|start">
<ImageView
<androidx.cardview.widget.CardView
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginEnd="10dp"
android:src="@mipmap/ic_home" />
app:cardBackgroundColor="#FFFF9800"
app:cardCornerRadius="50dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:padding="2.5dp"
android:src="@drawable/ic_home" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="match_parent"
@@ -428,11 +448,21 @@
android:layout_marginBottom="15dp"
android:gravity="center|start">
<ImageView
<androidx.cardview.widget.CardView
android:layout_width="15dp"
android:layout_height="15dp"
android:layout_marginEnd="10dp"
android:src="@mipmap/ic_help" />
app:cardBackgroundColor="#FF03A9F4"
app:cardCornerRadius="50dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:padding="2dp"
android:src="@drawable/ic_info" />
</androidx.cardview.widget.CardView>
<TextView
android:layout_width="match_parent"
@@ -470,7 +500,7 @@
android:layout_marginBottom="10dp"
android:alpha="0.8"
android:lineSpacingExtra="10dp"
android:text="Q.如何使用?\nA.目前模块支持 LSPosed、LSPatch 以及太极(无极)框架,在太极和 LSPosed 的作用域中,只需勾选 QQ、TIM、微信即可模块可以做到即插即用激活后无需重启手机重启 QQ、TIM 或微信就可以了。"
android:text="Q.如何使用?\nA.目前模块支持 LSPosed、LSPatch 以及太极和一些常见的免 Root 框架,在太极和 LSPosed 的作用域中,只需勾选 QQ、TIM、微信即可模块可以做到即插即用激活后无需重启手机重启 QQ、TIM 或微信就可以了。"
android:textColor="@color/colorTextDark"
android:textSize="12sp" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

View File

@@ -1,12 +1,12 @@
plugins {
id 'com.android.application' version '7.3.0' apply false
id 'com.android.library' version '7.3.0' apply false
id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
id 'com.android.application' version '7.3.1' apply false
id 'com.android.library' version '7.3.1' apply false
id 'org.jetbrains.kotlin.android' version '1.7.22' apply false
}
ext {
appVersionName = "4.0"
appVersionCode = 25
appVersionName = "4.2"
appVersionCode = 27
enableR8 = true
}

View File

@@ -1,6 +1,6 @@
#Wed May 25 04:34:58 CST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME