mirror of
https://github.com/fankes/TSBattery.git
synced 2025-09-06 18:55:45 +08:00
refactor: migrate to YukiHookAPI new usage
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
package="com.fankes.tsbattery">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
@@ -29,7 +29,7 @@ import com.highcapable.yukihookapi.hook.factory.configs
|
|||||||
import com.highcapable.yukihookapi.hook.factory.encase
|
import com.highcapable.yukihookapi.hook.factory.encase
|
||||||
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
|
import com.highcapable.yukihookapi.hook.xposed.proxy.IYukiHookXposedInit
|
||||||
|
|
||||||
@InjectYukiHookWithXposed(isUsingResourcesHook = false)
|
@InjectYukiHookWithXposed
|
||||||
object HookEntry : IYukiHookXposedInit {
|
object HookEntry : IYukiHookXposedInit {
|
||||||
|
|
||||||
/** 是否完全支持当前版本 */
|
/** 是否完全支持当前版本 */
|
||||||
|
@@ -52,10 +52,7 @@ import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
|
|||||||
import com.highcapable.yukihookapi.hook.factory.method
|
import com.highcapable.yukihookapi.hook.factory.method
|
||||||
import com.highcapable.yukihookapi.hook.factory.processName
|
import com.highcapable.yukihookapi.hook.factory.processName
|
||||||
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
|
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
|
||||||
import com.highcapable.yukihookapi.hook.log.loggerD
|
import com.highcapable.yukihookapi.hook.log.YLog
|
||||||
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.BuildClass
|
import com.highcapable.yukihookapi.hook.type.android.BuildClass
|
||||||
import com.highcapable.yukihookapi.hook.type.android.BundleClass
|
import com.highcapable.yukihookapi.hook.type.android.BundleClass
|
||||||
import com.highcapable.yukihookapi.hook.type.android.ContextClass
|
import com.highcapable.yukihookapi.hook.type.android.ContextClass
|
||||||
@@ -78,40 +75,48 @@ import java.lang.reflect.Proxy
|
|||||||
object QQTIMHooker : YukiBaseHooker() {
|
object QQTIMHooker : YukiBaseHooker() {
|
||||||
|
|
||||||
/** QQ、TIM 存在的类 */
|
/** QQ、TIM 存在的类 */
|
||||||
const val JumpActivityClass = "${PackageName.QQ}.activity.JumpActivity"
|
const val JumpActivityClassName = "${PackageName.QQ}.activity.JumpActivity"
|
||||||
|
|
||||||
|
/** QQ、TIM 存在的类 */
|
||||||
|
private val JumpActivityClass by lazyClassOrNull(JumpActivityClassName)
|
||||||
|
|
||||||
/** QQ、TIM 存在的类 (NT 版本不再存在) */
|
/** QQ、TIM 存在的类 (NT 版本不再存在) */
|
||||||
private const val QQSettingSettingActivityClass = "${PackageName.QQ}.activity.QQSettingSettingActivity"
|
private val QQSettingSettingActivityClass by lazyClassOrNull("${PackageName.QQ}.activity.QQSettingSettingActivity")
|
||||||
|
|
||||||
/** QQ 新版存在的类 (Pad 模式 - NT 版本不再存在) */
|
/** QQ 新版存在的类 (Pad 模式 - NT 版本不再存在) */
|
||||||
private const val QQSettingSettingFragmentClass = "${PackageName.QQ}.fragment.QQSettingSettingFragment"
|
private val QQSettingSettingFragmentClass by lazyClassOrNull("${PackageName.QQ}.fragment.QQSettingSettingFragment")
|
||||||
|
|
||||||
/** QQ、TIM 存在的类 (NT 版本不再存在) */
|
/** QQ、TIM 存在的类 (NT 版本不再存在) */
|
||||||
private const val AboutActivityClass = "${PackageName.QQ}.activity.AboutActivity"
|
private val AboutActivityClass by lazyClassOrNull("${PackageName.QQ}.activity.AboutActivity")
|
||||||
|
|
||||||
/** QQ 新版本存在的类 */
|
/** QQ 新版本存在的类 */
|
||||||
private const val GeneralSettingActivityClass = "${PackageName.QQ}.activity.GeneralSettingActivity"
|
private val GeneralSettingActivityClass by lazyClassOrNull("${PackageName.QQ}.activity.GeneralSettingActivity")
|
||||||
|
|
||||||
/** QQ 新版本 (NT) 存在的类 */
|
/** QQ 新版本 (NT) 存在的类 */
|
||||||
private const val MainSettingFragmentClass = "${PackageName.QQ}.setting.main.MainSettingFragment"
|
private val MainSettingFragmentClass by lazyClassOrNull("${PackageName.QQ}.setting.main.MainSettingFragment")
|
||||||
|
|
||||||
/** QQ 新版本 (NT) 存在的类 */
|
/** QQ 新版本 (NT) 存在的类 */
|
||||||
private const val MainSettingConfigProviderClass = "${PackageName.QQ}.setting.main.MainSettingConfigProvider"
|
private val MainSettingConfigProviderClass by lazyClassOrNull("${PackageName.QQ}.setting.main.MainSettingConfigProvider")
|
||||||
|
|
||||||
/** QQ、TIM 新版本存在的类 */
|
/** QQ、TIM 新版本存在的类 */
|
||||||
private const val FormSimpleItemClass = "${PackageName.QQ}.widget.FormSimpleItem"
|
private val FormSimpleItemClass by lazyClassOrNull("${PackageName.QQ}.widget.FormSimpleItem")
|
||||||
|
|
||||||
/** QQ、TIM 旧版本存在的类 */
|
/** QQ、TIM 旧版本存在的类 */
|
||||||
private const val FormCommonSingleLineItemClass = "${PackageName.QQ}.widget.FormCommonSingleLineItem"
|
private val FormCommonSingleLineItemClass by lazyClassOrNull("${PackageName.QQ}.widget.FormCommonSingleLineItem")
|
||||||
|
|
||||||
/** QQ、TIM 存在的类 */
|
/** QQ、TIM 存在的类 */
|
||||||
private const val CoreServiceClass = "${PackageName.QQ}.app.CoreService"
|
private val CoreServiceClass by lazyClassOrNull("${PackageName.QQ}.app.CoreService")
|
||||||
|
|
||||||
/** QQ、TIM 存在的类 */
|
/** QQ、TIM 存在的类 */
|
||||||
private const val CoreService_KernelServiceClass = "${PackageName.QQ}.app.CoreService\$KernelService"
|
private val CoreService_KernelServiceClass by lazyClassOrNull("${PackageName.QQ}.app.CoreService\$KernelService")
|
||||||
|
|
||||||
/** 根据多个版本存的不同的类 */
|
/** 根据多个版本存的不同的类 */
|
||||||
private val BaseChatPieClass = VariousClass("${PackageName.QQ}.activity.aio.core.BaseChatPie", "${PackageName.QQ}.activity.BaseChatPie")
|
private val BaseChatPieClass by lazyClassOrNull(
|
||||||
|
VariousClass(
|
||||||
|
"${PackageName.QQ}.activity.aio.core.BaseChatPie",
|
||||||
|
"${PackageName.QQ}.activity.BaseChatPie"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
/** 一个内部进程的名称 (与 X5 浏览器内核有关) */
|
/** 一个内部进程的名称 (与 X5 浏览器内核有关) */
|
||||||
private val privilegedProcessName = "$packageName:privileged_process"
|
private val privilegedProcessName = "$packageName:privileged_process"
|
||||||
@@ -131,7 +136,7 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
* 在 QQ NT 中 [AboutActivityClass] 已被移除 - 以此作为判断条件
|
* 在 QQ NT 中 [AboutActivityClass] 已被移除 - 以此作为判断条件
|
||||||
* @return [Boolean]
|
* @return [Boolean]
|
||||||
*/
|
*/
|
||||||
private val isQQNTVersion get() = isQQ && AboutActivityClass.hasClass().not()
|
private val isQQNTVersion get() = isQQ && AboutActivityClass == null
|
||||||
|
|
||||||
/** 当前宿主的版本 */
|
/** 当前宿主的版本 */
|
||||||
private var hostVersionName = "<unknown>"
|
private var hostVersionName = "<unknown>"
|
||||||
@@ -303,7 +308,7 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
HookEntry.isHookClientSupport = false
|
HookEntry.isHookClientSupport = false
|
||||||
loggerW(msg = "$hostVersionName not supported!")
|
YLog.warn("$hostVersionName not supported!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,72 +318,55 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
* @param methodName 方法名
|
* @param methodName 方法名
|
||||||
*/
|
*/
|
||||||
private fun hookBaseChatPie(methodName: String) {
|
private fun hookBaseChatPie(methodName: String) {
|
||||||
BaseChatPieClass.hook {
|
BaseChatPieClass?.method {
|
||||||
injectMember {
|
name = methodName
|
||||||
method {
|
emptyParam()
|
||||||
name = methodName
|
returnType = UnitType
|
||||||
emptyParam()
|
}?.hook()?.intercept()
|
||||||
returnType = UnitType
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Hook CoreService QQ、TIM */
|
/** Hook CoreService QQ、TIM */
|
||||||
private fun hookCoreService() {
|
private fun hookCoreService() {
|
||||||
CoreServiceClass.hook {
|
CoreServiceClass?.apply {
|
||||||
if (isQQ) {
|
if (isQQ) {
|
||||||
injectMember {
|
method {
|
||||||
method { name = "startTempService" }
|
name = "startTempService"
|
||||||
intercept()
|
}.ignored().hook().intercept()
|
||||||
}.ignoredNoSuchMemberFailure()
|
method {
|
||||||
injectMember {
|
name = "startCoreService"
|
||||||
method {
|
param(BooleanType)
|
||||||
name = "startCoreService"
|
}.ignored().hook().intercept()
|
||||||
param(BooleanType)
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}.ignoredNoSuchMemberFailure()
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "onStartCommand"
|
|
||||||
param(IntentClass, IntType, IntType)
|
|
||||||
}
|
|
||||||
replaceTo(any = 2)
|
|
||||||
}.ignoredNoSuchMemberFailure()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method { name = "onCreate" }
|
|
||||||
afterHook {
|
|
||||||
if (ConfigData.isEnableKillQQTimCoreService)
|
|
||||||
instance<Service>().apply {
|
|
||||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
|
||||||
stopSelf()
|
|
||||||
loggerD(msg = "Shutdown CoreService OK!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CoreService_KernelServiceClass.hook {
|
|
||||||
injectMember {
|
|
||||||
method { name = "onCreate" }
|
|
||||||
afterHook {
|
|
||||||
if (ConfigData.isEnableKillQQTimCoreServiceChild)
|
|
||||||
instance<Service>().apply {
|
|
||||||
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
|
||||||
stopSelf()
|
|
||||||
loggerD(msg = "Shutdown CoreService\$KernelService OK!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
method {
|
||||||
name = "onStartCommand"
|
name = "onStartCommand"
|
||||||
param(IntentClass, IntType, IntType)
|
param(IntentClass, IntType, IntType)
|
||||||
}
|
}.ignored().hook().replaceTo(any = 2)
|
||||||
replaceTo(any = 2)
|
}
|
||||||
}.ignoredNoSuchMemberFailure()
|
method {
|
||||||
|
name = "onCreate"
|
||||||
|
}.ignored().hook().after {
|
||||||
|
if (ConfigData.isEnableKillQQTimCoreService)
|
||||||
|
instance<Service>().apply {
|
||||||
|
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||||
|
stopSelf()
|
||||||
|
YLog.debug("Shutdown CoreService OK!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoreService_KernelServiceClass?.apply {
|
||||||
|
method {
|
||||||
|
name = "onCreate"
|
||||||
|
}.ignored().hook().after {
|
||||||
|
if (ConfigData.isEnableKillQQTimCoreServiceChild)
|
||||||
|
instance<Service>().apply {
|
||||||
|
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
|
||||||
|
stopSelf()
|
||||||
|
YLog.debug("Shutdown CoreService\$KernelService OK!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
method {
|
||||||
|
name = "onStartCommand"
|
||||||
|
param(IntentClass, IntType, IntType)
|
||||||
|
}.ignored().hook().replaceTo(any = 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,63 +378,53 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
* 每个版本的差异暂未做排查
|
* 每个版本的差异暂未做排查
|
||||||
* 旧版本理论上没有这个类
|
* 旧版本理论上没有这个类
|
||||||
*/
|
*/
|
||||||
findClass(name = "${PackageName.QQ}.msf.service.y").hook {
|
"${PackageName.QQ}.msf.service.y".toClassOrNull()
|
||||||
injectMember {
|
?.method {
|
||||||
method {
|
name = "a"
|
||||||
name = "a"
|
param(StringClass, LongType)
|
||||||
param(StringClass, LongType)
|
returnType = UnitType
|
||||||
returnType = UnitType
|
}?.ignored()?.hook()?.intercept()
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}.onAllFailure { loggerE(msg = "Hook MsfService Failed $it") }
|
|
||||||
}.ignoredHookClassNotFoundFailure()
|
|
||||||
/**
|
/**
|
||||||
* 干掉自动上传服务的电源锁
|
* 干掉自动上传服务的电源锁
|
||||||
* 每个版本的差异暂未做排查
|
* 每个版本的差异暂未做排查
|
||||||
*/
|
*/
|
||||||
findClass(name = "com.tencent.upload.impl.UploadServiceImpl").hook {
|
"com.tencent.upload.impl.UploadServiceImpl".toClassOrNull()
|
||||||
injectMember {
|
?.method {
|
||||||
method { name = "acquireWakeLockIfNot" }
|
name = "acquireWakeLockIfNot"
|
||||||
intercept()
|
}?.ignored()?.hook()?.intercept()
|
||||||
}.onAllFailure { loggerE(msg = "Hook UploadServiceImpl Failed $it") }
|
|
||||||
}.ignoredHookClassNotFoundFailure()
|
|
||||||
/**
|
/**
|
||||||
* Hook 掉一个一像素保活 [Activity] 真的我怎么都想不到讯哥的程序员做出这种事情
|
* Hook 掉一个一像素保活 Activity 真的我怎么都想不到讯哥的程序员做出这种事情
|
||||||
* 这个东西经过测试会在锁屏的时候吊起来,解锁的时候自动 finish(),无限耍流氓耗电
|
* 这个东西经过测试会在锁屏的时候吊起来,解锁的时候自动 finish(),无限耍流氓耗电
|
||||||
* 2022/1/25 后期查证:锁屏界面消息快速回复窗口的解锁后拉起保活界面,也是毒瘤
|
* 2022/1/25 后期查证:锁屏界面消息快速回复窗口的解锁后拉起保活界面,也是毒瘤
|
||||||
*/
|
*/
|
||||||
findClass(name = "${PackageName.QQ}.activity.QQLSUnlockActivity").hook {
|
"${PackageName.QQ}.activity.QQLSUnlockActivity".toClassOrNull()
|
||||||
injectMember {
|
?.method {
|
||||||
method {
|
name = "onCreate"
|
||||||
name = "onCreate"
|
param(BundleClass)
|
||||||
param(BundleClass)
|
}?.ignored()?.hook {
|
||||||
}
|
|
||||||
var origDevice = ""
|
var origDevice = ""
|
||||||
beforeHook {
|
before {
|
||||||
/** 由于在 onCreate 里有一行判断只要型号是 xiaomi 的设备就开电源锁,所以说这里临时替换成菊花厂 */
|
/** 由于在 onCreate 里有一行判断只要型号是 xiaomi 的设备就开电源锁,所以说这里临时替换成菊花厂 */
|
||||||
origDevice = Build.MANUFACTURER
|
origDevice = Build.MANUFACTURER
|
||||||
if (Build.MANUFACTURER.lowercase() == "xiaomi")
|
if (Build.MANUFACTURER.lowercase() == "xiaomi")
|
||||||
BuildClass.field { name = "MANUFACTURER" }.get().set("HUAWEI")
|
BuildClass.field { name = "MANUFACTURER" }.get().set("HUAWEI")
|
||||||
}
|
}
|
||||||
afterHook {
|
after {
|
||||||
instance<Activity>().finish()
|
instance<Activity>().finish()
|
||||||
/** 这里再把型号替换回去 - 不影响应用变量等 Xposed 模块修改的型号 */
|
/** 这里再把型号替换回去 - 不影响应用变量等 Xposed 模块修改的型号 */
|
||||||
BuildClass.field { name = "MANUFACTURER" }.get().set(origDevice)
|
BuildClass.field { name = "MANUFACTURER" }.get().set(origDevice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* 这个东西同上
|
* 这个东西同上
|
||||||
* 反正也是一个一像素保活的 [Activity]
|
* 反正也是一个一像素保活的 Activity
|
||||||
* 讯哥的程序员真的有你的
|
* 讯哥的程序员真的有你的
|
||||||
* 2022/1/25 后期查证:锁屏界面消息快速回复窗口
|
* 2022/1/25 后期查证:锁屏界面消息快速回复窗口
|
||||||
*/
|
*/
|
||||||
findClass("${PackageName.QQ}.activity.QQLSActivity\$14", "ktq").hook {
|
VariousClass("${PackageName.QQ}.activity.QQLSActivity\$14", "ktq").toClassOrNull()
|
||||||
injectMember {
|
?.method {
|
||||||
method { name = "run" }
|
name = "run"
|
||||||
intercept()
|
}?.ignored()?.hook()?.intercept()
|
||||||
}.ignoredAllFailure()
|
|
||||||
}.ignoredHookClassNotFoundFailure()
|
|
||||||
/**
|
/**
|
||||||
* 这个是毒瘤核心类
|
* 这个是毒瘤核心类
|
||||||
* WakeLockMonitor
|
* WakeLockMonitor
|
||||||
@@ -457,144 +435,97 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
* 👮🏻 经过排查 Play 版本没这个类...... Emmmm 不想说啥了
|
* 👮🏻 经过排查 Play 版本没这个类...... Emmmm 不想说啥了
|
||||||
* ✅ 备注:8.9.x 版本已经基本移除了这个功能,没有再发现存在这个类
|
* ✅ 备注:8.9.x 版本已经基本移除了这个功能,没有再发现存在这个类
|
||||||
*/
|
*/
|
||||||
findClass(name = "com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor").hook {
|
"com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor".toClassOrNull()?.apply {
|
||||||
injectMember {
|
method {
|
||||||
method {
|
name = "onHook"
|
||||||
name = "onHook"
|
param(StringClass, AnyClass, AnyArrayClass, AnyClass)
|
||||||
param(StringClass, AnyClass, AnyArrayClass, AnyClass)
|
}.ignored().hook().intercept()
|
||||||
}
|
method {
|
||||||
intercept()
|
name = "doReport"
|
||||||
}
|
param("com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor\$WakeLockEntity", IntType)
|
||||||
injectMember {
|
}.ignored().hook().intercept()
|
||||||
method {
|
method {
|
||||||
name = "doReport"
|
name = "afterHookedMethod"
|
||||||
param("com.tencent.qapmsdk.qqbattery.monitor.WakeLockMonitor\$WakeLockEntity", IntType)
|
param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
||||||
}
|
}.ignored().hook().intercept()
|
||||||
intercept()
|
method {
|
||||||
}
|
name = "beforeHookedMethod"
|
||||||
injectMember {
|
param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
||||||
method {
|
}.ignored().hook().intercept()
|
||||||
name = "afterHookedMethod"
|
method {
|
||||||
param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
name = "onAppBackground"
|
||||||
}
|
}.ignored().hook().intercept()
|
||||||
intercept()
|
method {
|
||||||
}
|
name = "onOtherProcReport"
|
||||||
injectMember {
|
param(BundleClass)
|
||||||
method {
|
}.ignored().hook().intercept()
|
||||||
name = "beforeHookedMethod"
|
method {
|
||||||
param("com.tencent.qapmsdk.qqbattery.monitor.MethodHookParam")
|
name = "onProcessRun30Min"
|
||||||
}
|
}.ignored().hook().intercept()
|
||||||
intercept()
|
method {
|
||||||
}
|
name = "onProcessBG5Min"
|
||||||
injectMember {
|
}.ignored().hook().intercept()
|
||||||
method { name = "onAppBackground" }
|
method {
|
||||||
intercept()
|
name = "writeReport"
|
||||||
}
|
param(BooleanType)
|
||||||
injectMember {
|
}.ignored().hook().intercept()
|
||||||
method {
|
}
|
||||||
name = "onOtherProcReport"
|
|
||||||
param(BundleClass)
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method { name = "onProcessRun30Min" }
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method { name = "onProcessBG5Min" }
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "writeReport"
|
|
||||||
param(BooleanType)
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
}.ignoredHookClassNotFoundFailure()
|
|
||||||
/**
|
/**
|
||||||
* 这个是毒瘤核心操作类
|
* 这个是毒瘤核心操作类
|
||||||
* 功能同上、全部拦截
|
* 功能同上、全部拦截
|
||||||
* 👮🏻 经过排查 Play 版本也没这个类...... Emmmm 不想说啥了
|
* 👮🏻 经过排查 Play 版本也没这个类...... Emmmm 不想说啥了
|
||||||
* ✅ 备注:8.9.x 版本已经基本移除了这个功能,没有再发现存在这个类
|
* ✅ 备注:8.9.x 版本已经基本移除了这个功能,没有再发现存在这个类
|
||||||
*/
|
*/
|
||||||
findClass(name = "com.tencent.qapmsdk.qqbattery.QQBatteryMonitor").hook {
|
"com.tencent.qapmsdk.qqbattery.QQBatteryMonitor".toClassOrNull()?.apply {
|
||||||
injectMember {
|
method {
|
||||||
method { name = "start" }
|
name = "start"
|
||||||
intercept()
|
}.ignored().hook().intercept()
|
||||||
}
|
method {
|
||||||
injectMember {
|
name = "stop"
|
||||||
method { name = "stop" }
|
}.ignored().hook().intercept()
|
||||||
intercept()
|
method {
|
||||||
}
|
name = "handleMessage"
|
||||||
injectMember {
|
param(MessageClass)
|
||||||
method {
|
}.ignored().hook().intercept()
|
||||||
name = "handleMessage"
|
method {
|
||||||
param(MessageClass)
|
name = "startMonitorInner"
|
||||||
}
|
}.ignored().hook().intercept()
|
||||||
replaceToTrue()
|
method {
|
||||||
}
|
name = "onAppBackground"
|
||||||
injectMember {
|
}.ignored().hook().intercept()
|
||||||
method { name = "startMonitorInner" }
|
method {
|
||||||
intercept()
|
name = "onAppForeground"
|
||||||
}
|
}.ignored().hook().intercept()
|
||||||
injectMember {
|
method {
|
||||||
method { name = "onAppBackground" }
|
name = "setLogWhite"
|
||||||
intercept()
|
paramCount = 2
|
||||||
}
|
}.ignored().hook().intercept()
|
||||||
injectMember {
|
method {
|
||||||
method { name = "onAppForeground" }
|
name = "setCmdWhite"
|
||||||
intercept()
|
paramCount = 2
|
||||||
}
|
}.ignored().hook().intercept()
|
||||||
injectMember {
|
method {
|
||||||
method {
|
name = "onWriteLog"
|
||||||
name = "setLogWhite"
|
param(StringClass, StringClass)
|
||||||
paramCount = 2
|
}.ignored().hook().intercept()
|
||||||
}
|
method {
|
||||||
intercept()
|
name = "onCmdRequest"
|
||||||
}
|
param(StringClass)
|
||||||
injectMember {
|
}.ignored().hook().intercept()
|
||||||
method {
|
method {
|
||||||
name = "setCmdWhite"
|
name = "addData"
|
||||||
paramCount = 2
|
paramCount = 4
|
||||||
}
|
}.ignored().hook().intercept()
|
||||||
intercept()
|
method {
|
||||||
}
|
name = "onGpsScan"
|
||||||
injectMember {
|
paramCount = 2
|
||||||
method {
|
}.ignored().hook().intercept()
|
||||||
name = "onWriteLog"
|
}
|
||||||
param(StringClass, StringClass)
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "onCmdRequest"
|
|
||||||
param(StringClass)
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "addData"
|
|
||||||
paramCount = 4
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
injectMember {
|
|
||||||
method {
|
|
||||||
name = "onGpsScan"
|
|
||||||
paramCount = 2
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
}.ignoredHookClassNotFoundFailure()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Hook QQ 的设置界面添加模块设置入口 (新版) */
|
/** Hook QQ 的设置界面添加模块设置入口 (新版) */
|
||||||
private fun hookQQSettingsUi() {
|
private fun hookQQSettingsUi() {
|
||||||
if (MainSettingFragmentClass.hasClass().not()) return loggerE(msg = "Could not found main setting class, hook aborted")
|
if (MainSettingFragmentClass == null) return YLog.error("Could not found main setting class, hook aborted")
|
||||||
val kotlinUnit = "kotlin.Unit"
|
val kotlinUnit = "kotlin.Unit"
|
||||||
val kotlinFunction0 = "kotlin.jvm.functions.Function0"
|
val kotlinFunction0 = "kotlin.jvm.functions.Function0"
|
||||||
val simpleItemProcessorClass = searchClass {
|
val simpleItemProcessorClass = searchClass {
|
||||||
@@ -605,7 +536,7 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
returnType = UnitType
|
returnType = UnitType
|
||||||
}
|
}
|
||||||
field().count { it >= 6 }
|
field().count { it >= 6 }
|
||||||
}.get() ?: return loggerE(msg = "Could not found processor class, hook aborted")
|
}.get() ?: return YLog.error("Could not found processor class, hook aborted")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建入口点条目
|
* 创建入口点条目
|
||||||
@@ -623,7 +554,7 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
param { it[0].name == kotlinFunction0 }
|
param { it[0].name == kotlinFunction0 }
|
||||||
paramCount = 1
|
paramCount = 1
|
||||||
returnType = UnitType
|
returnType = UnitType
|
||||||
}.giveAll().lastOrNull() ?: error("Could not found processor method")
|
}.giveAll().firstOrNull() ?: error("Could not found processor method")
|
||||||
val proxyOnClick = Proxy.newProxyInstance(appClassLoader, arrayOf(onClickMethod.parameterTypes[0])) { any, method, args ->
|
val proxyOnClick = Proxy.newProxyInstance(appClassLoader, arrayOf(onClickMethod.parameterTypes[0])) { any, method, args ->
|
||||||
if (method.name == "invoke") {
|
if (method.name == "invoke") {
|
||||||
context.startModuleSettings()
|
context.startModuleSettings()
|
||||||
@@ -632,20 +563,15 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
}; onClickMethod.invoke(entryItem, proxyOnClick)
|
}; onClickMethod.invoke(entryItem, proxyOnClick)
|
||||||
} ?: error("Could not create TSBattery entry item")
|
} ?: error("Could not create TSBattery entry item")
|
||||||
}
|
}
|
||||||
MainSettingConfigProviderClass.hook {
|
MainSettingConfigProviderClass?.method {
|
||||||
injectMember {
|
param(ContextClass)
|
||||||
method {
|
returnType = ListClass
|
||||||
param(ContextClass)
|
}?.hook()?.after {
|
||||||
returnType = ListClass
|
val context = args().first().cast<Context>() ?: return@after
|
||||||
}
|
val processor = result<MutableList<Any?>>() ?: return@after
|
||||||
afterHook {
|
processor.add(1, processor[0]?.javaClass?.buildOf(arrayListOf<Any>().apply { add(createTSEntryItem(context)) }, "", "") {
|
||||||
val context = args().first().cast<Context>() ?: return@afterHook
|
param(ListClass, CharSequenceClass, CharSequenceClass)
|
||||||
val processor = result<MutableList<Any?>>() ?: return@afterHook
|
})
|
||||||
processor.add(1, processor[0]?.javaClass?.buildOf(arrayListOf<Any>().apply { add(createTSEntryItem(context)) }, "", "") {
|
|
||||||
param(ListClass, CharSequenceClass, CharSequenceClass)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -656,10 +582,10 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
private fun hookQQSettingsUiLegacy(instance: Any?) {
|
private fun hookQQSettingsUiLegacy(instance: Any?) {
|
||||||
/** 当前的顶级 Item 实例 */
|
/** 当前的顶级 Item 实例 */
|
||||||
val formItemRefRoot = instance?.current()?.field {
|
val formItemRefRoot = instance?.current()?.field {
|
||||||
type { it.name == FormSimpleItemClass || it.name == FormCommonSingleLineItemClass }.index(num = 1)
|
type { it == FormSimpleItemClass || it == FormCommonSingleLineItemClass }.index(num = 1)
|
||||||
}?.cast<View?>()
|
}?.cast<View?>()
|
||||||
/** 创建一个新的 Item */
|
/** 创建一个新的 Item */
|
||||||
FormSimpleItemClass.toClassOrNull()?.buildOf<View>(instance?.compatToActivity()) { param(ContextClass) }?.current {
|
FormSimpleItemClass?.buildOf<View>(instance?.compatToActivity()) { param(ContextClass) }?.current {
|
||||||
method {
|
method {
|
||||||
name = "setLeftText"
|
name = "setLeftText"
|
||||||
param(CharSequenceClass)
|
param(CharSequenceClass)
|
||||||
@@ -705,44 +631,29 @@ object QQTIMHooker : YukiBaseHooker() {
|
|||||||
hookQQBaseChatPie()
|
hookQQBaseChatPie()
|
||||||
hookCoreService()
|
hookCoreService()
|
||||||
hookQQDisgusting()
|
hookQQDisgusting()
|
||||||
loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"")
|
YLog.info("All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 仅注入主进程 */
|
/** 仅注入主进程 */
|
||||||
withProcess(mainProcessName) {
|
withProcess(mainProcessName) {
|
||||||
/** Hook 跳转事件 */
|
/** Hook 跳转事件 */
|
||||||
JumpActivityClass.hook {
|
JumpActivityClass?.method {
|
||||||
injectMember {
|
name = "doOnCreate"
|
||||||
method {
|
param(BundleClass)
|
||||||
name = "doOnCreate"
|
}?.hook()?.after { instance<Activity>().jumpToModuleSettings() }
|
||||||
param(BundleClass)
|
|
||||||
}
|
|
||||||
afterHook { instance<Activity>().jumpToModuleSettings() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** Hook 设置界面入口点 */
|
/** Hook 设置界面入口点 */
|
||||||
if (isQQNTVersion) hookQQSettingsUi()
|
if (isQQNTVersion) hookQQSettingsUi()
|
||||||
else {
|
else {
|
||||||
/** 将条目注入设置界面 (Activity) */
|
/** 将条目注入设置界面 (Activity) */
|
||||||
QQSettingSettingActivityClass.hook {
|
QQSettingSettingActivityClass?.method {
|
||||||
injectMember {
|
name = "doOnCreate"
|
||||||
method {
|
param(BundleClass)
|
||||||
name = "doOnCreate"
|
}?.hook()?.after { hookQQSettingsUiLegacy(instance) }
|
||||||
param(BundleClass)
|
|
||||||
}
|
|
||||||
afterHook { hookQQSettingsUiLegacy(instance) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** 将条目注入设置界面 (Fragment) */
|
/** 将条目注入设置界面 (Fragment) */
|
||||||
QQSettingSettingFragmentClass.hook {
|
QQSettingSettingFragmentClass?.method {
|
||||||
injectMember {
|
name = "doOnCreateView"
|
||||||
method {
|
paramCount = 3
|
||||||
name = "doOnCreateView"
|
}?.hook()?.after { hookQQSettingsUiLegacy(instance) }
|
||||||
paramCount = 3
|
|
||||||
}
|
|
||||||
afterHook { hookQQSettingsUiLegacy(instance) }
|
|
||||||
}
|
|
||||||
}.ignoredHookClassNotFoundFailure()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -45,9 +45,10 @@ import com.fankes.tsbattery.utils.factory.dp
|
|||||||
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
import com.highcapable.yukihookapi.hook.entity.YukiBaseHooker
|
||||||
import com.highcapable.yukihookapi.hook.factory.current
|
import com.highcapable.yukihookapi.hook.factory.current
|
||||||
import com.highcapable.yukihookapi.hook.factory.injectModuleAppResources
|
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.processName
|
||||||
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
|
import com.highcapable.yukihookapi.hook.factory.registerModuleAppActivities
|
||||||
import com.highcapable.yukihookapi.hook.log.loggerI
|
import com.highcapable.yukihookapi.hook.log.YLog
|
||||||
import com.highcapable.yukihookapi.hook.type.android.ViewClass
|
import com.highcapable.yukihookapi.hook.type.android.ViewClass
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,16 +59,19 @@ import com.highcapable.yukihookapi.hook.type.android.ViewClass
|
|||||||
object WeChatHooker : YukiBaseHooker() {
|
object WeChatHooker : YukiBaseHooker() {
|
||||||
|
|
||||||
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
||||||
const val LauncherUIClass = "${PackageName.WECHAT}.ui.LauncherUI"
|
const val LauncherUIClassName = "${PackageName.WECHAT}.ui.LauncherUI"
|
||||||
|
|
||||||
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
||||||
private const val EmptyActivityClass = "${PackageName.WECHAT}.ui.EmptyActivity"
|
private val LauncherUIClass by lazyClassOrNull("${PackageName.WECHAT}.ui.LauncherUI")
|
||||||
|
|
||||||
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
||||||
private const val WelabMainUIClass = "${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI"
|
private val EmptyActivityClass by lazyClassOrNull("${PackageName.WECHAT}.ui.EmptyActivity")
|
||||||
|
|
||||||
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
||||||
private const val SettingsUIClass = "${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI"
|
private val WelabMainUIClass by lazyClassOrNull("${PackageName.WECHAT}.plugin.welab.ui.WelabMainUI")
|
||||||
|
|
||||||
|
/** 微信存在的类 - 未测试每个版本是否都存在 */
|
||||||
|
private val SettingsUIClass by lazyClassOrNull("${PackageName.WECHAT}.plugin.setting.ui.setting.SettingsUI")
|
||||||
|
|
||||||
/** TSBattery 图标 TAG 名称 */
|
/** TSBattery 图标 TAG 名称 */
|
||||||
private const val TSBARRERY_ICON_TAG = "tsbattery_icon"
|
private const val TSBARRERY_ICON_TAG = "tsbattery_icon"
|
||||||
@@ -98,51 +102,41 @@ object WeChatHooker : YukiBaseHooker() {
|
|||||||
onCreate {
|
onCreate {
|
||||||
ConfigData.init(context = this)
|
ConfigData.init(context = this)
|
||||||
registerModuleAppActivities(when {
|
registerModuleAppActivities(when {
|
||||||
EmptyActivityClass.hasClass() -> EmptyActivityClass
|
EmptyActivityClass != null -> EmptyActivityClass
|
||||||
WelabMainUIClass.hasClass() -> WelabMainUIClass
|
WelabMainUIClass != null -> WelabMainUIClass
|
||||||
else -> error("Inject WeChat Activity Proxy failed, unsupport version $appVersionName($appVersionCode)")
|
else -> error("Inject WeChat Activity Proxy failed, unsupport version $appVersionName($appVersionCode)")
|
||||||
})
|
})
|
||||||
if (ConfigData.isDisableAllHook) return@onCreate
|
if (ConfigData.isDisableAllHook) return@onCreate
|
||||||
hookSystemWakeLock()
|
hookSystemWakeLock()
|
||||||
loggerI(msg = "All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"")
|
YLog.info("All processes are completed for \"${processName.takeIf { it != packageName } ?: packageName}\"")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/** 仅注入主进程 */
|
/** 仅注入主进程 */
|
||||||
withProcess(mainProcessName) {
|
withProcess(mainProcessName) {
|
||||||
/** Hook 跳转事件 */
|
/** Hook 跳转事件 */
|
||||||
LauncherUIClass.hook {
|
LauncherUIClass?.method {
|
||||||
injectMember {
|
name = "onResume"
|
||||||
method {
|
emptyParam()
|
||||||
name = "onResume"
|
}?.hook()?.after { instance<Activity>().jumpToModuleSettings(isFinish = false) }
|
||||||
emptyParam()
|
|
||||||
}
|
|
||||||
afterHook { instance<Activity>().jumpToModuleSettings(isFinish = false) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/** 向设置界面右上角添加按钮 */
|
/** 向设置界面右上角添加按钮 */
|
||||||
SettingsUIClass.hook {
|
SettingsUIClass?.method {
|
||||||
injectMember {
|
name = "onResume"
|
||||||
method {
|
emptyParam()
|
||||||
name = "onResume"
|
}?.hook()?.after {
|
||||||
emptyParam()
|
SettingsUIClass?.method {
|
||||||
}
|
name = "get_fragment"
|
||||||
afterHook {
|
emptyParam()
|
||||||
method {
|
superClass(isOnlySuperClass = true)
|
||||||
name = "get_fragment"
|
}?.get(instance)?.call()?.current()?.method {
|
||||||
emptyParam()
|
name = "getView"
|
||||||
superClass(isOnlySuperClass = true)
|
emptyParam()
|
||||||
}.get(instance).call()?.current()?.method {
|
returnType = ViewClass
|
||||||
name = "getView"
|
superClass(isOnlySuperClass = true)
|
||||||
emptyParam()
|
}?.invoke<ViewGroup?>()?.also {
|
||||||
returnType = ViewClass
|
it.context?.injectModuleAppResources()
|
||||||
superClass(isOnlySuperClass = true)
|
runCatching { it.getChildAt(0) as? ViewGroup? }.getOrNull()?.also { rootView ->
|
||||||
}?.invoke<ViewGroup?>()?.also {
|
if (rootView.findViewWithTag<View>(TSBARRERY_ICON_TAG) == null)
|
||||||
it.context?.injectModuleAppResources()
|
rootView.addView(createPreferenceIcon(it.context))
|
||||||
runCatching { it.getChildAt(0) as? ViewGroup? }.getOrNull()?.also { rootView ->
|
|
||||||
if (rootView.findViewWithTag<View>(TSBARRERY_ICON_TAG) == null)
|
|
||||||
rootView.addView(createPreferenceIcon(it.context))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -81,13 +81,8 @@ fun Activity.jumpToModuleSettings(isFinish: Boolean = true) {
|
|||||||
|
|
||||||
/** Hook 系统电源锁 */
|
/** Hook 系统电源锁 */
|
||||||
fun PackageParam.hookSystemWakeLock() {
|
fun PackageParam.hookSystemWakeLock() {
|
||||||
PowerManager_WakeLockClass.hook {
|
PowerManager_WakeLockClass.method {
|
||||||
injectMember {
|
name = "acquireLocked"
|
||||||
method {
|
emptyParam()
|
||||||
name = "acquireLocked"
|
}.hook().intercept()
|
||||||
emptyParam()
|
|
||||||
}
|
|
||||||
intercept()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
@@ -189,7 +189,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
|
|||||||
startActivity(Intent().apply {
|
startActivity(Intent().apply {
|
||||||
component = ComponentName(
|
component = ComponentName(
|
||||||
packageName,
|
packageName,
|
||||||
if (packageName != PackageName.WECHAT) QQTIMHooker.JumpActivityClass else WeChatHooker.LauncherUIClass
|
if (packageName != PackageName.WECHAT) QQTIMHooker.JumpActivityClassName else WeChatHooker.LauncherUIClassName
|
||||||
)
|
)
|
||||||
putExtra(JumpEvent.OPEN_MODULE_SETTING, YukiHookAPI.Status.compiledTimestamp)
|
putExtra(JumpEvent.OPEN_MODULE_SETTING, YukiHookAPI.Status.compiledTimestamp)
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
*
|
*
|
||||||
* This file is created by fankes on 2022/1/7.
|
* This file is created by fankes on 2022/1/7.
|
||||||
*/
|
*/
|
||||||
@file:Suppress("unused", "OPT_IN_USAGE", "EXPERIMENTAL_API_USAGE")
|
@file:Suppress("unused")
|
||||||
|
|
||||||
package com.fankes.tsbattery.utils.factory
|
package com.fankes.tsbattery.utils.factory
|
||||||
|
|
||||||
@@ -34,7 +34,6 @@ import androidx.appcompat.app.AlertDialog
|
|||||||
import com.fankes.tsbattery.R
|
import com.fankes.tsbattery.R
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.google.android.material.progressindicator.CircularProgressIndicator
|
import com.google.android.material.progressindicator.CircularProgressIndicator
|
||||||
import com.highcapable.yukihookapi.annotation.CauseProblemsApi
|
|
||||||
import com.highcapable.yukihookapi.hook.factory.applyModuleTheme
|
import com.highcapable.yukihookapi.hook.factory.applyModuleTheme
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -134,7 +133,6 @@ class DialogBuilder(val context: Context) {
|
|||||||
fun cancel() = dialogInstance?.cancel()
|
fun cancel() = dialogInstance?.cancel()
|
||||||
|
|
||||||
/** 显示对话框 */
|
/** 显示对话框 */
|
||||||
@CauseProblemsApi
|
|
||||||
fun show() = runInSafe {
|
fun show() = runInSafe {
|
||||||
instance?.create()?.apply {
|
instance?.create()?.apply {
|
||||||
customLayoutView?.let { setView(it) }
|
customLayoutView?.let { setView(it) }
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
package com.fankes.tsbattery.utils.factory
|
package com.fankes.tsbattery.utils.factory
|
||||||
|
|
||||||
import com.highcapable.yukihookapi.hook.log.loggerE
|
import com.highcapable.yukihookapi.hook.log.YLog
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 忽略异常返回值
|
* 忽略异常返回值
|
||||||
@@ -78,5 +78,5 @@ inline fun <T> safeOf(default: T, result: () -> T) = try {
|
|||||||
* @param block 正常回调
|
* @param block 正常回调
|
||||||
*/
|
*/
|
||||||
inline fun <T> T.runInSafe(msg: String = "", block: () -> Unit) {
|
inline fun <T> T.runInSafe(msg: String = "", block: () -> Unit) {
|
||||||
runCatching(block).onFailure { if (msg.isNotBlank()) loggerE(msg = msg, e = it) }
|
runCatching(block).onFailure { if (msg.isNotBlank()) YLog.error(msg, it) }
|
||||||
}
|
}
|
@@ -75,7 +75,7 @@ inline val Context.isNotSystemInDarkMode get() = !isSystemInDarkMode
|
|||||||
* @return [PackageInfo] or null
|
* @return [PackageInfo] or null
|
||||||
*/
|
*/
|
||||||
private fun Context.getPackageInfoCompat(packageName: String, flag: Number = 0) = runCatching {
|
private fun Context.getPackageInfoCompat(packageName: String, flag: Number = 0) = runCatching {
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION", "KotlinRedundantDiagnosticSuppress")
|
||||||
if (Build.VERSION.SDK_INT >= 33)
|
if (Build.VERSION.SDK_INT >= 33)
|
||||||
packageManager?.getPackageInfo(packageName, PackageInfoFlags.of(flag.toLong()))
|
packageManager?.getPackageInfo(packageName, PackageInfoFlags.of(flag.toLong()))
|
||||||
else packageManager?.getPackageInfo(packageName, flag.toInt())
|
else packageManager?.getPackageInfo(packageName, flag.toInt())
|
||||||
|
Reference in New Issue
Block a user