feat: lots of changes

- add BuildConfigWrapper
- merge to new project promote
- add ci version tag support
- add open parasitic from Host App
This commit is contained in:
2023-09-16 01:10:27 +08:00
parent bd027b37f5
commit c9d49a398f
8 changed files with 166 additions and 98 deletions

View File

@@ -19,8 +19,13 @@
*
* This file is Created by fankes on 2022/9/29.
*/
@file:Suppress("MemberVisibilityCanBePrivate")
package com.fankes.tsbattery.const
import com.fankes.tsbattery.generated.AppProperties
import com.fankes.tsbattery.wrapper.BuildConfigWrapper
/**
* 包名常量定义类
*/
@@ -43,4 +48,27 @@ object JumpEvent {
/** 启动模块设置 */
const val OPEN_MODULE_SETTING = "tsbattery_open_module_settings"
}
/**
* 模块版本常量定义类
*/
object ModuleVersion {
/** 当前 GitHub 提交的 ID (CI 自动构建) */
const val GITHUB_COMMIT_ID = AppProperties.GITHUB_CI_COMMIT_ID
/** 版本名称 */
const val NAME = BuildConfigWrapper.VERSION_NAME
/** 版本号 */
const val CODE = BuildConfigWrapper.VERSION_CODE
/** 是否为 CI 自动构建版本 */
val isCiMode = GITHUB_COMMIT_ID.isNotBlank()
/** 当前版本名称后缀 */
val suffix = GITHUB_COMMIT_ID.let { if (it.isNotBlank()) "-$it" else "" }
override fun toString() = "$NAME$suffix($CODE)"
}

View File

@@ -19,6 +19,8 @@
*
* This file is Created by fankes on 2022/9/29.
*/
@file:Suppress("ConstPropertyName")
package com.fankes.tsbattery.hook.entity
import android.app.Activity
@@ -30,8 +32,8 @@ 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.R
import com.fankes.tsbattery.const.ModuleVersion
import com.fankes.tsbattery.const.PackageName
import com.fankes.tsbattery.data.ConfigData
import com.fankes.tsbattery.hook.HookEntry
@@ -43,13 +45,31 @@ 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.*
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.processName
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
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.*
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.Proxy
/**
@@ -647,7 +667,7 @@ object QQTIMHooker : YukiBaseHooker() {
method {
name = "setRightText"
param(CharSequenceClass)
}.call("${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})")
}.call(ModuleVersion.toString())
method {
name = "setBgType"
param(IntType)
@@ -676,9 +696,10 @@ object QQTIMHooker : YukiBaseHooker() {
/** 不注入此进程防止部分系统发生 X5 浏览器内核崩溃问题 */
if (processName.startsWith(privilegedProcessName)) return@onCreate
ConfigData.init(context = this)
if (isQQNTVersion)
registerModuleAppActivities(GeneralSettingActivityClass)
else registerModuleAppActivities(AboutActivityClass)
registerModuleAppActivities(when {
isQQNTVersion -> GeneralSettingActivityClass
else -> AboutActivityClass
})
if (ConfigData.isDisableAllHook) return@onCreate
hookSystemWakeLock()
hookQQBaseChatPie()

View File

@@ -19,6 +19,8 @@
*
* This file is Created by fankes on 2022/9/29.
*/
@file:Suppress("ConstPropertyName")
package com.fankes.tsbattery.hook.entity
import android.app.Activity
@@ -95,13 +97,11 @@ object WeChatHooker : YukiBaseHooker() {
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)")
}
)
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}\"")

View File

