23 Commits
3.8 ... 3.96

Author SHA1 Message Date
c4de8ae448 Update version to 3.96 | Support QQ 8.8.93 2022-06-04 03:20:38 +08:00
9e092742da Fix GithubReleaseTool to LocalTime 2022-06-04 03:04:54 +08:00
fb27c107f4 Added BuildConfig.VERSION_NAME changed 2022-06-03 23:54:21 +08:00
2be9a3d934 Update version to 3.95 2022-05-31 02:06:35 +08:00
d7dbecb65c Update YukiHookAPI 2022-05-31 02:02:26 +08:00
6c2b3f12b3 Merge code 2022-05-30 02:11:30 +08:00
f1c520586a Merge code 2022-05-30 02:03:14 +08:00
e9c99343c3 Merge code 2022-05-30 01:43:47 +08:00
20de713ffd Merge systemBar support with native 2022-05-30 00:47:47 +08:00
3b78e8a515 Repair Licenses 2022-05-30 00:16:53 +08:00
cf898092bd Update version to 3.9 | Support QQ 8.8.90 2022-05-30 00:10:35 +08:00
251a5151df Added YukiPromoteTool 2022-05-30 00:03:57 +08:00
59e93bc040 Support QQ 8.8.90 2022-05-29 22:51:25 +08:00
d440e85be4 Update YukiHookAPI 2022-05-29 04:12:54 +08:00
e1dc99de01 Update YukiHookAPI 2022-05-27 03:34:16 +08:00
4eab1f7046 Update YukiHookAPI 2022-05-25 04:36:25 +08:00
3fc294dd8d Update YukiHookAPI 2022-05-10 01:52:07 +08:00
a2c06cc201 Update YukiHookAPI 2022-05-06 15:01:27 +08:00
6f39d5fdab Update YukiHookAPI 2022-05-04 14:01:41 +08:00
5ada7585e3 Update YukiHookAPI 2022-05-04 10:14:29 +08:00
31b8f157e5 Update YukiHookAPI 2022-05-04 09:31:13 +08:00
e71f137f74 Update Kotlin version 2022-05-04 07:01:04 +08:00
9e9bbcc8ca Update YukiHookAPI 2022-05-04 07:00:17 +08:00
11 changed files with 148 additions and 74 deletions

View File

