diff --git a/app/src/main/java/com/fankes/tsbattery/hook/HookMain.kt b/app/src/main/java/com/fankes/tsbattery/hook/HookMain.kt index a39529b..ade7065 100644 --- a/app/src/main/java/com/fankes/tsbattery/hook/HookMain.kt +++ b/app/src/main/java/com/fankes/tsbattery/hook/HookMain.kt @@ -23,12 +23,18 @@ package com.fankes.tsbattery.hook import android.app.Activity -import android.app.AlertDialog import android.os.Build import android.os.Bundle import android.util.Log import androidx.annotation.Keep +import com.fankes.tsbattery.hook.HookMedium.QQ_PACKAGE_NAME +import com.fankes.tsbattery.hook.HookMedium.SELF_PACKAGE_NAME +import com.fankes.tsbattery.hook.HookMedium.TIM_PACKAGE_NAME +import com.fankes.tsbattery.hook.HookMedium.WECHAT_PACKAGE_NAME import com.fankes.tsbattery.utils.XPrefUtils +import com.fankes.tsbattery.utils.showDialog +import com.fankes.tsbattery.utils.versionCode +import com.fankes.tsbattery.utils.versionName import de.robv.android.xposed.* import de.robv.android.xposed.callbacks.XC_LoadPackage import java.util.* @@ -62,7 +68,7 @@ class HookMain : IXposedHookLoadPackage { */ private fun XC_LoadPackage.LoadPackageParam.replaceToNull(clazz: String, name: String) { XposedHelpers.findAndHookMethod( - "com.tencent.mobileqq.$clazz", + "$QQ_PACKAGE_NAME.$clazz", classLoader, name, replaceToNull @@ -168,15 +174,15 @@ class HookMain : IXposedHookLoadPackage { if (lpparam == null) return when (lpparam.packageName) { /** Hook 自身 */ - "com.fankes.tsbattery" -> + SELF_PACKAGE_NAME -> XposedHelpers.findAndHookMethod( - "com.fankes.tsbattery.hook.HookMedium", + "$SELF_PACKAGE_NAME.hook.HookMedium", lpparam.classLoader, "isHooked", replaceToTrue ) /** 经过测试 QQ 与 TIM 这两个是一个模子里面的东西,所以他们的类名也基本上是一样的 */ - "com.tencent.mobileqq", "com.tencent.tim" -> { + QQ_PACKAGE_NAME, TIM_PACKAGE_NAME -> { lpparam.hookSystemWakeLock() /** 增加通知栏文本显示守护状态 */ runWithoutError("Notification") { @@ -205,41 +211,27 @@ class HookMain : IXposedHookLoadPackage { * 在里面加入提示运行信息的对话框测试模块是否激活 */ XposedHelpers.findAndHookMethod( - "com.tencent.mobileqq.activity.SplashActivity", + "$QQ_PACKAGE_NAME.activity.SplashActivity", lpparam.classLoader, "doOnCreate", Bundle::class.java, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam?) { - val self = param?.thisObject as? Activity ?: return - runWithoutError("模块已激活,但显示信息弹窗失败了") { - AlertDialog.Builder( - self, - android.R.style.Theme_Material_Light_Dialog - ).setCancelable(false) - .setTitle("TSBattery 已激活") - .setMessage( - "[提示模块运行信息功能已打开]\n" + - "模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" + - "已生效模块版本:${XPrefUtils.getString(HookMedium.ENABLE_MODULE_VERSION)}\n" + - "当前模式:${if (XPrefUtils.getBoolean(HookMedium.ENABLE_WHITE_MODE)) "保守模式" else "完全模式"}" + - "\n\n包名:${self.packageName}\n版本:${ - self.packageManager.getPackageInfo( - self.packageName, - 0 - ).versionName - }(${ - self.packageManager.getPackageInfo( - self.packageName, - 0 - ).versionCode - })" + "\n\nPS:模块只对挂后台锁屏情况下有省电效果,请不要将过多的群提醒,消息通知打开,这样子在使用过程时照样会极其耗电。\n" + - "如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n" + - "开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。" - ) - .setPositiveButton("我知道了", null) - .show() + (param?.thisObject as? Activity?)?.apply { + showDialog { + title = "TSBattery 已激活" + content = "[提示模块运行信息功能已打开]\n" + + "模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" + + "已生效模块版本:${XPrefUtils.getString(HookMedium.ENABLE_MODULE_VERSION)}\n" + + "当前模式:${if (XPrefUtils.getBoolean(HookMedium.ENABLE_WHITE_MODE)) "保守模式" else "完全模式"}" + + "\n\n包名:${packageName}\n版本:$versionName($versionCode)" + + "\n\nPS:模块只对挂后台锁屏情况下有省电效果,请不要将过多的群提醒,消息通知打开,这样子在使用过程时照样会极其耗电。\n" + + "如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n" + + "开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。" + addConfirmButton("我知道了") + noCancelable() + } } } }) @@ -249,7 +241,7 @@ class HookMain : IXposedHookLoadPackage { runWithoutError("BaseChatPie(first time)") { /** 通过在 SplashActivity 里取到应用的版本号 */ XposedHelpers.findAndHookMethod( - "com.tencent.mobileqq.activity.SplashActivity", + "$QQ_PACKAGE_NAME.activity.SplashActivity", lpparam.classLoader, "doOnCreate", Bundle::class.java, @@ -258,11 +250,10 @@ class HookMain : IXposedHookLoadPackage { override fun beforeHookedMethod(param: MethodHookParam?) { val self = param?.thisObject as? Activity ?: return val name = self.packageName - val version = - self.packageManager.getPackageInfo(name, 0).versionName + val version = self.versionName /** 这个地方我们只处理 QQ */ runWithoutError("BaseChatPie") { - if (name == "com.tencent.mobileqq") + if (name == QQ_PACKAGE_NAME) lpparam.hookQQBaseChatPie(version) } } @@ -286,7 +277,7 @@ class HookMain : IXposedHookLoadPackage { * 这个东西经过测试会在锁屏的时候吊起来,解锁的时候自动 finish(),无限耍流氓耗电 */ XposedHelpers.findAndHookMethod( - "com.tencent.mobileqq.activity.QQLSUnlockActivity", + "$QQ_PACKAGE_NAME.activity.QQLSUnlockActivity", lpparam.classLoader, "onCreate", Bundle::class.java, object : XC_MethodHook() { @@ -321,7 +312,7 @@ class HookMain : IXposedHookLoadPackage { * 讯哥的程序员真的有你的 */ XposedHelpers.findAndHookMethod( - "com.tencent.mobileqq.activity.QQLSActivity\$14", + "$QQ_PACKAGE_NAME.activity.QQLSActivity\$14", lpparam.classLoader, "run", replaceToNull @@ -406,7 +397,7 @@ class HookMain : IXposedHookLoadPackage { } } /** 微信 */ - "com.tencent.mm" -> { + WECHAT_PACKAGE_NAME -> { lpparam.hookSystemWakeLock() /** 判断是否开启提示模块运行信息 */ if (XPrefUtils.getBoolean(HookMedium.ENABLE_RUN_INFO)) @@ -416,39 +407,27 @@ class HookMain : IXposedHookLoadPackage { * 在里面加入提示运行信息的对话框测试模块是否激活 */ XposedHelpers.findAndHookMethod( - "com.tencent.mm.ui.LauncherUI", + "$WECHAT_PACKAGE_NAME.ui.LauncherUI", lpparam.classLoader, "onCreate", Bundle::class.java, object : XC_MethodHook() { override fun afterHookedMethod(param: MethodHookParam?) { - val self = param?.thisObject as? Activity ?: return - runWithoutError("模块已激活,但显示信息弹窗失败了") { - AlertDialog.Builder( - self, - android.R.style.Theme_Material_Light_Dialog - ).setCancelable(false) - .setTitle("TSBattery 已激活") - .setMessage( - "[提示模块运行信息功能已打开]\n" + - "模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" + - "已生效模块版本:${XPrefUtils.getString(HookMedium.ENABLE_MODULE_VERSION)}\n" + - "当前模式:基础省电" + - "\n\n包名:${self.packageName}\n版本:${ - self.packageManager.getPackageInfo( - self.packageName, - 0 - ).versionName - }(${ - self.packageManager.getPackageInfo( - self.packageName, - 0 - ).versionCode - })" + "\n\nPS:当前只支持微信的基础省电,即系统电源锁,后续会继续适配微信相关的省电功能(在新建文件夹了)。" - ) - .setPositiveButton("我知道了", null) - .show() + (param?.thisObject as? Activity?)?.apply { + showDialog { + title = "TSBattery 已激活" + content = "[提示模块运行信息功能已打开]\n" + + "模块工作看起来一切正常,请自行测试是否能达到省电效果。\n\n" + + "已生效模块版本:${XPrefUtils.getString(HookMedium.ENABLE_MODULE_VERSION)}\n" + + "当前模式:基础省电" + + "\n\n包名:${packageName}\n版本:$versionName($versionCode)" + + "\n\nPS:当前只支持微信的基础省电,即系统电源锁,后续会继续适配微信相关的省电功能(在新建文件夹了)。\n" + + "如果你不想看到此提示。请在模块设置中关闭“提示模块运行信息”,此设置默认关闭。\n" + + "开发者 酷安 @星夜不荟\n未经允许禁止转载、修改或复制我的劳动成果。" + addConfirmButton("我知道了") + noCancelable() + } } } }) diff --git a/app/src/main/java/com/fankes/tsbattery/hook/HookMedium.kt b/app/src/main/java/com/fankes/tsbattery/hook/HookMedium.kt index b0273d6..f369772 100644 --- a/app/src/main/java/com/fankes/tsbattery/hook/HookMedium.kt +++ b/app/src/main/java/com/fankes/tsbattery/hook/HookMedium.kt @@ -36,6 +36,11 @@ object HookMedium { const val ENABLE_WHITE_MODE = "_white_mode" const val ENABLE_MODULE_VERSION = "_module_version" + const val SELF_PACKAGE_NAME = "com.fankes.tsbattery" + const val QQ_PACKAGE_NAME = "com.tencent.mobileqq" + const val TIM_PACKAGE_NAME = "com.tencent.tim" + const val WECHAT_PACKAGE_NAME = "com.tencent.mm" + /** * 判断模块是否激活 * 在 [HookMain] 中 Hook 掉此方法 diff --git a/app/src/main/java/com/fankes/tsbattery/ui/MainActivity.kt b/app/src/main/java/com/fankes/tsbattery/ui/MainActivity.kt index ca65b8e..2810c53 100644 --- a/app/src/main/java/com/fankes/tsbattery/ui/MainActivity.kt +++ b/app/src/main/java/com/fankes/tsbattery/ui/MainActivity.kt @@ -36,7 +36,6 @@ import android.view.View import android.widget.LinearLayout import android.widget.TextView import android.widget.Toast -import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SwitchCompat import androidx.constraintlayout.utils.widget.ImageFilterView @@ -44,6 +43,7 @@ import com.fankes.tsbattery.BuildConfig import com.fankes.tsbattery.R import com.fankes.tsbattery.hook.HookMedium import com.fankes.tsbattery.utils.FileUtils +import com.fankes.tsbattery.utils.showDialog import com.gyf.immersionbar.ImmersionBar import java.io.File @@ -84,47 +84,48 @@ class MainActivity : AppCompatActivity() { /** 写入激活的模块版本 */ putString(HookMedium.ENABLE_MODULE_VERSION, moduleVersion) } else - AlertDialog.Builder(this) - .setTitle("模块没有激活") - .setMessage( - "检测到模块没有激活,模块需要 Xposed 环境依赖,同时需要系统拥有 Root 权限(太极阴可以免 Root),请自行查看本页面使用帮助与说明第三条。\n" + - "太极、应用转生、梦境(Pine)和第三方 Xposed 激活后可能不会提示激活,若想验证是否激活请打开“提示模块运行信息”自行检查," + - "如果生效就代表模块运行正常,这里的激活状态只是一个显示意义上的存在。\n" + - "太极(无极)在 MIUI 设备上会提示打开授权,请进行允许,然后再次打开本应用查看激活状态。" - ) - .setPositiveButton("我知道了", null) - .setCancelable(false) - .show() + showDialog { + title = "模块没有激活" + content = "检测到模块没有激活,模块需要 Xposed 环境依赖," + + "同时需要系统拥有 Root 权限(太极阴可以免 Root)," + + "请自行查看本页面使用帮助与说明第三条。\n" + + "太极、应用转生、梦境(Pine)和第三方 Xposed 激活后" + + "可能不会提示激活,若想验证是否激活请打开“提示模块运行信息”自行检查," + + "如果生效就代表模块运行正常,这里的激活状态只是一个显示意义上的存在。\n" + + "太极(无极)在 MIUI 设备上会提示打开授权,请进行允许,然后再次打开本应用查看激活状态。" + addConfirmButton("我知道了") + noCancelable() + } /** 设置文本 */ findViewById(R.id.main_text_version).text = "当前版本:$moduleVersion" findViewById(R.id.main_text_support_qq).apply { text = qqSupportVersion setOnClickListener { - AlertDialog.Builder(this@MainActivity) - .setTitle("兼容的 QQ 版本") - .setMessage(qqSupportVersion) - .setPositiveButton("我知道了", null) - .show() + showDialog { + title = "兼容的 QQ 版本" + content = qqSupportVersion + addConfirmButton("我知道了") + } } } findViewById(R.id.main_text_support_tim).apply { text = timSupportVersion setOnClickListener { - AlertDialog.Builder(this@MainActivity) - .setTitle("兼容的 TIM 版本") - .setMessage(timSupportVersion) - .setPositiveButton("我知道了", null) - .show() + showDialog { + title = "兼容的 TIM 版本" + content = timSupportVersion + addConfirmButton("我知道了") + } } } findViewById(R.id.main_text_support_wechat).apply { text = wechatSupportVersion setOnClickListener { - AlertDialog.Builder(this@MainActivity) - .setTitle("兼容的微信版本") - .setMessage(wechatSupportVersion) - .setPositiveButton("我知道了", null) - .show() + showDialog { + title = "兼容的微信版本" + content = wechatSupportVersion + addConfirmButton("我知道了") + } } } /** 初始化 View */ diff --git a/app/src/main/java/com/fankes/tsbattery/utils/DialogBuilder.kt b/app/src/main/java/com/fankes/tsbattery/utils/DialogBuilder.kt new file mode 100644 index 0000000..be33d94 --- /dev/null +++ b/app/src/main/java/com/fankes/tsbattery/utils/DialogBuilder.kt @@ -0,0 +1,89 @@ +/** + * Copyright (C) 2021. Fankes Studio(qzmmcn@163.com) + * + * This file is part of TSBattery. + * + * TSBattery is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TSBattery 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file is Created by fankes on 2022/1/7. + */ +@file:Suppress("unused") + +package com.fankes.tsbattery.utils + +import android.app.AlertDialog +import android.content.Context + +/** + * 构造对话框 + * @param it 对话框方法体 + */ +fun Context.showDialog(it: DialogBuilder.() -> Unit) = DialogBuilder(this).apply(it).show() + +/** + * 对话框构造器 + * @param context 实例 + */ +class DialogBuilder(private val context: Context) { + + private var instance: AlertDialog.Builder? = null // 实例对象 + + init { + instance = AlertDialog.Builder(context, android.R.style.Theme_Material_Light_Dialog) + } + + /** 设置对话框不可关闭 */ + fun noCancelable() = instance?.setCancelable(false) + + /** 设置对话框标题 */ + var title + get() = "" + set(value) { + instance?.setTitle(value) + } + + /** 设置对话框内容 */ + var content + get() = "" + set(value) { + instance?.setMessage(value) + } + + /** + * 设置对话框确定按钮 + * @param content 按钮文本内容 + * @param it 点击事件 + */ + fun addConfirmButton(content: String, it: () -> Unit = {}) = + instance?.setPositiveButton(content) { _, _ -> it() } + + /** + * 设置对话框取消按钮 + * @param content 按钮文本内容 + * @param it 点击事件 + */ + fun addCancelButton(content: String, it: () -> Unit = {}) = + instance?.setNegativeButton(content) { _, _ -> it() } + + /** + * 设置对话框第三个按钮 + * @param content 按钮文本内容 + * @param it 点击事件 + */ + fun addNeutralButton(content: String, it: () -> Unit = {}) = + instance?.setNeutralButton(content) { _, _ -> it() } + + /** 显示对话框 */ + internal fun show() = instance?.create()?.show() +} \ No newline at end of file diff --git a/app/src/main/java/com/fankes/tsbattery/utils/Utils.kt b/app/src/main/java/com/fankes/tsbattery/utils/Utils.kt new file mode 100644 index 0000000..0e0978a --- /dev/null +++ b/app/src/main/java/com/fankes/tsbattery/utils/Utils.kt @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2021. Fankes Studio(qzmmcn@163.com) + * + * This file is part of TSBattery. + * + * TSBattery is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * TSBattery 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * This file is Created by fankes on 2022/1/7. + */ +@file:Suppress("DEPRECATION") + +package com.fankes.tsbattery.utils + +import android.content.Context +import android.content.pm.PackageInfo + +/** 得到安装包信息 */ +val Context.packageInfo get() = packageManager?.getPackageInfo(packageName, 0) ?: PackageInfo() + +/** 得到版本信息 */ +val Context.versionName get() = packageInfo.versionName ?: "" + +/** 得到版本号 */ +val Context.versionCode get() = packageInfo.versionCode +