@@ -27,17 +27,24 @@ import android.content.ComponentName
import android.content.Intent
import android.view.HapticFeedbackConstants
import androidx.core.view.isVisible
import com.fankes.tsbattery.BuildConfig
import com.fankes.projectpromote.ProjectPromote
import com.fankes.tsbattery.R
import com.fankes.tsbattery.const.JumpEvent
import com.fankes.tsbattery.const.ModuleVersion
import com.fankes.tsbattery.const.PackageName
import com.fankes.tsbattery.databinding.ActivityMainBinding
import com.fankes.tsbattery.hook.entity.QQTIMHooker
import com.fankes.tsbattery.hook.entity.WeChatHooker
import com.fankes.tsbattery.ui.activity.base.BaseActivity
import com.fankes.tsbattery.utils.factory.*
import com.fankes.tsbattery.utils.factory.appVersionBrandOf
import com.fankes.tsbattery.utils.factory.hideOrShowLauncherIcon
import com.fankes.tsbattery.utils.factory.isInstall
import com.fankes.tsbattery.utils.factory.isLauncherIconShowing
import com.fankes.tsbattery.utils.factory.openBrowser
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.utils.tool.YukiPromoteTool
import com.fankes.tsbattery.wrapper.BuildConfigWrapper
import com.highcapable.yukihookapi.YukiHookAPI
class MainActivity : BaseActivity<ActivityMainBinding>() {
@@ -65,16 +72,13 @@ 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 pendingFlag = ""
private const val TIM_SUPPORT_VERSION = "2+、3+ (并未完全测试每个版本)。"
private const val WECHAT_SUPPORT_VERSION = "全版本仅支持基础省电,更多功能依然画饼。"
}
override fun onCreate() {
/** 检查更新 */
GithubReleaseTool.checkingForUpdate(context = this, BuildConfig.VERSION_NAME) { version, function ->
GithubReleaseTool.checkingForUpdate(context = this, ModuleVersion.NAME) { version, function ->
binding.mainTextReleaseVersion.apply {
text = "点击更新 $version"
isVisible = true
@@ -89,7 +93,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.mainTextApiWay.isVisible = true
refreshActivateExecutor()
/** 推广、恰饭 */
YukiPromoteTool.promote(context = this)
ProjectPromote.show(activity = this, ModuleVersion.toString())
} else
showDialog {
title = "模块没有激活"
@@ -102,7 +106,27 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
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.mainTextVersion.text = "模块版本:${ModuleVersion.NAME}"
/** 设置 CI 自动构建标识 */
if (ModuleVersion.isCiMode)
binding.mainTextReleaseVersion.apply {
text = "CI ${ModuleVersion.GITHUB_COMMIT_ID}"
isVisible = true
setOnClickListener {
showDialog {
title = "CI 自动构建说明"
msg = """
你正在使用的是 CI 自动构建版本Commit ID 为 ${ModuleVersion.GITHUB_COMMIT_ID}
它是由代码提交后自动触发并构建、自动编译发布的,并未经任何稳定性测试,使用风险自负。
CI 构建的版本不支持太极 (也请不要提交 CI 版本的适配,因为它们是不稳定的),你可以使用 LSPosed / LSPatch。
""".trimIndent()
confirmButton(text = "我知道了")
noCancelable()
}
}
}
binding.mainQqItem.setOnClickListener {
showDialog {
title = "兼容的 QQ 版本"
@@ -115,7 +139,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.mainTimItem.setOnClickListener {
showDialog {
title = "兼容的 TIM 版本"
msg = timSupportVersion
msg = TIM_SUPPORT_VERSION
confirmButton(text = "我知道了")
}
/** 振动提醒 */
@@ -124,7 +148,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
binding.mainWechatItem.setOnClickListener {
showDialog {
title = "兼容的微信版本"
msg = wechatSupportVersion
msg = WECHAT_SUPPORT_VERSION
confirmButton(text = "我知道了")
}
/** 振动提醒 */
@@ -148,6 +172,11 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
if (btn.isPressed.not()) return@setOnCheckedChangeListener
hideOrShowLauncherIcon(b)
}
/** 判断当前启动模式 */
if (packageName != BuildConfigWrapper.APPLICATION_ID) {
binding.quickActionItem.isVisible = false
binding.displaySettingItem.isVisible = false
}
}
/**

View File

@@ -29,7 +29,8 @@ import android.content.res.Resources
import android.widget.TextView
import androidx.core.view.isGone
import androidx.core.view.isVisible
import com.fankes.tsbattery.BuildConfig
import com.fankes.projectpromote.ProjectPromote
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
@@ -38,8 +39,14 @@ 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.factory.appIconOf
import com.fankes.tsbattery.utils.factory.appNameOf
import com.fankes.tsbattery.utils.factory.appVersionCode
import com.fankes.tsbattery.utils.factory.appVersionName
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.yukihookapi.YukiHookAPI
import kotlin.system.exitProcess
@@ -47,7 +54,7 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
override fun onCreate() {
/** 检查更新 */
GithubReleaseTool.checkingForUpdate(context = this, BuildConfig.VERSION_NAME) { version, function ->
GithubReleaseTool.checkingForUpdate(context = this, ModuleVersion.NAME) { version, function ->
binding.updateVersionText.apply {
text = "点击更新 $version"
isVisible = true
@@ -58,14 +65,18 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
binding.titleModuleIcon.setOnClickListener {
showDialog {
title = "打开模块主界面"
msg = "点击确定后将打开模块主界面,如果未安装模块本体将会无法打开"
msg = "点击确定后将打开模块主界面,如果未安装模块本体将尝试打开寄生界面"
confirmButton {
runCatching {
startActivity(Intent().apply {
component = ComponentName(BuildConfig.APPLICATION_ID, MainActivity::class.java.name)
component = ComponentName(BuildConfigWrapper.APPLICATION_ID, MainActivity::class.java.name)
flags = Intent.FLAG_ACTIVITY_NEW_TASK
})
}.onFailure { snake(msg = "打开失败,请确认你已安装模块 APP\n$it") }
}.onFailure {
runCatching {
startActivity(Intent(this@ConfigActivity, MainActivity::class.java))
}.onFailure { snake(msg = "打开失败,请确认你已安装模块 APP 或在模块更新后重启过$appName\n$it") }
}
}
cancelButton()
}
@@ -73,8 +84,8 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
binding.titleNameText.text = "TSBattery 设置 (${appName.trim()})"
binding.appIcon.setImageDrawable(appIconOf())
binding.appName.text = appName.trim()
binding.appVersion.text = "${appVersionName}($appVersionCode)"
binding.moduleVersion.text = "${BuildConfig.VERSION_NAME}(${BuildConfig.VERSION_CODE})"
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
@@ -116,6 +127,8 @@ class ConfigActivity : BaseActivity<ActivityConfigBinding>() {
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())
}
/** 显示需要重新启动提示 */

View File

@@ -40,7 +40,7 @@ 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.fankes.tsbattery.wrapper.BuildConfigWrapper
import com.google.android.material.snackbar.Snackbar
import com.highcapable.yukihookapi.hook.xposed.application.ModuleApplication.Companion.appContext
@@ -227,7 +227,7 @@ fun Context.openBrowser(url: String, packageName: String = "") = runCatching {
*/
fun Context.hideOrShowLauncherIcon(isShow: Boolean) {
packageManager?.setComponentEnabledSetting(
ComponentName(packageName, "${BuildConfig.APPLICATION_ID}.Home"),
ComponentName(packageName, "${BuildConfigWrapper.APPLICATION_ID}.Home"),
if (isShow) PackageManager.COMPONENT_ENABLED_STATE_DISABLED else PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP
)
@@ -239,5 +239,5 @@ fun Context.hideOrShowLauncherIcon(isShow: Boolean) {
*/
val Context.isLauncherIconShowing
get() = packageManager?.getComponentEnabledSetting(
ComponentName(packageName, "${BuildConfig.APPLICATION_ID}.Home")
ComponentName(packageName, "${BuildConfigWrapper.APPLICATION_ID}.Home")
) != PackageManager.COMPONENT_ENABLED_STATE_DISABLED

View File

@@ -1,59 +0,0 @@
/*
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
* Copyright (C) 2017-2023 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.prefs
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.prefs().edit { put(YUKI_PROMOTE_READED, value = true) }
if (context.prefs().get(YUKI_PROMOTE_READED).not())
context.showDialog {
title = "面向开发者的推广"
msg = "你想快速拥有一个自己的 Xposed 模块吗,你只需要拥有基础的 Android 开发经验以及使用 Kotlin 编程语言即可。\n\n" +
"快来体验 YukiHookAPI这是一个使用 Kotlin 构建的高效 Hook API 与 Xposed 模块解决方案,助你的开发变得更轻松。"
confirmButton(text = "去看看") {
context.openBrowser(url = "https://github.com/fankes/YukiHookAPI")
saveReaded()
}
cancelButton(text = "我不是开发者") { saveReaded() }
noCancelable()
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* TSBattery - A new way to save your battery avoid cancer apps hacker it.
* Copyright (C) 2017-2023 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 2023/9/16.
*/
@file:Suppress("unused")
package com.fankes.tsbattery.wrapper
import com.fankes.tsbattery.BuildConfig
/**
* 对 [BuildConfig] 的包装
*/
object BuildConfigWrapper {
const val APPLICATION_ID = BuildConfig.APPLICATION_ID
const val VERSION_NAME = BuildConfig.VERSION_NAME
const val VERSION_CODE = BuildConfig.VERSION_CODE
val isDebug = BuildConfig.DEBUG
}