@@ -2,7 +2,7 @@
[![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-v3.8-green)](https://github.com/fankes/TSBattery/releases)
[![Blank](https://img.shields.io/badge/version-v3.96-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)

View File

@@ -1,7 +1,7 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'com.google.devtools.ksp' version '1.6.20-1.0.5'
id 'com.google.devtools.ksp' version '1.6.21-1.0.5'
}
android {
@@ -31,6 +31,8 @@ android {
buildTypes {
release {
minifyEnabled rootProject.ext.enableR8
shrinkResources rootProject.ext.enableR8
zipAlignEnabled rootProject.ext.enableR8
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
@@ -50,34 +52,20 @@ android {
buildFeatures {
viewBinding true
}
lintOptions {
checkReleaseBuilds false
}
/** 移除无效耗时 lint Task */
tasks.whenTaskAdded {
task -> if (task.name == "lintVitalRelease") task.enabled = false
}
/** 移除无效耗时 lint Task */
tasks.whenTaskAdded {
task -> if (task.name == "lintVitalAnalyzeRelease") task.enabled = false
}
/** 移除无效耗时 lint Task */
tasks.whenTaskAdded {
task -> if (task.name == "lintVitalReportRelease") task.enabled = false
}
dependencies {
compileOnly 'de.robv.android.xposed:api:82'
implementation 'com.highcapable.yukihookapi:api:1.0.80'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.80'
implementation 'com.highcapable.yukihookapi:api:1.0.92'
ksp 'com.highcapable.yukihookapi:ksp-xposed:1.0.92'
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation 'com.geyifeng.immersionbar:immersionbar:3.2.0'
implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.0'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
implementation 'com.google.android.material:material:1.6.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'

View File

@@ -54,7 +54,7 @@ import com.highcapable.yukihookapi.hook.type.android.*
import com.highcapable.yukihookapi.hook.type.java.*
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
@InjectYukiHookWithXposed
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
class HookEntry : IYukiHookXposedInit {
companion object {
@@ -130,10 +130,14 @@ class HookEntry : IYukiHookXposedInit {
interceptBaseChatPie(methodName = "bk")
interceptBaseChatPie(methodName = "bl")
}
"8.8.83", "8.8.85", "8.8.88" -> {
"8.8.83", "8.8.85", "8.8.88", "8.8.90" -> {
interceptBaseChatPie(methodName = "bl")
interceptBaseChatPie(methodName = "bm")
}
"8.8.93" -> {
interceptBaseChatPie(methodName = "J3")
interceptBaseChatPie(methodName = "S")
}
else -> loggerD(msg = "$version not supported!")
}
}
@@ -400,6 +404,7 @@ class HookEntry : IYukiHookXposedInit {
debugTag = "TSBattery"
isDebug = false
isEnableModulePrefsCache = false
isEnableDataChannel = false
}
override fun onHook() = encase {

View File

@@ -37,10 +37,9 @@ import com.fankes.tsbattery.hook.HookConst.WECHAT_PACKAGE_NAME
import com.fankes.tsbattery.ui.activity.base.BaseActivity
import com.fankes.tsbattery.utils.factory.*
import com.fankes.tsbattery.utils.tool.GithubReleaseTool
import com.highcapable.yukihookapi.hook.factory.isModuleActive
import com.highcapable.yukihookapi.hook.factory.isTaiChiModuleActive
import com.fankes.tsbattery.utils.tool.YukiPromoteTool
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.factory.modulePrefs
import com.highcapable.yukihookapi.hook.xposed.YukiHookModuleStatus
class MainActivity : BaseActivity<ActivityMainBinding>() {
@@ -48,7 +47,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
private const val moduleVersion = BuildConfig.VERSION_NAME
private const val qqSupportVersion =
"8.2.11(Play)、8.8.17、8.8.23、8.8.35、8.8.38、8.8.50、8.8.55、8.8.68、8.8.80、8.8.83、8.8.85、8.8.88 (8.2.11、8.5.5~8.8.88)"
"8.2.11(Play)、8.8.17、8.8.23、8.8.35、8.8.38、8.8.50、8.8.55、8.8.68、8.8.80、8.8.83、8.8.85、8.8.88、8.8.90、8.8.93 (8.2.11、8.5.5~8.8.93)"
private const val timSupportVersion = "2+、3+ (并未完全测试每个版本)"
private const val wechatSupportVersion = "全版本仅支持基础省电,更多功能依然画饼"
@@ -66,7 +65,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
}
}
/** 判断 Hook 状态 */
if (isModuleActive) {
if (YukiHookAPI.Status.isModuleActive) {
binding.mainLinStatus.setBackgroundResource(R.drawable.bg_green_round)
binding.mainImgStatus.setImageResource(R.mipmap.ic_success)
binding.mainTextStatus.text = "模块已激活"
@@ -74,6 +73,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
refreshActivateExecutor()
/** 写入激活的模块版本 */
modulePrefs.put(DataConst.ENABLE_MODULE_VERSION, moduleVersion)
/** 推广、恰饭 */
YukiPromoteTool.promote(context = this)
} else
showDialog {
title = "模块没有激活"
@@ -89,7 +90,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
noCancelable()
}
/** 推荐使用 LSPosed */
if (isTaiChiModuleActive)
if (YukiHookAPI.Status.isTaiChiModuleActive)
showDialog {
title = "兼容性提示"
msg = "若你的设备已 Root推荐使用 LSPosed 激活模块,太极可能会出现模块设置无法保存的问题。"
@@ -201,10 +202,10 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
/** 刷新模块激活使用的方式 */
private fun refreshActivateExecutor() {
when {
YukiHookModuleStatus.executorVersion > 0 ->
YukiHookAPI.Status.executorVersion > 0 ->
binding.mainTextApiWay.text =
"Activated by ${YukiHookModuleStatus.executorName} API ${YukiHookModuleStatus.executorVersion}"
isTaiChiModuleActive -> binding.mainTextApiWay.text = "Activated by TaiChi"
"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"
}
}

View File

@@ -23,12 +23,14 @@
package com.fankes.tsbattery.ui.activity.base
import android.os.Build
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat
import androidx.viewbinding.ViewBinding
import com.fankes.tsbattery.R
import com.fankes.tsbattery.utils.factory.isNotSystemInDarkMode
import com.gyf.immersionbar.ktx.immersionBar
import com.highcapable.yukihookapi.hook.factory.method
import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
import java.lang.reflect.ParameterizedType
@@ -52,13 +54,14 @@ abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {
/** 隐藏系统的标题栏 */
supportActionBar?.hide()
/** 初始化沉浸状态栏 */
immersionBar {
statusBarColor(R.color.colorThemeBackground)
autoDarkModeEnable(true)
statusBarDarkFont(isNotSystemInDarkMode)
navigationBarColor(R.color.colorThemeBackground)
navigationBarDarkIcon(isNotSystemInDarkMode)
fitsSystemWindows(true)
ViewCompat.getWindowInsetsController(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()

View File

@@ -44,10 +44,10 @@ import com.highcapable.yukihookapi.hook.type.android.LayoutInflaterClass
/**
* 构造对话框
* @param isUseBlackTheme 是否使用深色主题
* @param it 对话框方法体
* @param initiate 对话框方法体
*/
fun Context.showDialog(isUseBlackTheme: Boolean = false, it: DialogBuilder.() -> Unit) =
DialogBuilder(this, isUseBlackTheme).apply(it).show()
fun Context.showDialog(isUseBlackTheme: Boolean = false, initiate: DialogBuilder.() -> Unit) =
DialogBuilder(context = this, isUseBlackTheme).apply(initiate).show()
/**
* 对话框构造器
@@ -140,34 +140,34 @@ class DialogBuilder(val context: Context, private val isUseBlackTheme: Boolean)
/**
* 设置对话框确定按钮
* @param text 按钮文本内容
* @param it 点击事件
* @param callback 点击事件
*/
fun confirmButton(text: String = "确定", it: () -> Unit = {}) {
fun confirmButton(text: String = "确定", callback: () -> Unit = {}) {
if (isUsingAndroidX)
runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> it() } }
else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> it() } }
runInSafe { instanceAndroidX?.setPositiveButton(text) { _, _ -> callback() } }
else runInSafe { instanceAndroid?.setPositiveButton(text) { _, _ -> callback() } }
}
/**
* 设置对话框取消按钮
* @param text 按钮文本内容
* @param it 点击事件
* @param callback 点击事件
*/
fun cancelButton(text: String = "取消", it: () -> Unit = {}) {
fun cancelButton(text: String = "取消", callback: () -> Unit = {}) {
if (isUsingAndroidX)
runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> it() } }
else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> it() } }
runInSafe { instanceAndroidX?.setNegativeButton(text) { _, _ -> callback() } }
else runInSafe { instanceAndroid?.setNegativeButton(text) { _, _ -> callback() } }
}
/**
* 设置对话框第三个按钮
* @param text 按钮文本内容
* @param it 点击事件
* @param callback 点击事件
*/
fun neutralButton(text: String = "更多", it: () -> Unit = {}) {
fun neutralButton(text: String = "更多", callback: () -> Unit = {}) {
if (isUsingAndroidX)
runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> it() } }
else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> it() } }
runInSafe { instanceAndroidX?.setNeutralButton(text) { _, _ -> callback() } }
else runInSafe { instanceAndroid?.setNeutralButton(text) { _, _ -> callback() } }
}
/** 取消对话框 */

View File

@@ -137,13 +137,13 @@ fun toast(msg: String) = Toast.makeText(appContext, msg, Toast.LENGTH_SHORT).sho
* 弹出 [Snackbar]
* @param msg 提示内容
* @param actionText 按钮文本 - 不写默认取消按钮
* @param it 按钮事件回调
* @param callback 按钮事件回调
*/
fun Context.snake(msg: String, actionText: String = "", it: () -> Unit = {}) =
fun Context.snake(msg: String, actionText: String = "", callback: () -> Unit = {}) =
Snackbar.make((this as Activity).findViewById(android.R.id.content), msg, Snackbar.LENGTH_LONG).apply {
if (actionText.isBlank()) return@apply
setActionTextColor(if (isSystemInDarkMode) Color.BLACK else Color.WHITE)
setAction(actionText) { it() }
setAction(actionText) { callback() }
}.show()
/**

View File

@@ -19,15 +19,21 @@
*
* This file is Created by fankes on 2022/3/20.
*/
@file:Suppress("NewApi")
package com.fankes.tsbattery.utils.tool
import android.app.Activity
import android.content.Context
import android.icu.text.SimpleDateFormat
import android.icu.util.Calendar
import android.icu.util.TimeZone
import com.fankes.tsbattery.utils.factory.*
import okhttp3.*
import org.json.JSONObject
import java.io.IOException
import java.io.Serializable
import java.util.*
/**
* 获取 Github Release 最新版本工具类
@@ -44,9 +50,9 @@ object GithubReleaseTool {
* 获取最新版本信息
* @param context 实例
* @param version 当前版本
* @param it 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体)
* @param result 成功后回调 - ([String] 最新版本,[Function] 更新对话框方法体)
*/
fun checkingForUpdate(context: Context, version: String, it: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) {
fun checkingForUpdate(context: Context, version: String, result: (String, () -> Unit) -> Unit) = checkingInternetConnect(context) {
OkHttpClient().newBuilder().build().newCall(
Request.Builder()
.url("https://api.github.com/repos/$REPO_AUTHOR/$REPO_NAME/releases/latest")
@@ -61,7 +67,7 @@ object GithubReleaseTool {
name = getString("name"),
htmlUrl = getString("html_url"),
content = getString("body"),
date = getString("published_at").replace(oldValue = "T", newValue = " ").replace(oldValue = "Z", newValue = "")
date = getString("published_at").localTime()
).apply {
fun showUpdate() = context.showDialog {
title = "最新版本 $name"
@@ -72,7 +78,7 @@ object GithubReleaseTool {
}
if (name != version) (context as? Activity?)?.runOnUiThread {
showUpdate()
it(name) { showUpdate() }
result(name) { showUpdate() }
}
}
}
@@ -83,9 +89,9 @@ object GithubReleaseTool {
/**
* 检查网络连接情况
* @param context 实例
* @param it 已连接回调
* @param callback 已连接回调
*/
private fun checkingInternetConnect(context: Context, it: () -> Unit) = runInSafe {
private fun checkingInternetConnect(context: Context, callback: () -> Unit) = runInSafe {
if (isNetWorkSuccess)
OkHttpClient().newBuilder().build().newCall(
Request.Builder()
@@ -106,11 +112,23 @@ object GithubReleaseTool {
}
override fun onResponse(call: Call, response: Response) = runInSafe {
(context as? Activity?)?.runOnUiThread { runInSafe { it() } }
(context as? Activity?)?.runOnUiThread { runInSafe { callback() } }
}
})
}
/**
* 格式化时间为本地时区
* @return [String] 本地时区时间
*/
private fun String.localTime() = replace(oldValue = "T", newValue = " ").replace(oldValue = "Z", newValue = "").let {
runCatching {
val local = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).apply { timeZone = Calendar.getInstance().timeZone }
val current = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ROOT).apply { timeZone = TimeZone.getTimeZone("GMT") }
local.format(current.parse(it))
}.getOrNull() ?: it
}
/**
* Github Release bean
* @param name 版本名称

View File

@@ -0,0 +1,59 @@
/*
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
* Copyright (C) 2019-2022 Fankes Studio(qzmmcn@163.com)
* https://github.com/fankes/TSBattery
*
* This software is non-free but opensource software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* and eula along with this software. If not, see
* <https://www.gnu.org/licenses/>
*
* This file is Created by fankes on 2022/5/30.
*/
package com.fankes.tsbattery.utils.tool
import android.content.Context
import com.fankes.tsbattery.BuildConfig
import com.fankes.tsbattery.utils.factory.openBrowser
import com.fankes.tsbattery.utils.factory.showDialog
import com.highcapable.yukihookapi.YukiHookAPI
import com.highcapable.yukihookapi.hook.factory.modulePrefs
import com.highcapable.yukihookapi.hook.xposed.prefs.data.PrefsData
/**
* [YukiHookAPI] 的自动推广工具类
*/
object YukiPromoteTool {
/** 推广已读存储键值 */
private val YUKI_PROMOTE_READED = PrefsData("yuki_promote_readed_${BuildConfig.VERSION_NAME}", false)
/**
* 显示推广对话框
* @param context 实例
*/
fun promote(context: Context) {
fun saveReaded() = context.modulePrefs.put(YUKI_PROMOTE_READED, value = true)
if (context.modulePrefs.get(YUKI_PROMOTE_READED).not())
context.showDialog {
title = "面向开发者的推广"
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
"快来体验 YukiHookAPI这是一个使用 Kotlin 重新构建的高效 Xposed Hook API助你的开发变得更轻松。"
confirmButton(text = "去看看") {
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
saveReaded()
}
cancelButton(text = "我不是开发者") { saveReaded() }
noCancelable()
}
}
}

View File

@@ -1,12 +1,12 @@
plugins {
id 'com.android.application' version '7.1.3' apply false
id 'com.android.library' version '7.1.3' apply false
id 'org.jetbrains.kotlin.android' version '1.6.20' apply false
id 'com.android.application' version '7.2.0' apply false
id 'com.android.library' version '7.2.0' apply false
id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}
ext {
appVersionName = "3.8"
appVersionCode = 16
appVersionName = "3.96"
appVersionCode = 19
enableR8 = true
}

View File

@@ -1,6 +1,6 @@
#Mon Feb 14 23:27:58 CST 2022
#Wed May 25 04:34:58 CST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME